Bug 1704750 - Simplify rasterizer edge termination condition. r=kvark

Floating point imprecision can cause the existing test to be unreliable. Just simplify it so it loops around till it overlaps one edge with another. This does a tiny bit more work but will have less chance of exiting earlier than it should.

Differential Revision: https://phabricator.services.mozilla.com/D114236
This commit is contained in:
Lee Salzman 2021-05-06 21:55:27 +00:00
Родитель 59ec919b24
Коммит 4d26cb2ec6
1 изменённых файлов: 16 добавлений и 26 удалений

Просмотреть файл

@ -880,35 +880,29 @@ static inline void draw_quad_spans(int nump, Point2D p[4], uint32_t z,
// If we're outside the clip rect, we're done. // If we're outside the clip rect, we're done.
if (y > clipRect.y1) break; if (y > clipRect.y1) break;
// Helper to find the next non-duplicate vertex that doesn't loop back. // Helper to find the next non-duplicate vertex that doesn't loop back.
#define STEP_EDGE(e0i, e0, e1i, e1, STEP_POINT, end) \ #define STEP_EDGE(y, e0i, e0, e1i, e1, STEP_POINT, end) \
for (;;) { \ do { \
/* Set new start of edge to be end of old edge */ \ /* Set new start of edge to be end of old edge */ \
e0i = e1i; \ e0i = e1i; \
e0 = e1; \ e0 = e1; \
/* Set new end of edge to next point */ \ /* Set new end of edge to next point */ \
e1i = STEP_POINT(e1i); \ e1i = STEP_POINT(e1i); \
e1 = p[e1i]; \ e1 = p[e1i]; \
/* If the edge is descending, use it. */ \ /* If the edge crossed the end, we're done. */ \
if (e1.y > e0.y) break; \ if (e0i == end) return; \
/* If the edge is ascending or crossed the end, we're done. */ \ /* Otherwise, it doesn't advance, so keep searching. */ \
if (e1.y < e0.y || e0i == end) return; \ } while (y > e1.y)
/* Otherwise, it's a duplicate, so keep searching. */ \
}
// Check if Y advanced past the end of the left edge // Check if Y advanced past the end of the left edge
if (y > l1.y) { if (y > l1.y) {
// Step to next left edge past Y and reset edge interpolants. // Step to next left edge past Y and reset edge interpolants.
do { STEP_EDGE(y, l0i, l0, l1i, l1, NEXT_POINT, r1i);
STEP_EDGE(l0i, l0, l1i, l1, NEXT_POINT, r1i);
} while (y > l1.y);
(flipped ? right : left) = (flipped ? right : left) =
Edge(y, l0, l1, interp_outs[l0i], interp_outs[l1i], l1i); Edge(y, l0, l1, interp_outs[l0i], interp_outs[l1i], l1i);
} }
// Check if Y advanced past the end of the right edge // Check if Y advanced past the end of the right edge
if (y > r1.y) { if (y > r1.y) {
// Step to next right edge past Y and reset edge interpolants. // Step to next right edge past Y and reset edge interpolants.
do { STEP_EDGE(y, r0i, r0, r1i, r1, PREV_POINT, l1i);
STEP_EDGE(r0i, r0, r1i, r1, PREV_POINT, l1i);
} while (y > r1.y);
(flipped ? left : right) = (flipped ? left : right) =
Edge(y, r0, r1, interp_outs[r0i], interp_outs[r1i], r0i); Edge(y, r0, r1, interp_outs[r0i], interp_outs[r1i], r0i);
} }
@ -1146,18 +1140,14 @@ static inline void draw_perspective_spans(int nump, Point3D* p,
// Check if Y advanced past the end of the left edge // Check if Y advanced past the end of the left edge
if (y > l1.y) { if (y > l1.y) {
// Step to next left edge past Y and reset edge interpolants. // Step to next left edge past Y and reset edge interpolants.
do { STEP_EDGE(y, l0i, l0, l1i, l1, NEXT_POINT, r1i);
STEP_EDGE(l0i, l0, l1i, l1, NEXT_POINT, r1i);
} while (y > l1.y);
(flipped ? right : left) = (flipped ? right : left) =
Edge(y, l0, l1, interp_outs[l0i], interp_outs[l1i], l1i); Edge(y, l0, l1, interp_outs[l0i], interp_outs[l1i], l1i);
} }
// Check if Y advanced past the end of the right edge // Check if Y advanced past the end of the right edge
if (y > r1.y) { if (y > r1.y) {
// Step to next right edge past Y and reset edge interpolants. // Step to next right edge past Y and reset edge interpolants.
do { STEP_EDGE(y, r0i, r0, r1i, r1, PREV_POINT, l1i);
STEP_EDGE(r0i, r0, r1i, r1, PREV_POINT, l1i);
} while (y > r1.y);
(flipped ? left : right) = (flipped ? left : right) =
Edge(y, r0, r1, interp_outs[r0i], interp_outs[r1i], r0i); Edge(y, r0, r1, interp_outs[r0i], interp_outs[r1i], r0i);
} }