util: adapt to clear interface changes
authorRoland Scheidegger <sroland@vmware.com>
Fri, 28 May 2010 22:02:05 +0000 (00:02 +0200)
committerRoland Scheidegger <sroland@vmware.com>
Fri, 28 May 2010 22:02:05 +0000 (00:02 +0200)
src/gallium/auxiliary/util/u_blitter.c
src/gallium/auxiliary/util/u_blitter.h
src/gallium/auxiliary/util/u_clear.h
src/gallium/auxiliary/util/u_surface.c
src/gallium/auxiliary/util/u_surface.h

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