From 9d6f2846818d36573bf7f80a9a22ea193efa16b3 Mon Sep 17 00:00:00 2001 From: rogerman Date: Fri, 8 May 2015 22:45:09 +0000 Subject: [PATCH] GFX3D: - Do more code cleanup and refactoring. --- desmume/src/NDSSystem.cpp | 1 + desmume/src/OGLRender.cpp | 329 ++++++++++++++++------------------ desmume/src/OGLRender.h | 16 +- desmume/src/OGLRender_3_2.cpp | 47 +++-- desmume/src/gfx3d.cpp | 56 +++++- desmume/src/gfx3d.h | 9 +- desmume/src/rasterize.cpp | 140 ++++++++------- desmume/src/rasterize.h | 6 +- desmume/src/render3D.cpp | 47 ++++- desmume/src/render3D.h | 12 ++ 10 files changed, 380 insertions(+), 283 deletions(-) diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index 54f824c9b..c2ac7716c 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -192,6 +192,7 @@ void NDS_DeInit(void) Screen_DeInit(); MMU_DeInit(); Render3D_DeInit(); + gfx3d_deinit(); WIFI_DeInit(); diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index b6c250884..73d62f7f9 100644 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -790,20 +790,31 @@ OpenGLRenderer::OpenGLRenderer() // Init OpenGL rendering states ref = new OGLRenderRef; + ref->workingDepthBuffer = (GLuint *)calloc(_framebufferWidth * _framebufferHeight, sizeof(GLuint)); + ref->workingDepthStencilBuffer = (GLuint *)calloc(_framebufferWidth * _framebufferHeight, sizeof(GLuint)); + ref->workingFogAttributesBuffer = (GLuint *)calloc(_framebufferWidth * _framebufferHeight, sizeof(GLuint)); + ref->workingPolyIDBuffer = (GLuint *)calloc(_framebufferWidth * _framebufferHeight, sizeof(GLuint)); ref->fboRenderID = 0; ref->fboMSIntermediateRenderID = 0; ref->fboPostprocessID = 0; ref->selectedRenderingFBO = 0; - memset(GPU_screen3D, 0, sizeof(GPU_screen3D)); - currTexture = NULL; - gpuScreen3DHasNewData[0] = false; - gpuScreen3DHasNewData[1] = false; - doubleBufferIndex = 0; + _pixelReadNeedsFinish = false; _currentPolyIndex = 0; } +OpenGLRenderer::~OpenGLRenderer() +{ + // Destroy OpenGL rendering states + free(ref->workingDepthBuffer); + free(ref->workingDepthStencilBuffer); + free(ref->workingFogAttributesBuffer); + free(ref->workingPolyIDBuffer); + delete ref; + ref = NULL; +} + bool OpenGLRenderer::IsExtensionPresent(const std::set *oglExtensionSet, const std::string extensionName) const { if (oglExtensionSet == NULL || oglExtensionSet->size() == 0) @@ -880,44 +891,34 @@ void OpenGLRenderer::SetVersion(unsigned int major, unsigned int minor, unsigned this->versionRevision = revision; } -void OpenGLRenderer::ConvertFramebuffer(const u32 *__restrict srcBuffer, u32 *dstBuffer) +Render3DError OpenGLRenderer::FlushFramebuffer(FragmentColor *dstBuffer) { - if (srcBuffer == NULL || dstBuffer == NULL) - { - return; - } - // Convert from 32-bit BGRA8888 format to 32-bit RGBA6665 reversed format. OpenGL // stores pixels using a flipped Y-coordinate, so this needs to be flipped back // to the DS Y-coordinate. - for(int i = 0, y = 191; y >= 0; y--) + for (size_t y = 0, ir = 0, iw = ((this->_framebufferHeight - 1) * this->_framebufferWidth); y < this->_framebufferHeight; y++, iw -= (this->_framebufferWidth * 2)) { - u32 *__restrict dst = dstBuffer + (y * GFX3D_FRAMEBUFFER_WIDTH); - - for(size_t x = 0; x < GFX3D_FRAMEBUFFER_WIDTH; x++, i++) + for (size_t x = 0; x < this->_framebufferWidth; x++, ir++, iw++) { // Use the correct endian format since OpenGL uses the native endian of // the architecture it is running on. #ifdef WORDS_BIGENDIAN - *dst++ = BGRA8888_32_To_RGBA6665_32(srcBuffer[i]); + dstBuffer[iw].color = BGRA8888_32_To_RGBA6665_32(this->_framebufferColor[ir].color); + #else - *dst++ = BGRA8888_32Rev_To_RGBA6665_32Rev(srcBuffer[i]); + dstBuffer[iw].color = BGRA8888_32Rev_To_RGBA6665_32Rev(this->_framebufferColor[ir].color); #endif } } + + return RENDER3DERROR_NOERR; } OpenGLRenderer_1_2::~OpenGLRenderer_1_2() { - if (ref == NULL) - { - return; - } - glFinish(); - gpuScreen3DHasNewData[0] = false; - gpuScreen3DHasNewData[1] = false; + _pixelReadNeedsFinish = false; delete[] ref->color4fBuffer; ref->color4fBuffer = NULL; @@ -944,10 +945,6 @@ OpenGLRenderer_1_2::~OpenGLRenderer_1_2() } glFinish(); - - // Destroy OpenGL rendering states - delete ref; - ref = NULL; } Render3DError OpenGLRenderer_1_2::InitExtensions() @@ -1110,14 +1107,11 @@ void OpenGLRenderer_1_2::DestroyVBOs() Render3DError OpenGLRenderer_1_2::CreatePBOs() { - glGenBuffersARB(2, this->ref->pboRenderDataID); - 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); - } + OGLRenderRef &OGLRef = *this->ref; - glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); + glGenBuffersARB(1, &OGLRef.pboRenderDataID); + glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, OGLRef.pboRenderDataID); + glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, this->_framebufferColorSizeBytes, NULL, GL_STREAM_READ_ARB); return OGLERROR_NOERR; } @@ -1130,7 +1124,7 @@ void OpenGLRenderer_1_2::DestroyPBOs() } glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); - glDeleteBuffersARB(2, this->ref->pboRenderDataID); + glDeleteBuffersARB(1, &this->ref->pboRenderDataID); this->isPBOSupported = false; } @@ -1357,14 +1351,14 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, this->_framebufferWidth, this->_framebufferHeight, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL); glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID); 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GDepth); glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthID); @@ -1372,7 +1366,7 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GPolyID); glBindTexture(GL_TEXTURE_2D, OGLRef.texGPolyID); @@ -1380,7 +1374,7 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FogAttr); glBindTexture(GL_TEXTURE_2D, OGLRef.texGFogAttrID); @@ -1388,7 +1382,7 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessFogID); @@ -1396,7 +1390,7 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glBindTexture(GL_TEXTURE_2D, 0); @@ -1517,15 +1511,15 @@ Render3DError OpenGLRenderer_1_2::CreateMultisampledFBO() glGenRenderbuffersEXT(1, &OGLRef.rboMSGDepthStencilID); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID); - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthID); - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID); - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID); - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID); - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_DEPTH24_STENCIL8_EXT, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_DEPTH24_STENCIL8_EXT, this->_framebufferWidth, this->_framebufferHeight); // Set up multisampled rendering FBO glGenFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderID); @@ -1708,35 +1702,41 @@ Render3DError OpenGLRenderer_1_2::UploadClearImage(const u16 *__restrict colorBu { OGLRenderRef &OGLRef = *this->ref; - static GLuint depth[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; - static GLuint depthStencil[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; - static GLuint fogAttributes[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; - static GLuint polyID[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; - - for (size_t i = 0; i < GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT; i++) + if (this->isShaderSupported) { - depth[i] = depthBuffer[i] | 0xFF000000; - depthStencil[i] = depthBuffer[i] << 8; - fogAttributes[i] = (fogBuffer[i]) ? 0xFF0000FF : 0xFF000000; - polyID[i] = (GLuint)polyIDBuffer[i] | 0xFF000000; + for (size_t i = 0; i < this->_framebufferWidth * this->_framebufferHeight; i++) + { + OGLRef.workingDepthStencilBuffer[i] = depthBuffer[i] << 8; + OGLRef.workingDepthBuffer[i] = depthBuffer[i] | 0xFF000000; + OGLRef.workingFogAttributesBuffer[i] = (fogBuffer[i]) ? 0xFF0000FF : 0xFF000000; + OGLRef.workingPolyIDBuffer[i] = (GLuint)polyIDBuffer[i] | 0xFF000000; + } + } + else + { + for (size_t i = 0; i < this->_framebufferWidth * this->_framebufferHeight; i++) + { + OGLRef.workingDepthStencilBuffer[i] = depthBuffer[i] << 8; + } } glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_GColor); glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthStencilID); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, depthStencil); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, OGLRef.workingDepthStencilBuffer); glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, colorBuffer); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, colorBuffer); - glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_GDepth); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, depth); - - glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_GPolyID); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, polyID); - - glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_FogAttr); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, fogAttributes); - - glActiveTextureARB(GL_TEXTURE0_ARB); + if (this->isShaderSupported) + { + glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_GDepth); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingDepthBuffer); + + glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_FogAttr); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingFogAttributesBuffer); + + glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_GPolyID); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingPolyIDBuffer); + } return OGLERROR_NOERR; } @@ -1860,22 +1860,22 @@ Render3DError OpenGLRenderer_1_2::DownsampleFBO() // Blit the color buffer glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the working depth buffer glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); - glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the polygon ID buffer glReadBuffer(GL_COLOR_ATTACHMENT2_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); - glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the fog buffer glReadBuffer(GL_COLOR_ATTACHMENT3_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); - glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Reset framebuffer targets glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); @@ -1888,16 +1888,12 @@ Render3DError OpenGLRenderer_1_2::DownsampleFBO() Render3DError OpenGLRenderer_1_2::ReadBackPixels() { - const size_t i = this->doubleBufferIndex; - if (this->isPBOSupported) { - glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, this->ref->pboRenderDataID[i]); - glReadPixels(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, 0); - glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); + glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0); } - this->gpuScreen3DHasNewData[i] = true; + this->_pixelReadNeedsFinish = true; return OGLERROR_NOERR; } @@ -1916,7 +1912,6 @@ Render3DError OpenGLRenderer_1_2::DeleteTexture(const TexCacheItem *item) Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine) { OGLRenderRef &OGLRef = *this->ref; - this->doubleBufferIndex = (this->doubleBufferIndex + 1) & 0x01; if(!BEGINGL()) { @@ -2211,22 +2206,22 @@ Render3DError OpenGLRenderer_1_2::ClearUsingImage(const u16 *__restrict colorBuf // Blit the working depth buffer glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); - glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the polygon ID buffer glReadBuffer(GL_COLOR_ATTACHMENT2_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); - glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the fog buffer glReadBuffer(GL_COLOR_ATTACHMENT3_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); - glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the color buffer. Do this last so that color attachment 0 is set to the read FBO. glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); @@ -2492,13 +2487,7 @@ Render3DError OpenGLRenderer_1_2::Reset() ENDGL(); - this->gpuScreen3DHasNewData[0] = false; - this->gpuScreen3DHasNewData[1] = false; - - for (size_t i = 0; i < 2; i++) - { - memset(this->GPU_screen3D[i], 0, sizeof(this->GPU_screen3D[i])); - } + this->_pixelReadNeedsFinish = false; if (OGLRef.color4fBuffer != NULL) { @@ -2511,13 +2500,14 @@ Render3DError OpenGLRenderer_1_2::Reset() } this->currTexture = NULL; - this->doubleBufferIndex = 0; this->_currentPolyIndex = 0; OGLRef.vtxPtrPosition = (GLvoid *)offsetof(VERT, coord); OGLRef.vtxPtrTexCoord = (GLvoid *)offsetof(VERT, texcoord); OGLRef.vtxPtrColor = (this->isShaderSupported) ? (GLvoid *)offsetof(VERT, color) : OGLRef.color4fBuffer; + + memset(this->clearImageColor16Buffer, 0, sizeof(this->clearImageColor16Buffer)); memset(this->clearImageDepthBuffer, 0, sizeof(this->clearImageDepthBuffer)); memset(this->clearImagePolyIDBuffer, 0, sizeof(this->clearImagePolyIDBuffer)); @@ -2530,15 +2520,11 @@ Render3DError OpenGLRenderer_1_2::Reset() Render3DError OpenGLRenderer_1_2::RenderFinish() { - const size_t i = this->doubleBufferIndex; - - if (!this->gpuScreen3DHasNewData[i]) + if (!this->_pixelReadNeedsFinish) { return OGLERROR_NOERR; } - OGLRenderRef &OGLRef = *this->ref; - if(!BEGINGL()) { return OGLERROR_BEGINGL_FAILED; @@ -2546,31 +2532,38 @@ Render3DError OpenGLRenderer_1_2::RenderFinish() if (this->isPBOSupported) { - glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, OGLRef.pboRenderDataID[i]); - - const u32 *__restrict mappedBufferPtr = (u32 *__restrict)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB); + const FragmentColor *__restrict mappedBufferPtr = (FragmentColor *__restrict)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB); if (mappedBufferPtr != NULL) { - this->ConvertFramebuffer(mappedBufferPtr, (u32 *)gfx3d_convertedScreen); + memcpy(this->_framebufferColor, mappedBufferPtr, this->_framebufferColorSizeBytes); glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); } - - glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); } else { - u32 *__restrict workingBuffer = this->GPU_screen3D[i]; - glReadPixels(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, workingBuffer); - this->ConvertFramebuffer(workingBuffer, (u32 *)gfx3d_convertedScreen); + glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, this->_framebufferColor); } ENDGL(); - this->gpuScreen3DHasNewData[i] = false; + this->FlushFramebuffer((FragmentColor *)gfx3d_convertedScreen); + this->_pixelReadNeedsFinish = false; return OGLERROR_NOERR; } +Render3DError OpenGLRenderer_1_2::SetFramebufferSize(size_t w, size_t h) +{ + if (w < GFX3D_FRAMEBUFFER_WIDTH || h < GFX3D_FRAMEBUFFER_HEIGHT) + { + return RENDER3DERROR_NOERR; + } + + // TODO: We're not prepared to do this yet, so do nothing for now. + + return RENDER3DERROR_NOERR; +} + Render3DError OpenGLRenderer_1_3::CreateToonTable() { OGLRenderRef &OGLRef = *this->ref; @@ -2605,33 +2598,41 @@ Render3DError OpenGLRenderer_1_3::UploadClearImage(const u16 *__restrict colorBu { OGLRenderRef &OGLRef = *this->ref; - static GLuint depth[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; - static GLuint depthStencil[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; - static GLuint fogAttributes[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; - static GLuint polyID[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; - - for (size_t i = 0; i < GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT; i++) + if (this->isShaderSupported) { - depth[i] = depthBuffer[i] | 0xFF000000; - depthStencil[i] = depthBuffer[i] << 8; - fogAttributes[i] = (fogBuffer[i]) ? 0xFF0000FF : 0xFF000000; - polyID[i] = (GLuint)polyIDBuffer[i] | 0xFF000000; + for (size_t i = 0; i < this->_framebufferWidth * this->_framebufferHeight; i++) + { + OGLRef.workingDepthStencilBuffer[i] = depthBuffer[i] << 8; + OGLRef.workingDepthBuffer[i] = depthBuffer[i] | 0xFF000000; + OGLRef.workingFogAttributesBuffer[i] = (fogBuffer[i]) ? 0xFF0000FF : 0xFF000000; + OGLRef.workingPolyIDBuffer[i] = (GLuint)polyIDBuffer[i] | 0xFF000000; + } + } + else + { + for (size_t i = 0; i < this->_framebufferWidth * this->_framebufferHeight; i++) + { + OGLRef.workingDepthStencilBuffer[i] = depthBuffer[i] << 8; + } } glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GColor); glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthStencilID); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, depthStencil); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, OGLRef.workingDepthStencilBuffer); glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, colorBuffer); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, colorBuffer); - glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GDepth); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, depth); - - glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GPolyID); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, polyID); - - glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FogAttr); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, fogAttributes); + if (this->isShaderSupported) + { + glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GDepth); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingDepthBuffer); + + glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FogAttr); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingFogAttributesBuffer); + + glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GPolyID); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingPolyIDBuffer); + } return OGLERROR_NOERR; } @@ -2729,14 +2730,9 @@ Render3DError OpenGLRenderer_1_5::CreatePBOs() { OGLRenderRef &OGLRef = *this->ref; - glGenBuffers(2, OGLRef.pboRenderDataID); - 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); - } - - glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); + glGenBuffers(1, &OGLRef.pboRenderDataID); + glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, OGLRef.pboRenderDataID); + glBufferData(GL_PIXEL_PACK_BUFFER_ARB, this->_framebufferColorSizeBytes, NULL, GL_STREAM_READ); return OGLERROR_NOERR; } @@ -2749,7 +2745,7 @@ void OpenGLRenderer_1_5::DestroyPBOs() } glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); - glDeleteBuffers(2, this->ref->pboRenderDataID); + glDeleteBuffers(1, &this->ref->pboRenderDataID); this->isPBOSupported = false; } @@ -2855,7 +2851,6 @@ Render3DError OpenGLRenderer_1_5::DisableVertexAttributes() Render3DError OpenGLRenderer_1_5::BeginRender(const GFX3D &engine) { OGLRenderRef &OGLRef = *this->ref; - this->doubleBufferIndex = (this->doubleBufferIndex + 1) & 0x01; if(!BEGINGL()) { @@ -2929,31 +2924,23 @@ Render3DError OpenGLRenderer_1_5::BeginRender(const GFX3D &engine) Render3DError OpenGLRenderer_1_5::ReadBackPixels() { - const size_t i = this->doubleBufferIndex; - if (this->isPBOSupported) { - glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, this->ref->pboRenderDataID[i]); - glReadPixels(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, 0); - glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); + glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0); } - this->gpuScreen3DHasNewData[i] = true; + this->_pixelReadNeedsFinish = true; return OGLERROR_NOERR; } Render3DError OpenGLRenderer_1_5::RenderFinish() { - const size_t i = this->doubleBufferIndex; - - if (!this->gpuScreen3DHasNewData[i]) + if (!this->_pixelReadNeedsFinish) { return OGLERROR_NOERR; } - OGLRenderRef &OGLRef = *this->ref; - if(!BEGINGL()) { return OGLERROR_BEGINGL_FAILED; @@ -2961,27 +2948,22 @@ Render3DError OpenGLRenderer_1_5::RenderFinish() if (this->isPBOSupported) { - glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, OGLRef.pboRenderDataID[i]); - - const u32 *__restrict mappedBufferPtr = (u32 *__restrict)glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY); + const FragmentColor *__restrict mappedBufferPtr = (FragmentColor *__restrict)glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY); if (mappedBufferPtr != NULL) { - this->ConvertFramebuffer(mappedBufferPtr, (u32 *)gfx3d_convertedScreen); + memcpy(this->_framebufferColor, mappedBufferPtr, this->_framebufferColorSizeBytes); glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB); } - - glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); } else { - u32 *__restrict workingBuffer = this->GPU_screen3D[i]; - glReadPixels(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, workingBuffer); - this->ConvertFramebuffer(workingBuffer, (u32 *)gfx3d_convertedScreen); + glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, this->_framebufferColor); } ENDGL(); - this->gpuScreen3DHasNewData[i] = false; + this->FlushFramebuffer((FragmentColor *)gfx3d_convertedScreen); + this->_pixelReadNeedsFinish = false; return OGLERROR_NOERR; } @@ -3392,7 +3374,6 @@ Render3DError OpenGLRenderer_2_0::DisableVertexAttributes() Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine) { OGLRenderRef &OGLRef = *this->ref; - this->doubleBufferIndex = (this->doubleBufferIndex + 1) & 0x01; if(!BEGINGL()) { @@ -3489,10 +3470,10 @@ Render3DError OpenGLRenderer_2_0::RenderEdgeMarking(const u16 *colorTable, const glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glUseProgram(OGLRef.programEdgeMarkID); - glUniform2f(OGLRef.uniformFramebufferSize, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glUniform2f(OGLRef.uniformFramebufferSize, this->_framebufferWidth, this->_framebufferHeight); glUniform4fv(OGLRef.uniformStateEdgeColor, 8, oglColor); - glViewport(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); glEnable(GL_BLEND); @@ -3559,7 +3540,7 @@ Render3DError OpenGLRenderer_2_0::RenderFog(const u8 *densityTable, const u32 co glUniform1f(OGLRef.uniformStateFogStep, oglFogStep); glUniform1fv(OGLRef.uniformStateFogDensity, 32, oglDensityTable); - glViewport(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); @@ -3737,22 +3718,15 @@ Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY &thePoly, bool enableT Render3DError OpenGLRenderer_2_1::ReadBackPixels() { - const size_t i = this->doubleBufferIndex; - - glBindBuffer(GL_PIXEL_PACK_BUFFER, this->ref->pboRenderDataID[i]); - glReadPixels(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, 0); - glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - - this->gpuScreen3DHasNewData[i] = true; + glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0); + this->_pixelReadNeedsFinish = true; return OGLERROR_NOERR; } Render3DError OpenGLRenderer_2_1::RenderFinish() { - const size_t i = this->doubleBufferIndex; - - if (!this->gpuScreen3DHasNewData[i]) + if (!this->_pixelReadNeedsFinish) { return OGLERROR_NOERR; } @@ -3762,20 +3736,17 @@ Render3DError OpenGLRenderer_2_1::RenderFinish() return OGLERROR_BEGINGL_FAILED; } - glBindBuffer(GL_PIXEL_PACK_BUFFER, this->ref->pboRenderDataID[i]); - - const u32 *__restrict mappedBufferPtr = (u32 *__restrict)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); + const FragmentColor *__restrict mappedBufferPtr = (FragmentColor *__restrict)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); if (mappedBufferPtr != NULL) { - this->ConvertFramebuffer(mappedBufferPtr, (u32 *)gfx3d_convertedScreen); + memcpy(this->_framebufferColor, mappedBufferPtr, this->_framebufferColorSizeBytes); glUnmapBuffer(GL_PIXEL_PACK_BUFFER); } - glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - ENDGL(); - this->gpuScreen3DHasNewData[i] = false; + this->FlushFramebuffer((FragmentColor *)gfx3d_convertedScreen); + this->_pixelReadNeedsFinish = false; return OGLERROR_NOERR; } diff --git a/desmume/src/OGLRender.h b/desmume/src/OGLRender.h index d9fde371c..f5c12587f 100644 --- a/desmume/src/OGLRender.h +++ b/desmume/src/OGLRender.h @@ -405,7 +405,7 @@ struct OGLRenderRef GLuint iboPostprocessIndexID; // PBO - GLuint pboRenderDataID[2]; + GLuint pboRenderDataID; // UBO / TBO GLuint uboRenderStatesID; @@ -482,6 +482,10 @@ struct OGLRenderRef // Client-side Buffers GLfloat *color4fBuffer; GLushort *vertIndexBuffer; + GLuint *workingDepthBuffer; + GLuint *workingDepthStencilBuffer; + GLuint *workingFogAttributesBuffer; + GLuint *workingPolyIDBuffer; // Vertex Attributes Pointers GLvoid *vtxPtrPosition; @@ -561,11 +565,11 @@ protected: // Textures TexCacheItem *currTexture; - CACHE_ALIGN u32 GPU_screen3D[2][GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT * sizeof(u32)]; - bool gpuScreen3DHasNewData[2]; - size_t doubleBufferIndex; + bool _pixelReadNeedsFinish; size_t _currentPolyIndex; + Render3DError FlushFramebuffer(FragmentColor *dstBuffer); + // OpenGL-specific methods virtual Render3DError CreateVBOs() = 0; virtual void DestroyVBOs() = 0; @@ -607,7 +611,7 @@ protected: public: OpenGLRenderer(); - virtual ~OpenGLRenderer() {}; + virtual ~OpenGLRenderer(); virtual Render3DError InitExtensions() = 0; virtual Render3DError DeleteTexture(const TexCacheItem *item) = 0; @@ -617,7 +621,6 @@ public: bool ValidateShaderProgramLink(GLuint theProgram) const; void GetVersion(unsigned int *major, unsigned int *minor, unsigned int *revision) const; void SetVersion(unsigned int major, unsigned int minor, unsigned int revision); - void ConvertFramebuffer(const u32 *__restrict srcBuffer, u32 *dstBuffer); }; class OpenGLRenderer_1_2 : public OpenGLRenderer @@ -681,6 +684,7 @@ public: virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer); virtual Render3DError Reset(); virtual Render3DError RenderFinish(); + virtual Render3DError SetFramebufferSize(size_t w, size_t h); virtual Render3DError DeleteTexture(const TexCacheItem *item); }; diff --git a/desmume/src/OGLRender_3_2.cpp b/desmume/src/OGLRender_3_2.cpp index 5541b6436..cf9ec6c9d 100644 --- a/desmume/src/OGLRender_3_2.cpp +++ b/desmume/src/OGLRender_3_2.cpp @@ -606,14 +606,14 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, this->_framebufferWidth, this->_framebufferHeight, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID); 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GDepth); glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthID); @@ -621,7 +621,7 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GPolyID); glBindTexture(GL_TEXTURE_2D, OGLRef.texGPolyID); @@ -629,7 +629,7 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FogAttr); glBindTexture(GL_TEXTURE_2D, OGLRef.texGFogAttrID); @@ -637,7 +637,7 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessFogID); @@ -645,7 +645,7 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); glBindTexture(GL_TEXTURE_2D, 0); @@ -769,15 +769,15 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO() glGenRenderbuffers(1, &OGLRef.rboMSGDepthStencilID); glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGColorID); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGDepthID); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGPolyID); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGFogAttrID); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGDepthStencilID); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_DEPTH24_STENCIL8, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_DEPTH24_STENCIL8, this->_framebufferWidth, this->_framebufferHeight); // Set up multisampled rendering FBO glGenFramebuffers(1, &OGLRef.fboMSIntermediateRenderID); @@ -1014,22 +1014,22 @@ Render3DError OpenGLRenderer_3_2::DownsampleFBO() // Blit the color buffer glReadBuffer(GL_COLOR_ATTACHMENT0); glDrawBuffer(GL_COLOR_ATTACHMENT0); - glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the working depth buffer glReadBuffer(GL_COLOR_ATTACHMENT1); glDrawBuffer(GL_COLOR_ATTACHMENT1); - glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the polygon ID buffer glReadBuffer(GL_COLOR_ATTACHMENT2); glDrawBuffer(GL_COLOR_ATTACHMENT2); - glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the fog buffer glReadBuffer(GL_COLOR_ATTACHMENT3); glDrawBuffer(GL_COLOR_ATTACHMENT3); - glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Reset framebuffer targets glReadBuffer(GL_COLOR_ATTACHMENT0); @@ -1043,7 +1043,6 @@ Render3DError OpenGLRenderer_3_2::DownsampleFBO() Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine) { OGLRenderRef &OGLRef = *this->ref; - this->doubleBufferIndex = (this->doubleBufferIndex + 1) & 0x01; if(!BEGINGL()) { @@ -1057,8 +1056,8 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine) glBindBuffer(GL_UNIFORM_BUFFER, OGLRef.uboRenderStatesID); OGLRenderStates *state = (OGLRenderStates *)glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(OGLRenderStates), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); - state->framebufferSize.x = GFX3D_FRAMEBUFFER_WIDTH; - state->framebufferSize.y = GFX3D_FRAMEBUFFER_HEIGHT; + state->framebufferSize.x = this->_framebufferWidth; + state->framebufferSize.y = this->_framebufferHeight; state->toonShadingMode = engine.renderState.shading; state->enableAlphaTest = (engine.renderState.enableAlphaTest) ? GL_TRUE : GL_FALSE; state->enableAntialiasing = (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE; @@ -1171,7 +1170,7 @@ Render3DError OpenGLRenderer_3_2::RenderEdgeMarking(const u16 *colorTable, const glDrawBuffer(GL_COLOR_ATTACHMENT0); glUseProgram(OGLRef.programEdgeMarkID); - glViewport(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); glEnable(GL_BLEND); @@ -1195,7 +1194,7 @@ Render3DError OpenGLRenderer_3_2::RenderFog(const u8 *densityTable, const u32 co glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID); glUseProgram(OGLRef.programFogID); - glViewport(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); @@ -1245,22 +1244,22 @@ Render3DError OpenGLRenderer_3_2::ClearUsingImage(const u16 *__restrict colorBuf // Blit the working depth buffer glReadBuffer(GL_COLOR_ATTACHMENT1); glDrawBuffer(GL_COLOR_ATTACHMENT1); - glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the polygon ID buffer glReadBuffer(GL_COLOR_ATTACHMENT2); glDrawBuffer(GL_COLOR_ATTACHMENT2); - glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the fog buffer glReadBuffer(GL_COLOR_ATTACHMENT3); glDrawBuffer(GL_COLOR_ATTACHMENT3); - glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); // Blit the color buffer. Do this last so that color attachment 0 is set to the read FBO. glReadBuffer(GL_COLOR_ATTACHMENT0); glDrawBuffer(GL_COLOR_ATTACHMENT0); - glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); } glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); diff --git a/desmume/src/gfx3d.cpp b/desmume/src/gfx3d.cpp index 3e16a0d62..2c81152dd 100644 --- a/desmume/src/gfx3d.cpp +++ b/desmume/src/gfx3d.cpp @@ -308,7 +308,10 @@ static float normalTable[1024]; #define fix2float(v) (((float)((s32)(v))) / (float)(1<<12)) #define fix10_2float(v) (((float)((s32)(v))) / (float)(1<<9)) -CACHE_ALIGN u8 gfx3d_convertedScreen[GFX3D_FRAMEBUFFER_WIDTH*GFX3D_FRAMEBUFFER_HEIGHT*4]; +// Color buffer that is filled by the 3D renderer and is read by the GPU engine. +u8 *gfx3d_convertedScreen = NULL; +static size_t gfx3d_framebufferWidth = GFX3D_FRAMEBUFFER_WIDTH; +static size_t gfx3d_framebufferHeight = GFX3D_FRAMEBUFFER_HEIGHT; // Matrix stack handling CACHE_ALIGN MatrixStack mtxStack[4] = { @@ -537,6 +540,14 @@ void gfx3d_init() vertlist = &vertlists[0]; } + gfx3d_framebufferWidth = GFX3D_FRAMEBUFFER_WIDTH; + gfx3d_framebufferHeight = GFX3D_FRAMEBUFFER_HEIGHT; + + if (gfx3d_convertedScreen == NULL) + { + gfx3d_convertedScreen = (u8 *)malloc(gfx3d_framebufferWidth * gfx3d_framebufferHeight * sizeof(FragmentColor)); + } + gfx3d.state.fogDensityTable = MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0360; gfx3d.state.edgeMarkColorTable = (u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0330); @@ -544,6 +555,20 @@ void gfx3d_init() gfx3d_reset(); } +void gfx3d_deinit() +{ + free(polylists); + polylists = NULL; + polylist = NULL; + + free(vertlists); + vertlists = NULL; + vertlist = NULL; + + free(gfx3d_convertedScreen); + gfx3d_convertedScreen = NULL; +} + void gfx3d_reset() { CurrentRenderer->RenderFinish(); @@ -616,7 +641,7 @@ void gfx3d_reset() last_s = 0; viewport = 0xBFFF0000; - memset(gfx3d_convertedScreen,0,sizeof(gfx3d_convertedScreen)); + memset(gfx3d_convertedScreen, 0, sizeof(gfx3d_framebufferWidth * gfx3d_framebufferHeight * sizeof(FragmentColor))); gfx3d.state.clearDepth = DS_DEPTH15TO24(0x7FFF); @@ -629,6 +654,31 @@ void gfx3d_reset() CurrentRenderer->Reset(); } +size_t gfx3d_getFramebufferWidth() +{ + return gfx3d_framebufferWidth; +} + +size_t gfx3d_getFramebufferHeight() +{ + return gfx3d_framebufferHeight; +} + +void gfx3d_setFramebufferSize(size_t w, size_t h) +{ + if (w < GFX3D_FRAMEBUFFER_WIDTH || h < GFX3D_FRAMEBUFFER_HEIGHT) + { + return; + } + + CurrentRenderer->RenderFinish(); + + gfx3d_framebufferWidth = w; + gfx3d_framebufferHeight = h; + gfx3d_convertedScreen = (u8 *)realloc(gfx3d_convertedScreen, w * h * sizeof(FragmentColor)); + + CurrentRenderer->SetFramebufferSize(w, h); +} //================================================================================= Geometry Engine //================================================================================= @@ -2282,7 +2332,7 @@ void gfx3d_VBlankEndSignal(bool skipFrame) if(!CommonSettings.showGpu.main) { - memset(gfx3d_convertedScreen,0,sizeof(gfx3d_convertedScreen)); + memset(gfx3d_convertedScreen, 0, sizeof(gfx3d_framebufferWidth * gfx3d_framebufferHeight * sizeof(FragmentColor))); return; } diff --git a/desmume/src/gfx3d.h b/desmume/src/gfx3d.h index 1ffdd2163..716b03c27 100644 --- a/desmume/src/gfx3d.h +++ b/desmume/src/gfx3d.h @@ -217,8 +217,13 @@ enum }; void gfx3d_init(); +void gfx3d_deinit(); void gfx3d_reset(); +size_t gfx3d_getFramebufferWidth(); +size_t gfx3d_getFramebufferHeight(); +void gfx3d_setFramebufferSize(size_t w, size_t h); + typedef struct { u8 enableLightFlags; @@ -715,9 +720,7 @@ extern CACHE_ALIGN const u8 material_3bit_to_8bit[8]; //these contain the 3d framebuffer converted into the most useful format //they are stored here instead of in the renderers in order to consolidate the buffers -extern CACHE_ALIGN u8 gfx3d_convertedScreen[GFX3D_FRAMEBUFFER_WIDTH*GFX3D_FRAMEBUFFER_HEIGHT*4]; -extern CACHE_ALIGN u8 gfx3d_convertedAlpha[GFX3D_FRAMEBUFFER_WIDTH*GFX3D_FRAMEBUFFER_HEIGHT*2]; //see cpp for explanation of illogical *2 - +extern u8 *gfx3d_convertedScreen; extern BOOL isSwapBuffers; int _hack_getMatrixStackLevel(int); diff --git a/desmume/src/rasterize.cpp b/desmume/src/rasterize.cpp index cfb755f48..18ad393dd 100644 --- a/desmume/src/rasterize.cpp +++ b/desmume/src/rasterize.cpp @@ -713,7 +713,7 @@ public: } //draws a single scanline - FORCEINLINE void drawscanline(const PolygonAttributes &polyAttr, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *pLeft, edge_fx_fl *pRight, bool lineHack) + FORCEINLINE void drawscanline(const PolygonAttributes &polyAttr, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *pLeft, edge_fx_fl *pRight, bool lineHack) { int XStart = pLeft->X; int width = pRight->X - XStart; @@ -755,20 +755,22 @@ public: //CONSIDER: in case some other math is wrong (shouldve been clipped OK), we might go out of bounds here. //better check the Y value. - if(RENDERER && (pLeft->Y<0 || pLeft->Y>191)) { + if (RENDERER && (pLeft->Y<0 || pLeft->Y > (framebufferHeight - 1))) + { printf("rasterizer rendering at y=%d! oops!\n",pLeft->Y); return; } - if(!RENDERER && (pLeft->Y<0 || pLeft->Y>=framebufferHeight)) { + if (!RENDERER && (pLeft->Y<0 || pLeft->Y >= framebufferHeight)) + { printf("rasterizer rendering at y=%d! oops!\n",pLeft->Y); return; } int x = XStart; - if(x<0) + if (x<0) { - if(RENDERER && !lineHack) + if (RENDERER && !lineHack) { printf("rasterizer rendering at x=%d! oops!\n",x); return; @@ -784,19 +786,19 @@ public: width -= -x; x = 0; } - if(x+width > (RENDERER?GFX3D_FRAMEBUFFER_WIDTH:framebufferWidth)) + if (x+width > framebufferWidth) { - if(RENDERER && !lineHack) + if (RENDERER && !lineHack) { printf("rasterizer rendering at x=%d! oops!\n",x+width-1); return; } - width = (RENDERER?GFX3D_FRAMEBUFFER_WIDTH:framebufferWidth)-x; + width = framebufferWidth - x; } - - while(width-- > 0) + + while (width-- > 0) { - pixel(polyAttr, this->_softRender->screenAttributes[adr], this->_softRender->screenColor[adr], color[0], color[1], color[2], u, v, 1.0f/invw, z); + pixel(polyAttr, this->_softRender->_framebufferAttributes[adr], dstColor[adr], color[0], color[1], color[2], u, v, 1.0f/invw, z); adr++; x++; @@ -812,7 +814,7 @@ public: //runs several scanlines, until an edge is finished template - void runscanlines(const PolygonAttributes &polyAttr, FragmentColor *color, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *left, edge_fx_fl *right, bool horizontal, bool lineHack) + void runscanlines(const PolygonAttributes &polyAttr, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *left, edge_fx_fl *right, bool horizontal, bool lineHack) { //oh lord, hack city for edge drawing @@ -821,16 +823,16 @@ public: bool first=true; //HACK: special handling for horizontal line poly - if (lineHack && left->Height == 0 && right->Height == 0 && left->YY>=0) + if (lineHack && left->Height == 0 && right->Height == 0 && left->YY>=0) { bool draw = (!SLI || (left->Y & SLI_MASK) == SLI_VALUE); - if(draw) drawscanline(polyAttr, framebufferWidth, framebufferHeight, left,right,lineHack); + if(draw) drawscanline(polyAttr, dstColor, framebufferWidth, framebufferHeight, left,right,lineHack); } while(Height--) { bool draw = (!SLI || (left->Y & SLI_MASK) == SLI_VALUE); - if(draw) drawscanline(polyAttr, framebufferWidth, framebufferHeight, left,right,lineHack); + if(draw) drawscanline(polyAttr, dstColor, framebufferWidth, framebufferHeight, left,right,lineHack); const int xl = left->X; const int xr = right->X; const int y = left->Y; @@ -855,9 +857,9 @@ public: for (int x = xs; x <= xe; x++) { int adr = (y*framebufferWidth)+x; - color[adr].r = 63; - color[adr].g = 0; - color[adr].b = 0; + dstColor[adr].r = 63; + dstColor[adr].g = 0; + dstColor[adr].b = 0; } } else if(bottom) @@ -867,9 +869,9 @@ public: for (int x = xs; x <= xe; x++) { int adr = (y*framebufferWidth)+x; - color[adr].r = 63; - color[adr].g = 0; - color[adr].b = 0; + dstColor[adr].r = 63; + dstColor[adr].g = 0; + dstColor[adr].b = 0; } } else @@ -879,18 +881,18 @@ public: for (int x = xs; x <= xe; x++) { int adr = (y*framebufferWidth)+x; - color[adr].r = 63; - color[adr].g = 0; - color[adr].b = 0; + dstColor[adr].r = 63; + dstColor[adr].g = 0; + dstColor[adr].b = 0; } xs = min(xr,nxr); xe = max(xr,nxr); for (int x = xs; x <= xe; x++) { int adr = (y*framebufferWidth)+x; - color[adr].r = 63; - color[adr].g = 0; - color[adr].b = 0; + dstColor[adr].r = 63; + dstColor[adr].g = 0; + dstColor[adr].b = 0; } } @@ -951,7 +953,7 @@ public: //I didnt reference anything for this algorithm but it seems like I've seen it somewhere before. //Maybe it is like crow's algorithm template - void shape_engine(const PolygonAttributes &polyAttr, FragmentColor *color, const size_t framebufferWidth, const size_t framebufferHeight, int type, const bool backwards, bool lineHack) + void shape_engine(const PolygonAttributes &polyAttr, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, int type, const bool backwards, bool lineHack) { bool failure = false; @@ -991,7 +993,7 @@ public: return; bool horizontal = left.Y == right.Y; - runscanlines(polyAttr, color, framebufferWidth, framebufferHeight, &left, &right, horizontal, lineHack); + runscanlines(polyAttr, dstColor, framebufferWidth, framebufferHeight, &left, &right, horizontal, lineHack); //if we ran out of an edge, step to the next one if (right.Height == 0) @@ -1013,6 +1015,10 @@ public: template FORCEINLINE void mainLoop() { + FragmentColor *dstColor = this->_softRender->GetFramebuffer(); + size_t dstWidth = this->_softRender->GetFramebufferWidth(); + size_t dstHeight = this->_softRender->GetFramebufferHeight(); + lastTexKey = NULL; PolygonAttributes polyAttr; @@ -1054,7 +1060,7 @@ public: for (int j = type; j < MAX_CLIPPED_VERTS; j++) this->verts[j] = NULL; - shape_engine(polyAttr, this->_softRender->screenColor, this->_softRender->_framebufferWidth, this->_softRender->_framebufferHeight, type, !this->_softRender->polyBackfacing[i], (thePoly->vtxFormat & 4) && CommonSettings.GFX3D_LineHack); + shape_engine(polyAttr, dstColor, dstWidth, dstHeight, type, !this->_softRender->polyBackfacing[i], (thePoly->vtxFormat & 4) && CommonSettings.GFX3D_LineHack); } } @@ -1154,10 +1160,7 @@ SoftRasterizerRenderer::SoftRasterizerRenderer() _stateSetupNeedsFinish = false; _renderGeometryNeedsFinish = false; - _framebufferWidth = GFX3D_FRAMEBUFFER_WIDTH; - _framebufferHeight = GFX3D_FRAMEBUFFER_HEIGHT; - screenAttributes = (FragmentAttributes *)malloc(_framebufferWidth * _framebufferHeight * sizeof(FragmentAttributes)); - screenColor = (FragmentColor *)malloc(_framebufferWidth * _framebufferHeight * sizeof(FragmentColor)); + _framebufferAttributes = (FragmentAttributes *)calloc(_framebufferWidth * _framebufferHeight, sizeof(FragmentAttributes)); if (!rasterizerUnitTasksInited) { @@ -1232,8 +1235,7 @@ SoftRasterizerRenderer::~SoftRasterizerRenderer() delete[] postprocessParam; postprocessParam = NULL; - free(screenAttributes); - free(screenColor); + free(_framebufferAttributes); } Render3DError SoftRasterizerRenderer::InitTables() @@ -1302,8 +1304,8 @@ template void SoftRasterizerRenderer::performViewportTransforms() { const float xfactor = (float)this->_framebufferWidth/(float)GFX3D_FRAMEBUFFER_WIDTH; const float yfactor = (float)this->_framebufferHeight/(float)GFX3D_FRAMEBUFFER_HEIGHT; - const float xmax = GFX3D_FRAMEBUFFER_WIDTH*xfactor-(CUSTOM?0.001f:0); //fudge factor to keep from overrunning render buffers - const float ymax = GFX3D_FRAMEBUFFER_HEIGHT*yfactor-(CUSTOM?0.001f:0); + const float xmax = (float)this->_framebufferWidth-(CUSTOM?0.001f:0); //fudge factor to keep from overrunning render buffers + const float ymax = (float)this->_framebufferHeight-(CUSTOM?0.001f:0); //viewport transforms for (size_t i = 0; i < this->_clippedPolyCount; i++) @@ -1558,7 +1560,7 @@ Render3DError SoftRasterizerRenderer::RenderEdgeMarking(const u16 *colorTable, c { for (size_t x = 0; x < this->_framebufferWidth; x++, i++) { - const FragmentAttributes dstAttributes = this->screenAttributes[i]; + const FragmentAttributes dstAttributes = this->_framebufferAttributes[i]; const u8 polyID = dstAttributes.opaquePolyID; if(this->edgeMarkDisabled[polyID>>3]) continue; @@ -1572,8 +1574,8 @@ Render3DError SoftRasterizerRenderer::RenderEdgeMarking(const u16 *colorTable, c FragmentColor edgeColor = this->edgeMarkTable[polyID>>3]; #define PIXOFFSET(dx,dy) ((dx)+(this->_framebufferWidth*(dy))) -#define ISEDGE(dx,dy) ((x+(dx) < this->_framebufferWidth) && (y+(dy) < this->_framebufferHeight) && polyID > this->screenAttributes[i+PIXOFFSET(dx,dy)].opaquePolyID) -#define DRAWEDGE(dx,dy) alphaBlend(screenColor[i+PIXOFFSET(dx,dy)], edgeColor) +#define ISEDGE(dx,dy) ((x+(dx) < this->_framebufferWidth) && (y+(dy) < this->_framebufferHeight) && polyID > this->_framebufferAttributes[i+PIXOFFSET(dx,dy)].opaquePolyID) +#define DRAWEDGE(dx,dy) alphaBlend(_framebufferColor[i+PIXOFFSET(dx,dy)], edgeColor) bool upleft = ISEDGE(-1,-1); bool up = ISEDGE( 0,-1); @@ -1714,12 +1716,12 @@ Render3DError SoftRasterizerRenderer::RenderFog(const u8 *densityTable, const u3 { for (size_t i = 0; i < framebufferFragmentCount; i++) { - const FragmentAttributes &destFragment = screenAttributes[i]; + const FragmentAttributes &destFragment = _framebufferAttributes[i]; const size_t fogIndex = destFragment.depth >> 9; assert(fogIndex < 32768); const u8 fog = (destFragment.isFogged) ? this->fogTable[fogIndex] : 0; - FragmentColor &destFragmentColor = screenColor[i]; + FragmentColor &destFragmentColor = _framebufferColor[i]; destFragmentColor.r = ((128-fog)*destFragmentColor.r + r*fog)>>7; destFragmentColor.g = ((128-fog)*destFragmentColor.g + g*fog)>>7; destFragmentColor.b = ((128-fog)*destFragmentColor.b + b*fog)>>7; @@ -1730,12 +1732,12 @@ Render3DError SoftRasterizerRenderer::RenderFog(const u8 *densityTable, const u3 { for (size_t i = 0; i < framebufferFragmentCount; i++) { - const FragmentAttributes &destFragment = screenAttributes[i]; + const FragmentAttributes &destFragment = _framebufferAttributes[i]; const size_t fogIndex = destFragment.depth >> 9; assert(fogIndex < 32768); const u8 fog = (destFragment.isFogged) ? this->fogTable[fogIndex] : 0; - FragmentColor &destFragmentColor = screenColor[i]; + FragmentColor &destFragmentColor = _framebufferColor[i]; destFragmentColor.a = ((128-fog)*destFragmentColor.a + a*fog)>>7; } } @@ -1749,8 +1751,8 @@ Render3DError SoftRasterizerRenderer::RenderEdgeMarkingAndFog(const SoftRasteriz { for (size_t x = 0; x < this->_framebufferWidth; x++, i++) { - FragmentColor &dstColor = screenColor[i]; - const FragmentAttributes dstAttributes = this->screenAttributes[i]; + FragmentColor &dstColor = _framebufferColor[i]; + const FragmentAttributes dstAttributes = this->_framebufferAttributes[i]; const u32 depth = dstAttributes.depth; const u8 polyID = dstAttributes.opaquePolyID; @@ -1772,7 +1774,7 @@ Render3DError SoftRasterizerRenderer::RenderEdgeMarkingAndFog(const SoftRasteriz bool up = false; #define PIXOFFSET(dx,dy) ((dx)+(this->_framebufferWidth*(dy))) -#define ISEDGE(dx,dy) ((x+(dx) < this->_framebufferWidth) && (y+(dy) < this->_framebufferHeight) && polyID != this->screenAttributes[i+PIXOFFSET(dx,dy)].opaquePolyID && depth >= this->screenAttributes[i+PIXOFFSET(dx,dy)].depth) +#define ISEDGE(dx,dy) ((x+(dx) < this->_framebufferWidth) && (y+(dy) < this->_framebufferHeight) && polyID != this->_framebufferAttributes[i+PIXOFFSET(dx,dy)].opaquePolyID && depth >= this->_framebufferAttributes[i+PIXOFFSET(dx,dy)].depth) up = ISEDGE( 0,-1); left = ISEDGE(-1, 0); @@ -1784,22 +1786,22 @@ Render3DError SoftRasterizerRenderer::RenderEdgeMarkingAndFog(const SoftRasteriz if (right) { - edgeColor = this->edgeMarkTable[this->screenAttributes[i+PIXOFFSET( 1, 0)].opaquePolyID >> 3]; + edgeColor = this->edgeMarkTable[this->_framebufferAttributes[i+PIXOFFSET( 1, 0)].opaquePolyID >> 3]; alphaBlend(dstColor, edgeColor); } else if (down) { - edgeColor = this->edgeMarkTable[this->screenAttributes[i+PIXOFFSET( 0, 1)].opaquePolyID >> 3]; + edgeColor = this->edgeMarkTable[this->_framebufferAttributes[i+PIXOFFSET( 0, 1)].opaquePolyID >> 3]; alphaBlend(dstColor, edgeColor); } else if (left) { - edgeColor = this->edgeMarkTable[this->screenAttributes[i+PIXOFFSET(-1, 0)].opaquePolyID >> 3]; + edgeColor = this->edgeMarkTable[this->_framebufferAttributes[i+PIXOFFSET(-1, 0)].opaquePolyID >> 3]; alphaBlend(dstColor, edgeColor); } else if (up) { - edgeColor = this->edgeMarkTable[this->screenAttributes[i+PIXOFFSET( 0,-1)].opaquePolyID >> 3]; + edgeColor = this->edgeMarkTable[this->_framebufferAttributes[i+PIXOFFSET( 0,-1)].opaquePolyID >> 3]; alphaBlend(dstColor, edgeColor); } @@ -1865,13 +1867,13 @@ Render3DError SoftRasterizerRenderer::ClearUsingImage(const u16 *__restrict colo size_t ir = x + (y * this->_framebufferWidth); size_t iw = x + ((this->_framebufferHeight - 1 - y) * this->_framebufferWidth); - ((u32 *)this->screenColor)[iw] = RGB15TO6665(colorBuffer[ir] & 0x7FFF, (colorBuffer[ir] >> 15) * 31); - this->screenAttributes[iw].isFogged = fogBuffer[ir]; - this->screenAttributes[iw].depth = depthBuffer[ir]; - this->screenAttributes[iw].opaquePolyID = polyIDBuffer[ir]; - this->screenAttributes[iw].translucentPolyID = kUnsetTranslucentPolyID; - this->screenAttributes[iw].isTranslucentPoly = false; - this->screenAttributes[iw].stencil = 0; + this->_framebufferColor[iw].color = RGB15TO6665(colorBuffer[ir] & 0x7FFF, (colorBuffer[ir] >> 15) * 31); + this->_framebufferAttributes[iw].isFogged = fogBuffer[ir]; + this->_framebufferAttributes[iw].depth = depthBuffer[ir]; + this->_framebufferAttributes[iw].opaquePolyID = polyIDBuffer[ir]; + this->_framebufferAttributes[iw].translucentPolyID = kUnsetTranslucentPolyID; + this->_framebufferAttributes[iw].isTranslucentPoly = false; + this->_framebufferAttributes[iw].stencil = 0; } } @@ -1888,8 +1890,8 @@ Render3DError SoftRasterizerRenderer::ClearUsingValues(const FragmentColor &clea for (size_t i = 0; i < (this->_framebufferWidth * this->_framebufferHeight); i++) { - this->screenAttributes[i] = clearAttributes; - this->screenColor[i] = convertedClearColor; + this->_framebufferAttributes[i] = clearAttributes; + this->_framebufferColor[i] = convertedClearColor; } return RENDER3DERROR_NOERR; @@ -1957,7 +1959,7 @@ Render3DError SoftRasterizerRenderer::EndRender(const u64 frameCount) this->RenderEdgeMarkingAndFog(this->postprocessParam[0]); } - memcpy(gfx3d_convertedScreen, this->screenColor, this->_framebufferWidth * this->_framebufferHeight * sizeof(FragmentColor)); + this->FlushFramebuffer((FragmentColor *)gfx3d_convertedScreen); } return RENDER3DERROR_NOERR; @@ -1997,7 +1999,19 @@ Render3DError SoftRasterizerRenderer::RenderFinish() } } - memcpy(gfx3d_convertedScreen, this->screenColor, this->_framebufferWidth * this->_framebufferHeight * sizeof(FragmentColor)); + this->FlushFramebuffer((FragmentColor *)gfx3d_convertedScreen); + + return RENDER3DERROR_NOERR; +} + +Render3DError SoftRasterizerRenderer::SetFramebufferSize(size_t w, size_t h) +{ + if (w < GFX3D_FRAMEBUFFER_WIDTH || h < GFX3D_FRAMEBUFFER_HEIGHT) + { + return RENDER3DERROR_NOERR; + } + + // TODO: We're not prepared to do this yet, so do nothing for now. return RENDER3DERROR_NOERR; } diff --git a/desmume/src/rasterize.h b/desmume/src/rasterize.h index 6d5e2f4e3..ea1112fc0 100644 --- a/desmume/src/rasterize.h +++ b/desmume/src/rasterize.h @@ -68,13 +68,10 @@ public: size_t _clippedPolyCount; FragmentColor toonColor32LUT[32]; GFX3D_Clipper::TClippedPoly *clippedPolys; - FragmentAttributes *screenAttributes; - FragmentColor *screenColor; + FragmentAttributes *_framebufferAttributes; TexCacheItem *polyTexKeys[POLYLIST_SIZE]; bool polyVisible[POLYLIST_SIZE]; bool polyBackfacing[POLYLIST_SIZE]; - size_t _framebufferWidth; - size_t _framebufferHeight; GFX3D_State *currentRenderState; SoftRasterizerPostProcessParams *postprocessParam; @@ -94,6 +91,7 @@ public: virtual Render3DError Reset(); virtual Render3DError Render(const GFX3D &engine); virtual Render3DError RenderFinish(); + virtual Render3DError SetFramebufferSize(size_t w, size_t h); }; #endif diff --git a/desmume/src/render3D.cpp b/desmume/src/render3D.cpp index 61e5c9bef..d53326626 100644 --- a/desmume/src/render3D.cpp +++ b/desmume/src/render3D.cpp @@ -125,11 +125,17 @@ Render3D::Render3D() needTableInit = false; } + _framebufferWidth = GFX3D_FRAMEBUFFER_WIDTH; + _framebufferHeight = GFX3D_FRAMEBUFFER_HEIGHT; + _framebufferColorSizeBytes = _framebufferWidth * _framebufferHeight * sizeof(FragmentColor); + _framebufferColor = (FragmentColor *)calloc(_framebufferWidth * _framebufferHeight, sizeof(FragmentColor)); + Reset(); } Render3D::~Render3D() { + free(_framebufferColor); TexCache_Reset(); } @@ -143,6 +149,38 @@ std::string Render3D::GetName() return this->_renderName; } +FragmentColor* Render3D::GetFramebuffer() +{ + return this->_framebufferColor; +} + +size_t Render3D::GetFramebufferWidth() +{ + return this->_framebufferWidth; +} + +size_t Render3D::GetFramebufferHeight() +{ + return this->_framebufferHeight; +} + +Render3DError Render3D::SetFramebufferSize(size_t w, size_t h) +{ + if (w < GFX3D_FRAMEBUFFER_WIDTH || h < GFX3D_FRAMEBUFFER_HEIGHT) + { + return RENDER3DERROR_NOERR; + } + + this->RenderFinish(); + + this->_framebufferWidth = w; + this->_framebufferHeight = h; + this->_framebufferColorSizeBytes = w * h * sizeof(FragmentColor); + this->_framebufferColor = (FragmentColor *)realloc(this->_framebufferColor, w * h * sizeof(FragmentColor)); + + return RENDER3DERROR_NOERR; +} + Render3DError Render3D::BeginRender(const GFX3D &engine) { return RENDER3DERROR_NOERR; @@ -168,6 +206,12 @@ Render3DError Render3D::EndRender(const u64 frameCount) return RENDER3DERROR_NOERR; } +Render3DError Render3D::FlushFramebuffer(FragmentColor *dstBuffer) +{ + memcpy(dstBuffer, this->_framebufferColor, this->_framebufferColorSizeBytes); + return RENDER3DERROR_NOERR; +} + Render3DError Render3D::UpdateToonTable(const u16 *toonTableBuffer) { return RENDER3DERROR_NOERR; @@ -274,6 +318,7 @@ Render3DError Render3D::SetupViewport(const u32 viewportValue) Render3DError Render3D::Reset() { + memset(this->_framebufferColor, 0, this->_framebufferColorSizeBytes); memset(this->clearImageColor16Buffer, 0, sizeof(this->clearImageColor16Buffer)); memset(this->clearImageDepthBuffer, 0, sizeof(this->clearImageDepthBuffer)); memset(this->clearImagePolyIDBuffer, 0, sizeof(this->clearImagePolyIDBuffer)); @@ -316,7 +361,7 @@ Render3DError Render3D::Render(const GFX3D &engine) Render3DError Render3D::RenderFinish() { - memset(gfx3d_convertedScreen, 0, sizeof(gfx3d_convertedScreen)); + this->FlushFramebuffer((FragmentColor *)gfx3d_convertedScreen); return RENDER3DERROR_NOERR; } diff --git a/desmume/src/render3D.h b/desmume/src/render3D.h index 2b549f3e2..a1121c5e9 100644 --- a/desmume/src/render3D.h +++ b/desmume/src/render3D.h @@ -103,6 +103,11 @@ protected: RendererID _renderID; std::string _renderName; + size_t _framebufferWidth; + size_t _framebufferHeight; + size_t _framebufferColorSizeBytes; + FragmentColor *_framebufferColor; + CACHE_ALIGN u16 clearImageColor16Buffer[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; CACHE_ALIGN u32 clearImageDepthBuffer[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; CACHE_ALIGN bool clearImageFogBuffer[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; @@ -113,6 +118,7 @@ protected: virtual Render3DError RenderEdgeMarking(const u16 *colorTable, const bool useAntialias); virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly); virtual Render3DError EndRender(const u64 frameCount); + virtual Render3DError FlushFramebuffer(FragmentColor *dstBuffer); virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const bool *__restrict fogBuffer, const u8 *__restrict polyIDBuffer); virtual Render3DError ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const; @@ -128,6 +134,10 @@ public: RendererID GetRenderID(); std::string GetName(); + FragmentColor* GetFramebuffer(); + size_t GetFramebufferWidth(); + size_t GetFramebufferHeight(); + virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer); virtual Render3DError ClearFramebuffer(const GFX3D_State &renderState); @@ -140,6 +150,8 @@ public: // sure to always call this function.) virtual Render3DError VramReconfigureSignal(); // Called when the emulator reconfigures its VRAM. You may need to invalidate your texture cache. + + virtual Render3DError SetFramebufferSize(size_t w, size_t h); // Called whenever the output framebuffer size changes. }; #endif