r300g: clear and copy a resource with a rectangular point sprite
authorMarek Olšák <maraeo@gmail.com>
Mon, 12 Jul 2010 09:41:52 +0000 (11:41 +0200)
committerMarek Olšák <maraeo@gmail.com>
Mon, 12 Jul 2010 11:06:45 +0000 (13:06 +0200)
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
src/gallium/drivers/r300/r300_render.c

index b09acb7f2b62b33b551c4c62d2e04e8c89276328..cce76cb1dfe5b2475d3e2c702e700846063bfe82 100644 (file)
@@ -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);
index 55c7758b7519b08a7ebc4e89b421c645ca27e857..adb02b4e639c2e14caaebacac15ce0ee5fd9660d 100644 (file)
@@ -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)