From a1d5131d2eaa5f5ccc8b38f9379f9c6bc989bc1a Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Sat, 29 May 2010 00:02:05 +0200 Subject: [PATCH] util: adapt to clear interface changes --- src/gallium/auxiliary/util/u_blitter.c | 126 +++++++++++++++++-------- src/gallium/auxiliary/util/u_blitter.h | 31 ++++-- src/gallium/auxiliary/util/u_clear.h | 27 ++---- src/gallium/auxiliary/util/u_surface.c | 52 ++++++---- src/gallium/auxiliary/util/u_surface.h | 10 +- 5 files changed, 151 insertions(+), 95 deletions(-) diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index 1f3246208ba..d05a193bf8d 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -26,8 +26,8 @@ /** * @file - * Blitter utility to facilitate acceleration of the clear, resource_copy_region, - * and resource_fill_region functions. + * Blitter utility to facilitate acceleration of the clear, clearRT, clearDS + * resource_copy_region functions. * * @author Marek Olšák */ @@ -88,6 +88,7 @@ struct blitter_context_priv void *dsa_write_depth_stencil; void *dsa_write_depth_keep_stencil; void *dsa_keep_depth_stencil; + void *dsa_keep_depth_write_stencil; void *velem_state; @@ -161,8 +162,12 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) dsa.stencil[0].writemask = 0xff; ctx->dsa_write_depth_stencil = pipe->create_depth_stencil_alpha_state(pipe, &dsa); - /* The DSA state objects which write depth and stencil are created - * on-demand. */ + + + dsa.depth.enabled = 0; + dsa.depth.writemask = 0; + ctx->dsa_keep_depth_write_stencil = + pipe->create_depth_stencil_alpha_state(pipe, &dsa); /* sampler state */ sampler_state = &ctx->template_sampler_state; @@ -234,6 +239,7 @@ void util_blitter_destroy(struct blitter_context *blitter) pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); + pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); pipe->delete_rasterizer_state(pipe, ctx->rs_state); pipe->delete_vs_state(pipe, ctx->vs_col); @@ -605,11 +611,19 @@ void util_blitter_clear(struct blitter_context *blitter, else pipe->bind_blend_state(pipe, ctx->blend_keep_color); - if (clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) { + if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) { sr.ref_value[0] = stencil & 0xff; pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); pipe->set_stencil_ref(pipe, &sr); } + else if (clear_buffers & PIPE_CLEAR_DEPTH) { + pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); + } + else if (clear_buffers & PIPE_CLEAR_STENCIL) { + sr.ref_value[0] = stencil & 0xff; + pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); + pipe->set_stencil_ref(pipe, &sr); + } else pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); @@ -766,48 +780,21 @@ void util_blitter_copy_region(struct blitter_context *blitter, pipe_surface_reference(&dstsurf, NULL); } -/* Fill a region of a surface with a constant value. */ -void util_blitter_fill_region(struct blitter_context *blitter, - struct pipe_resource *dst, - struct pipe_subresource subdst, - unsigned dstx, unsigned dsty, unsigned dstz, - unsigned width, unsigned height, - unsigned value) +/* Clear a region of a color surface to a constant value. */ +void util_blitter_clearRT(struct blitter_context *blitter, + struct pipe_surface *dstsurf, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) { struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; struct pipe_context *pipe = ctx->pipe; - struct pipe_screen *screen = pipe->screen; - struct pipe_surface *dstsurf; struct pipe_framebuffer_state fb_state; - float rgba[4]; - ubyte ub_rgba[4] = {0}; - union util_color color; - int i; - assert(dst); - if (!dst) + assert(dstsurf->texture); + if (!dstsurf->texture) return; - /* check if we can render to the surface */ - if (util_format_is_depth_or_stencil(dst->format) || /* unlikely, but you never know */ - !screen->is_format_supported(screen, dst->format, dst->target, - dst->nr_samples, - PIPE_BIND_RENDER_TARGET, 0)) { - util_resource_fill_region(pipe, dst, subdst, dstx, dsty, dstz, - width, height, value); - return; - } - - dstsurf = screen->get_tex_surface(screen, dst, subdst.face, subdst.level, - dstz, PIPE_BIND_RENDER_TARGET); - - /* unpack the color */ - color.ui = value; - util_unpack_color_ub(dst->format, &color, - ub_rgba, ub_rgba+1, ub_rgba+2, ub_rgba+3); - for (i = 0; i < 4; i++) - rgba[i] = ubyte_to_float(ub_rgba[i]); - /* check the saved state */ blitter_check_saved_CSOs(ctx); assert(blitter->saved_fb_state.nr_cbufs != ~0); @@ -832,6 +819,63 @@ void util_blitter_fill_region(struct blitter_context *blitter, blitter_set_rectangle(ctx, 0, 0, width, height, dstsurf->width, dstsurf->height, 0); blitter_draw_quad(ctx); blitter_restore_CSOs(ctx); +} - pipe_surface_reference(&dstsurf, NULL); +/* Clear a region of a depth stencil surface. */ +void util_blitter_clearDS(struct blitter_context *blitter, + struct pipe_surface *dstsurf, + unsigned clear_flags, + double depth, + unsigned stencil, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; + struct pipe_context *pipe = ctx->pipe; + struct pipe_framebuffer_state fb_state; + struct pipe_stencil_ref sr = { { 0 } }; + + assert(dstsurf->texture); + if (!dstsurf->texture) + return; + + /* check the saved state */ + blitter_check_saved_CSOs(ctx); + assert(blitter->saved_fb_state.nr_cbufs != ~0); + + /* bind CSOs */ + pipe->bind_blend_state(pipe, ctx->blend_keep_color); + if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) { + sr.ref_value[0] = stencil & 0xff; + pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); + pipe->set_stencil_ref(pipe, &sr); + } + else if (clear_flags & PIPE_CLEAR_DEPTH) { + pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); + } + else if (clear_flags & PIPE_CLEAR_STENCIL) { + sr.ref_value[0] = stencil & 0xff; + pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); + pipe->set_stencil_ref(pipe, &sr); + } + else + /* hmm that should be illegal probably, or make it a no-op somewhere */ + pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); + + pipe->bind_rasterizer_state(pipe, ctx->rs_state); + pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0)); + pipe->bind_vs_state(pipe, ctx->vs_col); + pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + + /* set a framebuffer state */ + fb_state.width = dstsurf->width; + fb_state.height = dstsurf->height; + fb_state.nr_cbufs = 0; + fb_state.cbufs[0] = 0; + fb_state.zsbuf = dstsurf; + pipe->set_framebuffer_state(pipe, &fb_state); + + blitter_set_rectangle(ctx, 0, 0, width, height, dstsurf->width, dstsurf->height, depth); + blitter_draw_quad(ctx); + blitter_restore_CSOs(ctx); } diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h index ef1e6b34498..f894fd5a933 100644 --- a/src/gallium/auxiliary/util/u_blitter.h +++ b/src/gallium/auxiliary/util/u_blitter.h @@ -123,22 +123,33 @@ void util_blitter_copy_region(struct blitter_context *blitter, boolean ignore_stencil); /** - * Fill a region of a surface with a constant value. - * - * If the surface cannot be rendered to or it's a depth-stencil format, - * a software fallback path is taken. + * 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 * already required to be saved: * - framebuffer state */ -void util_blitter_fill_region(struct blitter_context *blitter, - struct pipe_resource *dst, - struct pipe_subresource subdst, - unsigned dstx, unsigned dsty, unsigned dstz, - unsigned width, unsigned height, - unsigned value); +void util_blitter_clearRT(struct blitter_context *blitter, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height); +/** + * Clear a region of a depth-stencil surface, both stencil and depth + * or only one of them if this is a combined depth-stencil surface. + * + * These states must be saved in the blitter in addition to the state objects + * already required to be saved: + * - framebuffer state + */ +void util_blitter_clearDS(struct blitter_context *blitter, + struct pipe_surface *dst, + unsigned clear_flags, + double depth, + unsigned stencil, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height); /* The functions below should be used to save currently bound constant state * objects inside a driver. The objects are automatically restored at the end diff --git a/src/gallium/auxiliary/util/u_clear.h b/src/gallium/auxiliary/util/u_clear.h index 31f7fb2169a..07088a7a727 100644 --- a/src/gallium/auxiliary/util/u_clear.h +++ b/src/gallium/auxiliary/util/u_clear.h @@ -31,9 +31,6 @@ #include "pipe/p_context.h" #include "pipe/p_state.h" -#include "util/u_pack_color.h" -#include "util/u_rect.h" -#include "util/u_surface.h" /** @@ -46,25 +43,17 @@ util_clear(struct pipe_context *pipe, const float *rgba, double depth, unsigned stencil) { if (buffers & PIPE_CLEAR_COLOR) { - struct pipe_surface *ps = framebuffer->cbufs[0]; - struct pipe_subresource subdst; - union util_color uc; - - subdst.face = ps->face; - subdst.level = ps->level; - util_pack_color(rgba, ps->format, &uc); - pipe->resource_fill_region(pipe, ps->texture, subdst, 0, 0, ps->zslice, - ps->width, ps->height, uc.ui); + unsigned i; + for (i = 0; i < framebuffer->nr_cbufs; i++) { + struct pipe_surface *ps = framebuffer->cbufs[i]; + pipe->clearRT(pipe, ps, rgba, 0, 0, ps->width, ps->height); + } } if (buffers & PIPE_CLEAR_DEPTHSTENCIL) { struct pipe_surface *ps = framebuffer->zsbuf; - struct pipe_subresource subdst; - - subdst.face = ps->face; - subdst.level = ps->level; - pipe->resource_fill_region(pipe, ps->texture, subdst, 0, 0, ps->zslice, - ps->width, ps->height, - util_pack_z_stencil(ps->format, depth, stencil)); + pipe->clearDS(pipe, ps, buffers & PIPE_CLEAR_DEPTHSTENCIL, + depth, stencil, + 0, 0, ps->width, ps->height); } } diff --git a/src/gallium/auxiliary/util/u_surface.c b/src/gallium/auxiliary/util/u_surface.c index 9adf22c471e..1b4eaf2a6e6 100644 --- a/src/gallium/auxiliary/util/u_surface.c +++ b/src/gallium/auxiliary/util/u_surface.c @@ -40,6 +40,7 @@ #include "util/u_inlines.h" #include "util/u_rect.h" #include "util/u_surface.h" +#include "util/u_pack_color.h" /** @@ -195,26 +196,33 @@ util_resource_copy_region(struct pipe_context *pipe, /** - * Fallback for pipe->resource_fill_region() function. + * Fallback for pipe->clearRT() function. + * XXX this looks too hackish to be really useful. + * cpp > 4 looks like a gross hack at best... + * and we're missing the equivalent clearDS fallback. + * Plus can't use these transfer fallbacks when clearing + * multisampled surfaces for instance. */ void -util_resource_fill_region(struct pipe_context *pipe, - struct pipe_resource *dst, - struct pipe_subresource subdst, - unsigned dstx, unsigned dsty, unsigned dstz, - unsigned width, unsigned height, unsigned value) +util_clearRT(struct pipe_context *pipe, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) { struct pipe_transfer *dst_trans; void *dst_map; + union util_color uc; - assert(dst); - if (!dst) + assert(dst->texture); + if (!dst->texture) return; + util_pack_color(rgba, dst->texture->format, &uc); dst_trans = pipe_get_transfer(pipe, - dst, - subdst.face, - subdst.level, - dstz, + dst->texture, + dst->face, + dst->level, + dst->zslice, PIPE_TRANSFER_WRITE, dstx, dsty, width, height); @@ -225,22 +233,26 @@ util_resource_fill_region(struct pipe_context *pipe, if (dst_map) { assert(dst_trans->stride > 0); - switch (util_format_get_blocksize(dst->format)) { + switch (util_format_get_blocksize(dst->texture->format)) { case 1: case 2: case 4: - util_fill_rect(dst_map, dst->format, - dst_trans->stride, - 0, 0, width, height, value); + util_pack_color(rgba, dst->texture->format, &uc); + util_fill_rect(dst_map, dst->texture->format, + dst_trans->stride, + 0, 0, width, height, uc.ui); break; case 8: { /* expand the 4-byte clear value to an 8-byte value */ + /* should probably not convert back from ubyte but not + sure what this code really achieved since it doesn't even + check for format type... */ ushort *row = (ushort *) dst_map; - ushort val0 = UBYTE_TO_USHORT((value >> 0) & 0xff); - ushort val1 = UBYTE_TO_USHORT((value >> 8) & 0xff); - ushort val2 = UBYTE_TO_USHORT((value >> 16) & 0xff); - ushort val3 = UBYTE_TO_USHORT((value >> 24) & 0xff); + ushort val0 = UBYTE_TO_USHORT((uc.ui >> 0) & 0xff); + ushort val1 = UBYTE_TO_USHORT((uc.ui >> 8) & 0xff); + ushort val2 = UBYTE_TO_USHORT((uc.ui >> 16) & 0xff); + ushort val3 = UBYTE_TO_USHORT((uc.ui >> 24) & 0xff); unsigned i, j; val0 = (val0 << 8) | val0; val1 = (val1 << 8) | val1; diff --git a/src/gallium/auxiliary/util/u_surface.h b/src/gallium/auxiliary/util/u_surface.h index ccde738ca40..b640c793085 100644 --- a/src/gallium/auxiliary/util/u_surface.h +++ b/src/gallium/auxiliary/util/u_surface.h @@ -57,11 +57,11 @@ util_resource_copy_region(struct pipe_context *pipe, unsigned w, unsigned h); extern void -util_resource_fill_region(struct pipe_context *pipe, - struct pipe_resource *dst, - struct pipe_subresource subdst, - unsigned dstx, unsigned dsty, unsigned dstz, - unsigned width, unsigned height, unsigned value); +util_clearRT(struct pipe_context *pipe, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height); -- 2.30.2