From 3db6d5676c0d225c5e7570017f13521c761dd7c6 Mon Sep 17 00:00:00 2001 From: rogerman Date: Mon, 12 Aug 2024 11:23:23 -0700 Subject: [PATCH] OpenGL Renderer: Do some more code cleanup and tune-ups. - In the 3.2 Core Profile and ES renderers, synchronization of vertex info uploads now occurs at a more reasonable time. - Geometry rendering is now Y-flipped by default, eliminating the need to Y-flip the final output framebuffer under all conditions. - Legacy OpenGL no longer needs to perform any color conversion of the final output framebuffer if FBOs are supported. - Rename some functions and variables to better describe what things are doing now. --- desmume/src/OGLRender.cpp | 398 +++++++++++++++------------------- desmume/src/OGLRender.h | 26 ++- desmume/src/OGLRender_3_2.cpp | 118 ++++++---- desmume/src/OGLRender_3_2.h | 11 +- desmume/src/OGLRender_ES3.cpp | 2 +- 5 files changed, 265 insertions(+), 290 deletions(-) diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index 010109f30..d99c8809d 100755 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -310,7 +310,7 @@ void main() \n\ vtxColor = vec4(inColor / 63.0, polyAlpha); \n\ isPolyDrawable = ((polyMode != 3) || polyDrawShadow) ? 1.0 : -1.0;\n\ \n\ - gl_Position = inPosition / 4096.0;\n\ + gl_Position = vec4(inPosition.x, -inPosition.y, inPosition.z, inPosition.w) / 4096.0;\n\ } \n\ "}; @@ -600,7 +600,7 @@ varying vec2 texCoord;\n\ \n\ void main()\n\ {\n\ - texCoord = vec2(inTexCoord0.x, 1.0 - inTexCoord0.y);\n\ + texCoord = inTexCoord0;\n\ gl_Position = vec4(inPosition, 0.0, 1.0);\n\ }\n\ "}; @@ -1277,7 +1277,7 @@ OpenGLRenderer::OpenGLRenderer() _isSampleShadingSupported = false; isVAOSupported = false; _isDepthLEqualPolygonFacingSupported = false; - willFlipAndConvertFramebufferOnGPU = false; + _willConvertFramebufferOnGPU = false; _willUseMultisampleShaders = false; _emulateShadowPolygon = true; @@ -1578,7 +1578,7 @@ Render3DError OpenGLRenderer::FlushFramebuffer(const Color4u8 *__restrict srcFra { OGLRenderRef &OGLRef = *this->ref; - if (this->willFlipAndConvertFramebufferOnGPU && this->isPBOSupported) + if (this->_willConvertFramebufferOnGPU && this->isPBOSupported) { this->_renderNeedsFlushMain = false; return Render3D::FlushFramebuffer(srcFramebuffer, NULL, dstFramebuffer16); @@ -1589,13 +1589,13 @@ Render3DError OpenGLRenderer::FlushFramebuffer(const Color4u8 *__restrict srcFra { return this->_FlushFramebufferConvertOnCPU(srcFramebuffer, dstFramebufferMain, dstFramebuffer16, - !this->willFlipAndConvertFramebufferOnGPU); + !this->_willConvertFramebufferOnGPU); } else { return this->_FlushFramebufferConvertOnCPU(srcFramebuffer, dstFramebufferMain, dstFramebuffer16, - !this->willFlipAndConvertFramebufferOnGPU); + !this->_willConvertFramebufferOnGPU); } } @@ -1604,7 +1604,7 @@ Render3DError OpenGLRenderer::FlushFramebuffer(const Color4u8 *__restrict srcFra Color4u8* OpenGLRenderer::GetFramebuffer() { - return (this->willFlipAndConvertFramebufferOnGPU && this->isPBOSupported) ? this->_mappedFramebuffer : GPU->GetEngineMain()->Get3DFramebufferMain(); + return (this->_willConvertFramebufferOnGPU && this->isPBOSupported) ? this->_mappedFramebuffer : GPU->GetEngineMain()->Get3DFramebufferMain(); } GLsizei OpenGLRenderer::GetLimitedMultisampleSize() const @@ -2367,7 +2367,7 @@ Render3DError OpenGLRenderer_1_2::InitExtensions() std::set oglExtensionSet; this->GetExtensionSet(&oglExtensionSet); -#if !defined(GL_ES_VERSION_3_0) +#if defined(GL_VERSION_1_2) if (!this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_multitexture")) { return OGLERROR_DRIVER_VERSION_TOO_OLD; @@ -2607,7 +2607,7 @@ Render3DError OpenGLRenderer_1_2::InitExtensions() } // Set rendering support flags based on driver features. - this->willFlipAndConvertFramebufferOnGPU = this->isShaderSupported && this->isVBOSupported; + this->_willConvertFramebufferOnGPU = this->isShaderSupported && this->isVBOSupported; this->_deviceInfo.isEdgeMarkSupported = this->isShaderSupported && this->isVBOSupported && this->isFBOSupported; this->_deviceInfo.isFogSupported = this->isShaderSupported && this->isVBOSupported && this->isFBOSupported; this->_deviceInfo.isTextureSmoothingSupported = this->isShaderSupported; @@ -2714,7 +2714,7 @@ Render3DError OpenGLRenderer_1_2::CreateVAOs() glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_INT, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, texCoord)); glVertexAttribPointer(OGLVertexAttributeID_Color, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, color)); } -#if !defined(GL_ES_VERSION_3_0) +#if defined(GL_VERSION_1_2) else { glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -3847,7 +3847,7 @@ void OpenGLRenderer_1_2::_SetupGeometryShaders(const OGLGeometryFlags flags) glUniform1i(OGLRef.uniformPolyDrawShadow[flags.value], GL_FALSE); } -Render3DError OpenGLRenderer_1_2::EnableVertexAttributes() +void OpenGLRenderer_1_2::_RenderGeometryVertexAttribEnable() { OGLRenderRef &OGLRef = *this->ref; @@ -3855,58 +3855,48 @@ Render3DError OpenGLRenderer_1_2::EnableVertexAttributes() { glBindVertexArray(OGLRef.vaoGeometryStatesID); } + else if (this->isShaderSupported) + { + glEnableVertexAttribArray(OGLVertexAttributeID_Position); + glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); + glEnableVertexAttribArray(OGLVertexAttributeID_Color); + glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_INT, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, position)); + glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_INT, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, texCoord)); + glVertexAttribPointer(OGLVertexAttributeID_Color, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, color)); + } +#if defined(GL_VERSION_1_2) else { - if (this->isShaderSupported) - { - glEnableVertexAttribArray(OGLVertexAttributeID_Position); - glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); - glEnableVertexAttribArray(OGLVertexAttributeID_Color); - glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_INT, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, position)); - glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_INT, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, texCoord)); - glVertexAttribPointer(OGLVertexAttributeID_Color, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, color)); - } -#if !defined(GL_ES_VERSION_3_0) - else - { - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glVertexPointer(4, GL_FLOAT, 0, OGLRef.position4fBuffer); - glTexCoordPointer(2, GL_FLOAT, 0, OGLRef.texCoord2fBuffer); - glColorPointer(4, GL_FLOAT, 0, OGLRef.color4fBuffer); - } -#endif + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glVertexPointer(4, GL_FLOAT, 0, OGLRef.position4fBuffer); + glTexCoordPointer(2, GL_FLOAT, 0, OGLRef.texCoord2fBuffer); + glColorPointer(4, GL_FLOAT, 0, OGLRef.color4fBuffer); } - - return OGLERROR_NOERR; +#endif } -Render3DError OpenGLRenderer_1_2::DisableVertexAttributes() +void OpenGLRenderer_1_2::_RenderGeometryVertexAttribDisable() { if (this->isVAOSupported) { glBindVertexArray(0); } + else if (this->isShaderSupported) + { + glDisableVertexAttribArray(OGLVertexAttributeID_Position); + glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); + glDisableVertexAttribArray(OGLVertexAttributeID_Color); + } +#if defined(GL_VERSION_1_2) else { - if (this->isShaderSupported) - { - glDisableVertexAttribArray(OGLVertexAttributeID_Position); - glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); - glDisableVertexAttribArray(OGLVertexAttributeID_Color); - } -#if !defined(GL_ES_VERSION_3_0) - else - { - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - } -#endif + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); } - - return OGLERROR_NOERR; +#endif } Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr) @@ -3922,8 +3912,6 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLY *rawPolyList, cons // Fully transparent pixels (alpha == 0) -- Set stencil buffer to 0 // All other pixels (alpha != 0) -- Set stencil buffer to 1 - this->DisableVertexAttributes(); - const bool isRunningMSAA = this->isMultisampledFBOSupported && (OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID); if (isRunningMSAA) @@ -3950,31 +3938,9 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLY *rawPolyList, cons glDrawBuffer(GL_NONE); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); - - if (this->isVAOSupported) - { - glBindVertexArray(OGLRef.vaoPostprocessStatesID); - } - else - { - glEnableVertexAttribArray(OGLVertexAttributeID_Position); - glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); - glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0); - glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8)); - } - + this->_FramebufferProcessVertexAttribEnable(); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - if (this->isVAOSupported) - { - glBindVertexArray(0); - } - else - { - glDisableVertexAttribArray(OGLVertexAttributeID_Position); - glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); - } - // Setup for multiple pass alpha poly drawing OGLGeometryFlags oldGProgramFlags = this->_geometryProgramFlags; this->_geometryProgramFlags.EnableEdgeMark = 0; @@ -3985,7 +3951,7 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLY *rawPolyList, cons glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID); - this->EnableVertexAttributes(); + this->_RenderGeometryVertexAttribEnable(); // Draw the alpha polys, touching fully transparent pixels only once. glEnable(GL_DEPTH_TEST); @@ -4095,13 +4061,56 @@ void OpenGLRenderer_1_2::_ResolveFinalFramebuffer() glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); } -Render3DError OpenGLRenderer_1_2::ReadBackPixels() +void OpenGLRenderer_1_2::_FramebufferProcessVertexAttribEnable() +{ + if (!this->isShaderSupported) + { + // Framebuffer processing requires shaders, so there is no legacy code path + // for this method. + return; + } + + if (this->isVAOSupported) + { + glBindVertexArray(this->ref->vaoPostprocessStatesID); + } + else + { + glEnableVertexAttribArray(OGLVertexAttributeID_Position); + glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); + glDisableVertexAttribArray(OGLVertexAttributeID_Color); // Framebuffer processing doesn't use vertex colors. + glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0); + glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8)); + } +} + +void OpenGLRenderer_1_2::_FramebufferProcessVertexAttribDisable() +{ + if (!this->isShaderSupported) + { + // Framebuffer processing requires shaders, so there is no legacy code path + // for this method. + return; + } + + if (this->isVAOSupported) + { + glBindVertexArray(0); + } + else + { + glDisableVertexAttribArray(OGLVertexAttributeID_Position); + glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); + glDisableVertexAttribArray(OGLVertexAttributeID_Color); + } +} + +Render3DError OpenGLRenderer_1_2::_FramebufferConvertColorFormat() { OGLRenderRef &OGLRef = *this->ref; - // Both flips and converts the framebuffer on the GPU. No additional postprocessing - // should be necessary at this point. - if (this->willFlipAndConvertFramebufferOnGPU) + if ( this->_willConvertFramebufferOnGPU && + ((this->_outputFormat == NDSColorFormat_BGR666_Rev) || (OGLRef.readPixelsBestFormat == GL_BGRA)) ) { const GLuint convertProgramID = (this->_outputFormat == NDSColorFormat_BGR666_Rev) ? OGLRef.programFramebufferRGBA6665OutputID : OGLRef.programFramebufferRGBA8888OutputID; glUseProgram(convertProgramID); @@ -4125,46 +4134,11 @@ Render3DError OpenGLRenderer_1_2::ReadBackPixels() glDisable(GL_BLEND); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); - - if (this->isVAOSupported) - { - glBindVertexArray(OGLRef.vaoPostprocessStatesID); - } - else - { - glEnableVertexAttribArray(OGLVertexAttributeID_Position); - glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); - glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0); - glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8)); - } - + this->_FramebufferProcessVertexAttribEnable(); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - if (this->isVAOSupported) - { - glBindVertexArray(0); - } - else - { - glDisableVertexAttribArray(OGLVertexAttributeID_Position); - glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); - } + this->_FramebufferProcessVertexAttribDisable(); } - if (this->isPBOSupported) - { - // Read back the pixels in BGRA format, since legacy OpenGL devices may experience a performance - // penalty if the readback is in any other format. - if (this->_mappedFramebuffer != NULL) - { - glUnmapBuffer(GL_PIXEL_PACK_BUFFER); - this->_mappedFramebuffer = NULL; - } - - glReadPixels(0, 0, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight, OGLRef.readPixelsBestFormat, OGLRef.readPixelsBestDataType, 0); - } - - this->_pixelReadNeedsFinish = true; return OGLERROR_NOERR; } @@ -4370,7 +4344,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co } } } -#if !defined(GL_ES_VERSION_3_0) +#if defined(GL_VERSION_1_2) else { if (renderState.DISP3DCNT.EnableAlphaTest && (renderState.alphaTestRef > 0)) @@ -4381,10 +4355,6 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co { glAlphaFunc(GL_GREATER, 0); } - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glScalef(1.0f, -1.0f, 1.0f); } #endif } @@ -4398,6 +4368,42 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co this->_geometryProgramFlags.OpaqueDrawMode = 1; } + this->_needsZeroDstAlphaPass = true; + + return OGLERROR_NOERR; +} + +void OpenGLRenderer_1_2::_RenderGeometryLoopBegin() +{ + OGLRenderRef &OGLRef = *this->ref; + + glDisable(GL_CULL_FACE); // Polygons should already be culled before we get here. + glEnable(GL_DEPTH_TEST); + glEnable(GL_STENCIL_TEST); + + if (this->_enableAlphaBlending) + { + glEnable(GL_BLEND); + } + else + { + glDisable(GL_BLEND); + } + + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDepthMask(GL_TRUE); + +#if defined(GL_VERSION_1_2) + if (!this->isShaderSupported) + { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glScalef(1.0f, -1.0f, 1.0f); + } +#endif + + glActiveTexture(GL_TEXTURE0); + if (this->isFBOSupported) { if (this->_enableMultisampledRendering) @@ -4423,34 +4429,31 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); } + this->_RenderGeometryVertexAttribEnable(); +} + +void OpenGLRenderer_1_2::_RenderGeometryLoopEnd() +{ + this->_RenderGeometryVertexAttribDisable(); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); - this->_needsZeroDstAlphaPass = true; - - return OGLERROR_NOERR; +#if defined(GL_VERSION_1_2) + if (!this->isShaderSupported) + { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glScalef(1.0f, 1.0f, 1.0f); + } +#endif } Render3DError OpenGLRenderer_1_2::RenderGeometry() { if (this->_clippedPolyCount > 0) { - glDisable(GL_CULL_FACE); // Polygons should already be culled before we get here. - glEnable(GL_DEPTH_TEST); - glEnable(GL_STENCIL_TEST); - - if (this->_enableAlphaBlending) - { - glEnable(GL_BLEND); - } - else - { - glDisable(GL_BLEND); - } - - glActiveTexture(GL_TEXTURE0); - - this->EnableVertexAttributes(); + this->_RenderGeometryLoopBegin(); size_t indexOffset = 0; @@ -4517,9 +4520,7 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry() this->DrawPolygonsForIndexRange(rawPolyList, this->_clippedPolyList, this->_clippedPolyCount, this->_clippedPolyOpaqueCount, this->_clippedPolyCount - 1, indexOffset, lastPolyAttr); } - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDepthMask(GL_TRUE); - this->DisableVertexAttributes(); + this->_RenderGeometryLoopEnd(); } if (!this->_willUseMultisampleShaders) @@ -4557,18 +4558,7 @@ Render3DError OpenGLRenderer_1_2::PostprocessFramebuffer() glDisable(GL_DEPTH_TEST); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); - - if (this->isVAOSupported) - { - glBindVertexArray(OGLRef.vaoPostprocessStatesID); - } - else - { - glEnableVertexAttribArray(OGLVertexAttributeID_Position); - glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); - glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0); - glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8)); - } + this->_FramebufferProcessVertexAttribEnable(); if (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported) { @@ -4656,30 +4646,40 @@ Render3DError OpenGLRenderer_1_2::PostprocessFramebuffer() glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX); } - if (this->isVAOSupported) - { - glBindVertexArray(0); - } - else - { - glDisableVertexAttribArray(OGLVertexAttributeID_Position); - glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); - } + this->_FramebufferProcessVertexAttribDisable(); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::EndRender() { - //needs to happen before endgl because it could free some textureids for expired cache items - texCache.Evict(); + OGLRenderRef &OGLRef = *this->ref; if (this->_willUseMultisampleShaders) { this->_ResolveFinalFramebuffer(); } - this->ReadBackPixels(); + this->_FramebufferConvertColorFormat(); + + if (this->isPBOSupported) + { + // If PBOs are supported, then begin the asynchronous pixel read. + // The asynchronous pixel read ends when RenderFinish() is called, + // which is always called before RenderFlush(). + if (this->_mappedFramebuffer != NULL) + { + glUnmapBuffer(GL_PIXEL_PACK_BUFFER); + this->_mappedFramebuffer = NULL; + } + + glReadPixels(0, 0, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight, OGLRef.readPixelsBestFormat, OGLRef.readPixelsBestDataType, 0); + } + + this->_pixelReadNeedsFinish = true; + + //needs to happen before endgl because it could free some textureids for expired cache items + texCache.Evict(); ENDGL(); @@ -4928,7 +4928,7 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly, bool treatAs glUniform1f(OGLRef.uniformPolyDepthOffset[this->_geometryProgramFlags.value], 0.0f); glUniform1i(OGLRef.uniformPolyIsBackFacing[this->_geometryProgramFlags.value], (isBackFacing) ? GL_TRUE : GL_FALSE); } -#if !defined(GL_ES_VERSION_3_0) +#if defined(GL_VERSION_1_2) else { // Set the texture blending mode @@ -4970,7 +4970,7 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, size_t polyR glUniform1i(OGLRef.uniformTexSingleBitAlpha[this->_geometryProgramFlags.value], (packFormat != TEXMODE_A3I5 && packFormat != TEXMODE_A5I3) ? GL_TRUE : GL_FALSE); glUniform2f(OGLRef.uniformPolyTexScale[this->_geometryProgramFlags.value], theTexture->GetInvWidth(), theTexture->GetInvHeight()); } -#if !defined(GL_ES_VERSION_3_0) +#if defined(GL_VERSION_1_2) else { glEnable(GL_TEXTURE_2D); @@ -5176,7 +5176,7 @@ Render3DError OpenGLRenderer_1_2::Reset() glFinish(); -#if !defined(GL_ES_VERSION_3_0) +#if defined(GL_VERSION_1_2) if (!this->isShaderSupported) { glEnable(GL_NORMALIZE); @@ -5471,43 +5471,6 @@ Render3DError OpenGLRenderer_2_0::InitFinalRenderStates(const std::setref; - - if (this->isVAOSupported) - { - glBindVertexArray(OGLRef.vaoGeometryStatesID); - } - else - { - glEnableVertexAttribArray(OGLVertexAttributeID_Position); - glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); - glEnableVertexAttribArray(OGLVertexAttributeID_Color); - glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_INT, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, position)); - glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_INT, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, texCoord)); - glVertexAttribPointer(OGLVertexAttributeID_Color, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, color)); - } - - return OGLERROR_NOERR; -} - -Render3DError OpenGLRenderer_2_0::DisableVertexAttributes() -{ - if (this->isVAOSupported) - { - glBindVertexArray(0); - } - else - { - glDisableVertexAttribArray(OGLVertexAttributeID_Position); - glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); - glDisableVertexAttribArray(OGLVertexAttributeID_Color); - } - - return OGLERROR_NOERR; -} - Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList) { OGLRenderRef &OGLRef = *this->ref; @@ -5657,25 +5620,6 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State &renderState, co this->_geometryProgramFlags.OpaqueDrawMode = 1; } - if (this->isFBOSupported) - { - if (this->_enableMultisampledRendering) - { - OGLRef.selectedRenderingFBO = OGLRef.fboMSIntermediateRenderID; - } - else - { - OGLRef.selectedRenderingFBO = OGLRef.fboRenderID; - } - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); - glDrawBuffers(4, this->_geometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); - glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); - } - - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDepthMask(GL_TRUE); - this->_needsZeroDstAlphaPass = true; return OGLERROR_NOERR; diff --git a/desmume/src/OGLRender.h b/desmume/src/OGLRender.h index c703106d0..5d9eb17b7 100755 --- a/desmume/src/OGLRender.h +++ b/desmume/src/OGLRender.h @@ -871,7 +871,7 @@ protected: bool isShaderSupported; bool _isSampleShadingSupported; bool isVAOSupported; - bool willFlipAndConvertFramebufferOnGPU; + bool _willConvertFramebufferOnGPU; bool _willUseMultisampleShaders; bool _emulateShadowPolygon; @@ -961,12 +961,16 @@ protected: virtual void GetExtensionSet(std::set *oglExtensionSet) = 0; virtual void _SetupGeometryShaders(const OGLGeometryFlags flags) = 0; - virtual Render3DError EnableVertexAttributes() = 0; - virtual Render3DError DisableVertexAttributes() = 0; + virtual void _RenderGeometryVertexAttribEnable() = 0; + virtual void _RenderGeometryVertexAttribDisable() = 0; + virtual void _RenderGeometryLoopBegin() = 0; + virtual void _RenderGeometryLoopEnd() = 0; virtual void _ResolveWorkingBackFacing() = 0; virtual void _ResolveGeometry() = 0; virtual void _ResolveFinalFramebuffer() = 0; - virtual Render3DError ReadBackPixels() = 0; + virtual void _FramebufferProcessVertexAttribEnable() = 0; + virtual void _FramebufferProcessVertexAttribDisable() = 0; + virtual Render3DError _FramebufferConvertColorFormat() = 0; virtual Render3DError DrawShadowPolygon(const GLenum polyPrimitive, const GLsizei vertIndexCount, const GLushort *indexBufferPtr, const bool performDepthEqualTest, const bool enableAlphaDepthWrite, const bool isTranslucent, const u8 opaquePolyID) = 0; virtual void SetPolygonIndex(const size_t index) = 0; @@ -1039,13 +1043,17 @@ protected: virtual void GetExtensionSet(std::set *oglExtensionSet); virtual void _SetupGeometryShaders(const OGLGeometryFlags flags); - virtual Render3DError EnableVertexAttributes(); - virtual Render3DError DisableVertexAttributes(); + virtual void _RenderGeometryVertexAttribEnable(); + virtual void _RenderGeometryVertexAttribDisable(); virtual Render3DError ZeroDstAlphaPass(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr); + virtual void _RenderGeometryLoopBegin(); + virtual void _RenderGeometryLoopEnd(); virtual void _ResolveWorkingBackFacing(); virtual void _ResolveGeometry(); virtual void _ResolveFinalFramebuffer(); - virtual Render3DError ReadBackPixels(); + virtual void _FramebufferProcessVertexAttribEnable(); + virtual void _FramebufferProcessVertexAttribDisable(); + virtual Render3DError _FramebufferConvertColorFormat(); // Base rendering methods virtual Render3DError BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList); @@ -1082,10 +1090,6 @@ public: protected: virtual Render3DError InitFinalRenderStates(const std::set *oglExtensionSet); - - virtual Render3DError EnableVertexAttributes(); - virtual Render3DError DisableVertexAttributes(); - virtual Render3DError BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList); }; diff --git a/desmume/src/OGLRender_3_2.cpp b/desmume/src/OGLRender_3_2.cpp index a0884ea86..7ad0d0148 100755 --- a/desmume/src/OGLRender_3_2.cpp +++ b/desmume/src/OGLRender_3_2.cpp @@ -201,7 +201,7 @@ void main()\n\ \n\ vtxTexCoord = (texScaleMtx * inTexCoord0) / 16.0;\n\ vtxColor = vec4(inColor / 63.0, polyAlpha);\n\ - gl_Position = inPosition / 4096.0;\n\ + gl_Position = vec4(inPosition.x, -inPosition.y, inPosition.z, inPosition.w) / 4096.0;\n\ }\n\ "}; @@ -729,7 +729,7 @@ out vec2 texCoord;\n\ \n\ void main()\n\ {\n\ - texCoord = vec2(inTexCoord0.x, 1.0 - inTexCoord0.y);\n\ + texCoord = inTexCoord0;\n\ gl_Position = vec4(inPosition, 0.0, 1.0);\n\ }\n\ "}; @@ -779,6 +779,12 @@ OpenGLRenderer_3_2::~OpenGLRenderer_3_2() { glFinish(); + if (this->_syncBufferSetup != NULL) + { + glDeleteSync(this->_syncBufferSetup); + this->_syncBufferSetup = NULL; + } + glUseProgram(0); this->DestroyMSGeometryZeroDstAlphaProgram(); @@ -832,7 +838,7 @@ Render3DError OpenGLRenderer_3_2::InitExtensions() glActiveTexture(GL_TEXTURE0); // OpenGL v3.2 Core Profile should have all the necessary features to be able to flip and convert the framebuffer. - this->willFlipAndConvertFramebufferOnGPU = true; + this->_willConvertFramebufferOnGPU = true; this->_isSampleShadingSupported = this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_sample_shading"); this->_isConservativeDepthSupported = this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_conservative_depth") && IsOpenGLDriverVersionSupported(4, 0, 0); @@ -2327,16 +2333,14 @@ void OpenGLRenderer_3_2::_SetupGeometryShaders(const OGLGeometryFlags flags) glUniform1i(OGLRef.uniformPolyDrawShadow[flags.value], GL_FALSE); } -Render3DError OpenGLRenderer_3_2::EnableVertexAttributes() +void OpenGLRenderer_3_2::_RenderGeometryVertexAttribEnable() { glBindVertexArray(this->ref->vaoGeometryStatesID); - return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_3_2::DisableVertexAttributes() +void OpenGLRenderer_3_2::_RenderGeometryVertexAttribDisable() { glBindVertexArray(0); - return OGLERROR_NOERR; } Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr) @@ -2347,8 +2351,6 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLY *rawPolyList, cons // Fully transparent pixels (alpha == 0) -- Set stencil buffer to 0 // All other pixels (alpha != 0) -- Set stencil buffer to 1 - this->DisableVertexAttributes(); - const bool isRunningMSAA = this->_enableMultisampledRendering && (OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID); const bool isRunningMSAAWithPerSampleShading = isRunningMSAA && this->_willUseMultisampleShaders; // Doing per-sample shading will be more accurate than not doing so. @@ -2378,7 +2380,6 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLY *rawPolyList, cons glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); glBindVertexArray(OGLRef.vaoPostprocessStatesID); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glBindVertexArray(0); // Setup for multiple pass alpha poly drawing OGLGeometryFlags oldGProgramFlags = this->_geometryProgramFlags; @@ -2390,7 +2391,7 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLY *rawPolyList, cons glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID); - this->EnableVertexAttributes(); + glBindVertexArray(OGLRef.vaoGeometryStatesID); // Draw the alpha polys, touching fully transparent pixels only once. glEnable(GL_DEPTH_TEST); @@ -2492,14 +2493,22 @@ void OpenGLRenderer_3_2::_ResolveFinalFramebuffer() glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID); } -Render3DError OpenGLRenderer_3_2::ReadBackPixels() +void OpenGLRenderer_3_2::_FramebufferProcessVertexAttribEnable() +{ + glBindVertexArray(this->ref->vaoPostprocessStatesID); +} + +void OpenGLRenderer_3_2::_FramebufferProcessVertexAttribDisable() +{ + glBindVertexArray(0); +} + +Render3DError OpenGLRenderer_3_2::_FramebufferConvertColorFormat() { OGLRenderRef &OGLRef = *this->ref; if (this->_outputFormat == NDSColorFormat_BGR666_Rev) { - // Both flips and converts the framebuffer on the GPU. No additional postprocessing - // should be necessary at this point. glUseProgram(OGLRef.programFramebufferRGBA6665OutputID); glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID); glReadBuffer(OGL_WORKING_ATTACHMENT_ID); @@ -2515,30 +2524,7 @@ Render3DError OpenGLRenderer_3_2::ReadBackPixels() glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindVertexArray(0); } - else - { - // Just flips the framebuffer in Y to match the coordinates of OpenGL and the NDS hardware. - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID); - glReadBuffer(OGL_COLOROUT_ATTACHMENT_ID); - glDrawBuffer(OGL_WORKING_ATTACHMENT_ID); - glBlitFramebuffer(0, (GLint)this->_framebufferHeight, (GLint)this->_framebufferWidth, 0, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - glReadBuffer(OGL_WORKING_ATTACHMENT_ID); - } - if (this->isPBOSupported) - { - // 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. - if (this->_mappedFramebuffer != NULL) - { - glUnmapBuffer(GL_PIXEL_PACK_BUFFER); - this->_mappedFramebuffer = NULL; - } - - glReadPixels(0, 0, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight, OGLRef.readPixelsBestFormat, OGLRef.readPixelsBestDataType, 0); - } - - this->_pixelReadNeedsFinish = true; return OGLERROR_NOERR; } @@ -2569,6 +2555,7 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, co { glWaitSync(this->_syncBufferSetup, 0, GL_TIMEOUT_IGNORED); glDeleteSync(this->_syncBufferSetup); + this->_syncBufferSetup = NULL; } const size_t vtxBufferSize = sizeof(NDSVertex) * renderGList.rawVertCount; @@ -2576,8 +2563,6 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, co memcpy(vtxPtr, renderGList.rawVtxList, vtxBufferSize); glUnmapBuffer(GL_ARRAY_BUFFER); - this->_syncBufferSetup = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); - // Generate the clipped polygon list. if ( (OGLRef.uboPolyStatesID != 0) && (this->_clippedPolyCount > MAX_CLIPPED_POLY_COUNT_FOR_UBO) ) { @@ -2773,11 +2758,11 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, co if (this->_enableMultisampledRendering) { - OGLRef.selectedRenderingFBO = OGLRef.fboMSIntermediateRenderID; + OGLRef.selectedRenderingFBO = OGLRef.fboMSIntermediateRenderID; } else { - OGLRef.selectedRenderingFBO = OGLRef.fboRenderID; + OGLRef.selectedRenderingFBO = OGLRef.fboRenderID; } glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); @@ -2791,6 +2776,50 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, co return OGLERROR_NOERR; } +void OpenGLRenderer_3_2::_RenderGeometryLoopBegin() +{ + OGLRenderRef &OGLRef = *this->ref; + + glDisable(GL_CULL_FACE); // Polygons should already be culled before we get here. + glEnable(GL_DEPTH_TEST); + glEnable(GL_STENCIL_TEST); + + if (this->_enableAlphaBlending) + { + glEnable(GL_BLEND); + } + else + { + glDisable(GL_BLEND); + } + + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDepthMask(GL_TRUE); + + glActiveTexture(GL_TEXTURE0); + + if (this->_enableMultisampledRendering) + { + OGLRef.selectedRenderingFBO = OGLRef.fboMSIntermediateRenderID; + } + else + { + OGLRef.selectedRenderingFBO = OGLRef.fboRenderID; + } + + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); + glDrawBuffers(4, this->_geometryDrawBuffersEnum[this->_geometryProgramFlags.DrawBuffersMode]); + glReadBuffer(GL_COLOR_ATTACHMENT0); + + this->_RenderGeometryVertexAttribEnable(); +} + +void OpenGLRenderer_3_2::_RenderGeometryLoopEnd() +{ + OpenGLRenderer_2_1::_RenderGeometryLoopEnd(); + this->_syncBufferSetup = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); +} + Render3DError OpenGLRenderer_3_2::PostprocessFramebuffer() { if ( (this->_clippedPolyCount < 1) || @@ -3042,13 +3071,6 @@ void OpenGLRenderer_3_2::SetPolygonIndex(const size_t index) { this->_currentPolyIndex = index; glUniform1i(this->ref->uniformPolyStateIndex[this->_geometryProgramFlags.value], (GLint)index); - - if (this->_syncBufferSetup != NULL) - { - glWaitSync(this->_syncBufferSetup, 0, GL_TIMEOUT_IGNORED); - glDeleteSync(this->_syncBufferSetup); - this->_syncBufferSetup = NULL; - } } Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer, bool isBackFacing) diff --git a/desmume/src/OGLRender_3_2.h b/desmume/src/OGLRender_3_2.h index 7d8ab2f7c..91953cef2 100644 --- a/desmume/src/OGLRender_3_2.h +++ b/desmume/src/OGLRender_3_2.h @@ -95,13 +95,18 @@ protected: virtual void GetExtensionSet(std::set *oglExtensionSet); virtual void _SetupGeometryShaders(const OGLGeometryFlags flags); - virtual Render3DError EnableVertexAttributes(); - virtual Render3DError DisableVertexAttributes(); + virtual void _RenderGeometryVertexAttribEnable(); + virtual void _RenderGeometryVertexAttribDisable(); virtual Render3DError ZeroDstAlphaPass(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr); + virtual void _RenderGeometryLoopBegin(); + virtual void _RenderGeometryLoopEnd(); virtual void _ResolveWorkingBackFacing(); virtual void _ResolveGeometry(); virtual void _ResolveFinalFramebuffer(); - virtual Render3DError ReadBackPixels(); + virtual void _FramebufferProcessVertexAttribEnable(); + virtual void _FramebufferProcessVertexAttribDisable(); + virtual Render3DError _FramebufferConvertColorFormat(); + virtual Render3DError BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList); virtual Render3DError PostprocessFramebuffer(); diff --git a/desmume/src/OGLRender_ES3.cpp b/desmume/src/OGLRender_ES3.cpp index af727fa3c..dee5a7618 100644 --- a/desmume/src/OGLRender_ES3.cpp +++ b/desmume/src/OGLRender_ES3.cpp @@ -346,7 +346,7 @@ Render3DError OpenGLESRenderer_3_0::InitExtensions() glActiveTexture(GL_TEXTURE0); // OpenGL ES 3.0 should have all the necessary features to be able to flip and convert the framebuffer. - this->willFlipAndConvertFramebufferOnGPU = true; + this->_willConvertFramebufferOnGPU = true; this->_enableTextureSmoothing = CommonSettings.GFX3D_Renderer_TextureSmoothing; this->_emulateShadowPolygon = CommonSettings.OpenGL_Emulation_ShadowPolygon;