<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none;"><!-- P {margin-top:0;margin-bottom:0;} --></style>
</head>
<body dir="ltr">
<div id="divtagdefaultwrapper" style="font-size:12pt;color:#000000;font-family:Calibri,Helvetica,sans-serif;" dir="ltr">
<p>LGTM.  Great find.</p>
<p><br>
</p>
<p>Reviewed-by: Jose Fonseca <jfonseca@vmware.com></p>
<br>
<br>
<div style="color: rgb(0, 0, 0);">
<div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="x_divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>From:</b> sroland@vmware.com <sroland@vmware.com><br>
<b>Sent:</b> Friday, June 23, 2017 16:33<br>
<b>To:</b> Jose Fonseca; Brian Paul; mesa-dev@lists.freedesktop.org<br>
<b>Cc:</b> Roland Scheidegger<br>
<b>Subject:</b> [PATCH 2/2] llvmpipe: fix using 32bit rasterization mistakenly, causing overflows</font>
<div> </div>
</div>
</div>
<font size="2"><span style="font-size:10pt;">
<div class="PlainText">From: Roland Scheidegger <sroland@vmware.com><br>
<br>
We use the bounding box (triangle extents) to figure out if 32bit rasterization<br>
could potentially overflow. However, we used the bounding box which already got<br>
rounded up to 0 for negative coords for this, which is incorrect, leading to<br>
overflows and hence bogus rendering in some of our private use.<br>
<br>
It might be possible to simplify this somehow (we're now using 3 different<br>
boxes for binning) but I don't quite see how.<br>
---<br>
 src/gallium/drivers/llvmpipe/lp_setup_context.h | 11 ++++---<br>
 src/gallium/drivers/llvmpipe/lp_setup_line.c    | 20 ++++++------<br>
 src/gallium/drivers/llvmpipe/lp_setup_point.c   |  2 +-<br>
 src/gallium/drivers/llvmpipe/lp_setup_tri.c     | 41 ++++++++++++++++---------<br>
 4 files changed, 43 insertions(+), 31 deletions(-)<br>
<br>
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h<br>
index 9714691..4b55fd9 100644<br>
--- a/src/gallium/drivers/llvmpipe/lp_setup_context.h<br>
+++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h<br>
@@ -215,10 +215,11 @@ lp_setup_alloc_triangle(struct lp_scene *scene,<br>
                         unsigned *tri_size);<br>
 <br>
 boolean<br>
