Mesa (master): r300g: add generating texture coordinates for point sprites

Dave Airlie airlied at kemper.freedesktop.org
Mon Apr 12 23:20:11 UTC 2010


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

Author: Marek Olšák <maraeo at gmail.com>
Date:   Thu Dec 24 21:29:41 2009 +0100

r300g: add generating texture coordinates for point sprites

[airlied -
	Convert sprite coord index to a per-coord enable bit
	set the rasteriser block up correctly for point sprites.

The inputs to the RS hw block change for sprite coords, so fix them up
properly - this fixes piglit point-sprite test.
]

Signed-off-by: Dave Airlie <airlied at redhat.com>

---

 src/gallium/drivers/r300/r300_context.h         |   13 +++++++
 src/gallium/drivers/r300/r300_emit.c            |    6 +++
 src/gallium/drivers/r300/r300_state.c           |   34 +++++++++++++++++++-
 src/gallium/drivers/r300/r300_state_derived.c   |   40 +++++++++++++++++-----
 src/gallium/drivers/r300/r300_state_invariant.c |   13 +------
 5 files changed, 85 insertions(+), 21 deletions(-)

diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index d8bed53..6ab10c8 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -106,6 +106,16 @@ struct r300_rs_state {
     uint32_t color_control;         /* R300_GA_COLOR_CONTROL: 0x4278 */
     uint32_t polygon_mode;          /* R300_GA_POLY_MODE: 0x4288 */
     uint32_t clip_rule;             /* R300_SC_CLIP_RULE: 0x43D0 */
+
+    /* Specifies top of Raster pipe specific enable controls,
+     * i.e. texture coordinates stuffing for points, lines, triangles */
+    uint32_t stuffing_enable;       /* R300_GB_ENABLE: 0x4008 */
+
+    /* Point sprites texture coordinates, 0: lower left, 1: upper right */
+    float point_texcoord_left;      /* R300_GA_POINT_S0: 0x4200 */
+    float point_texcoord_bottom;    /* R300_GA_POINT_T0: 0x4204 */
+    float point_texcoord_right;     /* R300_GA_POINT_S1: 0x4208 */
+    float point_texcoord_top;       /* R300_GA_POINT_T1: 0x420c */
 };
 
 struct r300_rs_block {
@@ -420,6 +430,9 @@ struct r300_context {
     /* Whether the two-sided stencil ref value is different for front and
      * back faces, and fallback should be used for r3xx-r4xx. */
     boolean stencil_ref_bf_fallback;
+    /* Point sprites texcoord index,  1 bit per texcoord */
+    int sprite_coord_enable;
+
     /* upload managers */
     struct u_upload_mgr *upload_vb;
     struct u_upload_mgr *upload_ib;
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index 637b0ad..dd02eae 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -748,6 +748,12 @@ void r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state)
     OUT_CS_REG(R300_GA_LINE_STIPPLE_VALUE, rs->line_stipple_value);
     OUT_CS_REG(R300_GA_POLY_MODE, rs->polygon_mode);
     OUT_CS_REG(R300_SC_CLIP_RULE, rs->clip_rule);
+    OUT_CS_REG(R300_GB_ENABLE, rs->stuffing_enable);
+    OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4);
+    OUT_CS_32F(rs->point_texcoord_left);
+    OUT_CS_32F(rs->point_texcoord_bottom);
+    OUT_CS_32F(rs->point_texcoord_right);
+    OUT_CS_32F(rs->point_texcoord_top);
     END_CS;
 }
 
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index f1a0623..f5ece39 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -757,6 +757,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
                                   const struct pipe_rasterizer_state* state)
 {
     struct r300_rs_state* rs = CALLOC_STRUCT(r300_rs_state);
+    int i;
 
     /* Copy rasterizer state for Draw. */
     rs->rs = *state;
@@ -851,6 +852,30 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
 
     rs->clip_rule = state->scissor ? 0xAAAA : 0xFFFF;
 
+    /* Point sprites */
+    if (state->sprite_coord_enable) {
+        rs->stuffing_enable = R300_GB_POINT_STUFF_ENABLE;
+	for (i = 0; i < 8; i++) {
+	    if (state->sprite_coord_enable & (1 << i))
+		rs->stuffing_enable |=
+		    R300_GB_TEX_STR << (R300_GB_TEX0_SOURCE_SHIFT + (i*2));
+	}
+
+        rs->point_texcoord_left = 0.0f;
+        rs->point_texcoord_right = 1.0f;
+
+        switch (state->sprite_coord_mode) {
+            case PIPE_SPRITE_COORD_UPPER_LEFT:
+                rs->point_texcoord_top = 0.0f;
+                rs->point_texcoord_bottom = 1.0f;
+                break;
+            case PIPE_SPRITE_COORD_LOWER_LEFT:
+                rs->point_texcoord_top = 1.0f;
+                rs->point_texcoord_bottom = 0.0f;
+                break;
+        }
+    }
+
     return (void*)rs;
 }
 
