Skip to content

Commit

Permalink
softgpu: Make triangle fan rect detection generic.
Browse files Browse the repository at this point in the history
  • Loading branch information
unknownbrackets committed Oct 16, 2022
1 parent 51c359c commit 1931fa2
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 28 deletions.
63 changes: 37 additions & 26 deletions GPU/Software/RasterizerRectangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -483,40 +483,51 @@ bool DetectRectangleFromStrip(const RasterizerState &state, const ClipVertexData
return false;
}

bool DetectRectangleFromFan(const RasterizerState &state, const ClipVertexData *data, int c, int *tlIndex, int *brIndex) {
bool DetectRectangleFromFan(const RasterizerState &state, const ClipVertexData *data, int *tlIndex, int *brIndex) {
// Color and Z must be flat.
for (int i = 1; i < c; ++i) {
int tl = 0, br = 0;
for (int i = 1; i < 4; ++i) {
if (!AreCoordsRectangleCompatible(state, data[i], data[0]))
return false;

if (data[i].v.screenpos.x <= data[tl].v.screenpos.x && data[i].v.screenpos.y <= data[tl].v.screenpos.y)
tl = i;
if (data[i].v.screenpos.x >= data[br].v.screenpos.x && data[i].v.screenpos.y >= data[br].v.screenpos.y)
br = i;
}

// Check for the common case: a single TL-TR-BR-BL.
if (c == 4) {
const auto &pos0 = data[0].v.screenpos, &pos1 = data[1].v.screenpos;
const auto &pos2 = data[2].v.screenpos, &pos3 = data[3].v.screenpos;
if (pos0.x == pos3.x && pos1.x == pos2.x && pos0.y == pos1.y && pos3.y == pos2.y) {
// Looking like yes. Set TL/BR based on y order first...
*tlIndex = pos0.y > pos3.y ? 2 : 0;
*brIndex = pos0.y > pos3.y ? 0 : 2;
// And if it's horizontally flipped, trade to the actual TL/BR.
if (pos0.x > pos1.x) {
*tlIndex ^= 1;
*brIndex ^= 1;
}
*tlIndex = tl;
*brIndex = br;

// Do we need to think about rotation?
if (!state.enableTextures)
return true;
int tr = 1, bl = 1;
for (int i = 0; i < 4; ++i) {
if (i == tl || i == br)
continue;

const auto &textl = data[*tlIndex].v.texturecoords, &textr = data[*tlIndex ^ 1].v.texturecoords;
const auto &texbl = data[*brIndex ^ 1].v.texturecoords, &texbr = data[*brIndex].v.texturecoords;
if (data[i].v.screenpos.x <= data[tl].v.screenpos.x && data[i].v.screenpos.y >= data[tl].v.screenpos.y)
bl = i;
if (data[i].v.screenpos.x >= data[br].v.screenpos.x && data[i].v.screenpos.y <= data[br].v.screenpos.y)
tr = i;
}

if (textl.x == texbl.x && textr.x == texbr.x && textl.y == textr.y && texbl.y == texbr.y) {
// Okay, the texture is also good, but let's avoid rotation issues.
const auto &postl = data[*tlIndex].v.screenpos;
const auto &posbr = data[*brIndex].v.screenpos;
return textl.y < texbr.y && postl.y < posbr.y && textl.x < texbr.x && postl.x < posbr.x;
}
// Must have found each of the coordinates.
if (tl + tr + bl + br != 6)
return false;

// Note the common case is a single TL-TR-BR-BL.
const auto &postl = data[tl].v.screenpos, &postr = data[tr].v.screenpos;
const auto &posbr = data[br].v.screenpos, &posbl = data[bl].v.screenpos;
if (postl.x == posbl.x && postr.x == posbr.x && postl.y == postr.y && posbl.y == posbr.y) {
// Do we need to think about rotation?
if (!state.enableTextures)
return true;

const auto &textl = data[tl].v.texturecoords, &textr = data[tr].v.texturecoords;
const auto &texbl = data[bl].v.texturecoords, &texbr = data[br].v.texturecoords;

if (textl.x == texbl.x && textr.x == texbr.x && textl.y == textr.y && texbl.y == texbr.y) {
// Okay, the texture is also good, but let's avoid rotation issues.
return textl.y < texbr.y && postl.y < posbr.y && textl.x < texbr.x && postl.x < posbr.x;
}
}

Expand Down
2 changes: 1 addition & 1 deletion GPU/Software/RasterizerRectangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace Rasterizer {
void DrawSprite(const VertexData &v0, const VertexData &v1, const BinCoords &range, const RasterizerState &state);

bool DetectRectangleFromStrip(const RasterizerState &state, const ClipVertexData data[4], int *tlIndex, int *brIndex);
bool DetectRectangleFromFan(const RasterizerState &state, const ClipVertexData *data, int c, int *tlIndex, int *brIndex);
bool DetectRectangleFromFan(const RasterizerState &state, const ClipVertexData *data, int *tlIndex, int *brIndex);
bool DetectRectangleFromPair(const RasterizerState &state, const ClipVertexData data[6], int *tlIndex, int *brIndex);
bool DetectRectangleThroughModeSlices(const RasterizerState &state, const ClipVertexData data[4]);
}
2 changes: 1 addition & 1 deletion GPU/Software/TransformUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ void TransformUnit::SubmitPrimitive(const void* vertices, const void* indices, G
}

int tl = -1, br = -1;
if (Rasterizer::DetectRectangleFromFan(binner_->State(), data_, vertex_count, &tl, &br)) {
if (Rasterizer::DetectRectangleFromFan(binner_->State(), data_, &tl, &br)) {
Clipper::ProcessRect(data_[tl], data_[br], *binner_);
break;
}
Expand Down

0 comments on commit 1931fa2

Please sign in to comment.