diff --git a/src/platform/opengl/gl.c b/src/platform/opengl/gl.c index 776906b84..0b438e22d 100644 --- a/src/platform/opengl/gl.c +++ b/src/platform/opengl/gl.c @@ -21,7 +21,7 @@ static const GLint _glTexCoords[] = { 0, 1 }; -static void GBAGLContextInit(struct VideoBackend* v, unsigned width, unsigned height, WHandle handle) { +static void GBAGLContextInit(struct VideoBackend* v, WHandle handle) { UNUSED(handle); struct GBAGLContext* context = (struct GBAGLContext*) v; 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_T, GL_CLAMP_TO_EDGE); #endif +} + +static void GBAGLContextSetDimensions(struct VideoBackend* v, unsigned width, unsigned height) { + struct GBAGLContext* context = (struct GBAGLContext*) 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, 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) { context->d.init = GBAGLContextInit; context->d.deinit = GBAGLContextDeinit; + context->d.setDimensions = GBAGLContextSetDimensions; context->d.resized = GBAGLContextResized; context->d.swap = 0; context->d.clear = GBAGLContextClear; diff --git a/src/platform/opengl/gles2.c b/src/platform/opengl/gles2.c index 2bf4fc603..980e2eb3e 100644 --- a/src/platform/opengl/gles2.c +++ b/src/platform/opengl/gles2.c @@ -71,25 +71,13 @@ static const GLfloat _vertices[] = { 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); struct GBAGLES2Context* context = (struct GBAGLES2Context*) v; glGenTextures(1, &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_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); @@ -144,6 +132,23 @@ static void GBAGLES2ContextInit(struct VideoBackend* v, unsigned width, unsigned 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) { struct GBAGLES2Context* context = (struct GBAGLES2Context*) v; glDeleteTextures(1, &context->tex); @@ -312,6 +317,7 @@ void GBAGLES2ContextPostFrame(struct VideoBackend* v, const void* frame) { void GBAGLES2ContextCreate(struct GBAGLES2Context* context) { context->d.init = GBAGLES2ContextInit; context->d.deinit = GBAGLES2ContextDeinit; + context->d.setDimensions = GBAGLES2ContextSetDimensions; context->d.resized = GBAGLES2ContextResized; context->d.swap = 0; context->d.clear = GBAGLES2ContextClear; diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index cd4b58fe4..4a9b854b4 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -221,7 +221,7 @@ PainterGL::PainterGL(QGLWidget* parent, QGLFormat::OpenGLVersionFlags glVersion) #if defined(_WIN32) && defined(USE_EPOXY) epoxy_handle_external_wglMakeCurrent(); #endif - m_backend->init(m_backend, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, reinterpret_cast(m_gl->winId())); + m_backend->init(m_backend, reinterpret_cast(m_gl->winId())); #if !defined(_WIN32) || defined(USE_EPOXY) if (m_supportsShaders) { m_shader.preprocessShader = static_cast(&reinterpret_cast(m_backend)->initialShader); @@ -262,6 +262,19 @@ PainterGL::~PainterGL() { void PainterGL::setContext(mCoreThread* 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) { @@ -374,7 +387,9 @@ void PainterGL::enqueue(const uint32_t* backing) { } else { 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_mutex.unlock(); } diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index 368fbe702..0d48049db 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -34,8 +34,8 @@ using namespace std; GameController::GameController(QObject* parent) : QObject(parent) - , m_drawContext(new uint32_t[VIDEO_VERTICAL_PIXELS * VIDEO_HORIZONTAL_PIXELS]) - , m_frontBuffer(new uint32_t[VIDEO_VERTICAL_PIXELS * VIDEO_HORIZONTAL_PIXELS]) + , m_drawContext(nullptr) + , m_frontBuffer(nullptr) , m_threadContext() , m_activeKeys(0) , m_inactiveKeys(0) @@ -116,7 +116,9 @@ GameController::GameController(QObject* parent) m_threadContext.frameCallback = [](mCoreThread* context) { GameController* controller = static_cast(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)); if (controller->m_pauseAfterFrame.testAndSetAcquire(true, false)) { mCoreThreadPauseFromThread(context); @@ -208,8 +210,6 @@ GameController::~GameController() { clearMultiplayerController(); closeGame(); GBACheatDeviceDestroy(&m_cheatDevice); - delete[] m_drawContext; - delete[] m_frontBuffer; delete m_backupLoadState; } @@ -300,12 +300,17 @@ void GameController::openGame(bool biosOnly) { } 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) { mCoreLoadFile(m_threadContext.core, m_fname.toUtf8().constData()); 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) { VFile* bios = VFileDevice::open(m_bios, O_RDONLY); @@ -324,7 +329,7 @@ void GameController::openGame(bool biosOnly) { } 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); @@ -423,6 +428,9 @@ void GameController::closeGame() { // Make sure the event queue clears out before the thread is reused QCoreApplication::processEvents(); + delete[] m_drawContext; + delete[] m_frontBuffer; + m_patch = QString(); for (size_t i = 0; i < GBACheatSetsSize(&m_cheatDevice.cheats); ++i) { diff --git a/src/platform/sdl/gl-sdl.c b/src/platform/sdl/gl-sdl.c index 1f565ed4c..5521ee48f 100644 --- a/src/platform/sdl/gl-sdl.c +++ b/src/platform/sdl/gl-sdl.c @@ -42,7 +42,8 @@ bool mSDLGLInit(struct mSDLRenderer* renderer) { renderer->gl.d.lockAspectRatio = renderer->lockAspectRatio; renderer->gl.d.filter = renderer->filter; 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); return true; diff --git a/src/platform/sdl/gles2-sdl.c b/src/platform/sdl/gles2-sdl.c index 9b5d861ca..5d41e3ef5 100644 --- a/src/platform/sdl/gles2-sdl.c +++ b/src/platform/sdl/gles2-sdl.c @@ -102,6 +102,7 @@ bool mSDLGLES2Init(struct SDLSoftwareRenderer* renderer) { renderer->gl2.d.filter = renderer->filter; renderer->gl2.d.swap = mSDLGLCommonSwap; renderer->gl2.d.init(&renderer->gl2.d, 0); + renderer->gl2.d.setDimensions(&renderer->gl2.d, renderer->width, renderer->height); return true; } diff --git a/src/platform/video-backend.h b/src/platform/video-backend.h index a97b51990..b67b676be 100644 --- a/src/platform/video-backend.h +++ b/src/platform/video-backend.h @@ -16,8 +16,9 @@ typedef void* WHandle; #endif struct VideoBackend { - void (*init)(struct VideoBackend*, unsigned width, unsigned height, WHandle handle); + void (*init)(struct VideoBackend*, WHandle handle); void (*deinit)(struct VideoBackend*); + void (*setDimensions)(struct VideoBackend*, unsigned width, unsigned height); void (*swap)(struct VideoBackend*); void (*clear)(struct VideoBackend*); void (*resized)(struct VideoBackend*, unsigned w, unsigned h);