llvmpipe: Fix MSVC build.
[mesa.git] / src / gallium / drivers / llvmpipe / lp_setup_tri.c
index eeffbb5fee0dcc61f8b56013202149ec12f6c080..dfe1bd11ea0c2e06a5542da6a138b5e9272a0348 100644 (file)
@@ -228,7 +228,6 @@ do_triangle_ccw(struct lp_setup_context *setup,
    struct lp_rast_triangle *tri;
    int x[3];
    int y[3];
-   int area;
    struct u_rect bbox;
    unsigned tri_bytes;
    int i;
@@ -312,21 +311,8 @@ do_triangle_ccw(struct lp_setup_context *setup,
    tri->plane[1].dcdx = y[1] - y[2];
    tri->plane[2].dcdx = y[2] - y[0];
 
-   area = (tri->plane[0].dcdy * tri->plane[2].dcdx -
-           tri->plane[2].dcdy * tri->plane[0].dcdx);
-
    LP_COUNT(nr_tris);
 
-   /* Cull non-ccw and zero-sized triangles. 
-    *
-    * XXX: subject to overflow??
-    */
-   if (area <= 0) {
-      lp_scene_putback_data( scene, tri_bytes );
-      LP_COUNT(nr_culled_tris);
-      return TRUE;
-   }
-
    /* Setup parameter interpolants:
     */
    lp_setup_tri_coef( setup, &tri->inputs, v0, v1, v2, frontfacing );
@@ -357,26 +343,34 @@ do_triangle_ccw(struct lp_setup_context *setup,
        * Also, sometimes (in FBO cases) GL will render upside down
        * to its usual method, in which case it will probably want
        * to use the opposite, top-left convention.
+       *
+       * XXX: Chances are this will get stripped away.  In fact this
+       * is only meaningful if:
+       *
+       *          (plane->c & (FIXED_ONE-1)) == 0
+       *
        */         
-      if (plane->dcdx < 0) {
-         /* both fill conventions want this - adjust for left edges */
-         plane->c++;            
-      }
-      else if (plane->dcdx == 0) {
-         if (setup->pixel_offset == 0) {
-            /* correct for top-left fill convention:
-             */
-            if (plane->dcdy > 0) plane->c++;
+      if ((plane->c & (FIXED_ONE-1)) == 0) {
+         if (plane->dcdx < 0) {
+            /* both fill conventions want this - adjust for left edges */
+            plane->c++;            
          }
-         else {
-            /* correct for bottom-left fill convention:
-             */
-            if (plane->dcdy < 0) plane->c++;
+         else if (plane->dcdx == 0) {
+            if (setup->pixel_offset == 0) {
+               /* correct for top-left fill convention:
+                */
+               if (plane->dcdy > 0) plane->c++;
+            }
+            else {
+               /* correct for bottom-left fill convention:
+                */
+               if (plane->dcdy < 0) plane->c++;
+            }
          }
       }
 
-      plane->dcdx *= FIXED_ONE;
-      plane->dcdy *= FIXED_ONE;
+      plane->c = (plane->c + (FIXED_ONE-1)) / FIXED_ONE;
+
 
       /* find trivial reject offsets for each edge for a single-pixel
        * sized block.  These will be scaled up at each recursive level to
@@ -487,43 +481,47 @@ lp_setup_bin_triangle( struct lp_setup_context *setup,
    int sz = floor_pot((bbox->x1 - (bbox->x0 & ~3)) |
                      (bbox->y1 - (bbox->y0 & ~3)));
 
-   if (nr_planes == 3) {
-      if (sz < 4 && dx < 64)
-      {
-        /* Triangle is contained in a single 4x4 stamp:
-         */
-        int mask = (bbox->x0 & 63 & ~3) | ((bbox->y0 & 63 & ~3) << 8);
-
-        return lp_scene_bin_command( scene,
-                                     bbox->x0/64, bbox->y0/64,
-                                     LP_RAST_OP_TRIANGLE_3_4,
-                                     lp_rast_arg_triangle(tri, mask) );
-      }
-
-      if (sz < 16 && dx < 64)
-      {
-        int mask = (bbox->x0 & 63 & ~3) | ((bbox->y0 & 63 & ~3) << 8);
-
-        /* Triangle is contained in a single 16x16 block:
-         */
-        return lp_scene_bin_command( scene,
-                                     bbox->x0/64, bbox->y0/64,
-                                      LP_RAST_OP_TRIANGLE_3_16,
-                                      lp_rast_arg_triangle(tri, mask) );
-      }
-   }
-
-
    /* Determine which tile(s) intersect the triangle's bounding box
     */
    if (dx < TILE_SIZE)
    {
       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);
 
       assert(iy0 == bbox->y1 / TILE_SIZE &&
             ix0 == bbox->x1 / TILE_SIZE);
 
+      if (nr_planes == 3) {
+         if (sz < 4)
+         {
+            /* Triangle is contained in a single 4x4 stamp:
+             */
+
+            return lp_scene_bin_command( scene, ix0, iy0,
+                                         LP_RAST_OP_TRIANGLE_3_4,
+                                         lp_rast_arg_triangle(tri, mask) );
+         }
+
+         if (sz < 16)
+         {
+            /* Triangle is contained in a single 16x16 block:
+             */
+            return lp_scene_bin_command( scene, ix0, iy0,
+                                         LP_RAST_OP_TRIANGLE_3_16,
+                                         lp_rast_arg_triangle(tri, mask) );
+         }
+      }
+      else if (nr_planes == 4 && sz < 16) 
+      {
+         return lp_scene_bin_command( scene, ix0, iy0,
+                                      LP_RAST_OP_TRIANGLE_4_16,
+                                      lp_rast_arg_triangle(tri, mask) );
+      }
+
+
       /* Triangle is contained in a single tile:
        */
       return lp_scene_bin_command( scene, ix0, iy0,
@@ -635,23 +633,36 @@ fail:
 
 
 /**
- * Draw triangle if it's CW, cull otherwise.
+ * Try to draw the triangle, restart the scene on failure.
  */
-static void triangle_cw( struct lp_setup_context *setup,
-                        const float (*v0)[4],
-                        const float (*v1)[4],
-                        const float (*v2)[4] )
+static void retry_triangle_ccw( struct lp_setup_context *setup,
+                                const float (*v0)[4],
+                                const float (*v1)[4],
+                                const float (*v2)[4],
+                                boolean front)
 {
-   if (!do_triangle_ccw( setup, v1, v0, v2, !setup->ccw_is_frontface ))
+   if (!do_triangle_ccw( setup, v0, v1, v2, front ))
    {
       if (!lp_setup_flush_and_restart(setup))
          return;
 
-      if (!do_triangle_ccw( setup, v1, v0, v2, !setup->ccw_is_frontface ))
+      if (!do_triangle_ccw( setup, v0, v1, v2, front ))
          return;
    }
 }
 
+static INLINE float
+calc_area(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;
+}
+
 
 /**
  * Draw triangle if it's CW, cull otherwise.
@@ -661,17 +672,23 @@ static void triangle_cw( struct lp_setup_context *setup,
                         const float (*v1)[4],
                         const float (*v2)[4] )
 {
-   if (!do_triangle_ccw( setup, v0, v1, v2, setup->ccw_is_frontface ))
-   {
-      if (!lp_setup_flush_and_restart(setup))
-         return;
+   float area = calc_area(v0, v1, v2);
 
-      if (!do_triangle_ccw( setup, v0, v1, v2, setup->ccw_is_frontface ))
-         return;
-   }
+   if (area < 0.0f) 
+      retry_triangle_ccw(setup, v0, v2, v1, !setup->ccw_is_frontface);
 }
 
 
+static void triangle_ccw( struct lp_setup_context *setup,
+                          const float (*v0)[4],
+                          const float (*v1)[4],
+                          const float (*v2)[4])
+{
+   float area = calc_area(v0, v1, v2);
+
+   if (area > 0.0f) 
+      retry_triangle_ccw(setup, v0, v1, v2, setup->ccw_is_frontface);
+}
 
 /**
  * Draw triangle whether it's CW or CCW.
@@ -681,18 +698,12 @@ static void triangle_both( struct lp_setup_context *setup,
                           const float (*v1)[4],
                           const float (*v2)[4] )
 {
-   /* edge vectors e = v0 - v2, f = v1 - v2 */
-   const float ex = v0[0][0] - v2[0][0];
-   const float ey = v0[0][1] - v2[0][1];
-   const float fx = v1[0][0] - v2[0][0];
-   const float fy = v1[0][1] - v2[0][1];
-
-   /* det = cross(e,f).z */
-   const float det = ex * fy - ey * fx;
-   if (det < 0.0f) 
-      triangle_ccw( setup, v0, v1, v2 );
-   else if (det > 0.0f)
-      triangle_cw( setup, v0, v1, v2 );
+   float area = calc_area(v0, v1, v2);
+
+   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 );
 }