Mesa (master): llvmpipe: adapt to clear interface changes

Roland Scheidegger sroland at kemper.freedesktop.org
Thu Jun 3 08:47:36 PDT 2010


Module: Mesa
Branch: master
Commit: 1e17178fc40b6a1a54cb3e93c098bdd0d490b88a
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=1e17178fc40b6a1a54cb3e93c098bdd0d490b88a

Author: Roland Scheidegger <sroland at vmware.com>
Date:   Sat May 29 01:31:01 2010 +0200

llvmpipe: adapt to clear interface changes

with some newfangled code, should support separate depth/stencil clears.
Needs some testing.

---

 src/gallium/drivers/llvmpipe/lp_rast.c          |   33 +++++++---
 src/gallium/drivers/llvmpipe/lp_rast.h          |   16 ++++-
 src/gallium/drivers/llvmpipe/lp_scene.c         |    2 +-
 src/gallium/drivers/llvmpipe/lp_scene.h         |    2 +-
 src/gallium/drivers/llvmpipe/lp_screen.c        |    2 +
 src/gallium/drivers/llvmpipe/lp_setup.c         |   83 +++++++++++++++++++----
 src/gallium/drivers/llvmpipe/lp_setup_context.h |    2 +-
 src/gallium/drivers/llvmpipe/lp_surface.c       |    1 -
 8 files changed, 113 insertions(+), 28 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index 6bb868b..2280c71 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -177,7 +177,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;
@@ -269,6 +269,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;
@@ -276,7 +279,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
@@ -292,22 +295,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 881f475..757009d 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast.h
@@ -92,6 +92,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,
@@ -155,7 +160,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;
 };
@@ -197,6 +202,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;
@@ -205,7 +218,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 59e4c18..845c175 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 22d619f..4e55d43 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 cedc08e..e24b86d 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 656e6cc..1970173 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 584764c..c8b8a24 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 85687ad..4f409f9 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;
 }



More information about the mesa-commit mailing list