aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJosé Fonseca <[email protected]>2011-10-05 11:31:15 +0100
committerJosé Fonseca <[email protected]>2011-10-05 18:07:05 +0100
commitc620087432b2055aa9301f19f8b6444080698c90 (patch)
tree7950a03f39959a41913dded80267a19b0e316faa /src
parent9c697a9d004da4aa7a26d3bda17cc473f50345ea (diff)
llvmpipe: Ensure the 16x16 special rasterization path does not touch outside the tile.
llvmpipe has a few special rasterization paths for triangles contained in 16x16 blocks, but it allows the 16x16 block to be aligned only to a 4x4 grid. Some 16x16 blocks could actually intersect the tile if the triangle is 16 pixels in one dimension but 4 in the other, causing a buffer overflow. The fix consists of budging the 16x16 blocks back inside the tile.
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.c2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast_priv.h6
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast_tri.c4
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_tri.c24
4 files changed, 31 insertions, 5 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index 131785852c8..c4560bfe6c0 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -436,6 +436,8 @@ lp_rast_shade_quads_mask(struct lp_rasterizer_task *task,
assert(state);
/* Sanity checks */
+ assert(x < scene->tiles_x * TILE_SIZE);
+ assert(y < scene->tiles_y * TILE_SIZE);
assert(x % TILE_VECTOR_WIDTH == 0);
assert(y % TILE_VECTOR_HEIGHT == 0);
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
index cd686bc82c1..d0bda354732 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
@@ -151,6 +151,8 @@ lp_rast_get_depth_block_pointer(struct lp_rasterizer_task *task,
const struct lp_scene *scene = task->scene;
void *depth;
+ assert(x < scene->tiles_x * TILE_SIZE);
+ assert(y < scene->tiles_y * TILE_SIZE);
assert((x % TILE_VECTOR_WIDTH) == 0);
assert((y % TILE_VECTOR_HEIGHT) == 0);
@@ -181,6 +183,8 @@ lp_rast_get_color_tile_pointer(struct lp_rasterizer_task *task,
{
const struct lp_scene *scene = task->scene;
+ assert(task->x < scene->tiles_x * TILE_SIZE);
+ assert(task->y < scene->tiles_y * TILE_SIZE);
assert(task->x % TILE_SIZE == 0);
assert(task->y % TILE_SIZE == 0);
assert(buf < scene->fb.nr_cbufs);
@@ -219,6 +223,8 @@ lp_rast_get_color_block_pointer(struct lp_rasterizer_task *task,
unsigned px, py, pixel_offset;
uint8_t *color;
+ assert(x < task->scene->tiles_x * TILE_SIZE);
+ assert(y < task->scene->tiles_y * TILE_SIZE);
assert((x % TILE_VECTOR_WIDTH) == 0);
assert((y % TILE_VECTOR_HEIGHT) == 0);
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_tri.c b/src/gallium/drivers/llvmpipe/lp_rast_tri.c
index 042c315635e..3adfbaacd35 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_tri.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast_tri.c
@@ -364,8 +364,8 @@ lp_rast_triangle_3_4(struct lp_rasterizer_task *task,
{
const struct lp_rast_triangle *tri = arg.triangle.tri;
const struct lp_rast_plane *plane = GET_PLANES(tri);
- int x = (arg.triangle.plane_mask & 0xff) + task->x;
- int y = (arg.triangle.plane_mask >> 8) + task->y;
+ unsigned x = (arg.triangle.plane_mask & 0xff) + task->x;
+ unsigned y = (arg.triangle.plane_mask >> 8) + task->y;
__m128i p0 = _mm_load_si128((__m128i *)&plane[0]); /* c, dcdx, dcdy, eo */
__m128i p1 = _mm_load_si128((__m128i *)&plane[1]); /* c, dcdx, dcdy, eo */
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
index bfb6bf277bd..1737d1dbacf 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
@@ -593,18 +593,32 @@ lp_setup_bin_triangle( struct lp_setup_context *setup,
{
int ix0 = bbox->x0 / TILE_SIZE;
int iy0 = bbox->y0 / TILE_SIZE;
- int px = bbox->x0 & 63 & ~3;
- int py = bbox->y0 & 63 & ~3;
- int mask = px | (py << 8);
+ unsigned px = bbox->x0 & 63 & ~3;
+ unsigned py = bbox->y0 & 63 & ~3;
+ unsigned mask;
assert(iy0 == bbox->y1 / TILE_SIZE &&
ix0 == bbox->x1 / TILE_SIZE);
+ if (4 <= sz && sz < 16) {
+ /*
+ * 16x16 block is only 4x4 aligned, and can exceed the tile dimensions
+ * if the triangle is 16 pixels in one dimension but 4 in the other.
+ * So budge the 16x16 back inside the tile.
+ */
+ px = MIN2(px, TILE_SIZE - 16);
+ py = MIN2(py, TILE_SIZE - 16);
+ }
+
+ mask = px | (py << 8);
+
if (nr_planes == 3) {
if (sz < 4)
{
/* Triangle is contained in a single 4x4 stamp:
*/
+ assert(px + 4 <= TILE_SIZE);
+ assert(py + 4 <= TILE_SIZE);
return lp_scene_bin_cmd_with_state( scene, ix0, iy0,
setup->fs.stored,
LP_RAST_OP_TRIANGLE_3_4,
@@ -615,6 +629,8 @@ lp_setup_bin_triangle( struct lp_setup_context *setup,
{
/* Triangle is contained in a single 16x16 block:
*/
+ assert(px + 16 <= TILE_SIZE);
+ assert(py + 16 <= TILE_SIZE);
return lp_scene_bin_cmd_with_state( scene, ix0, iy0,
setup->fs.stored,
LP_RAST_OP_TRIANGLE_3_16,
@@ -623,6 +639,8 @@ lp_setup_bin_triangle( struct lp_setup_context *setup,
}
else if (nr_planes == 4 && sz < 16)
{
+ assert(px + 16 <= TILE_SIZE);
+ assert(py + 16 <= TILE_SIZE);
return lp_scene_bin_cmd_with_state(scene, ix0, iy0,
setup->fs.stored,
LP_RAST_OP_TRIANGLE_4_16,