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
This commit is contained in:
parent
8cb2443c2f
commit
8024783502
|
@ -62,10 +62,6 @@ volatile bool Renderer::s_bScreenshot;
|
||||||
int Renderer::s_target_width;
|
int Renderer::s_target_width;
|
||||||
int Renderer::s_target_height;
|
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.
|
// TODO: Add functionality to reinit all the render targets when the window is resized.
|
||||||
int Renderer::s_backbuffer_width;
|
int Renderer::s_backbuffer_width;
|
||||||
int Renderer::s_backbuffer_height;
|
int Renderer::s_backbuffer_height;
|
||||||
|
@ -180,8 +176,8 @@ bool Renderer::CalculateTargetSize(int multiplier)
|
||||||
|
|
||||||
if (newEFBWidth != s_target_width || newEFBHeight != s_target_height)
|
if (newEFBWidth != s_target_width || newEFBHeight != s_target_height)
|
||||||
{
|
{
|
||||||
s_Fulltarget_width = s_target_width = newEFBWidth;
|
s_target_width = newEFBWidth;
|
||||||
s_Fulltarget_height = s_target_height = newEFBHeight;
|
s_target_height = newEFBHeight;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -375,7 +371,7 @@ void Renderer::RecordVideoMemory()
|
||||||
FifoRecorder::GetInstance().SetVideoMemory(bpMem, cpMem, xfMem, xfRegs, sizeof(XFRegisters) / 4);
|
FifoRecorder::GetInstance().SetVideoMemory(bpMem, cpMem, xfMem, xfRegs, sizeof(XFRegisters) / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateViewport()
|
void UpdateViewport(Matrix44& vpCorrection)
|
||||||
{
|
{
|
||||||
g_renderer->UpdateViewport();
|
g_renderer->UpdateViewport(vpCorrection);
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,12 +66,6 @@ public:
|
||||||
virtual void ApplyState(bool bUseDstAlpha) = 0;
|
virtual void ApplyState(bool bUseDstAlpha) = 0;
|
||||||
virtual void RestoreState() = 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
|
// 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 GetTargetWidth() { return s_target_width; }
|
||||||
static int GetTargetHeight() { return s_target_height; }
|
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 EFBToScaledXf(float x) { return x * ((float)GetTargetWidth() / (float)EFB_WIDTH); }
|
||||||
static float EFBToScaledYf(float y) { return y * ((float)GetTargetHeight() / (float)EFB_HEIGHT); }
|
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
|
// Random utilities
|
||||||
static void SetScreenshot(const char *filename);
|
static void SetScreenshot(const char *filename);
|
||||||
static void DrawDebugText();
|
static void DrawDebugText();
|
||||||
|
@ -124,7 +112,7 @@ public:
|
||||||
// Finish up the current frame, print some stats
|
// 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 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;
|
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_width;
|
||||||
static int s_target_height;
|
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.
|
// TODO: Add functionality to reinit all the render targets when the window is resized.
|
||||||
static int s_backbuffer_width;
|
static int s_backbuffer_width;
|
||||||
static int s_backbuffer_height;
|
static int s_backbuffer_height;
|
||||||
|
@ -189,7 +173,7 @@ private:
|
||||||
|
|
||||||
extern Renderer *g_renderer;
|
extern Renderer *g_renderer;
|
||||||
|
|
||||||
void UpdateViewport();
|
void UpdateViewport(Matrix44& vpCorrection);
|
||||||
|
|
||||||
template <typename R>
|
template <typename R>
|
||||||
void GetScissorRect(MathUtil::Rectangle<R> &rect)
|
void GetScissorRect(MathUtil::Rectangle<R> &rect)
|
||||||
|
|
|
@ -43,12 +43,13 @@ static int nNormalMatricesChanged[2]; // min,max
|
||||||
static int nPostTransformMatricesChanged[2]; // min,max
|
static int nPostTransformMatricesChanged[2]; // min,max
|
||||||
static int nLightsChanged[2]; // min,max
|
static int nLightsChanged[2]; // min,max
|
||||||
|
|
||||||
|
static Matrix44 s_viewportCorrection;
|
||||||
static Matrix33 s_viewRotationMatrix;
|
static Matrix33 s_viewRotationMatrix;
|
||||||
static Matrix33 s_viewInvRotationMatrix;
|
static Matrix33 s_viewInvRotationMatrix;
|
||||||
static float s_fViewTranslationVector[3];
|
static float s_fViewTranslationVector[3];
|
||||||
static float s_fViewRotation[2];
|
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)
|
inline void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||||
{
|
{
|
||||||
|
@ -301,7 +302,8 @@ void VertexShaderManager::SetConstants()
|
||||||
bViewportChanged = false;
|
bViewportChanged = false;
|
||||||
SetVSConstant4f(C_DEPTHPARAMS,xfregs.viewport.farZ / 16777216.0f,xfregs.viewport.zRange / 16777216.0f,0.0f,0.0f);
|
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.
|
// This is so implementation-dependent that we can't have it here.
|
||||||
UpdateViewport();
|
UpdateViewport(s_viewportCorrection);
|
||||||
|
bProjectionChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bProjectionChanged)
|
if (bProjectionChanged)
|
||||||
|
@ -421,12 +423,18 @@ void VertexShaderManager::SetConstants()
|
||||||
Matrix44::Multiply(mtxB, mtxA, viewMtx); // view = rotation x translation
|
Matrix44::Multiply(mtxB, mtxA, viewMtx); // view = rotation x translation
|
||||||
Matrix44::Set(mtxB, g_fProjectionMatrix);
|
Matrix44::Set(mtxB, g_fProjectionMatrix);
|
||||||
Matrix44::Multiply(mtxB, viewMtx, mtxA); // mtxA = projection x view
|
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
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,8 +54,8 @@ D3DTexture2D* FramebufferManager::GetResolvedEFBDepthTexture()
|
||||||
|
|
||||||
FramebufferManager::FramebufferManager()
|
FramebufferManager::FramebufferManager()
|
||||||
{
|
{
|
||||||
const unsigned int target_width = Renderer::GetFullTargetWidth();
|
const unsigned int target_width = Renderer::GetTargetWidth();
|
||||||
const unsigned int target_height = Renderer::GetFullTargetHeight();
|
const unsigned int target_height = Renderer::GetTargetHeight();
|
||||||
DXGI_SAMPLE_DESC sample_desc = D3D::GetAAMode(g_ActiveConfig.iMultisampleMode);
|
DXGI_SAMPLE_DESC sample_desc = D3D::GetAAMode(g_ActiveConfig.iMultisampleMode);
|
||||||
|
|
||||||
// EFB color texture - primary render target
|
// EFB color texture - primary render target
|
||||||
|
@ -221,7 +221,7 @@ void XFBSource::CopyEFB(float Gamma)
|
||||||
D3D::SetLinearCopySampler();
|
D3D::SetLinearCopySampler();
|
||||||
|
|
||||||
D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture()->GetSRV(), sourceRc.AsRECT(),
|
D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture()->GetSRV(), sourceRc.AsRECT(),
|
||||||
Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(),
|
Renderer::GetTargetWidth(), Renderer::GetTargetHeight(),
|
||||||
PixelShaderCache::GetColorCopyProgram(true), VertexShaderCache::GetSimpleVertexShader(),
|
PixelShaderCache::GetColorCopyProgram(true), VertexShaderCache::GetSimpleVertexShader(),
|
||||||
VertexShaderCache::GetSimpleInputLayout(),Gamma);
|
VertexShaderCache::GetSimpleInputLayout(),Gamma);
|
||||||
|
|
||||||
|
|
|
@ -1080,10 +1080,10 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat,
|
||||||
params.NumBlocksY = FLOAT(numBlocksY);
|
params.NumBlocksY = FLOAT(numBlocksY);
|
||||||
params.PosX = FLOAT(correctSrc.left);
|
params.PosX = FLOAT(correctSrc.left);
|
||||||
params.PosY = FLOAT(correctSrc.top);
|
params.PosY = FLOAT(correctSrc.top);
|
||||||
params.TexLeft = float(targetRect.left) / g_renderer->GetFullTargetWidth();
|
params.TexLeft = float(targetRect.left) / g_renderer->GetTargetWidth();
|
||||||
params.TexTop = float(targetRect.top) / g_renderer->GetFullTargetHeight();
|
params.TexTop = float(targetRect.top) / g_renderer->GetTargetHeight();
|
||||||
params.TexRight = float(targetRect.right) / g_renderer->GetFullTargetWidth();
|
params.TexRight = float(targetRect.right) / g_renderer->GetTargetWidth();
|
||||||
params.TexBottom = float(targetRect.bottom) / g_renderer->GetFullTargetHeight();
|
params.TexBottom = float(targetRect.bottom) / g_renderer->GetTargetHeight();
|
||||||
D3D::g_context->UpdateSubresource(m_encodeParams, 0, NULL, ¶ms, 0, 0);
|
D3D::g_context->UpdateSubresource(m_encodeParams, 0, NULL, ¶ms, 0, 0);
|
||||||
|
|
||||||
D3D::g_context->VSSetConstantBuffers(0, 1, &m_encodeParams);
|
D3D::g_context->VSSetConstantBuffers(0, 1, &m_encodeParams);
|
||||||
|
|
|
@ -376,8 +376,7 @@ Renderer::Renderer()
|
||||||
D3D::g_context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(), ClearColor);
|
D3D::g_context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(), ClearColor);
|
||||||
D3D::g_context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 1.f, 0);
|
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,
|
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f,
|
||||||
(float)(s_Fulltarget_height - s_target_height) / 2.f,
|
|
||||||
(float)s_target_width, (float)s_target_height);
|
(float)s_target_width, (float)s_target_height);
|
||||||
D3D::g_context->RSSetViewports(1, &vp);
|
D3D::g_context->RSSetViewports(1, &vp);
|
||||||
D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
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 Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
|
||||||
{
|
{
|
||||||
TargetRectangle result;
|
TargetRectangle result;
|
||||||
result.left = EFBToScaledX(rc.left) + TargetStrideX();
|
result.left = EFBToScaledX(rc.left);
|
||||||
result.top = EFBToScaledY(rc.top) + TargetStrideY();
|
result.top = EFBToScaledY(rc.top);
|
||||||
result.right = EFBToScaledX(rc.right) + TargetStrideX();
|
result.right = EFBToScaledX(rc.right);
|
||||||
result.bottom = EFBToScaledY(rc.bottom) + TargetStrideY();
|
result.bottom = EFBToScaledY(rc.bottom);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,10 +456,10 @@ bool Renderer::SetScissorRect()
|
||||||
if (rc.top > EFB_HEIGHT) rc.top = EFB_HEIGHT;
|
if (rc.top > EFB_HEIGHT) rc.top = EFB_HEIGHT;
|
||||||
if (rc.bottom > EFB_HEIGHT) rc.bottom = EFB_HEIGHT;
|
if (rc.bottom > EFB_HEIGHT) rc.bottom = EFB_HEIGHT;
|
||||||
|
|
||||||
rc.left = EFBToScaledX(rc.left) + TargetStrideX();
|
rc.left = EFBToScaledX(rc.left);
|
||||||
rc.right = EFBToScaledX(rc.right) + TargetStrideX();
|
rc.right = EFBToScaledX(rc.right);
|
||||||
rc.top = EFBToScaledY(rc.top) + TargetStrideY();
|
rc.top = EFBToScaledY(rc.top);
|
||||||
rc.bottom = EFBToScaledY(rc.bottom) + TargetStrideY();
|
rc.bottom = EFBToScaledY(rc.bottom);
|
||||||
|
|
||||||
if (rc.left > rc.right)
|
if (rc.left > rc.right)
|
||||||
{
|
{
|
||||||
|
@ -483,8 +482,8 @@ bool Renderer::SetScissorRect()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//WARN_LOG(VIDEO, "Bad scissor rectangle: %i %i %i %i", rc.left, rc.top, rc.right, rc.bottom);
|
//WARN_LOG(VIDEO, "Bad scissor rectangle: %i %i %i %i", rc.left, rc.top, rc.right, rc.bottom);
|
||||||
*rc.AsRECT() = CD3D11_RECT(TargetStrideX(), TargetStrideY(),
|
*rc.AsRECT() = CD3D11_RECT(0, 0,
|
||||||
TargetStrideX() + s_target_width, TargetStrideY() + s_target_height);
|
s_target_width, s_target_height);
|
||||||
D3D::g_context->RSSetScissorRects(1, rc.AsRECT());
|
D3D::g_context->RSSetScissorRects(1, rc.AsRECT());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -570,8 +569,8 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
D3D::SetPointCopySampler();
|
D3D::SetPointCopySampler();
|
||||||
D3D::drawShadedTexQuad(FramebufferManager::GetEFBDepthTexture()->GetSRV(),
|
D3D::drawShadedTexQuad(FramebufferManager::GetEFBDepthTexture()->GetSRV(),
|
||||||
&RectToLock,
|
&RectToLock,
|
||||||
Renderer::GetFullTargetWidth(),
|
Renderer::GetTargetWidth(),
|
||||||
Renderer::GetFullTargetHeight(),
|
Renderer::GetTargetHeight(),
|
||||||
PixelShaderCache::GetDepthMatrixProgram(true),
|
PixelShaderCache::GetDepthMatrixProgram(true),
|
||||||
VertexShaderCache::GetSimpleVertexShader(),
|
VertexShaderCache::GetSimpleVertexShader(),
|
||||||
VertexShaderCache::GetSimpleInputLayout());
|
VertexShaderCache::GetSimpleInputLayout());
|
||||||
|
@ -647,18 +646,40 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
ResetAPIState();
|
ResetAPIState();
|
||||||
|
|
||||||
D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), NULL);
|
D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), NULL);
|
||||||
D3D::drawColorQuad(rgbaColor, (float)RectToLock.left * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f,
|
D3D::drawColorQuad(rgbaColor, (float)RectToLock.left * 2.f / (float)Renderer::GetTargetWidth() - 1.f,
|
||||||
- (float)RectToLock.top * 2.f / (float)Renderer::GetFullTargetHeight() + 1.f,
|
- (float)RectToLock.top * 2.f / (float)Renderer::GetTargetHeight() + 1.f,
|
||||||
(float)RectToLock.right * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f,
|
(float)RectToLock.right * 2.f / (float)Renderer::GetTargetWidth() - 1.f,
|
||||||
- (float)RectToLock.bottom * 2.f / (float)Renderer::GetFullTargetHeight() + 1.f);
|
- (float)RectToLock.bottom * 2.f / (float)Renderer::GetTargetHeight() + 1.f);
|
||||||
|
|
||||||
RestoreAPIState();
|
RestoreAPIState();
|
||||||
return 0;
|
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
|
// Called from VertexShaderManager
|
||||||
void Renderer::UpdateViewport()
|
void Renderer::UpdateViewport(Matrix44& vpCorrection)
|
||||||
{
|
{
|
||||||
// reversed gxsetviewport(xorig, yorig, width, height, nearz, farz)
|
// reversed gxsetviewport(xorig, yorig, width, height, nearz, farz)
|
||||||
// [0] = width/2
|
// [0] = width/2
|
||||||
|
@ -667,80 +688,49 @@ void Renderer::UpdateViewport()
|
||||||
// [3] = xorig + width/2 + 342
|
// [3] = xorig + width/2 + 342
|
||||||
// [4] = yorig + height/2 + 342
|
// [4] = yorig + height/2 + 342
|
||||||
// [5] = 16777215 * farz
|
// [5] = 16777215 * farz
|
||||||
const int old_fulltarget_w = Renderer::GetFullTargetWidth();
|
|
||||||
const int old_fulltarget_h = Renderer::GetFullTargetHeight();
|
|
||||||
|
|
||||||
int scissorXOff = bpmem.scissorOffset.x << 1;
|
int scissorXOff = bpmem.scissorOffset.x * 2;
|
||||||
int scissorYOff = bpmem.scissorOffset.y << 1;
|
int scissorYOff = bpmem.scissorOffset.y * 2;
|
||||||
|
|
||||||
// TODO: ceil, floor or just cast to int?
|
// TODO: ceil, floor or just cast to int?
|
||||||
// TODO: Directly use the floats instead of rounding them?
|
// 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 intendedX = Renderer::EFBToScaledX((int)ceil(xfregs.viewport.xOrig - xfregs.viewport.wd - scissorXOff));
|
||||||
int Y = Renderer::EFBToScaledY((int)ceil(xfregs.viewport.yOrig + xfregs.viewport.ht - scissorYOff)) + Renderer::TargetStrideY();
|
int intendedY = Renderer::EFBToScaledY((int)ceil(xfregs.viewport.yOrig + xfregs.viewport.ht - scissorYOff));
|
||||||
int Width = Renderer::EFBToScaledX((int)ceil(2.0f * xfregs.viewport.wd));
|
int intendedWd = Renderer::EFBToScaledX((int)ceil(2.0f * xfregs.viewport.wd));
|
||||||
int Height = Renderer::EFBToScaledY((int)ceil(-2.0f * xfregs.viewport.ht));
|
int intendedHt = Renderer::EFBToScaledY((int)ceil(-2.0f * xfregs.viewport.ht));
|
||||||
if (Width < 0)
|
if (intendedWd < 0)
|
||||||
{
|
{
|
||||||
X += Width;
|
intendedX += intendedWd;
|
||||||
Width *= -1;
|
intendedWd = -intendedWd;
|
||||||
}
|
}
|
||||||
if (Height < 0)
|
if (intendedHt < 0)
|
||||||
{
|
{
|
||||||
Y += Height;
|
intendedY += intendedHt;
|
||||||
Height *= -1;
|
intendedHt = -intendedHt;
|
||||||
}
|
}
|
||||||
bool sizeChanged = false;
|
|
||||||
|
// In D3D, the viewport rectangle must fit within the render target.
|
||||||
|
int X = intendedX;
|
||||||
if (X < 0)
|
if (X < 0)
|
||||||
{
|
|
||||||
s_Fulltarget_width -= 2 * X;
|
|
||||||
X = 0;
|
X = 0;
|
||||||
sizeChanged = true;
|
int Y = intendedY;
|
||||||
}
|
|
||||||
if (Y < 0)
|
if (Y < 0)
|
||||||
{
|
|
||||||
s_Fulltarget_height -= 2 * Y;
|
|
||||||
Y = 0;
|
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;
|
// If GX viewport is off the render target, we must clamp our viewport
|
||||||
float newy = (float)Y;
|
// within the bounds. Use the correction matrix to compensate.
|
||||||
float newwidth = (float)Width;
|
ViewportCorrectionMatrix(vpCorrection,
|
||||||
float newheight = (float)Height;
|
intendedX, intendedY, intendedWd, intendedHt,
|
||||||
// TODO: If the size hasn't changed for X frames, we should probably shrink the EFB texture for performance reasons
|
X, Y, Wd, Ht);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
// 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;
|
0.f, // (xfregs.viewport.farZ - xfregs.viewport.zRange) / 16777216.0f;
|
||||||
1.f); // xfregs.viewport.farZ / 16777216.0f;
|
1.f); // xfregs.viewport.farZ / 16777216.0f;
|
||||||
D3D::g_context->RSSetViewports(1, &vp);
|
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)
|
void Renderer::ReinterpretPixelData(unsigned int convtype)
|
||||||
{
|
{
|
||||||
// TODO: MSAA support..
|
// 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;
|
ID3D11PixelShader* pixel_shader;
|
||||||
if (convtype == 0) pixel_shader = PixelShaderCache::ReinterpRGB8ToRGBA6(true);
|
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
|
// convert data and set the target texture as our new EFB
|
||||||
g_renderer->ResetAPIState();
|
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->RSSetViewports(1, &vp);
|
||||||
|
|
||||||
D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTempTexture()->GetRTV(), NULL);
|
D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTempTexture()->GetRTV(), NULL);
|
||||||
D3D::SetPointCopySampler();
|
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();
|
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
|
// TODO: Improve sampling algorithm for the pixel shader so that we can use the multisampled EFB texture as source
|
||||||
D3DTexture2D* read_texture = FramebufferManager::GetResolvedEFBColorTexture();
|
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
|
// 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();
|
Renderer::RestoreAPIState();
|
||||||
D3D::BeginFrame();
|
D3D::BeginFrame();
|
||||||
D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
|
||||||
UpdateViewport();
|
|
||||||
VertexShaderManager::SetViewportChanged();
|
VertexShaderManager::SetViewportChanged();
|
||||||
|
|
||||||
Core::Callback_VideoCopiedToXFB(XFBWrited || (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB));
|
Core::Callback_VideoCopiedToXFB(XFBWrited || (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB));
|
||||||
|
@ -1167,7 +1162,7 @@ void Renderer::RestoreAPIState()
|
||||||
D3D::stateman->PopBlendState();
|
D3D::stateman->PopBlendState();
|
||||||
D3D::stateman->PopDepthState();
|
D3D::stateman->PopDepthState();
|
||||||
D3D::stateman->PopRasterizerState();
|
D3D::stateman->PopRasterizerState();
|
||||||
UpdateViewport();
|
VertexShaderManager::SetViewportChanged();
|
||||||
SetScissorRect();
|
SetScissorRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
|
|
||||||
void ReinterpretPixelData(unsigned int convtype);
|
void ReinterpretPixelData(unsigned int convtype);
|
||||||
|
|
||||||
void UpdateViewport();
|
void UpdateViewport(Matrix44& vpCorrection);
|
||||||
|
|
||||||
bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc);
|
bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc);
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
|
||||||
// Create texture copy
|
// Create texture copy
|
||||||
D3D::drawShadedTexQuad(
|
D3D::drawShadedTexQuad(
|
||||||
(srcFormat == PIXELFMT_Z24) ? FramebufferManager::GetEFBDepthTexture()->GetSRV() : FramebufferManager::GetEFBColorTexture()->GetSRV(),
|
(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),
|
(srcFormat == PIXELFMT_Z24) ? PixelShaderCache::GetDepthMatrixProgram(true) : PixelShaderCache::GetColorMatrixProgram(true),
|
||||||
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());
|
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());
|
||||||
|
|
||||||
|
|
|
@ -289,10 +289,10 @@ void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcR
|
||||||
XFBEncodeParams params = { 0 };
|
XFBEncodeParams params = { 0 };
|
||||||
params.Width = FLOAT(width);
|
params.Width = FLOAT(width);
|
||||||
params.Height = FLOAT(height);
|
params.Height = FLOAT(height);
|
||||||
params.TexLeft = FLOAT(targetRect.left) / g_renderer->GetFullTargetWidth();
|
params.TexLeft = FLOAT(targetRect.left) / g_renderer->GetTargetWidth();
|
||||||
params.TexTop = FLOAT(targetRect.top) / g_renderer->GetFullTargetHeight();
|
params.TexTop = FLOAT(targetRect.top) / g_renderer->GetTargetHeight();
|
||||||
params.TexRight = FLOAT(targetRect.right) / g_renderer->GetFullTargetWidth();
|
params.TexRight = FLOAT(targetRect.right) / g_renderer->GetTargetWidth();
|
||||||
params.TexBottom = FLOAT(targetRect.bottom) / g_renderer->GetFullTargetHeight();
|
params.TexBottom = FLOAT(targetRect.bottom) / g_renderer->GetTargetHeight();
|
||||||
params.Gamma = gamma;
|
params.Gamma = gamma;
|
||||||
D3D::g_context->UpdateSubresource(m_encodeParams, 0, NULL, ¶ms, 0, 0);
|
D3D::g_context->UpdateSubresource(m_encodeParams, 0, NULL, ¶ms, 0, 0);
|
||||||
|
|
||||||
|
|
|
@ -44,8 +44,8 @@ FramebufferManager::Efb FramebufferManager::s_efb;
|
||||||
FramebufferManager::FramebufferManager()
|
FramebufferManager::FramebufferManager()
|
||||||
{
|
{
|
||||||
bool depth_textures_supported = true;
|
bool depth_textures_supported = true;
|
||||||
int target_width = Renderer::GetFullTargetWidth();
|
int target_width = Renderer::GetTargetWidth();
|
||||||
int target_height = Renderer::GetFullTargetHeight();
|
int target_height = Renderer::GetTargetHeight();
|
||||||
s_efb.color_surface_Format = D3DFMT_A8R8G8B8;
|
s_efb.color_surface_Format = D3DFMT_A8R8G8B8;
|
||||||
|
|
||||||
// EFB color texture - primary render target
|
// EFB color texture - primary render target
|
||||||
|
@ -217,8 +217,8 @@ void XFBSource::CopyEFB(float Gamma)
|
||||||
D3D::drawShadedTexQuad(
|
D3D::drawShadedTexQuad(
|
||||||
FramebufferManager::GetEFBColorTexture(),
|
FramebufferManager::GetEFBColorTexture(),
|
||||||
&sourcerect,
|
&sourcerect,
|
||||||
Renderer::GetFullTargetWidth(),
|
Renderer::GetTargetWidth(),
|
||||||
Renderer::GetFullTargetHeight(),
|
Renderer::GetTargetHeight(),
|
||||||
texWidth,
|
texWidth,
|
||||||
texHeight,
|
texHeight,
|
||||||
PixelShaderCache::GetColorCopyProgram( g_ActiveConfig.iMultisampleMode),
|
PixelShaderCache::GetColorCopyProgram( g_ActiveConfig.iMultisampleMode),
|
||||||
|
|
|
@ -294,7 +294,7 @@ Renderer::Renderer()
|
||||||
CalculateTargetSize(SupersampleCoeficient);
|
CalculateTargetSize(SupersampleCoeficient);
|
||||||
|
|
||||||
// Make sure to use valid texture sizes
|
// 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_bLastFrameDumped = false;
|
||||||
s_bAVIDumping = false;
|
s_bAVIDumping = false;
|
||||||
|
@ -323,8 +323,8 @@ Renderer::Renderer()
|
||||||
|
|
||||||
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||||
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||||
vp.X = TargetStrideX();
|
vp.X = 0;
|
||||||
vp.Y = TargetStrideY();
|
vp.Y = 0;
|
||||||
vp.Width = s_target_width;
|
vp.Width = s_target_width;
|
||||||
vp.Height = s_target_height;
|
vp.Height = s_target_height;
|
||||||
D3D::dev->SetViewport(&vp);
|
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 Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
|
||||||
{
|
{
|
||||||
TargetRectangle result;
|
TargetRectangle result;
|
||||||
result.left = EFBToScaledX(rc.left) + TargetStrideX();
|
result.left = EFBToScaledX(rc.left);
|
||||||
result.top = EFBToScaledY(rc.top) + TargetStrideY();
|
result.top = EFBToScaledY(rc.top);
|
||||||
result.right = EFBToScaledX(rc.right) + TargetStrideX();
|
result.right = EFBToScaledX(rc.right);
|
||||||
result.bottom = EFBToScaledY(rc.bottom) + TargetStrideY();
|
result.bottom = EFBToScaledY(rc.bottom);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,10 +454,10 @@ bool Renderer::SetScissorRect()
|
||||||
rc.top = temp;
|
rc.top = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc.left = EFBToScaledX(rc.left) + TargetStrideX();
|
rc.left = EFBToScaledX(rc.left);
|
||||||
rc.top = EFBToScaledY(rc.top) + TargetStrideY();
|
rc.top = EFBToScaledY(rc.top);
|
||||||
rc.right = EFBToScaledX(rc.right) + TargetStrideX();
|
rc.right = EFBToScaledX(rc.right);
|
||||||
rc.bottom = EFBToScaledY(rc.bottom) + TargetStrideY();
|
rc.bottom = EFBToScaledY(rc.bottom);
|
||||||
|
|
||||||
// Check that the coordinates are good
|
// Check that the coordinates are good
|
||||||
if (rc.right != rc.left && rc.bottom != rc.top)
|
if (rc.right != rc.left && rc.bottom != rc.top)
|
||||||
|
@ -468,10 +468,10 @@ bool Renderer::SetScissorRect()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//WARN_LOG(VIDEO, "Bad scissor rectangle: %i %i %i %i", rc.left, rc.top, rc.right, rc.bottom);
|
//WARN_LOG(VIDEO, "Bad scissor rectangle: %i %i %i %i", rc.left, rc.top, rc.right, rc.bottom);
|
||||||
rc.left = TargetStrideX();
|
rc.left = 0;
|
||||||
rc.top = TargetStrideY();
|
rc.top = 0;
|
||||||
rc.right = TargetStrideX() + s_target_width;
|
rc.right = s_target_width;
|
||||||
rc.bottom = TargetStrideY() + s_target_height;
|
rc.bottom = s_target_height;
|
||||||
D3D::dev->SetScissorRect(rc.AsRECT());
|
D3D::dev->SetScissorRect(rc.AsRECT());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -606,8 +606,8 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
D3D::drawShadedTexQuad(
|
D3D::drawShadedTexQuad(
|
||||||
read_texture,
|
read_texture,
|
||||||
&RectToLock,
|
&RectToLock,
|
||||||
Renderer::GetFullTargetWidth(),
|
Renderer::GetTargetWidth(),
|
||||||
Renderer::GetFullTargetHeight(),
|
Renderer::GetTargetHeight(),
|
||||||
4, 4,
|
4, 4,
|
||||||
PixelShaderCache::GetDepthMatrixProgram(0, bformat != FOURCC_RAWZ),
|
PixelShaderCache::GetDepthMatrixProgram(0, bformat != FOURCC_RAWZ),
|
||||||
VertexShaderCache::GetSimpleVertexShader(0));
|
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?
|
// TODO: Speed this up by batching pokes?
|
||||||
ResetAPIState();
|
ResetAPIState();
|
||||||
D3D::drawColorQuad(GetFullTargetWidth(), GetFullTargetHeight(), poke_data,
|
D3D::drawColorQuad(GetTargetWidth(), GetTargetHeight(), poke_data,
|
||||||
(float)RectToLock.left * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f,
|
(float)RectToLock.left * 2.f / (float)Renderer::GetTargetWidth() - 1.f,
|
||||||
- (float)RectToLock.top * 2.f / (float)Renderer::GetFullTargetHeight() + 1.f,
|
- (float)RectToLock.top * 2.f / (float)Renderer::GetTargetHeight() + 1.f,
|
||||||
(float)RectToLock.right * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f,
|
(float)RectToLock.right * 2.f / (float)Renderer::GetTargetWidth() - 1.f,
|
||||||
- (float)RectToLock.bottom * 2.f / (float)Renderer::GetFullTargetHeight() + 1.f);
|
- (float)RectToLock.bottom * 2.f / (float)Renderer::GetTargetHeight() + 1.f);
|
||||||
RestoreAPIState();
|
RestoreAPIState();
|
||||||
return 0;
|
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
|
// Called from VertexShaderManager
|
||||||
void Renderer::UpdateViewport()
|
void Renderer::UpdateViewport(Matrix44& vpCorrection)
|
||||||
{
|
{
|
||||||
// reversed gxsetviewport(xorig, yorig, width, height, nearz, farz)
|
// reversed gxsetviewport(xorig, yorig, width, height, nearz, farz)
|
||||||
// [0] = width/2
|
// [0] = width/2
|
||||||
|
@ -700,98 +722,51 @@ void Renderer::UpdateViewport()
|
||||||
// [3] = xorig + width/2 + 342
|
// [3] = xorig + width/2 + 342
|
||||||
// [4] = yorig + height/2 + 342
|
// [4] = yorig + height/2 + 342
|
||||||
// [5] = 16777215 * farz
|
// [5] = 16777215 * farz
|
||||||
const int old_fulltarget_w = Renderer::GetFullTargetWidth();
|
|
||||||
const int old_fulltarget_h = Renderer::GetFullTargetHeight();
|
|
||||||
|
|
||||||
int scissorXOff = bpmem.scissorOffset.x << 1;
|
int scissorXOff = bpmem.scissorOffset.x * 2;
|
||||||
int scissorYOff = bpmem.scissorOffset.y << 1;
|
int scissorYOff = bpmem.scissorOffset.y * 2;
|
||||||
|
|
||||||
// TODO: ceil, floor or just cast to int?
|
// TODO: ceil, floor or just cast to int?
|
||||||
int X = EFBToScaledX((int)ceil(xfregs.viewport.xOrig - xfregs.viewport.wd - scissorXOff)) + TargetStrideX();
|
int intendedX = EFBToScaledX((int)ceil(xfregs.viewport.xOrig - xfregs.viewport.wd - scissorXOff));
|
||||||
int Y = EFBToScaledY((int)ceil(xfregs.viewport.yOrig + xfregs.viewport.ht - scissorYOff)) + TargetStrideY();
|
int intendedY = EFBToScaledY((int)ceil(xfregs.viewport.yOrig + xfregs.viewport.ht - scissorYOff));
|
||||||
int Width = EFBToScaledX((int)ceil(2.0f * xfregs.viewport.wd));
|
int intendedWd = EFBToScaledX((int)ceil(2.0f * xfregs.viewport.wd));
|
||||||
int Height = EFBToScaledY((int)ceil(-2.0f * xfregs.viewport.ht));
|
int intendedHt = EFBToScaledY((int)ceil(-2.0f * xfregs.viewport.ht));
|
||||||
if (Width < 0)
|
if (intendedWd < 0)
|
||||||
{
|
{
|
||||||
X += Width;
|
intendedX += intendedWd;
|
||||||
Width *= -1;
|
intendedWd = -intendedWd;
|
||||||
}
|
}
|
||||||
if (Height < 0)
|
if (intendedHt < 0)
|
||||||
{
|
{
|
||||||
Y += Height;
|
intendedY += intendedHt;
|
||||||
Height *= -1;
|
intendedHt = -intendedHt;
|
||||||
}
|
}
|
||||||
bool sizeChanged = false;
|
|
||||||
|
// In D3D, the viewport rectangle must fit within the render target.
|
||||||
|
int X = intendedX;
|
||||||
if (X < 0)
|
if (X < 0)
|
||||||
{
|
|
||||||
s_Fulltarget_width -= 2 * X;
|
|
||||||
X = 0;
|
X = 0;
|
||||||
sizeChanged=true;
|
int Y = intendedY;
|
||||||
}
|
|
||||||
if (Y < 0)
|
if (Y < 0)
|
||||||
{
|
|
||||||
s_Fulltarget_height -= 2 * Y;
|
|
||||||
Y = 0;
|
Y = 0;
|
||||||
sizeChanged = true;
|
int Wd = intendedWd;
|
||||||
}
|
if (X + Wd > GetTargetWidth())
|
||||||
if (!IS_AMD)
|
Wd = GetTargetWidth() - X;
|
||||||
{
|
int Ht = intendedHt;
|
||||||
if(X + Width > Renderer::GetFullTargetWidth())
|
if (Y + Ht > GetTargetHeight())
|
||||||
{
|
Ht = GetTargetHeight() - Y;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: If the size hasn't changed for X frames, we should probably shrink the EFB texture for performance reasons
|
// If GX viewport is off the render target, we must clamp our viewport
|
||||||
if (sizeChanged)
|
// within the bounds. Use the correction matrix to compensate.
|
||||||
{
|
ViewportCorrectionMatrix(vpCorrection,
|
||||||
const int ideal_width = s_Fulltarget_width;
|
intendedX, intendedY, intendedWd, intendedHt,
|
||||||
const int ideal_height = s_Fulltarget_height;
|
X, Y, Wd, Ht);
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
D3DVIEWPORT9 vp;
|
D3DVIEWPORT9 vp;
|
||||||
vp.X = X;
|
vp.X = X;
|
||||||
vp.Y = Y;
|
vp.Y = Y;
|
||||||
vp.Width = Width;
|
vp.Width = Wd;
|
||||||
vp.Height = Height;
|
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
|
// 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;
|
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.MinZ = 0.0;
|
||||||
vp.MaxZ = 1.0;
|
vp.MaxZ = 1.0;
|
||||||
D3D::dev->SetViewport(&vp);
|
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();
|
RestoreAPIState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::ReinterpretPixelData(unsigned int convtype)
|
void Renderer::ReinterpretPixelData(unsigned int convtype)
|
||||||
{
|
{
|
||||||
RECT source;
|
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;
|
LPDIRECT3DPIXELSHADER9 pixel_shader;
|
||||||
if (convtype == 0) pixel_shader = PixelShaderCache::ReinterpRGB8ToRGBA6();
|
if (convtype == 0) pixel_shader = PixelShaderCache::ReinterpRGB8ToRGBA6();
|
||||||
|
@ -854,13 +829,16 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
|
||||||
D3DVIEWPORT9 vp;
|
D3DVIEWPORT9 vp;
|
||||||
vp.X = 0;
|
vp.X = 0;
|
||||||
vp.Y = 0;
|
vp.Y = 0;
|
||||||
vp.Width = g_renderer->GetFullTargetWidth();
|
vp.Width = g_renderer->GetTargetWidth();
|
||||||
vp.Height = g_renderer->GetFullTargetHeight();
|
vp.Height = g_renderer->GetTargetHeight();
|
||||||
vp.MinZ = 0.0;
|
vp.MinZ = 0.0;
|
||||||
vp.MaxZ = 1.0;
|
vp.MaxZ = 1.0;
|
||||||
D3D::dev->SetViewport(&vp);
|
D3D::dev->SetViewport(&vp);
|
||||||
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
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();
|
FramebufferManager::SwapReinterpretTexture();
|
||||||
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
|
||||||
g_renderer->RestoreAPIState();
|
g_renderer->RestoreAPIState();
|
||||||
|
@ -974,7 +952,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||||
vp.MinZ = 0.0f;
|
vp.MinZ = 0.0f;
|
||||||
vp.MaxZ = 1.0f;
|
vp.MaxZ = 1.0f;
|
||||||
D3D::dev->SetViewport(&vp);
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -1063,7 +1041,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||||
{
|
{
|
||||||
TargetRectangle targetRc = ConvertEFBRectangle(rc);
|
TargetRectangle targetRc = ConvertEFBRectangle(rc);
|
||||||
LPDIRECT3DTEXTURE9 read_texture = FramebufferManager::GetEFBColorTexture();
|
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);
|
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->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||||
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||||
UpdateViewport();
|
|
||||||
VertexShaderManager::SetViewportChanged();
|
VertexShaderManager::SetViewportChanged();
|
||||||
|
|
||||||
Core::Callback_VideoCopiedToXFB(XFBWrited || (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB));
|
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.
|
// Gets us back into a more game-like state.
|
||||||
D3D::SetRenderState(D3DRS_FILLMODE, g_ActiveConfig.bWireFrame ? D3DFILL_WIREFRAME : D3DFILL_SOLID);
|
D3D::SetRenderState(D3DRS_FILLMODE, g_ActiveConfig.bWireFrame ? D3DFILL_WIREFRAME : D3DFILL_SOLID);
|
||||||
D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
||||||
UpdateViewport();
|
VertexShaderManager::SetViewportChanged();
|
||||||
SetScissorRect();
|
SetScissorRect();
|
||||||
if (bpmem.zmode.testenable) {
|
if (bpmem.zmode.testenable) {
|
||||||
D3D::SetRenderState(D3DRS_ZENABLE, TRUE);
|
D3D::SetRenderState(D3DRS_ZENABLE, TRUE);
|
||||||
|
|
|
@ -42,7 +42,7 @@ public:
|
||||||
|
|
||||||
void ReinterpretPixelData(unsigned int convtype);
|
void ReinterpretPixelData(unsigned int convtype);
|
||||||
|
|
||||||
void UpdateViewport();
|
void UpdateViewport(Matrix44& vpCorrection);
|
||||||
|
|
||||||
bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc);
|
bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc);
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
|
||||||
int SSAAMode = g_ActiveConfig.iMultisampleMode;
|
int SSAAMode = g_ActiveConfig.iMultisampleMode;
|
||||||
|
|
||||||
D3D::drawShadedTexQuad(read_texture, &sourcerect,
|
D3D::drawShadedTexQuad(read_texture, &sourcerect,
|
||||||
Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(),
|
Renderer::GetTargetWidth(), Renderer::GetTargetHeight(),
|
||||||
virtualW, virtualH,
|
virtualW, virtualH,
|
||||||
// TODO: why is D3DFMT_D24X8 singled out here? why not D3DFMT_D24X4S4/D24S8/D24FS8/D32/D16/D15S1 too, or none of them?
|
// 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),
|
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(
|
hash = TextureConverter::EncodeToRamFromTexture(
|
||||||
addr,
|
addr,
|
||||||
read_texture,
|
read_texture,
|
||||||
Renderer::GetFullTargetWidth(),
|
Renderer::GetTargetWidth(),
|
||||||
Renderer::GetFullTargetHeight(),
|
Renderer::GetTargetHeight(),
|
||||||
srcFormat == PIXELFMT_Z24,
|
srcFormat == PIXELFMT_Z24,
|
||||||
isIntensity,
|
isIntensity,
|
||||||
dstFormat,
|
dstFormat,
|
||||||
|
|
|
@ -207,7 +207,7 @@ void Shutdown()
|
||||||
TrnBuffers[i].Width = 0;
|
TrnBuffers[i].Width = 0;
|
||||||
TrnBuffers[i].Height = 0;
|
TrnBuffers[i].Height = 0;
|
||||||
}
|
}
|
||||||
WorkingBuffers = 0;
|
WorkingBuffers = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc,
|
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(
|
TextureConversionShader::SetShaderParameters(
|
||||||
(float)expandedWidth,
|
(float)expandedWidth,
|
||||||
(float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this?
|
(float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this?
|
||||||
(float)(Renderer::EFBToScaledX(source.left) + Renderer::TargetStrideX()),
|
(float)Renderer::EFBToScaledX(source.left),
|
||||||
(float)(Renderer::EFBToScaledY(source.top) + Renderer::TargetStrideY()),
|
(float)Renderer::EFBToScaledY(source.top),
|
||||||
Renderer::EFBToScaledXf(sampleStride),
|
Renderer::EFBToScaledXf(sampleStride),
|
||||||
Renderer::EFBToScaledYf(sampleStride),
|
Renderer::EFBToScaledYf(sampleStride),
|
||||||
(float)Renderer::GetFullTargetWidth(),
|
(float)Renderer::GetTargetWidth(),
|
||||||
(float)Renderer::GetFullTargetHeight());
|
(float)Renderer::GetTargetHeight());
|
||||||
|
|
||||||
TargetRectangle scaledSource;
|
TargetRectangle scaledSource;
|
||||||
scaledSource.top = 0;
|
scaledSource.top = 0;
|
||||||
|
@ -422,8 +422,8 @@ u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 So
|
||||||
TextureConversionShader::SetShaderParameters(
|
TextureConversionShader::SetShaderParameters(
|
||||||
(float)expandedWidth,
|
(float)expandedWidth,
|
||||||
(float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this?
|
(float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this?
|
||||||
(float)(Renderer::EFBToScaledX(source.left) + Renderer::TargetStrideX()),
|
(float)Renderer::EFBToScaledX(source.left),
|
||||||
(float)(Renderer::EFBToScaledY(source.top) + Renderer::TargetStrideY()),
|
(float)Renderer::EFBToScaledY(source.top),
|
||||||
Renderer::EFBToScaledXf(sampleStride),
|
Renderer::EFBToScaledXf(sampleStride),
|
||||||
Renderer::EFBToScaledYf(sampleStride),
|
Renderer::EFBToScaledYf(sampleStride),
|
||||||
(float)SourceW,
|
(float)SourceW,
|
||||||
|
@ -461,8 +461,8 @@ void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourc
|
||||||
0.0f,
|
0.0f,
|
||||||
1.0f,
|
1.0f,
|
||||||
1.0f,
|
1.0f,
|
||||||
(float)Renderer::GetFullTargetWidth(),
|
(float)Renderer::GetTargetWidth(),
|
||||||
(float)Renderer::GetFullTargetHeight());
|
(float)Renderer::GetTargetHeight());
|
||||||
g_renderer->ResetAPIState();
|
g_renderer->ResetAPIState();
|
||||||
EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false,Gamma);
|
EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false,Gamma);
|
||||||
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||||
|
|
|
@ -625,10 +625,10 @@ void Renderer::RenderText(const char *text, int left, int top, u32 color)
|
||||||
TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
|
TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
|
||||||
{
|
{
|
||||||
TargetRectangle result;
|
TargetRectangle result;
|
||||||
result.left = EFBToScaledX(rc.left) + TargetStrideX();
|
result.left = EFBToScaledX(rc.left);
|
||||||
result.top = EFBToScaledY(EFB_HEIGHT - rc.top) + TargetStrideY();
|
result.top = EFBToScaledY(EFB_HEIGHT - rc.top);
|
||||||
result.right = EFBToScaledX(rc.right) - (TargetStrideX() * 2);
|
result.right = EFBToScaledX(rc.right);
|
||||||
result.bottom = EFBToScaledY(EFB_HEIGHT - rc.bottom) - (TargetStrideY() * 2);
|
result.bottom = EFBToScaledY(EFB_HEIGHT - rc.bottom);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -822,7 +822,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from VertexShaderManager
|
// Called from VertexShaderManager
|
||||||
void Renderer::UpdateViewport()
|
void Renderer::UpdateViewport(Matrix44& vpCorrection)
|
||||||
{
|
{
|
||||||
// reversed gxsetviewport(xorig, yorig, width, height, nearz, farz)
|
// reversed gxsetviewport(xorig, yorig, width, height, nearz, farz)
|
||||||
// [0] = width/2
|
// [0] = width/2
|
||||||
|
@ -832,8 +832,8 @@ void Renderer::UpdateViewport()
|
||||||
// [4] = yorig + height/2 + 342
|
// [4] = yorig + height/2 + 342
|
||||||
// [5] = 16777215 * farz
|
// [5] = 16777215 * farz
|
||||||
|
|
||||||
int scissorXOff = bpmem.scissorOffset.x << 1;
|
int scissorXOff = bpmem.scissorOffset.x * 2;
|
||||||
int scissorYOff = bpmem.scissorOffset.y << 1;
|
int scissorYOff = bpmem.scissorOffset.y * 2;
|
||||||
|
|
||||||
// TODO: ceil, floor or just cast to int?
|
// TODO: ceil, floor or just cast to int?
|
||||||
int X = EFBToScaledX((int)ceil(xfregs.viewport.xOrig - xfregs.viewport.wd - (float)scissorXOff));
|
int X = EFBToScaledX((int)ceil(xfregs.viewport.xOrig - xfregs.viewport.wd - (float)scissorXOff));
|
||||||
|
@ -852,6 +852,10 @@ void Renderer::UpdateViewport()
|
||||||
Y += Height;
|
Y += Height;
|
||||||
Height *= -1;
|
Height *= -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OpenGL does not require any viewport correct
|
||||||
|
Matrix44::LoadIdentity(vpCorrection);
|
||||||
|
|
||||||
// Update the view port
|
// Update the view port
|
||||||
glViewport(X, Y, Width, Height);
|
glViewport(X, Y, Width, Height);
|
||||||
glDepthRange(GLNear, GLFar);
|
glDepthRange(GLNear, GLFar);
|
||||||
|
@ -1432,7 +1436,7 @@ void Renderer::RestoreAPIState()
|
||||||
SetColorMask();
|
SetColorMask();
|
||||||
SetDepthMode();
|
SetDepthMode();
|
||||||
SetBlendMode(true);
|
SetBlendMode(true);
|
||||||
UpdateViewport();
|
VertexShaderManager::SetViewportChanged();
|
||||||
|
|
||||||
if (g_ActiveConfig.bWireFrame)
|
if (g_ActiveConfig.bWireFrame)
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
|
|
@ -45,7 +45,7 @@ public:
|
||||||
|
|
||||||
void ReinterpretPixelData(unsigned int convtype);
|
void ReinterpretPixelData(unsigned int convtype);
|
||||||
|
|
||||||
void UpdateViewport();
|
void UpdateViewport(Matrix44& vpCorrection);
|
||||||
|
|
||||||
bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc);
|
bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue