diff options
author | Marek Olšák <maraeo@gmail.com> | 2010-07-12 11:41:52 +0200 |
---|---|---|
committer | Marek Olšák <maraeo@gmail.com> | 2010-07-12 13:06:45 +0200 |
commit | 78e8a8765f435bf0902d62afbcb3b8d68a0b716f (patch) | |
tree | 04a755dec7cc647292f52687856cd451a4160beb /src/gallium | |
parent | 0864851e2763291ff1ea2ceaa3c6f16b14abd362 (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')
-rw-r--r-- | src/gallium/drivers/r300/r300_context.c | 8 | ||||
-rw-r--r-- | 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 b09acb7f2b..cce76cb1df 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 55c7758b75..adb02b4e63 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) |