mirror of https://github.com/mgba-emu/mgba.git
Switch: Experimental support for hi-res mode
This commit is contained in:
parent
a64c38d314
commit
585563eed7
|
@ -18,7 +18,7 @@
|
||||||
#ifndef DISABLE_THREADING
|
#ifndef DISABLE_THREADING
|
||||||
#include <mgba/feature/thread-proxy.h>
|
#include <mgba/feature/thread-proxy.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef BUILD_GLES2
|
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
|
||||||
#include <mgba/internal/gba/renderers/gl.h>
|
#include <mgba/internal/gba/renderers/gl.h>
|
||||||
#endif
|
#endif
|
||||||
#include <mgba/internal/gba/renderers/proxy.h>
|
#include <mgba/internal/gba/renderers/proxy.h>
|
||||||
|
@ -130,7 +130,7 @@ struct mVideoLogContext;
|
||||||
struct GBACore {
|
struct GBACore {
|
||||||
struct mCore d;
|
struct mCore d;
|
||||||
struct GBAVideoSoftwareRenderer renderer;
|
struct GBAVideoSoftwareRenderer renderer;
|
||||||
#ifdef BUILD_GLES2
|
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
|
||||||
struct GBAVideoGLRenderer glRenderer;
|
struct GBAVideoGLRenderer glRenderer;
|
||||||
#endif
|
#endif
|
||||||
struct GBAVideoProxyRenderer proxyRenderer;
|
struct GBAVideoProxyRenderer proxyRenderer;
|
||||||
|
@ -180,7 +180,7 @@ static bool _GBACoreInit(struct mCore* core) {
|
||||||
GBAVideoSoftwareRendererCreate(&gbacore->renderer);
|
GBAVideoSoftwareRendererCreate(&gbacore->renderer);
|
||||||
gbacore->renderer.outputBuffer = NULL;
|
gbacore->renderer.outputBuffer = NULL;
|
||||||
|
|
||||||
#ifdef BUILD_GLES2
|
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
|
||||||
GBAVideoGLRendererCreate(&gbacore->glRenderer);
|
GBAVideoGLRendererCreate(&gbacore->glRenderer);
|
||||||
gbacore->glRenderer.outputTex = -1;
|
gbacore->glRenderer.outputTex = -1;
|
||||||
#endif
|
#endif
|
||||||
|
@ -229,7 +229,7 @@ static bool _GBACoreSupportsFeature(const struct mCore* core, enum mCoreFeature
|
||||||
UNUSED(core);
|
UNUSED(core);
|
||||||
switch (feature) {
|
switch (feature) {
|
||||||
case mCORE_FEATURE_OPENGL:
|
case mCORE_FEATURE_OPENGL:
|
||||||
#ifdef BUILD_GLES2
|
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
|
@ -289,7 +289,7 @@ static void _GBACoreLoadConfig(struct mCore* core, const struct mCoreConfig* con
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _GBACoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
|
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;
|
struct GBACore* gbacore = (struct GBACore*) core;
|
||||||
int scale = gbacore->glRenderer.scale;
|
int scale = gbacore->glRenderer.scale;
|
||||||
#else
|
#else
|
||||||
|
@ -308,7 +308,7 @@ static void _GBACoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t s
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _GBACoreSetVideoGLTex(struct mCore* core, unsigned texid) {
|
static void _GBACoreSetVideoGLTex(struct mCore* core, unsigned texid) {
|
||||||
#ifdef BUILD_GLES2
|
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
|
||||||
struct GBACore* gbacore = (struct GBACore*) core;
|
struct GBACore* gbacore = (struct GBACore*) core;
|
||||||
gbacore->glRenderer.outputTex = texid;
|
gbacore->glRenderer.outputTex = texid;
|
||||||
#else
|
#else
|
||||||
|
@ -442,7 +442,7 @@ static void _GBACoreReset(struct mCore* core) {
|
||||||
struct GBACore* gbacore = (struct GBACore*) core;
|
struct GBACore* gbacore = (struct GBACore*) core;
|
||||||
struct GBA* gba = (struct GBA*) core->board;
|
struct GBA* gba = (struct GBA*) core->board;
|
||||||
if (gbacore->renderer.outputBuffer
|
if (gbacore->renderer.outputBuffer
|
||||||
#ifdef BUILD_GLES2
|
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
|
||||||
|| gbacore->glRenderer.outputTex != (unsigned) -1
|
|| gbacore->glRenderer.outputTex != (unsigned) -1
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
|
@ -451,7 +451,7 @@ static void _GBACoreReset(struct mCore* core) {
|
||||||
renderer = &gbacore->renderer.d;
|
renderer = &gbacore->renderer.d;
|
||||||
}
|
}
|
||||||
int fakeBool;
|
int fakeBool;
|
||||||
#ifdef BUILD_GLES2
|
#if defined(BUILD_GLES2) || defined(BUILD_GLES3)
|
||||||
if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) {
|
if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) {
|
||||||
renderer = &gbacore->glRenderer.d;
|
renderer = &gbacore->glRenderer.d;
|
||||||
mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale);
|
mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale);
|
||||||
|
|
|
@ -46,7 +46,7 @@ static const char* const _vertexShader =
|
||||||
"varying vec2 texCoord;\n"
|
"varying vec2 texCoord;\n"
|
||||||
|
|
||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" vec2 ratio = insize / 256.0;\n"
|
" vec2 ratio = insize;\n"
|
||||||
" vec2 scaledOffset = offset * dims;\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"
|
" gl_Position = vec4(scaledOffset.x * 2.0 - dims.x, scaledOffset.y * -2.0 + dims.y, 0.0, 1.0);\n"
|
||||||
" texCoord = offset * ratio;\n"
|
" texCoord = offset * ratio;\n"
|
||||||
|
@ -91,6 +91,7 @@ static unsigned framecount = 0;
|
||||||
static unsigned framecap = 10;
|
static unsigned framecap = 10;
|
||||||
static u32 vibrationDeviceHandles[4];
|
static u32 vibrationDeviceHandles[4];
|
||||||
static HidVibrationValue vibrationStop = { .freq_low = 160.f, .freq_high = 320.f };
|
static HidVibrationValue vibrationStop = { .freq_low = 160.f, .freq_high = 320.f };
|
||||||
|
static bool usePbo = true;
|
||||||
|
|
||||||
static enum ScreenMode {
|
static enum ScreenMode {
|
||||||
SM_PA,
|
SM_PA,
|
||||||
|
@ -110,9 +111,9 @@ static bool initEgl() {
|
||||||
EGLConfig config;
|
EGLConfig config;
|
||||||
EGLint numConfigs;
|
EGLint numConfigs;
|
||||||
static const EGLint attributeList[] = {
|
static const EGLint attributeList[] = {
|
||||||
EGL_RED_SIZE, 1,
|
EGL_RED_SIZE, 8,
|
||||||
EGL_GREEN_SIZE, 1,
|
EGL_GREEN_SIZE, 8,
|
||||||
EGL_BLUE_SIZE, 1,
|
EGL_BLUE_SIZE, 8,
|
||||||
EGL_NONE
|
EGL_NONE
|
||||||
};
|
};
|
||||||
eglChooseConfig(s_display, attributeList, &config, 1, &numConfigs);
|
eglChooseConfig(s_display, attributeList, &config, 1, &numConfigs);
|
||||||
|
@ -165,6 +166,7 @@ static void _mapKey(struct mInputMap* map, uint32_t binding, int nativeKey, enum
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _drawStart(void) {
|
static void _drawStart(void) {
|
||||||
|
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +244,15 @@ static void _setup(struct mGUIRunner* runner) {
|
||||||
_mapKey(&runner->core->inputMap, AUTO_INPUT, KEY_L, GBA_KEY_L);
|
_mapKey(&runner->core->inputMap, AUTO_INPUT, KEY_L, GBA_KEY_L);
|
||||||
_mapKey(&runner->core->inputMap, AUTO_INPUT, KEY_R, GBA_KEY_R);
|
_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_RUMBLE, &rumble.d);
|
||||||
runner->core->setPeripheral(runner->core, mPERIPH_ROTATION, &rotation);
|
runner->core->setPeripheral(runner->core, mPERIPH_ROTATION, &rotation);
|
||||||
runner->core->setAVStream(runner->core, &stream);
|
runner->core->setAVStream(runner->core, &stream);
|
||||||
|
@ -281,6 +291,8 @@ static void _gameUnloaded(struct mGUIRunner* runner) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _drawTex(struct mGUIRunner* runner, unsigned width, unsigned height, bool faded) {
|
static void _drawTex(struct mGUIRunner* runner, unsigned width, unsigned height, bool faded) {
|
||||||
|
glViewport(0, 0, 1280, 720);
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
@ -315,26 +327,33 @@ static void _drawTex(struct mGUIRunner* runner, unsigned width, unsigned height,
|
||||||
|
|
||||||
glUniform1i(texLocation, 0);
|
glUniform1i(texLocation, 0);
|
||||||
glUniform2f(dimsLocation, aspectX, aspectY);
|
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) {
|
if (!faded) {
|
||||||
glUniform4f(colorLocation, 1.0f, 1.0f, 1.0f, 1.0f);
|
glUniform4f(colorLocation, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
} else {
|
} 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);
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
|
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _prepareForFrame(struct mGUIRunner* runner) {
|
static void _prepareForFrame(struct mGUIRunner* runner) {
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
|
if (usePbo) {
|
||||||
frameBuffer = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, 256 * 256 * 4, GL_MAP_WRITE_BIT);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
|
||||||
if (frameBuffer) {
|
frameBuffer = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, 256 * 256 * 4, GL_MAP_WRITE_BIT);
|
||||||
runner->core->setVideoBuffer(runner->core, frameBuffer, 256);
|
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) {
|
static void _drawFrame(struct mGUIRunner* runner, bool faded) {
|
||||||
|
@ -346,13 +365,17 @@ static void _drawFrame(struct mGUIRunner* runner, bool faded) {
|
||||||
unsigned width, height;
|
unsigned width, height;
|
||||||
runner->core->desiredVideoDimensions(runner->core, &width, &height);
|
runner->core->desiredVideoDimensions(runner->core, &width, &height);
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
|
|
||||||
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, tex);
|
if (usePbo) {
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, height, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
||||||
|
|
||||||
|
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);
|
_drawTex(runner, width, height, faded);
|
||||||
|
|
||||||
|
@ -689,8 +712,42 @@ int main(int argc, char* argv[]) {
|
||||||
},
|
},
|
||||||
.nStates = 16
|
.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,
|
.setup = _setup,
|
||||||
.teardown = NULL,
|
.teardown = NULL,
|
||||||
.gameLoaded = _gameLoaded,
|
.gameLoaded = _gameLoaded,
|
||||||
|
|
Loading…
Reference in New Issue