diff options
Diffstat (limited to 'src/gallium/drivers/r300/r300_render.c')
-rw-r--r-- | src/gallium/drivers/r300/r300_render.c | 147 |
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) |