From f9be06b15f08cb559580e1d19b43158640a37d67 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 2 Dec 2015 13:23:51 -0500 Subject: PICA: Implement scissor test --- src/video_core/rasterizer.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'src/video_core/rasterizer.cpp') diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp index a84170094..514d64208 100644 --- a/src/video_core/rasterizer.cpp +++ b/src/video_core/rasterizer.cpp @@ -338,12 +338,25 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0, return; } - // TODO: Proper scissor rect test! u16 min_x = std::min({vtxpos[0].x, vtxpos[1].x, vtxpos[2].x}); u16 min_y = std::min({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y}); u16 max_x = std::max({vtxpos[0].x, vtxpos[1].x, vtxpos[2].x}); u16 max_y = std::max({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y}); + // Convert the scissor box coordinates to 12.4 fixed point + u16 scissor_left = (u16)(regs.scissor_test.GetLeft() << 4); + u16 scissor_top = (u16)(regs.scissor_test.GetTop() << 4); + u16 scissor_right = (u16)(regs.scissor_test.right << 4); + u16 scissor_bottom = (u16)(regs.scissor_test.bottom << 4); + + if (regs.scissor_test.mode == Regs::ScissorMode::Include) { + // Calculate the new bounds + min_x = std::max(min_x, scissor_right); + min_y = std::max(min_y, scissor_bottom); + max_x = std::min(max_x, scissor_left); + max_y = std::min(max_y, scissor_top); + } + min_x &= Fix12P4::IntMask(); min_y &= Fix12P4::IntMask(); max_x = ((max_x + Fix12P4::FracMask()) & Fix12P4::IntMask()); @@ -383,6 +396,13 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0, for (u16 y = min_y + 8; y < max_y; y += 0x10) { for (u16 x = min_x + 8; x < max_x; x += 0x10) { + // Do not process the pixel if it's inside the scissor box and the scissor mode is set to Exclude + if (regs.scissor_test.mode == Regs::ScissorMode::Exclude && + x >= scissor_right && x <= scissor_left && + y >= scissor_bottom && y <= scissor_top) { + continue; + } + // Calculate the barycentric coordinates w0, w1 and w2 int w0 = bias0 + SignedArea(vtxpos[1].xy(), vtxpos[2].xy(), {x, y}); int w1 = bias1 + SignedArea(vtxpos[2].xy(), vtxpos[0].xy(), {x, y}); -- cgit v1.2.3 From f0b9bc14b64765bd8bc78cb4cfb4a30eb9ab9324 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sun, 24 Jan 2016 22:59:16 -0800 Subject: PICA: Scissor fixes and cleanups --- src/video_core/rasterizer.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'src/video_core/rasterizer.cpp') diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp index 514d64208..6f369a00e 100644 --- a/src/video_core/rasterizer.cpp +++ b/src/video_core/rasterizer.cpp @@ -344,17 +344,18 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0, u16 max_y = std::max({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y}); // Convert the scissor box coordinates to 12.4 fixed point - u16 scissor_left = (u16)(regs.scissor_test.GetLeft() << 4); - u16 scissor_top = (u16)(regs.scissor_test.GetTop() << 4); - u16 scissor_right = (u16)(regs.scissor_test.right << 4); - u16 scissor_bottom = (u16)(regs.scissor_test.bottom << 4); + u16 scissor_x1 = (u16)( regs.scissor_test.x1 << 4); + u16 scissor_y1 = (u16)( regs.scissor_test.y1 << 4); + // x2,y2 have +1 added to cover the entire sub-pixel area + u16 scissor_x2 = (u16)((regs.scissor_test.x2 + 1) << 4); + u16 scissor_y2 = (u16)((regs.scissor_test.y2 + 1) << 4); if (regs.scissor_test.mode == Regs::ScissorMode::Include) { // Calculate the new bounds - min_x = std::max(min_x, scissor_right); - min_y = std::max(min_y, scissor_bottom); - max_x = std::min(max_x, scissor_left); - max_y = std::min(max_y, scissor_top); + min_x = std::max(min_x, scissor_x1); + min_y = std::max(min_y, scissor_y1); + max_x = std::min(max_x, scissor_x2); + max_y = std::min(max_y, scissor_y2); } min_x &= Fix12P4::IntMask(); @@ -397,10 +398,10 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0, for (u16 x = min_x + 8; x < max_x; x += 0x10) { // Do not process the pixel if it's inside the scissor box and the scissor mode is set to Exclude - if (regs.scissor_test.mode == Regs::ScissorMode::Exclude && - x >= scissor_right && x <= scissor_left && - y >= scissor_bottom && y <= scissor_top) { - continue; + if (regs.scissor_test.mode == Regs::ScissorMode::Exclude) { + if (x >= scissor_x1 && x < scissor_x2 && + y >= scissor_y1 && y < scissor_y2) + continue; } // Calculate the barycentric coordinates w0, w1 and w2 -- cgit v1.2.3