u_blitter: cleanup checking for and restoring saved states

This commit is contained in:
Marek Olšák 2011-10-07 19:10:41 +02:00
parent 5baa33a738
commit c12c05c198
2 changed files with 175 additions and 101 deletions

View file

@ -263,100 +263,134 @@ void util_blitter_destroy(struct blitter_context *blitter)
FREE(ctx);
}
static void blitter_check_saved_CSOs(struct blitter_context_priv *ctx)
static void blitter_set_running_flag(struct blitter_context_priv *ctx)
{
if (ctx->base.running) {
_debug_printf("u_blitter: Caught recursion on save. "
"This is a driver bug.\n");
_debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n",
__LINE__);
}
ctx->base.running = TRUE;
/* make sure these CSOs have been saved */
assert(ctx->base.saved_blend_state != INVALID_PTR &&
ctx->base.saved_dsa_state != INVALID_PTR &&
ctx->base.saved_rs_state != INVALID_PTR &&
ctx->base.saved_fs != INVALID_PTR &&
ctx->base.saved_vs != INVALID_PTR &&
ctx->base.saved_velem_state != INVALID_PTR);
}
static void blitter_restore_CSOs(struct blitter_context_priv *ctx)
static void blitter_unset_running_flag(struct blitter_context_priv *ctx)
{
if (!ctx->base.running) {
_debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n",
__LINE__);
}
ctx->base.running = FALSE;
}
static void blitter_check_saved_vertex_states(struct blitter_context_priv *ctx)
{
assert(ctx->base.saved_num_vertex_buffers != ~0 &&
ctx->base.saved_velem_state != INVALID_PTR &&
ctx->base.saved_vs != INVALID_PTR &&
ctx->base.saved_rs_state != INVALID_PTR);
}
static void blitter_restore_vertex_states(struct blitter_context_priv *ctx)
{
struct pipe_context *pipe = ctx->base.pipe;
unsigned i;
/* restore the state objects which are always required to be saved */
pipe->bind_rasterizer_state(pipe, ctx->base.saved_rs_state);
pipe->bind_vs_state(pipe, ctx->base.saved_vs);
pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state);
/* Vertex buffers. */
pipe->set_vertex_buffers(pipe,
ctx->base.saved_num_vertex_buffers,
ctx->base.saved_vertex_buffers);
ctx->base.saved_rs_state = INVALID_PTR;
ctx->base.saved_vs = INVALID_PTR;
for (i = 0; i < ctx->base.saved_num_vertex_buffers; i++) {
if (ctx->base.saved_vertex_buffers[i].buffer) {
pipe_resource_reference(&ctx->base.saved_vertex_buffers[i].buffer,
NULL);
}
}
ctx->base.saved_num_vertex_buffers = ~0;
/* Vertex elements. */
pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state);
ctx->base.saved_velem_state = INVALID_PTR;
/* restore the state objects which are required to be saved for clear/copy
*/
if (ctx->base.saved_blend_state != INVALID_PTR) {
pipe->bind_blend_state(pipe, ctx->base.saved_blend_state);
ctx->base.saved_blend_state = INVALID_PTR;
}
if (ctx->base.saved_dsa_state != INVALID_PTR) {
pipe->bind_depth_stencil_alpha_state(pipe, ctx->base.saved_dsa_state);
ctx->base.saved_dsa_state = INVALID_PTR;
}
if (ctx->base.saved_fs != INVALID_PTR) {
pipe->bind_fs_state(pipe, ctx->base.saved_fs);
ctx->base.saved_fs = INVALID_PTR;
}
/* Vertex shader. */
pipe->bind_vs_state(pipe, ctx->base.saved_vs);
ctx->base.saved_vs = INVALID_PTR;
/* Rasterizer. */
pipe->bind_rasterizer_state(pipe, ctx->base.saved_rs_state);
ctx->base.saved_rs_state = INVALID_PTR;
}
static void blitter_check_saved_fragment_states(struct blitter_context_priv *ctx)
{
assert(ctx->base.saved_fs != INVALID_PTR &&
ctx->base.saved_dsa_state != INVALID_PTR &&
ctx->base.saved_blend_state != INVALID_PTR);
}
static void blitter_restore_fragment_states(struct blitter_context_priv *ctx)
{
struct pipe_context *pipe = ctx->base.pipe;
/* Fragment shader. */
pipe->bind_fs_state(pipe, ctx->base.saved_fs);
ctx->base.saved_fs = INVALID_PTR;
/* Depth, stencil, alpha. */
pipe->bind_depth_stencil_alpha_state(pipe, ctx->base.saved_dsa_state);
ctx->base.saved_dsa_state = INVALID_PTR;
/* Blend state. */
pipe->bind_blend_state(pipe, ctx->base.saved_blend_state);
ctx->base.saved_blend_state = INVALID_PTR;
/* Miscellaneous states. */
/* XXX check whether these are saved and whether they need to be restored
* (depending on the operation) */
pipe->set_stencil_ref(pipe, &ctx->base.saved_stencil_ref);
pipe->set_viewport_state(pipe, &ctx->base.saved_viewport);
pipe->set_clip_state(pipe, &ctx->base.saved_clip);
}
if (ctx->base.saved_fb_state.nr_cbufs != ~0) {
pipe->set_framebuffer_state(pipe, &ctx->base.saved_fb_state);
util_unreference_framebuffer_state(&ctx->base.saved_fb_state);
ctx->base.saved_fb_state.nr_cbufs = ~0;
}
static void blitter_check_saved_fb_state(struct blitter_context_priv *ctx)
{
assert(ctx->base.saved_fb_state.nr_cbufs != ~0);
}
if (ctx->base.saved_num_sampler_states != ~0) {
pipe->bind_fragment_sampler_states(pipe,
ctx->base.saved_num_sampler_states,
ctx->base.saved_sampler_states);
ctx->base.saved_num_sampler_states = ~0;
}
static void blitter_restore_fb_state(struct blitter_context_priv *ctx)
{
struct pipe_context *pipe = ctx->base.pipe;
if (ctx->base.saved_num_sampler_views != ~0) {
pipe->set_fragment_sampler_views(pipe,
ctx->base.saved_num_sampler_views,
ctx->base.saved_sampler_views);
pipe->set_framebuffer_state(pipe, &ctx->base.saved_fb_state);
util_unreference_framebuffer_state(&ctx->base.saved_fb_state);
}
for (i = 0; i < ctx->base.saved_num_sampler_views; i++)
pipe_sampler_view_reference(&ctx->base.saved_sampler_views[i],
NULL);
static void blitter_check_saved_textures(struct blitter_context_priv *ctx)
{
assert(ctx->base.saved_num_sampler_states != ~0 &&
ctx->base.saved_num_sampler_views != ~0);
}
ctx->base.saved_num_sampler_views = ~0;
}
static void blitter_restore_textures(struct blitter_context_priv *ctx)
{
struct pipe_context *pipe = ctx->base.pipe;
unsigned i;
if (ctx->base.saved_num_vertex_buffers != ~0) {
pipe->set_vertex_buffers(pipe,
ctx->base.saved_num_vertex_buffers,
ctx->base.saved_vertex_buffers);
/* Fragment sampler states. */
pipe->bind_fragment_sampler_states(pipe,
ctx->base.saved_num_sampler_states,
ctx->base.saved_sampler_states);
ctx->base.saved_num_sampler_states = ~0;
for (i = 0; i < ctx->base.saved_num_vertex_buffers; i++) {
if (ctx->base.saved_vertex_buffers[i].buffer) {
pipe_resource_reference(&ctx->base.saved_vertex_buffers[i].buffer,
NULL);
}
}
ctx->base.saved_num_vertex_buffers = ~0;
}
/* Fragment sampler views. */
pipe->set_fragment_sampler_views(pipe,
ctx->base.saved_num_sampler_views,
ctx->base.saved_sampler_views);
if (!ctx->base.running) {
_debug_printf("u_blitter: Caught recursion on restore. "
"This is a driver bug.\n");
}
ctx->base.running = FALSE;
for (i = 0; i < ctx->base.saved_num_sampler_views; i++)
pipe_sampler_view_reference(&ctx->base.saved_sampler_views[i], NULL);
ctx->base.saved_num_sampler_views = ~0;
}
static void blitter_set_rectangle(struct blitter_context_priv *ctx,
@ -684,9 +718,11 @@ static void util_blitter_clear_custom(struct blitter_context *blitter,
assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
blitter_check_saved_CSOs(ctx);
blitter_set_running_flag(ctx);
blitter_check_saved_vertex_states(ctx);
blitter_check_saved_fragment_states(ctx);
/* bind CSOs */
/* bind states */
if (custom_blend) {
pipe->bind_blend_state(pipe, custom_blend);
} else if (clear_buffers & PIPE_CLEAR_COLOR) {
@ -718,7 +754,10 @@ static void util_blitter_clear_custom(struct blitter_context *blitter,
blitter_set_dst_dimensions(ctx, width, height);
blitter->draw_rectangle(blitter, 0, 0, width, height, depth,
UTIL_BLITTER_ATTRIB_COLOR, color);
blitter_restore_CSOs(ctx);
blitter_restore_vertex_states(ctx);
blitter_restore_fragment_states(ctx);
blitter_unset_running_flag(ctx);
}
void util_blitter_clear(struct blitter_context *blitter,
@ -817,10 +856,11 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
dstsurf = pipe->create_surface(pipe, dst, &surf_templ);
/* Check whether the states are properly saved. */
blitter_check_saved_CSOs(ctx);
assert(blitter->saved_fb_state.nr_cbufs != ~0);
assert(blitter->saved_num_sampler_views != ~0);
assert(blitter->saved_num_sampler_states != ~0);
blitter_set_running_flag(ctx);
blitter_check_saved_vertex_states(ctx);
blitter_check_saved_fragment_states(ctx);
blitter_check_saved_textures(ctx);
blitter_check_saved_fb_state(ctx);
/* Initialize framebuffer state. */
fb_state.width = dstsurf->width;
@ -918,7 +958,11 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
break;
}
blitter_restore_CSOs(ctx);
blitter_restore_vertex_states(ctx);
blitter_restore_fragment_states(ctx);
blitter_restore_textures(ctx);
blitter_restore_fb_state(ctx);
blitter_unset_running_flag(ctx);
pipe_surface_reference(&dstsurf, NULL);
pipe_sampler_view_reference(&view, NULL);
@ -940,10 +984,12 @@ void util_blitter_clear_render_target(struct blitter_context *blitter,
return;
/* check the saved state */
blitter_check_saved_CSOs(ctx);
assert(blitter->saved_fb_state.nr_cbufs != ~0);
blitter_set_running_flag(ctx);
blitter_check_saved_vertex_states(ctx);
blitter_check_saved_fragment_states(ctx);
blitter_check_saved_fb_state(ctx);
/* bind CSOs */
/* bind states */
pipe->bind_blend_state(pipe, ctx->blend_write_color);
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
pipe->bind_rasterizer_state(pipe, ctx->rs_state);
@ -962,7 +1008,11 @@ void util_blitter_clear_render_target(struct blitter_context *blitter,
blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0,
UTIL_BLITTER_ATTRIB_COLOR, color);
blitter_restore_CSOs(ctx);
blitter_restore_vertex_states(ctx);
blitter_restore_fragment_states(ctx);
blitter_restore_fb_state(ctx);
blitter_unset_running_flag(ctx);
}
/* Clear a region of a depth stencil surface. */
@ -984,10 +1034,12 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
return;
/* check the saved state */
blitter_check_saved_CSOs(ctx);
assert(blitter->saved_fb_state.nr_cbufs != ~0);
blitter_set_running_flag(ctx);
blitter_check_saved_vertex_states(ctx);
blitter_check_saved_fragment_states(ctx);
blitter_check_saved_fb_state(ctx);
/* bind CSOs */
/* bind states */
pipe->bind_blend_state(pipe, ctx->blend_keep_color);
if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
sr.ref_value[0] = stencil & 0xff;
@ -1022,7 +1074,11 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, depth,
UTIL_BLITTER_ATTRIB_NONE, NULL);
blitter_restore_CSOs(ctx);
blitter_restore_vertex_states(ctx);
blitter_restore_fragment_states(ctx);
blitter_restore_fb_state(ctx);
blitter_unset_running_flag(ctx);
}
/* draw a rectangle across a region using a custom dsa stage - for r600g */
@ -1040,10 +1096,12 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
return;
/* check the saved state */
blitter_check_saved_CSOs(ctx);
assert(blitter->saved_fb_state.nr_cbufs != ~0);
blitter_set_running_flag(ctx);
blitter_check_saved_vertex_states(ctx);
blitter_check_saved_fragment_states(ctx);
blitter_check_saved_fb_state(ctx);
/* bind CSOs */
/* bind states */
pipe->bind_blend_state(pipe, ctx->blend_write_color);
pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage);
@ -1069,5 +1127,9 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
blitter_set_dst_dimensions(ctx, zsurf->width, zsurf->height);
blitter->draw_rectangle(blitter, 0, 0, zsurf->width, zsurf->height, depth,
UTIL_BLITTER_ATTRIB_NONE, NULL);
blitter_restore_CSOs(ctx);
blitter_restore_vertex_states(ctx);
blitter_restore_fragment_states(ctx);
blitter_restore_fb_state(ctx);
blitter_unset_running_flag(ctx);
}