@@ -859,6 +884,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
 {
     struct r300_context* r300 = r300_context(pipe);
     struct r300_rs_state* rs = (struct r300_rs_state*)state;
+    int last_sprite_coord_enable = r300->sprite_coord_enable;
 
     if (r300->draw) {
         draw_flush(r300->draw);
@@ -867,12 +893,18 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
 
     if (rs) {
         r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw;
+        r300->sprite_coord_enable = rs->rs.sprite_coord_enable;
     } else {
         r300->polygon_offset_enabled = FALSE;
+        r300->sprite_coord_enable = 0;
     }
 
     UPDATE_STATE(state, r300->rs_state);
-    r300->rs_state.size = 19 + (r300->polygon_offset_enabled ? 5 : 0);
+    r300->rs_state.size = 26 + (r300->polygon_offset_enabled ? 5 : 0);
+
+    if (last_sprite_coord_enable != r300->sprite_coord_enable) {
+        r300->rs_block_state.dirty = TRUE;
+    }
 }
 
 /* Free rasterizer state. */
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c
index 86c5277..ddf7285 100644
--- a/src/gallium/drivers/r300/r300_state_derived.c
+++ b/src/gallium/drivers/r300/r300_state_derived.c
@@ -37,6 +37,12 @@
 /* r300_state_derived: Various bits of state which are dependent upon
  * currently bound CSO data. */
 
+enum r300_rs_swizzle {
+    SWIZ_XYZW = 0,
+    SWIZ_X001,
+    SWIZ_XY01,
+};
+
 static void r300_draw_emit_attrib(struct r300_context* r300,
                                   enum attrib_emit emit,
                                   enum interp_mode interp,
@@ -180,14 +186,20 @@ static void r300_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset)
 }
 
 static void r300_rs_tex(struct r300_rs_block* rs, int id, int ptr,
-                        boolean swizzle_X001)
+                        enum r300_rs_swizzle swiz)
 {
-    if (swizzle_X001) {
+    if (swiz == SWIZ_X001) {
         rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) |
                       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) |
+                      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) |
                       R300_RS_SEL_S(R300_RS_SEL_C0) |
