diff options
author | Roland Scheidegger <sroland@vmware.com> | 2010-06-03 17:46:14 +0200 |
---|---|---|
committer | Roland Scheidegger <sroland@vmware.com> | 2010-06-03 17:46:14 +0200 |
commit | 992382762a74fd834926fd2c3cd9e14a186e2dd5 (patch) | |
tree | c4572bb01331b71931b3570b36a7acfc38f79a68 /src | |
parent | 05863c487756c1c9dc823cf639f77cad4111bd23 (diff) | |
parent | a6e5c6c000df8655de3b41d5809547bb41c88c23 (diff) |
Merge branch 'gallium-newclear'
Conflicts:
src/gallium/state_trackers/python/p_context.i
Diffstat (limited to 'src')
47 files changed, 763 insertions, 336 deletions
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index bcd5686470..183ffe5670 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, clear_render_target, clear_depth_stencil + * 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); @@ -596,11 +602,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); @@ -757,48 +771,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_clear_render_target(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); @@ -823,6 +810,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_clear_depth_stencil(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 ef1e6b3449..10143a5e0f 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_clear_render_target(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_clear_depth_stencil(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 31f7fb2169..ad69df3f89 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->clear_render_target(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->clear_depth_stencil(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 9adf22c471..9dd1002f5f 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->clear_render_target() 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 clear_depth_stencil 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_clear_render_target(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 ccde738ca4..d8fb9f1d6f 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_clear_render_target(struct pipe_context *pipe, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height); diff --git a/src/gallium/docs/d3d11ddi.txt b/src/gallium/docs/d3d11ddi.txt index d9c2b441a9..e3368fdbd6 100644 --- a/src/gallium/docs/d3d11ddi.txt +++ b/src/gallium/docs/d3d11ddi.txt @@ -79,7 +79,7 @@ set_clip_state set_polygon_stipple + Gallium supports polygon stipple -resource_fill_region +clearRT/clearDS + Gallium supports subrectangle fills of surfaces, D3D10 only supports full clears of views * DirectX 10/11 DDI functions and Gallium equivalents diff --git a/src/gallium/docs/source/context.rst b/src/gallium/docs/source/context.rst index 89c02b1b70..27d352b7a3 100644 --- a/src/gallium/docs/source/context.rst +++ b/src/gallium/docs/source/context.rst @@ -102,14 +102,29 @@ the LOD range the texture is going to be constrained to. Clearing ^^^^^^^^ +Clear is one of the most difficult concepts to nail down to a single +interface (due to both different requirements from APIs and also driver/hw +specific differences). + ``clear`` initializes some or all of the surfaces currently bound to the framebuffer to particular RGBA, depth, or stencil values. +Currently, this does not take into account color or stencil write masks (as +used by GL), and always clears the whole surfaces (no scissoring as used by +GL clear or explicit rectangles like d3d9 uses). It can, however, also clear +only depth or stencil in a combined depth/stencil surface, if the driver +supports PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE. +If a surface includes several layers/slices (XXX: not yet...) then all layers +will be cleared. -Clear is one of the most difficult concepts to nail down to a single -interface and it seems likely that we will want to add additional -clear paths, for instance clearing surfaces not bound to the -framebuffer, or read-modify-write clears such as depth-only or -stencil-only clears of packed depth-stencil buffers. +``clear_render_target`` clears a single color rendertarget with the specified +color value. While it is only possible to clear one surface at a time (which can +include several layers), this surface need not be bound to the framebuffer. + +``clear_depth_stencil``clears a single depth, stencil or depth/stencil surface +with the specified depth and stencil values (for combined depth/stencil buffers, +is is also possible to only clear one or the other part). While it is only +possible to clear one surface at a time (which can include several layers), +this surface need not be bound to the framebuffer. Drawing @@ -266,8 +281,6 @@ These methods operate directly on ``pipe_resource`` objects, and stand apart from any 3D state in the context. Blitting functionality may be moved to a separate abstraction at some point in the future. -``resource_fill_region`` performs a fill operation on a section of a resource. - ``resource_copy_region`` blits a region of a subresource of a resource to a region of another subresource of a resource, provided that both resources have the same format. The source and destination may be the same resource, but overlapping diff --git a/src/gallium/drivers/cell/ppu/cell_surface.c b/src/gallium/drivers/cell/ppu/cell_surface.c index 8000eee88a..777454479b 100644 --- a/src/gallium/drivers/cell/ppu/cell_surface.c +++ b/src/gallium/drivers/cell/ppu/cell_surface.c @@ -34,5 +34,4 @@ void cell_init_surface_functions(struct cell_context *cell) { cell->pipe.resource_copy_region = util_resource_copy_region; - cell->pipe.resource_fill_region = util_resource_fill_region; } diff --git a/src/gallium/drivers/failover/fo_context.c b/src/gallium/drivers/failover/fo_context.c index 2246c1468c..9c9c1bdc45 100644 --- a/src/gallium/drivers/failover/fo_context.c +++ b/src/gallium/drivers/failover/fo_context.c @@ -146,6 +146,8 @@ struct pipe_context *failover_create( struct pipe_context *hw, failover->pipe.draw_arrays = failover_draw_arrays; failover->pipe.draw_elements = failover_draw_elements; failover->pipe.clear = hw->clear; + failover->pipe.clear_render_target = hw->clear_render_target; + failover->pipe.clear_depth_stencil = hw->clear_depth_stencil; /* No software occlusion fallback (or other optional functionality) * at this point - if the hardware doesn't support it, don't @@ -157,7 +159,6 @@ struct pipe_context *failover_create( struct pipe_context *hw, failover_init_state_functions( failover ); failover->pipe.resource_copy_region = hw->resource_copy_region; - failover->pipe.resource_fill_region = hw->resource_fill_region; #if 0 failover->pipe.texture_create = hw->texture_create; diff --git a/src/gallium/drivers/i915/i915_blit.c b/src/gallium/drivers/i915/i915_blit.c index 6717e46e1b..c5b5979bf9 100644 --- a/src/gallium/drivers/i915/i915_blit.c +++ b/src/gallium/drivers/i915/i915_blit.c @@ -36,6 +36,7 @@ void i915_fill_blit(struct i915_context *i915, unsigned cpp, + unsigned rgba_mask, unsigned short dst_pitch, struct i915_winsys_buffer *dst_buffer, unsigned dst_offset, @@ -62,8 +63,7 @@ i915_fill_blit(struct i915_context *i915, case 4: BR13 = (((int) dst_pitch) & 0xffff) | (0xF0 << 16) | (1 << 24) | (1 << 25); - CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | - XY_COLOR_BLT_WRITE_RGB); + CMD = (XY_COLOR_BLT_CMD | rgba_mask); break; default: return; diff --git a/src/gallium/drivers/i915/i915_blit.h b/src/gallium/drivers/i915/i915_blit.h index 43f8e7c9aa..d82d2f258e 100644 --- a/src/gallium/drivers/i915/i915_blit.h +++ b/src/gallium/drivers/i915/i915_blit.h @@ -44,6 +44,7 @@ extern void i915_copy_blit(struct i915_context *i915, extern void i915_fill_blit(struct i915_context *i915, unsigned cpp, + unsigned rgba_mask, unsigned short dst_pitch, struct i915_winsys_buffer *dst_buffer, unsigned dst_offset, diff --git a/src/gallium/drivers/i915/i915_clear.c b/src/gallium/drivers/i915/i915_clear.c index 0d0859f8f3..6d824a507a 100644 --- a/src/gallium/drivers/i915/i915_clear.c +++ b/src/gallium/drivers/i915/i915_clear.c @@ -40,7 +40,7 @@ */ void i915_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba, - double depth, unsigned stencil) + double depth, unsigned stencil) { util_clear(pipe, &i915_context(pipe)->framebuffer, buffers, rgba, depth, stencil); diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c index 62b064ccf8..f82426520c 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -129,6 +129,9 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: return 0; + case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: + /* disable for now */ + return 0; default: return 0; } @@ -181,6 +184,9 @@ i915_is_format_supported(struct pipe_screen *screen, PIPE_FORMAT_L8A8_UNORM, PIPE_FORMAT_UYVY, PIPE_FORMAT_YUYV, + /* XXX why not? + PIPE_FORMAT_Z16_UNORM, */ + PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_FORMAT_NONE /* list terminator */ }; @@ -190,6 +196,9 @@ i915_is_format_supported(struct pipe_screen *screen, PIPE_FORMAT_NONE /* list terminator */ }; static const enum pipe_format depth_supported[] = { + /* XXX why not? + PIPE_FORMAT_Z16_UNORM, */ + PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_FORMAT_NONE /* list terminator */ }; diff --git a/src/gallium/drivers/i915/i915_state_emit.c b/src/gallium/drivers/i915/i915_state_emit.c index 4d069fffa8..22082fece8 100644 --- a/src/gallium/drivers/i915/i915_state_emit.c +++ b/src/gallium/drivers/i915/i915_state_emit.c @@ -51,6 +51,7 @@ static unsigned translate_format( enum pipe_format format ) static unsigned translate_depth_format( enum pipe_format zformat ) { switch (zformat) { + case PIPE_FORMAT_Z24X8_UNORM: case PIPE_FORMAT_Z24_UNORM_S8_USCALED: return DEPTH_FRMT_24_FIXED_8_OTHER; case PIPE_FORMAT_Z16_UNORM: diff --git a/src/gallium/drivers/i915/i915_state_sampler.c b/src/gallium/drivers/i915/i915_state_sampler.c index 73e61b6624..77b9bccbb7 100644 --- a/src/gallium/drivers/i915/i915_state_sampler.c +++ b/src/gallium/drivers/i915/i915_state_sampler.c @@ -222,6 +222,7 @@ translate_texture_format(enum pipe_format pipeFormat) return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); #endif case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_Z24X8_UNORM: return (MAPSURF_32BIT | MT_32BIT_xI824); default: debug_printf("i915: translate_texture_format() bad image format %x\n", diff --git a/src/gallium/drivers/i915/i915_surface.c b/src/gallium/drivers/i915/i915_surface.c index 41b1fed36d..7869be8f68 100644 --- a/src/gallium/drivers/i915/i915_surface.c +++ b/src/gallium/drivers/i915/i915_surface.c @@ -28,12 +28,14 @@ #include "i915_surface.h" #include "i915_resource.h" #include "i915_blit.h" +#include "i915_reg.h" #include "i915_screen.h" #include "pipe/p_defines.h" #include "util/u_inlines.h" #include "util/u_math.h" #include "util/u_format.h" #include "util/u_memory.h" +#include "util/u_pack_color.h" /* Assumes all values are within bounds -- no checking at this level - @@ -41,11 +43,11 @@ */ static void i915_surface_copy(struct pipe_context *pipe, - struct pipe_resource *dst, struct pipe_subresource subdst, - unsigned dstx, unsigned dsty, unsigned dstz, - struct pipe_resource *src, struct pipe_subresource subsrc, - unsigned srcx, unsigned srcy, unsigned srcz, - unsigned width, unsigned height) + struct pipe_resource *dst, struct pipe_subresource subdst, + unsigned dstx, unsigned dsty, unsigned dstz, + struct pipe_resource *src, struct pipe_subresource subsrc, + unsigned srcx, unsigned srcy, unsigned srcz, + unsigned width, unsigned height) { struct i915_texture *dst_tex = i915_texture(dst); struct i915_texture *src_tex = i915_texture(src); @@ -93,39 +95,67 @@ i915_surface_copy(struct pipe_context *pipe, static void -i915_surface_fill(struct pipe_context *pipe, - struct pipe_resource *dst, struct pipe_subresource subdst, - unsigned dstx, unsigned dsty, unsigned dstz, - unsigned width, unsigned height, unsigned value) +i915_clear_render_target(struct pipe_context *pipe, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) { - struct i915_texture *tex = i915_texture(dst); + struct i915_texture *tex = i915_texture(dst->texture); struct pipe_resource *pt = &tex->b.b; - unsigned dst_offset; /* in bytes */ - - if (dst->target == PIPE_TEXTURE_CUBE) { - dst_offset = tex->image_offset[subdst.level][subdst.face]; - } - else if (dst->target == PIPE_TEXTURE_3D) { - dst_offset = tex->image_offset[subdst.level][dstz]; - } - else { - dst_offset = tex->image_offset[subdst.level][0]; - assert(subdst.face == 0); - assert(dstz == 0); - } + union util_color uc; assert(util_format_get_blockwidth(pt->format) == 1); assert(util_format_get_blockheight(pt->format) == 1); + util_pack_color(rgba, dst->format, &uc); i915_fill_blit( i915_context(pipe), util_format_get_blocksize(pt->format), + XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB, (unsigned short) tex->stride, - tex->buffer, dst_offset, + tex->buffer, dst->offset, (short) dstx, (short) dsty, (short) width, (short) height, - value ); + uc.ui ); } +static void +i915_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 i915_texture *tex = i915_texture(dst->texture); + struct pipe_resource *pt = &tex->b.b; + unsigned packedds; + unsigned mask = 0; + + assert(util_format_get_blockwidth(pt->format) == 1); + assert(util_format_get_blockheight(pt->format) == 1); + + packedds = util_pack_z_stencil(dst->format, depth, stencil); + + if (clear_flags & PIPE_CLEAR_DEPTH) + mask |= XY_COLOR_BLT_WRITE_RGB; + /* XXX presumably this does read-modify-write + (otherwise this won't work anyway). Hence will only want to + do it if really have stencil and it isn't cleared */ + if (!((clear_flags & PIPE_CLEAR_STENCIL) || + (dst->format != PIPE_FORMAT_Z24_UNORM_S8_USCALED))) + mask |= XY_COLOR_BLT_WRITE_ALPHA; + + i915_fill_blit( i915_context(pipe), + util_format_get_blocksize(pt->format), + mask, + (unsigned short) tex->stride, + tex->buffer, dst->offset, + (short) dstx, (short) dsty, + (short) width, (short) height, + packedds ); +} /* * Screen surface functions @@ -179,7 +209,8 @@ void i915_init_surface_functions(struct i915_context *i915) { i915->base.resource_copy_region = i915_surface_copy; - i915->base.resource_fill_region = i915_surface_fill; + i915->base.clear_render_target = i915_clear_render_target; + i915->base.clear_depth_stencil = i915_clear_depth_stencil; } /* No good reason for these to be in the screen. diff --git a/src/gallium/drivers/i965/brw_pipe_clear.c b/src/gallium/drivers/i965/brw_pipe_clear.c index abf507991e..d5cff338a6 100644 --- a/src/gallium/drivers/i965/brw_pipe_clear.c +++ b/src/gallium/drivers/i965/brw_pipe_clear.c @@ -26,6 +26,7 @@ **************************************************************************/ #include "util/u_pack_color.h" +#include "util/u_math.h" #include "pipe/p_state.h" @@ -42,12 +43,12 @@ * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferIndexes field * since that might include software renderbuffers or renderbuffers * which we're clearing with triangles. - * \param mask bitmask of BUFFER_BIT_* values indicating buffers to clear */ static enum pipe_error try_clear( struct brw_context *brw, struct brw_surface *surface, - unsigned value ) + unsigned value, + unsigned rgba_mask) { uint32_t BR13, CMD; int x1 = 0; @@ -67,12 +68,11 @@ try_clear( struct brw_context *brw, x1, y1, x2 - x1, y2 - y1); BR13 = 0xf0 << 16; - CMD = XY_COLOR_BLT_CMD | XY_BLT_WRITE_RGB | XY_BLT_WRITE_ALPHA; + CMD = XY_COLOR_BLT_CMD | rgba_mask; /* Setup the blit command */ if (cpp == 4) { BR13 |= BR13_8888; - CMD |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; } else { assert(cpp == 2); @@ -121,24 +121,36 @@ static void color_clear(struct brw_context *brw, if (bsurface->cpp == 2) value.ui |= value.ui << 16; - ret = try_clear( brw, bsurface, value.ui ); + ret = try_clear( brw, bsurface, value.ui, + XY_BLT_WRITE_RGB | XY_BLT_WRITE_ALPHA ); if (ret != 0) { brw_context_flush( brw ); - ret = try_clear( brw, bsurface, value.ui ); + ret = try_clear( brw, bsurface, value.ui, + XY_BLT_WRITE_RGB | XY_BLT_WRITE_ALPHA ); assert( ret == 0 ); } } -static void zstencil_clear(struct brw_context *brw, +static void zstencil_clear(struct brw_context *brw, struct brw_surface *bsurface, + unsigned clear_flags, double depth, unsigned stencil ) { enum pipe_error ret; unsigned value; + unsigned mask = 0; + union fi tmp; + + if (clear_flags & PIPE_CLEAR_DEPTH) + mask |= XY_BLT_WRITE_RGB; switch (bsurface->base.format) { + case PIPE_FORMAT_Z32_FLOAT: + tmp.f = (float)depth; + value = tmp.ui; + break; case PIPE_FORMAT_Z24X8_UNORM: case PIPE_FORMAT_Z24_UNORM_S8_USCALED: value = ((unsigned)(depth * MASK24) & MASK24); @@ -152,24 +164,31 @@ static void zstencil_clear(struct brw_context *brw, } switch (bsurface->base.format) { + case PIPE_FORMAT_Z32_FLOAT: + mask |= XY_BLT_WRITE_ALPHA; + break; case PIPE_FORMAT_Z24X8_UNORM: + value = value | (stencil << 24); + mask |= XY_BLT_WRITE_ALPHA; + break; case PIPE_FORMAT_Z24_UNORM_S8_USCALED: value = value | (stencil << 24); + if (clear_flags & PIPE_CLEAR_STENCIL) + mask |= XY_BLT_WRITE_ALPHA; break; - case PIPE_FORMAT_Z16_UNORM: value = value | (value << 16); + mask |= XY_BLT_WRITE_ALPHA; break; - default: break; } - ret = try_clear( brw, bsurface, value ); + ret = try_clear( brw, bsurface, value, mask ); if (ret != 0) { brw_context_flush( brw ); - ret = try_clear( brw, bsurface, value ); + ret = try_clear( brw, bsurface, value, mask ); assert( ret == 0 ); } } @@ -201,15 +220,48 @@ static void brw_clear(struct pipe_context *pipe, if (brw->curr.fb.zsbuf) { zstencil_clear( brw, brw_surface(brw->curr.fb.zsbuf), + buffers & PIPE_CLEAR_DEPTHSTENCIL, depth, stencil ); } } } +/* XXX should respect region */ +static void brw_clear_render_target(struct pipe_context *pipe, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct brw_context *brw = brw_context( pipe ); + + color_clear( brw, + brw_surface(dst), + rgba ); +} + +/* XXX should respect region */ +static void brw_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 brw_context *brw = brw_context( pipe ); + + zstencil_clear( brw, + brw_surface(dst), + clear_flags, + depth, stencil ); +} void brw_pipe_clear_init( struct brw_context *brw ) { brw->base.clear = brw_clear; + brw->base.clear_render_target = brw_clear_render_target; + brw->base.clear_depth_stencil = brw_clear_depth_stencil; } diff --git a/src/gallium/drivers/i965/brw_resource.c b/src/gallium/drivers/i965/brw_resource.c index 1efdb1e0b4..3b61ffbd03 100644 --- a/src/gallium/drivers/i965/brw_resource.c +++ b/src/gallium/drivers/i965/brw_resource.c @@ -39,7 +39,6 @@ brw_init_resource_functions(struct brw_context *brw ) brw->base.transfer_destroy = u_transfer_destroy_vtbl; brw->base.transfer_inline_write = u_transfer_inline_write_vtbl; brw->base.resource_copy_region = util_resource_copy_region; - brw->base.resource_fill_region = util_resource_fill_region; } void diff --git a/src/gallium/drivers/i965/brw_screen.c b/src/gallium/drivers/i965/brw_screen.c index 5a45687b09..50a446db91 100644 --- a/src/gallium/drivers/i965/brw_screen.c +++ b/src/gallium/drivers/i965/brw_screen.c @@ -188,6 +188,9 @@ brw_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: return 0; + case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: + /* disable for now */ + return 0; default: return 0; } diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c index 9813170fb1..898e0b3af8 100644 --- a/src/gallium/drivers/identity/id_context.c +++ b/src/gallium/drivers/identity/id_context.c @@ -649,33 +649,6 @@ identity_resource_copy_region(struct pipe_context *_pipe, } static void -identity_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) -{ - struct identity_context *id_pipe = identity_context(_pipe); - struct identity_resource *id_resource_dst = identity_resource(_dst); - struct pipe_context *pipe = id_pipe->pipe; - struct pipe_resource *dst = id_resource_dst->resource; - - pipe->resource_fill_region(pipe, - dst, - subdst, - dstx, - dsty, - dstz, - width, - height, - value); -} - -static void identity_clear(struct pipe_context *_pipe, unsigned buffers, const float *rgba, @@ -693,6 +666,52 @@ identity_clear(struct pipe_context *_pipe, } static void +identity_clear_render_target(struct pipe_context *_pipe, + struct pipe_surface *_dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct identity_surface *id_surface_dst = identity_surface(_dst); + struct pipe_context *pipe = id_pipe->pipe; + struct pipe_surface *dst = id_surface_dst->surface; + + pipe->clear_render_target(pipe, + dst, + rgba, + dstx, + dsty, + width, + height); +} +static void +identity_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 identity_context *id_pipe = identity_context(_pipe); + struct identity_surface *id_surface_dst = identity_surface(_dst); + struct pipe_context *pipe = id_pipe->pipe; + struct pipe_surface *dst = id_surface_dst->surface; + + pipe->clear_depth_stencil(pipe, + dst, + clear_flags, + depth, + stencil, + dstx, + dsty, + width, + height); + +} + +static void identity_flush(struct pipe_context *_pipe, unsigned flags, struct pipe_fence_handle **fence) @@ -913,8 +932,9 @@ identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) id_pipe->base.set_vertex_sampler_views = identity_set_vertex_sampler_views; id_pipe->base.set_vertex_buffers = identity_set_vertex_buffers; id_pipe->base.resource_copy_region = identity_resource_copy_region; - id_pipe->base.resource_fill_region = identity_resource_fill_region; id_pipe->base.clear = identity_clear; + id_pipe->base.clear_render_target = identity_clear_render_target; + id_pipe->base.clear_depth_stencil = identity_clear_depth_stencil; id_pipe->base.flush = identity_flush; id_pipe->base.is_resource_referenced = identity_is_resource_referenced; id_pipe->base.create_sampler_view = identity_context_create_sampler_view; diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index 386387b3a5..50e44dcb2b 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -172,7 +172,7 @@ lp_rast_tile_begin(struct lp_rasterizer_task *task, if (zsbuf) { struct llvmpipe_resource *lpt = llvmpipe_resource(zsbuf->texture); - if (scene->has_depth_clear) + if (scene->has_depthstencil_clear) usage = LP_TEX_USAGE_WRITE_ALL; else usage = LP_TEX_USAGE_READ_WRITE; @@ -264,6 +264,9 @@ lp_rast_clear_zstencil(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { struct lp_rasterizer *rast = task->rast; + const struct lp_rast_clearzs *clearzs = arg.clear_zstencil; + unsigned clear_value = clearzs->clearzs_value; + unsigned clear_mask = clearzs->clearzs_mask; const unsigned height = TILE_SIZE / TILE_VECTOR_HEIGHT; const unsigned width = TILE_SIZE * TILE_VECTOR_HEIGHT; const unsigned block_size = rast->zsbuf.blocksize; @@ -271,7 +274,7 @@ lp_rast_clear_zstencil(struct lp_rasterizer_task *task, uint8_t *dst; unsigned i, j; - LP_DBG(DEBUG_RAST, "%s 0x%x\n", __FUNCTION__, arg.clear_zstencil); + LP_DBG(DEBUG_RAST, "%s 0x%x%x\n", __FUNCTION__, clear_value, clear_mask); /* * Clear the aera of the swizzled depth/depth buffer matching this tile, in @@ -287,22 +290,34 @@ lp_rast_clear_zstencil(struct lp_rasterizer_task *task, switch (block_size) { case 1: - memset(dst, (uint8_t) arg.clear_zstencil, height * width); + memset(dst, (uint8_t) clear_value, height * width); break; case 2: for (i = 0; i < height; i++) { uint16_t *row = (uint16_t *)dst; for (j = 0; j < width; j++) - *row++ = (uint16_t) arg.clear_zstencil; + *row++ = (uint16_t) clear_value; dst += dst_stride; } break; case 4: - for (i = 0; i < height; i++) { - uint32_t *row = (uint32_t *)dst; - for (j = 0; j < width; j++) - *row++ = arg.clear_zstencil; - dst += dst_stride; + if (clear_mask == 0xffffffff) { + for (i = 0; i < height; i++) { + uint32_t *row = (uint32_t *)dst; + for (j = 0; j < width; j++) + *row++ = clear_value; + dst += dst_stride; + } + } + else { + for (i = 0; i < height; i++) { + uint32_t *row = (uint32_t *)dst; + for (j = 0; j < width; j++) { + uint32_t tmp = ~clear_mask & *row; + *row++ = (clear_value & clear_mask) | tmp; + } + dst += dst_stride; + } } break; default: diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h index ff0e3cfc73..80ca68f5a2 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.h +++ b/src/gallium/drivers/llvmpipe/lp_rast.h @@ -88,6 +88,11 @@ struct lp_rast_shader_inputs { PIPE_ALIGN_VAR(16) int step[3][16]; }; +struct lp_rast_clearzs { + unsigned clearzs_value; + unsigned clearzs_mask; +}; + /** * Rasterization information for a triangle known to be in this bin, @@ -151,7 +156,7 @@ union lp_rast_cmd_arg { const struct lp_rast_triangle *triangle; const struct lp_rast_state *set_state; uint8_t clear_color[4]; - unsigned clear_zstencil; + const struct lp_rast_clearzs *clear_zstencil; struct lp_fence *fence; struct llvmpipe_query *query_obj; }; @@ -193,6 +198,14 @@ lp_rast_arg_fence( struct lp_fence *fence ) static INLINE union lp_rast_cmd_arg +lp_rast_arg_clearzs( const struct lp_rast_clearzs *clearzs ) +{ + union lp_rast_cmd_arg arg; + arg.clear_zstencil = clearzs; + return arg; +} + +static INLINE union lp_rast_cmd_arg lp_rast_arg_null( void ) { union lp_rast_cmd_arg arg; @@ -201,7 +214,6 @@ lp_rast_arg_null( void ) } - /** * Binnable Commands. * These get put into bins by the setup code and are called when diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c index 59e4c18ad0..845c175cf2 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.c +++ b/src/gallium/drivers/llvmpipe/lp_scene.c @@ -201,7 +201,7 @@ lp_scene_reset(struct lp_scene *scene ) scene->scene_size = 0; scene->has_color_clear = FALSE; - scene->has_depth_clear = FALSE; + scene->has_depthstencil_clear = FALSE; } diff --git a/src/gallium/drivers/llvmpipe/lp_scene.h b/src/gallium/drivers/llvmpipe/lp_scene.h index 22d619fdbc..4e55d43174 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.h +++ b/src/gallium/drivers/llvmpipe/lp_scene.h @@ -125,7 +125,7 @@ struct lp_scene { unsigned scene_size; boolean has_color_clear; - boolean has_depth_clear; + boolean has_depthstencil_clear; /** * Number of active tiles in each dimension. diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index 98ac11d76a..2fc5d6ecff 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -162,6 +162,8 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_MAX_VS_PREDS: case PIPE_CAP_MAX_FS_PREDS: return LP_MAX_TGSI_PREDS; + case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: + return 1; default: assert(0); return 0; diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index bdb40a2d4b..8556dc87b4 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -143,6 +143,7 @@ static void reset_context( struct lp_setup_context *setup ) /* Reset some state: */ setup->clear.flags = 0; + setup->clear.clearzs.clearzs_mask = 0; /* Have an explicit "start-binning" call and get rid of this * pointer twiddling? @@ -172,10 +173,15 @@ static void begin_binning( struct lp_setup_context *setup ) { struct lp_scene *scene = lp_setup_get_current_scene(setup); + boolean need_zsload = FALSE; + if (setup->fb.zsbuf && + ((setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && + util_format_is_depth_and_stencil(setup->fb.zsbuf->format)) + need_zsload = TRUE; LP_DBG(DEBUG_SETUP, "%s color: %s depth: %s\n", __FUNCTION__, (setup->clear.flags & PIPE_CLEAR_COLOR) ? "clear": "load", - (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) ? "clear": "load"); + need_zsload ? "clear": "load"); if (setup->fb.nr_cbufs) { if (setup->clear.flags & PIPE_CLEAR_COLOR) { @@ -188,10 +194,11 @@ begin_binning( struct lp_setup_context *setup ) if (setup->fb.zsbuf) { if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) { - lp_scene_bin_everywhere( scene, - lp_rast_clear_zstencil, - setup->clear.zstencil ); - scene->has_depth_clear = TRUE; + if (!need_zsload) + scene->has_depthstencil_clear = TRUE; + lp_scene_bin_everywhere( scene, + lp_rast_clear_zstencil, + lp_rast_arg_clearzs(&setup->clear.clearzs) ); } } @@ -306,6 +313,8 @@ lp_setup_clear( struct lp_setup_context *setup, { struct lp_scene *scene = lp_setup_get_current_scene(setup); unsigned i; + boolean full_zs_clear = TRUE; + uint32_t mask = 0; LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); @@ -316,10 +325,53 @@ lp_setup_clear( struct lp_setup_context *setup, } if (flags & PIPE_CLEAR_DEPTHSTENCIL) { - setup->clear.zstencil.clear_zstencil = - util_pack_z_stencil(setup->fb.zsbuf->format, - depth, - stencil); + if (setup->fb.zsbuf && + ((setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && + util_format_is_depth_and_stencil(setup->fb.zsbuf->format)) + full_zs_clear = FALSE; + + if (full_zs_clear) { + setup->clear.clearzs.clearzs_value = + util_pack_z_stencil(setup->fb.zsbuf->format, + depth, + stencil); + setup->clear.clearzs.clearzs_mask = 0xffffffff; + } + else { + /* hmm */ + uint32_t tmpval; + if (flags & PIPE_CLEAR_DEPTH) { + tmpval = util_pack_z(setup->fb.zsbuf->format, + depth); + switch (setup->fb.zsbuf->format) { + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + mask = 0xffffff; + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + mask = 0xffffff00; + break; + default: + assert(0); + } + } + else { + switch (setup->fb.zsbuf->format) { + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + mask = 0xff000000; + tmpval = stencil << 24; + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + mask = 0xff; + tmpval = stencil; + break; + default: + assert(0); + } + } + setup->clear.clearzs.clearzs_mask |= mask; + setup->clear.clearzs.clearzs_value = + (setup->clear.clearzs.clearzs_value & ~mask) | (tmpval & mask); + } } if (setup->state == SETUP_ACTIVE) { @@ -336,11 +388,16 @@ lp_setup_clear( struct lp_setup_context *setup, scene->has_color_clear = TRUE; } - if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) { - lp_scene_bin_everywhere( scene, + if (flags & PIPE_CLEAR_DEPTHSTENCIL) { + if (full_zs_clear) + scene->has_depthstencil_clear = TRUE; + else + setup->clear.clearzs.clearzs_mask = mask; + lp_scene_bin_everywhere( scene, lp_rast_clear_zstencil, - setup->clear.zstencil ); - scene->has_depth_clear = TRUE; + lp_rast_arg_clearzs(&setup->clear.clearzs) ); + + } } diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h index 584764ce8a..c8b8a2480b 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_context.h +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h @@ -97,7 +97,7 @@ struct lp_setup_context struct { unsigned flags; union lp_rast_cmd_arg color; /**< lp_rast_clear_color() cmd */ - union lp_rast_cmd_arg zstencil; /**< lp_rast_clear_zstencil() cmd */ + struct lp_rast_clearzs clearzs; /**< lp_rast_clear_zstencil() cmd */ } clear; enum setup_state { diff --git a/src/gallium/drivers/llvmpipe/lp_surface.c b/src/gallium/drivers/llvmpipe/lp_surface.c index 85687ada1c..4f409f9b63 100644 --- a/src/gallium/drivers/llvmpipe/lp_surface.c +++ b/src/gallium/drivers/llvmpipe/lp_surface.c @@ -153,5 +153,4 @@ void llvmpipe_init_surface_functions(struct llvmpipe_context *lp) { lp->pipe.resource_copy_region = lp_resource_copy; - lp->pipe.resource_fill_region = util_resource_fill_region; } diff --git a/src/gallium/drivers/nv50/nv50_clear.c b/src/gallium/drivers/nv50/nv50_clear.c index 5447904e9c..ee7cf281f4 100644 --- a/src/gallium/drivers/nv50/nv50_clear.c +++ b/src/gallium/drivers/nv50/nv50_clear.c @@ -51,13 +51,15 @@ nv50_clear(struct pipe_context *pipe, unsigned buffers, mode |= 0x3c; } - if (buffers & PIPE_CLEAR_DEPTHSTENCIL) { + if (buffers & PIPE_CLEAR_DEPTH) { BEGIN_RING(chan, tesla, NV50TCL_CLEAR_DEPTH, 1); OUT_RING (chan, fui(depth)); + mode |= NV50TCL_CLEAR_BUFFERS_Z; + } + if (buffers & PIPE_CLEAR_STENCIL) { BEGIN_RING(chan, tesla, NV50TCL_CLEAR_STENCIL, 1); OUT_RING (chan, stencil & 0xff); - - mode |= 0x03; + mode |= NV50TCL_CLEAR_BUFFERS_S; } BEGIN_RING(chan, tesla, NV50TCL_CLEAR_BUFFERS, 1); diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index 2c0caada36..21908bcd3c 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -150,6 +150,8 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return 1; case PIPE_CAP_INDEP_BLEND_FUNC: return 0; + case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: + return 1; case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: return 1; diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c index 40b8d25533..5535610e0a 100644 --- a/src/gallium/drivers/nv50/nv50_surface.c +++ b/src/gallium/drivers/nv50/nv50_surface.c @@ -27,6 +27,7 @@ #include "nv50_resource.h" #include "pipe/p_defines.h" #include "util/u_inlines.h" +#include "util/u_pack_color.h" #include "util/u_tile.h" #include "util/u_format.h" @@ -221,50 +222,49 @@ nv50_surface_copy(struct pipe_context *pipe, nv50_miptree_surface_del(ps_dst); } +/* XXX this should probably look more along the lines of nv50_clear */ static void -nv50_surface_fill(struct pipe_context *pipe, struct pipe_resource *dest, - struct pipe_subresource subdst, - unsigned destx, unsigned desty, unsigned destz, - unsigned width, unsigned height, unsigned value) +nv50_clear_render_target(struct pipe_context *pipe, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) { struct nv50_context *nv50 = nv50_context(pipe); - struct pipe_surface *ps; struct nv50_screen *screen = nv50->screen; struct nouveau_channel *chan = screen->eng2d->channel; struct nouveau_grobj *eng2d = screen->eng2d; int format, ret; + union util_color uc; + util_pack_color(rgba, dst->format, &uc); - format = nv50_format(dest->format); + format = nv50_format(dst->format); if (format < 0) return; - ps = nv50_miptree_surface_new(pipe->screen, dest, subdst.face, - subdst.level, destz, 0 /* bind flags */); - WAIT_RING (chan, 32); - ret = nv50_surface_set(screen, ps, 1); + ret = nv50_surface_set(screen, dst, 1); if (ret) return; BEGIN_RING(chan, eng2d, NV50_2D_DRAW_SHAPE, 3); OUT_RING (chan, NV50_2D_DRAW_SHAPE_RECTANGLES); OUT_RING (chan, format); - OUT_RING (chan, value); + OUT_RING (chan, uc.ui); BEGIN_RING(chan, eng2d, NV50_2D_DRAW_POINT32_X(0), 4); - OUT_RING (chan, destx); - OUT_RING (chan, desty); + OUT_RING (chan, dstx); + OUT_RING (chan, dsty); OUT_RING (chan, width); OUT_RING (chan, height); - nv50_miptree_surface_del(ps); } void nv50_init_surface_functions(struct nv50_context *nv50) { nv50->pipe.resource_copy_region = nv50_surface_copy; - nv50->pipe.resource_fill_region = nv50_surface_fill; + nv50->pipe.clear_render_target = nv50_clear_render_target; } diff --git a/src/gallium/drivers/nvfx/nvfx_screen.c b/src/gallium/drivers/nvfx/nvfx_screen.c index 7e534a0c73..a78d2411a0 100644 --- a/src/gallium/drivers/nvfx/nvfx_screen.c +++ b/src/gallium/drivers/nvfx/nvfx_screen.c @@ -80,6 +80,8 @@ nvfx_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return 0; case PIPE_CAP_INDEP_BLEND_FUNC: return 0; + case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: + return 0; case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: return 1; diff --git a/src/gallium/drivers/nvfx/nvfx_surface.c b/src/gallium/drivers/nvfx/nvfx_surface.c index fc3a670d40..44e1af2e6a 100644 --- a/src/gallium/drivers/nvfx/nvfx_surface.c +++ b/src/gallium/drivers/nvfx/nvfx_surface.c @@ -30,6 +30,7 @@ #include "nvfx_resource.h" #include "pipe/p_defines.h" #include "util/u_inlines.h" +#include "util/u_pack_color.h" static void nvfx_surface_copy(struct pipe_context *pipe, @@ -55,26 +56,41 @@ nvfx_surface_copy(struct pipe_context *pipe, } static void -nvfx_surface_fill(struct pipe_context *pipe, struct pipe_resource *dest, - struct pipe_subresource subdst, - unsigned destx, unsigned desty, unsigned destz, - unsigned width, unsigned height, unsigned value) +nvfx_clear_render_target(struct pipe_context *pipe, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) { struct nvfx_context *nvfx = nvfx_context(pipe); - struct pipe_surface *ps; struct nv04_surface_2d *eng2d = nvfx->screen->eng2d; + union util_color uc; + util_pack_color(rgba, dst->format, &uc); + + eng2d->fill(eng2d, dst, dstx, dsty, width, height, uc.ui); +} - ps = nvfx_miptree_surface_new(pipe->screen, dest, subdst.face, - subdst.level, destz, 0 /* bind flags */); - - eng2d->fill(eng2d, ps, destx, desty, width, height, value); +static void +nvfx_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 nvfx_context *nvfx = nvfx_context(pipe); + struct nv04_surface_2d *eng2d = nvfx->screen->eng2d; - nvfx_miptree_surface_del(ps); + eng2d->fill(eng2d, dst, dstx, dsty, width, height, + util_pack_z_stencil(dst->format, depth, stencil)); } + void nvfx_init_surface_functions(struct nvfx_context *nvfx) { nvfx->pipe.resource_copy_region = nvfx_surface_copy; - nvfx->pipe.resource_fill_region = nvfx_surface_fill; + nvfx->pipe.clear_render_target = nvfx_clear_render_target; + nvfx->pipe.clear_depth_stencil = nvfx_clear_depth_stencil; } diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index 66ca4e0c18..49ec51fd13 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -188,26 +188,44 @@ static void r300_resource_copy_region(struct pipe_context *pipe, } } -/* Fill a region of a surface with a constant value. */ -static void r300_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) +/* 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_fill_region(r300->blitter, dst, subdst, - dstx, dsty, dstz, width, height, value); + 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; + r300->context.clear_render_target = r300_clear_render_target; + r300->context.clear_depth_stencil = r300_clear_depth_stencil; r300->context.resource_copy_region = r300_resource_copy_region; - r300->context.resource_fill_region = r300_resource_fill_region; } diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 0be11ad017..e7db074be6 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -147,6 +147,9 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_MAX_CONST_BUFFER_SIZE: return 256; + case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: + return 1; + /* Fragment coordinate conventions. */ case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: diff --git a/src/gallium/drivers/rbug/rbug_context.c b/src/gallium/drivers/rbug/rbug_context.c index bb7d13bfcd..164d811ab4 100644 --- a/src/gallium/drivers/rbug/rbug_context.c +++ b/src/gallium/drivers/rbug/rbug_context.c @@ -800,33 +800,6 @@ rbug_resource_copy_region(struct pipe_context *_pipe, } static void -rbug_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) -{ - struct rbug_context *rb_pipe = rbug_context(_pipe); - struct rbug_resource *rb_resource_dst = rbug_resource(_dst); - struct pipe_context *pipe = rb_pipe->pipe; - struct pipe_resource *dst = rb_resource_dst->resource; - - pipe->resource_fill_region(pipe, - dst, - subdst, - dstx, - dsty, - dstz, - width, - height, - value); -} - -static void rbug_clear(struct pipe_context *_pipe, unsigned buffers, const float *rgba, @@ -844,6 +817,52 @@ rbug_clear(struct pipe_context *_pipe, } static void +rbug_clear_render_target(struct pipe_context *_pipe, + struct pipe_surface *_dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_surface *rb_surface_dst = rbug_surface(_dst); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_surface *dst = rb_surface_dst->surface; + + pipe->clear_render_target(pipe, + dst, + rgba, + dstx, + dsty, + width, + height); +} + +static void +rbug_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 rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_surface *rb_surface_dst = rbug_surface(_dst); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_surface *dst = rb_surface_dst->surface; + + pipe->clear_depth_stencil(pipe, + dst, + clear_flags, + depth, + stencil, + dstx, + dsty, + width, + height); +} + +static void rbug_flush(struct pipe_context *_pipe, unsigned flags, struct pipe_fence_handle **fence) @@ -1075,8 +1094,9 @@ rbug_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) rb_pipe->base.set_vertex_buffers = rbug_set_vertex_buffers; rb_pipe->base.set_sample_mask = rbug_set_sample_mask; rb_pipe->base.resource_copy_region = rbug_resource_copy_region; - rb_pipe->base.resource_fill_region = rbug_resource_fill_region; rb_pipe->base.clear = rbug_clear; + rb_pipe->base.clear_render_target = rbug_clear_render_target; + rb_pipe->base.clear_depth_stencil = rbug_clear_depth_stencil; rb_pipe->base.flush = rbug_flush; rb_pipe->base.is_resource_referenced = rbug_is_resource_referenced; rb_pipe->base.create_sampler_view = rbug_context_create_sampler_view; diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index bad5702852..cb59040395 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -143,6 +143,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_MAX_FS_PREDS: return TGSI_EXEC_NUM_PREDS; + case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: + return 0; default: return 0; } diff --git a/src/gallium/drivers/softpipe/sp_surface.c b/src/gallium/drivers/softpipe/sp_surface.c index 0296c26ad2..99433f7d1d 100644 --- a/src/gallium/drivers/softpipe/sp_surface.c +++ b/src/gallium/drivers/softpipe/sp_surface.c @@ -33,5 +33,4 @@ void sp_init_surface_functions(struct softpipe_context *sp) { sp->pipe.resource_copy_region = util_resource_copy_region; - sp->pipe.resource_fill_region = util_resource_fill_region; } diff --git a/src/gallium/drivers/svga/svga_pipe_blit.c b/src/gallium/drivers/svga/svga_pipe_blit.c index 2dd99b4631..e742fec4a2 100644 --- a/src/gallium/drivers/svga/svga_pipe_blit.c +++ b/src/gallium/drivers/svga/svga_pipe_blit.c @@ -108,5 +108,4 @@ void svga_init_blit_functions(struct svga_context *svga) { svga->pipe.resource_copy_region = svga_surface_copy; - svga->pipe.resource_fill_region = util_resource_fill_region; } diff --git a/src/gallium/drivers/svga/svga_pipe_clear.c b/src/gallium/drivers/svga/svga_pipe_clear.c index cbff95c917..41f239c1a8 100644 --- a/src/gallium/drivers/svga/svga_pipe_clear.c +++ b/src/gallium/drivers/svga/svga_pipe_clear.c @@ -61,9 +61,11 @@ try_clear(struct svga_context *svga, } if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && fb->zsbuf) { - flags |= SVGA3D_CLEAR_DEPTH; + if (buffers & PIPE_CLEAR_DEPTH) + flags |= SVGA3D_CLEAR_DEPTH; - if (svga->curr.framebuffer.zsbuf->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM) + if ((svga->curr.framebuffer.zsbuf->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM) && + (buffers & PIPE_CLEAR_STENCIL)) flags |= SVGA3D_CLEAR_STENCIL; rect.w = MAX2(rect.w, fb->zsbuf->width); @@ -100,7 +102,7 @@ svga_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba, { struct svga_context *svga = svga_context( pipe ); int ret; - + if (buffers & PIPE_CLEAR_COLOR) SVGA_DBG(DEBUG_DMA, "clear sid %p\n", svga_surface(svga->curr.framebuffer.cbufs[0])->handle); diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c index 3de04d05f8..54d9faeb72 100644 --- a/src/gallium/drivers/svga/svga_screen.c +++ b/src/gallium/drivers/svga/svga_screen.c @@ -230,6 +230,9 @@ svga_get_paramf(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_MAX_VS_PREDS: return svgascreen->use_vs30 ? 1 : 0; + case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: + return 1; + default: return 0; } diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c index 344a50b462..9ca916fe7b 100644 --- a/src/gallium/drivers/trace/tr_context.c +++ b/src/gallium/drivers/trace/tr_context.c @@ -1085,61 +1085,88 @@ trace_context_resource_copy_region(struct pipe_context *_pipe, static INLINE void -trace_context_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) +trace_context_clear(struct pipe_context *_pipe, + unsigned buffers, + const float *rgba, + double depth, + unsigned stencil) { struct trace_context *tr_ctx = trace_context(_pipe); struct pipe_context *pipe = tr_ctx->pipe; - dst = trace_resource_unwrap(tr_ctx, dst); + trace_dump_call_begin("pipe_context", "clear"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, buffers); + trace_dump_arg_array(float, rgba, 4); + trace_dump_arg(float, depth); + trace_dump_arg(uint, stencil); + + pipe->clear(pipe, buffers, rgba, depth, stencil); + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_clear_render_target(struct pipe_context *_pipe, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; - trace_dump_call_begin("pipe_context", "resource_fill_region"); + dst = trace_surface_unwrap(tr_ctx, dst); + + trace_dump_call_begin("pipe_context", "clear_render_target"); trace_dump_arg(ptr, pipe); trace_dump_arg(ptr, dst); - trace_dump_arg_struct(subresource, subdst); + trace_dump_arg_array(float, rgba, 4); trace_dump_arg(uint, dstx); trace_dump_arg(uint, dsty); - trace_dump_arg(uint, dstz); trace_dump_arg(uint, width); trace_dump_arg(uint, height); - trace_dump_arg(uint, value); - pipe->resource_fill_region(pipe, dst, subdst, dstx, dsty, dstz, - width, height, value); + pipe->clear_render_target(pipe, dst, rgba, dstx, dsty, width, height); trace_dump_call_end(); } - static INLINE void -trace_context_clear(struct pipe_context *_pipe, - unsigned buffers, - const float *rgba, - double depth, - unsigned stencil) +trace_context_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 trace_context *tr_ctx = trace_context(_pipe); struct pipe_context *pipe = tr_ctx->pipe; - trace_dump_call_begin("pipe_context", "clear"); + dst = trace_surface_unwrap(tr_ctx, dst); + + trace_dump_call_begin("pipe_context", "clear_depth_stencil"); trace_dump_arg(ptr, pipe); - trace_dump_arg(uint, buffers); - trace_dump_arg_array(float, rgba, 4); + trace_dump_arg(ptr, dst); + trace_dump_arg(uint, clear_flags); trace_dump_arg(float, depth); trace_dump_arg(uint, stencil); + trace_dump_arg(uint, dstx); + trace_dump_arg(uint, dsty); + trace_dump_arg(uint, width); + trace_dump_arg(uint, height); - pipe->clear(pipe, buffers, rgba, depth, stencil); + pipe->clear_depth_stencil(pipe, dst, clear_flags, depth, stencil, + dstx, dsty, width, height); trace_dump_call_end(); } - static INLINE void trace_context_flush(struct pipe_context *_pipe, unsigned flags, @@ -1451,8 +1478,9 @@ trace_context_create(struct trace_screen *tr_scr, tr_ctx->base.sampler_view_destroy = trace_sampler_view_destroy; tr_ctx->base.set_vertex_buffers = trace_context_set_vertex_buffers; tr_ctx->base.resource_copy_region = trace_context_resource_copy_region; - tr_ctx->base.resource_fill_region = trace_context_resource_fill_region; tr_ctx->base.clear = trace_context_clear; + tr_ctx->base.clear_render_target = trace_context_clear_render_target; + tr_ctx->base.clear_depth_stencil = trace_context_clear_depth_stencil; tr_ctx->base.flush = trace_context_flush; tr_ctx->base.is_resource_referenced = trace_is_resource_referenced; diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index 6b72983176..3e082bef2f 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -257,17 +257,6 @@ struct pipe_context { unsigned width, unsigned height); /** - * Fill a region of a resource with a constant value. - * Resources with nr_samples > 1 are not allowed. - */ - void (*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); - - /** * Resolve a multisampled resource into a non-multisampled one. * Source and destination must have the same size and same format. */ @@ -290,9 +279,33 @@ struct pipe_context { */ void (*clear)(struct pipe_context *pipe, unsigned buffers, - const float *rgba, + const float *rgba, double depth, - unsigned stencil); + unsigned stencil); + + /** + * Clear a color rendertarget surface. + * \param rgba pointer to an array of one float for each of r, g, b, a. + */ + void (*clear_render_target)(struct pipe_context *pipe, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height); + + /** + * Clear a depth-stencil surface. + * \param clear_flags bitfield of PIPE_CLEAR_DEPTH/STENCIL values. + * \param depth depth clear value in [0,1]. + * \param stencil stencil clear value + */ + void (*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); /** Flush rendering * \param flags bitmask of PIPE_FLUSH_x tokens) diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index b54a6ef824..420649c5a9 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -189,9 +189,10 @@ enum pipe_texture_target { */ /** All color buffers currently bound */ #define PIPE_CLEAR_COLOR (1 << 0) +#define PIPE_CLEAR_DEPTH (1 << 1) +#define PIPE_CLEAR_STENCIL (1 << 2) /** Depth/stencil combined */ -#define PIPE_CLEAR_DEPTHSTENCIL (1 << 1) - +#define PIPE_CLEAR_DEPTHSTENCIL (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL) /** * Transfer object usage flags @@ -453,6 +454,7 @@ enum pipe_cap { PIPE_CAP_INDEP_BLEND_ENABLE, /** different blend funcs per rendertarget */ PIPE_CAP_INDEP_BLEND_FUNC, + PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE, PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT, PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER, diff --git a/src/gallium/state_trackers/python/p_context.i b/src/gallium/state_trackers/python/p_context.i index ff792279d2..cf0144b5dc 100644 --- a/src/gallium/state_trackers/python/p_context.i +++ b/src/gallium/state_trackers/python/p_context.i @@ -428,15 +428,42 @@ error1: width, height); } - void resource_fill_region(struct pipe_resource *dst, - struct pipe_subresource subdst, - unsigned dstx, unsigned dsty, unsigned dstz, - unsigned width, unsigned height, - unsigned value) + + void clear_render_target(struct st_surface *dst, + float *rgba, + unsigned x, unsigned y, + unsigned width, unsigned height) { - $self->pipe->resource_fill_region($self->pipe, - dst, subdst, dstx, dsty, dstz, - width, height, value); + struct pipe_surface *_dst = NULL; + + _dst = st_pipe_surface(dst, PIPE_BIND_RENDER_TARGET); + if(!_dst) + SWIG_exception(SWIG_ValueError, "couldn't acquire destination surface for writing"); + + $self->pipe->clear_render_target($self->pipe, _dst, rgba, x, y, width, height); + + fail: + pipe_surface_reference(&_dst, NULL); + } + + void clear_depth_stencil(struct st_surface *dst, + unsigned clear_flags, + double depth, + unsigned stencil, + unsigned x, unsigned y, + unsigned width, unsigned height) + { + struct pipe_surface *_dst = NULL; + + _dst = st_pipe_surface(dst, PIPE_BIND_DEPTH_STENCIL); + if(!_dst) + SWIG_exception(SWIG_ValueError, "couldn't acquire destination surface for writing"); + + $self->pipe->clear_depth_stencil($self->pipe, _dst, clear_flags, depth, stencil, + x, y, width, height); + + fail: + pipe_surface_reference(&_dst, NULL); } %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1)); diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index 7e3b87351f..a819d30530 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -62,10 +62,12 @@ void st_init_clear(struct st_context *st) { struct pipe_context *pipe = st->pipe; + struct pipe_screen *pscreen = st->pipe->screen; memset(&st->clear, 0, sizeof(st->clear)); st->clear.raster.gl_rasterization_rules = 1; + st->clear.enable_ds_separate = pscreen->get_param(pscreen, PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE); /* fragment shader state: color pass-through program */ st->clear.fs = util_make_fragment_passthrough_shader(pipe); @@ -365,7 +367,8 @@ check_clear_depth_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) * Determine if we need to clear the depth buffer by drawing a quad. */ static INLINE GLboolean -check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) +check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb, + boolean ds_separate) { const struct st_renderbuffer *strb = st_renderbuffer(rb); const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format); @@ -377,7 +380,7 @@ check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) ctx->Scissor.Height < rb->Height)) return GL_TRUE; - if (isDS && ctx->DrawBuffer->Visual.stencilBits > 0) + if (!ds_separate && isDS && ctx->DrawBuffer->Visual.stencilBits > 0) return GL_TRUE; return GL_FALSE; @@ -388,7 +391,8 @@ check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) * Determine if we need to clear the stencil buffer by drawing a quad. */ static INLINE GLboolean -check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) +check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb, + boolean ds_separate) { const struct st_renderbuffer *strb = st_renderbuffer(rb); const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format); @@ -415,7 +419,7 @@ check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) * rather than taking depth and stencil clear values from the * current state. */ - if (isDS && ctx->DrawBuffer->Visual.depthBits > 0) + if (!ds_separate && isDS && ctx->DrawBuffer->Visual.depthBits > 0) return GL_TRUE; return GL_FALSE; @@ -495,24 +499,27 @@ st_Clear(GLcontext *ctx, GLbitfield mask) } else { /* separate depth/stencil clears */ + /* I don't think truly separate buffers are actually possible in gallium or hw? */ if (mask & BUFFER_BIT_DEPTH) { struct st_renderbuffer *strb = st_renderbuffer(depthRb); if (strb->surface) { - if (check_clear_depth_with_quad(ctx, depthRb)) - quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + if (check_clear_depth_with_quad(ctx, depthRb, + st->clear.enable_ds_separate)) + quad_buffers |= PIPE_CLEAR_DEPTH; else - clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + clear_buffers |= PIPE_CLEAR_DEPTH; } } if (mask & BUFFER_BIT_STENCIL) { struct st_renderbuffer *strb = st_renderbuffer(stencilRb); if (strb->surface) { - if (check_clear_stencil_with_quad(ctx, stencilRb)) - quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + if (check_clear_stencil_with_quad(ctx, stencilRb, + st->clear.enable_ds_separate)) + quad_buffers |= PIPE_CLEAR_STENCIL; else - clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + clear_buffers |= PIPE_CLEAR_STENCIL; } } } @@ -525,12 +532,22 @@ st_Clear(GLcontext *ctx, GLbitfield mask) quad_buffers |= clear_buffers; clear_with_quad(ctx, quad_buffers & PIPE_CLEAR_COLOR, - mask & BUFFER_BIT_DEPTH, - mask & BUFFER_BIT_STENCIL); - } else if (clear_buffers) + quad_buffers & PIPE_CLEAR_DEPTH, + quad_buffers & PIPE_CLEAR_STENCIL); + } else if (clear_buffers) { + /* driver cannot know it can clear everything if the buffer + * is a combined depth/stencil buffer but this wasn't actually + * required from the visual. Hence fix this up to avoid potential + * read-modify-write in the driver. + */ + if (((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && + (depthRb == stencilRb) && + (ctx->DrawBuffer->Visual.depthBits == 0 || + ctx->DrawBuffer->Visual.stencilBits == 0)) + clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; st->pipe->clear(st->pipe, clear_buffers, ctx->Color.ClearColor, ctx->Depth.Clear, ctx->Stencil.Clear); - + } if (mask & BUFFER_BIT_ACCUM) st_clear_accum_buffer(ctx, ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer); diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index a578143abc..efff55a905 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -175,6 +175,7 @@ struct st_context float vertices[4][2][4]; /**< vertex pos + color */ struct pipe_resource *vbuf; unsigned vbuf_slot; + boolean enable_ds_separate; } clear; /** used for anything using util_draw_vertex_buffer */ |