View file

@ -126,19 +126,21 @@ struct pipe_context *util_blitter_get_pipe(struct blitter_context *blitter)
}
/*
* These states must be saved before any of the following functions is called:
* - blend state
* - depth stencil alpha state
* - rasterizer state
* - vertex shader
* - any other shader??? (XXX)
* - fragment shader
* These states must be saved before any of the following functions are called:
* - vertex buffers
* - vertex elements
* - vertex shader
* - rasterizer state
*/
/**
* Clear a specified set of currently bound buffers to specified values.
*
* These states must be saved in the blitter in addition to the state objects
* already required to be saved:
* - fragment shader
* - depth stencil alpha state
* - blend state
*/
void util_blitter_clear(struct blitter_context *blitter,
unsigned width, unsigned height,
@ -155,7 +157,7 @@ void util_blitter_clear_depth_custom(struct blitter_context *blitter,
* Copy a block of pixels from one surface to another.
*
* You can copy from any color format to any other color format provided
* the former can be sampled and the latter can be rendered to. Otherwise,
* the former can be sampled from and the latter can be rendered to. Otherwise,
* a software fallback path is taken and both surfaces must be of the same
* format.
*
@ -163,14 +165,18 @@ void util_blitter_clear_depth_custom(struct blitter_context *blitter,
* cannot be copied unless you set ignore_stencil to FALSE. In that case,
* a software fallback path is taken and both surfaces must be of the same
* format.
* XXX implement hw-accel stencil copy using shader stencil export.
*
* Use pipe_screen->is_format_supported to know your options.
*
* These states must be saved in the blitter in addition to the state objects
* already required to be saved:
* - framebuffer state
* - fragment shader
* - depth stencil alpha state
* - blend state
* - fragment sampler states
* - fragment sampler textures
* - framebuffer state
*/
void util_blitter_copy_texture(struct blitter_context *blitter,
struct pipe_resource *dst,
@ -186,6 +192,9 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
*
* These states must be saved in the blitter in addition to the state objects
* already required to be saved:
* - fragment shader
* - depth stencil alpha state
* - blend state
* - framebuffer state
*/
void util_blitter_clear_render_target(struct blitter_context *blitter,
@ -200,6 +209,9 @@ void util_blitter_clear_render_target(struct blitter_context *blitter,
*
* These states must be saved in the blitter in addition to the state objects
* already required to be saved:
* - fragment shader
* - depth stencil alpha state
* - blend state
* - framebuffer state
*/
void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
@ -220,7 +232,7 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
* of the util_blitter_{clear, copy_region, fill_region} functions and then
* forgotten.
*
* CSOs not listed here are not affected by util_blitter. */
* States not listed here are not affected by util_blitter. */
static INLINE
void util_blitter_save_blend(struct blitter_context *blitter,
@ -322,8 +334,8 @@ util_blitter_save_fragment_sampler_views(struct blitter_context *blitter,
static INLINE void
util_blitter_save_vertex_buffers(struct blitter_context *blitter,
int num_vertex_buffers,
struct pipe_vertex_buffer *vertex_buffers)
int num_vertex_buffers,
struct pipe_vertex_buffer *vertex_buffers)
{
assert(num_vertex_buffers <= Elements(blitter->saved_vertex_buffers));