diff options
Diffstat (limited to 'src/gallium/drivers/svga/svga_pipe_clear.c')
-rw-r--r-- | src/gallium/drivers/svga/svga_pipe_clear.c | 135 |
1 files changed, 125 insertions, 10 deletions
diff --git a/src/gallium/drivers/svga/svga_pipe_clear.c b/src/gallium/drivers/svga/svga_pipe_clear.c index c4edced9bae..bab61780610 100644 --- a/src/gallium/drivers/svga/svga_pipe_clear.c +++ b/src/gallium/drivers/svga/svga_pipe_clear.c @@ -34,6 +34,78 @@ #include "svga_surface.h" +/** + * Clear the whole color buffer(s) by drawing a quad. For VGPU10 we use + * this when clearing integer render targets. We'll also clear the + * depth and/or stencil buffers if the clear_buffers mask specifies them. + */ +static void +clear_buffers_with_quad(struct svga_context *svga, + unsigned clear_buffers, + const union pipe_color_union *color, + double depth, unsigned stencil) +{ + const struct pipe_framebuffer_state *fb = &svga->curr.framebuffer; + + util_blitter_save_vertex_buffer_slot(svga->blitter, svga->curr.vb); + util_blitter_save_vertex_elements(svga->blitter, (void*)svga->curr.velems); + util_blitter_save_vertex_shader(svga->blitter, svga->curr.vs); + util_blitter_save_geometry_shader(svga->blitter, svga->curr.gs); + util_blitter_save_so_targets(svga->blitter, svga->num_so_targets, + (struct pipe_stream_output_target**)svga->so_targets); + util_blitter_save_rasterizer(svga->blitter, (void*)svga->curr.rast); + util_blitter_save_viewport(svga->blitter, &svga->curr.viewport); + util_blitter_save_scissor(svga->blitter, &svga->curr.scissor); + util_blitter_save_fragment_shader(svga->blitter, svga->curr.fs); + util_blitter_save_blend(svga->blitter, (void*)svga->curr.blend); + util_blitter_save_depth_stencil_alpha(svga->blitter, + (void*)svga->curr.depth); + util_blitter_save_stencil_ref(svga->blitter, &svga->curr.stencil_ref); + util_blitter_save_sample_mask(svga->blitter, svga->curr.sample_mask); + + util_blitter_clear(svga->blitter, + fb->width, fb->height, + 1, /* num_layers */ + clear_buffers, color, + depth, stencil); +} + + +/** + * Check if any of the color buffers are integer buffers. + */ +static boolean +is_integer_target(struct pipe_framebuffer_state *fb, unsigned buffers) +{ + unsigned i; + + for (i = 0; i < fb->nr_cbufs; i++) { + if ((buffers & (PIPE_CLEAR_COLOR0 << i)) && + fb->cbufs[i] && + util_format_is_pure_integer(fb->cbufs[i]->format)) { + return TRUE; + } + } + return FALSE; +} + + +/** + * Check if the integer values in the clear color can be represented + * by floats. If so, we can use the VGPU10 ClearRenderTargetView command. + * Otherwise, we need to clear with a quad. + */ +static boolean +ints_fit_in_floats(const union pipe_color_union *color) +{ + const int max = 1 << 24; + return (color->i[0] <= max && + color->i[1] <= max && + color->i[2] <= max && + color->i[3] <= max); +} + + static enum pipe_error try_clear(struct svga_context *svga, unsigned buffers, @@ -52,7 +124,7 @@ try_clear(struct svga_context *svga, if (ret != PIPE_OK) return ret; - if (svga->rebind.rendertargets) { + if (svga->rebind.flags.rendertargets) { ret = svga_reemit_framebuffer_bindings(svga); if (ret != PIPE_OK) { return ret; @@ -71,29 +143,72 @@ try_clear(struct svga_context *svga, if (buffers & PIPE_CLEAR_DEPTH) flags |= SVGA3D_CLEAR_DEPTH; - if ((svga->curr.framebuffer.zsbuf->format == PIPE_FORMAT_S8_UINT_Z24_UNORM) && - (buffers & PIPE_CLEAR_STENCIL)) + if (buffers & PIPE_CLEAR_STENCIL) flags |= SVGA3D_CLEAR_STENCIL; rect.w = MAX2(rect.w, fb->zsbuf->width); rect.h = MAX2(rect.h, fb->zsbuf->height); } - if (memcmp(&rect, &svga->state.hw_clear.viewport, sizeof(rect)) != 0) { + if (!svga_have_vgpu10(svga) && + !svga_rects_equal(&rect, &svga->state.hw_clear.viewport)) { restore_viewport = TRUE; ret = SVGA3D_SetViewport(svga->swc, &rect); if (ret != PIPE_OK) return ret; } - ret = SVGA3D_ClearRect(svga->swc, flags, uc.ui[0], (float) depth, stencil, - rect.x, rect.y, rect.w, rect.h); - if (ret != PIPE_OK) - return ret; + if (svga_have_vgpu10(svga)) { + if (flags & SVGA3D_CLEAR_COLOR) { + unsigned i; + + if (is_integer_target(fb, buffers) && !ints_fit_in_floats(color)) { + clear_buffers_with_quad(svga, buffers, color, depth, stencil); + /* We also cleared depth/stencil, so that's done */ + flags &= ~(SVGA3D_CLEAR_DEPTH | SVGA3D_CLEAR_STENCIL); + } + else { + struct pipe_surface *rtv; + + /* Issue VGPU10 Clear commands */ + for (i = 0; i < fb->nr_cbufs; i++) { + if ((fb->cbufs[i] == NULL) || + !(buffers & (PIPE_CLEAR_COLOR0 << i))) + continue; + + rtv = svga_validate_surface_view(svga, + svga_surface(fb->cbufs[i])); + if (rtv == NULL) + return PIPE_ERROR_OUT_OF_MEMORY; + + ret = SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, + rtv, color->f); + if (ret != PIPE_OK) + return ret; + } + } + } + if (flags & (SVGA3D_CLEAR_DEPTH | SVGA3D_CLEAR_STENCIL)) { + struct pipe_surface *dsv = + svga_validate_surface_view(svga, svga_surface(fb->zsbuf)); + if (dsv == NULL) + return PIPE_ERROR_OUT_OF_MEMORY; + + ret = SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv, flags, + stencil, (float) depth); + if (ret != PIPE_OK) + return ret; + } + } + else { + ret = SVGA3D_ClearRect(svga->swc, flags, uc.ui[0], (float) depth, stencil, + rect.x, rect.y, rect.w, rect.h); + if (ret != PIPE_OK) + return ret; + } if (restore_viewport) { - memcpy(&rect, &svga->state.hw_clear.viewport, sizeof rect); - ret = SVGA3D_SetViewport(svga->swc, &rect); + ret = SVGA3D_SetViewport(svga->swc, &svga->state.hw_clear.viewport); } return ret; |