Mesa (master): r300g: clear and copy a resource with a rectangular point sprite

Marek Olšák mareko at kemper.freedesktop.org
Mon Jul 12 11:10:14 UTC 2010


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

Author: Marek Olšák <maraeo at gmail.com>
Date:   Mon Jul 12 11:41:52 2010 +0200

r300g: clear and copy a resource with a rectangular point sprite

With an ordinary quad, the pixels on the main diagonal are computed
and stored twice, which is somewhat inefficient and might not work well
with specialized clear codepaths.

---

 src/gallium/drivers/r300/r300_context.c |    8 +-
 src/gallium/drivers/r300/r300_render.c  |  147 +++++++++++++++++++++++++++++++
 2 files changed, 152 insertions(+), 3 deletions(-)

diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index b09acb7..cce76cb 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -373,14 +373,16 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
     r300_init_blit_functions(r300);
     r300_init_flush_functions(r300);
     r300_init_query_functions(r300);
-    r300_init_render_functions(r300);
     r300_init_state_functions(r300);
     r300_init_resource_functions(r300);
 
-    rws->set_flush_cb(r300->rws, r300_flush_cb, r300);
-
     r300->blitter = util_blitter_create(&r300->context);
 
+    /* Render functions must be initialized after blitter. */
+    r300_init_render_functions(r300);
+
+    rws->set_flush_cb(r300->rws, r300_flush_cb, r300);
+
     r300->upload_ib = u_upload_create(&r300->context,
 				      32 * 1024, 16,
 				      PIPE_BIND_INDEX_BUFFER);
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index 55c7758..adb02b4 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -1019,6 +1019,152 @@ struct draw_stage* r300_draw_stage(struct r300_context* r300)
  *                         End of SW TCL functions                          *
  ***************************************************************************/
 
