зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1633953 - refactor draw_quad_spans edge stepping to make it easier to read. r=jimb
Differential Revision: https://phabricator.services.mozilla.com/D73041
This commit is contained in:
Родитель
8d59795c6c
Коммит
9873811aca
|
@ -2822,37 +2822,42 @@ static inline void draw_quad_spans(int nump, Point2D p[4], uint16_t z,
|
|||
// r1.x, r1.y);
|
||||
}
|
||||
|
||||
// Current X of left edge.
|
||||
float lx = l0.x;
|
||||
// Scale for change in Y of left edge.
|
||||
float lk = 1.0f / (l1.y - l0.y);
|
||||
// dX/dY slope for left edge.
|
||||
float lm = (l1.x - l0.x) * lk;
|
||||
// Current X of right edge.
|
||||
float rx = r0.x;
|
||||
// Scale for change in Y of right edge.
|
||||
float rk = 1.0f / (r1.y - r0.y);
|
||||
// dX/dY slope for right edge.
|
||||
float rm = (r1.x - r0.x) * rk;
|
||||
struct Edge
|
||||
{
|
||||
float yScale;
|
||||
float xSlope;
|
||||
float x;
|
||||
Interpolants interpSlope;
|
||||
Interpolants interp;
|
||||
|
||||
Edge(float y, const Point2D& p0, const Point2D& p1,
|
||||
const Interpolants& i0, const Interpolants& i1) :
|
||||
// inverse Y scale for slope calculations
|
||||
yScale(1.0f / (p1.y - p0.y)),
|
||||
// Calculate dX/dY slope
|
||||
xSlope((p1.x - p0.x) * yScale),
|
||||
// Initialize current X based on Y and slope
|
||||
x(p0.x + (y - p0.y) * xSlope),
|
||||
// Calculate change in interpolants per change in Y
|
||||
interpSlope((i1 - i0) * yScale),
|
||||
// Initialize current interpolants based on Y and slope
|
||||
interp(i0 + (y - p0.y) * interpSlope)
|
||||
{}
|
||||
|
||||
void nextRow() {
|
||||
// step current X and interpolants to next row from slope
|
||||
x += xSlope;
|
||||
interp += interpSlope;
|
||||
}
|
||||
};
|
||||
|
||||
// Vertex selection above should result in equal left and right start rows
|
||||
assert(l0.y == r0.y);
|
||||
// Find the start y, clip to within the clip rect, and round to row center.
|
||||
float y = floor(max(l0.y, clipRect.y0) + 0.5f) + 0.5f;
|
||||
// Advance left and right X based on difference of Y from edge starts
|
||||
lx += (y - l0.y) * lm;
|
||||
rx += (y - r0.y) * rm;
|
||||
// Interpolants at start of left edge
|
||||
Interpolants lo = interp_outs[l0i];
|
||||
// Calculate change in left edge interpolants per change in Y
|
||||
Interpolants lom = (interp_outs[l1i] - lo) * lk;
|
||||
// Advance current left interpolants to current Y
|
||||
lo = lo + lom * (y - l0.y);
|
||||
// Interpolants at start of right edge
|
||||
Interpolants ro = interp_outs[r0i];
|
||||
// Calculate change in right edge interpolants per change in Y
|
||||
Interpolants rom = (interp_outs[r1i] - ro) * rk;
|
||||
// Advance current right edge interpolants to current Y
|
||||
ro = ro + rom * (y - r0.y);
|
||||
// Initialize left and right edges from end points and start Y
|
||||
Edge left(y, l0, l1, interp_outs[l0i], interp_outs[l1i]);
|
||||
Edge right(y, r0, r1, interp_outs[r0i], interp_outs[r1i]);
|
||||
// Get pointer to color buffer and depth buffer at current Y
|
||||
P* fbuf = (P*)colortex.sample_ptr(0, int(y), layer, sizeof(P));
|
||||
uint16_t* fdepth =
|
||||
|
@ -2876,42 +2881,22 @@ static inline void draw_quad_spans(int nump, Point2D p[4], uint16_t z,
|
|||
if (e1.y < e0.y || e0i == end) return; \
|
||||
/* Otherwise, it's a duplicate, so keep searching. */ \
|
||||
}
|
||||
// Step to next left edge and reset edge interpolants.
|
||||
STEP_EDGE(l0i, l0, l1i, l1, NEXT_POINT, r1i);
|
||||
// New scale for change in left edge Y
|
||||
lk = 1.0f / (l1.y - l0.y);
|
||||
// dX/dY slope
|
||||
lm = (l1.x - l0.x) * lk;
|
||||
// Advance current left X to current Y
|
||||
lx = l0.x + (y - l0.y) * lm;
|
||||
// Left edge start interpolants
|
||||
lo = interp_outs[l0i];
|
||||
// New slope of change in left edge interpolants per change in Y
|
||||
lom = (interp_outs[l1i] - lo) * lk;
|
||||
// Advance current left edge interpolants to current Y
|
||||
lo += lom * (y - l0.y);
|
||||
left = Edge(y, l0, l1, interp_outs[l0i], interp_outs[l1i]);
|
||||
}
|
||||
// Check if Y advanced past the end of the right edge
|
||||
if (y > r1.y) {
|
||||
// Step to next right edge and reset edge interpolants.
|
||||
STEP_EDGE(r0i, r0, r1i, r1, PREV_POINT, l1i);
|
||||
// New scale for change in right edge Y
|
||||
rk = 1.0f / (r1.y - r0.y);
|
||||
// dX/dY slope
|
||||
rm = (r1.x - r0.x) * rk;
|
||||
// Advance current right X to current Y
|
||||
rx = r0.x + (y - r0.y) * rm;
|
||||
// Right edge start interpolants
|
||||
ro = interp_outs[r0i];
|
||||
// New slope of change in right edge interpolants per change in Y
|
||||
rom = (interp_outs[r1i] - ro) * rk;
|
||||
// Advance current right edge interpolants to current Y
|
||||
ro += rom * (y - r0.y);
|
||||
right = Edge(y, r0, r1, interp_outs[r0i], interp_outs[r1i]);
|
||||
}
|
||||
// lx..rx form the bounds of the span. WR does not use backface culling,
|
||||
// so we need to use min/max to support the span in either orientation.
|
||||
// Clip the span to fall within the clip rect and then round to nearest
|
||||
// column.
|
||||
int startx = int(max(min(lx, rx), clipRect.x0) + 0.5f);
|
||||
int endx = int(min(max(lx, rx), clipRect.x1) + 0.5f);
|
||||
int startx = int(max(min(left.x, right.x), clipRect.x0) + 0.5f);
|
||||
int endx = int(min(max(left.x, right.x), clipRect.x1) + 0.5f);
|
||||
// Check if span is non-empty.
|
||||
int span = endx - startx;
|
||||
if (span > 0) {
|
||||
|
@ -2932,7 +2917,7 @@ static inline void draw_quad_spans(int nump, Point2D p[4], uint16_t z,
|
|||
// The depth buffer is unitialized on this row, but we know it will
|
||||
// thus be cleared entirely to the clear value. This lets us quickly
|
||||
// check the constant Z value of the quad against the clear Z to know
|
||||
// if the entire span passes of fails the depth all at once.
|
||||
// if the entire span passes or fails the depth test all at once.
|
||||
switch (ctx->depthfunc) {
|
||||
case GL_LESS:
|
||||
if (int16_t(z) < int16_t(depthtex.clear_val))
|
||||
|
@ -2997,15 +2982,16 @@ static inline void draw_quad_spans(int nump, Point2D p[4], uint16_t z,
|
|||
{
|
||||
// Change in interpolants is difference between current right and left
|
||||
// edges per the change in right and left X.
|
||||
Interpolants step = (ro - lo) * (1.0f / (rx - lx));
|
||||
Interpolants step =
|
||||
(right.interp - left.interp) * (1.0f / (right.x - left.x));
|
||||
// Advance current interpolants to X at start of span.
|
||||
Interpolants o = lo + step * (startx + 0.5f - lx);
|
||||
Interpolants o = left.interp + step * (startx + 0.5f - left.x);
|
||||
fragment_shader->init_span(&o, &step, 4.0f);
|
||||
}
|
||||
if (!use_discard) {
|
||||
// Fast paths for the case where fragment discard is not used.
|
||||
if (use_depth) {
|
||||
// If depth is used, we want to process span in 8-pixel chunks to
|
||||
// If depth is used, we want to process spans in 8-pixel chunks to
|
||||
// maximize sampling and testing 16-bit depth values within the 128-
|
||||
// bit width of a SIMD register.
|
||||
if (span >= 8) {
|
||||
|
@ -3083,14 +3069,10 @@ static inline void draw_quad_spans(int nump, Point2D p[4], uint16_t z,
|
|||
}
|
||||
}
|
||||
next_span:
|
||||
// Advance left and right X positions to next row based on slope.
|
||||
lx += lm;
|
||||
rx += rm;
|
||||
// Advance Y to next row.
|
||||
// Advance Y and edge interpolants to next row.
|
||||
y++;
|
||||
// Advance left and right edge interpolants to next row based on slope.
|
||||
lo += lom;
|
||||
ro += rom;
|
||||
left.nextRow();
|
||||
right.nextRow();
|
||||
// Advance buffers to next row.
|
||||
fbuf += colortex.stride(sizeof(P)) / sizeof(P);
|
||||
fdepth += depthtex.stride(sizeof(uint16_t)) / sizeof(uint16_t);
|
||||
|
@ -3153,44 +3135,52 @@ static inline void draw_perspective_spans(int nump, Point3D* p,
|
|||
r1 = p[r1i]; // End of right edge
|
||||
}
|
||||
|
||||
// Current coordinates for left edge. Where in the 2D case of draw_quad_spans
|
||||
// it is enough to just track the X coordinate as we advance along the rows,
|
||||
// for the perspective case we also need to keep track of Z and W. For
|
||||
// simplicity, we just use the full 3D point to track all these coordinates.
|
||||
Point3D lc = l0;
|
||||
// Scale for change in Y of left edge
|
||||
float lk = 1.0f / (l1.y - l0.y);
|
||||
// Left slope of coordinates per change in Y
|
||||
Point3D lm = (l1 - l0) * lk;
|
||||
// Current coordinates for right edge
|
||||
Point3D rc = r0;
|
||||
// Scale for change in Y of right edge
|
||||
float rk = 1.0f / (r1.y - r0.y);
|
||||
// Right slope of coordinates per change in Y
|
||||
Point3D rm = (r1 - r0) * rk;
|
||||
struct Edge
|
||||
{
|
||||
float yScale;
|
||||
// Current coordinates for edge. Where in the 2D case of draw_quad_spans,
|
||||
// it is enough to just track the X coordinate as we advance along the rows,
|
||||
// for the perspective case we also need to keep track of Z and W. For
|
||||
// simplicity, we just use the full 3D point to track all these coordinates.
|
||||
Point3D pSlope;
|
||||
Point3D p;
|
||||
Interpolants interpSlope;
|
||||
Interpolants interp;
|
||||
|
||||
Edge(float y, const Point3D& p0, const Point3D& p1,
|
||||
const Interpolants& i0, const Interpolants& i1) :
|
||||
// inverse Y scale for slope calculations
|
||||
yScale(1.0f / (p1.y - p0.y)),
|
||||
// Calculate dX/dY slope
|
||||
pSlope((p1 - p0) * yScale),
|
||||
// Initialize current coords based on Y and slope
|
||||
p(p0 + (y - p0.y) * pSlope),
|
||||
// Crucially, these interpolants must be scaled by the point's 1/w value,
|
||||
// which allows linear interpolation in a perspective-correct manner.
|
||||
// This will be canceled out inside the fragment shader later.
|
||||
// Calculate change in interpolants per change in Y
|
||||
interpSlope((i1 * p1.w - i0 * p0.w) * yScale),
|
||||
// Initialize current interpolants based on Y and slope
|
||||
interp(i0 * p0.w + (y - p0.y) * interpSlope)
|
||||
{}
|
||||
|
||||
float x() const { return p.x; }
|
||||
vec2_scalar zw() const { return {p.z, p.w}; }
|
||||
|
||||
void nextRow() {
|
||||
// step current coords and interpolants to next row from slope
|
||||
p += pSlope;
|
||||
interp += interpSlope;
|
||||
}
|
||||
};
|
||||
|
||||
// Vertex selection above should result in equal left and right start rows
|
||||
assert(l0.y == r0.y);
|
||||
// Find the start y, clip to within the clip rect, and round to row center.
|
||||
float y = floor(max(l0.y, clipRect.y0) + 0.5f) + 0.5f;
|
||||
// Advance left and right coordinates to current Y.
|
||||
lc += (y - l0.y) * lm;
|
||||
rc += (y - r0.y) * rm;
|
||||
// Interpolants at start of left edge. Crucially, these interpolants must be
|
||||
// scaled by the point's 1/w value, allows linearly interpolation in a
|
||||
// perspective-correct manner. This will be canceled out inside the fragment
|
||||
// shader later.
|
||||
Interpolants lo = interp_outs[l0i] * l0.w;
|
||||
// Calculate change in left edge interpolants per change in Y, also taking
|
||||
// into account scaling by 1/w
|
||||
Interpolants lom = (interp_outs[l1i] * l1.w - lo) * lk;
|
||||
// Advance current left interpolants to current Y
|
||||
lo = lo + lom * (y - l0.y);
|
||||
// Interpolants at start of right edge, scaled by 1/w
|
||||
Interpolants ro = interp_outs[r0i] * r0.w;
|
||||
// Calculate change in right edge interpolants per change in Y
|
||||
Interpolants rom = (interp_outs[r1i] * r1.w - ro) * rk;
|
||||
// Advance current right edge interpolants to current Y
|
||||
ro = ro + rom * (y - r0.y);
|
||||
// Initialize left and right edges from end points and start Y
|
||||
Edge left(y, l0, l1, interp_outs[l0i], interp_outs[l1i]);
|
||||
Edge right(y, r0, r1, interp_outs[r0i], interp_outs[r1i]);
|
||||
// Get pointer to color buffer and depth buffer at current Y
|
||||
P* fbuf = (P*)colortex.sample_ptr(0, int(y), layer, sizeof(P));
|
||||
uint16_t* fdepth =
|
||||
|
@ -3199,42 +3189,22 @@ static inline void draw_perspective_spans(int nump, Point3D* p,
|
|||
while (y < clipRect.y1) {
|
||||
// Check if Y advanced past the end of the left edge
|
||||
if (y > l1.y) {
|
||||
// Step to next left edge and reset edge interpolants.
|
||||
STEP_EDGE(l0i, l0, l1i, l1, NEXT_POINT, r1i);
|
||||
// New scale for change in left edge Y
|
||||
lk = 1.0f / (l1.y - l0.y);
|
||||
// Left coordinate slope
|
||||
lm = (l1 - l0) * lk;
|
||||
// Advance current left coords to current Y
|
||||
lc = l0 + (y - l0.y) * lm;
|
||||
// Left edge start interpolants, scaled by 1/w
|
||||
lo = interp_outs[l0i] * l0.w;
|
||||
// New slope of left edge interpolants per change in Y, scaled by 1/w
|
||||
lom = (interp_outs[l1i] * l1.w - lo) * lk;
|
||||
// Advance current left edge interpolants to current Y
|
||||
lo += lom * (y - l0.y);
|
||||
left = Edge(y, l0, l1, interp_outs[l0i], interp_outs[l1i]);
|
||||
}
|
||||
// Check if Y advanced past the end of the right edge
|
||||
if (y > r1.y) {
|
||||
// Step to next right edge and reset edge interpolants.
|
||||
STEP_EDGE(r0i, r0, r1i, r1, PREV_POINT, l1i);
|
||||
// New scale for change in right edge Y
|
||||
rk = 1.0f / (r1.y - r0.y);
|
||||
// Right coordinate slope
|
||||
rm = (r1 - r0) * rk;
|
||||
// Advance current right coords to current Y
|
||||
rc = r0 + (y - r0.y) * rm;
|
||||
// Right edge start interpolants, scaled by 1/w
|
||||
ro = interp_outs[r0i] * r0.w;
|
||||
// New slope of right edge interpolants per change in Y, scaled by 1/w
|
||||
rom = (interp_outs[r1i] * r1.w - ro) * rk;
|
||||
// Advance current right edge interpolants to current Y
|
||||
ro += rom * (y - r0.y);
|
||||
right = Edge(y, r0, r1, interp_outs[r0i], interp_outs[r1i]);
|
||||
}
|
||||
// lx..rx form the bounds of the span. WR does not use backface culling,
|
||||
// so we need to use min/max to support the span in either orientation.
|
||||
// Clip the span to fall within the clip rect and then round to nearest
|
||||
// column.
|
||||
int startx = int(max(min(lc.x, rc.x), clipRect.x0) + 0.5f);
|
||||
int endx = int(min(max(lc.x, rc.x), clipRect.x1) + 0.5f);
|
||||
int startx = int(max(min(left.x(), right.x()), clipRect.x0) + 0.5f);
|
||||
int endx = int(min(max(left.x(), right.x()), clipRect.x1) + 0.5f);
|
||||
// Check if span is non-empty.
|
||||
int span = endx - startx;
|
||||
if (span > 0) {
|
||||
|
@ -3285,9 +3255,9 @@ static inline void draw_perspective_spans(int nump, Point3D* p,
|
|||
{
|
||||
// Calculate the fragment Z and W change per change in fragment X step.
|
||||
vec2_scalar stepZW =
|
||||
(rc.sel(Z, W) - lc.sel(Z, W)) * (1.0f / (rc.x - lc.x));
|
||||
(right.zw() - left.zw()) * (1.0f / (right.x() - left.x()));
|
||||
// Calculate initial Z and W values for span start.
|
||||
vec2_scalar zw = lc.sel(Z, W) + stepZW * (startx + 0.5f - lc.x);
|
||||
vec2_scalar zw = left.zw() + stepZW * (startx + 0.5f - left.x());
|
||||
// Set fragment shader's Z and W values so that it can use them to
|
||||
// cancel out the 1/w baked into the interpolants.
|
||||
fragment_shader->gl_FragCoord.z = init_interp(zw.x, stepZW.x);
|
||||
|
@ -3297,9 +3267,10 @@ static inline void draw_perspective_spans(int nump, Point3D* p,
|
|||
// edges per the change in right and left X. The left and right
|
||||
// interpolant values were previously multipled by 1/w, so the step and
|
||||
// initial span values take this into account.
|
||||
Interpolants step = (ro - lo) * (1.0f / (rc.x - lc.x));
|
||||
Interpolants step =
|
||||
(right.interp - left.interp) * (1.0f / (right.x() - left.x()));
|
||||
// Advance current interpolants to X at start of span.
|
||||
Interpolants o = lo + step * (startx + 0.5f - lc.x);
|
||||
Interpolants o = left.interp + step * (startx + 0.5f - left.x());
|
||||
fragment_shader->init_span(&o, &step, 4.0f);
|
||||
}
|
||||
if (!use_discard) {
|
||||
|
@ -3345,14 +3316,10 @@ static inline void draw_perspective_spans(int nump, Point3D* p,
|
|||
}
|
||||
}
|
||||
}
|
||||
// Advance left and right coordinates to next row based on slope.
|
||||
lc += lm;
|
||||
rc += rm;
|
||||
// Advance Y to next row.
|
||||
// Advance Y and edge interpolants to next row.
|
||||
y++;
|
||||
// Advance left and right edge interpolants to next row based on slope.
|
||||
lo += lom;
|
||||
ro += rom;
|
||||
left.nextRow();
|
||||
right.nextRow();
|
||||
// Advance buffers to next row.
|
||||
fbuf += colortex.stride(sizeof(P)) / sizeof(P);
|
||||
fdepth += depthtex.stride(sizeof(uint16_t)) / sizeof(uint16_t);
|
||||
|
|
Загрузка…
Ссылка в новой задаче