@@ -223,15 +235,20 @@ 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,
-                        boolean swizzle_X001)
+			enum r300_rs_swizzle swiz)
 {
     int rs_tex_comp = ptr*4;
 
-    if (swizzle_X001) {
+    if (swiz == SWIZ_X001) {
         rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) |
                       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) |
+                      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) |
@@ -260,7 +277,7 @@ static void r300_update_rs_block(struct r300_context* r300,
     int i, col_count = 0, tex_count = 0, fp_offset = 0, count;
     void (*rX00_rs_col)(struct r300_rs_block*, int, int, boolean);
     void (*rX00_rs_col_write)(struct r300_rs_block*, int, int);
-    void (*rX00_rs_tex)(struct r300_rs_block*, int, int, boolean);
+    void (*rX00_rs_tex)(struct r300_rs_block*, int, int, enum r300_rs_swizzle);
     void (*rX00_rs_tex_write)(struct r300_rs_block*, int, int);
     boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED ||
                               vs_outputs->bcolor[1] != ATTR_UNUSED;
@@ -302,14 +319,19 @@ static void r300_update_rs_block(struct r300_context* r300,
 
     /* Rasterize texture coordinates. */
     for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
-        if (vs_outputs->generic[i] != ATTR_UNUSED) {
+	bool sprite_coord = !!(r300->sprite_coord_enable & (1 << i));
+
+        if (vs_outputs->generic[i] != ATTR_UNUSED || sprite_coord) {
             /* Always rasterize if it's written by the VS,
              * otherwise it locks up. */
-            rX00_rs_tex(&rs, tex_count, tex_count, FALSE);
+            rX00_rs_tex(&rs, tex_count, tex_count,
+			sprite_coord ? SWIZ_XY01 : SWIZ_XYZW);
 
             /* Write it to the FS input register if it's used by the FS. */
             if (fs_inputs->generic[i] != ATTR_UNUSED) {
                 rX00_rs_tex_write(&rs, tex_count, fp_offset);
+                if (sprite_coord)
+                    debug_printf("r300: SpriteCoord (generic index %i) is being written to reg %i\n", i, fp_offset);
                 fp_offset++;
             }
             tex_count++;
@@ -326,7 +348,7 @@ static void r300_update_rs_block(struct r300_context* r300,
     if (vs_outputs->fog != ATTR_UNUSED) {
         /* Always rasterize if it's written by the VS,
          * otherwise it locks up. */
-        rX00_rs_tex(&rs, tex_count, tex_count, TRUE);
+        rX00_rs_tex(&rs, tex_count, tex_count, SWIZ_X001);
 
         /* Write it to the FS input register if it's used by the FS. */
         if (fs_inputs->fog != ATTR_UNUSED) {
@@ -345,7 +367,7 @@ static void r300_update_rs_block(struct r300_context* r300,
     /* Rasterize WPOS. */
     /* If the FS doesn't need it, it's not written by the VS. */
     if (vs_outputs->wpos != ATTR_UNUSED && fs_inputs->wpos != ATTR_UNUSED) {
-        rX00_rs_tex(&rs, tex_count, tex_count, FALSE);
+        rX00_rs_tex(&rs, tex_count, tex_count, SWIZ_XYZW);
         rX00_rs_tex_write(&rs, tex_count, fp_offset);
 
         fp_offset++;
diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c
index a8cd2f5..ffb175f 100644
--- a/src/gallium/drivers/r300/r300_state_invariant.c
+++ b/src/gallium/drivers/r300/r300_state_invariant.c
@@ -44,13 +44,9 @@ void r300_emit_invariant_state(struct r300_context* r300,
     struct r300_capabilities* caps = &r300_screen(r300->context.screen)->caps;
     CS_LOCALS(r300);
 
-    BEGIN_CS(14 + (caps->has_tcl ? 2: 0));
+    BEGIN_CS(12 + (caps->has_tcl ? 2: 0));
 
     /*** Graphics Backend (GB) ***/
-    /* Various GB enables */
-    OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE |
-                               R300_GB_LINE_STUFF_ENABLE  |
-                               R300_GB_TRIANGLE_STUFF_ENABLE);
     /* Subpixel multisampling for AA
      * These are commented out because glisse's CS checker doesn't like them.
      * I presume these will be re-enabled later.
@@ -78,7 +74,7 @@ void r300_emit_invariant_state(struct r300_context* r300,
     END_CS;
 
     /* XXX unsorted stuff from surface_fill */
-    BEGIN_CS(42 + (caps->has_tcl ? 7 : 0) +
+    BEGIN_CS(38 + (caps->has_tcl ? 7 : 0) +
              (caps->family >= CHIP_FAMILY_RV350 ? 4 : 0));
 
     if (caps->has_tcl) {
@@ -90,11 +86,6 @@ void r300_emit_invariant_state(struct r300_context* r300,
         OUT_CS_32F(1.0);
         OUT_CS_32F(1.0);
     }
-    /* XXX point tex stuffing */
-    OUT_CS_REG_SEQ(R300_GA_POINT_S0, 1);
-    OUT_CS_32F(0.0);
-    OUT_CS_REG_SEQ(R300_GA_POINT_S1, 1);
-    OUT_CS_32F(1.0);
     /* XXX line tex stuffing */
     OUT_CS_REG_SEQ(R300_GA_LINE_S0, 1);
     OUT_CS_32F(0.0);




More information about the mesa-commit mailing list