diff options
-rw-r--r-- | src/gallium/auxiliary/util/u_blitter.c | 87 | ||||
-rw-r--r-- | src/gallium/auxiliary/util/u_blitter.h | 18 |
2 files changed, 97 insertions, 8 deletions
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index 2a4a13e9ff4..85e1e979120 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -100,7 +100,7 @@ struct blitter_context_priv void *velem_state; void *velem_uint_state; void *velem_sint_state; - void *velem_state_readbuf; + void *velem_state_readbuf[4]; /**< X, XY, XYZ, XYZW */ /* Sampler state. */ void *sampler_state; @@ -285,9 +285,19 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) } if (ctx->has_stream_out) { - velem[0].src_format = PIPE_FORMAT_R32_UINT; - velem[0].vertex_buffer_index = ctx->base.vb_slot; - ctx->velem_state_readbuf = pipe->create_vertex_elements_state(pipe, 1, &velem[0]); + static enum pipe_format formats[4] = { + PIPE_FORMAT_R32_UINT, + PIPE_FORMAT_R32G32_UINT, + PIPE_FORMAT_R32G32B32_UINT, + PIPE_FORMAT_R32G32B32A32_UINT + }; + + for (i = 0; i < 4; i++) { + velem[0].src_format = formats[i]; + velem[0].vertex_buffer_index = ctx->base.vb_slot; + ctx->velem_state_readbuf[i] = + pipe->create_vertex_elements_state(pipe, 1, &velem[0]); + } } /* fragment shaders are created on-demand */ @@ -352,8 +362,11 @@ void util_blitter_destroy(struct blitter_context *blitter) pipe->delete_vertex_elements_state(pipe, ctx->velem_sint_state); pipe->delete_vertex_elements_state(pipe, ctx->velem_uint_state); } - if (ctx->velem_state_readbuf) - pipe->delete_vertex_elements_state(pipe, ctx->velem_state_readbuf); + for (i = 0; i < 4; i++) { + if (ctx->velem_state_readbuf[i]) { + pipe->delete_vertex_elements_state(pipe, ctx->velem_state_readbuf[i]); + } + } for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) { if (ctx->fs_texfetch_col[i]) @@ -1739,7 +1752,7 @@ void util_blitter_copy_buffer(struct blitter_context *blitter, vb.stride = 4; pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, &vb); - pipe->bind_vertex_elements_state(pipe, ctx->velem_state_readbuf); + pipe->bind_vertex_elements_state(pipe, ctx->velem_state_readbuf[0]); pipe->bind_vs_state(pipe, ctx->vs_pos_only); if (ctx->has_geometry_shader) pipe->bind_gs_state(pipe, NULL); @@ -1756,6 +1769,66 @@ void util_blitter_copy_buffer(struct blitter_context *blitter, pipe_so_target_reference(&so_target, NULL); } +void util_blitter_clear_buffer(struct blitter_context *blitter, + struct pipe_resource *dst, + unsigned offset, unsigned size, + unsigned num_channels, + const union pipe_color_union *clear_value) +{ + struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; + struct pipe_context *pipe = ctx->base.pipe; + struct pipe_vertex_buffer vb = {0}; + struct pipe_stream_output_target *so_target; + + assert(num_channels >= 1); + assert(num_channels <= 4); + + /* IMPORTANT: DON'T DO ANY BOUNDS CHECKING HERE! + * + * R600 uses this to initialize texture resources, so width0 might not be + * what you think it is. + */ + + /* Streamout is required. */ + if (!ctx->has_stream_out) { + assert(!"Streamout unsupported in util_blitter_clear_buffer()"); + return; + } + + /* Some alignment is required. */ + if (offset % 4 != 0 || size % 4 != 0) { + assert(!"Bad alignment in util_blitter_clear_buffer()"); + return; + } + + u_upload_data(ctx->upload, 0, num_channels*4, clear_value, + &vb.buffer_offset, &vb.buffer); + vb.stride = 0; + + blitter_set_running_flag(ctx); + blitter_check_saved_vertex_states(ctx); + blitter_disable_render_cond(ctx); + + pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, &vb); + pipe->bind_vertex_elements_state(pipe, + ctx->velem_state_readbuf[num_channels-1]); + pipe->bind_vs_state(pipe, ctx->vs_pos_only); + if (ctx->has_geometry_shader) + pipe->bind_gs_state(pipe, NULL); + pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state); + + so_target = pipe->create_stream_output_target(pipe, dst, offset, size); + pipe->set_stream_output_targets(pipe, 1, &so_target, 0); + + util_draw_arrays(pipe, PIPE_PRIM_POINTS, 0, size / 4); + + blitter_restore_vertex_states(ctx); + blitter_restore_render_cond(ctx); + blitter_unset_running_flag(ctx); + pipe_so_target_reference(&so_target, NULL); + pipe_resource_reference(&vb.buffer, NULL); +} + /* probably radeon specific */ void util_blitter_custom_resolve_color(struct blitter_context *blitter, struct pipe_resource *dst, diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h index 20e69ed5b73..19015844ef7 100644 --- a/src/gallium/auxiliary/util/u_blitter.h +++ b/src/gallium/auxiliary/util/u_blitter.h @@ -276,7 +276,7 @@ void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ, /** * Copy data from one buffer to another using the Stream Output functionality. - * Some alignment is required, otherwise software fallback is used. + * 4-byte alignment is required, otherwise software fallback is used. */ void util_blitter_copy_buffer(struct blitter_context *blitter, struct pipe_resource *dst, @@ -286,6 +286,22 @@ void util_blitter_copy_buffer(struct blitter_context *blitter, unsigned size); /** + * Clear the contents of a buffer using the Stream Output functionality. + * 4-byte alignment is required. + * + * "num_channels" can be 1, 2, 3, or 4, and specifies if the clear value is + * R, RG, RGB, or RGBA. + * + * For each element, only "num_channels" components of "clear_value" are + * copied to the buffer, then the offset is incremented by num_channels*4. + */ +void util_blitter_clear_buffer(struct blitter_context *blitter, + struct pipe_resource *dst, + unsigned offset, unsigned size, + unsigned num_channels, + const union pipe_color_union *clear_value); + +/** * Clear a region of a (color) surface to a constant value. * * These states must be saved in the blitter in addition to the state objects |