llvmpipe: special case triangles which fall in a single 16x16 block
authorKeith Whitwell <keithw@vmware.com>
Sun, 15 Aug 2010 21:58:26 +0000 (22:58 +0100)
committerKeith Whitwell <keithw@vmware.com>
Sun, 15 Aug 2010 22:02:10 +0000 (23:02 +0100)
Check for these and route them to a dedicated handler with one fewer
levels of recursive rasterization.

src/gallium/drivers/llvmpipe/lp_rast.h
src/gallium/drivers/llvmpipe/lp_rast_tri.c
src/gallium/drivers/llvmpipe/lp_setup_tri.c

index 44319a0ad6fc498d503588ac7c66c324c2dca54c..102e902d02c5de9f26b11eb618f33e35f2c1990d 100644 (file)
@@ -256,5 +256,9 @@ void lp_rast_begin_query(struct lp_rasterizer_task *,
 void lp_rast_end_query(struct lp_rasterizer_task *,
                        const union lp_rast_cmd_arg );
 
+void
+lp_rast_triangle_3_16(struct lp_rasterizer_task *task,
+                      const union lp_rast_cmd_arg arg);
+
 
 #endif
index 980c18c0240e3fe8fd1628d895c71dfe9055530b..673f67386bc02de43747cb1fd79dbdca0c7ecb1f 100644 (file)
@@ -157,3 +157,85 @@ build_mask_linear(int c, int dcdx, int dcdy)
 #define NR_PLANES 7
 #include "lp_rast_tri_tmp.h"
 
+
+/* Special case for 3 plane triangle which is contained entirely
+ * within a 16x16 block.
+ */
+void
+lp_rast_triangle_3_16(struct lp_rasterizer_task *task,
+                      const union lp_rast_cmd_arg arg)
+{
+   const struct lp_rast_triangle *tri = arg.triangle.tri;
+   const struct lp_rast_plane *plane = tri->plane;
+   unsigned mask = arg.triangle.plane_mask;
+   const int x = task->x + (mask & 0xf) * 16;
+   const int y = task->y + (mask >> 4) * 16;
+   unsigned outmask, inmask, partmask, partial_mask;
+   unsigned j;
+   int c[3];
+
+   outmask = 0;                 /* outside one or more trivial reject planes */
+   partmask = 0;                /* outside one or more trivial accept planes */
+
+   for (j = 0; j < 3; j++) {
+      c[j] = plane[j].c + plane[j].dcdy * y - plane[j].dcdx * x;
+
+      {
+        const int dcdx = -plane[j].dcdx * 4;
+        const int dcdy = plane[j].dcdy * 4;
+        const int cox = c[j] + plane[j].eo * 4;
+        const int cio = c[j] + plane[j].ei * 4 - 1;
+
+        outmask |= build_mask_linear(cox, dcdx, dcdy);
+        partmask |= build_mask_linear(cio, dcdx, dcdy);
+      }
+   }
+
+   if (outmask == 0xffff)
+      return;
+
+   /* Mask of sub-blocks which are inside all trivial accept planes:
+    */
+   inmask = ~partmask & 0xffff;
+
+   /* Mask of sub-blocks which are inside all trivial reject planes,
+    * but outside at least one trivial accept plane:
+    */
+   partial_mask = partmask & ~outmask;
+
+   assert((partial_mask & inmask) == 0);
+
+   /* Iterate over partials:
+    */
+   while (partial_mask) {
+      int i = ffs(partial_mask) - 1;
+      int ix = (i & 3) * 4;
+      int iy = (i >> 2) * 4;
+      int px = x + ix;
+      int py = y + iy; 
+      int cx[3];
+
+      partial_mask &= ~(1 << i);
+
+      for (j = 0; j < 3; j++)
+         cx[j] = (c[j] 
+                 - plane[j].dcdx * ix
+                 + plane[j].dcdy * iy);
+
+      do_block_4_3(task, tri, plane, px, py, cx);
+   }
+
+   /* Iterate over fulls: 
+    */
+   while (inmask) {
+      int i = ffs(inmask) - 1;
+      int ix = (i & 3) * 4;
+      int iy = (i >> 2) * 4;
+      int px = x + ix;
+      int py = y + iy; 
+
+      inmask &= ~(1 << i);
+
+      block_full_4(task, tri, px, py);
+   }
+}
index 393533ebee47306ab940b2620faed289316651f5..614a6372b4277b8be82faa0e0ec52203399b6b9c 100644 (file)
@@ -643,6 +643,26 @@ do_triangle_ccw(struct lp_setup_context *setup,
 
    /* Convert to tile coordinates, and inclusive ranges:
     */
+   if (nr_planes == 3) {
+      int ix0 = minx / 16;
+      int iy0 = miny / 16;
+      int ix1 = (maxx-1) / 16;
+      int iy1 = (maxy-1) / 16;
+      
+      if (iy0 == iy1 && ix0 == ix1)
+      {
+
+        /* Triangle is contained in a single 16x16 block:
+         */
+        int mask = (ix0 & 3) | ((iy0 & 3) << 4);
+
+        lp_scene_bin_command( scene, ix0/4, iy0/4,
+                              lp_rast_triangle_3_16,
+                              lp_rast_arg_triangle(tri, mask) );
+        return;
+      }
+   }
+
    ix0 = minx / TILE_SIZE;
    iy0 = miny / TILE_SIZE;
    ix1 = (maxx-1) / TILE_SIZE;