Merge branch 'scissoring-fixed'
Fixes various cases in scissor rect emulation. This should fix glitches in various games, right now it's only known to (partially) fix Baten Kaitos: Eternal Wings. Fix by delroth, port to D3D9/11 by godisgovernment, cleanup by me.
This commit is contained in:
commit
11933bf6b5
|
@ -44,9 +44,24 @@ void SetGenerationMode(const BPCmd &bp)
|
||||||
g_renderer->SetGenerationMode();
|
g_renderer->SetGenerationMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetScissor(const BPCmd &bp)
|
void SetScissor()
|
||||||
{
|
{
|
||||||
g_renderer->SetScissorRect();
|
const int xoff = bpmem.scissorOffset.x * 2 - 342;
|
||||||
|
const int yoff = bpmem.scissorOffset.y * 2 - 342;
|
||||||
|
|
||||||
|
EFBRectangle rc (bpmem.scissorTL.x - xoff - 342, bpmem.scissorTL.y - yoff - 342,
|
||||||
|
bpmem.scissorBR.x - xoff - 341, bpmem.scissorBR.y - yoff - 341);
|
||||||
|
|
||||||
|
if (rc.left < 0) rc.left = 0;
|
||||||
|
if (rc.top < 0) rc.top = 0;
|
||||||
|
if (rc.right > EFB_WIDTH) rc.right = EFB_WIDTH;
|
||||||
|
if (rc.bottom > EFB_HEIGHT) rc.bottom = EFB_HEIGHT;
|
||||||
|
|
||||||
|
if (rc.left > rc.right) rc.right = rc.left;
|
||||||
|
if (rc.top > rc.bottom) rc.bottom = rc.top;
|
||||||
|
|
||||||
|
TargetRectangle trc = g_renderer->ConvertEFBRectangle(rc);
|
||||||
|
g_renderer->SetScissorRect(trc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetLineWidth(const BPCmd &bp)
|
void SetLineWidth(const BPCmd &bp)
|
||||||
|
|
|
@ -38,7 +38,7 @@ enum
|
||||||
|
|
||||||
void FlushPipeline();
|
void FlushPipeline();
|
||||||
void SetGenerationMode(const BPCmd &bp);
|
void SetGenerationMode(const BPCmd &bp);
|
||||||
void SetScissor(const BPCmd &bp);
|
void SetScissor();
|
||||||
void SetLineWidth(const BPCmd &bp);
|
void SetLineWidth(const BPCmd &bp);
|
||||||
void SetDepthMode(const BPCmd &bp);
|
void SetDepthMode(const BPCmd &bp);
|
||||||
void SetBlendMode(const BPCmd &bp);
|
void SetBlendMode(const BPCmd &bp);
|
||||||
|
|
|
@ -162,7 +162,7 @@ void BPWritten(const BPCmd& bp)
|
||||||
case BPMEM_SCISSORTL: // Scissor Rectable Top, Left
|
case BPMEM_SCISSORTL: // Scissor Rectable Top, Left
|
||||||
case BPMEM_SCISSORBR: // Scissor Rectable Bottom, Right
|
case BPMEM_SCISSORBR: // Scissor Rectable Bottom, Right
|
||||||
case BPMEM_SCISSOROFFSET: // Scissor Offset
|
case BPMEM_SCISSOROFFSET: // Scissor Offset
|
||||||
SetScissor(bp);
|
SetScissor();
|
||||||
break;
|
break;
|
||||||
case BPMEM_LINEPTWIDTH: // Line Width
|
case BPMEM_LINEPTWIDTH: // Line Width
|
||||||
SetLineWidth(bp);
|
SetLineWidth(bp);
|
||||||
|
|
|
@ -54,7 +54,7 @@ public:
|
||||||
|
|
||||||
virtual void SetColorMask() = 0;
|
virtual void SetColorMask() = 0;
|
||||||
virtual void SetBlendMode(bool forceUpdate) = 0;
|
virtual void SetBlendMode(bool forceUpdate) = 0;
|
||||||
virtual bool SetScissorRect() = 0;
|
virtual void SetScissorRect(const TargetRectangle& rc) = 0;
|
||||||
virtual void SetGenerationMode() = 0;
|
virtual void SetGenerationMode() = 0;
|
||||||
virtual void SetDepthMode() = 0;
|
virtual void SetDepthMode() = 0;
|
||||||
virtual void SetLogicOpMode() = 0;
|
virtual void SetLogicOpMode() = 0;
|
||||||
|
@ -175,16 +175,4 @@ extern Renderer *g_renderer;
|
||||||
|
|
||||||
void UpdateViewport(Matrix44& vpCorrection);
|
void UpdateViewport(Matrix44& vpCorrection);
|
||||||
|
|
||||||
template <typename R>
|
|
||||||
void GetScissorRect(MathUtil::Rectangle<R> &rect)
|
|
||||||
{
|
|
||||||
const int xoff = bpmem.scissorOffset.x * 2 - 342;
|
|
||||||
const int yoff = bpmem.scissorOffset.y * 2 - 342;
|
|
||||||
|
|
||||||
rect.left = (R)(bpmem.scissorTL.x - xoff - 342);
|
|
||||||
rect.top = (R)(bpmem.scissorTL.y - yoff - 342);
|
|
||||||
rect.right = (R)(bpmem.scissorBR.x - xoff - 341);
|
|
||||||
rect.bottom = (R)(bpmem.scissorBR.y - yoff - 341);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // _COMMON_RENDERBASE_H_
|
#endif // _COMMON_RENDERBASE_H_
|
||||||
|
|
|
@ -70,8 +70,7 @@ void HandleGLError();
|
||||||
// This structure should only be used to represent a rectangle in EFB
|
// This structure should only be used to represent a rectangle in EFB
|
||||||
// coordinates, where the origin is at the upper left and the frame dimensions
|
// coordinates, where the origin is at the upper left and the frame dimensions
|
||||||
// are 640 x 528.
|
// are 640 x 528.
|
||||||
struct EFBRectangle : public MathUtil::Rectangle<int>
|
typedef MathUtil::Rectangle<int> EFBRectangle;
|
||||||
{};
|
|
||||||
|
|
||||||
// This structure should only be used to represent a rectangle in standard target
|
// This structure should only be used to represent a rectangle in standard target
|
||||||
// coordinates, where the origin is at the lower left and the frame dimensions
|
// coordinates, where the origin is at the lower left and the frame dimensions
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "Movie.h"
|
#include "Movie.h"
|
||||||
#include "Television.h"
|
#include "Television.h"
|
||||||
#include "Host.h"
|
#include "Host.h"
|
||||||
|
#include "BPFunctions.h"
|
||||||
|
|
||||||
namespace DX11
|
namespace DX11
|
||||||
{
|
{
|
||||||
|
@ -444,51 +445,9 @@ bool Renderer::CheckForResize()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renderer::SetScissorRect()
|
void Renderer::SetScissorRect(const TargetRectangle& rc)
|
||||||
{
|
{
|
||||||
TargetRectangle rc;
|
D3D::context->RSSetScissorRects(1, rc.AsRECT());
|
||||||
GetScissorRect(rc);
|
|
||||||
|
|
||||||
if (rc.left < 0) rc.left = 0;
|
|
||||||
if (rc.right < 0) rc.right = 0;
|
|
||||||
if (rc.top < 0) rc.top = 0;
|
|
||||||
if (rc.bottom < 0) rc.bottom = 0;
|
|
||||||
|
|
||||||
if (rc.left > EFB_WIDTH) rc.left = EFB_WIDTH;
|
|
||||||
if (rc.right > EFB_WIDTH) rc.right = EFB_WIDTH;
|
|
||||||
if (rc.top > EFB_HEIGHT) rc.top = EFB_HEIGHT;
|
|
||||||
if (rc.bottom > EFB_HEIGHT) rc.bottom = EFB_HEIGHT;
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
int temp = rc.right;
|
|
||||||
rc.right = rc.left;
|
|
||||||
rc.left = temp;
|
|
||||||
}
|
|
||||||
if (rc.top > rc.bottom)
|
|
||||||
{
|
|
||||||
int temp = rc.bottom;
|
|
||||||
rc.bottom = rc.top;
|
|
||||||
rc.top = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc.right >= rc.left && rc.bottom >= rc.top)
|
|
||||||
{
|
|
||||||
D3D::context->RSSetScissorRects(1, rc.AsRECT());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//WARN_LOG(VIDEO, "Bad scissor rectangle: %i %i %i %i", rc.left, rc.top, rc.right, rc.bottom);
|
|
||||||
*rc.AsRECT() = CD3D11_RECT(0.f, 0.f, s_target_width, s_target_height);
|
|
||||||
D3D::context->RSSetScissorRects(1, rc.AsRECT());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::SetColorMask()
|
void Renderer::SetColorMask()
|
||||||
|
@ -1163,7 +1122,7 @@ void Renderer::RestoreAPIState()
|
||||||
D3D::stateman->PopDepthState();
|
D3D::stateman->PopDepthState();
|
||||||
D3D::stateman->PopRasterizerState();
|
D3D::stateman->PopRasterizerState();
|
||||||
VertexShaderManager::SetViewportChanged();
|
VertexShaderManager::SetViewportChanged();
|
||||||
SetScissorRect();
|
BPFunctions::SetScissor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::ApplyState(bool bUseDstAlpha)
|
void Renderer::ApplyState(bool bUseDstAlpha)
|
||||||
|
|
|
@ -15,7 +15,7 @@ public:
|
||||||
|
|
||||||
void SetColorMask();
|
void SetColorMask();
|
||||||
void SetBlendMode(bool forceUpdate);
|
void SetBlendMode(bool forceUpdate);
|
||||||
bool SetScissorRect();
|
void SetScissorRect(const TargetRectangle& rc);
|
||||||
void SetGenerationMode();
|
void SetGenerationMode();
|
||||||
void SetDepthMode();
|
void SetDepthMode();
|
||||||
void SetLogicOpMode();
|
void SetLogicOpMode();
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#include "Debugger.h"
|
#include "Debugger.h"
|
||||||
#include "Core.h"
|
#include "Core.h"
|
||||||
#include "Movie.h"
|
#include "Movie.h"
|
||||||
|
#include "BPFunctions.h"
|
||||||
|
|
||||||
namespace DX9
|
namespace DX9
|
||||||
{
|
{
|
||||||
|
@ -426,55 +427,9 @@ bool Renderer::CheckForResize()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renderer::SetScissorRect()
|
void Renderer::SetScissorRect(const TargetRectangle& rc)
|
||||||
{
|
{
|
||||||
TargetRectangle rc;
|
D3D::dev->SetScissorRect(rc.AsRECT());
|
||||||
GetScissorRect(rc);
|
|
||||||
|
|
||||||
if (rc.left < 0) rc.left = 0;
|
|
||||||
if (rc.right < 0) rc.right = 0;
|
|
||||||
if (rc.top < 0) rc.top = 0;
|
|
||||||
if (rc.bottom < 0) rc.bottom = 0;
|
|
||||||
|
|
||||||
if (rc.left > EFB_WIDTH) rc.left = EFB_WIDTH;
|
|
||||||
if (rc.right > EFB_WIDTH) rc.right = EFB_WIDTH;
|
|
||||||
if (rc.top > EFB_HEIGHT) rc.top = EFB_HEIGHT;
|
|
||||||
if (rc.bottom > EFB_HEIGHT) rc.bottom = EFB_HEIGHT;
|
|
||||||
|
|
||||||
if (rc.left > rc.right)
|
|
||||||
{
|
|
||||||
int temp = rc.right;
|
|
||||||
rc.right = rc.left;
|
|
||||||
rc.left = temp;
|
|
||||||
}
|
|
||||||
if (rc.top > rc.bottom)
|
|
||||||
{
|
|
||||||
int temp = rc.bottom;
|
|
||||||
rc.bottom = rc.top;
|
|
||||||
rc.top = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
D3D::dev->SetScissorRect(rc.AsRECT());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//WARN_LOG(VIDEO, "Bad scissor rectangle: %i %i %i %i", rc.left, rc.top, rc.right, rc.bottom);
|
|
||||||
rc.left = 0;
|
|
||||||
rc.top = 0;
|
|
||||||
rc.right = s_target_width;
|
|
||||||
rc.bottom = s_target_height;
|
|
||||||
D3D::dev->SetScissorRect(rc.AsRECT());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::SetColorMask()
|
void Renderer::SetColorMask()
|
||||||
|
@ -1293,7 +1248,7 @@ void Renderer::RestoreAPIState()
|
||||||
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);
|
||||||
VertexShaderManager::SetViewportChanged();
|
VertexShaderManager::SetViewportChanged();
|
||||||
SetScissorRect();
|
BPFunctions::SetScissor();
|
||||||
if (bpmem.zmode.testenable) {
|
if (bpmem.zmode.testenable) {
|
||||||
D3D::SetRenderState(D3DRS_ZENABLE, TRUE);
|
D3D::SetRenderState(D3DRS_ZENABLE, TRUE);
|
||||||
if (bpmem.zmode.updateenable)
|
if (bpmem.zmode.updateenable)
|
||||||
|
|
|
@ -15,7 +15,7 @@ public:
|
||||||
|
|
||||||
void SetColorMask();
|
void SetColorMask();
|
||||||
void SetBlendMode(bool forceUpdate);
|
void SetBlendMode(bool forceUpdate);
|
||||||
bool SetScissorRect();
|
void SetScissorRect(const TargetRectangle& rc);
|
||||||
void SetGenerationMode();
|
void SetGenerationMode();
|
||||||
void SetDepthMode();
|
void SetDepthMode();
|
||||||
void SetLogicOpMode();
|
void SetLogicOpMode();
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
#include "Core.h"
|
#include "Core.h"
|
||||||
#include "Movie.h"
|
#include "Movie.h"
|
||||||
#include "Host.h"
|
#include "Host.h"
|
||||||
|
#include "BPFunctions.h"
|
||||||
|
|
||||||
#include "main.h" // Local
|
#include "main.h" // Local
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -642,49 +643,9 @@ TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
|
||||||
// Renderer::GetTargetHeight() = the fixed ini file setting
|
// Renderer::GetTargetHeight() = the fixed ini file setting
|
||||||
// donkopunchstania - it appears scissorBR is the bottom right pixel inside the scissor box
|
// donkopunchstania - it appears scissorBR is the bottom right pixel inside the scissor box
|
||||||
// therefore the width and height are (scissorBR + 1) - scissorTL
|
// therefore the width and height are (scissorBR + 1) - scissorTL
|
||||||
bool Renderer::SetScissorRect()
|
void Renderer::SetScissorRect(const TargetRectangle& rc)
|
||||||
{
|
{
|
||||||
MathUtil::Rectangle<float> rc;
|
glScissor(rc.left, rc.bottom, rc.GetWidth(), rc.GetHeight());
|
||||||
GetScissorRect(rc);
|
|
||||||
|
|
||||||
if (rc.left < 0) rc.left = 0;
|
|
||||||
if (rc.top < 0) rc.top = 0;
|
|
||||||
if (rc.right > EFB_WIDTH) rc.right = EFB_WIDTH;
|
|
||||||
if (rc.bottom > EFB_HEIGHT) rc.bottom = EFB_HEIGHT;
|
|
||||||
|
|
||||||
if (rc.left > rc.right)
|
|
||||||
{
|
|
||||||
int temp = rc.right;
|
|
||||||
rc.right = rc.left;
|
|
||||||
rc.left = temp;
|
|
||||||
}
|
|
||||||
if (rc.top > rc.bottom)
|
|
||||||
{
|
|
||||||
int temp = rc.bottom;
|
|
||||||
rc.bottom = rc.top;
|
|
||||||
rc.top = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the coordinates are good
|
|
||||||
if (rc.right != rc.left && rc.bottom != rc.top)
|
|
||||||
{
|
|
||||||
glScissor(
|
|
||||||
EFBToScaledX(rc.left), // x = 0 for example
|
|
||||||
EFBToScaledY(EFB_HEIGHT - rc.bottom), // y = 0 for example
|
|
||||||
EFBToScaledX(rc.right - rc.left), // width = 640 for example
|
|
||||||
EFBToScaledY(rc.bottom - rc.top)); // height = 480 for example
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glScissor(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
Renderer::GetTargetWidth(),
|
|
||||||
Renderer::GetTargetHeight()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::SetColorMask()
|
void Renderer::SetColorMask()
|
||||||
|
@ -1432,7 +1393,7 @@ void Renderer::RestoreAPIState()
|
||||||
// Gets us back into a more game-like state.
|
// Gets us back into a more game-like state.
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
SetGenerationMode();
|
SetGenerationMode();
|
||||||
SetScissorRect();
|
BPFunctions::SetScissor();
|
||||||
SetColorMask();
|
SetColorMask();
|
||||||
SetDepthMode();
|
SetDepthMode();
|
||||||
SetBlendMode(true);
|
SetBlendMode(true);
|
||||||
|
|
|
@ -15,7 +15,7 @@ public:
|
||||||
|
|
||||||
void SetColorMask();
|
void SetColorMask();
|
||||||
void SetBlendMode(bool forceUpdate);
|
void SetBlendMode(bool forceUpdate);
|
||||||
bool SetScissorRect();
|
void SetScissorRect(const TargetRectangle& rc);
|
||||||
void SetGenerationMode();
|
void SetGenerationMode();
|
||||||
void SetDepthMode();
|
void SetDepthMode();
|
||||||
void SetLogicOpMode();
|
void SetLogicOpMode();
|
||||||
|
|
Loading…
Reference in New Issue