From 5bfe553a8b5f57f4b23e3a16cd5e58dc35923b3d Mon Sep 17 00:00:00 2001 From: zeromus Date: Sun, 29 Mar 2015 09:10:03 +0000 Subject: [PATCH 2/7] set final revision in changelog --- desmume/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desmume/ChangeLog b/desmume/ChangeLog index f7ad56d11..fd04a9f8b 100644 --- a/desmume/ChangeLog +++ b/desmume/ChangeLog @@ -1,4 +1,4 @@ -0.9.10 -> 0.9.11 (r4908-r????) +0.9.10 -> 0.9.11 (r4908-r5146) In this version, we have focused on the Cocoa frontend, but there have been some good core fixes over so long. Notably, the save-related issues resulting in the advice "dont use 0.9.10" have been resolved. From 4fe116b4239018901528b9af055d9ef3f4a34303 Mon Sep 17 00:00:00 2001 From: zeromus Date: Sun, 5 Apr 2015 18:35:43 +0000 Subject: [PATCH 3/7] Merged revision(s) 5152 from trunk/desmume/src: fix small mistake in r5121 that whacks all battery saves when making a savestate ........ --- desmume/src/mc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desmume/src/mc.cpp b/desmume/src/mc.cpp index 8187ae269..b5e865b03 100644 --- a/desmume/src/mc.cpp +++ b/desmume/src/mc.cpp @@ -123,7 +123,7 @@ bool BackupDevice::save_state(EMUFILE* os) std::vector data(fsize); fpMC->fseek(0, SEEK_SET); if(data.size()!=0) - fpMC->fwrite((char *)&data[0], fsize); + fpMC->fread((char *)&data[0], fsize); u32 version = 5; //v0 From 0b4fd3cb5e7ec2279fdc0a5b081202089af49541 Mon Sep 17 00:00:00 2001 From: rogerman Date: Tue, 7 Apr 2015 22:34:29 +0000 Subject: [PATCH 4/7] OpenGL Renderer (v0.9.11): - Backport changes from r5154 to the 0.9.11 branch. --- desmume/src/OGLRender.cpp | 806 ++++++++++------------------------ desmume/src/OGLRender.h | 87 ++-- desmume/src/OGLRender_3_2.cpp | 198 ++++----- desmume/src/OGLRender_3_2.h | 2 +- desmume/src/render3D.cpp | 53 ++- desmume/src/render3D.h | 11 +- 6 files changed, 421 insertions(+), 736 deletions(-) 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(); From d1e7a1ba41f49c0cfaa170fd30dc4881fa8bbbf5 Mon Sep 17 00:00:00 2001 From: zeromus Date: Tue, 14 Apr 2015 23:41:43 +0000 Subject: [PATCH 5/7] fix files missing from Makefile.am --- desmume/src/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/desmume/src/Makefile.am b/desmume/src/Makefile.am index 47761e02f..c329a069b 100644 --- a/desmume/src/Makefile.am +++ b/desmume/src/Makefile.am @@ -30,7 +30,7 @@ libdesmume_a_SOURCES = \ wifi.cpp wifi.h \ mic.h \ MMU.cpp MMU.h MMU_timing.h NDSSystem.cpp NDSSystem.h registers.h \ - OGLRender.h \ + OGLRender.h OGLRender_3_2.h \ ROMReader.cpp ROMReader.h \ render3D.cpp render3D.h \ rtc.cpp rtc.h \ @@ -87,6 +87,7 @@ libdesmume_a_SOURCES = \ utils/tinyxml/tinyxml.h \ utils/tinyxml/tinyxmlerror.cpp \ utils/tinyxml/tinyxmlparser.cpp \ + utils/glcorearb.h \ addons/slot2_auto.cpp addons/slot2_mpcf.cpp addons/slot2_paddle.cpp addons/slot2_gbagame.cpp addons/slot2_none.cpp addons/slot2_rumblepak.cpp addons/slot2_guitarGrip.cpp addons/slot2_expMemory.cpp addons/slot2_piano.cpp addons/slot2_passme.cpp addons/slot1_none.cpp addons/slot1_r4.cpp addons/slot1_retail_nand.cpp addons/slot1_retail_auto.cpp addons/slot1_retail_mcrom.cpp addons/slot1_retail_mcrom_debug.cpp addons/slot1comp_mc.cpp addons/slot1comp_mc.h addons/slot1comp_rom.h addons/slot1comp_rom.cpp addons/slot1comp_protocol.h addons/slot1comp_protocol.cpp \ cheatSystem.cpp cheatSystem.h \ texcache.cpp texcache.h rasterize.cpp rasterize.h \ From 7c7fd242c221a8f722d39f9df5cdf40789cb31e3 Mon Sep 17 00:00:00 2001 From: zeromus Date: Tue, 14 Apr 2015 23:42:15 +0000 Subject: [PATCH 6/7] oops this should probably be tabs --- desmume/src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desmume/src/Makefile.am b/desmume/src/Makefile.am index c329a069b..7b9e26317 100644 --- a/desmume/src/Makefile.am +++ b/desmume/src/Makefile.am @@ -87,7 +87,7 @@ libdesmume_a_SOURCES = \ utils/tinyxml/tinyxml.h \ utils/tinyxml/tinyxmlerror.cpp \ utils/tinyxml/tinyxmlparser.cpp \ - utils/glcorearb.h \ + utils/glcorearb.h \ addons/slot2_auto.cpp addons/slot2_mpcf.cpp addons/slot2_paddle.cpp addons/slot2_gbagame.cpp addons/slot2_none.cpp addons/slot2_rumblepak.cpp addons/slot2_guitarGrip.cpp addons/slot2_expMemory.cpp addons/slot2_piano.cpp addons/slot2_passme.cpp addons/slot1_none.cpp addons/slot1_r4.cpp addons/slot1_retail_nand.cpp addons/slot1_retail_auto.cpp addons/slot1_retail_mcrom.cpp addons/slot1_retail_mcrom_debug.cpp addons/slot1comp_mc.cpp addons/slot1comp_mc.h addons/slot1comp_rom.h addons/slot1comp_rom.cpp addons/slot1comp_protocol.h addons/slot1comp_protocol.cpp \ cheatSystem.cpp cheatSystem.h \ texcache.cpp texcache.h rasterize.cpp rasterize.h \ From ad2dafe6616abd0ab73a6a5b4aaf7dceecf5fa5e Mon Sep 17 00:00:00 2001 From: zeromus Date: Thu, 4 Oct 2018 22:43:21 -0400 Subject: [PATCH 7/7] add lua apis for raw joystick input (on windows, anyway) --- desmume/src/lua-engine.cpp | 87 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/desmume/src/lua-engine.cpp b/desmume/src/lua-engine.cpp index 3778407cd..904f8ca95 100644 --- a/desmume/src/lua-engine.cpp +++ b/desmume/src/lua-engine.cpp @@ -4504,6 +4504,90 @@ DEFINE_LUA_FUNCTION(stylus_write, "table") return 0; } +#if defined(_WIN32) + const char* s_dpadDirections[4] = {"up", "right", "down", "left"}; + const char* s_buttonNames[33] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32"}; +#endif +// this function takes two optional variables +// joystickID: a value (0-15) that identifies the controller to read; default is 0 which is the "preferred device" set in the control panel +// returnDiagonals: a boolean (true/false) that determines whether or not to return diagonal values from a supported D-pad; default is false, which ignores diagonal values +DEFINE_LUA_FUNCTION(controller_get, "[joystickID = 0 [,returnDiagonals = false]]") { + unsigned int i_joystickID = 0;bool f_returnDiagonals = 0; // initialize optional variables + switch (lua_gettop(L)) { // get number of arguments + case 1: + i_joystickID = lua_tonumber(L,1); + break; + case 2: + i_joystickID = lua_tonumber(L,1); + if (lua_isboolean(L,2)) { // only accept true/false + f_returnDiagonals = lua_toboolean(L,2); + } + break; + } + lua_newtable(L); // create new empty table + + JOYCAPS joycaps; + MMRESULT joygetdevcaps_result = joyGetDevCaps(i_joystickID, &joycaps, sizeof(joycaps)); // get controller's joystick (dpad) capabilities and number of buttons + if (joygetdevcaps_result != JOYERR_NOERROR) {return 1;} // joystick doesn't exist so return an empty table + + JOYINFOEX joyinfoex; + joyinfoex.dwSize = sizeof(joyinfoex); + joyinfoex.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOV; + MMRESULT joygetposex_result = joyGetPosEx(i_joystickID, &joyinfoex); // query joystick's pov and buttons + if (joygetposex_result != JOYERR_NOERROR) {return 1;} // joystick doesn't exist so return an empty table + + bool dpad[4] = {0,0,0,0}; // up, right, down, left; + if ((joycaps.wCaps & JOYCAPS_HASPOV) && (joycaps.wCaps & JOYCAPS_POV4DIR)) { // confirm joystick has a pov that supports discrete values + if (joyinfoex.dwPOV != JOY_POVCENTERED) { // dpad is neutral + if (!(joyinfoex.dwPOV % 9000)) { // dpad is not currently on a diagonal so don't bother checking them + dpad[(joyinfoex.dwPOV / 4500)/2] = true; // divide by 2 to ignore diagonals + } else if (f_returnDiagonals) { // get the diagonal values if asked + switch (joyinfoex.dwPOV) { + case 4500: // up/right + dpad[0] = true; + dpad[1] = true; + break; + case 13500: // down/right + dpad[2] = true; + dpad[1] = true; + break; + case 22500: // down/left + dpad[2] = true; + dpad[3] = true; + break; + case 31500: // up/left + dpad[0] = true; + dpad[3] = true; + break; + } + } + + } + } else { + // there is no supported dpad so all dpad booleans will default to false + // should add support for JOYCAPS_POVCTS here but my three test controllers don't use it; unsure if it's even needed + } + + for (int i = 0; i < 4; i++) { // add dpad data to the table + lua_pushboolean(L, dpad[i]); // dpad direction isPressed + lua_setfield(L, -2, s_dpadDirections[i]); // dpad direction name + } + + int pow = 1; // joyinfoex.dwButtons is the total value of all pressed buttons; button values are powers of 2, starting with 2^0 for button 1 + for (unsigned int i = 1; i <= joycaps.wNumButtons; i++) { // add button data to the table + lua_pushboolean(L, (joyinfoex.dwButtons & pow) ? (true) : (false)); // button isPressed + lua_setfield(L, -2, s_buttonNames[i]); // button number + pow *= 2; + } + + return 1; // return the table +} +static const struct luaL_reg controllerlib [] = { + {"get", controller_get}, + {"read", controller_get}, + {NULL, NULL} +}; + static int gcEMUFILE_MEMORY(lua_State *L) { EMUFILE_MEMORY** ppEmuFile = (EMUFILE_MEMORY**)luaL_checkudata(L, 1, "EMUFILE_MEMORY*"); @@ -4867,6 +4951,9 @@ void registerLibs(lua_State* L) luaL_register(L, "agg", aggbasicshapes); luaL_register(L, "agg", agggeneralattributes); luaL_register(L, "agg", aggcustom); + + luaL_register(L, "controller", controllerlib); + lua_settop(L, 0); // clean the stack, because each call to luaL_register leaves a table on top