From 2c7a08fc6198a2b44c78a0fca9903946da501a80 Mon Sep 17 00:00:00 2001 From: Rodolfo Osvaldo Bogado Date: Wed, 19 May 2010 03:15:36 +0000 Subject: [PATCH] after a good commit lets make some experiments: implemented fixed efb scale to improve alignment and discard some error caused by incorrect scale. make both plugins work similar. this must improve opengl image quality a lot. also implemented dynamic resizing in opengl, this way the resolution math the windows resolution on resize. this is highly experimental so please test a lot. implemented shader dumping on error thinking in future experiments with shaders. enjoy :) git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5458 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/VideoCommon/Src/Render.h | 3 + .../Src/FramebufferManager.cpp | 13 +- .../Plugin_VideoDX9/Src/PixelShaderCache.cpp | 4 + Source/Plugins/Plugin_VideoDX9/Src/Render.cpp | 79 +++--- .../Plugin_VideoDX9/Src/TextureCache.cpp | 13 +- .../Src/FramebufferManager.cpp | 8 +- .../Plugin_VideoOGL/Src/PixelShaderCache.cpp | 4 + Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 248 +++++++++++++----- .../Plugin_VideoOGL/Src/TextureConverter.cpp | 2 +- 9 files changed, 249 insertions(+), 125 deletions(-) diff --git a/Source/Core/VideoCommon/Src/Render.h b/Source/Core/VideoCommon/Src/Render.h index b009b65ff3..37350e08c4 100644 --- a/Source/Core/VideoCommon/Src/Render.h +++ b/Source/Core/VideoCommon/Src/Render.h @@ -79,6 +79,9 @@ public: static float GetTargetScaleX(); static float GetTargetScaleY(); + static float GetXFBScaleX(); + static float GetXFBScaleY(); + static TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc); static u32 AccessEFB(EFBAccessType type, int x, int y); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp index 9119bb596e..7c5b4555dd 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp @@ -322,27 +322,28 @@ void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight it--; } - float MultiSampleCompensation = 1.0f; + float SuperSampleCompensation = 1.0f; + float scaleX = Renderer::GetXFBScaleX(); + float scaleY = Renderer::GetXFBScaleY(); if(g_ActiveConfig.iMultisampleMode > 0 && g_ActiveConfig.iMultisampleMode < 4) { switch (g_ActiveConfig.iMultisampleMode) { case 1: - MultiSampleCompensation = 2.0f/3.0f; break; case 2: - MultiSampleCompensation = 0.5f; + SuperSampleCompensation = 0.5f; break; case 3: - MultiSampleCompensation = 1.0f/3.0f; + SuperSampleCompensation = 1.0f/3.0f; break; default: break; }; } - float scaleX = Renderer::GetTargetScaleX() * MultiSampleCompensation ; - float scaleY = Renderer::GetTargetScaleY() * MultiSampleCompensation; + scaleX *= SuperSampleCompensation ; + scaleY *= SuperSampleCompensation; TargetRectangle targetSource,efbSource; efbSource = Renderer::ConvertEFBRectangle(sourceRc); targetSource.top = (sourceRc.top *scaleY); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp index 84985d8f4f..5a8447260b 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp @@ -397,6 +397,10 @@ bool PixelShaderCache::SetShader(bool dstAlpha) if (g_ActiveConfig.bShowShaderErrors) { PanicAlert("Failed to compile Pixel Shader:\n\n%s", code); + static int counter = 0; + char szTemp[MAX_PATH]; + sprintf(szTemp, "%sBADps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++); + SaveData(szTemp, code); } return false; } diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 9808ba9f38..77abe85a7b 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -69,6 +69,9 @@ static int s_XFB_height; static float xScale; static float yScale; +static int EFBxScale; +static int EFByScale; + static int s_recordWidth; static int s_recordHeight; @@ -303,28 +306,17 @@ bool Renderer::Init() yScale = (float)(dst_rect.bottom - dst_rect.top) / (float)s_XFB_height; } - - s_target_width = EFB_WIDTH * xScale; - s_target_height = EFB_HEIGHT * yScale; - s_LastAA = (g_ActiveConfig.iMultisampleMode > 3)?0:g_ActiveConfig.iMultisampleMode; float SupersampleCoeficient = 1.0f; switch (s_LastAA) { case 1: - s_target_width = (s_target_width * 3) / 2; - s_target_height = (s_target_height * 3) / 2; - SupersampleCoeficient = 3.0f/2.0f; break; case 2: - s_target_width *= 2; - s_target_height *= 2; SupersampleCoeficient = 2.0f; break; case 3: - s_target_width *= 3; - s_target_height *= 3; SupersampleCoeficient = 3.0f; break; default: @@ -334,6 +326,12 @@ bool Renderer::Init() xScale *= SupersampleCoeficient; yScale *= SupersampleCoeficient; + EFBxScale = ceilf(xScale); + EFByScale = ceilf(yScale); + + s_target_width = EFB_WIDTH * EFBxScale; + s_target_height = EFB_HEIGHT * EFByScale; + s_Fulltarget_width = s_target_width; s_Fulltarget_height = s_target_height; @@ -393,8 +391,12 @@ int Renderer::GetTargetWidth() { return s_target_width; } int Renderer::GetTargetHeight() { return s_target_height; } int Renderer::GetFullTargetWidth() { return s_Fulltarget_width; } int Renderer::GetFullTargetHeight() { return s_Fulltarget_height; } -float Renderer::GetTargetScaleX() { return xScale; } -float Renderer::GetTargetScaleY() { return yScale; } +float Renderer::GetTargetScaleX() { return EFBxScale; } +float Renderer::GetTargetScaleY() { return EFByScale; } + +float Renderer::GetXFBScaleX() { return xScale; } +float Renderer::GetXFBScaleY() { return yScale; } + int Renderer::GetFrameBufferWidth() { @@ -507,10 +509,10 @@ TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc) int Xstride = (s_Fulltarget_width - s_target_width) / 2; int Ystride = (s_Fulltarget_height - s_target_height) / 2; TargetRectangle result; - result.left = (int)(rc.left * xScale) + Xstride; - result.top = (int)(rc.top * yScale) + Ystride; - result.right = (int)(rc.right * xScale) + Xstride; - result.bottom = (int)(rc.bottom * yScale) + Ystride; + result.left = (int)(rc.left * EFBxScale) + Xstride; + result.top = (int)(rc.top * EFByScale) + Ystride; + result.right = (int)(rc.right * EFBxScale) + Xstride; + result.bottom = (int)(rc.bottom * EFByScale) + Ystride; return result; } @@ -573,12 +575,13 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect if(!fbWidth || !fbHeight) return; VideoFifo_CheckEFBAccess(); + VideoFifo_CheckSwapRequestAt(xfbAddr, fbWidth, fbHeight); FBManager.CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc); - XFBWrited = true; + XFBWrited = true; + // XXX: Without the VI, how would we know what kind of field this is? So + // just use progressive. if (!g_ActiveConfig.bUseXFB) { - // XXX: Without the VI, how would we know what kind of field this is? So - // just use progressive. Renderer::Swap(xfbAddr, FIELD_PROGRESSIVE, fbWidth, fbHeight); Common::AtomicStoreRelease(s_swapRequested, FALSE); } @@ -597,10 +600,10 @@ bool Renderer::SetScissorRect() int Xstride = (s_Fulltarget_width - s_target_width) / 2; int Ystride = (s_Fulltarget_height - s_target_height) / 2; - rc.left = (int)(rc.left * xScale); - rc.top = (int)(rc.top * yScale); - rc.right = (int)(rc.right * xScale); - rc.bottom = (int)(rc.bottom * yScale); + rc.left = (int)(rc.left * EFBxScale); + rc.top = (int)(rc.top * EFByScale); + rc.right = (int)(rc.right * EFBxScale); + rc.bottom = (int)(rc.bottom * EFByScale); if (rc.left < 0) rc.left = 0; if (rc.right < 0) rc.right = 0; @@ -1006,9 +1009,9 @@ void Renderer::SetBlendMode(bool forceUpdate) void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight) { - if (g_bSkipCurrentFrame || !XFBWrited || !fbWidth || !fbHeight) + if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.bUseRealXFB) || !fbWidth || !fbHeight) { - g_VideoInitialize.pCopiedToXFB(false); + g_VideoInitialize.pCopiedToXFB(false); return; } // this function is called after the XFB field is changed, not after @@ -1238,29 +1241,17 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight) { xScale = (float)(dst_rect.right - dst_rect.left) / (float)s_XFB_width; yScale = (float)(dst_rect.bottom - dst_rect.top) / (float)s_XFB_height; - } - - s_target_width = EFB_WIDTH * xScale; - s_target_height = EFB_HEIGHT * yScale; + } - s_LastAA = (g_ActiveConfig.iMultisampleMode > 3)?0:g_ActiveConfig.iMultisampleMode; - - float SupersampleCoeficient = 1.0f; + float SupersampleCoeficient = 1.0f; switch (s_LastAA) { case 1: - s_target_width = (s_target_width * 3) / 2; - s_target_height = (s_target_height * 3) / 2; - SupersampleCoeficient = 3.0f/2.0f; break; case 2: - s_target_width *= 2; - s_target_height *= 2; - SupersampleCoeficient = 2.0f; + SupersampleCoeficient = 2.0f; break; case 3: - s_target_width *= 3; - s_target_height *= 3; SupersampleCoeficient = 3.0f; break; default: @@ -1269,6 +1260,12 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight) xScale *= SupersampleCoeficient; yScale *= SupersampleCoeficient; + + EFBxScale = ceilf(xScale); + EFByScale = ceilf(yScale); + + s_target_width = EFB_WIDTH * ceilf(EFBxScale); + s_target_height = EFB_HEIGHT * ceilf(EFByScale); D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface()); D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface()); if(WindowResized) diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index 94d920df80..db5507c8f6 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -361,26 +361,27 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo int tex_w = (abs(source_rect.GetWidth()) >> bScaleByHalf); int tex_h = (abs(source_rect.GetHeight()) >> bScaleByHalf); //compensate the texture grow if supersampling is enabled to conserve memory usage - float MultiSampleCompensation = 1.0f; + float SuperSampleCompensation = 1.0f; + float xScale = Renderer::GetTargetScaleX(); + float yScale = Renderer::GetTargetScaleY(); if(g_ActiveConfig.iMultisampleMode > 0 && g_ActiveConfig.iMultisampleMode < 4) { switch (g_ActiveConfig.iMultisampleMode) { case 1: - MultiSampleCompensation = 2.0f/3.0f; break; case 2: - MultiSampleCompensation = 0.5f; + SuperSampleCompensation = 0.5f; break; case 3: - MultiSampleCompensation = 1.0f/3.0f; + SuperSampleCompensation = 1.0f/3.0f; break; default: break; }; } - int Scaledtex_w = (g_ActiveConfig.bCopyEFBScaled)?((int)(Renderer::GetTargetScaleX() * MultiSampleCompensation * tex_w)):tex_w; - int Scaledtex_h = (g_ActiveConfig.bCopyEFBScaled)?((int)(Renderer::GetTargetScaleY() * MultiSampleCompensation * tex_h)):tex_h; + int Scaledtex_w = (g_ActiveConfig.bCopyEFBScaled)?((int)(xScale * SuperSampleCompensation * tex_w)):tex_w; + int Scaledtex_h = (g_ActiveConfig.bCopyEFBScaled)?((int)(yScale * SuperSampleCompensation * tex_h)):tex_h; TexCache::iterator iter; LPDIRECT3DTEXTURE9 tex = NULL; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp index a92c1584df..35245c55ca 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp @@ -268,9 +268,9 @@ TargetRectangle FramebufferManager::ConvertEFBRectangle(const EFBRectangle& rc) float XScale = Renderer::GetTargetScaleX(); float YScale = Renderer::GetTargetScaleY(); result.left = rc.left * XScale; - result.top = Renderer::GetTargetHeight() - (rc.top * YScale); + result.top = ((EFB_HEIGHT - rc.top) * YScale); result.right = rc.right * XScale ; - result.bottom = Renderer::GetTargetHeight() - (rc.bottom * YScale); + result.bottom = ((EFB_HEIGHT - rc.bottom) * YScale); return result; } @@ -411,6 +411,10 @@ void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight newVirt.xfbWidth = fbWidth; newVirt.xfbHeight = fbHeight; + newVirt.xfbSource.srcAddr = xfbAddr; + newVirt.xfbSource.srcWidth = fbWidth; + newVirt.xfbSource.srcHeight = fbHeight; + newVirt.xfbSource.texture = xfbTexture; newVirt.xfbSource.texWidth = m_targetWidth; newVirt.xfbSource.texHeight = m_targetHeight; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp index cdcd552e2e..570c5bcf0f 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp @@ -221,6 +221,10 @@ FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable) // printf("Compiling pixel shader. size = %i\n", strlen(code)); if (!code || !CompilePixelShader(newentry.shader, code)) { ERROR_LOG(VIDEO, "failed to create pixel shader"); + static int counter = 0; + char szTemp[MAX_PATH]; + sprintf(szTemp, "%sBADps_%04i.txt", File::GetUserPath(D_DUMP_IDX), counter++); + SaveData(szTemp, code); return NULL; } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index 767fc867c0..05e3ccac04 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -114,6 +114,18 @@ static int m_FrameBufferHeight; static GLuint s_tempScreenshotFramebuffer = 0; +static int s_XFB_width; +static int s_XFB_height; + +static float xScale; +static float yScale; + +static int EFBxScale; +static int EFByScale; + +static int s_recordWidth; +static int s_recordHeight; + static bool s_skipSwap = false; #ifndef _WIN32 @@ -156,12 +168,33 @@ static const GLenum glDestFactors[8] = { }; static const GLenum glCmpFuncs[8] = { - GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS + GL_NEVER, + GL_LESS, + GL_EQUAL, + GL_LEQUAL, + GL_GREATER, + GL_NOTEQUAL, + GL_GEQUAL, + GL_ALWAYS }; static const GLenum glLogicOpCodes[16] = { - GL_CLEAR, GL_AND, GL_AND_REVERSE, GL_COPY, GL_AND_INVERTED, GL_NOOP, GL_XOR, - GL_OR, GL_NOR, GL_EQUIV, GL_INVERT, GL_OR_REVERSE, GL_COPY_INVERTED, GL_OR_INVERTED, GL_NAND, GL_SET + GL_CLEAR, + GL_AND, + GL_AND_REVERSE, + GL_COPY, + GL_AND_INVERTED, + GL_NOOP, + GL_XOR, + GL_OR, + GL_NOR, + GL_EQUIV, + GL_INVERT, + GL_OR_REVERSE, + GL_COPY_INVERTED, + GL_OR_INVERTED, + GL_NAND, + GL_SET }; void SetDefaultRectTexParams() @@ -203,15 +236,15 @@ bool Renderer::Init() s_MSAACoverageSamples = 0; switch (g_ActiveConfig.iMultisampleMode) { - case MULTISAMPLE_OFF: s_MSAASamples = 1; break; - case MULTISAMPLE_2X: s_MSAASamples = 2; break; - case MULTISAMPLE_4X: s_MSAASamples = 4; break; - case MULTISAMPLE_8X: s_MSAASamples = 8; break; - case MULTISAMPLE_CSAA_8X: s_MSAASamples = 4; s_MSAACoverageSamples = 8; break; - case MULTISAMPLE_CSAA_8XQ: s_MSAASamples = 8; s_MSAACoverageSamples = 8; break; - case MULTISAMPLE_CSAA_16X: s_MSAASamples = 4; s_MSAACoverageSamples = 16; break; - case MULTISAMPLE_CSAA_16XQ: s_MSAASamples = 8; s_MSAACoverageSamples = 16; break; - default: + case MULTISAMPLE_OFF: s_MSAASamples = 1; break; + case MULTISAMPLE_2X: s_MSAASamples = 2; break; + case MULTISAMPLE_4X: s_MSAASamples = 4; break; + case MULTISAMPLE_8X: s_MSAASamples = 8; break; + case MULTISAMPLE_CSAA_8X: s_MSAASamples = 4; s_MSAACoverageSamples = 8; break; + case MULTISAMPLE_CSAA_8XQ: s_MSAASamples = 8; s_MSAACoverageSamples = 8; break; + case MULTISAMPLE_CSAA_16X: s_MSAASamples = 4; s_MSAACoverageSamples = 16; break; + case MULTISAMPLE_CSAA_16XQ: s_MSAASamples = 8; s_MSAACoverageSamples = 16; break; + default: s_MSAASamples = 1; } GLint numvertexattribs = 0; @@ -307,31 +340,40 @@ bool Renderer::Init() // Decide frambuffer size int W = (int)OpenGL_GetBackbufferWidth(), H = (int)OpenGL_GetBackbufferHeight(); + + s_XFB_width = MAX_XFB_WIDTH; + s_XFB_height = MAX_XFB_HEIGHT; + + TargetRectangle dst_rect; + ComputeDrawRectangle(W, H, false, &dst_rect); + + xScale = 1.0f; + yScale = 1.0f; + + if(!g_ActiveConfig.bNativeResolution) + { + if (g_ActiveConfig.b2xResolution) + { + xScale = 2.0f; + yScale = 2.0f; + } + else + { + xScale = (float)(dst_rect.right - dst_rect.left) / (float)s_XFB_width; + yScale = (float)(dst_rect.bottom - dst_rect.top) / (float)s_XFB_height; + } + } - if (g_ActiveConfig.b2xResolution) - { - m_FrameBufferWidth = (2 * EFB_HEIGHT >= W) ? 2 * EFB_HEIGHT : W; - m_FrameBufferHeight = (2 * EFB_HEIGHT >= H) ? 2 * EFB_HEIGHT : H; - } - else - { - // The size of the framebuffer targets should really NOT be the size of the OpenGL viewport. - // The EFB is larger than 640x480 - in fact, it's 640x528, give or take a couple of lines. - m_FrameBufferWidth = (EFB_WIDTH >= W) ? EFB_WIDTH : W; - m_FrameBufferHeight = (480 >= H) ? 480 : H; + + EFBxScale = ceilf(xScale); + EFByScale = ceilf(yScale); - // Adjust all heights with this ratio, the resulting height will be the same as H or EFB_HEIGHT. I.e. - // 768 (-1) for 1024x768 etc. - m_FrameBufferHeight *= (float)EFB_HEIGHT / 480.0; - - // Ensure a minimum target size so that the native res target always fits - if (m_FrameBufferWidth < EFB_WIDTH) m_FrameBufferWidth = EFB_WIDTH; - if (m_FrameBufferHeight < EFB_HEIGHT) m_FrameBufferHeight = EFB_HEIGHT; - } + m_FrameBufferWidth = EFB_WIDTH * EFBxScale; + m_FrameBufferHeight = EFB_HEIGHT * EFByScale; // Save the custom resolution - m_CustomWidth = (int)OpenGL_GetBackbufferWidth(); - m_CustomHeight = (int)OpenGL_GetBackbufferHeight(); + m_CustomWidth = W; + m_CustomHeight = H; // Because of the fixed framebuffer size we need to disable the resolution options while running g_Config.bRunning = true; @@ -432,8 +474,8 @@ void Renderer::Shutdown(void) cgDestroyContext(g_cgcontext); g_cgcontext = 0; } - - glDeleteFramebuffersEXT(1, &s_tempScreenshotFramebuffer); + if(s_tempScreenshotFramebuffer) + glDeleteFramebuffersEXT(1, &s_tempScreenshotFramebuffer); s_tempScreenshotFramebuffer = 0; g_framebufferManager.Shutdown(); @@ -486,29 +528,33 @@ int Renderer::GetCustomHeight() // Return the rendering target width and height int Renderer::GetTargetWidth() { - return (g_ActiveConfig.bNativeResolution || g_ActiveConfig.b2xResolution) ? - (g_ActiveConfig.bNativeResolution ? EFB_WIDTH : EFB_WIDTH * 2) : m_CustomWidth; + return m_FrameBufferWidth; } int Renderer::GetTargetHeight() { - return (g_ActiveConfig.bNativeResolution || g_ActiveConfig.b2xResolution) ? - (g_ActiveConfig.bNativeResolution ? EFB_HEIGHT : EFB_HEIGHT * 2) : m_CustomHeight; + return m_FrameBufferHeight; } float Renderer::GetTargetScaleX() { - return (float)GetTargetWidth() / (float)EFB_WIDTH; + return EFBxScale; } float Renderer::GetTargetScaleY() { - return (float)GetTargetHeight() / (float)EFB_HEIGHT; + return EFByScale; } + +float Renderer::GetXFBScaleX() { return xScale; } +float Renderer::GetXFBScaleY() { return yScale; } + TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc) { return g_framebufferManager.ConvertEFBRectangle(rc); } + + void Renderer::ResetAPIState() { // Gets us to a reasonably sane state where it's possible to do things like @@ -693,25 +739,20 @@ bool Renderer::SetScissorRect() { int xoff = bpmem.scissorOffset.x * 2 - 342; int yoff = bpmem.scissorOffset.y * 2 - 342; - float MValueX = GetTargetScaleX(); - float MValueY = GetTargetScaleY(); - float rc_left = (float)bpmem.scissorTL.x - xoff - 342; // left = 0 - rc_left *= MValueX; - if (rc_left < 0) rc_left = 0; + float rc_left = (float)bpmem.scissorTL.x - xoff - 342; // left = 0 + if (rc_left < 0) rc_left = 0; float rc_top = (float)bpmem.scissorTL.y - yoff - 342; // right = 0 - rc_top *= MValueY; - if (rc_top < 0) rc_top = 0; + if (rc_top < 0) rc_top = 0; float rc_right = (float)bpmem.scissorBR.x - xoff - 341; // right = 640 - rc_right *= MValueX; - if (rc_right > EFB_WIDTH * MValueX) rc_right = EFB_WIDTH * MValueX; + if (rc_right > EFB_WIDTH) rc_right = EFB_WIDTH; + float rc_bottom = (float)bpmem.scissorBR.y - yoff - 341; // bottom = 480 - rc_bottom *= MValueY; - if (rc_bottom > EFB_HEIGHT * MValueY) rc_bottom = EFB_HEIGHT * MValueY; + if (rc_bottom > EFB_HEIGHT) rc_bottom = EFB_HEIGHT; - if(rc_left > rc_right) + if(rc_left > rc_right) { int temp = rc_right; rc_right = rc_left; @@ -724,18 +765,27 @@ bool Renderer::SetScissorRect() rc_top = temp; } + // Check that the coordinates are good if (rc_right >= rc_left && rc_bottom >= rc_top) { - glScissor( - (int)rc_left, // x = 0 for example - Renderer::GetTargetHeight() - (int)(rc_bottom), // y = 0 for example - (int)(rc_right - rc_left), // width = 640 for example - (int)(rc_bottom - rc_top) // height = 480 for example + glScissor( + (int)(rc_left * EFBxScale), // x = 0 for example + (int)((EFB_HEIGHT - rc_bottom) * EFByScale), // y = 0 for example + (int)((rc_right - rc_left)* EFBxScale), // width = 640 for example + (int)((rc_bottom - rc_top) * EFByScale) // height = 480 for example ); return true; } - + else + { + glScissor( + 0, + 0, + Renderer::GetTargetWidth(), + Renderer::GetTargetHeight() + ); + } return false; } @@ -770,6 +820,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glClear(bits); + SetScissorRect(); } static bool XFBWrited = false; void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc) @@ -808,13 +859,12 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight) return; } - OpenGL_Update(); // just updates the render window position and the backbuffer size DVSTARTPROFILE(); ResetAPIState(); TargetRectangle back_rc; - ComputeDrawRectangle(OpenGL_GetBackbufferWidth(), OpenGL_GetBackbufferHeight(), true, &back_rc); + ComputeDrawRectangle(m_CustomWidth, m_CustomHeight, true, &back_rc); // Make sure that the wireframe setting doesn't screw up the screen copy. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); @@ -1055,6 +1105,69 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight) } #endif + OpenGL_Update(); // just updates the render window position and the backbuffer size + bool xfbchanged = false; + if(s_XFB_width != fbWidth || s_XFB_height != fbHeight) + { + xfbchanged = true; + s_XFB_width = fbWidth; + s_XFB_height = fbHeight; + if(s_XFB_width < 1) s_XFB_width = MAX_XFB_WIDTH; + if(s_XFB_width > MAX_XFB_WIDTH) s_XFB_width = MAX_XFB_WIDTH; + if(s_XFB_height < 1) s_XFB_height = MAX_XFB_HEIGHT; + if(s_XFB_height > MAX_XFB_HEIGHT) s_XFB_height = MAX_XFB_HEIGHT; + + } + bool WindowResized = false; + int W = (int)OpenGL_GetBackbufferWidth(), H = (int)OpenGL_GetBackbufferHeight(); + if (W != m_CustomWidth || H != m_CustomHeight) + { + WindowResized = true; + m_CustomWidth = W; + m_CustomHeight = H; + } + + + if( xfbchanged || WindowResized) + { + TargetRectangle dst_rect; + ComputeDrawRectangle(m_CustomWidth, m_CustomHeight, false, &dst_rect); + + xScale = 1.0f; + yScale = 1.0f; + + if(!g_ActiveConfig.bNativeResolution) + { + if (g_ActiveConfig.b2xResolution) + { + xScale = 2.0f; + yScale = 2.0f; + } + else + { + xScale = (float)(dst_rect.right - dst_rect.left) / (float)s_XFB_width; + yScale = (float)(dst_rect.bottom - dst_rect.top) / (float)s_XFB_height; + } + } + + + EFBxScale = ceilf(xScale); + EFByScale = ceilf(yScale); + + int m_newFrameBufferWidth = EFB_WIDTH * EFBxScale; + int m_newFrameBufferHeight = EFB_HEIGHT * EFByScale; + if(m_newFrameBufferWidth != m_FrameBufferWidth || m_newFrameBufferHeight != m_FrameBufferHeight ) + { + m_FrameBufferWidth = m_newFrameBufferWidth; + m_FrameBufferHeight = m_newFrameBufferHeight; + + g_framebufferManager.Shutdown(); + g_framebufferManager.Init(m_FrameBufferWidth, m_FrameBufferHeight, s_MSAASamples, s_MSAACoverageSamples); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + } + + } + // Place messages on the picture, then copy it to the screen // --------------------------------------------------------------------- // Count FPS. @@ -1432,15 +1545,12 @@ void UpdateViewport() // [5] = 16777215 * farz int scissorXOff = bpmem.scissorOffset.x * 2; // 342 int scissorYOff = bpmem.scissorOffset.y * 2; // 342 - - float MValueX = Renderer::GetTargetScaleX(); - float MValueY = Renderer::GetTargetScaleY(); - + // Stretch picture with increased internal resolution - int GLx = (int)ceil((xfregs.rawViewport[3] - xfregs.rawViewport[0] - scissorXOff) * MValueX); - int GLy = (int)ceil(Renderer::GetTargetHeight() - ((int)(xfregs.rawViewport[4] - xfregs.rawViewport[1] - scissorYOff)) * MValueY); - int GLWidth = (int)ceil((int)(2 * xfregs.rawViewport[0]) * MValueX); - int GLHeight = (int)ceil((int)(-2 * xfregs.rawViewport[1]) * MValueY); + int GLx = (int)ceil((xfregs.rawViewport[3] - xfregs.rawViewport[0] - scissorXOff) * EFBxScale); + int GLy = (int)ceil((float)((int)(EFB_HEIGHT - xfregs.rawViewport[4] + xfregs.rawViewport[1] + scissorYOff)) * EFByScale); + int GLWidth = (int)ceil((float)(2 * xfregs.rawViewport[0]) * EFBxScale); + int GLHeight = (int)ceil((float)(-2 * xfregs.rawViewport[1]) * EFByScale); double GLNear = (xfregs.rawViewport[5] - xfregs.rawViewport[2]) / 16777216.0f; double GLFar = xfregs.rawViewport[5] / 16777216.0f; if(GLWidth < 0) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp index b4ba22470c..4e3ebfe769 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp @@ -294,7 +294,7 @@ void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyf float MValueX = Renderer::GetTargetScaleX(); float MValueY = Renderer::GetTargetScaleY(); - float top = Renderer::GetTargetHeight() - (source.top + expandedHeight) * MValueY ; + float top = (EFB_HEIGHT - source.top - expandedHeight) * MValueY ; float sampleStride = bScaleByHalf?2.0f:1.0f;