diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index cdc872cd5..b70d3fb80 100755 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -1060,11 +1060,13 @@ OpenGLRenderer::OpenGLRenderer() ref->fboMSIntermediateRenderID = 0; ref->fboPostprocessID = 0; ref->selectedRenderingFBO = 0; + ref->texFinalColorID = 0; _mappedFramebuffer = NULL; _workingTextureUnpackBuffer = (FragmentColor *)malloc_alignedCacheLine(1024 * 1024 * sizeof(FragmentColor)); _pixelReadNeedsFinish = false; _currentPolyIndex = 0; + _lastTextureDrawTarget = OGLTextureUnitID_GColor; } OpenGLRenderer::~OpenGLRenderer() @@ -1532,11 +1534,15 @@ OpenGLRenderer_1_2::~OpenGLRenderer_1_2() // Kill the texture cache now before all of our texture IDs disappear. texCache.Reset(); + glDeleteTextures(1, &ref->texFinalColorID); + ref->texFinalColorID = 0; + glFinish(); } Render3DError OpenGLRenderer_1_2::InitExtensions() { + OGLRenderRef &OGLRef = *this->ref; Render3DError error = OGLERROR_NOERR; // Get OpenGL extensions @@ -1622,7 +1628,19 @@ Render3DError OpenGLRenderer_1_2::InitExtensions() } } - if (!this->isShaderSupported) + if (this->isShaderSupported) + { + glGenTextures(1, &OGLRef.texFinalColorID); + glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_FinalColor); + glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + glActiveTextureARB(GL_TEXTURE0_ARB); + } + else { INFO("OpenGL: Shaders are unsupported. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n"); } @@ -1665,10 +1683,35 @@ Render3DError OpenGLRenderer_1_2::InitExtensions() this->willFlipFramebufferOnGPU = this->isPBOSupported; this->willConvertFramebufferOnGPU = (this->isShaderSupported && this->isPBOSupported); + // This texture will be used as an FBO color attachment. + // If this texture wasn't already created by passing the shader support check, + // then create the texture now. + bool createdTextureForFBO = false; + if (OGLRef.texFinalColorID == 0) + { + glGenTextures(1, &OGLRef.texFinalColorID); + glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_FinalColor); + glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + glActiveTextureARB(GL_TEXTURE0_ARB); + + createdTextureForFBO = true; + } + error = this->CreateFBOs(); if (error != OGLERROR_NOERR) { this->isFBOSupported = false; + + if (createdTextureForFBO) + { + glDeleteTextures(1, &OGLRef.texFinalColorID); + OGLRef.texFinalColorID = 0; + } } } else @@ -2017,25 +2060,12 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() glGenTextures(1, &OGLRef.texCIPolyID); glGenTextures(1, &OGLRef.texCIDepthStencilID); - glGenTextures(1, &OGLRef.texFinalColorID); glGenTextures(1, &OGLRef.texGColorID); glGenTextures(1, &OGLRef.texGDepthID); glGenTextures(1, &OGLRef.texGFogAttrID); glGenTextures(1, &OGLRef.texGPolyID); glGenTextures(1, &OGLRef.texGDepthStencilID); glGenTextures(1, &OGLRef.texZeroAlphaPixelMaskID); - glGenTextures(1, &OGLRef.texPostprocessFogID); - - if (this->willFlipFramebufferOnGPU) - { - glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_FinalColor); - glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); - } glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_GColor); glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthStencilID); @@ -2087,13 +2117,6 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() glActiveTextureARB(GL_TEXTURE0_ARB); - glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessFogID); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); - glBindTexture(GL_TEXTURE_2D, OGLRef.texCIColorID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -2132,14 +2155,6 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() glBindTexture(GL_TEXTURE_2D, 0); - // Set up RBOs - if (this->willConvertFramebufferOnGPU) - { - glGenRenderbuffersEXT(1, &OGLRef.rboFramebufferRGBA6665ID); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboFramebufferRGBA6665ID); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); - } - // Set up FBOs glGenFramebuffersEXT(1, &OGLRef.fboClearImageID); glGenFramebuffersEXT(1, &OGLRef.fboRenderID); @@ -2155,7 +2170,7 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { - INFO("OpenGL: Failed to created FBOs!\n"); + INFO("OpenGL: Failed to create FBOs!\n"); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &OGLRef.fboClearImageID); @@ -2172,9 +2187,6 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() glDeleteTextures(1, &OGLRef.texGFogAttrID); glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texZeroAlphaPixelMaskID); - glDeleteTextures(1, &OGLRef.texPostprocessFogID); - glDeleteTextures(1, &OGLRef.texFinalColorID); - glDeleteRenderbuffersEXT(1, &OGLRef.rboFramebufferRGBA6665ID); OGLRef.fboClearImageID = 0; OGLRef.fboRenderID = 0; @@ -2200,13 +2212,12 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, OGLRef.texGDepthID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, OGLRef.texGPolyID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, GL_TEXTURE_2D, OGLRef.texGFogAttrID, 0); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT4_EXT, GL_TEXTURE_2D, OGLRef.texZeroAlphaPixelMaskID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texGDepthStencilID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texGDepthStencilID, 0); if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { - INFO("OpenGL: Failed to created FBOs!\n"); + INFO("OpenGL: Failed to create FBOs!\n"); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &OGLRef.fboClearImageID); @@ -2223,9 +2234,6 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() glDeleteTextures(1, &OGLRef.texGFogAttrID); glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texZeroAlphaPixelMaskID); - glDeleteTextures(1, &OGLRef.texPostprocessFogID); - glDeleteTextures(1, &OGLRef.texFinalColorID); - glDeleteRenderbuffersEXT(1, &OGLRef.rboFramebufferRGBA6665ID); OGLRef.fboClearImageID = 0; OGLRef.fboRenderID = 0; @@ -2247,17 +2255,9 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, OGLRef.texPostprocessFogID, 0); - - if (this->willFlipFramebufferOnGPU) - { - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, OGLRef.texFinalColorID, 0); - } - - if (this->willConvertFramebufferOnGPU) - { - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboFramebufferRGBA6665ID); - } + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, OGLRef.texGColorID, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, OGLRef.texFinalColorID, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, OGLRef.texZeroAlphaPixelMaskID, 0); if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { @@ -2278,9 +2278,6 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() glDeleteTextures(1, &OGLRef.texGFogAttrID); glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texZeroAlphaPixelMaskID); - glDeleteTextures(1, &OGLRef.texPostprocessFogID); - glDeleteTextures(1, &OGLRef.texFinalColorID); - glDeleteRenderbuffersEXT(1, &OGLRef.rboFramebufferRGBA6665ID); OGLRef.fboClearImageID = 0; OGLRef.fboRenderID = 0; @@ -2324,9 +2321,6 @@ void OpenGLRenderer_1_2::DestroyFBOs() glDeleteTextures(1, &OGLRef.texGFogAttrID); glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texZeroAlphaPixelMaskID); - glDeleteTextures(1, &OGLRef.texPostprocessFogID); - glDeleteTextures(1, &OGLRef.texFinalColorID); - glDeleteRenderbuffersEXT(1, &OGLRef.rboFramebufferRGBA6665ID); OGLRef.fboClearImageID = 0; OGLRef.fboRenderID = 0; @@ -2988,12 +2982,12 @@ Render3DError OpenGLRenderer_1_2::InitFramebufferOutputShaderLocations() OGLRenderRef &OGLRef = *this->ref; glUseProgram(OGLRef.programFramebufferRGBA6665OutputID); - const GLint uniformTexFinalColorRGBA6665 = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID, "texInFragColor"); - glUniform1i(uniformTexFinalColorRGBA6665, OGLTextureUnitID_FinalColor); + OGLRef.uniformTexInFragColor_ConvertRGBA6665 = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID, "texInFragColor"); + glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_FinalColor); glUseProgram(OGLRef.programFramebufferRGBA8888OutputID); - const GLint uniformTexFinalColorRGBA8888 = glGetUniformLocation(OGLRef.programFramebufferRGBA8888OutputID, "texInFragColor"); - glUniform1i(uniformTexFinalColorRGBA8888, OGLTextureUnitID_FinalColor); + OGLRef.uniformTexInFragColor_ConvertRGBA8888 = glGetUniformLocation(OGLRef.programFramebufferRGBA8888OutputID, "texInFragColor"); + glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA8888, OGLTextureUnitID_FinalColor); return OGLERROR_NOERR; } @@ -3136,8 +3130,6 @@ Render3DError OpenGLRenderer_1_2::EnableVertexAttributes() } } - glActiveTextureARB(GL_TEXTURE0_ARB); - return OGLERROR_NOERR; } @@ -3235,10 +3227,29 @@ Render3DError OpenGLRenderer_1_2::ReadBackPixels() if (this->willFlipFramebufferOnGPU) { glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); - glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); + + if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor) + { + glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); + this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor; + } + else + { + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + this->_lastTextureDrawTarget = OGLTextureUnitID_GColor; + } + glBlitFramebufferEXT(0, this->_framebufferHeight, this->_framebufferWidth, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); - glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); + + if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor) + { + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + } + else + { + glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); + } } if (this->willConvertFramebufferOnGPU) @@ -3246,9 +3257,22 @@ Render3DError OpenGLRenderer_1_2::ReadBackPixels() // Perform the color space conversion while we're still on the GPU so // that we can avoid having to do it on the CPU. const GLuint convertProgramID = (this->_outputFormat == NDSColorFormat_BGR666_Rev) ? OGLRef.programFramebufferRGBA6665OutputID : OGLRef.programFramebufferRGBA8888OutputID; - glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); glUseProgram(convertProgramID); + + if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor) + { + glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_GColor); + glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); + this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor; + } + else + { + glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_FinalColor); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + this->_lastTextureDrawTarget = OGLTextureUnitID_GColor; + } + glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); @@ -3282,8 +3306,14 @@ Render3DError OpenGLRenderer_1_2::ReadBackPixels() glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); } - // Read back the pixels. - glReadBuffer(GL_COLOR_ATTACHMENT2_EXT); + if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor) + { + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + } + else + { + glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); + } } // Read back the pixels in BGRA format, since legacy OpenGL devices may experience a performance @@ -3459,6 +3489,8 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState, glDisable(GL_BLEND); } + glActiveTextureARB(GL_TEXTURE0_ARB); + this->EnableVertexAttributes(); const POLY &firstPoly = polyList->list[indexList->list[0]]; @@ -3559,6 +3591,8 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState, this->DownsampleFBO(); + this->_lastTextureDrawTarget = OGLTextureUnitID_GColor; + return OGLERROR_NOERR; } @@ -3606,7 +3640,7 @@ Render3DError OpenGLRenderer_1_2::RenderEdgeMarking(const u16 *colorTable, const alpha}; // Set up the postprocessing states - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); @@ -3628,7 +3662,7 @@ Render3DError OpenGLRenderer_1_2::RenderEdgeMarking(const u16 *colorTable, const } // Pass 1: Determine the pixels with zero alpha - glDrawBuffer(GL_COLOR_ATTACHMENT4_EXT); + glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); glUseProgram(OGLRef.programZeroAlphaPixelMaskID); glDisable(GL_BLEND); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); @@ -3657,8 +3691,11 @@ Render3DError OpenGLRenderer_1_2::RenderEdgeMarking(const u16 *colorTable, const glDisableVertexAttribArray(OGLVertexAttributeID_Position); glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); } + + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + this->_lastTextureDrawTarget = OGLTextureUnitID_GColor; - return RENDER3DERROR_NOERR; + return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly) @@ -3685,6 +3722,7 @@ Render3DError OpenGLRenderer_1_2::RenderFog(const u8 *densityTable, const u32 co const GLfloat oglFogStep = (GLfloat)(0x0400 >> shift) / 32767.0f; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); + glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); glUseProgram(OGLRef.programFogID); glUniform1i(OGLRef.uniformStateEnableFogAlphaOnly, (alphaOnly) ? GL_TRUE : GL_FALSE); glUniform4f(OGLRef.uniformStateFogColor, oglColor[0], oglColor[1], oglColor[2], oglColor[3]); @@ -3725,6 +3763,9 @@ Render3DError OpenGLRenderer_1_2::RenderFog(const u8 *densityTable, const u32 co glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); } + glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); + this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor; + return OGLERROR_NOERR; } @@ -3742,8 +3783,11 @@ Render3DError OpenGLRenderer_1_2::EndRender(const u64 frameCount) Render3DError OpenGLRenderer_1_2::UpdateToonTable(const u16 *toonTableBuffer) { - glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_ToonTable); - glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 32, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, toonTableBuffer); + if (this->isShaderSupported) + { + glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_ToonTable); + glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 32, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, toonTableBuffer); + } return OGLERROR_NOERR; } @@ -4314,6 +4358,13 @@ Render3DError OpenGLRenderer_1_2::SetFramebufferSize(size_t w, size_t h) } } + if (this->isShaderSupported || this->isFBOSupported) + { + glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_FinalColor); + glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + } + if (this->isFBOSupported) { glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_GColor); @@ -4333,10 +4384,6 @@ Render3DError OpenGLRenderer_1_2::SetFramebufferSize(size_t w, size_t h) glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_FogAttr); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); - - glActiveTextureARB(GL_TEXTURE0_ARB); - glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessFogID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); } if (this->isMultisampledFBOSupported) @@ -4355,18 +4402,7 @@ Render3DError OpenGLRenderer_1_2::SetFramebufferSize(size_t w, size_t h) glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_DEPTH24_STENCIL8_EXT, w, h); } - if (this->willFlipFramebufferOnGPU) - { - glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_FinalColor); - glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); - } - - if (this->willConvertFramebufferOnGPU) - { - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboFramebufferRGBA6665ID); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, w, h); - } + glActiveTextureARB(GL_TEXTURE0_ARB); const size_t newFramebufferColorSizeBytes = w * h * sizeof(FragmentColor); @@ -4415,8 +4451,6 @@ Render3DError OpenGLRenderer_2_0::EnableVertexAttributes() glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VERT), OGLRef.vtxPtrColor); } - glActiveTexture(GL_TEXTURE0); - return OGLERROR_NOERR; } diff --git a/desmume/src/OGLRender.h b/desmume/src/OGLRender.h index 526cf873b..cf14e636e 100755 --- a/desmume/src/OGLRender.h +++ b/desmume/src/OGLRender.h @@ -1,7 +1,7 @@ /* Copyright (C) 2006 yopyop Copyright (C) 2006-2007 shash - Copyright (C) 2008-2016 DeSmuME team + Copyright (C) 2008-2017 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -429,7 +429,6 @@ struct OGLRenderRef GLuint texGPolyID; GLuint texZeroAlphaPixelMaskID; GLuint texGDepthStencilID; - GLuint texPostprocessFogID; GLuint texFinalColorID; GLuint rboMSGColorID; @@ -437,7 +436,6 @@ struct OGLRenderRef GLuint rboMSGPolyID; GLuint rboMSGFogAttrID; GLuint rboMSGDepthStencilID; - GLuint rboFramebufferRGBA6665ID; GLuint fboClearImageID; GLuint fboRenderID; @@ -466,6 +464,10 @@ struct OGLRenderRef GLuint programFramebufferRGBA8888OutputID; GLint uniformFramebufferSize; + GLint uniformFramebufferSize_ConvertRGBA6665; + GLint uniformFramebufferSize_ConvertRGBA8888; + GLint uniformTexInFragColor_ConvertRGBA6665; + GLint uniformTexInFragColor_ConvertRGBA8888; GLint uniformStateToonShadingMode; GLint uniformStateEnableAlphaTest; GLint uniformStateEnableAntialiasing; @@ -622,6 +624,7 @@ protected: FragmentColor *_workingTextureUnpackBuffer; bool _pixelReadNeedsFinish; size_t _currentPolyIndex; + OGLTextureUnitID _lastTextureDrawTarget; Render3DError FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstFramebufferMain, u16 *__restrict dstFramebuffer16); OpenGLTexture* GetLoadedTextureFromPolygon(const POLY &thePoly, bool enableTexturing); diff --git a/desmume/src/OGLRender_3_2.cpp b/desmume/src/OGLRender_3_2.cpp index 46eeaa29f..fd74108d6 100644 --- a/desmume/src/OGLRender_3_2.cpp +++ b/desmume/src/OGLRender_3_2.cpp @@ -1,7 +1,7 @@ /* Copyright (C) 2006 yopyop Copyright (C) 2006-2007 shash - Copyright (C) 2008-2016 DeSmuME team + Copyright (C) 2008-2017 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -803,12 +803,12 @@ Render3DError OpenGLRenderer_3_2::InitFramebufferOutputShaderLocations() OGLRenderRef &OGLRef = *this->ref; glUseProgram(OGLRef.programFramebufferRGBA6665OutputID); - const GLint uniformTexFinalColorRGBA6665 = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID, "texInFragColor"); - glUniform1i(uniformTexFinalColorRGBA6665, OGLTextureUnitID_FinalColor); + OGLRef.uniformTexInFragColor_ConvertRGBA6665 = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID, "texInFragColor"); + glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_FinalColor); glUseProgram(OGLRef.programFramebufferRGBA8888OutputID); - const GLint uniformTexFinalColorRGBA8888 = glGetUniformLocation(OGLRef.programFramebufferRGBA8888OutputID, "texInFragColor"); - glUniform1i(uniformTexFinalColorRGBA8888, OGLTextureUnitID_FinalColor); + OGLRef.uniformTexInFragColor_ConvertRGBA8888 = glGetUniformLocation(OGLRef.programFramebufferRGBA8888OutputID, "texInFragColor"); + glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA8888, OGLTextureUnitID_FinalColor); return OGLERROR_NOERR; } @@ -831,7 +831,6 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() glGenTextures(1, &OGLRef.texGPolyID); glGenTextures(1, &OGLRef.texGDepthStencilID); glGenTextures(1, &OGLRef.texZeroAlphaPixelMaskID); - glGenTextures(1, &OGLRef.texPostprocessFogID); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FinalColor); glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID); @@ -891,13 +890,6 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessFogID); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); - glBindTexture(GL_TEXTURE_2D, OGLRef.texCIColorID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -936,11 +928,6 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() glBindTexture(GL_TEXTURE_2D, 0); - // Set up RBOs - glGenRenderbuffers(1, &OGLRef.rboFramebufferRGBA6665ID); - glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboFramebufferRGBA6665ID); - glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); - // Set up FBOs glGenFramebuffers(1, &OGLRef.fboClearImageID); glGenFramebuffers(1, &OGLRef.fboRenderID); @@ -955,7 +942,7 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - INFO("OpenGL: Failed to created FBOs. Some emulation features will be disabled.\n"); + INFO("OpenGL: Failed to create FBOs!\n"); glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &OGLRef.fboClearImageID); @@ -972,9 +959,6 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() glDeleteTextures(1, &OGLRef.texGFogAttrID); glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texZeroAlphaPixelMaskID); - glDeleteTextures(1, &OGLRef.texPostprocessFogID); - glDeleteTextures(1, &OGLRef.texFinalColorID); - glDeleteRenderbuffers(1, &OGLRef.rboFramebufferRGBA6665ID); OGLRef.fboClearImageID = 0; OGLRef.fboRenderID = 0; @@ -996,7 +980,7 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - INFO("OpenGL: Failed to created FBOs. Some emulation features will be disabled.\n"); + INFO("OpenGL: Failed to create FBOs!\n"); glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &OGLRef.fboClearImageID); @@ -1013,9 +997,6 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() glDeleteTextures(1, &OGLRef.texGFogAttrID); glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texZeroAlphaPixelMaskID); - glDeleteTextures(1, &OGLRef.texPostprocessFogID); - glDeleteTextures(1, &OGLRef.texFinalColorID); - glDeleteRenderbuffers(1, &OGLRef.rboFramebufferRGBA6665ID); OGLRef.fboClearImageID = 0; OGLRef.fboRenderID = 0; @@ -1028,13 +1009,13 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() glReadBuffer(GL_COLOR_ATTACHMENT0); glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OGLRef.texPostprocessFogID, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OGLRef.texGColorID, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, OGLRef.texFinalColorID, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_RENDERBUFFER, OGLRef.rboFramebufferRGBA6665ID); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_RENDERBUFFER, OGLRef.texZeroAlphaPixelMaskID); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - INFO("OpenGL: Failed to created FBOs. Some emulation features will be disabled.\n"); + INFO("OpenGL: Failed to create FBOs!\n"); glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &OGLRef.fboClearImageID); @@ -1051,9 +1032,6 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() glDeleteTextures(1, &OGLRef.texGFogAttrID); glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texZeroAlphaPixelMaskID); - glDeleteTextures(1, &OGLRef.texPostprocessFogID); - glDeleteTextures(1, &OGLRef.texFinalColorID); - glDeleteRenderbuffers(1, &OGLRef.rboFramebufferRGBA6665ID); OGLRef.fboClearImageID = 0; OGLRef.fboRenderID = 0; @@ -1096,9 +1074,6 @@ void OpenGLRenderer_3_2::DestroyFBOs() glDeleteTextures(1, &OGLRef.texGFogAttrID); glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texZeroAlphaPixelMaskID); - glDeleteTextures(1, &OGLRef.texPostprocessFogID); - glDeleteTextures(1, &OGLRef.texFinalColorID); - glDeleteRenderbuffers(1, &OGLRef.rboFramebufferRGBA6665ID); OGLRef.fboClearImageID = 0; OGLRef.fboRenderID = 0; @@ -1361,7 +1336,6 @@ void OpenGLRenderer_3_2::GetExtensionSet(std::set *oglExtensionSet) Render3DError OpenGLRenderer_3_2::EnableVertexAttributes() { glBindVertexArray(this->ref->vaoGeometryStatesID); - glActiveTexture(GL_TEXTURE0); return OGLERROR_NOERR; } @@ -1421,18 +1395,50 @@ Render3DError OpenGLRenderer_3_2::ReadBackPixels() // Flip the framebuffer in Y to match the coordinates of OpenGL and the NDS hardware. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboPostprocessID); - glDrawBuffer(GL_COLOR_ATTACHMENT1); + + if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor) + { + glDrawBuffer(GL_COLOR_ATTACHMENT1); + this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor; + } + else + { + glDrawBuffer(GL_COLOR_ATTACHMENT0); + this->_lastTextureDrawTarget = OGLTextureUnitID_GColor; + } + glBlitFramebuffer(0, this->_framebufferHeight, this->_framebufferWidth, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID); - glReadBuffer(GL_COLOR_ATTACHMENT1); + + if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor) + { + glReadBuffer(GL_COLOR_ATTACHMENT0); + } + else + { + glReadBuffer(GL_COLOR_ATTACHMENT1); + } if (this->_outputFormat == NDSColorFormat_BGR666_Rev) { // Perform the RGBA6665 color space conversion while we're still on the GPU so // that we can avoid having to do it on the CPU. - glDrawBuffer(GL_COLOR_ATTACHMENT2); glUseProgram(OGLRef.programFramebufferRGBA6665OutputID); + + if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor) + { + glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_GColor); + glDrawBuffer(GL_COLOR_ATTACHMENT1); + this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor; + } + else + { + glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_FinalColor); + glDrawBuffer(GL_COLOR_ATTACHMENT0); + this->_lastTextureDrawTarget = OGLTextureUnitID_GColor; + } + glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); @@ -1445,17 +1451,20 @@ Render3DError OpenGLRenderer_3_2::ReadBackPixels() glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); glBindVertexArray(0); - glReadBuffer(GL_COLOR_ATTACHMENT2); + if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor) + { + glReadBuffer(GL_COLOR_ATTACHMENT0); + } + else + { + glReadBuffer(GL_COLOR_ATTACHMENT1); + } } // Read back the pixels in RGBA format, since an OpenGL 3.2 device should be able to read back this // format without a performance penalty. glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_RGBA, GL_UNSIGNED_BYTE, 0); - // Set the read and draw target buffers back to color attachment 0, which is always the default. - glReadBuffer(GL_COLOR_ATTACHMENT0); - glDrawBuffer(GL_COLOR_ATTACHMENT0); - this->_pixelReadNeedsFinish = true; return OGLERROR_NOERR; } @@ -1597,7 +1606,7 @@ Render3DError OpenGLRenderer_3_2::RenderEdgeMarking(const u16 *colorTable, const OGLRenderRef &OGLRef = *this->ref; // Set up the postprocessing states - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID); + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID); glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); @@ -1608,7 +1617,7 @@ Render3DError OpenGLRenderer_3_2::RenderEdgeMarking(const u16 *colorTable, const glBindVertexArray(OGLRef.vaoPostprocessStatesID); // Pass 1: Determine the pixels with zero alpha - glDrawBuffer(GL_COLOR_ATTACHMENT4); + glDrawBuffer(GL_COLOR_ATTACHMENT2); glUseProgram(OGLRef.programZeroAlphaPixelMaskID); glDisable(GL_BLEND); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); @@ -1628,7 +1637,10 @@ Render3DError OpenGLRenderer_3_2::RenderEdgeMarking(const u16 *colorTable, const glBindVertexArray(0); - return RENDER3DERROR_NOERR; + glReadBuffer(GL_COLOR_ATTACHMENT0); + this->_lastTextureDrawTarget = OGLTextureUnitID_GColor; + + return OGLERROR_NOERR; } Render3DError OpenGLRenderer_3_2::RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly) @@ -1636,6 +1648,7 @@ Render3DError OpenGLRenderer_3_2::RenderFog(const u8 *densityTable, const u32 co OGLRenderRef &OGLRef = *this->ref; glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID); + glDrawBuffer(GL_COLOR_ATTACHMENT1); glUseProgram(OGLRef.programFogID); glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight); @@ -1652,6 +1665,9 @@ Render3DError OpenGLRenderer_3_2::RenderFog(const u8 *densityTable, const u32 co glBindVertexArray(0); + glReadBuffer(GL_COLOR_ATTACHMENT1); + this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor; + return OGLERROR_NOERR; } @@ -1743,6 +1759,7 @@ Render3DError OpenGLRenderer_3_2::ClearUsingValues(const FragmentColor &clearCol OGLRenderRef &OGLRef = *this->ref; OGLRef.selectedRenderingFBO = (CommonSettings.GFX3D_Renderer_Multisample) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID; glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); + glReadBuffer(GL_COLOR_ATTACHMENT0); glDrawBuffers(4, RenderDrawList); const GLfloat oglColor[4] = {divide6bitBy63_LUT[clearColor6665.r], divide6bitBy63_LUT[clearColor6665.g], divide6bitBy63_LUT[clearColor6665.b], divide5bitBy31_LUT[clearColor6665.a]}; @@ -1905,13 +1922,6 @@ Render3DError OpenGLRenderer_3_2::SetFramebufferSize(size_t w, size_t h) glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FogAttr); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessFogID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); - - glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboFramebufferRGBA6665ID); - glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, w, h); - if (this->isMultisampledFBOSupported) { GLint maxSamples = (GLint)this->_deviceInfo.maxSamples; @@ -1928,6 +1938,8 @@ Render3DError OpenGLRenderer_3_2::SetFramebufferSize(size_t w, size_t h) glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_DEPTH24_STENCIL8, w, h); } + glActiveTexture(GL_TEXTURE0); + const size_t newFramebufferColorSizeBytes = w * h * sizeof(FragmentColor); glBufferData(GL_PIXEL_PACK_BUFFER, newFramebufferColorSizeBytes, NULL, GL_STREAM_READ);