llvmpipe: fix some corner cases with line rendering
Some comparisons were wrong depending on swapped endpoints and the bottom_edge_rule (if the endpoint was exactly touching pixel center), hence the code assuming a line endpoint which should be drawn according to diamond exit rules would already be drawn (so not adjusting the endpoint) when in reality it was not, in which case the line would end up one pixel too short. Note that this is still not fully correct - the logic as such should be correct now, however these comparisons can give wrong results due to float math vs. fixed point planes (an endpoint very close to a pixel center might be exactly at pixel center in fixed point), but this should do for now. (Also, the logic is still completely wrong for state trackers not using half_pixel_center setting, but this is only really a concern for dx9 state tracker.) Reviewed-by: Brian Paul <brianp@vmware.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22481>
This commit is contained in:

committed by
Marge Bot

parent
9b6abe4206
commit
f23d54cfaa
@@ -409,8 +409,8 @@ try_setup_line(struct lp_setup_context *setup,
|
||||
}
|
||||
|
||||
/* Are we already drawing start/end? */
|
||||
bool will_draw_start = sign(-x1diff) != sign(dx);
|
||||
bool will_draw_end = (sign(x2diff) == sign(-dx)) || x2diff==0;
|
||||
bool will_draw_start;
|
||||
bool will_draw_end;
|
||||
|
||||
/* interpolate using the preferred wide-lines formula */
|
||||
info.dx *= 1.0f + dydx * dydx;
|
||||
@@ -421,23 +421,31 @@ try_setup_line(struct lp_setup_context *setup,
|
||||
const float (*temp)[4] = v1;
|
||||
v1 = v2;
|
||||
v2 = temp;
|
||||
dx = -dx;
|
||||
|
||||
/* Otherwise shift planes appropriately */
|
||||
/* left edge */
|
||||
will_draw_start = x1diff <= 0.f;
|
||||
if (will_draw_start != draw_start) {
|
||||
x_offset_end = -x1diff - 0.5f;
|
||||
y_offset_end = x_offset_end * dydx;
|
||||
|
||||
}
|
||||
/* right edge */
|
||||
will_draw_end = x2diff > 0.f;
|
||||
if (will_draw_end != draw_end) {
|
||||
x_offset = -x2diff - 0.5f;
|
||||
y_offset = x_offset * dydx;
|
||||
}
|
||||
} else {
|
||||
/* Otherwise shift planes appropriately */
|
||||
/* right edge */
|
||||
will_draw_start = x1diff > 0.f;
|
||||
if (will_draw_start != draw_start) {
|
||||
x_offset = -x1diff + 0.5f;
|
||||
y_offset = x_offset * dydx;
|
||||
}
|
||||
/* left edge */
|
||||
will_draw_end = x2diff <= 0.f;
|
||||
if (will_draw_end != draw_end) {
|
||||
x_offset_end = -x2diff + 0.5f;
|
||||
y_offset_end = x_offset_end * dydx;
|
||||
@@ -493,9 +501,15 @@ try_setup_line(struct lp_setup_context *setup,
|
||||
draw_end = (xintersect < 1.0f && xintersect >= 0.0f);
|
||||
}
|
||||
|
||||
/* Are we already drawing start/end? */
|
||||
bool will_draw_start = sign(y1diff) == sign(dy);
|
||||
bool will_draw_end = (sign(-y2diff) == sign(dy)) || y2diff==0;
|
||||
/*
|
||||
* Are we already drawing start/end?
|
||||
* FIXME: this needs to be done with fixed point arithmetic (otherwise
|
||||
* the comparisons against zero are not mirroring what actually happens
|
||||
* when rasterizing using the plane equations).
|
||||
*/
|
||||
|
||||
bool will_draw_start;
|
||||
bool will_draw_end;
|
||||
|
||||
/* interpolate using the preferred wide-lines formula */
|
||||
info.dx = 0.0f;
|
||||
@@ -506,23 +520,42 @@ try_setup_line(struct lp_setup_context *setup,
|
||||
const float (*temp)[4] = v1;
|
||||
v1 = v2;
|
||||
v2 = temp;
|
||||
dy = -dy;
|
||||
|
||||
if (setup->bottom_edge_rule) {
|
||||
will_draw_start = y1diff >= 0.f;
|
||||
will_draw_end = y2diff < 0.f;
|
||||
} else {
|
||||
will_draw_start = y1diff > 0.f;
|
||||
will_draw_end = y2diff <= 0.f;
|
||||
}
|
||||
|
||||
/* Otherwise shift planes appropriately */
|
||||
/* bottom edge */
|
||||
if (will_draw_start != draw_start) {
|
||||
y_offset_end = -y1diff + 0.5f;
|
||||
x_offset_end = y_offset_end * dxdy;
|
||||
}
|
||||
/* top edge */
|
||||
if (will_draw_end != draw_end) {
|
||||
y_offset = -y2diff + 0.5f;
|
||||
x_offset = y_offset * dxdy;
|
||||
}
|
||||
} else {
|
||||
if (setup->bottom_edge_rule) {
|
||||
will_draw_start = y1diff < 0.f;
|
||||
will_draw_end = y2diff >= 0.f;
|
||||
} else {
|
||||
will_draw_start = y1diff <= 0.f;
|
||||
will_draw_end = y2diff > 0.f;
|
||||
}
|
||||
|
||||
/* Otherwise shift planes appropriately */
|
||||
/* top edge */
|
||||
if (will_draw_start != draw_start) {
|
||||
y_offset = -y1diff - 0.5f;
|
||||
x_offset = y_offset * dxdy;
|
||||
}
|
||||
/* bottom edge */
|
||||
if (will_draw_end != draw_end) {
|
||||
y_offset_end = -y2diff - 0.5f;
|
||||
x_offset_end = y_offset_end * dxdy;
|
||||
|
Reference in New Issue
Block a user