/**
* @file
- * Blitter utility to facilitate acceleration of the clear, resource_copy_region,
- * and resource_fill_region functions.
+ * Blitter utility to facilitate acceleration of the clear, clearRT, clearDS
+ * resource_copy_region functions.
*
* @author Marek Olšák
*/
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;
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;
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);
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);
pipe_surface_reference(&dstsurf, NULL);
}
-/* Fill a region of a surface with a constant value. */
-void util_blitter_fill_region(struct blitter_context *blitter,
- struct pipe_resource *dst,
- struct pipe_subresource subdst,
- unsigned dstx, unsigned dsty, unsigned dstz,
- unsigned width, unsigned height,
- unsigned value)
+/* Clear a region of a color surface to a constant value. */
+void util_blitter_clearRT(struct blitter_context *blitter,
+ struct pipe_surface *dstsurf,
+ const float *rgba,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->pipe;
- struct pipe_screen *screen = pipe->screen;
- struct pipe_surface *dstsurf;
struct pipe_framebuffer_state fb_state;
- float rgba[4];
- ubyte ub_rgba[4] = {0};
- union util_color color;
- int i;
- assert(dst);
- if (!dst)
+ assert(dstsurf->texture);
+ if (!dstsurf->texture)
return;
- /* check if we can render to the surface */
- if (util_format_is_depth_or_stencil(dst->format) || /* unlikely, but you never know */
- !screen->is_format_supported(screen, dst->format, dst->target,
- dst->nr_samples,
- PIPE_BIND_RENDER_TARGET, 0)) {
- util_resource_fill_region(pipe, dst, subdst, dstx, dsty, dstz,
- width, height, value);
- return;
- }
-
- dstsurf = screen->get_tex_surface(screen, dst, subdst.face, subdst.level,
- dstz, PIPE_BIND_RENDER_TARGET);
-
- /* unpack the color */
- color.ui = value;
- util_unpack_color_ub(dst->format, &color,
- ub_rgba, ub_rgba+1, ub_rgba+2, ub_rgba+3);
- for (i = 0; i < 4; i++)
- rgba[i] = ubyte_to_float(ub_rgba[i]);
-
/* check the saved state */
blitter_check_saved_CSOs(ctx);
assert(blitter->saved_fb_state.nr_cbufs != ~0);
blitter_set_rectangle(ctx, 0, 0, width, height, dstsurf->width, dstsurf->height, 0);
blitter_draw_quad(ctx);
blitter_restore_CSOs(ctx);
+}
- pipe_surface_reference(&dstsurf, NULL);
+/* Clear a region of a depth stencil surface. */
+void util_blitter_clearDS(struct blitter_context *blitter,
+ struct pipe_surface *dstsurf,
+ unsigned clear_flags,
+ double depth,
+ unsigned stencil,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height)
+{
+ struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_framebuffer_state fb_state;
+ struct pipe_stencil_ref sr = { { 0 } };
+
+ assert(dstsurf->texture);
+ if (!dstsurf->texture)
+ return;
+
+ /* check the saved state */
+ blitter_check_saved_CSOs(ctx);
+ assert(blitter->saved_fb_state.nr_cbufs != ~0);
+
+ /* bind CSOs */
+ pipe->bind_blend_state(pipe, ctx->blend_keep_color);
+ if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
+ sr.ref_value[0] = stencil & 0xff;
+ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
+ pipe->set_stencil_ref(pipe, &sr);
+ }
+ else if (clear_flags & PIPE_CLEAR_DEPTH) {
+ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);
+ }
+ else if (clear_flags & PIPE_CLEAR_STENCIL) {
+ sr.ref_value[0] = stencil & 0xff;
+ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
+ pipe->set_stencil_ref(pipe, &sr);
+ }
+ else
+ /* hmm that should be illegal probably, or make it a no-op somewhere */
+ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
+
+ pipe->bind_rasterizer_state(pipe, ctx->rs_state);
+ pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0));
+ pipe->bind_vs_state(pipe, ctx->vs_col);
+ pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
+
+ /* set a framebuffer state */
+ fb_state.width = dstsurf->width;
+ fb_state.height = dstsurf->height;
+ fb_state.nr_cbufs = 0;
+ fb_state.cbufs[0] = 0;
+ fb_state.zsbuf = dstsurf;
+ pipe->set_framebuffer_state(pipe, &fb_state);
+
+ blitter_set_rectangle(ctx, 0, 0, width, height, dstsurf->width, dstsurf->height, depth);
+ blitter_draw_quad(ctx);
+ blitter_restore_CSOs(ctx);
}
boolean ignore_stencil);
/**
- * Fill a region of a surface with a constant value.
- *
- * If the surface cannot be rendered to or it's a depth-stencil format,
- * a software fallback path is taken.
+ * Clear a region of a (color) surface to a constant value.
*
* These states must be saved in the blitter in addition to the state objects
* already required to be saved:
* - framebuffer state
*/
-void util_blitter_fill_region(struct blitter_context *blitter,
- struct pipe_resource *dst,
- struct pipe_subresource subdst,
- unsigned dstx, unsigned dsty, unsigned dstz,
- unsigned width, unsigned height,
- unsigned value);
+void util_blitter_clearRT(struct blitter_context *blitter,
+ struct pipe_surface *dst,
+ const float *rgba,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height);
+/**
+ * Clear a region of a depth-stencil surface, both stencil and depth
+ * or only one of them if this is a combined depth-stencil surface.
+ *
+ * These states must be saved in the blitter in addition to the state objects
+ * already required to be saved:
+ * - framebuffer state
+ */
+void util_blitter_clearDS(struct blitter_context *blitter,
+ struct pipe_surface *dst,
+ unsigned clear_flags,
+ double depth,
+ unsigned stencil,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height);
/* The functions below should be used to save currently bound constant state
* objects inside a driver. The objects are automatically restored at the end
#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"
/**
const float *rgba, double depth, unsigned stencil)
{
if (buffers & PIPE_CLEAR_COLOR) {
- struct pipe_surface *ps = framebuffer->cbufs[0];
- struct pipe_subresource subdst;
- union util_color uc;
-
- subdst.face = ps->face;
- subdst.level = ps->level;
- util_pack_color(rgba, ps->format, &uc);
- pipe->resource_fill_region(pipe, ps->texture, subdst, 0, 0, ps->zslice,
- ps->width, ps->height, uc.ui);
+ unsigned i;
+ for (i = 0; i < framebuffer->nr_cbufs; i++) {
+ struct pipe_surface *ps = framebuffer->cbufs[i];
+ pipe->clearRT(pipe, ps, rgba, 0, 0, ps->width, ps->height);
+ }
}
if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
struct pipe_surface *ps = framebuffer->zsbuf;
- struct pipe_subresource subdst;
-
- subdst.face = ps->face;
- subdst.level = ps->level;
- pipe->resource_fill_region(pipe, ps->texture, subdst, 0, 0, ps->zslice,
- ps->width, ps->height,
- util_pack_z_stencil(ps->format, depth, stencil));
+ pipe->clearDS(pipe, ps, buffers & PIPE_CLEAR_DEPTHSTENCIL,
+ depth, stencil,
+ 0, 0, ps->width, ps->height);
}
}
#include "util/u_inlines.h"
#include "util/u_rect.h"
#include "util/u_surface.h"
+#include "util/u_pack_color.h"
/**
/**
- * Fallback for pipe->resource_fill_region() function.
+ * Fallback for pipe->clearRT() function.
+ * XXX this looks too hackish to be really useful.
+ * cpp > 4 looks like a gross hack at best...
+ * and we're missing the equivalent clearDS fallback.
+ * Plus can't use these transfer fallbacks when clearing
+ * multisampled surfaces for instance.
*/
void
-util_resource_fill_region(struct pipe_context *pipe,
- struct pipe_resource *dst,
- struct pipe_subresource subdst,
- unsigned dstx, unsigned dsty, unsigned dstz,
- unsigned width, unsigned height, unsigned value)
+util_clearRT(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ const float *rgba,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height)
{
struct pipe_transfer *dst_trans;
void *dst_map;
+ union util_color uc;
- assert(dst);
- if (!dst)
+ assert(dst->texture);
+ if (!dst->texture)
return;
+ util_pack_color(rgba, dst->texture->format, &uc);
dst_trans = pipe_get_transfer(pipe,
- dst,
- subdst.face,
- subdst.level,
- dstz,
+ dst->texture,
+ dst->face,
+ dst->level,
+ dst->zslice,
PIPE_TRANSFER_WRITE,
dstx, dsty, width, height);
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;