mirror of https://github.com/mgba-emu/mgba.git
OpenGL: Make video dimensions customizable
This commit is contained in:
parent
73b58ec7c4
commit
fae8ef7f42
|
@ -21,7 +21,7 @@ static const GLint _glTexCoords[] = {
|
||||||
0, 1
|
0, 1
|
||||||
};
|
};
|
||||||
|
|
||||||
static void GBAGLContextInit(struct VideoBackend* v, unsigned width, unsigned height, WHandle handle) {
|
static void GBAGLContextInit(struct VideoBackend* v, WHandle handle) {
|
||||||
UNUSED(handle);
|
UNUSED(handle);
|
||||||
struct GBAGLContext* context = (struct GBAGLContext*) v;
|
struct GBAGLContext* context = (struct GBAGLContext*) v;
|
||||||
glGenTextures(1, &context->tex);
|
glGenTextures(1, &context->tex);
|
||||||
|
@ -31,9 +31,14 @@ static void GBAGLContextInit(struct VideoBackend* v, unsigned width, unsigned he
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GBAGLContextSetDimensions(struct VideoBackend* v, unsigned width, unsigned height) {
|
||||||
|
struct GBAGLContext* context = (struct GBAGLContext*) v;
|
||||||
v->width = width;
|
v->width = width;
|
||||||
v->height = height;
|
v->height = height;
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, context->tex);
|
||||||
#ifdef COLOR_16_BIT
|
#ifdef COLOR_16_BIT
|
||||||
#ifdef COLOR_5_6_5
|
#ifdef COLOR_5_6_5
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
|
||||||
|
@ -113,6 +118,7 @@ void GBAGLContextPostFrame(struct VideoBackend* v, const void* frame) {
|
||||||
void GBAGLContextCreate(struct GBAGLContext* context) {
|
void GBAGLContextCreate(struct GBAGLContext* context) {
|
||||||
context->d.init = GBAGLContextInit;
|
context->d.init = GBAGLContextInit;
|
||||||
context->d.deinit = GBAGLContextDeinit;
|
context->d.deinit = GBAGLContextDeinit;
|
||||||
|
context->d.setDimensions = GBAGLContextSetDimensions;
|
||||||
context->d.resized = GBAGLContextResized;
|
context->d.resized = GBAGLContextResized;
|
||||||
context->d.swap = 0;
|
context->d.swap = 0;
|
||||||
context->d.clear = GBAGLContextClear;
|
context->d.clear = GBAGLContextClear;
|
||||||
|
|
|
@ -71,25 +71,13 @@ static const GLfloat _vertices[] = {
|
||||||
1.f, -1.f,
|
1.f, -1.f,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void GBAGLES2ContextInit(struct VideoBackend* v, unsigned width, unsigned height, WHandle handle) {
|
static void GBAGLES2ContextInit(struct VideoBackend* v, WHandle handle) {
|
||||||
UNUSED(handle);
|
UNUSED(handle);
|
||||||
struct GBAGLES2Context* context = (struct GBAGLES2Context*) v;
|
struct GBAGLES2Context* context = (struct GBAGLES2Context*) v;
|
||||||
glGenTextures(1, &context->tex);
|
glGenTextures(1, &context->tex);
|
||||||
glBindTexture(GL_TEXTURE_2D, context->tex);
|
glBindTexture(GL_TEXTURE_2D, context->tex);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
v->width = width;
|
|
||||||
v->height = height;
|
|
||||||
|
|
||||||
#ifdef COLOR_16_BIT
|
|
||||||
#ifdef COLOR_5_6_5
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
|
|
||||||
#else
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0);
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
glClearColor(0.f, 0.f, 0.f, 1.f);
|
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||||
|
|
||||||
|
@ -144,6 +132,23 @@ static void GBAGLES2ContextInit(struct VideoBackend* v, unsigned width, unsigned
|
||||||
context->finalShader.tex = 0;
|
context->finalShader.tex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void GBAGLES2ContextSetDimensions(struct VideoBackend* v, unsigned width, unsigned height) {
|
||||||
|
struct GBAGLES2Context* context = (struct GBAGLES2Context*) v;
|
||||||
|
v->width = width;
|
||||||
|
v->height = height;
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, context->tex);
|
||||||
|
#ifdef COLOR_16_BIT
|
||||||
|
#ifdef COLOR_5_6_5
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
|
||||||
|
#else
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void GBAGLES2ContextDeinit(struct VideoBackend* v) {
|
static void GBAGLES2ContextDeinit(struct VideoBackend* v) {
|
||||||
struct GBAGLES2Context* context = (struct GBAGLES2Context*) v;
|
struct GBAGLES2Context* context = (struct GBAGLES2Context*) v;
|
||||||
glDeleteTextures(1, &context->tex);
|
glDeleteTextures(1, &context->tex);
|
||||||
|
@ -312,6 +317,7 @@ void GBAGLES2ContextPostFrame(struct VideoBackend* v, const void* frame) {
|
||||||
void GBAGLES2ContextCreate(struct GBAGLES2Context* context) {
|
void GBAGLES2ContextCreate(struct GBAGLES2Context* context) {
|
||||||
context->d.init = GBAGLES2ContextInit;
|
context->d.init = GBAGLES2ContextInit;
|
||||||
context->d.deinit = GBAGLES2ContextDeinit;
|
context->d.deinit = GBAGLES2ContextDeinit;
|
||||||
|
context->d.setDimensions = GBAGLES2ContextSetDimensions;
|
||||||
context->d.resized = GBAGLES2ContextResized;
|
context->d.resized = GBAGLES2ContextResized;
|
||||||
context->d.swap = 0;
|
context->d.swap = 0;
|
||||||
context->d.clear = GBAGLES2ContextClear;
|
context->d.clear = GBAGLES2ContextClear;
|
||||||
|
|
|
@ -221,7 +221,7 @@ PainterGL::PainterGL(QGLWidget* parent, QGLFormat::OpenGLVersionFlags glVersion)
|
||||||
#if defined(_WIN32) && defined(USE_EPOXY)
|
#if defined(_WIN32) && defined(USE_EPOXY)
|
||||||
epoxy_handle_external_wglMakeCurrent();
|
epoxy_handle_external_wglMakeCurrent();
|
||||||
#endif
|
#endif
|
||||||
m_backend->init(m_backend, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, reinterpret_cast<WHandle>(m_gl->winId()));
|
m_backend->init(m_backend, reinterpret_cast<WHandle>(m_gl->winId()));
|
||||||
#if !defined(_WIN32) || defined(USE_EPOXY)
|
#if !defined(_WIN32) || defined(USE_EPOXY)
|
||||||
if (m_supportsShaders) {
|
if (m_supportsShaders) {
|
||||||
m_shader.preprocessShader = static_cast<void*>(&reinterpret_cast<GBAGLES2Context*>(m_backend)->initialShader);
|
m_shader.preprocessShader = static_cast<void*>(&reinterpret_cast<GBAGLES2Context*>(m_backend)->initialShader);
|
||||||
|
@ -262,6 +262,19 @@ PainterGL::~PainterGL() {
|
||||||
|
|
||||||
void PainterGL::setContext(mCoreThread* context) {
|
void PainterGL::setContext(mCoreThread* context) {
|
||||||
m_context = context;
|
m_context = context;
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_gl->makeCurrent();
|
||||||
|
#if defined(_WIN32) && defined(USE_EPOXY)
|
||||||
|
epoxy_handle_external_wglMakeCurrent();
|
||||||
|
#endif
|
||||||
|
unsigned width, height;
|
||||||
|
context->core->desiredVideoDimensions(context->core, &width, &height);
|
||||||
|
m_backend->setDimensions(m_backend, width, height);
|
||||||
|
m_gl->doneCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PainterGL::setMessagePainter(MessagePainter* messagePainter) {
|
void PainterGL::setMessagePainter(MessagePainter* messagePainter) {
|
||||||
|
@ -374,7 +387,9 @@ void PainterGL::enqueue(const uint32_t* backing) {
|
||||||
} else {
|
} else {
|
||||||
buffer = m_free.takeLast();
|
buffer = m_free.takeLast();
|
||||||
}
|
}
|
||||||
memcpy(buffer, backing, VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
|
unsigned width, height;
|
||||||
|
m_context->core->desiredVideoDimensions(m_context->core, &width, &height);
|
||||||
|
memcpy(buffer, backing, width * height * BYTES_PER_PIXEL);
|
||||||
m_queue.enqueue(buffer);
|
m_queue.enqueue(buffer);
|
||||||
m_mutex.unlock();
|
m_mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,8 +34,8 @@ using namespace std;
|
||||||
|
|
||||||
GameController::GameController(QObject* parent)
|
GameController::GameController(QObject* parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, m_drawContext(new uint32_t[VIDEO_VERTICAL_PIXELS * VIDEO_HORIZONTAL_PIXELS])
|
, m_drawContext(nullptr)
|
||||||
, m_frontBuffer(new uint32_t[VIDEO_VERTICAL_PIXELS * VIDEO_HORIZONTAL_PIXELS])
|
, m_frontBuffer(nullptr)
|
||||||
, m_threadContext()
|
, m_threadContext()
|
||||||
, m_activeKeys(0)
|
, m_activeKeys(0)
|
||||||
, m_inactiveKeys(0)
|
, m_inactiveKeys(0)
|
||||||
|
@ -116,7 +116,9 @@ GameController::GameController(QObject* parent)
|
||||||
|
|
||||||
m_threadContext.frameCallback = [](mCoreThread* context) {
|
m_threadContext.frameCallback = [](mCoreThread* context) {
|
||||||
GameController* controller = static_cast<GameController*>(context->userData);
|
GameController* controller = static_cast<GameController*>(context->userData);
|
||||||
memcpy(controller->m_frontBuffer, controller->m_drawContext, VIDEO_VERTICAL_PIXELS * VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL);
|
unsigned width, height;
|
||||||
|
controller->m_threadContext.core->desiredVideoDimensions(controller->m_threadContext.core, &width, &height);
|
||||||
|
memcpy(controller->m_frontBuffer, controller->m_drawContext, width * height * BYTES_PER_PIXEL);
|
||||||
QMetaObject::invokeMethod(controller, "frameAvailable", Q_ARG(const uint32_t*, controller->m_frontBuffer));
|
QMetaObject::invokeMethod(controller, "frameAvailable", Q_ARG(const uint32_t*, controller->m_frontBuffer));
|
||||||
if (controller->m_pauseAfterFrame.testAndSetAcquire(true, false)) {
|
if (controller->m_pauseAfterFrame.testAndSetAcquire(true, false)) {
|
||||||
mCoreThreadPauseFromThread(context);
|
mCoreThreadPauseFromThread(context);
|
||||||
|
@ -208,8 +210,6 @@ GameController::~GameController() {
|
||||||
clearMultiplayerController();
|
clearMultiplayerController();
|
||||||
closeGame();
|
closeGame();
|
||||||
GBACheatDeviceDestroy(&m_cheatDevice);
|
GBACheatDeviceDestroy(&m_cheatDevice);
|
||||||
delete[] m_drawContext;
|
|
||||||
delete[] m_frontBuffer;
|
|
||||||
delete m_backupLoadState;
|
delete m_backupLoadState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,12 +300,17 @@ void GameController::openGame(bool biosOnly) {
|
||||||
}
|
}
|
||||||
m_threadContext.core->init(m_threadContext.core);
|
m_threadContext.core->init(m_threadContext.core);
|
||||||
|
|
||||||
|
unsigned width, height;
|
||||||
|
m_threadContext.core->desiredVideoDimensions(m_threadContext.core, &width, &height);
|
||||||
|
m_drawContext = new uint32_t[width * height];
|
||||||
|
m_frontBuffer = new uint32_t[width * height];
|
||||||
|
|
||||||
if (!biosOnly) {
|
if (!biosOnly) {
|
||||||
mCoreLoadFile(m_threadContext.core, m_fname.toUtf8().constData());
|
mCoreLoadFile(m_threadContext.core, m_fname.toUtf8().constData());
|
||||||
mCoreAutoloadSave(m_threadContext.core);
|
mCoreAutoloadSave(m_threadContext.core);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_threadContext.core->setVideoBuffer(m_threadContext.core, m_drawContext, VIDEO_HORIZONTAL_PIXELS);
|
m_threadContext.core->setVideoBuffer(m_threadContext.core, m_drawContext, width);
|
||||||
|
|
||||||
if (!m_bios.isNull() && m_useBios) {
|
if (!m_bios.isNull() && m_useBios) {
|
||||||
VFile* bios = VFileDevice::open(m_bios, O_RDONLY);
|
VFile* bios = VFileDevice::open(m_bios, O_RDONLY);
|
||||||
|
@ -324,7 +329,7 @@ void GameController::openGame(bool biosOnly) {
|
||||||
}
|
}
|
||||||
|
|
||||||
m_inputController->recalibrateAxes();
|
m_inputController->recalibrateAxes();
|
||||||
memset(m_drawContext, 0xF8, VIDEO_VERTICAL_PIXELS * VIDEO_HORIZONTAL_PIXELS * 4);
|
memset(m_drawContext, 0xF8, width * height * 4);
|
||||||
|
|
||||||
m_threadContext.core->setAVStream(m_threadContext.core, m_stream);
|
m_threadContext.core->setAVStream(m_threadContext.core, m_stream);
|
||||||
|
|
||||||
|
@ -423,6 +428,9 @@ void GameController::closeGame() {
|
||||||
// Make sure the event queue clears out before the thread is reused
|
// Make sure the event queue clears out before the thread is reused
|
||||||
QCoreApplication::processEvents();
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
delete[] m_drawContext;
|
||||||
|
delete[] m_frontBuffer;
|
||||||
|
|
||||||
m_patch = QString();
|
m_patch = QString();
|
||||||
|
|
||||||
for (size_t i = 0; i < GBACheatSetsSize(&m_cheatDevice.cheats); ++i) {
|
for (size_t i = 0; i < GBACheatSetsSize(&m_cheatDevice.cheats); ++i) {
|
||||||
|
|
|
@ -42,7 +42,8 @@ bool mSDLGLInit(struct mSDLRenderer* renderer) {
|
||||||
renderer->gl.d.lockAspectRatio = renderer->lockAspectRatio;
|
renderer->gl.d.lockAspectRatio = renderer->lockAspectRatio;
|
||||||
renderer->gl.d.filter = renderer->filter;
|
renderer->gl.d.filter = renderer->filter;
|
||||||
renderer->gl.d.swap = mSDLGLCommonSwap;
|
renderer->gl.d.swap = mSDLGLCommonSwap;
|
||||||
renderer->gl.d.init(&renderer->gl.d, renderer->width, renderer->height, 0);
|
renderer->gl.d.init(&renderer->gl.d, 0);
|
||||||
|
renderer->gl.d.setDimensions(&renderer->gl.d, renderer->width, renderer->height);
|
||||||
|
|
||||||
_doViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl.d);
|
_doViewport(renderer->viewportWidth, renderer->viewportHeight, &renderer->gl.d);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -102,6 +102,7 @@ bool mSDLGLES2Init(struct SDLSoftwareRenderer* renderer) {
|
||||||
renderer->gl2.d.filter = renderer->filter;
|
renderer->gl2.d.filter = renderer->filter;
|
||||||
renderer->gl2.d.swap = mSDLGLCommonSwap;
|
renderer->gl2.d.swap = mSDLGLCommonSwap;
|
||||||
renderer->gl2.d.init(&renderer->gl2.d, 0);
|
renderer->gl2.d.init(&renderer->gl2.d, 0);
|
||||||
|
renderer->gl2.d.setDimensions(&renderer->gl2.d, renderer->width, renderer->height);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,9 @@ typedef void* WHandle;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct VideoBackend {
|
struct VideoBackend {
|
||||||
void (*init)(struct VideoBackend*, unsigned width, unsigned height, WHandle handle);
|
void (*init)(struct VideoBackend*, WHandle handle);
|
||||||
void (*deinit)(struct VideoBackend*);
|
void (*deinit)(struct VideoBackend*);
|
||||||
|
void (*setDimensions)(struct VideoBackend*, unsigned width, unsigned height);
|
||||||
void (*swap)(struct VideoBackend*);
|
void (*swap)(struct VideoBackend*);
|
||||||
void (*clear)(struct VideoBackend*);
|
void (*clear)(struct VideoBackend*);
|
||||||
void (*resized)(struct VideoBackend*, unsigned w, unsigned h);
|
void (*resized)(struct VideoBackend*, unsigned w, unsigned h);
|
||||||
|
|
Loading…
Reference in New Issue