draw: no need to rearrange most primitives in vcache for flatshade-first
authorKeith Whitwell <keith@tungstengraphics.com>
Tue, 10 Jun 2008 13:46:25 +0000 (14:46 +0100)
committerKeith Whitwell <keith@tungstengraphics.com>
Tue, 10 Jun 2008 13:48:57 +0000 (14:48 +0100)
The driver/pipeline will still be applying flatshade-first state to the
triangles emitted from vcache, so there's no need to rotate the vertices
of most primitives.  The only exception is POLYGON, as explained in the
code.

src/gallium/auxiliary/draw/draw_pt_fetch.c
src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h

index 07f4c991642c0d8b0a533e9738286d5ef1c97b5d..b8fd3aa1d86fb75d5c2d3f7441f236d7ab164f3c 100644 (file)
@@ -114,7 +114,10 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
       fetch->translate = translate_cache_find(fetch->cache, &key);
 
       {
-        static struct vertex_header vh = { 0, 1, 0, 0xffff };
+        static struct vertex_header vh = { 0, 
+                                            1, /* edgeflag */
+                                            0, 
+                                            0xffff };
         fetch->translate->set_buffer(fetch->translate,
                                      draw->pt.nr_vertex_buffers,
                                      &vh,
index ec05bbeab40289761aee78533111d4f65e1a61de..f2334a84f633453db1c0daba6b51c293db2b65f0 100644 (file)
@@ -7,15 +7,18 @@ static void FUNC( struct draw_pt_front_end *frontend,
 {
    struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
    struct draw_context *draw = vcache->draw;
-
-   boolean flatfirst = (draw->rasterizer->flatshade && 
-                        draw->rasterizer->flatshade_first);
    unsigned i;
    ushort flags;
 
    if (0) debug_printf("%s %d\n", __FUNCTION__, count);
 
-
+   /* Note that no adjustment is made here for flatshade provoking
+    * vertex.  This was previously the case, but was incorrect as the
+    * same logic would be applied twice both here & in the pipeline
+    * code or driver.  The rule is now that we just preserve the
+    * original order in this code, and leave identification of the PV
+    * to the pipeline and driver.
+    */
    switch (vcache->input_prim) {
    case PIPE_PRIM_POINTS:
       for (i = 0; i < count; i ++) {
@@ -72,45 +75,23 @@ static void FUNC( struct draw_pt_front_end *frontend,
       break;
 
    case PIPE_PRIM_TRIANGLE_STRIP:
-      if (flatfirst) {
-         for (i = 0; i+2 < count; i++) {
-            TRIANGLE( vcache,
-                      DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, 
-                      get_elt(elts, i + 0),
-                      get_elt(elts, i + 1 + (i&1)),
-                      get_elt(elts, i + 2 - (i&1)));
-         }
-      }
-      else {
-         for (i = 0; i+2 < count; i++) {
-            TRIANGLE( vcache,
-                      DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, 
-                      get_elt(elts, i + 0 + (i&1)),
-                      get_elt(elts, i + 1 - (i&1)),
-                      get_elt(elts, i + 2 ));
-         }
+      for (i = 0; i+2 < count; i++) {
+         TRIANGLE( vcache,
+                   DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, 
+                   get_elt(elts, i + 0 + (i&1)),
+                   get_elt(elts, i + 1 - (i&1)),
+                   get_elt(elts, i + 2 ));
       }
       break;
 
    case PIPE_PRIM_TRIANGLE_FAN:
       if (count >= 3) {
-         if (flatfirst) {
-            for (i = 0; i+2 < count; i++) {
-               TRIANGLE( vcache,
-                         DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, 
-                         get_elt(elts, i + 1),
-                         get_elt(elts, i + 2),
-                         get_elt(elts, 0 ));
-            }
-         }
-         else {
-            for (i = 0; i+2 < count; i++) {
-               TRIANGLE( vcache,
-                         DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, 
-                         get_elt(elts, 0),
-                         get_elt(elts, i + 1),
-                         get_elt(elts, i + 2 ));
-            }
+         for (i = 0; i+2 < count; i++) {
+            TRIANGLE( vcache,
+                      DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, 
+                      get_elt(elts, i + 1),
+                      get_elt(elts, i + 2),
+                      get_elt(elts, 0 ));
          }
       }
       break;
@@ -138,26 +119,58 @@ static void FUNC( struct draw_pt_front_end *frontend,
 
    case PIPE_PRIM_POLYGON:
       {
+         boolean flatfirst = (draw->rasterizer->flatshade && 
+                              draw->rasterizer->flatshade_first);
+
          /* These bitflags look a little odd because we submit the
           * vertices as (1,2,0) to satisfy flatshade requirements.  
+          *
+          * Polygon is defined has having vertex 0 be the provoking
+          * flatshade vertex and all known API's match this usage.
+          * However, the PV's for the triangles we emit from this
+          * decomposition vary according to the API, and hence we have
+          * to choose between two ways of emitting the triangles.
           */
-         const ushort edge_first  = DRAW_PIPE_EDGE_FLAG_2;
-         const ushort edge_middle = DRAW_PIPE_EDGE_FLAG_0;
-         const ushort edge_last   = DRAW_PIPE_EDGE_FLAG_1;
-
-         flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle;
-
-        for (i = 0; i+2 < count; i++, flags = edge_middle) {
-
-            if (i + 3 == count)
-               flags |= edge_last;
-
-           TRIANGLE( vcache,
-                      flags,
-                      get_elt(elts, i + 1),
-                      get_elt(elts, i + 2),
-                      get_elt(elts, 0));
-        }
+         if (flatfirst) {
+            const ushort edge_first  = DRAW_PIPE_EDGE_FLAG_0;
+            const ushort edge_middle = DRAW_PIPE_EDGE_FLAG_1;
+            const ushort edge_last   = DRAW_PIPE_EDGE_FLAG_2;
+            
+            flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle;
+            
+            for (i = 0; i+2 < count; i++, flags = edge_middle) {
+               
+               if (i + 3 == count)
+                  flags |= edge_last;
+               
+               /* PV is first vertex */
+               TRIANGLE( vcache,
+                         flags,
+                         get_elt(elts, 0),
+                         get_elt(elts, i + 1),
+                         get_elt(elts, i + 2));
+            }
+         }
+         else {
+            const ushort edge_first  = DRAW_PIPE_EDGE_FLAG_2;
+            const ushort edge_middle = DRAW_PIPE_EDGE_FLAG_0;
+            const ushort edge_last   = DRAW_PIPE_EDGE_FLAG_1;
+            
+            flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle;
+            
+            for (i = 0; i+2 < count; i++, flags = edge_middle) {
+               
+               if (i + 3 == count)
+                  flags |= edge_last;
+               
+               /* PV is third vertex */
+               TRIANGLE( vcache,
+                         flags,
+                         get_elt(elts, i + 1),
+                         get_elt(elts, i + 2),
+                         get_elt(elts, 0));
+            }
+         }
       }
       break;