From 797dfad57edb2e52c609f6f512a32b62a4b00510 Mon Sep 17 00:00:00 2001 From: Sergey Lipskiy Date: Sun, 2 Jun 2013 22:20:44 +0700 Subject: [PATCH] Frame buffer related fixes. Zelda OOT pause screen works! --- DepthBuffer.cpp | 11 +++++++++++ FrameBuffer.cpp | 44 ++++++++++++++++++++++++++++++++++---------- OpenGL.cpp | 27 +++++++++++++++++++++------ gDP.cpp | 21 +++++++++++++-------- 4 files changed, 79 insertions(+), 24 deletions(-) diff --git a/DepthBuffer.cpp b/DepthBuffer.cpp index 7ced19ec..8828be47 100644 --- a/DepthBuffer.cpp +++ b/DepthBuffer.cpp @@ -136,6 +136,13 @@ void DepthBuffer_Destroy() void DepthBuffer_SetBuffer( u32 address ) { + const FrameBuffer * pFrameBuffer = FrameBuffer_FindBuffer(address); + bool bNeedClear = false; + if (pFrameBuffer != NULL) { + bNeedClear = pFrameBuffer->changed > 0; +// FrameBuffer_RemoveBuffer(address); + } + DepthBuffer *current = depthBuffer.top; // Search through saved depth buffers @@ -150,6 +157,8 @@ void DepthBuffer_SetBuffer( u32 address ) ogl_glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, current->renderbuf); GLuint attachments[2] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT }; ogl_glDrawBuffers(2, attachments, frameBuffer.top->texture->glName); + if (bNeedClear) + OGL_ClearDepthBuffer(); } #ifdef DEBUG DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "DepthBuffer_SetBuffer( 0x%08X ); color buffer is 0x%08X\n", @@ -176,6 +185,8 @@ void DepthBuffer_SetBuffer( u32 address ) ogl_glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, current->renderbuf); GLuint attachments[2] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT }; ogl_glDrawBuffers(2, attachments, frameBuffer.top->texture->glName); + if (bNeedClear) + OGL_ClearDepthBuffer(); } #ifdef DEBUG diff --git a/FrameBuffer.cpp b/FrameBuffer.cpp index 09193ba7..d57859fc 100644 --- a/FrameBuffer.cpp +++ b/FrameBuffer.cpp @@ -156,16 +156,18 @@ void FrameBuffer_Destroy() void FrameBuffer_SaveBuffer( u32 address, u16 size, u16 width, u16 height ) { frameBuffer.drawBuffer = GL_DRAW_FRAMEBUFFER; - FrameBuffer *current = frameBuffer.top; + //DepthBuffer_RemoveBuffer( address ); + FrameBuffer *current = frameBuffer.top; // Search through saved frame buffers while (current != NULL) { if ((current->startAddress <= address) && (current->endAddress >= address)) { - if ((current->width != width) || - (current->height != height) || + if ((current->startAddress != address) || + (current->width != width) || + //(current->height != height) || (current->size != size) || // TODO FIX ME (current->scaleX != OGL.scaleX) || (current->scaleY != OGL.scaleY)) @@ -174,11 +176,9 @@ void FrameBuffer_SaveBuffer( u32 address, u16 size, u16 width, u16 height ) break; } - current->startAddress = address; - current->endAddress = address + ((width * height << size >> 1) - 1); - current->texture->address = current->startAddress; ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, current->fbo); + if (depthBuffer.top != NULL && depthBuffer.top->renderbuf > 0) { ogl_glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer.top->renderbuf); ogl_glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer.top->renderbuf); @@ -229,8 +229,8 @@ void FrameBuffer_SaveBuffer( u32 address, u16 size, u16 width, u16 height ) current->texture->maskT = 0; current->texture->mirrorS = 0; current->texture->mirrorT = 0; - current->texture->realWidth = (u32)pow2( current->width * OGL.scaleX ); - current->texture->realHeight = (u32)pow2( current->height * OGL.scaleY ); + current->texture->realWidth = (u32)pow2( current->texture->width ); + current->texture->realHeight = (u32)pow2( current->texture->height ); current->texture->textureBytes = current->texture->realWidth * current->texture->realHeight * 4; cache.cachedBytes += current->texture->textureBytes; @@ -281,12 +281,23 @@ void FrameBuffer_RenderBuffer( u32 address ) ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glDrawBuffer( GL_FRONT ); ogl_glBlitFramebuffer( - 0, 0, min(OGL.width, current->texture->realWidth), min(OGL.height, current->texture->realHeight), +// 0, 0, current->texture->realWidth, current->texture->realHeight, + 0, 0, OGL.width, OGL.height, 0, OGL.heightOffset, OGL.width, OGL.height+OGL.heightOffset, GL_COLOR_BUFFER_BIT, GL_LINEAR ); glDrawBuffer( GL_BACK ); ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer.top->fbo); + /* + current = current->lower; + while (current != NULL) + { + if ((current->startAddress <= address) && + (current->endAddress >= address)) + assert(false); + current = current->lower; + } + */ return; } current = current->lower; @@ -303,6 +314,19 @@ void FrameBuffer_RenderBuffer( u32 address ) if ((current->startAddress <= address) && (current->endAddress >= address)) { + /* + float fill_color[4] = {1.0f, 0.0f, 0.0f, 1.0f}; + ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, current->fbo); + ogl_glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer.top->renderbuf); + ogl_glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer.top->renderbuf); + GLuint attachments[2] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT }; + ogl_glDrawBuffers(2, attachments, current->texture->glName); + assert(checkFBO()); + OGL_ClearDepthBuffer(); + OGL_ClearColorBuffer(fill_color); + ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer.top->fbo); + */ + glPushAttrib( GL_ENABLE_BIT | GL_VIEWPORT_BIT ); Combiner_BeginTextureUpdate(); @@ -509,6 +533,6 @@ void FrameBuffer_ActivateBufferTexture( s16 t, FrameBuffer *buffer ) buffer->texture->offsetT = (float)buffer->height - (gDP.textureImage.address - buffer->startAddress) / (buffer->width << buffer->size >> 1); } - FrameBuffer_MoveToTop( buffer ); +// FrameBuffer_RenderBuffer(buffer->startAddress); TextureCache_ActivateTexture( t, buffer->texture ); } diff --git a/OpenGL.cpp b/OpenGL.cpp index 97afe8f0..3342bd45 100644 --- a/OpenGL.cpp +++ b/OpenGL.cpp @@ -579,8 +579,13 @@ void OGL_UpdateCullFace() void OGL_UpdateViewport() { - glViewport( gSP.viewport.x * OGL.scaleX, (VI.height - (gSP.viewport.y + gSP.viewport.height)) * OGL.scaleY + (frameBuffer.drawBuffer == GL_BACK ? OGL.heightOffset : 0), + if (frameBuffer.drawBuffer == GL_BACK) + glViewport( gSP.viewport.x * OGL.scaleX, (VI.height - (gSP.viewport.y + gSP.viewport.height)) * OGL.scaleY + OGL.heightOffset, gSP.viewport.width * OGL.scaleX, gSP.viewport.height * OGL.scaleY ); + else + glViewport( gSP.viewport.x * OGL.scaleX, (frameBuffer.top->height - (gSP.viewport.y + gSP.viewport.height)) * OGL.scaleY, + gSP.viewport.width * OGL.scaleX, gSP.viewport.height * OGL.scaleY ); + glDepthRange( 0.0f, 1.0f );//gSP.viewport.nearz, gSP.viewport.farz ); } @@ -657,7 +662,8 @@ void OGL_UpdateStates() if (gDP.changed & CHANGED_SCISSOR) { - glScissor( gDP.scissor.ulx * OGL.scaleX, (VI.height - gDP.scissor.lry) * OGL.scaleY + (frameBuffer.drawBuffer == GL_BACK ? OGL.heightOffset : 0), + const u32 screenHeight = (frameBuffer.top == NULL || frameBuffer.drawBuffer == GL_BACK) ? VI.height : frameBuffer.top->height; + glScissor( gDP.scissor.ulx * OGL.scaleX, (screenHeight - gDP.scissor.lry) * OGL.scaleY + (frameBuffer.drawBuffer == GL_BACK ? OGL.heightOffset : 0), (gDP.scissor.lrx - gDP.scissor.ulx) * OGL.scaleX, (gDP.scissor.lry - gDP.scissor.uly) * OGL.scaleY ); } @@ -929,6 +935,11 @@ void OGL_DrawRect( int ulx, int uly, int lrx, int lry, float *color ) glDisable( GL_CULL_FACE ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); + u32 width = VI.width, height = VI.height; + if (frameBuffer.top != NULL && frameBuffer.drawBuffer != GL_BACK) { + width = frameBuffer.top->width; + height = frameBuffer.top->height; + } glOrtho( 0, VI.width, VI.height, 0, 1.0f, -1.0f ); glViewport( 0, (frameBuffer.drawBuffer == GL_BACK ? OGL.heightOffset : 0), OGL.width, OGL.height ); glDepthRange( 0.0f, 1.0f ); @@ -960,10 +971,14 @@ void OGL_DrawTexturedRect( float ulx, float uly, float lrx, float lry, float uls glDisable( GL_CULL_FACE ); glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - glOrtho( 0, VI.width, VI.height, 0, 1.0f, -1.0f ); - glViewport( 0, (frameBuffer.drawBuffer == GL_BACK ? OGL.heightOffset : 0), OGL.width, OGL.height ); - + glLoadIdentity(); + if (frameBuffer.drawBuffer != GL_DRAW_FRAMEBUFFER) { + glOrtho( 0, VI.width, VI.height, 0, 1.0f, -1.0f ); + glViewport( 0, (frameBuffer.drawBuffer == GL_BACK ? OGL.heightOffset : 0), OGL.width, OGL.height ); + } else { + glOrtho( 0, frameBuffer.top->width, frameBuffer.top->height, 0, 1.0f, -1.0f ); + glViewport( 0, 0, frameBuffer.top->width*frameBuffer.top->scaleX, frameBuffer.top->height*frameBuffer.top->scaleY ); + } if (combiner.usesT0) { rect[0].s0 = rect[0].s0 * cache.current[0]->shiftScaleS - gSP.textureTile[0]->fuls; diff --git a/gDP.cpp b/gDP.cpp index 1af7803a..268302d1 100644 --- a/gDP.cpp +++ b/gDP.cpp @@ -346,12 +346,17 @@ void gDPSetColorImage( u32 format, u32 size, u32 width, u32 address ) }*/ address = RSP_SegmentToPhysical( address ); - if (gDP.colorImage.address != address) + if (gDP.colorImage.address != address || gDP.colorImage.width != width) { - if (OGL.frameBufferTextures && address != gDP.depthImageAddress) + if (width >= gDP.scissor.lrx-1 && width <= gDP.scissor.lrx+1) + gDP.colorImage.height = gDP.scissor.lry; + else if (width >= gSP.viewport.width-1 && width <= gSP.viewport.width+1) + gDP.colorImage.height = gSP.viewport.height; + + if (OGL.frameBufferTextures)// && address != gDP.depthImageAddress) { //if (gDP.colorImage.changed) - FrameBuffer_SaveBuffer( address, (u16)size, (u16)width, width == VI.width ? (u16)VI.height : 1 ); + FrameBuffer_SaveBuffer( address, (u16)size, (u16)width, gDP.colorImage.height ); //if (address != gDP.depthImageAddress) //FrameBuffer_RestoreBuffer( address, (u16)size, (u16)width ); @@ -361,10 +366,10 @@ void gDPSetColorImage( u32 format, u32 size, u32 width, u32 address ) gDP.colorImage.changed = FALSE; - if (width == VI.width) - gDP.colorImage.height = VI.height; - else - gDP.colorImage.height = 1; +// if (width == VI.width) +// gDP.colorImage.height = VI.height; +// else +// gDP.colorImage.height = 1; } gDP.colorImage.format = format; @@ -871,7 +876,7 @@ void gDPTextureRectangle( f32 ulx, f32 uly, f32 lrx, f32 lry, s32 tile, f32 s, f gSP.textureTile[0] = &gDP.tiles[gSP.texture.tile]; gSP.textureTile[1] = &gDP.tiles[gSP.texture.tile < 7 ? gSP.texture.tile + 1 : gSP.texture.tile]; - if (depthBuffer.current) depthBuffer.current->cleared = FALSE; + if (depthBuffer.top) depthBuffer.top->cleared = FALSE; gDP.colorImage.changed = TRUE; gDP.colorImage.height = max( gDP.colorImage.height, (u32)gDP.scissor.lry );