Switch: Experimental support for hi-res mode
@@ -18,7 +18,7 @@ #include <mgba/internal/gba/overrides.h>
#ifndef DISABLE_THREADING #include <mgba/feature/thread-proxy.h> #endif -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) #include <mgba/internal/gba/renderers/gl.h> #endif #include <mgba/internal/gba/renderers/proxy.h>@@ -130,7 +130,7 @@
struct GBACore { struct mCore d; struct GBAVideoSoftwareRenderer renderer; -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) struct GBAVideoGLRenderer glRenderer; #endif struct GBAVideoProxyRenderer proxyRenderer;@@ -180,7 +180,7 @@
GBAVideoSoftwareRendererCreate(&gbacore->renderer); gbacore->renderer.outputBuffer = NULL; -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) GBAVideoGLRendererCreate(&gbacore->glRenderer); gbacore->glRenderer.outputTex = -1; #endif@@ -229,7 +229,7 @@ static bool _GBACoreSupportsFeature(const struct mCore* core, enum mCoreFeature feature) {
UNUSED(core); switch (feature) { case mCORE_FEATURE_OPENGL: -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) return true; #else return false;@@ -289,7 +289,7 @@ mCoreConfigCopyValue(&core->config, config, "videoScale");
} static void _GBACoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) { -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) struct GBACore* gbacore = (struct GBACore*) core; int scale = gbacore->glRenderer.scale; #else@@ -308,7 +308,7 @@ memset(gbacore->renderer.scanlineDirty, 0xFFFFFFFF, sizeof(gbacore->renderer.scanlineDirty));
} static void _GBACoreSetVideoGLTex(struct mCore* core, unsigned texid) { -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) struct GBACore* gbacore = (struct GBACore*) core; gbacore->glRenderer.outputTex = texid; #else@@ -442,7 +442,7 @@ static void _GBACoreReset(struct mCore* core) {
struct GBACore* gbacore = (struct GBACore*) core; struct GBA* gba = (struct GBA*) core->board; if (gbacore->renderer.outputBuffer -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) || gbacore->glRenderer.outputTex != (unsigned) -1 #endif ) {@@ -451,7 +451,7 @@ if (gbacore->renderer.outputBuffer) {
renderer = &gbacore->renderer.d; } int fakeBool; -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) { renderer = &gbacore->glRenderer.d; mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale);
@@ -46,7 +46,7 @@ "uniform vec2 insize;\n"
"varying vec2 texCoord;\n" "void main() {\n" - " vec2 ratio = insize / 256.0;\n" + " vec2 ratio = insize;\n" " vec2 scaledOffset = offset * dims;\n" " gl_Position = vec4(scaledOffset.x * 2.0 - dims.x, scaledOffset.y * -2.0 + dims.y, 0.0, 1.0);\n" " texCoord = offset * ratio;\n"@@ -91,6 +91,7 @@ static unsigned framecount = 0;
static unsigned framecap = 10; static u32 vibrationDeviceHandles[4]; static HidVibrationValue vibrationStop = { .freq_low = 160.f, .freq_high = 320.f }; +static bool usePbo = true; static enum ScreenMode { SM_PA,@@ -110,9 +111,9 @@
EGLConfig config; EGLint numConfigs; static const EGLint attributeList[] = { - EGL_RED_SIZE, 1, - EGL_GREEN_SIZE, 1, - EGL_BLUE_SIZE, 1, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, EGL_NONE }; eglChooseConfig(s_display, attributeList, &config, 1, &numConfigs);@@ -165,6 +166,7 @@ mInputBindKey(map, binding, __builtin_ctz(nativeKey), key);
} static void _drawStart(void) { + glClearColor(0.f, 0.f, 0.f, 1.f); glClear(GL_COLOR_BUFFER_BIT); }@@ -242,7 +244,15 @@ _mapKey(&runner->core->inputMap, AUTO_INPUT, KEY_DRIGHT, GBA_KEY_RIGHT);
_mapKey(&runner->core->inputMap, AUTO_INPUT, KEY_L, GBA_KEY_L); _mapKey(&runner->core->inputMap, AUTO_INPUT, KEY_R, GBA_KEY_R); - runner->core->setVideoBuffer(runner->core, frameBuffer, 256); + int fakeBool; + if (mCoreConfigGetIntValue(&runner->config, "hwaccelVideo", &fakeBool) && fakeBool && runner->core->supportsFeature(runner->core, mCORE_FEATURE_OPENGL)) { + runner->core->setVideoGLTex(runner->core, tex); + usePbo = false; + } else { + runner->core->setVideoBuffer(runner->core, frameBuffer, 256); + usePbo = true; + } + runner->core->setPeripheral(runner->core, mPERIPH_RUMBLE, &rumble.d); runner->core->setPeripheral(runner->core, mPERIPH_ROTATION, &rotation); runner->core->setAVStream(runner->core, &stream);@@ -281,6 +291,8 @@ hidSendVibrationValues(vibrationDeviceHandles, values, 4);
} static void _drawTex(struct mGUIRunner* runner, unsigned width, unsigned height, bool faded) { + glViewport(0, 0, 1280, 720); + glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);@@ -315,26 +327,33 @@ aspectY *= max;
glUniform1i(texLocation, 0); glUniform2f(dimsLocation, aspectX, aspectY); - glUniform2f(insizeLocation, width, height); + if (usePbo) { + glUniform2f(insizeLocation, width / 256.f, height / 256.f); + } else { + glUniform2f(insizeLocation, 1, 1); + } if (!faded) { glUniform4f(colorLocation, 1.0f, 1.0f, 1.0f, 1.0f); } else { - glUniform4f(colorLocation, 0.8f, 0.8f, 0.8f, 0.8f); + glUniform4f(colorLocation, 0.8f, 0.8f, 0.8f, 0.8f); } glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glBindVertexArray(0); glUseProgram(0); + glDisable(GL_BLEND); } static void _prepareForFrame(struct mGUIRunner* runner) { - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); - frameBuffer = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, 256 * 256 * 4, GL_MAP_WRITE_BIT); - if (frameBuffer) { - runner->core->setVideoBuffer(runner->core, frameBuffer, 256); + if (usePbo) { + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); + frameBuffer = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, 256 * 256 * 4, GL_MAP_WRITE_BIT); + if (frameBuffer) { + runner->core->setVideoBuffer(runner->core, frameBuffer, 256); + } + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); } - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); } static void _drawFrame(struct mGUIRunner* runner, bool faded) {@@ -346,13 +365,17 @@
unsigned width, height; runner->core->desiredVideoDimensions(runner->core, &width, &height); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + glActiveTexture(GL_TEXTURE0); + if (usePbo) { + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, tex); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, height, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + glBindTexture(GL_TEXTURE_2D, tex); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, height, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + } else { + glBindTexture(GL_TEXTURE_2D, tex); + } _drawTex(runner, width, height, faded);@@ -689,8 +712,42 @@ GUI_V_U(30),
}, .nStates = 16 }, + { + .title = "GPU-accelerated renderer (experimental, requires game reload)", + .data = "hwaccelVideo", + .submenu = 0, + .state = 0, + .validStates = (const char*[]) { + "Off", + "On", + }, + .nStates = 2 + }, + { + .title = "Hi-res scaling (requires GPU rendering)", + .data = "videoScale", + .submenu = 0, + .state = 0, + .validStates = (const char*[]) { + "1x", + "2x", + "3x", + "4x", + "5x", + "6x", + }, + .stateMappings = (const struct GUIVariant[]) { + GUI_V_U(1), + GUI_V_U(2), + GUI_V_U(3), + GUI_V_U(4), + GUI_V_U(5), + GUI_V_U(6), + }, + .nStates = 6 + }, }, - .nConfigExtra = 2, + .nConfigExtra = 4, .setup = _setup, .teardown = NULL, .gameLoaded = _gameLoaded,