diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index c3cb72a59..468915811 100644 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -41,7 +41,6 @@ static OpenGLRenderer *_OGLRenderer = NULL; // Lookup Tables static CACHE_ALIGN GLfloat material_8bit_to_float[256] = {0}; -static CACHE_ALIGN GLuint dsDepthToD24S8_LUT[32768] = {0}; static CACHE_ALIGN const GLfloat divide5bitBy31_LUT[32] = {0.0, 0.03225806451613, 0.06451612903226, 0.09677419354839, 0.1290322580645, 0.1612903225806, 0.1935483870968, 0.2258064516129, 0.258064516129, 0.2903225806452, 0.3225806451613, 0.3548387096774, @@ -262,78 +261,53 @@ static const char *fragmentShader_100 = {"\ \n\ uniform sampler2D texMainRender; \n\ uniform sampler1D texToonTable; \n\ + \n\ + uniform int stateToonShadingMode; \n\ + uniform bool stateEnableAlphaTest; \n\ + uniform bool stateUseWDepth; \n\ + uniform float stateAlphaTestRef; \n\ + \n\ + uniform int polyMode; \n\ uniform int polyID; \n\ - uniform bool hasTexture; \n\ - uniform int polygonMode; \n\ - uniform int toonShadingMode; \n\ - uniform bool oglWBuffer; \n\ - uniform bool enableAlphaTest; \n\ - uniform float alphaTestRef; \n\ + \n\ + uniform bool polyEnableTexture; \n\ \n\ void main() \n\ { \n\ - vec4 texColor = vec4(1.0, 1.0, 1.0, 1.0); \n\ - vec4 fragColor; \n\ + vec4 mainTexColor = (polyEnableTexture) ? texture2D(texMainRender, vtxTexCoord) : vec4(1.0, 1.0, 1.0, 1.0); \n\ + vec4 tempFragColor = mainTexColor; \n\ \n\ - if(hasTexture) \n\ + if(polyMode == 0) \n\ { \n\ - texColor = texture2D(texMainRender, vtxTexCoord); \n\ + tempFragColor = vtxColor * mainTexColor; \n\ } \n\ - \n\ - fragColor = texColor; \n\ - \n\ - if(polygonMode == 0) \n\ + else if(polyMode == 1) \n\ { \n\ - fragColor = vtxColor * texColor; \n\ + tempFragColor.rgb = (polyEnableTexture) ? (mainTexColor.rgb * mainTexColor.a) + (vtxColor.rgb * (1.0 - mainTexColor.a)) : vtxColor.rgb; \n\ + tempFragColor.a = vtxColor.a; \n\ } \n\ - else if(polygonMode == 1) \n\ + else if(polyMode == 2) \n\ { \n\ - if (texColor.a == 0.0 || !hasTexture) \n\ - { \n\ - fragColor.rgb = vtxColor.rgb; \n\ - } \n\ - else if (texColor.a == 1.0) \n\ - { \n\ - fragColor.rgb = texColor.rgb; \n\ - } \n\ - else \n\ - { \n\ - fragColor.rgb = texColor.rgb * (1.0-texColor.a) + vtxColor.rgb * texColor.a;\n\ - } \n\ - \n\ - fragColor.a = vtxColor.a; \n\ + vec3 toonColor = vec3(texture1D(texToonTable, vtxColor.r).rgb); \n\ + tempFragColor.rgb = (stateToonShadingMode == 0) ? mainTexColor.rgb * toonColor.rgb : min((mainTexColor.rgb * vtxColor.rgb) + toonColor.rgb, 1.0); \n\ + tempFragColor.a = mainTexColor.a * vtxColor.a; \n\ } \n\ - else if(polygonMode == 2) \n\ - { \n\ - if (toonShadingMode == 0) \n\ - { \n\ - vec3 toonColor = vec3(texture1D(texToonTable, vtxColor.r).rgb); \n\ - fragColor.rgb = texColor.rgb * toonColor.rgb;\n\ - fragColor.a = texColor.a * vtxColor.a;\n\ - } \n\ - else \n\ - { \n\ - vec3 toonColor = vec3(texture1D(texToonTable, vtxColor.r).rgb); \n\ - fragColor.rgb = texColor.rgb * vtxColor.rgb + toonColor.rgb; \n\ - fragColor.a = texColor.a * vtxColor.a; \n\ - } \n\ - } \n\ - else if(polygonMode == 3) \n\ + else if(polyMode == 3) \n\ { \n\ if (polyID != 0) \n\ { \n\ - fragColor = vtxColor; \n\ + tempFragColor = vtxColor; \n\ } \n\ } \n\ \n\ - if (fragColor.a == 0.0 || (enableAlphaTest && fragColor.a < alphaTestRef)) \n\ + if (tempFragColor.a == 0.0 || (stateEnableAlphaTest && tempFragColor.a < stateAlphaTestRef)) \n\ { \n\ discard; \n\ } \n\ \n\ float vertW = (vtxPosition.w == 0.0) ? 0.00000001 : vtxPosition.w; \n\ - gl_FragDepth = (oglWBuffer) ? vtxPosition.w/4096.0 : clamp((vtxPosition.z/vertW) * 0.5 + 0.5, 0.0, 1.0); \n\ - gl_FragColor = fragColor; \n\ + gl_FragDepth = (stateUseWDepth) ? vtxPosition.w/4096.0 : clamp((vtxPosition.z/vertW) * 0.5 + 0.5, 0.0, 1.0); \n\ + gl_FragColor = tempFragColor; \n\ } \n\ "}; @@ -357,43 +331,6 @@ FORCEINLINE u32 BGRA8888_32Rev_To_RGBA6665_32Rev(const u32 srcPix) ((dstPix >> 1) & 0xFF000000); // A } -//opengl state caching: -//This is of dubious performance assistance, but it is easy to take out so I am leaving it for now. -//every function that is xgl* can be replaced with gl* if we decide to rip this out or if anyone else -//doesnt feel like sticking with it (or if it causes trouble) - -struct GLCaps { - u8 caps[0x100]; - GLCaps() { - memset(caps,0xFF,sizeof(caps)); - } -}; -static GLCaps glcaps; - -static void _xglEnable(GLenum cap) { - cap -= 0x0B00; - if(glcaps.caps[cap] == 0xFF || glcaps.caps[cap] == 0) { - glEnable(cap+0x0B00); - glcaps.caps[cap] = 1; - } -} - -static void _xglDisable(GLenum cap) { - cap -= 0x0B00; - if(glcaps.caps[cap]) { - glDisable(cap+0x0B00); - glcaps.caps[cap] = 0; - } -} - -#define xglEnable(cap) { \ - CTASSERT((cap-0x0B00)<0x100); \ - _xglEnable(cap); } - -#define xglDisable(cap) {\ - CTASSERT((cap-0x0B00)<0x100); \ - _xglDisable(cap); } - bool IsVersionSupported(unsigned int checkVersionMajor, unsigned int checkVersionMinor, unsigned int checkVersionRevision) { bool result = false; @@ -811,7 +748,7 @@ void OpenGLRenderer::ConvertFramebuffer(const u32 *__restrict srcBuffer, u32 *ds { u32 *__restrict dst = dstBuffer + (y * GFX3D_FRAMEBUFFER_WIDTH); - for(unsigned int x = 0; x < GFX3D_FRAMEBUFFER_WIDTH; x++, i++) + for(size_t x = 0; x < GFX3D_FRAMEBUFFER_WIDTH; x++, i++) { // Use the correct endian format since OpenGL uses the native endian of // the architecture it is running on. @@ -849,7 +786,7 @@ OpenGLRenderer_1_2::~OpenGLRenderer_1_2() gpuScreen3DHasNewData[0] = false; gpuScreen3DHasNewData[1] = false; - delete [] ref->color4fBuffer; + delete[] ref->color4fBuffer; ref->color4fBuffer = NULL; DestroyShaders(); @@ -934,70 +871,47 @@ Render3DError OpenGLRenderer_1_2::InitExtensions() this->CreateVBOs(); } -#if !defined(GL_ARB_pixel_buffer_object) && !defined(GL_EXT_pixel_buffer_object) - this->isPBOSupported = false; -#else this->isPBOSupported = this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_buffer_object") && (this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_pixel_buffer_object") || this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_pixel_buffer_object")); -#endif if (this->isPBOSupported) { this->CreatePBOs(); } -#if !defined(GL_ARB_vertex_array_object) && !defined(GL_APPLE_vertex_array_object) - this->isVAOSupported = false; -#else this->isVAOSupported = this->isShaderSupported && this->isVBOSupported && (this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_array_object") || this->IsExtensionPresent(&oglExtensionSet, "GL_APPLE_vertex_array_object")); -#endif if (this->isVAOSupported) { this->CreateVAOs(); } // Don't use ARB versions since we're using the EXT versions for backwards compatibility. -#if !defined(GL_EXT_framebuffer_object) || \ - !defined(GL_EXT_framebuffer_blit) || \ - !defined(GL_EXT_packed_depth_stencil) - - this->isFBOSupported = false; -#else this->isFBOSupported = this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_object") && this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_blit") && this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_packed_depth_stencil"); -#endif if (this->isFBOSupported) { error = this->CreateFBOs(); if (error != OGLERROR_NOERR) { - OGLRef.fboFinalOutputID = 0; + OGLRef.fboRenderID = 0; this->isFBOSupported = false; } } else { - OGLRef.fboFinalOutputID = 0; + OGLRef.fboRenderID = 0; INFO("OpenGL: FBOs are unsupported. Some emulation features will be disabled.\n"); } // Don't use ARB versions since we're using the EXT versions for backwards compatibility. -#if !defined(GL_EXT_framebuffer_object) || \ - !defined(GL_EXT_framebuffer_multisample) || \ - !defined(GL_EXT_framebuffer_blit) || \ - !defined(GL_EXT_packed_depth_stencil) - - this->isMultisampledFBOSupported = false; -#else this->isMultisampledFBOSupported = this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_object") && this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_blit") && this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_packed_depth_stencil") && this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_multisample"); -#endif if (this->isMultisampledFBOSupported) { error = this->CreateMultisampledFBO(); @@ -1057,7 +971,7 @@ void OpenGLRenderer_1_2::DestroyVBOs() Render3DError OpenGLRenderer_1_2::CreatePBOs() { glGenBuffersARB(2, this->ref->pboRenderDataID); - for (unsigned int i = 0; i < 2; i++) + for (size_t i = 0; i < 2; i++) { glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, this->ref->pboRenderDataID[i]); glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT * sizeof(u32), NULL, GL_STREAM_READ_ARB); @@ -1179,15 +1093,18 @@ Render3DError OpenGLRenderer_1_2::CreateShaders(const std::string *vertexShaderP uniformTexSampler = glGetUniformLocation(OGLRef.shaderProgram, "texToonTable"); glUniform1i(uniformTexSampler, OGLTextureUnitID_ToonTable); - OGLRef.uniformPolyAlpha = glGetUniformLocation(OGLRef.shaderProgram, "polyAlpha"); - OGLRef.uniformTexScale = glGetUniformLocation(OGLRef.shaderProgram, "texScale"); - OGLRef.uniformPolyID = glGetUniformLocation(OGLRef.shaderProgram, "polyID"); - OGLRef.uniformHasTexture = glGetUniformLocation(OGLRef.shaderProgram, "hasTexture"); - OGLRef.uniformPolygonMode = glGetUniformLocation(OGLRef.shaderProgram, "polygonMode"); - OGLRef.uniformToonShadingMode = glGetUniformLocation(OGLRef.shaderProgram, "toonShadingMode"); - OGLRef.uniformWBuffer = glGetUniformLocation(OGLRef.shaderProgram, "oglWBuffer"); - OGLRef.uniformEnableAlphaTest = glGetUniformLocation(OGLRef.shaderProgram, "enableAlphaTest"); - OGLRef.uniformAlphaTestRef = glGetUniformLocation(OGLRef.shaderProgram, "alphaTestRef"); + OGLRef.uniformTexScale = glGetUniformLocation(OGLRef.shaderProgram, "texScale"); + + OGLRef.uniformStateToonShadingMode = glGetUniformLocation(OGLRef.shaderProgram, "stateToonShadingMode"); + OGLRef.uniformStateEnableAlphaTest = glGetUniformLocation(OGLRef.shaderProgram, "stateEnableAlphaTest"); + OGLRef.uniformStateUseWDepth = glGetUniformLocation(OGLRef.shaderProgram, "stateUseWDepth"); + OGLRef.uniformStateAlphaTestRef = glGetUniformLocation(OGLRef.shaderProgram, "stateAlphaTestRef"); + + OGLRef.uniformPolyMode = glGetUniformLocation(OGLRef.shaderProgram, "polyMode"); + OGLRef.uniformPolyAlpha = glGetUniformLocation(OGLRef.shaderProgram, "polyAlpha"); + OGLRef.uniformPolyID = glGetUniformLocation(OGLRef.shaderProgram, "polyID"); + + OGLRef.uniformPolyEnableTexture = glGetUniformLocation(OGLRef.shaderProgram, "polyEnableTexture"); INFO("OpenGL: Successfully created shaders.\n"); @@ -1258,7 +1175,25 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() OGLRenderRef &OGLRef = *this->ref; // Set up FBO render targets - this->CreateClearImage(); + glGenTextures(1, &OGLRef.texClearImageColorID); + glGenTextures(1, &OGLRef.texClearImageDepthStencilID); + + glBindTexture(GL_TEXTURE_2D, OGLRef.texClearImageColorID); + 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, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + + glBindTexture(GL_TEXTURE_2D, OGLRef.texClearImageDepthStencilID); + 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); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL); + + glBindTexture(GL_TEXTURE_2D, 0); // Set up FBOs glGenFramebuffersEXT(1, &OGLRef.fboClearImageID); @@ -1274,15 +1209,16 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &OGLRef.fboClearImageID); - this->DestroyClearImage(); + glDeleteTextures(1, &OGLRef.texClearImageColorID); + glDeleteTextures(1, &OGLRef.texClearImageDepthStencilID); this->isFBOSupported = false; return OGLERROR_FBO_CREATE_ERROR; } // Set up final output FBO - OGLRef.fboFinalOutputID = 0; - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboFinalOutputID); + OGLRef.fboRenderID = 0; + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); INFO("OpenGL: Successfully created FBOs.\n"); @@ -1300,7 +1236,9 @@ void OpenGLRenderer_1_2::DestroyFBOs() glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &OGLRef.fboClearImageID); - this->DestroyClearImage(); + glDeleteTextures(1, &OGLRef.texClearImageColorID); + glDeleteTextures(1, &OGLRef.texClearImageDepthStencilID); + this->isFBOSupported = false; } @@ -1325,35 +1263,35 @@ Render3DError OpenGLRenderer_1_2::CreateMultisampledFBO() OGLRenderRef &OGLRef = *this->ref; // Set up FBO render targets - glGenRenderbuffersEXT(1, &OGLRef.rboMultisampleColorID); - glGenRenderbuffersEXT(1, &OGLRef.rboMultisampleDepthStencilID); + glGenRenderbuffersEXT(1, &OGLRef.rboMSFragColorID); + glGenRenderbuffersEXT(1, &OGLRef.rboMSFragDepthStencilID); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMultisampleColorID); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSFragColorID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMultisampleDepthStencilID); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSFragDepthStencilID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_DEPTH24_STENCIL8_EXT, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); // Set up multisampled rendering FBO - glGenFramebuffersEXT(1, &OGLRef.fboMultisampleRenderID); + glGenFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderID); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboMultisampleRenderID); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMultisampleColorID); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMultisampleDepthStencilID); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMultisampleDepthStencilID); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderID); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSFragColorID); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSFragDepthStencilID); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSFragDepthStencilID); if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { INFO("OpenGL: Failed to create multisampled FBO. Multisample antialiasing will be disabled.\n"); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - glDeleteFramebuffersEXT(1, &OGLRef.fboMultisampleRenderID); - glDeleteRenderbuffersEXT(1, &OGLRef.rboMultisampleColorID); - glDeleteRenderbuffersEXT(1, &OGLRef.rboMultisampleDepthStencilID); + glDeleteFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderID); + glDeleteRenderbuffersEXT(1, &OGLRef.rboMSFragColorID); + glDeleteRenderbuffersEXT(1, &OGLRef.rboMSFragDepthStencilID); return OGLERROR_FBO_CREATE_ERROR; } - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboFinalOutputID); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); INFO("OpenGL: Successfully created multisampled FBO.\n"); return OGLERROR_NOERR; @@ -1369,9 +1307,9 @@ void OpenGLRenderer_1_2::DestroyMultisampledFBO() OGLRenderRef &OGLRef = *this->ref; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - glDeleteFramebuffersEXT(1, &OGLRef.fboMultisampleRenderID); - glDeleteRenderbuffersEXT(1, &OGLRef.rboMultisampleColorID); - glDeleteRenderbuffersEXT(1, &OGLRef.rboMultisampleDepthStencilID); + glDeleteFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderID); + glDeleteRenderbuffersEXT(1, &OGLRef.rboMSFragColorID); + glDeleteRenderbuffersEXT(1, &OGLRef.rboMSFragDepthStencilID); this->isMultisampledFBOSupported = false; } @@ -1432,12 +1370,9 @@ Render3DError OpenGLRenderer_1_2::InitTables() if (needTableInit) { - for (unsigned int i = 0; i < 256; i++) + for (size_t i = 0; i < 256; i++) material_8bit_to_float[i] = (GLfloat)(i * 4) / 255.0f; - for (unsigned int i = 0; i < 32768; i++) - dsDepthToD24S8_LUT[i] = (GLuint)DS_DEPTH15TO24(i) << 8; - needTableInit = false; } @@ -1447,97 +1382,51 @@ Render3DError OpenGLRenderer_1_2::InitTables() Render3DError OpenGLRenderer_1_2::CreateToonTable() { OGLRenderRef &OGLRef = *this->ref; + u16 tempToonTable[32]; + memset(tempToonTable, 0, sizeof(tempToonTable)); // The toon table is a special 1D texture where each pixel corresponds // to a specific color in the toon table. glGenTextures(1, &OGLRef.texToonTableID); - glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_ToonTable); - glBindTexture(GL_TEXTURE_1D, OGLRef.texToonTableID); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, tempToonTable); glBindTexture(GL_TEXTURE_1D, 0); - glActiveTextureARB(GL_TEXTURE0_ARB); - return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::DestroyToonTable() { - glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_ToonTable); - glBindTexture(GL_TEXTURE_1D, 0); - glActiveTextureARB(GL_TEXTURE0_ARB); glDeleteTextures(1, &this->ref->texToonTableID); return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_1_2::UploadToonTable(const GLushort *toonTableBuffer) +Render3DError OpenGLRenderer_1_2::UploadToonTable(const u16 *toonTableBuffer) { glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_ToonTable); glBindTexture(GL_TEXTURE_1D, this->ref->texToonTableID); - glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, toonTableBuffer); + glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 32, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, toonTableBuffer); glActiveTextureARB(GL_TEXTURE0_ARB); return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_1_2::CreateClearImage() -{ - OGLRenderRef &OGLRef = *this->ref; - - glGenTextures(1, &OGLRef.texClearImageColorID); - glGenTextures(1, &OGLRef.texClearImageDepthStencilID); - - glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_ClearImage); - - glBindTexture(GL_TEXTURE_2D, OGLRef.texClearImageColorID); - 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, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); - - glBindTexture(GL_TEXTURE_2D, OGLRef.texClearImageDepthStencilID); - 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); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL); - - glActiveTextureARB(GL_TEXTURE0_ARB); - - return OGLERROR_NOERR; -} - -Render3DError OpenGLRenderer_1_2::DestroyClearImage() -{ - OGLRenderRef &OGLRef = *this->ref; - - glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_ClearImage); - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTextureARB(GL_TEXTURE0_ARB); - glDeleteTextures(1, &OGLRef.texClearImageColorID); - glDeleteTextures(1, &OGLRef.texClearImageDepthStencilID); - - return OGLERROR_NOERR; -} - -Render3DError OpenGLRenderer_1_2::UploadClearImage(const GLushort *clearImageColorBuffer, const GLint *clearImageDepthBuffer) +Render3DError OpenGLRenderer_1_2::UploadClearImage(const u16 *clearImageColor16Buffer, const u32 *clearImageDepthStencilBuffer) { OGLRenderRef &OGLRef = *this->ref; glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_ClearImage); glBindTexture(GL_TEXTURE_2D, OGLRef.texClearImageColorID); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, clearImageColorBuffer); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, clearImageColor16Buffer); glBindTexture(GL_TEXTURE_2D, OGLRef.texClearImageDepthStencilID); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, clearImageDepthBuffer); - glBindTexture(GL_TEXTURE_2D, 0); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, clearImageDepthStencilBuffer); + glBindTexture(GL_TEXTURE_2D, 0); glActiveTextureARB(GL_TEXTURE0_ARB); return OGLERROR_NOERR; @@ -1567,11 +1456,11 @@ void OpenGLRenderer_1_2::GetExtensionSet(std::set *oglExtensionSet) Render3DError OpenGLRenderer_1_2::ExpandFreeTextures() { - static const int kInitTextures = 128; + static const GLsizei kInitTextures = 128; GLuint oglTempTextureID[kInitTextures]; glGenTextures(kInitTextures, oglTempTextureID); - for(int i=0;iref->freeTextureIDs.push(oglTempTextureID[i]); } @@ -1579,20 +1468,20 @@ Render3DError OpenGLRenderer_1_2::ExpandFreeTextures() return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_1_2::SetupVertices(const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, GLushort *outIndexBuffer, unsigned int *outIndexCount) +Render3DError OpenGLRenderer_1_2::SetupVertices(const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, GLushort *outIndexBuffer, size_t *outIndexCount) { OGLRenderRef &OGLRef = *this->ref; - const unsigned int polyCount = polyList->count; - unsigned int vertIndexCount = 0; + const size_t polyCount = polyList->count; + size_t vertIndexCount = 0; - for(unsigned int i = 0; i < polyCount; i++) + for(size_t i = 0; i < polyCount; i++) { const POLY *poly = &polyList->list[indexList->list[i]]; - const unsigned int polyType = poly->type; + const size_t polyType = poly->type; if (this->isShaderSupported) { - for(unsigned int j = 0; j < polyType; j++) + for(size_t j = 0; j < polyType; j++) { const GLushort vertIndex = poly->vertIndexes[j]; @@ -1618,10 +1507,10 @@ Render3DError OpenGLRenderer_1_2::SetupVertices(const VERTLIST *vertList, const { const GLfloat thePolyAlpha = (!poly->isWireframe() && poly->isTranslucent()) ? divide5bitBy31_LUT[poly->getAttributeAlpha()] : 1.0f; - for(unsigned int j = 0; j < polyType; j++) + for(size_t j = 0; j < polyType; j++) { const GLushort vertIndex = poly->vertIndexes[j]; - const GLushort colorIndex = vertIndex * 4; + const size_t colorIndex = vertIndex * 4; // Consolidate the vertex color and the poly alpha to our internal color buffer // so that OpenGL can use it. @@ -1656,7 +1545,7 @@ Render3DError OpenGLRenderer_1_2::SetupVertices(const VERTLIST *vertList, const return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_1_2::EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const unsigned int vertIndexCount) +Render3DError OpenGLRenderer_1_2::EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount) { OGLRenderRef &OGLRef = *this->ref; @@ -1760,7 +1649,7 @@ Render3DError OpenGLRenderer_1_2::SelectRenderingFramebuffer() if (this->isMultisampledFBOSupported) { - OGLRef.selectedRenderingFBO = CommonSettings.GFX3D_Renderer_Multisample ? OGLRef.fboMultisampleRenderID : OGLRef.fboFinalOutputID; + OGLRef.selectedRenderingFBO = (CommonSettings.GFX3D_Renderer_Multisample) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); } @@ -1771,22 +1660,22 @@ Render3DError OpenGLRenderer_1_2::DownsampleFBO() { OGLRenderRef &OGLRef = *this->ref; - if (!this->isMultisampledFBOSupported || OGLRef.selectedRenderingFBO != OGLRef.fboMultisampleRenderID) + if (!this->isMultisampledFBOSupported || OGLRef.selectedRenderingFBO != OGLRef.fboMSIntermediateRenderID) { return OGLERROR_NOERR; } glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboFinalOutputID); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderID); glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboFinalOutputID); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::ReadBackPixels() { - const unsigned int i = this->doubleBufferIndex; + const size_t i = this->doubleBufferIndex; if (this->isPBOSupported) { @@ -1822,10 +1711,10 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State *renderState) if (this->isShaderSupported) { - glUniform1i(OGLRef.uniformEnableAlphaTest, renderState->enableAlphaTest ? GL_TRUE : GL_FALSE); - glUniform1f(OGLRef.uniformAlphaTestRef, divide5bitBy31_LUT[renderState->alphaTestRef]); - glUniform1i(OGLRef.uniformToonShadingMode, renderState->shading); - glUniform1i(OGLRef.uniformWBuffer, renderState->wbuffer ? GL_TRUE : GL_FALSE); + glUniform1i(OGLRef.uniformStateToonShadingMode, renderState->shading); + glUniform1i(OGLRef.uniformStateEnableAlphaTest, (renderState->enableAlphaTest) ? GL_TRUE : GL_FALSE); + glUniform1i(OGLRef.uniformStateUseWDepth, (renderState->wbuffer) ? GL_TRUE : GL_FALSE); + glUniform1f(OGLRef.uniformStateAlphaTestRef, divide5bitBy31_LUT[renderState->alphaTestRef]); } else { @@ -1856,7 +1745,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State *renderState) Render3DError OpenGLRenderer_1_2::PreRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList) { OGLRenderRef &OGLRef = *this->ref; - unsigned int vertIndexCount = 0; + size_t vertIndexCount = 0; if (!this->isShaderSupported) { @@ -1877,7 +1766,7 @@ Render3DError OpenGLRenderer_1_2::DoRender(const GFX3D_State *renderState, const u32 lastTexPalette = 0; u32 lastPolyAttr = 0; u32 lastViewport = 0xFFFFFFFF; - const unsigned int polyCount = polyList->count; + const size_t polyCount = polyList->count; GLushort *indexBufferPtr = this->isVBOSupported ? 0 : OGLRef.vertIndexBuffer; // Map GFX3D_QUADS and GFX3D_QUAD_STRIP to GL_TRIANGLES since we will convert them. @@ -1889,21 +1778,37 @@ Render3DError OpenGLRenderer_1_2::DoRender(const GFX3D_State *renderState, const static const GLenum oglPrimitiveType[] = {GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, GL_LINE_LOOP, GL_LINE_LOOP, GL_LINE_STRIP, GL_LINE_STRIP}; - static const unsigned int indexIncrementLUT[] = {3, 6, 3, 6, 3, 4, 3, 4}; + static const GLsizei indexIncrementLUT[] = {3, 6, 3, 6, 3, 4, 3, 4}; - for(unsigned int i = 0; i < polyCount; i++) + // Set up initial states, but only if there are polygons to draw + if (polyCount > 0) + { + const POLY *poly = &polyList->list[indexList->list[0]]; + + lastPolyAttr = poly->polyAttr; + this->SetupPolygon(poly); + + lastTexParams = poly->texParam; + lastTexPalette = poly->texPalette; + this->SetupTexture(poly, renderState->enableTexturing); + + lastViewport = poly->viewport; + this->SetupViewport(poly->viewport); + } + + for(size_t i = 0; i < polyCount; i++) { const POLY *poly = &polyList->list[indexList->list[i]]; // Set up the polygon if it changed - if(lastPolyAttr != poly->polyAttr || i == 0) + if(lastPolyAttr != poly->polyAttr) { lastPolyAttr = poly->polyAttr; this->SetupPolygon(poly); } // Set up the texture if it changed - if(lastTexParams != poly->texParam || lastTexPalette != poly->texPalette || i == 0) + if(lastTexParams != poly->texParam || lastTexPalette != poly->texPalette) { lastTexParams = poly->texParam; lastTexPalette = poly->texPalette; @@ -1911,10 +1816,10 @@ Render3DError OpenGLRenderer_1_2::DoRender(const GFX3D_State *renderState, const } // Set up the viewport if it changed - if(lastViewport != poly->viewport || i == 0) + if(lastViewport != poly->viewport) { lastViewport = poly->viewport; - this->SetupViewport(poly); + this->SetupViewport(poly->viewport); } // In wireframe mode, redefine all primitives as GL_LINE_LOOP rather than @@ -1925,7 +1830,7 @@ Render3DError OpenGLRenderer_1_2::DoRender(const GFX3D_State *renderState, const const GLenum polyPrimitive = !poly->isWireframe() ? oglPrimitiveType[poly->vtxFormat] : GL_LINE_LOOP; // Render the polygon - const unsigned int vertIndexCount = indexIncrementLUT[poly->vtxFormat]; + const GLsizei vertIndexCount = indexIncrementLUT[poly->vtxFormat]; glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); indexBufferPtr += vertIndexCount; } @@ -1950,79 +1855,28 @@ Render3DError OpenGLRenderer_1_2::EndRender(const u64 frameCount) return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_1_2::UpdateClearImage(const u16 *__restrict colorBuffer, const u16 *__restrict depthBuffer, const u8 clearStencil, const u8 xScroll, const u8 yScroll) +Render3DError OpenGLRenderer_1_2::UpdateClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthStencilBuffer) { - static const size_t pixelsPerLine = GFX3D_FRAMEBUFFER_WIDTH; - static const size_t lineCount = GFX3D_FRAMEBUFFER_HEIGHT; - static const size_t totalPixelCount = pixelsPerLine * lineCount; - static const size_t bufferSize = totalPixelCount * sizeof(u16); - - static CACHE_ALIGN GLushort clearImageColorBuffer[totalPixelCount] = {0}; - static CACHE_ALIGN GLint clearImageDepthBuffer[totalPixelCount] = {0}; - static CACHE_ALIGN u16 lastColorBuffer[totalPixelCount] = {0}; - static CACHE_ALIGN u16 lastDepthBuffer[totalPixelCount] = {0}; - static u8 lastXScroll = 0; - static u8 lastYScroll = 0; - if (!this->isFBOSupported) { return OGLERROR_FEATURE_UNSUPPORTED; } - if (lastXScroll != xScroll || - lastYScroll != yScroll || - memcmp(colorBuffer, lastColorBuffer, bufferSize) || - memcmp(depthBuffer, lastDepthBuffer, bufferSize) ) - { - lastXScroll = xScroll; - lastYScroll = yScroll; - memcpy(lastColorBuffer, colorBuffer, bufferSize); - memcpy(lastDepthBuffer, depthBuffer, bufferSize); - - unsigned int dd = totalPixelCount - pixelsPerLine; - - for(unsigned int iy = 0; iy < lineCount; iy++) - { - const unsigned int y = ((iy + yScroll) & 0xFF) << 8; - - for(unsigned int ix = 0; ix < pixelsPerLine; ix++) - { - const unsigned int x = (ix + xScroll) & 0xFF; - const unsigned int adr = y + x; - - clearImageColorBuffer[dd] = colorBuffer[adr]; - clearImageDepthBuffer[dd] = dsDepthToD24S8_LUT[depthBuffer[adr] & 0x7FFF] | clearStencil; - - dd++; - } - - dd -= pixelsPerLine * 2; - } - - this->UploadClearImage(clearImageColorBuffer, clearImageDepthBuffer); - } - - this->clearImageStencilValue = clearStencil; + this->UploadClearImage(colorBuffer, depthStencilBuffer); + this->clearImageStencilValue = depthStencilBuffer[0] & 0x3F; return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::UpdateToonTable(const u16 *toonTableBuffer) { - // Update the toon table if it changed. - if (memcmp(this->currentToonTable16, toonTableBuffer, sizeof(this->currentToonTable16))) - { - memcpy(this->currentToonTable16, toonTableBuffer, sizeof(this->currentToonTable16)); - this->toonTableNeedsUpdate = true; - } + this->UploadToonTable(toonTableBuffer); return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_2::ClearUsingImage() const { - static u8 lastClearStencil = 0; - if (!this->isFBOSupported) { return OGLERROR_FEATURE_UNSUPPORTED; @@ -2041,12 +1895,7 @@ Render3DError OpenGLRenderer_1_2::ClearUsingImage() const // We do this because glBlitFramebufferEXT() for GL_STENCIL_BUFFER_BIT has been tested // to be unsupported on ATI/AMD GPUs running in compatibility mode. So we do the separate // glClear() for GL_STENCIL_BUFFER_BIT to keep these GPUs working. - if (lastClearStencil == this->clearImageStencilValue) - { - lastClearStencil = this->clearImageStencilValue; - glClearStencil(lastClearStencil); - } - + glClearStencil(this->clearImageStencilValue); glClear(GL_STENCIL_BUFFER_BIT); return OGLERROR_NOERR; @@ -2054,34 +1903,9 @@ Render3DError OpenGLRenderer_1_2::ClearUsingImage() const Render3DError OpenGLRenderer_1_2::ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearStencil) const { - static u8 last_r = 0; - static u8 last_g = 0; - static u8 last_b = 0; - static u8 last_a = 0; - static u32 lastClearDepth = 0; - static u8 lastClearStencil = 0; - - if (r != last_r || g != last_g || b != last_b || a != last_a) - { - last_r = r; - last_g = g; - last_b = b; - last_a = a; - glClearColor(divide5bitBy31_LUT[r], divide5bitBy31_LUT[g], divide5bitBy31_LUT[b], divide5bitBy31_LUT[a]); - } - - if (clearDepth != lastClearDepth) - { - lastClearDepth = clearDepth; - glClearDepth((GLfloat)clearDepth / (GLfloat)0x00FFFFFF); - } - - if (clearStencil != lastClearStencil) - { - lastClearStencil = clearStencil; - glClearStencil(clearStencil); - } - + glClearColor(divide5bitBy31_LUT[r], divide5bitBy31_LUT[g], divide5bitBy31_LUT[b], divide5bitBy31_LUT[a]); + glClearDepth((GLclampd)clearDepth / (GLclampd)0x00FFFFFF); + glClearStencil(clearStencil); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); return OGLERROR_NOERR; @@ -2089,23 +1913,21 @@ Render3DError OpenGLRenderer_1_2::ClearUsingValues(const u8 r, const u8 g, const Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY *thePoly) { - static unsigned int lastTexBlendMode = 0; - static int lastStencilState = -1; - OGLRenderRef &OGLRef = *this->ref; const PolygonAttributes attr = thePoly->getAttributes(); - // Set up polygon ID + // Set up polygon attributes if (this->isShaderSupported) { + glUniform1i(OGLRef.uniformPolyMode, attr.polygonMode); + glUniform1f(OGLRef.uniformPolyAlpha, (!attr.isWireframe && attr.isTranslucent) ? divide5bitBy31_LUT[attr.alpha] : 1.0f); glUniform1i(OGLRef.uniformPolyID, attr.polygonID); } - - // Set up alpha value - if (this->isShaderSupported) + else { - const GLfloat thePolyAlpha = (!attr.isWireframe && attr.isTranslucent) ? divide5bitBy31_LUT[attr.alpha] : 1.0f; - glUniform1f(OGLRef.uniformPolyAlpha, thePolyAlpha); + // Set the texture blending mode + static const GLint oglTexBlendMode[4] = {GL_MODULATE, GL_DECAL, GL_MODULATE, GL_MODULATE}; + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, oglTexBlendMode[attr.polygonMode]); } // Set up depth test mode @@ -2118,11 +1940,11 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY *thePoly) if (cullingMode == 0) { - xglDisable(GL_CULL_FACE); + glDisable(GL_CULL_FACE); } else { - xglEnable(GL_CULL_FACE); + glEnable(GL_CULL_FACE); glCullFace(cullingMode); } @@ -2133,49 +1955,39 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY *thePoly) // can change this too. if(attr.polygonMode == 3) { - xglEnable(GL_STENCIL_TEST); + glEnable(GL_STENCIL_TEST); if(attr.polygonID == 0) { + //when the polyID is zero, we are writing the shadow mask. + //set stencilbuf = 1 where the shadow volume is obstructed by geometry. + //do not write color or depth information. + glStencilFunc(GL_ALWAYS, 65, 255); + glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); enableDepthWrite = GL_FALSE; - if(lastStencilState != 0) - { - lastStencilState = 0; - //when the polyID is zero, we are writing the shadow mask. - //set stencilbuf = 1 where the shadow volume is obstructed by geometry. - //do not write color or depth information. - glStencilFunc(GL_ALWAYS, 65, 255); - glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - } } else { + //when the polyid is nonzero, we are drawing the shadow poly. + //only draw the shadow poly where the stencilbuf==1. + //I am not sure whether to update the depth buffer here--so I chose not to. + glStencilFunc(GL_EQUAL, 65, 255); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); enableDepthWrite = GL_TRUE; - if(lastStencilState != 1) - { - lastStencilState = 1; - //when the polyid is nonzero, we are drawing the shadow poly. - //only draw the shadow poly where the stencilbuf==1. - //I am not sure whether to update the depth buffer here--so I chose not to. - glStencilFunc(GL_EQUAL, 65, 255); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - } } } else { - xglEnable(GL_STENCIL_TEST); + glEnable(GL_STENCIL_TEST); if(attr.isTranslucent) { - lastStencilState = 3; glStencilFunc(GL_NOTEQUAL, attr.polygonID, 255); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } - else if(lastStencilState != 2) + else { - lastStencilState = 2; glStencilFunc(GL_ALWAYS, 64, 255); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); @@ -2189,29 +2001,6 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY *thePoly) glDepthMask(enableDepthWrite); - // Set up texture blending mode - if(attr.polygonMode != lastTexBlendMode) - { - lastTexBlendMode = attr.polygonMode; - - if(this->isShaderSupported) - { - glUniform1i(OGLRef.uniformPolygonMode, attr.polygonMode); - - // Update the toon table if necessary - if (this->toonTableNeedsUpdate && attr.polygonMode == 2) - { - this->UploadToonTable(this->currentToonTable16); - this->toonTableNeedsUpdate = false; - } - } - else - { - static const GLint oglTexBlendMode[4] = {GL_MODULATE, GL_DECAL, GL_MODULATE, GL_MODULATE}; - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, oglTexBlendMode[attr.polygonMode]); - } - } - return OGLERROR_NOERR; } @@ -2225,7 +2014,7 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY *thePoly, bool enableT { if (this->isShaderSupported) { - glUniform1i(OGLRef.uniformHasTexture, GL_FALSE); + glUniform1i(OGLRef.uniformPolyEnableTexture, GL_FALSE); } else { @@ -2238,7 +2027,7 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY *thePoly, bool enableT // Enable textures if they weren't already enabled if (this->isShaderSupported) { - glUniform1i(OGLRef.uniformHasTexture, GL_TRUE); + glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE); } else { @@ -2295,10 +2084,10 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY *thePoly, bool enableT return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_1_2::SetupViewport(const POLY *thePoly) +Render3DError OpenGLRenderer_1_2::SetupViewport(const u32 viewportValue) { VIEWPORT viewport; - viewport.decode(thePoly->viewport); + viewport.decode(viewportValue); glViewport(viewport.x, viewport.y, viewport.width, viewport.height); return OGLERROR_NOERR; @@ -2313,25 +2102,25 @@ Render3DError OpenGLRenderer_1_2::Reset() glFinish(); - for (unsigned int i = 0; i < 2; i++) + for (size_t i = 0; i < 2; i++) { memset(this->GPU_screen3D[i], 0, sizeof(this->GPU_screen3D[i])); } - memset(currentToonTable16, 0, sizeof(currentToonTable16)); - this->toonTableNeedsUpdate = true; - if(this->isShaderSupported) { - glUniform1f(OGLRef.uniformPolyAlpha, 1.0f); glUniform2f(OGLRef.uniformTexScale, 1.0f, 1.0f); + + glUniform1i(OGLRef.uniformStateToonShadingMode, 0); + glUniform1i(OGLRef.uniformStateEnableAlphaTest, GL_TRUE); + glUniform1i(OGLRef.uniformStateUseWDepth, GL_FALSE); + glUniform1f(OGLRef.uniformStateAlphaTestRef, 0.0f); + + glUniform1i(OGLRef.uniformPolyMode, 1); + glUniform1f(OGLRef.uniformPolyAlpha, 1.0f); glUniform1i(OGLRef.uniformPolyID, 0); - glUniform1i(OGLRef.uniformHasTexture, GL_FALSE); - glUniform1i(OGLRef.uniformPolygonMode, 0); - glUniform1i(OGLRef.uniformToonShadingMode, 0); - glUniform1i(OGLRef.uniformWBuffer, GL_FALSE); - glUniform1i(OGLRef.uniformEnableAlphaTest, GL_TRUE); - glUniform1f(OGLRef.uniformAlphaTestRef, 0.0f); + + glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE); } else { @@ -2340,6 +2129,7 @@ Render3DError OpenGLRenderer_1_2::Reset() glEnable(GL_TEXTURE_2D); glAlphaFunc(GL_GREATER, 0); glEnable(GL_ALPHA_TEST); + glEnable(GL_BLEND); memset(OGLRef.color4fBuffer, 0, VERTLIST_SIZE * 4 * sizeof(GLfloat)); } @@ -2354,7 +2144,7 @@ Render3DError OpenGLRenderer_1_2::Reset() Render3DError OpenGLRenderer_1_2::RenderFinish() { - const unsigned int i = this->doubleBufferIndex; + const size_t i = this->doubleBufferIndex; if (!this->gpuScreen3DHasNewData[i]) { @@ -2390,100 +2180,28 @@ Render3DError OpenGLRenderer_1_2::RenderFinish() return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_1_3::CreateToonTable() -{ - OGLRenderRef &OGLRef = *this->ref; - - // The toon table is a special 1D texture where each pixel corresponds - // to a specific color in the toon table. - glGenTextures(1, &OGLRef.texToonTableID); - glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_ToonTable); - - glBindTexture(GL_TEXTURE_1D, OGLRef.texToonTableID); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glBindTexture(GL_TEXTURE_1D, 0); - - glActiveTexture(GL_TEXTURE0); - - return OGLERROR_NOERR; -} - -Render3DError OpenGLRenderer_1_3::DestroyToonTable() -{ - glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_ToonTable); - glBindTexture(GL_TEXTURE_1D, 0); - glActiveTexture(GL_TEXTURE0); - glDeleteTextures(1, &this->ref->texToonTableID); - - return OGLERROR_NOERR; -} - -Render3DError OpenGLRenderer_1_3::UploadToonTable(const GLushort *toonTableBuffer) +Render3DError OpenGLRenderer_1_3::UploadToonTable(const u16 *toonTableBuffer) { glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_ToonTable); glBindTexture(GL_TEXTURE_1D, this->ref->texToonTableID); - glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, toonTableBuffer); + glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 32, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, toonTableBuffer); glActiveTexture(GL_TEXTURE0); return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_1_3::CreateClearImage() -{ - OGLRenderRef &OGLRef = *this->ref; - - glGenTextures(1, &OGLRef.texClearImageColorID); - glGenTextures(1, &OGLRef.texClearImageDepthStencilID); - - glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_ClearImage); - - glBindTexture(GL_TEXTURE_2D, OGLRef.texClearImageColorID); - 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, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); - - glBindTexture(GL_TEXTURE_2D, OGLRef.texClearImageDepthStencilID); - 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); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL); - - glActiveTexture(GL_TEXTURE0); - - return OGLERROR_NOERR; -} - -Render3DError OpenGLRenderer_1_3::DestroyClearImage() -{ - OGLRenderRef &OGLRef = *this->ref; - - glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_ClearImage); - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE0); - glDeleteTextures(1, &OGLRef.texClearImageColorID); - glDeleteTextures(1, &OGLRef.texClearImageDepthStencilID); - - return OGLERROR_NOERR; -} - -Render3DError OpenGLRenderer_1_3::UploadClearImage(const GLushort *clearImageColorBuffer, const GLint *clearImageDepthBuffer) +Render3DError OpenGLRenderer_1_3::UploadClearImage(const u16 *clearImageColor16Buffer, const u32 *clearImageDepthStencilBuffer) { OGLRenderRef &OGLRef = *this->ref; glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_ClearImage); glBindTexture(GL_TEXTURE_2D, OGLRef.texClearImageColorID); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, clearImageColorBuffer); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, clearImageColor16Buffer); glBindTexture(GL_TEXTURE_2D, OGLRef.texClearImageDepthStencilID); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, clearImageDepthBuffer); - glBindTexture(GL_TEXTURE_2D, 0); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, clearImageDepthStencilBuffer); + glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); return OGLERROR_NOERR; @@ -2572,7 +2290,7 @@ Render3DError OpenGLRenderer_1_5::CreatePBOs() OGLRenderRef &OGLRef = *this->ref; glGenBuffers(2, OGLRef.pboRenderDataID); - for (unsigned int i = 0; i < 2; i++) + for (size_t i = 0; i < 2; i++) { glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, OGLRef.pboRenderDataID[i]); glBufferData(GL_PIXEL_PACK_BUFFER_ARB, GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT * sizeof(u32), NULL, GL_STREAM_READ); @@ -2619,7 +2337,7 @@ Render3DError OpenGLRenderer_1_5::CreateVAOs() return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_1_5::EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const unsigned int vertIndexCount) +Render3DError OpenGLRenderer_1_5::EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount) { OGLRenderRef &OGLRef = *this->ref; @@ -2699,7 +2417,7 @@ Render3DError OpenGLRenderer_1_5::DisableVertexAttributes() Render3DError OpenGLRenderer_1_5::ReadBackPixels() { - const unsigned int i = this->doubleBufferIndex; + const size_t i = this->doubleBufferIndex; if (this->isPBOSupported) { @@ -2717,7 +2435,7 @@ Render3DError OpenGLRenderer_1_5::ReadBackPixels() Render3DError OpenGLRenderer_1_5::RenderFinish() { - const unsigned int i = this->doubleBufferIndex; + const size_t i = this->doubleBufferIndex; if (!this->gpuScreen3DHasNewData[i]) { @@ -2789,70 +2507,47 @@ Render3DError OpenGLRenderer_2_0::InitExtensions() this->isVBOSupported = true; this->CreateVBOs(); -#if !defined(GL_ARB_pixel_buffer_object) && !defined(GL_EXT_pixel_buffer_object) - this->isPBOSupported = false; -#else this->isPBOSupported = this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_buffer_object") && (this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_pixel_buffer_object") || this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_pixel_buffer_object")); -#endif if (this->isPBOSupported) { this->CreatePBOs(); } -#if !defined(GL_ARB_vertex_array_object) && !defined(GL_APPLE_vertex_array_object) - this->isVAOSupported = false; -#else this->isVAOSupported = this->isShaderSupported && this->isVBOSupported && (this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_array_object") || this->IsExtensionPresent(&oglExtensionSet, "GL_APPLE_vertex_array_object")); -#endif if (this->isVAOSupported) { this->CreateVAOs(); } // Don't use ARB versions since we're using the EXT versions for backwards compatibility. -#if !defined(GL_EXT_framebuffer_object) || \ - !defined(GL_EXT_framebuffer_blit) || \ - !defined(GL_EXT_packed_depth_stencil) - - this->isFBOSupported = false; -#else this->isFBOSupported = this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_object") && this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_blit") && this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_packed_depth_stencil"); -#endif if (this->isFBOSupported) { error = this->CreateFBOs(); if (error != OGLERROR_NOERR) { - OGLRef.fboFinalOutputID = 0; + OGLRef.fboRenderID = 0; this->isFBOSupported = false; } } else { - OGLRef.fboFinalOutputID = 0; + OGLRef.fboRenderID = 0; INFO("OpenGL: FBOs are unsupported. Some emulation features will be disabled.\n"); } // Don't use ARB versions since we're using the EXT versions for backwards compatibility. -#if !defined(GL_EXT_framebuffer_object) || \ - !defined(GL_EXT_framebuffer_multisample) || \ - !defined(GL_EXT_framebuffer_blit) || \ - !defined(GL_EXT_packed_depth_stencil) - - this->isMultisampledFBOSupported = false; -#else this->isMultisampledFBOSupported = this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_object") && this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_blit") && this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_packed_depth_stencil") && this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_multisample"); -#endif if (this->isMultisampledFBOSupported) { error = this->CreateMultisampledFBO(); @@ -2897,17 +2592,17 @@ Render3DError OpenGLRenderer_2_0::InitFinalRenderStates(const std::setcount; - unsigned int vertIndexCount = 0; + const size_t polyCount = polyList->count; + size_t vertIndexCount = 0; - for(unsigned int i = 0; i < polyCount; i++) + for(size_t i = 0; i < polyCount; i++) { const POLY *poly = &polyList->list[indexList->list[i]]; - const unsigned int polyType = poly->type; + const size_t polyType = poly->type; - for(unsigned int j = 0; j < polyType; j++) + for(size_t j = 0; j < polyType; j++) { const GLushort vertIndex = poly->vertIndexes[j]; @@ -2935,7 +2630,7 @@ Render3DError OpenGLRenderer_2_0::SetupVertices(const VERTLIST *vertList, const return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_2_0::EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const unsigned int vertIndexCount) +Render3DError OpenGLRenderer_2_0::EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount) { OGLRenderRef &OGLRef = *this->ref; @@ -2991,10 +2686,10 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State *renderState) this->SelectRenderingFramebuffer(); - glUniform1i(OGLRef.uniformEnableAlphaTest, renderState->enableAlphaTest ? GL_TRUE : GL_FALSE); - glUniform1f(OGLRef.uniformAlphaTestRef, divide5bitBy31_LUT[renderState->alphaTestRef]); - glUniform1i(OGLRef.uniformToonShadingMode, renderState->shading); - glUniform1i(OGLRef.uniformWBuffer, renderState->wbuffer ? GL_TRUE : GL_FALSE); + glUniform1i(OGLRef.uniformStateToonShadingMode, renderState->shading); + glUniform1i(OGLRef.uniformStateEnableAlphaTest, (renderState->enableAlphaTest) ? GL_TRUE : GL_FALSE); + glUniform1i(OGLRef.uniformStateUseWDepth, (renderState->wbuffer) ? GL_TRUE : GL_FALSE); + glUniform1f(OGLRef.uniformStateAlphaTestRef, divide5bitBy31_LUT[renderState->alphaTestRef]); if(renderState->enableAlphaBlending) { @@ -3013,7 +2708,7 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State *renderState) Render3DError OpenGLRenderer_2_0::PreRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList) { OGLRenderRef &OGLRef = *this->ref; - unsigned int vertIndexCount = 0; + size_t vertIndexCount = 0; this->SetupVertices(vertList, polyList, indexList, OGLRef.vertIndexBuffer, &vertIndexCount); this->EnableVertexAttributes(vertList, OGLRef.vertIndexBuffer, vertIndexCount); @@ -3023,19 +2718,14 @@ Render3DError OpenGLRenderer_2_0::PreRender(const GFX3D_State *renderState, cons Render3DError OpenGLRenderer_2_0::SetupPolygon(const POLY *thePoly) { - static unsigned int lastTexBlendMode = 0; - static int lastStencilState = -1; - OGLRenderRef &OGLRef = *this->ref; const PolygonAttributes attr = thePoly->getAttributes(); - // Set up polygon ID + // Set up polygon attributes + glUniform1i(OGLRef.uniformPolyMode, attr.polygonMode); + glUniform1f(OGLRef.uniformPolyAlpha, (!attr.isWireframe && attr.isTranslucent) ? divide5bitBy31_LUT[attr.alpha] : 1.0f); glUniform1i(OGLRef.uniformPolyID, attr.polygonID); - // Set up alpha value - const GLfloat thePolyAlpha = (!attr.isWireframe && attr.isTranslucent) ? divide5bitBy31_LUT[attr.alpha] : 1.0f; - glUniform1f(OGLRef.uniformPolyAlpha, thePolyAlpha); - // Set up depth test mode static const GLenum oglDepthFunc[2] = {GL_LESS, GL_EQUAL}; glDepthFunc(oglDepthFunc[attr.enableDepthTest]); @@ -3046,11 +2736,11 @@ Render3DError OpenGLRenderer_2_0::SetupPolygon(const POLY *thePoly) if (cullingMode == 0) { - xglDisable(GL_CULL_FACE); + glDisable(GL_CULL_FACE); } else { - xglEnable(GL_CULL_FACE); + glEnable(GL_CULL_FACE); glCullFace(cullingMode); } @@ -3061,49 +2751,39 @@ Render3DError OpenGLRenderer_2_0::SetupPolygon(const POLY *thePoly) // can change this too. if(attr.polygonMode == 3) { - xglEnable(GL_STENCIL_TEST); + glEnable(GL_STENCIL_TEST); if(attr.polygonID == 0) { + //when the polyID is zero, we are writing the shadow mask. + //set stencilbuf = 1 where the shadow volume is obstructed by geometry. + //do not write color or depth information. + glStencilFunc(GL_ALWAYS, 65, 255); + glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); enableDepthWrite = GL_FALSE; - if(lastStencilState != 0) - { - lastStencilState = 0; - //when the polyID is zero, we are writing the shadow mask. - //set stencilbuf = 1 where the shadow volume is obstructed by geometry. - //do not write color or depth information. - glStencilFunc(GL_ALWAYS, 65, 255); - glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - } } else { + //when the polyid is nonzero, we are drawing the shadow poly. + //only draw the shadow poly where the stencilbuf==1. + //I am not sure whether to update the depth buffer here--so I chose not to. + glStencilFunc(GL_EQUAL, 65, 255); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); enableDepthWrite = GL_TRUE; - if(lastStencilState != 1) - { - lastStencilState = 1; - //when the polyid is nonzero, we are drawing the shadow poly. - //only draw the shadow poly where the stencilbuf==1. - //I am not sure whether to update the depth buffer here--so I chose not to. - glStencilFunc(GL_EQUAL, 65, 255); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - } } } else { - xglEnable(GL_STENCIL_TEST); + glEnable(GL_STENCIL_TEST); if(attr.isTranslucent) { - lastStencilState = 3; glStencilFunc(GL_NOTEQUAL, attr.polygonID, 255); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } - else if(lastStencilState != 2) + else { - lastStencilState = 2; glStencilFunc(GL_ALWAYS, 64, 255); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); @@ -3117,20 +2797,6 @@ Render3DError OpenGLRenderer_2_0::SetupPolygon(const POLY *thePoly) glDepthMask(enableDepthWrite); - // Set up texture blending mode - if(attr.polygonMode != lastTexBlendMode) - { - lastTexBlendMode = attr.polygonMode; - glUniform1i(OGLRef.uniformPolygonMode, attr.polygonMode); - - // Update the toon table if necessary - if (this->toonTableNeedsUpdate && attr.polygonMode == 2) - { - this->UploadToonTable(this->currentToonTable16); - this->toonTableNeedsUpdate = false; - } - } - return OGLERROR_NOERR; } @@ -3142,11 +2808,11 @@ Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY *thePoly, bool enableT // Check if we need to use textures if (thePoly->texParam == 0 || params.texFormat == TEXMODE_NONE || !enableTexturing) { - glUniform1i(OGLRef.uniformHasTexture, GL_FALSE); + glUniform1i(OGLRef.uniformPolyEnableTexture, GL_FALSE); return OGLERROR_NOERR; } - glUniform1i(OGLRef.uniformHasTexture, GL_TRUE); + glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE); // texCacheUnit.TexCache_SetTexture(format, texpal); TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly->texParam, thePoly->texPalette); @@ -3191,7 +2857,7 @@ Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY *thePoly, bool enableT Render3DError OpenGLRenderer_2_1::ReadBackPixels() { - const unsigned int i = this->doubleBufferIndex; + const size_t i = this->doubleBufferIndex; this->DownsampleFBO(); @@ -3206,7 +2872,7 @@ Render3DError OpenGLRenderer_2_1::ReadBackPixels() Render3DError OpenGLRenderer_2_1::RenderFinish() { - const unsigned int i = this->doubleBufferIndex; + const size_t i = this->doubleBufferIndex; if (!this->gpuScreen3DHasNewData[i]) { diff --git a/desmume/src/OGLRender.h b/desmume/src/OGLRender.h index 6f5f50d02..5a6e060c4 100644 --- a/desmume/src/OGLRender.h +++ b/desmume/src/OGLRender.h @@ -310,16 +310,15 @@ struct OGLRenderRef // FBO GLuint texClearImageColorID; GLuint texClearImageDepthStencilID; + + GLuint rboFragColorID; + GLuint rboFragDepthStencilID; + GLuint rboMSFragColorID; + GLuint rboMSFragDepthStencilID; + GLuint fboClearImageID; - - GLuint rboFinalOutputColorID; - GLuint rboFinalOutputDepthStencilID; - GLuint fboFinalOutputID; - - // Multisampled FBO - GLuint rboMultisampleColorID; - GLuint rboMultisampleDepthStencilID; - GLuint fboMultisampleRenderID; + GLuint fboMSIntermediateRenderID; + GLuint fboRenderID; GLuint selectedRenderingFBO; // Shader states @@ -327,15 +326,18 @@ struct OGLRenderRef GLuint fragmentShaderID; GLuint shaderProgram; - GLint uniformPolyID; - GLint uniformPolyAlpha; GLint uniformTexScale; - GLint uniformHasTexture; - GLint uniformPolygonMode; - GLint uniformToonShadingMode; - GLint uniformWBuffer; - GLint uniformEnableAlphaTest; - GLint uniformAlphaTestRef; + + GLint uniformStateToonShadingMode; + GLint uniformStateEnableAlphaTest; + GLint uniformStateUseWDepth; + GLint uniformStateAlphaTestRef; + + GLint uniformPolyMode; + GLint uniformPolyAlpha; + GLint uniformPolyID; + + GLint uniformPolyEnableTexture; GLuint texToonTableID; @@ -347,7 +349,7 @@ struct OGLRenderRef // Client-side Buffers GLfloat *color4fBuffer; - DS_ALIGN(16) GLushort vertIndexBuffer[OGLRENDER_VERT_INDEX_BUFFER_COUNT]; + CACHE_ALIGN GLushort vertIndexBuffer[OGLRENDER_VERT_INDEX_BUFFER_COUNT]; }; struct GFX3D_State; @@ -410,12 +412,9 @@ protected: // Textures TexCacheItem *currTexture; - u16 currentToonTable16[32]; - bool toonTableNeedsUpdate; - - DS_ALIGN(16) u32 GPU_screen3D[2][GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT * sizeof(u32)]; + CACHE_ALIGN u32 GPU_screen3D[2][GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT * sizeof(u32)]; bool gpuScreen3DHasNewData[2]; - unsigned int doubleBufferIndex; + size_t doubleBufferIndex; u8 clearImageStencilValue; // OpenGL-specific methods @@ -439,15 +438,13 @@ protected: virtual Render3DError SetupShaderIO() = 0; virtual Render3DError CreateToonTable() = 0; virtual Render3DError DestroyToonTable() = 0; - virtual Render3DError UploadToonTable(const GLushort *toonTableBuffer) = 0; - virtual Render3DError CreateClearImage() = 0; - virtual Render3DError DestroyClearImage() = 0; - virtual Render3DError UploadClearImage(const GLushort *clearImageColorBuffer, const GLint *clearImageDepthBuffer) = 0; + virtual Render3DError UploadToonTable(const u16 *toonTableBuffer) = 0; + virtual Render3DError UploadClearImage(const u16 *clearImageColor16Buffer, const u32 *clearImageDepthStencilBuffer) = 0; virtual void GetExtensionSet(std::set *oglExtensionSet) = 0; virtual Render3DError ExpandFreeTextures() = 0; - virtual Render3DError SetupVertices(const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, GLushort *outIndexBuffer, unsigned int *outIndexCount) = 0; - virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const unsigned int vertIndexCount) = 0; + virtual Render3DError SetupVertices(const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, GLushort *outIndexBuffer, size_t *outIndexCount) = 0; + virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount) = 0; virtual Render3DError DisableVertexAttributes() = 0; virtual Render3DError SelectRenderingFramebuffer() = 0; virtual Render3DError DownsampleFBO() = 0; @@ -460,7 +457,7 @@ protected: virtual Render3DError PostRender() = 0; virtual Render3DError EndRender(const u64 frameCount) = 0; - virtual Render3DError UpdateClearImage(const u16 *__restrict colorBuffer, const u16 *__restrict depthBuffer, const u8 clearStencil, const u8 xScroll, const u8 yScroll) = 0; + virtual Render3DError UpdateClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthStencilBuffer) = 0; virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer) = 0; virtual Render3DError ClearUsingImage() const = 0; @@ -468,7 +465,7 @@ protected: virtual Render3DError SetupPolygon(const POLY *thePoly) = 0; virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing) = 0; - virtual Render3DError SetupViewport(const POLY *thePoly) = 0; + virtual Render3DError SetupViewport(const u32 viewportValue) = 0; public: OpenGLRenderer(); @@ -512,15 +509,13 @@ protected: virtual Render3DError SetupShaderIO(); virtual Render3DError CreateToonTable(); virtual Render3DError DestroyToonTable(); - virtual Render3DError UploadToonTable(const GLushort *toonTableBuffer); - virtual Render3DError CreateClearImage(); - virtual Render3DError DestroyClearImage(); - virtual Render3DError UploadClearImage(const GLushort *clearImageColorBuffer, const GLint *clearImageDepthBuffer); + virtual Render3DError UploadToonTable(const u16 *toonTableBuffer); + virtual Render3DError UploadClearImage(const u16 *clearImageColor16Buffer, const u32 *clearImageDepthStencilBuffer); virtual void GetExtensionSet(std::set *oglExtensionSet); virtual Render3DError ExpandFreeTextures(); - virtual Render3DError SetupVertices(const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, GLushort *outIndexBuffer, unsigned int *outIndexCount); - virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const unsigned int vertIndexCount); + virtual Render3DError SetupVertices(const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, GLushort *outIndexBuffer, size_t *outIndexCount); + virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount); virtual Render3DError DisableVertexAttributes(); virtual Render3DError SelectRenderingFramebuffer(); virtual Render3DError DownsampleFBO(); @@ -533,7 +528,7 @@ protected: virtual Render3DError PostRender(); virtual Render3DError EndRender(const u64 frameCount); - virtual Render3DError UpdateClearImage(const u16 *__restrict colorBuffer, const u16 *__restrict depthBuffer, const u8 clearStencil, const u8 xScroll, const u8 yScroll); + virtual Render3DError UpdateClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthStencilBuffer); virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer); virtual Render3DError ClearUsingImage() const; @@ -541,7 +536,7 @@ protected: virtual Render3DError SetupPolygon(const POLY *thePoly); virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing); - virtual Render3DError SetupViewport(const POLY *thePoly); + virtual Render3DError SetupViewport(const u32 viewportValue); public: OpenGLRenderer_1_2(); @@ -557,12 +552,8 @@ public: class OpenGLRenderer_1_3 : public OpenGLRenderer_1_2 { protected: - virtual Render3DError CreateToonTable(); - virtual Render3DError DestroyToonTable(); - virtual Render3DError UploadToonTable(const GLushort *toonTableBuffer); - virtual Render3DError CreateClearImage(); - virtual Render3DError DestroyClearImage(); - virtual Render3DError UploadClearImage(const GLushort *clearImageColorBuffer, const GLint *clearImageDepthBuffer); + virtual Render3DError UploadToonTable(const u16 *toonTableBuffer); + virtual Render3DError UploadClearImage(const u16 *clearImageColor16Buffer, const u32 *clearImageDepthStencilBuffer); }; class OpenGLRenderer_1_4 : public OpenGLRenderer_1_3 @@ -580,7 +571,7 @@ protected: virtual void DestroyPBOs(); virtual Render3DError CreateVAOs(); - virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const unsigned int vertIndexCount); + virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount); virtual Render3DError DisableVertexAttributes(); virtual Render3DError ReadBackPixels(); @@ -596,8 +587,8 @@ protected: virtual Render3DError InitExtensions(); virtual Render3DError InitFinalRenderStates(const std::set *oglExtensionSet); - virtual Render3DError SetupVertices(const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, GLushort *outIndexBuffer, unsigned int *outIndexCount); - virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const unsigned int vertIndexCount); + virtual Render3DError SetupVertices(const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, GLushort *outIndexBuffer, size_t *outIndexCount); + virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount); virtual Render3DError DisableVertexAttributes(); virtual Render3DError BeginRender(const GFX3D_State *renderState); diff --git a/desmume/src/OGLRender_3_2.cpp b/desmume/src/OGLRender_3_2.cpp index 1773daa58..9c82b342b 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-2013 DeSmuME team + Copyright (C) 2008-2015 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 @@ -110,80 +110,55 @@ static const char *fragmentShader_150 = {"\ \n\ uniform sampler2D texMainRender; \n\ uniform sampler1D texToonTable; \n\ + \n\ + uniform int stateToonShadingMode; \n\ + uniform bool stateEnableAlphaTest; \n\ + uniform bool stateUseWDepth; \n\ + uniform float stateAlphaTestRef; \n\ + \n\ + uniform int polyMode; \n\ uniform int polyID; \n\ - uniform bool hasTexture; \n\ - uniform int polygonMode; \n\ - uniform int toonShadingMode; \n\ - uniform bool oglWBuffer; \n\ - uniform bool enableAlphaTest; \n\ - uniform float alphaTestRef; \n\ + \n\ + uniform bool polyEnableTexture; \n\ \n\ out vec4 outFragColor; \n\ \n\ void main() \n\ { \n\ - vec4 texColor = vec4(1.0, 1.0, 1.0, 1.0); \n\ - vec4 fragColor; \n\ + vec4 mainTexColor = (polyEnableTexture) ? texture(texMainRender, vtxTexCoord) : vec4(1.0, 1.0, 1.0, 1.0); \n\ + vec4 tempFragColor = mainTexColor; \n\ \n\ - if(hasTexture) \n\ + if(polyMode == 0) \n\ { \n\ - texColor = texture(texMainRender, vtxTexCoord); \n\ + tempFragColor = vtxColor * mainTexColor; \n\ } \n\ - \n\ - fragColor = texColor; \n\ - \n\ - if(polygonMode == 0) \n\ + else if(polyMode == 1) \n\ { \n\ - fragColor = vtxColor * texColor; \n\ + tempFragColor.rgb = (polyEnableTexture) ? (mainTexColor.rgb * mainTexColor.a) + (vtxColor.rgb * (1.0 - mainTexColor.a)) : vtxColor.rgb; \n\ + tempFragColor.a = vtxColor.a; \n\ } \n\ - else if(polygonMode == 1) \n\ - { \n\ - if (texColor.a == 0.0 || !hasTexture) \n\ - { \n\ - fragColor.rgb = vtxColor.rgb; \n\ - } \n\ - else if (texColor.a == 1.0) \n\ - { \n\ - fragColor.rgb = texColor.rgb; \n\ - } \n\ - else \n\ - { \n\ - fragColor.rgb = texColor.rgb * (1.0-texColor.a) + vtxColor.rgb * texColor.a; \n\ - } \n\ - \n\ - fragColor.a = vtxColor.a; \n\ - } \n\ - else if(polygonMode == 2) \n\ + else if(polyMode == 2) \n\ { \n\ vec3 toonColor = vec3(texture(texToonTable, vtxColor.r).rgb); \n\ - \n\ - if (toonShadingMode == 0) \n\ - { \n\ - fragColor.rgb = texColor.rgb * toonColor.rgb; \n\ - } \n\ - else \n\ - { \n\ - fragColor.rgb = texColor.rgb * vtxColor.rgb + toonColor.rgb; \n\ - } \n\ - \n\ - fragColor.a = texColor.a * vtxColor.a; \n\ + tempFragColor.rgb = (stateToonShadingMode == 0) ? mainTexColor.rgb * toonColor.rgb : min((mainTexColor.rgb * vtxColor.rgb) + toonColor.rgb, 1.0); \n\ + tempFragColor.a = mainTexColor.a * vtxColor.a; \n\ } \n\ - else if(polygonMode == 3) \n\ + else if(polyMode == 3) \n\ { \n\ if (polyID != 0) \n\ { \n\ - fragColor = vtxColor; \n\ + tempFragColor = vtxColor; \n\ } \n\ } \n\ \n\ - if (fragColor.a == 0.0 || (enableAlphaTest && fragColor.a < alphaTestRef)) \n\ + if (tempFragColor.a == 0.0 || (stateEnableAlphaTest && tempFragColor.a < stateAlphaTestRef)) \n\ { \n\ discard; \n\ } \n\ \n\ float vertW = (vtxPosition.w == 0.0) ? 0.00000001 : vtxPosition.w; \n\ - gl_FragDepth = (oglWBuffer) ? vtxPosition.w/4096.0 : clamp((vtxPosition.z/vertW) * 0.5 + 0.5, 0.0, 1.0); \n\ - outFragColor = fragColor; \n\ + gl_FragDepth = (stateUseWDepth) ? vtxPosition.w/4096.0 : clamp((vtxPosition.z/vertW) * 0.5 + 0.5, 0.0, 1.0); \n\ + outFragColor = tempFragColor; \n\ } \n\ "}; @@ -252,7 +227,7 @@ Render3DError OpenGLRenderer_3_2::InitExtensions() error = this->CreateFBOs(); if (error != OGLERROR_NOERR) { - OGLRef.fboFinalOutputID = 0; + OGLRef.fboRenderID = 0; this->isFBOSupported = false; return error; } @@ -283,19 +258,28 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() OGLRenderRef &OGLRef = *this->ref; // Set up FBO render targets - this->CreateClearImage(); + glGenTextures(1, &OGLRef.texClearImageColorID); + glGenTextures(1, &OGLRef.texClearImageDepthStencilID); - glGenRenderbuffers(1, &OGLRef.rboFinalOutputColorID); - glGenRenderbuffers(1, &OGLRef.rboFinalOutputDepthStencilID); + glBindTexture(GL_TEXTURE_2D, OGLRef.texClearImageColorID); + 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, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); - glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboFinalOutputColorID); - glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); - glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboFinalOutputDepthStencilID); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glBindTexture(GL_TEXTURE_2D, OGLRef.texClearImageDepthStencilID); + 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); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); + + glBindTexture(GL_TEXTURE_2D, 0); // Set up FBOs glGenFramebuffers(1, &OGLRef.fboClearImageID); - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboClearImageID); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OGLRef.texClearImageColorID, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, OGLRef.texClearImageDepthStencilID, 0); @@ -305,37 +289,40 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() INFO("OpenGL: Failed to created FBOs. Some emulation features will be disabled.\n"); glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &OGLRef.fboClearImageID); - this->DestroyClearImage(); - - glDeleteRenderbuffers(1, &OGLRef.rboFinalOutputColorID); - glDeleteRenderbuffers(1, &OGLRef.rboFinalOutputDepthStencilID); + glDeleteTextures(1, &OGLRef.texClearImageColorID); + glDeleteTextures(1, &OGLRef.texClearImageDepthStencilID); return OGLERROR_FBO_CREATE_ERROR; } // Set up final output FBO - glGenFramebuffers(1, &OGLRef.fboFinalOutputID); + glGenRenderbuffers(1, &OGLRef.rboFragColorID); + glGenRenderbuffers(1, &OGLRef.rboFragDepthStencilID); + glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboFragColorID); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboFragDepthStencilID); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboFinalOutputID); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, OGLRef.rboFinalOutputColorID); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, OGLRef.rboFinalOutputDepthStencilID); + glGenFramebuffers(1, &OGLRef.fboRenderID); + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, OGLRef.rboFragColorID); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, OGLRef.rboFragDepthStencilID); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { INFO("OpenGL: Failed to created FBOs. Some emulation features will be disabled.\n"); glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &OGLRef.fboClearImageID); - this->DestroyClearImage(); + glDeleteTextures(1, &OGLRef.texClearImageColorID); + glDeleteTextures(1, &OGLRef.texClearImageDepthStencilID); - glDeleteFramebuffers(1, &OGLRef.fboFinalOutputID); - glDeleteRenderbuffers(1, &OGLRef.rboFinalOutputColorID); - glDeleteRenderbuffers(1, &OGLRef.rboFinalOutputDepthStencilID); + glDeleteFramebuffers(1, &OGLRef.fboRenderID); + glDeleteRenderbuffers(1, &OGLRef.rboFragColorID); + glDeleteRenderbuffers(1, &OGLRef.rboFragDepthStencilID); - OGLRef.fboFinalOutputID = 0; + OGLRef.fboRenderID = 0; return OGLERROR_FBO_CREATE_ERROR; } @@ -356,13 +343,13 @@ void OpenGLRenderer_3_2::DestroyFBOs() OGLRenderRef &OGLRef = *this->ref; glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &OGLRef.fboClearImageID); - this->DestroyClearImage(); + glDeleteTextures(1, &OGLRef.texClearImageColorID); + glDeleteTextures(1, &OGLRef.texClearImageDepthStencilID); - glDeleteFramebuffers(1, &OGLRef.fboFinalOutputID); - glDeleteRenderbuffers(1, &OGLRef.rboFinalOutputColorID); - glDeleteRenderbuffers(1, &OGLRef.rboFinalOutputDepthStencilID); + glDeleteFramebuffers(1, &OGLRef.fboRenderID); + glDeleteRenderbuffers(1, &OGLRef.rboFragColorID); + glDeleteRenderbuffers(1, &OGLRef.rboFragDepthStencilID); this->isFBOSupported = false; } @@ -388,33 +375,32 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO() OGLRenderRef &OGLRef = *this->ref; // Set up FBO render targets - glGenRenderbuffers(1, &OGLRef.rboMultisampleColorID); - glGenRenderbuffers(1, &OGLRef.rboMultisampleDepthStencilID); + glGenRenderbuffers(1, &OGLRef.rboMSFragColorID); + glGenRenderbuffers(1, &OGLRef.rboMSFragDepthStencilID); - glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMultisampleColorID); + glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSFragColorID); glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); - glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMultisampleDepthStencilID); + glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSFragDepthStencilID); glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_DEPTH24_STENCIL8, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); // Set up multisampled rendering FBO - glGenFramebuffers(1, &OGLRef.fboMultisampleRenderID); - - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboMultisampleRenderID); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, OGLRef.rboMultisampleColorID); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, OGLRef.rboMultisampleDepthStencilID); + glGenFramebuffers(1, &OGLRef.fboMSIntermediateRenderID); + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderID); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, OGLRef.rboMSFragColorID); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, OGLRef.rboMSFragDepthStencilID); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &OGLRef.fboMultisampleRenderID); - glDeleteRenderbuffers(1, &OGLRef.rboMultisampleColorID); - glDeleteRenderbuffers(1, &OGLRef.rboMultisampleDepthStencilID); + glDeleteFramebuffers(1, &OGLRef.fboMSIntermediateRenderID); + glDeleteRenderbuffers(1, &OGLRef.rboMSFragColorID); + glDeleteRenderbuffers(1, &OGLRef.rboMSFragDepthStencilID); INFO("OpenGL: Failed to create multisampled FBO. Multisample antialiasing will be disabled.\n"); return OGLERROR_FBO_CREATE_ERROR; } - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboFinalOutputID); + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID); INFO("OpenGL: Successfully created multisampled FBO.\n"); return OGLERROR_NOERR; @@ -430,9 +416,9 @@ void OpenGLRenderer_3_2::DestroyMultisampledFBO() OGLRenderRef &OGLRef = *this->ref; glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &OGLRef.fboMultisampleRenderID); - glDeleteRenderbuffers(1, &OGLRef.rboMultisampleColorID); - glDeleteRenderbuffers(1, &OGLRef.rboMultisampleDepthStencilID); + glDeleteFramebuffers(1, &OGLRef.fboMSIntermediateRenderID); + glDeleteRenderbuffers(1, &OGLRef.rboMSFragColorID); + glDeleteRenderbuffers(1, &OGLRef.rboMSFragDepthStencilID); this->isMultisampledFBOSupported = false; } @@ -498,14 +484,14 @@ void OpenGLRenderer_3_2::GetExtensionSet(std::set *oglExtensionSet) GLint extensionCount = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount); - for (unsigned int i = 0; i < extensionCount; i++) + for (size_t i = 0; i < extensionCount; i++) { std::string extensionName = std::string((const char *)glGetStringi(GL_EXTENSIONS, i)); oglExtensionSet->insert(extensionName); } } -Render3DError OpenGLRenderer_3_2::EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const unsigned int vertIndexCount) +Render3DError OpenGLRenderer_3_2::EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount) { OGLRenderRef &OGLRef = *this->ref; @@ -525,15 +511,11 @@ Render3DError OpenGLRenderer_3_2::DisableVertexAttributes() Render3DError OpenGLRenderer_3_2::SelectRenderingFramebuffer() { OGLRenderRef &OGLRef = *this->ref; + static const GLenum drawDirect[1] = {GL_COLOR_ATTACHMENT0}; - if (this->isMultisampledFBOSupported) - { - OGLRef.selectedRenderingFBO = CommonSettings.GFX3D_Renderer_Multisample ? OGLRef.fboMultisampleRenderID : OGLRef.fboFinalOutputID; - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); - - const GLenum drawBufferList = {GL_COLOR_ATTACHMENT0}; - glDrawBuffers(1, &drawBufferList); - } + OGLRef.selectedRenderingFBO = (CommonSettings.GFX3D_Renderer_Multisample) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID; + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); + glDrawBuffers(1, &drawDirect[0]); return OGLERROR_NOERR; } @@ -542,15 +524,15 @@ Render3DError OpenGLRenderer_3_2::DownsampleFBO() { OGLRenderRef &OGLRef = *this->ref; - if (!this->isMultisampledFBOSupported || OGLRef.selectedRenderingFBO != OGLRef.fboMultisampleRenderID) + if (OGLRef.selectedRenderingFBO != OGLRef.fboMSIntermediateRenderID) { return OGLERROR_NOERR; } glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.selectedRenderingFBO); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboFinalOutputID); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderID); glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboFinalOutputID); + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID); return OGLERROR_NOERR; } diff --git a/desmume/src/OGLRender_3_2.h b/desmume/src/OGLRender_3_2.h index 2f1a5ed05..b16d84e2e 100644 --- a/desmume/src/OGLRender_3_2.h +++ b/desmume/src/OGLRender_3_2.h @@ -72,7 +72,7 @@ protected: virtual Render3DError SetupShaderIO(); virtual void GetExtensionSet(std::set *oglExtensionSet); - virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const unsigned int vertIndexCount); + virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount); virtual Render3DError DisableVertexAttributes(); virtual Render3DError SelectRenderingFramebuffer(); virtual Render3DError DownsampleFBO(); diff --git a/desmume/src/render3D.cpp b/desmume/src/render3D.cpp index de89a716b..4e7b4f2f4 100644 --- a/desmume/src/render3D.cpp +++ b/desmume/src/render3D.cpp @@ -24,6 +24,7 @@ #include "MMU.h" #include "texcache.h" +static CACHE_ALIGN u32 dsDepthToD24S8_LUT[32768] = {0}; int cur3DCore = GPU3D_NULL; GPU3DInterface gpu3DNull = { @@ -97,6 +98,23 @@ bool NDS_3D_ChangeCore(int newCore) return true; } +Render3D::Render3D() +{ + static bool needTableInit = true; + + if (needTableInit) + { + for (size_t i = 0; i < 32768; i++) + { + dsDepthToD24S8_LUT[i] = (u32)DS_DEPTH15TO24(i) << 8; + } + + needTableInit = false; + } + + Reset(); +} + Render3DError Render3D::BeginRender(const GFX3D_State *renderState) { return RENDER3DERROR_NOERR; @@ -122,7 +140,7 @@ Render3DError Render3D::EndRender(const u64 frameCount) return RENDER3DERROR_NOERR; } -Render3DError Render3D::UpdateClearImage(const u16 *__restrict colorBuffer, const u16 *__restrict depthBuffer, const u8 clearStencil, const u8 xScroll, const u8 yScroll) +Render3DError Render3D::UpdateClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthStencilBuffer) { return RENDER3DERROR_NOERR; } @@ -149,7 +167,7 @@ Render3DError Render3D::ClearFramebuffer(const GFX3D_State *renderState) clearColor.b = (renderState->clearColor >> 10) & 0x1F; clearColor.a = (renderState->clearColor >> 16) & 0x1F; - const u8 clearStencil = (renderState->clearColor >> 24) & 0x3F; + const u8 polyID = (renderState->clearColor >> 24) & 0x3F; if (renderState->enableClearImage) { @@ -159,19 +177,39 @@ Render3DError Render3D::ClearFramebuffer(const GFX3D_State *renderState) const u8 xScroll = scrollBits & 0xFF; const u8 yScroll = (scrollBits >> 8) & 0xFF; - error = this->UpdateClearImage(clearColorBuffer, clearDepthBuffer, clearStencil, xScroll, yScroll); + size_t dd = (GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT) - GFX3D_FRAMEBUFFER_WIDTH; + + for (size_t iy = 0; iy < GFX3D_FRAMEBUFFER_HEIGHT; iy++) + { + const size_t y = ((iy + yScroll) & 0xFF) << 8; + + for (size_t ix = 0; ix < GFX3D_FRAMEBUFFER_WIDTH; ix++) + { + const size_t x = (ix + xScroll) & 0xFF; + const size_t adr = y + x; + + this->clearImageColor16Buffer[dd] = clearColorBuffer[adr]; + this->clearImageDepthStencilBuffer[dd] = dsDepthToD24S8_LUT[clearDepthBuffer[adr] & 0x7FFF] | polyID; + + dd++; + } + + dd -= GFX3D_FRAMEBUFFER_WIDTH * 2; + } + + error = this->UpdateClearImage(this->clearImageColor16Buffer, this->clearImageDepthStencilBuffer); if (error == RENDER3DERROR_NOERR) { error = this->ClearUsingImage(); } else { - error = this->ClearUsingValues(clearColor.r, clearColor.g, clearColor.b, clearColor.a, renderState->clearDepth, clearStencil); + error = this->ClearUsingValues(clearColor.r, clearColor.g, clearColor.b, clearColor.a, renderState->clearDepth, polyID); } } else { - error = this->ClearUsingValues(clearColor.r, clearColor.g, clearColor.b, clearColor.a, renderState->clearDepth, clearStencil); + error = this->ClearUsingValues(clearColor.r, clearColor.g, clearColor.b, clearColor.a, renderState->clearDepth, polyID); } return error; @@ -197,13 +235,16 @@ Render3DError Render3D::SetupTexture(const POLY *thePoly, bool enableTexturing) return RENDER3DERROR_NOERR; } -Render3DError Render3D::SetupViewport(const POLY *thePoly) +Render3DError Render3D::SetupViewport(const u32 viewportValue) { return RENDER3DERROR_NOERR; } Render3DError Render3D::Reset() { + memset(this->clearImageColor16Buffer, 0, sizeof(this->clearImageColor16Buffer)); + memset(this->clearImageDepthStencilBuffer, 0, sizeof(this->clearImageDepthStencilBuffer)); + return RENDER3DERROR_NOERR; } diff --git a/desmume/src/render3D.h b/desmume/src/render3D.h index 23bf7edd3..8e64227e9 100644 --- a/desmume/src/render3D.h +++ b/desmume/src/render3D.h @@ -1,6 +1,6 @@ /* Copyright (C) 2006-2007 shash - Copyright (C) 2007-2013 DeSmuME team + Copyright (C) 2007-2015 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 @@ -84,13 +84,16 @@ typedef int Render3DError; class Render3D { protected: + CACHE_ALIGN u16 clearImageColor16Buffer[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; + CACHE_ALIGN u32 clearImageDepthStencilBuffer[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; + virtual Render3DError BeginRender(const GFX3D_State *renderState); virtual Render3DError PreRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList); virtual Render3DError DoRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList); virtual Render3DError PostRender(); virtual Render3DError EndRender(const u64 frameCount); - virtual Render3DError UpdateClearImage(const u16 *__restrict colorBuffer, const u16 *__restrict depthBuffer, const u8 clearStencil, const u8 xScroll, const u8 yScroll); + virtual Render3DError UpdateClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthStencilBuffer); virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer); virtual Render3DError ClearFramebuffer(const GFX3D_State *renderState); @@ -99,9 +102,11 @@ protected: virtual Render3DError SetupPolygon(const POLY *thePoly); virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing); - virtual Render3DError SetupViewport(const POLY *thePoly); + virtual Render3DError SetupViewport(const u32 viewportValue); public: + Render3D(); + virtual Render3DError Reset(); virtual Render3DError Render(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, const u64 frameCount); virtual Render3DError RenderFinish();