-lp_setup_bin_triangle( struct lp_setup_context *setup,<br>
-                       struct lp_rast_triangle *tri,<br>
-                       const struct u_rect *bbox,<br>
-                       int nr_planes,<br>
-                       unsigned scissor_index );<br>
+lp_setup_bin_triangle(struct lp_setup_context *setup,<br>
+                      struct lp_rast_triangle *tri,<br>
+                      const struct u_rect *bboxorig,<br>
+                      const struct u_rect *bbox,<br>
+                      int nr_planes,<br>
+                      unsigned scissor_index);<br>
 <br>
 #endif<br>
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_line.c b/src/gallium/drivers/llvmpipe/lp_setup_line.c<br>
index 018130c..d0bac5e 100644<br>
--- a/src/gallium/drivers/llvmpipe/lp_setup_line.c<br>
+++ b/src/gallium/drivers/llvmpipe/lp_setup_line.c<br>
@@ -288,7 +288,9 @@ try_setup_line( struct lp_setup_context *setup,<br>
    struct lp_rast_plane *plane;<br>
    struct lp_line_info info;<br>
    float width = MAX2(1.0, setup->line_width);<br>
-   struct u_rect bbox;<br>
+   const struct u_rect *scissor;<br>
+   struct u_rect bbox, bboxpos;<br>
+   boolean s_planes[4];<br>
    unsigned tri_bytes;<br>
    int x[4]; <br>
    int y[4];<br>
@@ -579,10 +581,12 @@ try_setup_line( struct lp_setup_context *setup,<br>
       return TRUE;<br>
    }<br>
 <br>
+   bboxpos = bbox;<br>
+<br>
    /* Can safely discard negative regions:<br>
     */<br>
-   bbox.x0 = MAX2(bbox.x0, 0);<br>
-   bbox.y0 = MAX2(bbox.y0, 0);<br>
+   bboxpos.x0 = MAX2(bboxpos.x0, 0);<br>
+   bboxpos.y0 = MAX2(bboxpos.y0, 0);<br>
 <br>
    nr_planes = 4;<br>
    /*<br>
@@ -591,8 +595,8 @@ try_setup_line( struct lp_setup_context *setup,<br>
     */<br>
    if (setup->scissor_test) {<br>
       /* why not just use draw_regions */<br>
-      boolean s_planes[4];<br>
-      scissor_planes_needed(s_planes, &bbox, &setup->scissors[viewport_index]);<br>
+      scissor = &setup->scissors[viewport_index];<br>
+      scissor_planes_needed(s_planes, &bboxpos, scissor);<br>
       nr_planes += s_planes[0] + s_planes[1] + s_planes[2] + s_planes[3];<br>
    }<br>
 <br>
@@ -718,11 +722,7 @@ try_setup_line( struct lp_setup_context *setup,<br>
     * (easier to evaluate) to ordinary planes.)<br>
     */<br>
    if (nr_planes > 4) {<br>
-      /* why not just use draw_regions */<br>
-      const struct u_rect *scissor = &setup->scissors[viewport_index];<br>
       struct lp_rast_plane *plane_s = &plane[4];<br>
-      boolean s_planes[4];<br>
-      scissor_planes_needed(s_planes, &bbox, scissor);<br>
 <br>
       if (s_planes[0]) {<br>
          plane_s->dcdx = -1 << 8;<br>
@@ -755,7 +755,7 @@ try_setup_line( struct lp_setup_context *setup,<br>
       assert(plane_s == &plane[nr_planes]);<br>
    }<br>
 <br>
-   return lp_setup_bin_triangle(setup, line, &bbox, nr_planes, viewport_index);<br>
+   return lp_setup_bin_triangle(setup, line, &bbox, &bboxpos, nr_planes, viewport_index);<br>
 }<br>
 <br>
 <br>
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_point.c b/src/gallium/drivers/llvmpipe/lp_setup_point.c<br>
index ddb6f0e..8cb6b83 100644<br>
--- a/src/gallium/drivers/llvmpipe/lp_setup_point.c<br>
+++ b/src/gallium/drivers/llvmpipe/lp_setup_point.c<br>
@@ -513,7 +513,7 @@ try_setup_point( struct lp_setup_context *setup,<br>
       plane[3].eo = 0;<br>
    }<br>
 <br>
-   return lp_setup_bin_triangle(setup, point, &bbox, nr_planes, viewport_index);<br>
+   return lp_setup_bin_triangle(setup, point, &bbox, &bbox, nr_planes, viewport_index);<br>
 }<br>
 <br>
 <br>
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c<br>
index 324e938..39755d6 100644<br>
--- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c<br>
+++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c<br>
@@ -273,7 +273,9 @@ do_triangle_ccw(struct lp_setup_context *setup,<br>
    const struct lp_setup_variant_key *key = &setup->setup.variant->key;<br>
    struct lp_rast_triangle *tri;<br>
    struct lp_rast_plane *plane;<br>
-   struct u_rect bbox;<br>
+   const struct u_rect *scissor;<br>
+   struct u_rect bbox, bboxpos;<br>
+   boolean s_planes[4];<br>
    unsigned tri_bytes;<br>
    int nr_planes = 3;<br>
    unsigned viewport_index = 0;<br>
@@ -332,12 +334,14 @@ do_triangle_ccw(struct lp_setup_context *setup,<br>
       return TRUE;<br>
    }<br>
 <br>
+   bboxpos = bbox;<br>
+<br>
    /* Can safely discard negative regions, but need to keep hold of<br>
     * information about when the triangle extends past screen<br>
     * boundaries.  See trimmed_box in lp_setup_bin_triangle().<br>
     */<br>
-   bbox.x0 = MAX2(bbox.x0, 0);<br>
-   bbox.y0 = MAX2(bbox.y0, 0);<br>
+   bboxpos.x0 = MAX2(bboxpos.x0, 0);<br>
+   bboxpos.y0 = MAX2(bboxpos.y0, 0);<br>
 <br>
    nr_planes = 3;<br>
    /*<br>
@@ -346,8 +350,8 @@ do_triangle_ccw(struct lp_setup_context *setup,<br>
     */<br>
    if (setup->scissor_test) {<br>
       /* why not just use draw_regions */<br>
-      boolean s_planes[4];<br>
-      scissor_planes_needed(s_planes, &bbox, &setup->scissors[viewport_index]);<br>
+      scissor = &setup->scissors[viewport_index];<br>
+      scissor_planes_needed(s_planes, &bboxpos, scissor);<br>
       nr_planes += s_planes[0] + s_planes[1] + s_planes[2] + s_planes[3];<br>
    }<br>
 <br>
@@ -680,10 +684,7 @@ do_triangle_ccw(struct lp_setup_context *setup,<br>
     */<br>
    if (nr_planes > 3) {<br>
       /* why not just use draw_regions */<br>
-      const struct u_rect *scissor = &setup->scissors[viewport_index];<br>
       struct lp_rast_plane *plane_s = &plane[3];<br>
-      boolean s_planes[4];<br>
-      scissor_planes_needed(s_planes, &bbox, scissor);<br>
 <br>
       if (s_planes[0]) {<br>
          plane_s->dcdx = -1 << 8;<br>
@@ -716,7 +717,7 @@ do_triangle_ccw(struct lp_setup_context *setup,<br>
       assert(plane_s == &plane[nr_planes]);<br>
    }<br>
 <br>
-   return lp_setup_bin_triangle(setup, tri, &bbox, nr_planes, viewport_index);<br>
+   return lp_setup_bin_triangle(setup, tri, &bbox, &bboxpos, nr_planes, viewport_index);<br>
 }<br>
 <br>
 /*<br>
@@ -747,11 +748,12 @@ floor_pot(uint32_t n)<br>
 <br>
 <br>
 boolean<br>
-lp_setup_bin_triangle( struct lp_setup_context *setup,<br>
-                       struct lp_rast_triangle *tri,<br>
-                       const struct u_rect *bbox,<br>
-                       int nr_planes,<br>
-                       unsigned viewport_index )<br>
+lp_setup_bin_triangle(struct lp_setup_context *setup,<br>
+                      struct lp_rast_triangle *tri,<br>
+                      const struct u_rect *bboxorig,<br>
+                      const struct u_rect *bbox,<br>
+                      int nr_planes,<br>
+                      unsigned viewport_index)<br>
 {<br>
    struct lp_scene *scene = setup->scene;<br>
    struct u_rect trimmed_box = *bbox;   <br>
@@ -767,7 +769,16 @@ lp_setup_bin_triangle( struct lp_setup_context *setup,<br>
    int max_sz = ((bbox->x1 - (bbox->x0 & ~3)) |<br>
                  (bbox->y1 - (bbox->y0 & ~3)));<br>
    int sz = floor_pot(max_sz);<br>
-   boolean use_32bits = max_sz <= MAX_FIXED_LENGTH32;<br>
+<br>
+   /*<br>
+    * NOTE: It is important to use the original bounding box<br>
+    * which might contain negative values here, because if the<br>
+    * plane math may overflow or not with the 32bit rasterization<br>
+    * functions depends on the original extent of the triangle.<br>
+    */<br>
+   int max_szorig = ((bboxorig->x1 - (bboxorig->x0 & ~3)) |<br>
+                     (bboxorig->y1 - (bboxorig->y0 & ~3)));<br>
+   boolean use_32bits = max_szorig <= MAX_FIXED_LENGTH32;<br>
 <br>
    /* Now apply scissor, etc to the bounding box.  Could do this<br>
     * earlier, but it confuses the logic for tri-16 and would force<br>
-- <br>
2.7.4<br>
<br>
</div>
</span></font></div>
</div>
</body>
</html>