summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Scheidegger <sroland@vmware.com>2010-06-03 17:46:14 +0200
committerRoland Scheidegger <sroland@vmware.com>2010-06-03 17:46:14 +0200
commit992382762a74fd834926fd2c3cd9e14a186e2dd5 (patch)
treec4572bb01331b71931b3570b36a7acfc38f79a68
parent05863c487756c1c9dc823cf639f77cad4111bd23 (diff)
parenta6e5c6c000df8655de3b41d5809547bb41c88c23 (diff)
Merge branch 'gallium-newclear'
Conflicts: src/gallium/state_trackers/python/p_context.i
-rw-r--r--src/gallium/auxiliary/util/u_blitter.c126
-rw-r--r--src/gallium/auxiliary/util/u_blitter.h31
-rw-r--r--src/gallium/auxiliary/util/u_clear.h27
-rw-r--r--src/gallium/auxiliary/util/u_surface.c52
-rw-r--r--src/gallium/auxiliary/util/u_surface.h10
-rw-r--r--src/gallium/docs/d3d11ddi.txt2
-rw-r--r--src/gallium/docs/source/context.rst27
-rw-r--r--src/gallium/drivers/cell/ppu/cell_surface.c1
-rw-r--r--src/gallium/drivers/failover/fo_context.c3
-rw-r--r--src/gallium/drivers/i915/i915_blit.c4
-rw-r--r--src/gallium/drivers/i915/i915_blit.h1
-rw-r--r--src/gallium/drivers/i915/i915_clear.c2
-rw-r--r--src/gallium/drivers/i915/i915_screen.c9
-rw-r--r--src/gallium/drivers/i915/i915_state_emit.c1
-rw-r--r--src/gallium/drivers/i915/i915_state_sampler.c1
-rw-r--r--src/gallium/drivers/i915/i915_surface.c83
-rw-r--r--src/gallium/drivers/i965/brw_pipe_clear.c74
-rw-r--r--src/gallium/drivers/i965/brw_resource.c1
-rw-r--r--src/gallium/drivers/i965/brw_screen.c3
-rw-r--r--src/gallium/drivers/identity/id_context.c76
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.c33
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.h16
-rw-r--r--src/gallium/drivers/llvmpipe/lp_scene.c2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_scene.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_screen.c2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.c83
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_context.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_surface.c1
-rw-r--r--src/gallium/drivers/nv50/nv50_clear.c8
-rw-r--r--src/gallium/drivers/nv50/nv50_screen.c2
-rw-r--r--src/gallium/drivers/nv50/nv50_surface.c30
-rw-r--r--src/gallium/drivers/nvfx/nvfx_screen.c2
-rw-r--r--src/gallium/drivers/nvfx/nvfx_surface.c38
-rw-r--r--src/gallium/drivers/r300/r300_blit.c38
-rw-r--r--src/gallium/drivers/r300/r300_screen.c3
-rw-r--r--src/gallium/drivers/rbug/rbug_context.c76
-rw-r--r--src/gallium/drivers/softpipe/sp_screen.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_surface.c1
-rw-r--r--src/gallium/drivers/svga/svga_pipe_blit.c1
-rw-r--r--src/gallium/drivers/svga/svga_pipe_clear.c8
-rw-r--r--src/gallium/drivers/svga/svga_screen.c3
-rw-r--r--src/gallium/drivers/trace/tr_context.c78
-rw-r--r--src/gallium/include/pipe/p_context.h39
-rw-r--r--src/gallium/include/pipe/p_defines.h6
-rw-r--r--src/gallium/state_trackers/python/p_context.i43
-rw-r--r--src/mesa/state_tracker/st_cb_clear.c45
-rw-r--r--src/mesa/state_tracker/st_context.h1
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 */