From cf3778bae03460325960d2aec0cd4cdf325299eb Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Mon, 14 Jun 2010 05:18:47 +0200 Subject: r300g: rewrite occlusion queries The previous implementation had issues with queries spanning over several command streams as well as using a very large number of queries. This fixes flickering in Enemy Territory: Quake Wars. The driver now renders everything correctly in this game and the graphics is awesome. --- src/gallium/drivers/r300/r300_blit.c | 130 ++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 54 deletions(-) (limited to 'src/gallium/drivers/r300/r300_blit.c') diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index 3bb1caef40..2a47701291 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -25,8 +25,23 @@ #include "util/u_format.h" -static void r300_blitter_save_states(struct r300_context* r300) +enum r300_blitter_op { + R300_CLEAR, + R300_CLEAR_SURFACE, + R300_COPY +}; + +static void r300_blitter_begin(struct r300_context* r300, enum r300_blitter_op op) +{ + if (r300->query_current) { + r300->blitter_saved_query = r300->query_current; + r300_stop_query(r300); + } + + /* Yeah we have to save all those states to ensure the blitter operation + * is really transparent. The states will be restored by the blitter once + * copying is done. */ util_blitter_save_blend(r300->blitter, r300->blend_state.state); util_blitter_save_depth_stencil_alpha(r300->blitter, r300->dsa_state.state); util_blitter_save_stencil_ref(r300->blitter, &(r300->stencil_ref)); @@ -38,6 +53,30 @@ static void r300_blitter_save_states(struct r300_context* r300) util_blitter_save_vertex_elements(r300->blitter, r300->velems); util_blitter_save_vertex_buffers(r300->blitter, r300->vertex_buffer_count, r300->vertex_buffer); + + if (op & (R300_CLEAR_SURFACE | R300_COPY)) + util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state); + + if (op & R300_COPY) { + struct r300_textures_state* state = + (struct r300_textures_state*)r300->textures_state.state; + + util_blitter_save_fragment_sampler_states( + r300->blitter, state->sampler_state_count, + (void**)state->sampler_states); + + util_blitter_save_fragment_sampler_views( + r300->blitter, state->sampler_view_count, + (struct pipe_sampler_view**)state->sampler_views); + } +} + +static void r300_blitter_end(struct r300_context *r300) +{ + if (r300->blitter_saved_query) { + r300_resume_query(r300, r300->blitter_saved_query); + r300->blitter_saved_query = NULL; + } } /* Clear currently bound buffers. */ @@ -73,13 +112,45 @@ static void r300_clear(struct pipe_context* pipe, struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)r300->fb_state.state; - r300_blitter_save_states(r300); - + r300_blitter_begin(r300, R300_CLEAR); util_blitter_clear(r300->blitter, fb->width, fb->height, fb->nr_cbufs, buffers, rgba, depth, stencil); + r300_blitter_end(r300); +} + +/* Clear a region of a color surface to a constant value. */ +static void r300_clear_render_target(struct pipe_context *pipe, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct r300_context *r300 = r300_context(pipe); + + r300_blitter_begin(r300, R300_CLEAR_SURFACE); + util_blitter_clear_render_target(r300->blitter, dst, rgba, + dstx, dsty, width, height); + r300_blitter_end(r300); +} + +/* Clear a region of a depth stencil surface. */ +static void r300_clear_depth_stencil(struct pipe_context *pipe, + struct pipe_surface *dst, + unsigned clear_flags, + double depth, + unsigned stencil, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct r300_context *r300 = r300_context(pipe); + + r300_blitter_begin(r300, R300_CLEAR_SURFACE); + util_blitter_clear_depth_stencil(r300->blitter, dst, clear_flags, depth, stencil, + dstx, dsty, width, height); + r300_blitter_end(r300); } /* Copy a block of pixels from one surface to another using HW. */ @@ -93,27 +164,12 @@ static void r300_hw_copy_region(struct pipe_context* pipe, unsigned width, unsigned height) { struct r300_context* r300 = r300_context(pipe); - struct r300_textures_state* state = - (struct r300_textures_state*)r300->textures_state.state; - - /* Yeah we have to save all those states to ensure this blitter operation - * is really transparent. The states will be restored by the blitter once - * copying is done. */ - r300_blitter_save_states(r300); - util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state); - - util_blitter_save_fragment_sampler_states( - r300->blitter, state->sampler_state_count, - (void**)state->sampler_states); - util_blitter_save_fragment_sampler_views( - r300->blitter, state->sampler_view_count, - (struct pipe_sampler_view**)state->sampler_views); - - /* Do a copy */ + r300_blitter_begin(r300, R300_COPY); util_blitter_copy_region(r300->blitter, dst, subdst, dstx, dsty, dstz, src, subsrc, srcx, srcy, srcz, width, height, TRUE); + r300_blitter_end(r300); } /* Copy a block of pixels from one surface to another. */ @@ -187,40 +243,6 @@ static void r300_resource_copy_region(struct pipe_context *pipe, } } -/* Clear a region of a color surface to a constant value. */ -static void r300_clear_render_target(struct pipe_context *pipe, - struct pipe_surface *dst, - const float *rgba, - unsigned dstx, unsigned dsty, - unsigned width, unsigned height) -{ - struct r300_context *r300 = r300_context(pipe); - - r300_blitter_save_states(r300); - util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state); - - util_blitter_clear_render_target(r300->blitter, dst, rgba, - dstx, dsty, width, height); -} - -/* Clear a region of a depth stencil surface. */ -static void r300_clear_depth_stencil(struct pipe_context *pipe, - struct pipe_surface *dst, - unsigned clear_flags, - double depth, - unsigned stencil, - unsigned dstx, unsigned dsty, - unsigned width, unsigned height) -{ - struct r300_context *r300 = r300_context(pipe); - - r300_blitter_save_states(r300); - util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state); - - util_blitter_clear_depth_stencil(r300->blitter, dst, clear_flags, depth, stencil, - dstx, dsty, width, height); -} - void r300_init_blit_functions(struct r300_context *r300) { r300->context.clear = r300_clear; -- cgit v1.2.3