diff --git a/CHANGES b/CHANGES index da14c8b59..0f4783510 100644 --- a/CHANGES +++ b/CHANGES @@ -27,6 +27,7 @@ Misc: - Qt: Handle multiple save game files for disparate games separately (fixes mgba.io/i/2887) - Qt: Remove maligned double-click-to-fullscreen shortcut (closes mgba.io/i/2632) - Scripting: Add `callbacks:oneshot` for single-call callbacks + - Switch: Add bilinear filtering option (closes mgba.io/i/3111) 0.10.3: (2024-01-07) Emulation fixes: diff --git a/src/platform/switch/main.c b/src/platform/switch/main.c index 3e891ab3d..36f2627ad 100644 --- a/src/platform/switch/main.c +++ b/src/platform/switch/main.c @@ -125,6 +125,12 @@ static enum ScreenMode { SM_MAX } screenMode = SM_PA; +static enum FilterMode { + FM_NEAREST, + FM_LINEAR, + FM_MAX +} filterMode = FM_NEAREST; + static bool eglInit() { s_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (!s_display) { @@ -314,6 +320,9 @@ static void _setup(struct mGUIRunner* runner) { if (mCoreConfigGetUIntValue(&runner->config, "screenMode", &mode) && mode < SM_MAX) { screenMode = mode; } + if (mCoreConfigGetUIntValue(&runner->config, "filterMode", &mode) && mode < FM_MAX) { + filterMode = mode; + } runner->core->setAudioBufferSize(runner->core, SAMPLES); } @@ -331,6 +340,9 @@ static void _gameLoaded(struct mGUIRunner* runner) { if (mCoreConfigGetUIntValue(&runner->config, "screenMode", &mode) && mode < SM_MAX) { screenMode = mode; } + if (mCoreConfigGetUIntValue(&runner->config, "filterMode", &mode) && mode < FM_MAX) { + filterMode = mode; + } int fakeBool; if (mCoreConfigGetIntValue(&runner->config, "interframeBlending", &fakeBool)) { @@ -381,6 +393,8 @@ static void _gameUnloaded(struct mGUIRunner* runner) { static void _drawTex(struct mGUIRunner* runner, unsigned width, unsigned height, bool faded, bool blendTop) { glViewport(0, 1080 - vheight, vwidth, vheight); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterMode == FM_LINEAR ? GL_LINEAR : GL_NEAREST); + glUseProgram(program); glBindVertexArray(vao); float inwidth = width; @@ -711,21 +725,18 @@ static void glInit(void) { 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_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glGenTextures(1, &oldTex); glBindTexture(GL_TEXTURE_2D, oldTex); 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_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glGenTextures(1, &screenshotTex); glBindTexture(GL_TEXTURE_2D, screenshotTex); 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_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glGenBuffers(1, &pbo); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); @@ -981,11 +992,22 @@ int main(int argc, char* argv[]) { }, .nStates = 16 }, + { + .title = "Filtering", + .data = GUI_V_S("filterMode"), + .submenu = 0, + .state = FM_NEAREST, + .validStates = (const char*[]) { + "None", + "Bilinear", + }, + .nStates = 2 + }, { .title = "GPU-accelerated renderer", .data = GUI_V_S("hwaccelVideo"), .submenu = 0, - .state = 0, + .state = FM_NEAREST, .validStates = (const char*[]) { "Off", "On",