diff options
Diffstat (limited to 'src/gallium/drivers/llvmpipe/lp_setup_tri.c')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup_tri.c | 147 |
1 files changed, 94 insertions, 53 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c index 2164f3a1e3c..53ab1f1f0c0 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c @@ -40,12 +40,14 @@ #include "lp_state_setup.h" #include "lp_context.h" +#include <inttypes.h> + #define NUM_CHANNELS 4 #if defined(PIPE_ARCH_SSE) #include <emmintrin.h> #endif - + static INLINE int subpixel_snap(float a) { @@ -61,13 +63,13 @@ 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; + int32_t x[4]; + int32_t y[4]; + int64_t area; + int32_t dx01; + int32_t dy01; + int32_t dx20; + int32_t dy20; }; @@ -187,6 +189,19 @@ lp_rast_tri_tab[MAX_PLANES+1] = { LP_RAST_OP_TRIANGLE_8 }; +static unsigned +lp_rast_32_tri_tab[MAX_PLANES+1] = { + 0, /* should be impossible */ + LP_RAST_OP_TRIANGLE_32_1, + LP_RAST_OP_TRIANGLE_32_2, + LP_RAST_OP_TRIANGLE_32_3, + LP_RAST_OP_TRIANGLE_32_4, + LP_RAST_OP_TRIANGLE_32_5, + LP_RAST_OP_TRIANGLE_32_6, + LP_RAST_OP_TRIANGLE_32_7, + LP_RAST_OP_TRIANGLE_32_8 +}; + /** @@ -363,7 +378,10 @@ do_triangle_ccw(struct lp_setup_context *setup, plane = GET_PLANES(tri); #if defined(PIPE_ARCH_SSE) - { + if (setup->fb.width <= MAX_FIXED_LENGTH32 && + setup->fb.height <= MAX_FIXED_LENGTH32 && + (bbox.x1 - bbox.x0) <= MAX_FIXED_LENGTH32 && + (bbox.y1 - bbox.y0) <= MAX_FIXED_LENGTH32) { __m128i vertx, verty; __m128i shufx, shufy; __m128i dcdx, dcdy, c; @@ -375,6 +393,7 @@ do_triangle_ccw(struct lp_setup_context *setup, __m128i c_inc_mask, c_inc; __m128i eo, p0, p1, p2; __m128i zero = _mm_setzero_si128(); + PIPE_ALIGN_VAR(16) int32_t temp_vec[4]; vertx = _mm_loadu_si128((__m128i *)position->x); /* vertex x coords */ verty = _mm_loadu_si128((__m128i *)position->y); /* vertex y coords */ @@ -421,11 +440,20 @@ do_triangle_ccw(struct lp_setup_context *setup, transpose4_epi32(&c, &dcdx, &dcdy, &eo, &p0, &p1, &p2, &unused); - _mm_store_si128((__m128i *)&plane[0], p0); - _mm_store_si128((__m128i *)&plane[1], p1); - _mm_store_si128((__m128i *)&plane[2], p2); - } -#else +#define STORE_PLANE(plane, vec) do { \ + _mm_store_si128((__m128i *)&temp_vec, vec); \ + plane.c = (int64_t)temp_vec[0]; \ + plane.dcdx = temp_vec[1]; \ + plane.dcdy = temp_vec[2]; \ + plane.eo = temp_vec[3]; \ + } while(0) + + STORE_PLANE(plane[0], p0); + STORE_PLANE(plane[1], p1); + STORE_PLANE(plane[2], p2); +#undef STORE_PLANE + } else +#endif { int i; plane[0].dcdy = position->dx01; @@ -439,7 +467,8 @@ do_triangle_ccw(struct lp_setup_context *setup, /* half-edge constants, will be interated over the whole render * target. */ - plane[i].c = plane[i].dcdx * position->x[i] - plane[i].dcdy * position->y[i]; + plane[i].c = IMUL64(plane[i].dcdx, position->x[i]) - + IMUL64(plane[i].dcdy, position->y[i]); /* correct for top-left vs. bottom-left fill convention. */ @@ -460,8 +489,12 @@ do_triangle_ccw(struct lp_setup_context *setup, } } - plane[i].dcdx *= FIXED_ONE; - plane[i].dcdy *= FIXED_ONE; + /* Scale up to match c: + */ + assert((plane[i].dcdx << FIXED_ORDER) >> FIXED_ORDER == plane[i].dcdx); + assert((plane[i].dcdy << FIXED_ORDER) >> FIXED_ORDER == plane[i].dcdy); + plane[i].dcdx <<= FIXED_ORDER; + plane[i].dcdy <<= FIXED_ORDER; /* find trivial reject offsets for each edge for a single-pixel * sized block. These will be scaled up at each recursive level to @@ -473,22 +506,21 @@ do_triangle_ccw(struct lp_setup_context *setup, if (plane[i].dcdy > 0) plane[i].eo += plane[i].dcdy; } } -#endif if (0) { - debug_printf("p0: %08x/%08x/%08x/%08x\n", + debug_printf("p0: %"PRIx64"/%08x/%08x/%"PRIx64"\n", plane[0].c, plane[0].dcdx, plane[0].dcdy, plane[0].eo); - debug_printf("p1: %08x/%08x/%08x/%08x\n", + debug_printf("p1: %"PRIx64"/%08x/%08x/%"PRIx64"\n", plane[1].c, plane[1].dcdx, plane[1].dcdy, plane[1].eo); - debug_printf("p0: %08x/%08x/%08x/%08x\n", + debug_printf("p2: %"PRIx64"/%08x/%08x/%"PRIx64"\n", plane[2].c, plane[2].dcdx, plane[2].dcdy, @@ -578,7 +610,6 @@ lp_setup_bin_triangle( struct lp_setup_context *setup, struct lp_scene *scene = setup->scene; struct u_rect trimmed_box = *bbox; int i; - /* What is the largest power-of-two boundary this triangle crosses: */ int dx = floor_pot((bbox->x0 ^ bbox->x1) | @@ -587,8 +618,10 @@ lp_setup_bin_triangle( struct lp_setup_context *setup, /* The largest dimension of the rasterized area of the triangle * (aligned to a 4x4 grid), rounded down to the nearest power of two: */ - int sz = floor_pot((bbox->x1 - (bbox->x0 & ~3)) | - (bbox->y1 - (bbox->y0 & ~3))); + int max_sz = ((bbox->x1 - (bbox->x0 & ~3)) | + (bbox->y1 - (bbox->y0 & ~3))); + int sz = floor_pot(max_sz); + boolean use_32bits = max_sz <= MAX_FIXED_LENGTH32; /* Now apply scissor, etc to the bounding box. Could do this * earlier, but it confuses the logic for tri-16 and would force @@ -619,6 +652,8 @@ lp_setup_bin_triangle( struct lp_setup_context *setup, assert(py + 4 <= TILE_SIZE); return lp_scene_bin_cmd_with_state( scene, ix0, iy0, setup->fs.stored, + use_32bits ? + LP_RAST_OP_TRIANGLE_32_3_4 : LP_RAST_OP_TRIANGLE_3_4, lp_rast_arg_triangle_contained(tri, px, py) ); } @@ -641,6 +676,8 @@ lp_setup_bin_triangle( struct lp_setup_context *setup, return lp_scene_bin_cmd_with_state( scene, ix0, iy0, setup->fs.stored, + use_32bits ? + LP_RAST_OP_TRIANGLE_32_3_16 : LP_RAST_OP_TRIANGLE_3_16, lp_rast_arg_triangle_contained(tri, px, py) ); } @@ -655,6 +692,8 @@ lp_setup_bin_triangle( struct lp_setup_context *setup, return lp_scene_bin_cmd_with_state(scene, ix0, iy0, setup->fs.stored, + use_32bits ? + LP_RAST_OP_TRIANGLE_32_4_16 : LP_RAST_OP_TRIANGLE_4_16, lp_rast_arg_triangle_contained(tri, px, py)); } @@ -662,19 +701,20 @@ lp_setup_bin_triangle( struct lp_setup_context *setup, /* Triangle is contained in a single tile: */ - return lp_scene_bin_cmd_with_state( scene, ix0, iy0, setup->fs.stored, - lp_rast_tri_tab[nr_planes], - lp_rast_arg_triangle(tri, (1<<nr_planes)-1) ); + return lp_scene_bin_cmd_with_state( + scene, ix0, iy0, setup->fs.stored, + use_32bits ? lp_rast_32_tri_tab[nr_planes] : lp_rast_tri_tab[nr_planes], + lp_rast_arg_triangle(tri, (1<<nr_planes)-1)); } else { struct lp_rast_plane *plane = GET_PLANES(tri); - int c[MAX_PLANES]; - int ei[MAX_PLANES]; + int64_t c[MAX_PLANES]; + int64_t ei[MAX_PLANES]; - int eo[MAX_PLANES]; - int xstep[MAX_PLANES]; - int ystep[MAX_PLANES]; + int64_t eo[MAX_PLANES]; + int64_t xstep[MAX_PLANES]; + int64_t ystep[MAX_PLANES]; int x, y; int ix0 = trimmed_box.x0 / TILE_SIZE; @@ -684,16 +724,16 @@ lp_setup_bin_triangle( struct lp_setup_context *setup, for (i = 0; i < nr_planes; i++) { c[i] = (plane[i].c + - plane[i].dcdy * iy0 * TILE_SIZE - - plane[i].dcdx * ix0 * TILE_SIZE); + IMUL64(plane[i].dcdy, iy0) * TILE_SIZE - + IMUL64(plane[i].dcdx, ix0) * TILE_SIZE); ei[i] = (plane[i].dcdy - plane[i].dcdx - plane[i].eo) << TILE_ORDER; eo[i] = plane[i].eo << TILE_ORDER; - xstep[i] = -(plane[i].dcdx << TILE_ORDER); - ystep[i] = plane[i].dcdy << TILE_ORDER; + xstep[i] = -(((int64_t)plane[i].dcdx) << TILE_ORDER); + ystep[i] = ((int64_t)plane[i].dcdy) << TILE_ORDER; } @@ -705,22 +745,22 @@ lp_setup_bin_triangle( struct lp_setup_context *setup, */ for (y = iy0; y <= iy1; y++) { - boolean in = FALSE; /* are we inside the triangle? */ - int cx[MAX_PLANES]; + boolean in = FALSE; /* are we inside the triangle? */ + int64_t cx[MAX_PLANES]; for (i = 0; i < nr_planes; i++) cx[i] = c[i]; - for (x = ix0; x <= ix1; x++) - { + for (x = ix0; x <= ix1; x++) + { int out = 0; int partial = 0; for (i = 0; i < nr_planes; i++) { - int planeout = cx[i] + eo[i]; - int planepartial = cx[i] + ei[i] - 1; - out |= (planeout >> 31); - partial |= (planepartial >> 31) & (1<<i); + int64_t planeout = cx[i] + eo[i]; + int64_t planepartial = cx[i] + ei[i] - 1; + out |= (planeout >> 63); + partial |= (planepartial >> 63) & (1<<i); } if (out) { @@ -730,7 +770,7 @@ lp_setup_bin_triangle( struct lp_setup_context *setup, LP_COUNT(nr_empty_64); } else if (partial) { - /* Not trivially accepted by at least one plane - + /* Not trivially accepted by at least one plane - * rasterize/shade partial tile */ int count = util_bitcount(partial); @@ -738,7 +778,9 @@ lp_setup_bin_triangle( struct lp_setup_context *setup, if (!lp_scene_bin_cmd_with_state( scene, x, y, setup->fs.stored, - lp_rast_tri_tab[count], + use_32bits ? + lp_rast_32_tri_tab[count] : + lp_rast_tri_tab[count], lp_rast_arg_triangle(tri, partial) )) goto fail; @@ -752,14 +794,12 @@ lp_setup_bin_triangle( struct lp_setup_context *setup, goto fail; } - /* Iterate cx values across the region: - */ + /* Iterate cx values across the region: */ for (i = 0; i < nr_planes; i++) cx[i] += xstep[i]; - } - - /* Iterate c values down the region: - */ + } + + /* Iterate c values down the region: */ for (i = 0; i < nr_planes; i++) c[i] += ystep[i]; } @@ -823,7 +863,8 @@ calc_fixed_position( struct lp_setup_context *setup, 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; + position->area = IMUL64(position->dx01, position->dy20) - + IMUL64(position->dx20, position->dy01); } |