Mesa (master): r300g: fix hardlock when using more than one stuffed sprite coords

Marek Olšák mareko at kemper.freedesktop.org
Mon Aug 2 08:26:52 PDT 2010


Module: Mesa
Branch: master
Commit: afa925066c158ac49e3b0f883f67debd8545bf26
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=afa925066c158ac49e3b0f883f67debd8545bf26

Author: Marek Olšák <maraeo at gmail.com>
Date:   Mon Aug  2 17:14:07 2010 +0200

r300g: fix hardlock when using more than one stuffed sprite coords

If texture coordinates come from the vertex shader, there are always
4 components in the rasterizer input packet, but if the coordinates
are stuffed (like for point sprites), there are only 2 or 3 components
(based on GB_ENABLE) and if we rasterize more, it locks up.

---

 src/gallium/drivers/r300/r300_state.c         |    2 +-
 src/gallium/drivers/r300/r300_state_derived.c |   38 +++++++++++++------------
 2 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index fced77e..bc0c86d 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -1014,7 +1014,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
 	for (i = 0; i < 8; i++) {
 	    if (state->sprite_coord_enable & (1 << i))
                 stuffing_enable |=
-		    R300_GB_TEX_STR << (R300_GB_TEX0_SOURCE_SHIFT + (i*2));
+                    R300_GB_TEX_ST << (R300_GB_TEX0_SOURCE_SHIFT + (i*2));
 	}
 
         point_texcoord_left = 0.0f;
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c
index a85db27..66f64f0 100644
--- a/src/gallium/drivers/r300/r300_state_derived.c
+++ b/src/gallium/drivers/r300/r300_state_derived.c
@@ -213,19 +213,19 @@ static void r300_rs_tex(struct r300_rs_block* rs, int id, int ptr,
                         enum r300_rs_swizzle swiz)
 {
     if (swiz == SWIZ_X001) {
-        rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) |
+        rs->ip[id] |= R300_RS_TEX_PTR(ptr) |
                       R300_RS_SEL_S(R300_RS_SEL_C0) |
                       R300_RS_SEL_T(R300_RS_SEL_K0) |
                       R300_RS_SEL_R(R300_RS_SEL_K0) |
                       R300_RS_SEL_Q(R300_RS_SEL_K1);
     } else if (swiz == SWIZ_XY01) {
-        rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) |
+        rs->ip[id] |= R300_RS_TEX_PTR(ptr) |
                       R300_RS_SEL_S(R300_RS_SEL_C0) |
                       R300_RS_SEL_T(R300_RS_SEL_C1) |
                       R300_RS_SEL_R(R300_RS_SEL_K0) |
                       R300_RS_SEL_Q(R300_RS_SEL_K1);
     } else {
-        rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) |
+        rs->ip[id] |= R300_RS_TEX_PTR(ptr) |
                       R300_RS_SEL_S(R300_RS_SEL_C0) |
                       R300_RS_SEL_T(R300_RS_SEL_C1) |
                       R300_RS_SEL_R(R300_RS_SEL_C2) |
@@ -261,23 +261,21 @@ static void r500_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset)
 static void r500_rs_tex(struct r300_rs_block* rs, int id, int ptr,
 			enum r300_rs_swizzle swiz)
 {
-    int rs_tex_comp = ptr*4;
-
     if (swiz == SWIZ_X001) {
-        rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) |
+        rs->ip[id] |= R500_RS_SEL_S(ptr) |
                       R500_RS_SEL_T(R500_RS_IP_PTR_K0) |
                       R500_RS_SEL_R(R500_RS_IP_PTR_K0) |
                       R500_RS_SEL_Q(R500_RS_IP_PTR_K1);
     } else if (swiz == SWIZ_XY01) {
-        rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) |
-                      R500_RS_SEL_T(rs_tex_comp + 1) |
+        rs->ip[id] |= R500_RS_SEL_S(ptr) |
+                      R500_RS_SEL_T(ptr + 1) |
                       R500_RS_SEL_R(R500_RS_IP_PTR_K0) |
                       R500_RS_SEL_Q(R500_RS_IP_PTR_K1);
     } else {
-        rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) |
-                      R500_RS_SEL_T(rs_tex_comp + 1) |
-                      R500_RS_SEL_R(rs_tex_comp + 2) |
-                      R500_RS_SEL_Q(rs_tex_comp + 3);
+        rs->ip[id] |= R500_RS_SEL_S(ptr) |
+                      R500_RS_SEL_T(ptr + 1) |
+                      R500_RS_SEL_R(ptr + 2) |
+                      R500_RS_SEL_Q(ptr + 3);
     }
     rs->inst[id] |= R500_RS_INST_TEX_ID(id);
 }
