From 5b66a455b0226aa84fcd953c7ebdb70850971b46 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 27 May 2019 14:05:11 -0700 Subject: [PATCH] Switch: Interframe blending --- src/platform/switch/main.c | 65 +++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 8 deletions(-) diff --git a/src/platform/switch/main.c b/src/platform/switch/main.c index 3c86706ae..33e2b9298 100644 --- a/src/platform/switch/main.c +++ b/src/platform/switch/main.c @@ -15,6 +15,7 @@ #include #include #include +#include #define AUTO_INPUT 0x4E585031 #define SAMPLES 0x400 @@ -67,11 +68,13 @@ static GLuint program; static GLuint vbo; static GLuint vao; static GLuint pbo; +static GLuint copyFbo; static GLuint texLocation; static GLuint dimsLocation; static GLuint insizeLocation; static GLuint colorLocation; static GLuint tex; +static GLuint oldTex; static color_t* frameBuffer; static struct mAVStream stream; @@ -95,6 +98,7 @@ static bool usePbo = true; static u8 vmode; static u32 vwidth; static u32 vheight; +static bool interframeBlending = false; static enum ScreenMode { SM_PA, @@ -130,7 +134,8 @@ static bool initEgl() { } EGLint contextAttributeList[] = { - EGL_CONTEXT_CLIENT_VERSION, 3, + EGL_CONTEXT_MAJOR_VERSION, 3, + EGL_CONTEXT_MINOR_VERSION, 1, EGL_NONE }; s_context = eglCreateContext(s_display, config, EGL_NO_CONTEXT, contextAttributeList); @@ -283,6 +288,10 @@ static void _gameLoaded(struct mGUIRunner* runner) { screenMode = mode; } + int fakeBool; + mCoreConfigGetIntValue(&runner->config, "interframeBlending", &fakeBool); + interframeBlending = fakeBool; + rumble.up = 0; rumble.down = 0; } @@ -296,7 +305,7 @@ static void _gameUnloaded(struct mGUIRunner* runner) { hidSendVibrationValues(vibrationDeviceHandles, values, 4); } -static void _drawTex(struct mGUIRunner* runner, unsigned width, unsigned height, bool faded) { +static void _drawTex(struct mGUIRunner* runner, unsigned width, unsigned height, bool faded, bool blendTop) { glViewport(0, 1080 - vheight, vwidth, vheight); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -341,9 +350,9 @@ static void _drawTex(struct mGUIRunner* runner, unsigned width, unsigned height, glUniform2f(insizeLocation, 1, 1); } if (!faded) { - glUniform4f(colorLocation, 1.0f, 1.0f, 1.0f, 1.0f); + glUniform4f(colorLocation, 1.0f, 1.0f, 1.0f, blendTop ? 0.5f : 1.0f); } else { - glUniform4f(colorLocation, 0.8f, 0.8f, 0.8f, 0.8f); + glUniform4f(colorLocation, 0.8f, 0.8f, 0.8f, blendTop ? 0.4f : 0.8f); } glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -355,6 +364,20 @@ static void _drawTex(struct mGUIRunner* runner, unsigned width, unsigned height, } static void _prepareForFrame(struct mGUIRunner* runner) { + if (interframeBlending) { + glBindFramebuffer(GL_READ_FRAMEBUFFER, copyFbo); + glReadBuffer(GL_COLOR_ATTACHMENT0); + int width, height; + int format; + glBindTexture(GL_TEXTURE_2D, tex); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format); + glBindTexture(GL_TEXTURE_2D, oldTex); + glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, width, height, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + } + if (usePbo) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); frameBuffer = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, 256 * 256 * 4, GL_MAP_WRITE_BIT); @@ -382,11 +405,19 @@ static void _drawFrame(struct mGUIRunner* runner, bool faded) { 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 { + } else if (!interframeBlending) { glBindTexture(GL_TEXTURE_2D, tex); } - _drawTex(runner, width, height, faded); + if (interframeBlending) { + glBindTexture(GL_TEXTURE_2D, oldTex); + _drawTex(runner, width, height, faded, false); + glBindTexture(GL_TEXTURE_2D, tex); + _drawTex(runner, width, height, faded, true); + } else { + _drawTex(runner, width, height, faded, false); + } + HidVibrationValue values[4]; if (rumble.up) { @@ -412,7 +443,7 @@ static void _drawScreenshot(struct mGUIRunner* runner, const color_t* pixels, un glBindTexture(GL_TEXTURE_2D, tex); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - _drawTex(runner, width, height, faded); + _drawTex(runner, width, height, faded, false); } static uint16_t _pollGameInput(struct mGUIRunner* runner) { @@ -556,20 +587,36 @@ int main(int argc, char* argv[]) { glViewport(0, 1080 - vheight, vwidth, vheight); glClearColor(0.f, 0.f, 0.f, 1.f); - glGenTextures(1, &tex); glActiveTexture(GL_TEXTURE0); + glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, 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); 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); + glGenBuffers(1, &pbo); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); glBufferData(GL_PIXEL_UNPACK_BUFFER, 256 * 256 * 4, NULL, GL_STREAM_DRAW); frameBuffer = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, 256 * 256 * 4, GL_MAP_WRITE_BIT); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + glGenFramebuffers(1, ©Fbo); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_2D, oldTex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glBindFramebuffer(GL_READ_FRAMEBUFFER, copyFbo); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + program = glCreateProgram(); GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); @@ -829,7 +876,9 @@ int main(int argc, char* argv[]) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); glDeleteBuffers(1, &pbo); + glDeleteFramebuffers(1, ©Fbo); glDeleteTextures(1, &tex); + glDeleteTextures(1, &oldTex); glDeleteBuffers(1, &vbo); glDeleteProgram(program); glDeleteVertexArrays(1, &vao);