Pica/Scissor: Implemented the scissor test in the sw renderer.
This commit is contained in:
parent
402692c08d
commit
232594bee4
3 changed files with 53 additions and 2 deletions
|
@ -28,6 +28,7 @@ std::string Regs::GetCommandName(int index) {
|
||||||
ADD_FIELD(viewport_size_y);
|
ADD_FIELD(viewport_size_y);
|
||||||
ADD_FIELD(viewport_depth_range);
|
ADD_FIELD(viewport_depth_range);
|
||||||
ADD_FIELD(viewport_depth_far_plane);
|
ADD_FIELD(viewport_depth_far_plane);
|
||||||
|
ADD_FIELD(scissor_test);
|
||||||
ADD_FIELD(viewport_corner);
|
ADD_FIELD(viewport_corner);
|
||||||
ADD_FIELD(texture0_enable);
|
ADD_FIELD(texture0_enable);
|
||||||
ADD_FIELD(texture0);
|
ADD_FIELD(texture0);
|
||||||
|
|
|
@ -112,7 +112,36 @@ struct Regs {
|
||||||
BitField<24, 5, Semantic> map_w;
|
BitField<24, 5, Semantic> map_w;
|
||||||
} vs_output_attributes[7];
|
} vs_output_attributes[7];
|
||||||
|
|
||||||
INSERT_PADDING_WORDS(0x11);
|
INSERT_PADDING_WORDS(0xe);
|
||||||
|
|
||||||
|
enum class ScissorMode : u32 {
|
||||||
|
Disabled = 0,
|
||||||
|
Exclude = 1, // Exclude pixels inside the scissor box
|
||||||
|
|
||||||
|
Include = 3 // Exclude pixels outside the scissor box
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
BitField<0, 2, ScissorMode> mode;
|
||||||
|
|
||||||
|
union {
|
||||||
|
BitField< 0, 16, u32> right;
|
||||||
|
BitField<16, 16, u32> bottom;
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
BitField< 0, 16, u32> left;
|
||||||
|
BitField<16, 16, u32> top;
|
||||||
|
};
|
||||||
|
|
||||||
|
u32 GetWidth() const {
|
||||||
|
return left - right + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GetHeight() const {
|
||||||
|
return top - bottom + 1;
|
||||||
|
}
|
||||||
|
} scissor_test;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
BitField< 0, 16, u32> x;
|
BitField< 0, 16, u32> x;
|
||||||
|
@ -986,6 +1015,7 @@ ASSERT_REG_POSITION(viewport_depth_range, 0x4d);
|
||||||
ASSERT_REG_POSITION(viewport_depth_far_plane, 0x4e);
|
ASSERT_REG_POSITION(viewport_depth_far_plane, 0x4e);
|
||||||
ASSERT_REG_POSITION(vs_output_attributes[0], 0x50);
|
ASSERT_REG_POSITION(vs_output_attributes[0], 0x50);
|
||||||
ASSERT_REG_POSITION(vs_output_attributes[1], 0x51);
|
ASSERT_REG_POSITION(vs_output_attributes[1], 0x51);
|
||||||
|
ASSERT_REG_POSITION(scissor_test, 0x65);
|
||||||
ASSERT_REG_POSITION(viewport_corner, 0x68);
|
ASSERT_REG_POSITION(viewport_corner, 0x68);
|
||||||
ASSERT_REG_POSITION(texture0_enable, 0x80);
|
ASSERT_REG_POSITION(texture0_enable, 0x80);
|
||||||
ASSERT_REG_POSITION(texture0, 0x81);
|
ASSERT_REG_POSITION(texture0, 0x81);
|
||||||
|
|
|
@ -334,12 +334,25 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Proper scissor rect test!
|
|
||||||
u16 min_x = std::min({vtxpos[0].x, vtxpos[1].x, vtxpos[2].x});
|
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 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_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});
|
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_width = (u16)(regs.scissor_test.GetWidth() << 4);
|
||||||
|
u16 scissor_height = (u16)(regs.scissor_test.GetHeight() << 4);
|
||||||
|
u16 scissor_x = (u16)(regs.scissor_test.right << 4);
|
||||||
|
u16 scissor_y = (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_x);
|
||||||
|
min_y = std::max(min_y, scissor_y);
|
||||||
|
max_x = std::min(max_x, (u16)(scissor_x + scissor_width));
|
||||||
|
max_y = std::min(max_y, (u16)(scissor_y + scissor_height));
|
||||||
|
}
|
||||||
|
|
||||||
min_x &= Fix12P4::IntMask();
|
min_x &= Fix12P4::IntMask();
|
||||||
min_y &= Fix12P4::IntMask();
|
min_y &= Fix12P4::IntMask();
|
||||||
max_x = ((max_x + Fix12P4::FracMask()) & Fix12P4::IntMask());
|
max_x = ((max_x + Fix12P4::FracMask()) & Fix12P4::IntMask());
|
||||||
|
@ -379,6 +392,13 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
|
||||||
for (u16 y = min_y + 8; y < max_y; y += 0x10) {
|
for (u16 y = min_y + 8; y < max_y; y += 0x10) {
|
||||||
for (u16 x = min_x + 8; x < max_x; x += 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) {
|
||||||
|
if (x >= scissor_x && x <= scissor_x + scissor_width &&
|
||||||
|
y >= scissor_y && y <= scissor_y + scissor_height)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the barycentric coordinates w0, w1 and w2
|
// Calculate the barycentric coordinates w0, w1 and w2
|
||||||
int w0 = bias0 + SignedArea(vtxpos[1].xy(), vtxpos[2].xy(), {x, y});
|
int w0 = bias0 + SignedArea(vtxpos[1].xy(), vtxpos[2].xy(), {x, y});
|
||||||
int w1 = bias1 + SignedArea(vtxpos[2].xy(), vtxpos[0].xy(), {x, y});
|
int w1 = bias1 + SignedArea(vtxpos[2].xy(), vtxpos[0].xy(), {x, y});
|
||||||
|
|
Loading…
Reference in a new issue