summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/llvmpipe
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/llvmpipe')
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_tri.c162
1 files changed, 106 insertions, 56 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
index 26d35debdaf..9916101734f 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
@@ -58,9 +58,16 @@ fixed_to_float(int a)
}
-
-
-
+/* Position and area in fixed point coordinates */
+struct fixed_position {
+ int x[4];
+ int y[4];
+ int area;
+ int dx01;
+ int dy01;
+ int dx20;
+ int dy20;
+};
/**
@@ -226,21 +233,23 @@ lp_setup_whole_tile(struct lp_setup_context *setup,
*/
static boolean
do_triangle_ccw(struct lp_setup_context *setup,
- const float (*v0)[4],
- const float (*v1)[4],
- const float (*v2)[4],
- boolean frontfacing )
+ struct fixed_position* position,
+ const float (*v0)[4],
+ const float (*v1)[4],
+ const float (*v2)[4],
+ boolean frontfacing )
{
struct lp_scene *scene = setup->scene;
const struct lp_setup_variant_key *key = &setup->setup.variant->key;
struct lp_rast_triangle *tri;
struct lp_rast_plane *plane;
- int x[4];
- int y[4];
struct u_rect bbox;
unsigned tri_bytes;
int nr_planes = 3;
+ /* Area should always be positive here */
+ assert(position->area > 0);
+
if (0)
lp_setup_print_triangle(setup, v0, v1, v2);
@@ -251,17 +260,6 @@ do_triangle_ccw(struct lp_setup_context *setup,
nr_planes = 3;
}
- /* x/y positions in fixed point */
- x[0] = subpixel_snap(v0[0][0] - setup->pixel_offset);
- x[1] = subpixel_snap(v1[0][0] - setup->pixel_offset);
- x[2] = subpixel_snap(v2[0][0] - setup->pixel_offset);
- x[3] = 0;
- y[0] = subpixel_snap(v0[0][1] - setup->pixel_offset);
- y[1] = subpixel_snap(v1[0][1] - setup->pixel_offset);
- y[2] = subpixel_snap(v2[0][1] - setup->pixel_offset);
- y[3] = 0;
-
-
/* Bounding rectangle (in pixels) */
{
/* Yes this is necessary to accurately calculate bounding boxes
@@ -272,12 +270,12 @@ do_triangle_ccw(struct lp_setup_context *setup,
int adj = (setup->pixel_offset != 0) ? 1 : 0;
/* Inclusive x0, exclusive x1 */
- bbox.x0 = MIN3(x[0], x[1], x[2]) >> FIXED_ORDER;
- bbox.x1 = (MAX3(x[0], x[1], x[2]) - 1) >> FIXED_ORDER;
+ bbox.x0 = MIN3(position->x[0], position->x[1], position->x[2]) >> FIXED_ORDER;
+ bbox.x1 = (MAX3(position->x[0], position->x[1], position->x[2]) - 1) >> FIXED_ORDER;
/* Inclusive / exclusive depending upon adj (bottom-left or top-right) */
- bbox.y0 = (MIN3(y[0], y[1], y[2]) + adj) >> FIXED_ORDER;
- bbox.y1 = (MAX3(y[0], y[1], y[2]) - 1 + adj) >> FIXED_ORDER;
+ bbox.y0 = (MIN3(position->y[0], position->y[1], position->y[2]) + adj) >> FIXED_ORDER;
+ bbox.y1 = (MAX3(position->y[0], position->y[1], position->y[2]) - 1 + adj) >> FIXED_ORDER;
}
if (bbox.x1 < bbox.x0 ||
@@ -354,8 +352,8 @@ do_triangle_ccw(struct lp_setup_context *setup,
__m128i eo, p0, p1, p2;
__m128i zero = _mm_setzero_si128();
- vertx = _mm_loadu_si128((__m128i *)x); /* vertex x coords */
- verty = _mm_loadu_si128((__m128i *)y); /* vertex y coords */
+ vertx = _mm_loadu_si128((__m128i *)position->x); /* vertex x coords */
+ verty = _mm_loadu_si128((__m128i *)position->y); /* vertex y coords */
shufx = _mm_shuffle_epi32(vertx, _MM_SHUFFLE(3,0,2,1));
shufy = _mm_shuffle_epi32(verty, _MM_SHUFFLE(3,0,2,1));
@@ -406,18 +404,18 @@ do_triangle_ccw(struct lp_setup_context *setup,
#else
{
int i;
- plane[0].dcdy = x[0] - x[1];
- plane[1].dcdy = x[1] - x[2];
- plane[2].dcdy = x[2] - x[0];
- plane[0].dcdx = y[0] - y[1];
- plane[1].dcdx = y[1] - y[2];
- plane[2].dcdx = y[2] - y[0];
+ plane[0].dcdy = position->dx01;
+ plane[1].dcdy = position->x[1] - position->x[2];
+ plane[2].dcdy = position->dx20;
+ plane[0].dcdx = position->dy01;
+ plane[1].dcdx = position->y[1] - position->y[2];
+ plane[2].dcdx = position->dy20;
for (i = 0; i < 3; i++) {
/* half-edge constants, will be interated over the whole render
* target.
*/
- plane[i].c = plane[i].dcdx * x[i] - plane[i].dcdy * y[i];
+ plane[i].c = plane[i].dcdx * position->x[i] - plane[i].dcdy * position->y[i];
/* correct for top-left vs. bottom-left fill convention.
*
@@ -768,31 +766,77 @@ fail:
* Try to draw the triangle, restart the scene on failure.
*/
static void retry_triangle_ccw( struct lp_setup_context *setup,
+ struct fixed_position* position,
const float (*v0)[4],
const float (*v1)[4],
const float (*v2)[4],
boolean front)
{
- if (!do_triangle_ccw( setup, v0, v1, v2, front ))
+ if (!do_triangle_ccw( setup, position, v0, v1, v2, front ))
{
if (!lp_setup_flush_and_restart(setup))
return;
- if (!do_triangle_ccw( setup, v0, v1, v2, front ))
+ if (!do_triangle_ccw( setup, position, v0, v1, v2, front ))
return;
}
}
-static INLINE float
-calc_area(const float (*v0)[4],
- const float (*v1)[4],
- const float (*v2)[4])
+
+/**
+ * Calculate fixed position data for a triangle
+ */
+static INLINE void
+calc_fixed_position( struct lp_setup_context *setup,
+ struct fixed_position* position,
+ const float (*v0)[4],
+ const float (*v1)[4],
+ const float (*v2)[4])
{
- float dx01 = v0[0][0] - v1[0][0];
- float dy01 = v0[0][1] - v1[0][1];
- float dx20 = v2[0][0] - v0[0][0];
- float dy20 = v2[0][1] - v0[0][1];
- return dx01 * dy20 - dx20 * dy01;
+ position->x[0] = subpixel_snap(v0[0][0] - setup->pixel_offset);
+ position->x[1] = subpixel_snap(v1[0][0] - setup->pixel_offset);
+ position->x[2] = subpixel_snap(v2[0][0] - setup->pixel_offset);
+ position->x[3] = 0;
+
+ position->y[0] = subpixel_snap(v0[0][1] - setup->pixel_offset);
+ position->y[1] = subpixel_snap(v1[0][1] - setup->pixel_offset);
+ position->y[2] = subpixel_snap(v2[0][1] - setup->pixel_offset);
+ position->y[3] = 0;
+
+ position->dx01 = position->x[0] - position->x[1];
+ position->dy01 = position->y[0] - position->y[1];
+
+ position->dx20 = position->x[2] - position->x[0];
+ position->dy20 = position->y[2] - position->y[0];
+
+ position->area = position->dx01 * position->dy20 - position->dx20 * position->dy01;
+}
+
+
+/**
+ * Rotate a triangle, flipping its clockwise direction,
+ * Swaps values for xy[1] and xy[2]
+ */
+static INLINE void
+rotate_fixed_position( struct fixed_position* position )
+{
+ int x, y;
+
+ x = position->x[2];
+ y = position->y[2];
+ position->x[2] = position->x[1];
+ position->y[2] = position->y[1];
+ position->x[1] = x;
+ position->y[1] = y;
+
+ x = position->dx01;
+ y = position->dy01;
+ position->dx01 = -position->dx20;
+ position->dy01 = -position->dy20;
+ position->dx20 = -x;
+ position->dy20 = -y;
+
+ position->area = -position->area;
}
@@ -804,10 +848,13 @@ static void triangle_cw( struct lp_setup_context *setup,
const float (*v1)[4],
const float (*v2)[4] )
{
- float area = calc_area(v0, v1, v2);
+ struct fixed_position position;
+ calc_fixed_position(setup, &position, v0, v1, v2);
- if (area < 0.0f)
- retry_triangle_ccw(setup, v0, v2, v1, !setup->ccw_is_frontface);
+ if (position.area < 0) {
+ rotate_fixed_position(&position);
+ retry_triangle_ccw(setup, &position, v0, v2, v1, !setup->ccw_is_frontface);
+ }
}
@@ -816,10 +863,11 @@ static void triangle_ccw( struct lp_setup_context *setup,
const float (*v1)[4],
const float (*v2)[4])
{
- float area = calc_area(v0, v1, v2);
+ struct fixed_position position;
+ calc_fixed_position(setup, &position, v0, v1, v2);
- if (area > 0.0f)
- retry_triangle_ccw(setup, v0, v1, v2, setup->ccw_is_frontface);
+ if (position.area > 0)
+ retry_triangle_ccw(setup, &position, v0, v1, v2, setup->ccw_is_frontface);
}
/**
@@ -830,7 +878,8 @@ static void triangle_both( struct lp_setup_context *setup,
const float (*v1)[4],
const float (*v2)[4] )
{
- float area = calc_area(v0, v1, v2);
+ struct fixed_position position;
+ calc_fixed_position(setup, &position, v0, v1, v2);
if (0) {
assert(!util_is_inf_or_nan(v0[0][0]));
@@ -839,13 +888,14 @@ static void triangle_both( struct lp_setup_context *setup,
assert(!util_is_inf_or_nan(v1[0][1]));
assert(!util_is_inf_or_nan(v2[0][0]));
assert(!util_is_inf_or_nan(v2[0][1]));
- assert(!util_is_inf_or_nan(area));
}
- if (area > 0.0f)
- retry_triangle_ccw( setup, v0, v1, v2, setup->ccw_is_frontface );
- else if (area < 0.0f)
- retry_triangle_ccw( setup, v0, v2, v1, !setup->ccw_is_frontface );
+ if (position.area > 0)
+ retry_triangle_ccw( setup, &position, v0, v1, v2, setup->ccw_is_frontface );
+ else if (position.area < 0) {
+ rotate_fixed_position( &position );
+ retry_triangle_ccw( setup, &position, v0, v2, v1, !setup->ccw_is_frontface );
+ }
}