+/* If we used a quad to draw a rectangle, the pixels on the main diagonal
+ * would be computed and stored twice, which makes the clear/copy codepaths
+ * somewhat inefficient. Instead we use a rectangular point sprite with TCL
+ * turned off. */
+static void r300_blitter_draw_rectangle(struct blitter_context *blitter,
+                                        unsigned x1, unsigned y1,
+                                        unsigned x2, unsigned y2,
+                                        float depth,
+                                        enum blitter_attrib_type type,
+                                        const float attrib[4])
+{
+    struct r300_context *r300 = r300_context(util_blitter_get_pipe(blitter));
+    unsigned width = x2 - x1;
+    unsigned height = y2 - y1;
+    unsigned i, dwords;
+    unsigned vertex_size = type == UTIL_BLITTER_ATTRIB_COLOR ? 7 : 3;
+    unsigned last_sprite_coord_enable = r300->sprite_coord_enable;
+    uint32_t vap_cntl_status;
+    CB_LOCALS;
+
+    /* Compute the number of dwords. */
+    dwords = r300->draw ? 0 : 4;
+    switch (type) {
+        case UTIL_BLITTER_ATTRIB_COLOR:
+            dwords += 29;
+            break;
+
+        case UTIL_BLITTER_ATTRIB_TEXCOORD:
+            dwords += 32;
+            break;
+
+        case UTIL_BLITTER_ATTRIB_NONE:
+            dwords += 25;
+            break;
+    }
+
+    /* Initialize the VAP control. */
+    vap_cntl_status = R300_VAP_TCL_BYPASS;
+#ifdef PIPE_ARCH_LITTLE_ENDIAN
+    vap_cntl_status |= R300_VC_NO_SWAP;
+#else
+    vap_cntl_status |= R300_VC_32BIT_SWAP);
+#endif
+
+    if (type == UTIL_BLITTER_ATTRIB_TEXCOORD)
+        r300->sprite_coord_enable = 1;
+
+    r300_update_derived_state(r300);
+
+    /* Mark some states we don't care about as non-dirty. */
+    r300->viewport_state.dirty = FALSE;
+    r300->clip_state.dirty = FALSE;
+    r300->vertex_stream_state.dirty = FALSE;
+    r300->vs_state.dirty = FALSE;
+    r300->vs_constants.dirty = FALSE;
+
+    r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0, NULL);
+
+    BEGIN_CS_AS_CB(r300, dwords);
+    /* Set up GA. */
+    OUT_CB_REG(R300_GA_POINT_SIZE, (height * 6) | ((width * 6) << 16));
+
+    switch (type) {
+        case UTIL_BLITTER_ATTRIB_COLOR:
+            /* Set up the VAP output. */
+            OUT_CB_REG(R300_VAP_VSM_VTX_ASSM,
+                       R300_INPUT_CNTL_POS | R300_INPUT_CNTL_COLOR);
+            OUT_CB_REG_SEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2);
+            OUT_CB(R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT |
+                   R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT);
+            OUT_CB(0);
+            /* Set up PSC. */
+            OUT_CB_REG(R300_VAP_PROG_STREAM_CNTL_0,
+                       R300_DATA_TYPE_FLOAT_3 |
+                       ((R300_DATA_TYPE_FLOAT_4 | (2 << R300_DST_VEC_LOC_SHIFT) |
+                         R300_LAST_VEC) << 16));
+            OUT_CB_REG(R300_VAP_PROG_STREAM_CNTL_EXT_0,
+                       R300_VAP_SWIZZLE_XYZ1 | (R300_VAP_SWIZZLE_XYZW << 16));
+            break;
+
+        case UTIL_BLITTER_ATTRIB_TEXCOORD:
+            /* Set up the GA to generate texcoords. */
+            OUT_CB_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE |
+                       (R300_GB_TEX_STR << R300_GB_TEX0_SOURCE_SHIFT));
+            OUT_CB_REG_SEQ(R300_GA_POINT_S0, 4);
+            OUT_CB_32F(attrib[0]);
+            OUT_CB_32F(attrib[3]);
+            OUT_CB_32F(attrib[2]);
+            OUT_CB_32F(attrib[1]);
+            /* Pass-through. */
+
+        case UTIL_BLITTER_ATTRIB_NONE:
+            /* Set up the VAP output. */
+            OUT_CB_REG(R300_VAP_VSM_VTX_ASSM, R300_INPUT_CNTL_POS);
+            OUT_CB_REG_SEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2);
+            OUT_CB(R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT);
+            OUT_CB(0);
+            /* Set up PSC. */
+            OUT_CB_REG(R300_VAP_PROG_STREAM_CNTL_0,
+                       R300_DATA_TYPE_FLOAT_3 | R300_LAST_VEC);
+            OUT_CB_REG(R300_VAP_PROG_STREAM_CNTL_EXT_0, R300_VAP_SWIZZLE_XYZ1);
+            break;
+    }
+
+    /* Set up VAP controls. */
+    if (!r300->draw)
+        OUT_CB_REG(R300_VAP_CNTL_STATUS, vap_cntl_status);
+    OUT_CB_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE);
+    OUT_CB_REG(R300_VAP_VTE_CNTL, R300_VTX_XY_FMT | R300_VTX_Z_FMT);
+    OUT_CB_REG(R300_VAP_VTX_SIZE, vertex_size);
+    OUT_CB_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
+    OUT_CB(1);
+    OUT_CB(0);
+
+    /* Draw. */
+    OUT_CB_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, vertex_size);
+    OUT_CB(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (1 << 16) |
+           R300_VAP_VF_CNTL__PRIM_POINTS);
+
+    OUT_CB_32F(x1 + width * 0.5f);
+    OUT_CB_32F(y1 + height * 0.5f);
+    OUT_CB_32F(depth);
+
+    if (type == UTIL_BLITTER_ATTRIB_COLOR)
+        for (i = 0; i < 4; i++)
+            OUT_CB_32F(attrib[i]);
+
+    /* If we do not re-enable VAP immediately after the draw packet,
+     * it goes crazy. Sometimes I wish this hardware didn't do random shit. */
+    if (!r300->draw)
+        OUT_CB_REG(R300_VAP_CNTL_STATUS,
+                   vap_cntl_status & ~R300_VAP_TCL_BYPASS);
+    END_CB;
+
+    /* Restore the state. */
+    r300->clip_state.dirty = TRUE;
+    r300->rs_block_state.dirty = TRUE;
+    r300->rs_state.dirty = TRUE;
+    r300->vertex_stream_state.dirty = TRUE;
+    r300->viewport_state.dirty = TRUE;
+    r300->vs_state.dirty = TRUE;
+    r300->vs_constants.dirty = TRUE;
+
+    r300->sprite_coord_enable = last_sprite_coord_enable;
+}
+
 static void r300_resource_resolve(struct pipe_context* pipe,
                                   struct pipe_resource* dest,
                                   struct pipe_subresource subdest,
@@ -1072,6 +1218,7 @@ void r300_init_render_functions(struct r300_context *r300)
     }
 
     r300->context.resource_resolve = r300_resource_resolve;
+    r300->blitter->draw_rectangle = r300_blitter_draw_rectangle;
 
     /* Plug in the two-sided stencil reference value fallback if needed. */
     if (!r300->screen->caps.is_r500)




More information about the mesa-commit mailing list