@@ -305,7 +303,7 @@ static void r300_update_rs_block(struct r300_context *r300)
     struct r300_shader_semantics *vs_outputs = &vs->outputs;
     struct r300_shader_semantics *fs_inputs = &r300_fs(r300)->shader->inputs;
     struct r300_rs_block rs = {0};
-    int i, col_count = 0, tex_count = 0, fp_offset = 0, count, loc = 0;
+    int i, col_count = 0, tex_count = 0, fp_offset = 0, count, loc = 0, tex_ptr = 0;
     void (*rX00_rs_col)(struct r300_rs_block*, int, int, enum r300_rs_swizzle);
     void (*rX00_rs_col_write)(struct r300_rs_block*, int, int);
     void (*rX00_rs_tex)(struct r300_rs_block*, int, int, enum r300_rs_swizzle);
@@ -393,8 +391,9 @@ static void r300_update_rs_block(struct r300_context *r300)
                 stream_loc_notcl[loc++] = 6 + tex_count;
 
                 /* Rasterize it. */
-                rX00_rs_tex(&rs, tex_count, tex_count, SWIZ_XYZW);
+                rX00_rs_tex(&rs, tex_count, tex_ptr, SWIZ_XYZW);
                 tex_count++;
+                tex_ptr += 4;
             }
         }
     }
@@ -412,7 +411,7 @@ static void r300_update_rs_block(struct r300_context *r300)
             }
 
             /* Rasterize it. */
-            rX00_rs_tex(&rs, tex_count, tex_count,
+            rX00_rs_tex(&rs, tex_count, tex_ptr,
 			sprite_coord ? SWIZ_XY01 : SWIZ_XYZW);
 
             /* Write it to the FS input register if it's needed by the FS. */
@@ -429,6 +428,7 @@ static void r300_update_rs_block(struct r300_context *r300)
                     i, sprite_coord ? " (sprite coord)" : "");
             }
             tex_count++;
+            tex_ptr += sprite_coord ? 2 : 4;
         } else {
             /* Skip the FS input register, leave it uninitialized. */
             /* If we try to set it to (0,0,0,1), it will lock up. */
@@ -449,7 +449,7 @@ static void r300_update_rs_block(struct r300_context *r300)
         stream_loc_notcl[loc++] = 6 + tex_count;
 
         /* Rasterize it. */
-        rX00_rs_tex(&rs, tex_count, tex_count, SWIZ_X001);
+        rX00_rs_tex(&rs, tex_count, tex_ptr, SWIZ_X001);
 
         /* Write it to the FS input register if it's needed by the FS. */
         if (fs_inputs->fog != ATTR_UNUSED) {
@@ -461,6 +461,7 @@ static void r300_update_rs_block(struct r300_context *r300)
             DBG(r300, DBG_RS, "r300: Rasterized fog unused.\n");
         }
         tex_count++;
+        tex_ptr += 4;
     } else {
         /* Skip the FS input register, leave it uninitialized. */
         /* If we try to set it to (0,0,0,1), it will lock up. */
@@ -480,7 +481,7 @@ static void r300_update_rs_block(struct r300_context *r300)
         stream_loc_notcl[loc++] = 6 + tex_count;
 
         /* Rasterize it. */
-        rX00_rs_tex(&rs, tex_count, tex_count, SWIZ_XYZW);
+        rX00_rs_tex(&rs, tex_count, tex_ptr, SWIZ_XYZW);
 
         /* Write it to the FS input register. */
         rX00_rs_tex_write(&rs, tex_count, fp_offset);
@@ -489,6 +490,7 @@ static void r300_update_rs_block(struct r300_context *r300)
 
         fp_offset++;
         tex_count++;
+        tex_ptr += 4;
     }
 
     /* Invalidate the rest of the no-TCL (GA) stream locations. */
@@ -507,7 +509,7 @@ static void r300_update_rs_block(struct r300_context *r300)
     DBG(r300, DBG_RS, "r300: --- Rasterizer status ---: colors: %i, "
         "generics: %i.\n", col_count, tex_count);
 
-    rs.count = (tex_count*4) | (col_count << R300_IC_COUNT_SHIFT) |
+    rs.count = MIN2(tex_ptr, 32) | (col_count << R300_IC_COUNT_SHIFT) |
         R300_HIRES_EN;
 
     count = MAX3(col_count, tex_count, 1);



More information about the mesa-commit mailing list