From 80247835020092c598fcee519f77e7d581b4d146 Mon Sep 17 00:00:00 2001 From: Nolan Check Date: Thu, 12 May 2011 02:14:45 +0000 Subject: [PATCH] Don't resize render target to handle out-of-bounds viewports. Instead, adjust the projection matrix. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7538 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/VideoCommon/Src/RenderBase.cpp | 12 +- Source/Core/VideoCommon/Src/RenderBase.h | 20 +- .../VideoCommon/Src/VertexShaderManager.cpp | 16 +- .../Src/FramebufferManager.cpp | 6 +- .../Plugin_VideoDX11/Src/PSTextureEncoder.cpp | 8 +- .../Plugins/Plugin_VideoDX11/Src/Render.cpp | 163 +++++++-------- Source/Plugins/Plugin_VideoDX11/Src/Render.h | 2 +- .../Plugin_VideoDX11/Src/TextureCache.cpp | 2 +- .../Plugin_VideoDX11/Src/XFBEncoder.cpp | 8 +- .../Src/FramebufferManager.cpp | 8 +- Source/Plugins/Plugin_VideoDX9/Src/Render.cpp | 197 ++++++++---------- Source/Plugins/Plugin_VideoDX9/Src/Render.h | 2 +- .../Plugin_VideoDX9/Src/TextureCache.cpp | 6 +- .../Plugin_VideoDX9/Src/TextureConverter.cpp | 18 +- Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 20 +- Source/Plugins/Plugin_VideoOGL/Src/Render.h | 2 +- 16 files changed, 229 insertions(+), 261 deletions(-) diff --git a/Source/Core/VideoCommon/Src/RenderBase.cpp b/Source/Core/VideoCommon/Src/RenderBase.cpp index 237605ccf3..edb278acca 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.cpp +++ b/Source/Core/VideoCommon/Src/RenderBase.cpp @@ -62,10 +62,6 @@ volatile bool Renderer::s_bScreenshot; int Renderer::s_target_width; int Renderer::s_target_height; -// The custom resolution -int Renderer::s_Fulltarget_width; -int Renderer::s_Fulltarget_height; - // TODO: Add functionality to reinit all the render targets when the window is resized. int Renderer::s_backbuffer_width; int Renderer::s_backbuffer_height; @@ -180,8 +176,8 @@ bool Renderer::CalculateTargetSize(int multiplier) if (newEFBWidth != s_target_width || newEFBHeight != s_target_height) { - s_Fulltarget_width = s_target_width = newEFBWidth; - s_Fulltarget_height = s_target_height = newEFBHeight; + s_target_width = newEFBWidth; + s_target_height = newEFBHeight; return true; } return false; @@ -375,7 +371,7 @@ void Renderer::RecordVideoMemory() FifoRecorder::GetInstance().SetVideoMemory(bpMem, cpMem, xfMem, xfRegs, sizeof(XFRegisters) / 4); } -void UpdateViewport() +void UpdateViewport(Matrix44& vpCorrection) { - g_renderer->UpdateViewport(); + g_renderer->UpdateViewport(vpCorrection); } diff --git a/Source/Core/VideoCommon/Src/RenderBase.h b/Source/Core/VideoCommon/Src/RenderBase.h index 98f32c443c..17132ebb8c 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.h +++ b/Source/Core/VideoCommon/Src/RenderBase.h @@ -66,12 +66,6 @@ public: virtual void ApplyState(bool bUseDstAlpha) = 0; virtual void RestoreState() = 0; - // Real internal resolution: - // D3D doesn't support viewports larger than the target size, so we need to resize the target to the viewport size for those. - // OpenGL supports this, so GetFullTargetWidth returns the same as GetTargetWidth there. - static int GetFullTargetWidth() { return s_Fulltarget_width; } - static int GetFullTargetHeight() { return s_Fulltarget_height; } - // Ideal internal resolution - determined by display resolution (automatic scaling) and/or a multiple of the native EFB resolution static int GetTargetWidth() { return s_target_width; } static int GetTargetHeight() { return s_target_height; } @@ -99,12 +93,6 @@ public: static float EFBToScaledXf(float x) { return x * ((float)GetTargetWidth() / (float)EFB_WIDTH); } static float EFBToScaledYf(float y) { return y * ((float)GetTargetHeight() / (float)EFB_HEIGHT); } - // Returns the offset at which the EFB will be drawn onto the backbuffer - // NOTE: Never calculate this manually (e.g. to "increase accuracy"), since you might end up getting off-by-one errors. - // This is a per-frame constant, so it won't cause any issues. - static int TargetStrideX() { return (s_Fulltarget_width - s_target_width) / 2; } - static int TargetStrideY() { return (s_Fulltarget_height - s_target_height) / 2; } - // Random utilities static void SetScreenshot(const char *filename); static void DrawDebugText(); @@ -124,7 +112,7 @@ public: // Finish up the current frame, print some stats virtual void Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight, const EFBRectangle& rc,float Gamma = 1.0f) = 0; - virtual void UpdateViewport() = 0; + virtual void UpdateViewport(Matrix44& vpCorrection) = 0; virtual bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc) = 0; @@ -160,10 +148,6 @@ protected: static int s_target_width; static int s_target_height; - // The custom resolution - static int s_Fulltarget_width; - static int s_Fulltarget_height; - // TODO: Add functionality to reinit all the render targets when the window is resized. static int s_backbuffer_width; static int s_backbuffer_height; @@ -189,7 +173,7 @@ private: extern Renderer *g_renderer; -void UpdateViewport(); +void UpdateViewport(Matrix44& vpCorrection); template void GetScissorRect(MathUtil::Rectangle &rect) diff --git a/Source/Core/VideoCommon/Src/VertexShaderManager.cpp b/Source/Core/VideoCommon/Src/VertexShaderManager.cpp index 49b1f50ff9..a18829fde2 100644 --- a/Source/Core/VideoCommon/Src/VertexShaderManager.cpp +++ b/Source/Core/VideoCommon/Src/VertexShaderManager.cpp @@ -43,12 +43,13 @@ static int nNormalMatricesChanged[2]; // min,max static int nPostTransformMatricesChanged[2]; // min,max static int nLightsChanged[2]; // min,max +static Matrix44 s_viewportCorrection; static Matrix33 s_viewRotationMatrix; static Matrix33 s_viewInvRotationMatrix; static float s_fViewTranslationVector[3]; static float s_fViewRotation[2]; -void UpdateViewport(); +void UpdateViewport(Matrix44& vpCorrection); inline void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) { @@ -301,7 +302,8 @@ void VertexShaderManager::SetConstants() bViewportChanged = false; SetVSConstant4f(C_DEPTHPARAMS,xfregs.viewport.farZ / 16777216.0f,xfregs.viewport.zRange / 16777216.0f,0.0f,0.0f); // This is so implementation-dependent that we can't have it here. - UpdateViewport(); + UpdateViewport(s_viewportCorrection); + bProjectionChanged = true; } if (bProjectionChanged) @@ -421,12 +423,18 @@ void VertexShaderManager::SetConstants() Matrix44::Multiply(mtxB, mtxA, viewMtx); // view = rotation x translation Matrix44::Set(mtxB, g_fProjectionMatrix); Matrix44::Multiply(mtxB, viewMtx, mtxA); // mtxA = projection x view + Matrix44::Multiply(s_viewportCorrection, mtxA, mtxB); // mtxB = viewportCorrection x mtxA - SetMultiVSConstant4fv(C_PROJECTION, 4, &mtxA.data[0]); + SetMultiVSConstant4fv(C_PROJECTION, 4, mtxB.data); } else { - SetMultiVSConstant4fv(C_PROJECTION, 4, &g_fProjectionMatrix[0]); + Matrix44 projMtx; + Matrix44::Set(projMtx, g_fProjectionMatrix); + + Matrix44 correctedMtx; + Matrix44::Multiply(s_viewportCorrection, projMtx, correctedMtx); + SetMultiVSConstant4fv(C_PROJECTION, 4, correctedMtx.data); } } } diff --git a/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp index e1a0c9e32e..a052567102 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp @@ -54,8 +54,8 @@ D3DTexture2D* FramebufferManager::GetResolvedEFBDepthTexture() FramebufferManager::FramebufferManager() { - const unsigned int target_width = Renderer::GetFullTargetWidth(); - const unsigned int target_height = Renderer::GetFullTargetHeight(); + const unsigned int target_width = Renderer::GetTargetWidth(); + const unsigned int target_height = Renderer::GetTargetHeight(); DXGI_SAMPLE_DESC sample_desc = D3D::GetAAMode(g_ActiveConfig.iMultisampleMode); // EFB color texture - primary render target @@ -221,7 +221,7 @@ void XFBSource::CopyEFB(float Gamma) D3D::SetLinearCopySampler(); D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture()->GetSRV(), sourceRc.AsRECT(), - Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(), + Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(true), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(),Gamma); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PSTextureEncoder.cpp b/Source/Plugins/Plugin_VideoDX11/Src/PSTextureEncoder.cpp index 0dd1399100..1e27c16a34 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/PSTextureEncoder.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/PSTextureEncoder.cpp @@ -1080,10 +1080,10 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat, params.NumBlocksY = FLOAT(numBlocksY); params.PosX = FLOAT(correctSrc.left); params.PosY = FLOAT(correctSrc.top); - params.TexLeft = float(targetRect.left) / g_renderer->GetFullTargetWidth(); - params.TexTop = float(targetRect.top) / g_renderer->GetFullTargetHeight(); - params.TexRight = float(targetRect.right) / g_renderer->GetFullTargetWidth(); - params.TexBottom = float(targetRect.bottom) / g_renderer->GetFullTargetHeight(); + params.TexLeft = float(targetRect.left) / g_renderer->GetTargetWidth(); + params.TexTop = float(targetRect.top) / g_renderer->GetTargetHeight(); + params.TexRight = float(targetRect.right) / g_renderer->GetTargetWidth(); + params.TexBottom = float(targetRect.bottom) / g_renderer->GetTargetHeight(); D3D::g_context->UpdateSubresource(m_encodeParams, 0, NULL, ¶ms, 0, 0); D3D::g_context->VSSetConstantBuffers(0, 1, &m_encodeParams); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index 418b03ea40..bc8f7e6ca1 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -376,8 +376,7 @@ Renderer::Renderer() D3D::g_context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(), ClearColor); D3D::g_context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 1.f, 0); - D3D11_VIEWPORT vp = CD3D11_VIEWPORT((float)(s_Fulltarget_width - s_target_width) / 2.f, - (float)(s_Fulltarget_height - s_target_height) / 2.f, + D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)s_target_width, (float)s_target_height); D3D::g_context->RSSetViewports(1, &vp); D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); @@ -402,10 +401,10 @@ void Renderer::RenderText(const char *text, int left, int top, u32 color) TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc) { TargetRectangle result; - result.left = EFBToScaledX(rc.left) + TargetStrideX(); - result.top = EFBToScaledY(rc.top) + TargetStrideY(); - result.right = EFBToScaledX(rc.right) + TargetStrideX(); - result.bottom = EFBToScaledY(rc.bottom) + TargetStrideY(); + result.left = EFBToScaledX(rc.left); + result.top = EFBToScaledY(rc.top); + result.right = EFBToScaledX(rc.right); + result.bottom = EFBToScaledY(rc.bottom); return result; } @@ -457,10 +456,10 @@ bool Renderer::SetScissorRect() if (rc.top > EFB_HEIGHT) rc.top = EFB_HEIGHT; if (rc.bottom > EFB_HEIGHT) rc.bottom = EFB_HEIGHT; - rc.left = EFBToScaledX(rc.left) + TargetStrideX(); - rc.right = EFBToScaledX(rc.right) + TargetStrideX(); - rc.top = EFBToScaledY(rc.top) + TargetStrideY(); - rc.bottom = EFBToScaledY(rc.bottom) + TargetStrideY(); + rc.left = EFBToScaledX(rc.left); + rc.right = EFBToScaledX(rc.right); + rc.top = EFBToScaledY(rc.top); + rc.bottom = EFBToScaledY(rc.bottom); if (rc.left > rc.right) { @@ -483,8 +482,8 @@ bool Renderer::SetScissorRect() else { //WARN_LOG(VIDEO, "Bad scissor rectangle: %i %i %i %i", rc.left, rc.top, rc.right, rc.bottom); - *rc.AsRECT() = CD3D11_RECT(TargetStrideX(), TargetStrideY(), - TargetStrideX() + s_target_width, TargetStrideY() + s_target_height); + *rc.AsRECT() = CD3D11_RECT(0, 0, + s_target_width, s_target_height); D3D::g_context->RSSetScissorRects(1, rc.AsRECT()); return false; } @@ -570,8 +569,8 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) D3D::SetPointCopySampler(); D3D::drawShadedTexQuad(FramebufferManager::GetEFBDepthTexture()->GetSRV(), &RectToLock, - Renderer::GetFullTargetWidth(), - Renderer::GetFullTargetHeight(), + Renderer::GetTargetWidth(), + Renderer::GetTargetHeight(), PixelShaderCache::GetDepthMatrixProgram(true), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout()); @@ -647,18 +646,40 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) ResetAPIState(); D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), NULL); - D3D::drawColorQuad(rgbaColor, (float)RectToLock.left * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f, - - (float)RectToLock.top * 2.f / (float)Renderer::GetFullTargetHeight() + 1.f, - (float)RectToLock.right * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f, - - (float)RectToLock.bottom * 2.f / (float)Renderer::GetFullTargetHeight() + 1.f); + D3D::drawColorQuad(rgbaColor, (float)RectToLock.left * 2.f / (float)Renderer::GetTargetWidth() - 1.f, + - (float)RectToLock.top * 2.f / (float)Renderer::GetTargetHeight() + 1.f, + (float)RectToLock.right * 2.f / (float)Renderer::GetTargetWidth() - 1.f, + - (float)RectToLock.bottom * 2.f / (float)Renderer::GetTargetHeight() + 1.f); RestoreAPIState(); return 0; } } +// Viewport correction: +// Say you want a viewport at (ix, iy) with size (iw, ih), +// but your viewport must be clamped at (ax, ay) with size (aw, ah). +// Just multiply the projection matrix with the following to get the same +// effect: +// [ (iw/aw) 0 0 ((iw - 2*(ax-ix)) / aw - 1) ] +// [ 0 (ih/ah) 0 ((-ih + 2*(ay-iy)) / ah + 1) ] +// [ 0 0 1 0 ] +// [ 0 0 0 1 ] +static void ViewportCorrectionMatrix(Matrix44& result, + float ix, float iy, float iw, float ih, // Intended viewport (x, y, width, height) + float ax, float ay, float aw, float ah) // Actual viewport (x, y, width, height) +{ + Matrix44::LoadIdentity(result); + if (aw == 0.f || ah == 0.f) + return; + result.data[4*0+0] = iw / aw; + result.data[4*0+3] = (iw - 2.f * (ax - ix)) / aw - 1.f; + result.data[4*1+1] = ih / ah; + result.data[4*1+3] = (-ih + 2.f * (ay - iy)) / ah + 1.f; +} + // Called from VertexShaderManager -void Renderer::UpdateViewport() +void Renderer::UpdateViewport(Matrix44& vpCorrection) { // reversed gxsetviewport(xorig, yorig, width, height, nearz, farz) // [0] = width/2 @@ -667,80 +688,49 @@ void Renderer::UpdateViewport() // [3] = xorig + width/2 + 342 // [4] = yorig + height/2 + 342 // [5] = 16777215 * farz - const int old_fulltarget_w = Renderer::GetFullTargetWidth(); - const int old_fulltarget_h = Renderer::GetFullTargetHeight(); - int scissorXOff = bpmem.scissorOffset.x << 1; - int scissorYOff = bpmem.scissorOffset.y << 1; + int scissorXOff = bpmem.scissorOffset.x * 2; + int scissorYOff = bpmem.scissorOffset.y * 2; // TODO: ceil, floor or just cast to int? // TODO: Directly use the floats instead of rounding them? - int X = Renderer::EFBToScaledX((int)ceil(xfregs.viewport.xOrig - xfregs.viewport.wd - scissorXOff)) + Renderer::TargetStrideX(); - int Y = Renderer::EFBToScaledY((int)ceil(xfregs.viewport.yOrig + xfregs.viewport.ht - scissorYOff)) + Renderer::TargetStrideY(); - int Width = Renderer::EFBToScaledX((int)ceil(2.0f * xfregs.viewport.wd)); - int Height = Renderer::EFBToScaledY((int)ceil(-2.0f * xfregs.viewport.ht)); - if (Width < 0) + int intendedX = Renderer::EFBToScaledX((int)ceil(xfregs.viewport.xOrig - xfregs.viewport.wd - scissorXOff)); + int intendedY = Renderer::EFBToScaledY((int)ceil(xfregs.viewport.yOrig + xfregs.viewport.ht - scissorYOff)); + int intendedWd = Renderer::EFBToScaledX((int)ceil(2.0f * xfregs.viewport.wd)); + int intendedHt = Renderer::EFBToScaledY((int)ceil(-2.0f * xfregs.viewport.ht)); + if (intendedWd < 0) { - X += Width; - Width *= -1; + intendedX += intendedWd; + intendedWd = -intendedWd; } - if (Height < 0) + if (intendedHt < 0) { - Y += Height; - Height *= -1; + intendedY += intendedHt; + intendedHt = -intendedHt; } - bool sizeChanged = false; + + // In D3D, the viewport rectangle must fit within the render target. + int X = intendedX; if (X < 0) - { - s_Fulltarget_width -= 2 * X; X = 0; - sizeChanged = true; - } + int Y = intendedY; if (Y < 0) - { - s_Fulltarget_height -= 2 * Y; Y = 0; - sizeChanged = true; - } + int Wd = intendedWd; + if (X + Wd > GetTargetWidth()) + Wd = GetTargetWidth() - X; + int Ht = intendedHt; + if (Y + Ht > GetTargetHeight()) + Ht = GetTargetHeight() - Y; - float newx = (float)X; - float newy = (float)Y; - float newwidth = (float)Width; - float newheight = (float)Height; - // TODO: If the size hasn't changed for X frames, we should probably shrink the EFB texture for performance reasons - if (sizeChanged) - { - // Make sure that the requested size is actually supported by the GFX driver - if (Renderer::GetFullTargetWidth() > (int)D3D::GetMaxTextureSize() || Renderer::GetFullTargetHeight() > (int)D3D::GetMaxTextureSize()) - { - // Skip EFB recreation and viewport setting. Most likely causes glitches in this case, but prevents crashes at least - ERROR_LOG(VIDEO, "Tried to set a viewport which is too wide to emulate with Direct3D11. Requested EFB size is %dx%d\n", Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight()); - - // Fix the viewport to fit to the old EFB size, TODO: Check this for off-by-one errors - newx *= (float)(old_fulltarget_w-1) / (float)(Renderer::GetFullTargetWidth()-1); - newy *= (float)(old_fulltarget_h-1) / (float)(Renderer::GetFullTargetHeight()-1); - newwidth *= (float)(old_fulltarget_w-1) / (float)(Renderer::GetFullTargetWidth()-1); - newheight *= (float)(old_fulltarget_h-1) / (float)(Renderer::GetFullTargetHeight()-1); - - s_Fulltarget_width = old_fulltarget_w; - s_Fulltarget_height = old_fulltarget_h; - } - else - { - D3D::g_context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), NULL); - - delete g_framebuffer_manager; - g_framebuffer_manager = new FramebufferManager; - - D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); - float clear_col[4] = { 0.f, 0.f, 0.f, 1.f }; - D3D::g_context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(), clear_col); - D3D::g_context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 1.f, 0); - } - } + // If GX viewport is off the render target, we must clamp our viewport + // within the bounds. Use the correction matrix to compensate. + ViewportCorrectionMatrix(vpCorrection, + intendedX, intendedY, intendedWd, intendedHt, + X, Y, Wd, Ht); // Some games set invalids values for z min and z max so fix them to the max an min alowed and let the shaders do this work - D3D11_VIEWPORT vp = CD3D11_VIEWPORT(newx, newy, newwidth, newheight, + D3D11_VIEWPORT vp = CD3D11_VIEWPORT(X, Y, Wd, Ht, 0.f, // (xfregs.viewport.farZ - xfregs.viewport.zRange) / 16777216.0f; 1.f); // xfregs.viewport.farZ / 16777216.0f; D3D::g_context->RSSetViewports(1, &vp); @@ -778,7 +768,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE void Renderer::ReinterpretPixelData(unsigned int convtype) { // TODO: MSAA support.. - D3D11_RECT source = CD3D11_RECT(0, 0, g_renderer->GetFullTargetWidth(), g_renderer->GetFullTargetHeight()); + D3D11_RECT source = CD3D11_RECT(0, 0, g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight()); ID3D11PixelShader* pixel_shader; if (convtype == 0) pixel_shader = PixelShaderCache::ReinterpRGB8ToRGBA6(true); @@ -792,12 +782,14 @@ void Renderer::ReinterpretPixelData(unsigned int convtype) // convert data and set the target texture as our new EFB g_renderer->ResetAPIState(); - D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)g_renderer->GetFullTargetWidth(), (float)g_renderer->GetFullTargetHeight()); + D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)g_renderer->GetTargetWidth(), (float)g_renderer->GetTargetHeight()); D3D::g_context->RSSetViewports(1, &vp); D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTempTexture()->GetRTV(), NULL); D3D::SetPointCopySampler(); - D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture()->GetSRV(), &source, g_renderer->GetFullTargetWidth(), g_renderer->GetFullTargetHeight(), pixel_shader, VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout()); + D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture()->GetSRV(), &source, + g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight(), + pixel_shader, VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout()); g_renderer->RestoreAPIState(); @@ -1019,7 +1011,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons // TODO: Improve sampling algorithm for the pixel shader so that we can use the multisampled EFB texture as source D3DTexture2D* read_texture = FramebufferManager::GetResolvedEFBColorTexture(); - D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(), PixelShaderCache::GetColorCopyProgram(false),VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), Gamma); + D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), + Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), + PixelShaderCache::GetColorCopyProgram(false), + VertexShaderCache::GetSimpleVertexShader(), + VertexShaderCache::GetSimpleInputLayout(), Gamma); } // done with drawing the game stuff, good moment to save a screenshot @@ -1146,7 +1142,6 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons Renderer::RestoreAPIState(); D3D::BeginFrame(); D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); - UpdateViewport(); VertexShaderManager::SetViewportChanged(); Core::Callback_VideoCopiedToXFB(XFBWrited || (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB)); @@ -1167,7 +1162,7 @@ void Renderer::RestoreAPIState() D3D::stateman->PopBlendState(); D3D::stateman->PopDepthState(); D3D::stateman->PopRasterizerState(); - UpdateViewport(); + VertexShaderManager::SetViewportChanged(); SetScissorRect(); } diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.h b/Source/Plugins/Plugin_VideoDX11/Src/Render.h index 4ab4d27419..7e6b4594b5 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.h @@ -47,7 +47,7 @@ public: void ReinterpretPixelData(unsigned int convtype); - void UpdateViewport(); + void UpdateViewport(Matrix44& vpCorrection); bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp index f8c6db0d36..542cb2bf0e 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp @@ -130,7 +130,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo // Create texture copy D3D::drawShadedTexQuad( (srcFormat == PIXELFMT_Z24) ? FramebufferManager::GetEFBDepthTexture()->GetSRV() : FramebufferManager::GetEFBColorTexture()->GetSRV(), - &sourcerect, Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(), + &sourcerect, Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), (srcFormat == PIXELFMT_Z24) ? PixelShaderCache::GetDepthMatrixProgram(true) : PixelShaderCache::GetColorMatrixProgram(true), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout()); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/XFBEncoder.cpp b/Source/Plugins/Plugin_VideoDX11/Src/XFBEncoder.cpp index 19af9021cc..07969fb837 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/XFBEncoder.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/XFBEncoder.cpp @@ -289,10 +289,10 @@ void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcR XFBEncodeParams params = { 0 }; params.Width = FLOAT(width); params.Height = FLOAT(height); - params.TexLeft = FLOAT(targetRect.left) / g_renderer->GetFullTargetWidth(); - params.TexTop = FLOAT(targetRect.top) / g_renderer->GetFullTargetHeight(); - params.TexRight = FLOAT(targetRect.right) / g_renderer->GetFullTargetWidth(); - params.TexBottom = FLOAT(targetRect.bottom) / g_renderer->GetFullTargetHeight(); + params.TexLeft = FLOAT(targetRect.left) / g_renderer->GetTargetWidth(); + params.TexTop = FLOAT(targetRect.top) / g_renderer->GetTargetHeight(); + params.TexRight = FLOAT(targetRect.right) / g_renderer->GetTargetWidth(); + params.TexBottom = FLOAT(targetRect.bottom) / g_renderer->GetTargetHeight(); params.Gamma = gamma; D3D::g_context->UpdateSubresource(m_encodeParams, 0, NULL, ¶ms, 0, 0); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp index 712cebfd64..0a87a1baf5 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp @@ -44,8 +44,8 @@ FramebufferManager::Efb FramebufferManager::s_efb; FramebufferManager::FramebufferManager() { bool depth_textures_supported = true; - int target_width = Renderer::GetFullTargetWidth(); - int target_height = Renderer::GetFullTargetHeight(); + int target_width = Renderer::GetTargetWidth(); + int target_height = Renderer::GetTargetHeight(); s_efb.color_surface_Format = D3DFMT_A8R8G8B8; // EFB color texture - primary render target @@ -217,8 +217,8 @@ void XFBSource::CopyEFB(float Gamma) D3D::drawShadedTexQuad( FramebufferManager::GetEFBColorTexture(), &sourcerect, - Renderer::GetFullTargetWidth(), - Renderer::GetFullTargetHeight(), + Renderer::GetTargetWidth(), + Renderer::GetTargetHeight(), texWidth, texHeight, PixelShaderCache::GetColorCopyProgram( g_ActiveConfig.iMultisampleMode), diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 81a2207abf..6c785aa012 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -294,7 +294,7 @@ Renderer::Renderer() CalculateTargetSize(SupersampleCoeficient); // Make sure to use valid texture sizes - D3D::FixTextureSize(s_Fulltarget_width, s_Fulltarget_height); + D3D::FixTextureSize(s_target_width, s_target_height); s_bLastFrameDumped = false; s_bAVIDumping = false; @@ -323,8 +323,8 @@ Renderer::Renderer() D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface()); D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface()); - vp.X = TargetStrideX(); - vp.Y = TargetStrideY(); + vp.X = 0; + vp.Y = 0; vp.Width = s_target_width; vp.Height = s_target_height; D3D::dev->SetViewport(&vp); @@ -356,10 +356,10 @@ void Renderer::RenderText(const char *text, int left, int top, u32 color) TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc) { TargetRectangle result; - result.left = EFBToScaledX(rc.left) + TargetStrideX(); - result.top = EFBToScaledY(rc.top) + TargetStrideY(); - result.right = EFBToScaledX(rc.right) + TargetStrideX(); - result.bottom = EFBToScaledY(rc.bottom) + TargetStrideY(); + result.left = EFBToScaledX(rc.left); + result.top = EFBToScaledY(rc.top); + result.right = EFBToScaledX(rc.right); + result.bottom = EFBToScaledY(rc.bottom); return result; } @@ -454,10 +454,10 @@ bool Renderer::SetScissorRect() rc.top = temp; } - rc.left = EFBToScaledX(rc.left) + TargetStrideX(); - rc.top = EFBToScaledY(rc.top) + TargetStrideY(); - rc.right = EFBToScaledX(rc.right) + TargetStrideX(); - rc.bottom = EFBToScaledY(rc.bottom) + TargetStrideY(); + rc.left = EFBToScaledX(rc.left); + rc.top = EFBToScaledY(rc.top); + rc.right = EFBToScaledX(rc.right); + rc.bottom = EFBToScaledY(rc.bottom); // Check that the coordinates are good if (rc.right != rc.left && rc.bottom != rc.top) @@ -468,10 +468,10 @@ bool Renderer::SetScissorRect() else { //WARN_LOG(VIDEO, "Bad scissor rectangle: %i %i %i %i", rc.left, rc.top, rc.right, rc.bottom); - rc.left = TargetStrideX(); - rc.top = TargetStrideY(); - rc.right = TargetStrideX() + s_target_width; - rc.bottom = TargetStrideY() + s_target_height; + rc.left = 0; + rc.top = 0; + rc.right = s_target_width; + rc.bottom = s_target_height; D3D::dev->SetScissorRect(rc.AsRECT()); } return false; @@ -606,8 +606,8 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) D3D::drawShadedTexQuad( read_texture, &RectToLock, - Renderer::GetFullTargetWidth(), - Renderer::GetFullTargetHeight(), + Renderer::GetTargetWidth(), + Renderer::GetTargetHeight(), 4, 4, PixelShaderCache::GetDepthMatrixProgram(0, bformat != FOURCC_RAWZ), VertexShaderCache::GetSimpleVertexShader(0)); @@ -680,18 +680,40 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) { // TODO: Speed this up by batching pokes? ResetAPIState(); - D3D::drawColorQuad(GetFullTargetWidth(), GetFullTargetHeight(), poke_data, - (float)RectToLock.left * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f, - - (float)RectToLock.top * 2.f / (float)Renderer::GetFullTargetHeight() + 1.f, - (float)RectToLock.right * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f, - - (float)RectToLock.bottom * 2.f / (float)Renderer::GetFullTargetHeight() + 1.f); + D3D::drawColorQuad(GetTargetWidth(), GetTargetHeight(), poke_data, + (float)RectToLock.left * 2.f / (float)Renderer::GetTargetWidth() - 1.f, + - (float)RectToLock.top * 2.f / (float)Renderer::GetTargetHeight() + 1.f, + (float)RectToLock.right * 2.f / (float)Renderer::GetTargetWidth() - 1.f, + - (float)RectToLock.bottom * 2.f / (float)Renderer::GetTargetHeight() + 1.f); RestoreAPIState(); return 0; } } +// Viewport correction: +// Say you want a viewport at (ix, iy) with size (iw, ih), +// but your viewport must be clamped at (ax, ay) with size (aw, ah). +// Just multiply the projection matrix with the following to get the same +// effect: +// [ (iw/aw) 0 0 ((iw - 2*(ax-ix)) / aw - 1) ] +// [ 0 (ih/ah) 0 ((-ih + 2*(ay-iy)) / ah + 1) ] +// [ 0 0 1 0 ] +// [ 0 0 0 1 ] +static void ViewportCorrectionMatrix(Matrix44& result, + float ix, float iy, float iw, float ih, // Intended viewport (x, y, width, height) + float ax, float ay, float aw, float ah) // Actual viewport (x, y, width, height) +{ + Matrix44::LoadIdentity(result); + if (aw == 0.f || ah == 0.f) + return; + result.data[4*0+0] = iw / aw; + result.data[4*0+3] = (iw - 2.f * (ax - ix)) / aw - 1.f; + result.data[4*1+1] = ih / ah; + result.data[4*1+3] = (-ih + 2.f * (ay - iy)) / ah + 1.f; +} + // Called from VertexShaderManager -void Renderer::UpdateViewport() +void Renderer::UpdateViewport(Matrix44& vpCorrection) { // reversed gxsetviewport(xorig, yorig, width, height, nearz, farz) // [0] = width/2 @@ -700,98 +722,51 @@ void Renderer::UpdateViewport() // [3] = xorig + width/2 + 342 // [4] = yorig + height/2 + 342 // [5] = 16777215 * farz - const int old_fulltarget_w = Renderer::GetFullTargetWidth(); - const int old_fulltarget_h = Renderer::GetFullTargetHeight(); - int scissorXOff = bpmem.scissorOffset.x << 1; - int scissorYOff = bpmem.scissorOffset.y << 1; + int scissorXOff = bpmem.scissorOffset.x * 2; + int scissorYOff = bpmem.scissorOffset.y * 2; // TODO: ceil, floor or just cast to int? - int X = EFBToScaledX((int)ceil(xfregs.viewport.xOrig - xfregs.viewport.wd - scissorXOff)) + TargetStrideX(); - int Y = EFBToScaledY((int)ceil(xfregs.viewport.yOrig + xfregs.viewport.ht - scissorYOff)) + TargetStrideY(); - int Width = EFBToScaledX((int)ceil(2.0f * xfregs.viewport.wd)); - int Height = EFBToScaledY((int)ceil(-2.0f * xfregs.viewport.ht)); - if (Width < 0) + int intendedX = EFBToScaledX((int)ceil(xfregs.viewport.xOrig - xfregs.viewport.wd - scissorXOff)); + int intendedY = EFBToScaledY((int)ceil(xfregs.viewport.yOrig + xfregs.viewport.ht - scissorYOff)); + int intendedWd = EFBToScaledX((int)ceil(2.0f * xfregs.viewport.wd)); + int intendedHt = EFBToScaledY((int)ceil(-2.0f * xfregs.viewport.ht)); + if (intendedWd < 0) { - X += Width; - Width *= -1; + intendedX += intendedWd; + intendedWd = -intendedWd; } - if (Height < 0) + if (intendedHt < 0) { - Y += Height; - Height *= -1; + intendedY += intendedHt; + intendedHt = -intendedHt; } - bool sizeChanged = false; + + // In D3D, the viewport rectangle must fit within the render target. + int X = intendedX; if (X < 0) - { - s_Fulltarget_width -= 2 * X; X = 0; - sizeChanged=true; - } + int Y = intendedY; if (Y < 0) - { - s_Fulltarget_height -= 2 * Y; Y = 0; - sizeChanged = true; - } - if (!IS_AMD) - { - if(X + Width > Renderer::GetFullTargetWidth()) - { - s_Fulltarget_width += (X + Width - Renderer::GetFullTargetWidth()) * 2; - sizeChanged = true; - } - if(Y + Height > Renderer::GetFullTargetHeight()) - { - s_Fulltarget_height += (Y + Height - Renderer::GetFullTargetHeight()) * 2; - sizeChanged = true; - } - } + int Wd = intendedWd; + if (X + Wd > GetTargetWidth()) + Wd = GetTargetWidth() - X; + int Ht = intendedHt; + if (Y + Ht > GetTargetHeight()) + Ht = GetTargetHeight() - Y; - // TODO: If the size hasn't changed for X frames, we should probably shrink the EFB texture for performance reasons - if (sizeChanged) - { - const int ideal_width = s_Fulltarget_width; - const int ideal_height = s_Fulltarget_height; - - // Make sure that the requested size is actually supported by the GFX driver - D3D::FixTextureSize(s_Fulltarget_width, s_Fulltarget_height); - - // If the new EFB size is big enough for the requested viewport, we just recreate the internal buffer. - // Otherwise we use a hack to make the viewport fit into the smaller buffer by rendering at a lower resolution. - if (s_Fulltarget_width < ideal_width || s_Fulltarget_height < ideal_height) - { - // HACK: Skip EFB recreation and viewport setting. Most likely causes glitches in this case, but prevents crashes at least - ERROR_LOG(VIDEO, "Tried to set a viewport which is too wide to emulate with Direct3D9. Requested EFB size is %dx%d, keeping the %dx%d EFB now\n", ideal_width, ideal_height, old_fulltarget_w, old_fulltarget_h); - - // Modify the viewport to fit to the old EFB size (effectively makes us render at a lower resolution) - X = X * old_fulltarget_w / ideal_width; - Y = Y * old_fulltarget_h / ideal_height; - Width = Width * old_fulltarget_w / ideal_width; - Height = Height * old_fulltarget_h / ideal_height; - - s_Fulltarget_width = old_fulltarget_w; - s_Fulltarget_height = old_fulltarget_h; - } - else - { - D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface()); - D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface()); - - delete g_framebuffer_manager; - g_framebuffer_manager = new FramebufferManager; - - D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface()); - D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface()); - D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0); - } - } + // If GX viewport is off the render target, we must clamp our viewport + // within the bounds. Use the correction matrix to compensate. + ViewportCorrectionMatrix(vpCorrection, + intendedX, intendedY, intendedWd, intendedHt, + X, Y, Wd, Ht); D3DVIEWPORT9 vp; vp.X = X; vp.Y = Y; - vp.Width = Width; - vp.Height = Height; + vp.Width = Wd; + vp.Height = Ht; // Some games set invalids values for z min and z max so fix them to the max an min alowed and let the shaders do this work vp.MinZ = 0.0f; // (xfregs.viewport.farZ - xfregs.viewport.zRange) / 16777216.0f; @@ -830,14 +805,14 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE vp.MinZ = 0.0; vp.MaxZ = 1.0; D3D::dev->SetViewport(&vp); - D3D::drawClearQuad(GetFullTargetWidth(), GetFullTargetHeight(), color, (z & 0xFFFFFF) / float(0xFFFFFF), PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader()); + D3D::drawClearQuad(GetTargetWidth(), GetTargetHeight(), color, (z & 0xFFFFFF) / float(0xFFFFFF), PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader()); RestoreAPIState(); } void Renderer::ReinterpretPixelData(unsigned int convtype) { RECT source; - SetRect(&source, 0, 0, g_renderer->GetFullTargetWidth(), g_renderer->GetFullTargetHeight()); + SetRect(&source, 0, 0, g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight()); LPDIRECT3DPIXELSHADER9 pixel_shader; if (convtype == 0) pixel_shader = PixelShaderCache::ReinterpRGB8ToRGBA6(); @@ -854,13 +829,16 @@ void Renderer::ReinterpretPixelData(unsigned int convtype) D3DVIEWPORT9 vp; vp.X = 0; vp.Y = 0; - vp.Width = g_renderer->GetFullTargetWidth(); - vp.Height = g_renderer->GetFullTargetHeight(); + vp.Width = g_renderer->GetTargetWidth(); + vp.Height = g_renderer->GetTargetHeight(); vp.MinZ = 0.0; vp.MaxZ = 1.0; D3D::dev->SetViewport(&vp); D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); - D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture(), &source, g_renderer->GetFullTargetWidth(), g_renderer->GetFullTargetHeight(), g_renderer->GetFullTargetWidth(), g_renderer->GetFullTargetHeight(), pixel_shader, VertexShaderCache::GetSimpleVertexShader(0)); + D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture(), &source, + g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight(), + g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight(), + pixel_shader, VertexShaderCache::GetSimpleVertexShader(0)); FramebufferManager::SwapReinterpretTexture(); D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER); g_renderer->RestoreAPIState(); @@ -974,7 +952,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons vp.MinZ = 0.0f; vp.MaxZ = 1.0f; D3D::dev->SetViewport(&vp); - D3D::drawClearQuad(GetFullTargetWidth(), GetFullTargetHeight(), 0, 1.0, PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader()); + D3D::drawClearQuad(GetTargetWidth(), GetTargetHeight(), 0, 1.0, PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader()); } else { @@ -1063,7 +1041,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons { TargetRectangle targetRc = ConvertEFBRectangle(rc); LPDIRECT3DTEXTURE9 read_texture = FramebufferManager::GetEFBColorTexture(); - D3D::drawShadedTexQuad(read_texture,targetRc.AsRECT(),Renderer::GetFullTargetWidth(),Renderer::GetFullTargetHeight(),Width,Height,PixelShaderCache::GetColorCopyProgram(g_ActiveConfig.iMultisampleMode),VertexShaderCache::GetSimpleVertexShader(g_ActiveConfig.iMultisampleMode),Gamma); + D3D::drawShadedTexQuad(read_texture,targetRc.AsRECT(), + Renderer::GetTargetWidth(),Renderer::GetTargetHeight(), + Width,Height, + PixelShaderCache::GetColorCopyProgram(g_ActiveConfig.iMultisampleMode), + VertexShaderCache::GetSimpleVertexShader(g_ActiveConfig.iMultisampleMode),Gamma); } D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER); @@ -1267,7 +1249,6 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface()); D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface()); - UpdateViewport(); VertexShaderManager::SetViewportChanged(); Core::Callback_VideoCopiedToXFB(XFBWrited || (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB)); @@ -1311,7 +1292,7 @@ void Renderer::RestoreAPIState() // Gets us back into a more game-like state. D3D::SetRenderState(D3DRS_FILLMODE, g_ActiveConfig.bWireFrame ? D3DFILL_WIREFRAME : D3DFILL_SOLID); D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); - UpdateViewport(); + VertexShaderManager::SetViewportChanged(); SetScissorRect(); if (bpmem.zmode.testenable) { D3D::SetRenderState(D3DRS_ZENABLE, TRUE); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.h b/Source/Plugins/Plugin_VideoDX9/Src/Render.h index 21ddfcb730..b3c89f82f9 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.h @@ -42,7 +42,7 @@ public: void ReinterpretPixelData(unsigned int convtype); - void UpdateViewport(); + void UpdateViewport(Matrix44& vpCorrection); bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index b7b77e6d9b..7c741e08a9 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -132,7 +132,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo int SSAAMode = g_ActiveConfig.iMultisampleMode; D3D::drawShadedTexQuad(read_texture, &sourcerect, - Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(), + Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), virtualW, virtualH, // TODO: why is D3DFMT_D24X8 singled out here? why not D3DFMT_D24X4S4/D24S8/D24FS8/D32/D16/D15S1 too, or none of them? PixelShaderCache::GetDepthMatrixProgram(SSAAMode, (srcFormat == PIXELFMT_Z24) && bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8), @@ -146,8 +146,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo hash = TextureConverter::EncodeToRamFromTexture( addr, read_texture, - Renderer::GetFullTargetWidth(), - Renderer::GetFullTargetHeight(), + Renderer::GetTargetWidth(), + Renderer::GetTargetHeight(), srcFormat == PIXELFMT_Z24, isIntensity, dstFormat, diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp index 627db705bd..b41f8fd4fa 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp @@ -207,7 +207,7 @@ void Shutdown() TrnBuffers[i].Width = 0; TrnBuffers[i].Height = 0; } - WorkingBuffers = 0; + WorkingBuffers = 0; } void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc, @@ -358,12 +358,12 @@ void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyf TextureConversionShader::SetShaderParameters( (float)expandedWidth, (float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this? - (float)(Renderer::EFBToScaledX(source.left) + Renderer::TargetStrideX()), - (float)(Renderer::EFBToScaledY(source.top) + Renderer::TargetStrideY()), + (float)Renderer::EFBToScaledX(source.left), + (float)Renderer::EFBToScaledY(source.top), Renderer::EFBToScaledXf(sampleStride), Renderer::EFBToScaledYf(sampleStride), - (float)Renderer::GetFullTargetWidth(), - (float)Renderer::GetFullTargetHeight()); + (float)Renderer::GetTargetWidth(), + (float)Renderer::GetTargetHeight()); TargetRectangle scaledSource; scaledSource.top = 0; @@ -422,8 +422,8 @@ u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 So TextureConversionShader::SetShaderParameters( (float)expandedWidth, (float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this? - (float)(Renderer::EFBToScaledX(source.left) + Renderer::TargetStrideX()), - (float)(Renderer::EFBToScaledY(source.top) + Renderer::TargetStrideY()), + (float)Renderer::EFBToScaledX(source.left), + (float)Renderer::EFBToScaledY(source.top), Renderer::EFBToScaledXf(sampleStride), Renderer::EFBToScaledYf(sampleStride), (float)SourceW, @@ -461,8 +461,8 @@ void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourc 0.0f, 1.0f, 1.0f, - (float)Renderer::GetFullTargetWidth(), - (float)Renderer::GetFullTargetHeight()); + (float)Renderer::GetTargetWidth(), + (float)Renderer::GetTargetHeight()); g_renderer->ResetAPIState(); EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false,Gamma); D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface()); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index de67ae3bee..c8e667763c 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -625,10 +625,10 @@ void Renderer::RenderText(const char *text, int left, int top, u32 color) TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc) { TargetRectangle result; - result.left = EFBToScaledX(rc.left) + TargetStrideX(); - result.top = EFBToScaledY(EFB_HEIGHT - rc.top) + TargetStrideY(); - result.right = EFBToScaledX(rc.right) - (TargetStrideX() * 2); - result.bottom = EFBToScaledY(EFB_HEIGHT - rc.bottom) - (TargetStrideY() * 2); + result.left = EFBToScaledX(rc.left); + result.top = EFBToScaledY(EFB_HEIGHT - rc.top); + result.right = EFBToScaledX(rc.right); + result.bottom = EFBToScaledY(EFB_HEIGHT - rc.bottom); return result; } @@ -822,7 +822,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) } // Called from VertexShaderManager -void Renderer::UpdateViewport() +void Renderer::UpdateViewport(Matrix44& vpCorrection) { // reversed gxsetviewport(xorig, yorig, width, height, nearz, farz) // [0] = width/2 @@ -832,8 +832,8 @@ void Renderer::UpdateViewport() // [4] = yorig + height/2 + 342 // [5] = 16777215 * farz - int scissorXOff = bpmem.scissorOffset.x << 1; - int scissorYOff = bpmem.scissorOffset.y << 1; + int scissorXOff = bpmem.scissorOffset.x * 2; + int scissorYOff = bpmem.scissorOffset.y * 2; // TODO: ceil, floor or just cast to int? int X = EFBToScaledX((int)ceil(xfregs.viewport.xOrig - xfregs.viewport.wd - (float)scissorXOff)); @@ -852,6 +852,10 @@ void Renderer::UpdateViewport() Y += Height; Height *= -1; } + + // OpenGL does not require any viewport correct + Matrix44::LoadIdentity(vpCorrection); + // Update the view port glViewport(X, Y, Width, Height); glDepthRange(GLNear, GLFar); @@ -1432,7 +1436,7 @@ void Renderer::RestoreAPIState() SetColorMask(); SetDepthMode(); SetBlendMode(true); - UpdateViewport(); + VertexShaderManager::SetViewportChanged(); if (g_ActiveConfig.bWireFrame) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.h b/Source/Plugins/Plugin_VideoOGL/Src/Render.h index 4d8a0e8e2d..5805c524ae 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.h @@ -45,7 +45,7 @@ public: void ReinterpretPixelData(unsigned int convtype); - void UpdateViewport(); + void UpdateViewport(Matrix44& vpCorrection); bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc);