summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/r300/r300_render.c
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2010-07-12 11:41:52 +0200
committerMarek Olšák <[email protected]>2010-07-12 13:06:45 +0200
commit78e8a8765f435bf0902d62afbcb3b8d68a0b716f (patch)
tree04a755dec7cc647292f52687856cd451a4160beb /src/gallium/drivers/r300/r300_render.c
parent0864851e2763291ff1ea2ceaa3c6f16b14abd362 (diff)
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.
Diffstat (limited to 'src/gallium/drivers/r300/r300_render.c')
-rw-r--r--src/gallium/drivers/r300/r300_render.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index 55c7758b751..adb02b4e639 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)