ilo: add ilo_state_zs
authorChia-I Wu <olvaffe@gmail.com>
Sat, 16 May 2015 00:27:24 +0000 (08:27 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Sun, 14 Jun 2015 15:00:03 +0000 (23:00 +0800)
We want to replace ilo_zs_surface with ilo_state_zs.  One noteworthy
difference is that ilo_state_zs always aligns level 0 to 8x4 when HiZ is
enabled.  HiZ will not be enabled for 1D surfaces as a result.

src/gallium/drivers/ilo/Makefile.sources
src/gallium/drivers/ilo/core/ilo_state_zs.c [new file with mode: 0644]
src/gallium/drivers/ilo/core/ilo_state_zs.h [new file with mode: 0644]

index 91a6f65..943e291 100644 (file)
@@ -23,6 +23,8 @@ C_SOURCES := \
        core/ilo_state_3d.h \
        core/ilo_state_3d_bottom.c \
        core/ilo_state_3d_top.c \
+       core/ilo_state_zs.c \
+       core/ilo_state_zs.h \
        core/intel_winsys.h \
        ilo_blit.c \
        ilo_blit.h \
diff --git a/src/gallium/drivers/ilo/core/ilo_state_zs.c b/src/gallium/drivers/ilo/core/ilo_state_zs.c
new file mode 100644 (file)
index 0000000..901fedb
--- /dev/null
@@ -0,0 +1,727 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2012-2015 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#include "intel_winsys.h"
+
+#include "ilo_debug.h"
+#include "ilo_image.h"
+#include "ilo_state_zs.h"
+
+static bool
+zs_set_gen6_null_3DSTATE_DEPTH_BUFFER(struct ilo_state_zs *zs,
+                                      const struct ilo_dev *dev)
+{
+   const enum gen_depth_format format = GEN6_ZFORMAT_D32_FLOAT;
+   uint32_t dw1;
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
+      dw1 = GEN6_SURFTYPE_NULL << GEN7_DEPTH_DW1_TYPE__SHIFT |
+            format << GEN7_DEPTH_DW1_FORMAT__SHIFT;
+   } else {
+      dw1 = GEN6_SURFTYPE_NULL << GEN6_DEPTH_DW1_TYPE__SHIFT |
+            GEN6_TILING_Y << GEN6_DEPTH_DW1_TILING__SHIFT |
+            format << GEN6_DEPTH_DW1_FORMAT__SHIFT;
+   }
+
+   STATIC_ASSERT(ARRAY_SIZE(zs->depth) >= 5);
+   zs->depth[0] = dw1;
+   zs->depth[1] = 0;
+   zs->depth[2] = 0;
+   zs->depth[3] = 0;
+   zs->depth[4] = 0;
+
+   zs->depth_format = format;
+
+   return true;
+}
+
+static enum gen_surface_type
+get_gen6_surface_type(const struct ilo_dev *dev, const struct ilo_image *img)
+{
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   switch (img->target) {
+   case PIPE_TEXTURE_1D:
+   case PIPE_TEXTURE_1D_ARRAY:
+      return GEN6_SURFTYPE_1D;
+   case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_CUBE:
+   case PIPE_TEXTURE_RECT:
+   case PIPE_TEXTURE_2D_ARRAY:
+   case PIPE_TEXTURE_CUBE_ARRAY:
+      return GEN6_SURFTYPE_2D;
+   case PIPE_TEXTURE_3D:
+      return GEN6_SURFTYPE_3D;
+   default:
+      assert(!"unknown texture target");
+      return GEN6_SURFTYPE_NULL;
+   }
+}
+
+static enum gen_depth_format
+get_gen6_depth_format(const struct ilo_dev *dev, const struct ilo_image *img)
+{
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
+      switch (img->format) {
+      case PIPE_FORMAT_Z32_FLOAT:
+         return GEN6_ZFORMAT_D32_FLOAT;
+      case PIPE_FORMAT_Z24X8_UNORM:
+         return GEN6_ZFORMAT_D24_UNORM_X8_UINT;
+      case PIPE_FORMAT_Z16_UNORM:
+         return GEN6_ZFORMAT_D16_UNORM;
+      default:
+         assert(!"unknown depth format");
+         return GEN6_ZFORMAT_D32_FLOAT;
+      }
+   } else {
+      switch (img->format) {
+      case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
+         return GEN6_ZFORMAT_D32_FLOAT_S8X24_UINT;
+      case PIPE_FORMAT_Z32_FLOAT:
+         return GEN6_ZFORMAT_D32_FLOAT;
+      case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+         return GEN6_ZFORMAT_D24_UNORM_S8_UINT;
+      case PIPE_FORMAT_Z24X8_UNORM:
+         return GEN6_ZFORMAT_D24_UNORM_X8_UINT;
+      case PIPE_FORMAT_Z16_UNORM:
+         return GEN6_ZFORMAT_D16_UNORM;
+      default:
+         assert(!"unknown depth format");
+         return GEN6_ZFORMAT_D32_FLOAT;
+      }
+   }
+}
+
+static bool
+zs_validate_gen6(const struct ilo_dev *dev,
+                 const struct ilo_state_zs_info *info)
+{
+   const struct ilo_image *img = (info->z_img) ? info->z_img : info->s_img;
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   /*
+    * From the Ivy Bridge PRM, volume 2 part 1, page 315:
+    *
+    *      The stencil buffer has a format of S8_UINT, and shares Surface
+    *      Type, Height, Width, and Depth, Minimum Array Element, Render
+    *      Target View Extent, Depth Coordinate Offset X/Y, LOD, and Depth
+    *      Buffer Object Control State fields of the depth buffer.
+    */
+   if (info->z_img == info->s_img) {
+      assert(info->z_img->target == info->s_img->target &&
+             info->z_img->width0 == info->s_img->width0 &&
+             info->z_img->height0 == info->s_img->height0 &&
+             info->z_img->depth0 == info->s_img->depth0);
+   }
+
+   assert(info->level < img->level_count);
+   assert(img->bo_stride);
+
+   if (info->hiz_enable) {
+      assert(info->z_img &&
+             ilo_image_can_enable_aux(info->z_img, info->level));
+   }
+
+   if (info->is_cube_map) {
+      assert(get_gen6_surface_type(dev, img) == GEN6_SURFTYPE_2D);
+
+      /*
+       * From the Sandy Bridge PRM, volume 2 part 1, page 323:
+       *
+       *     "For cube maps, Width must be set equal to Height."
+       */
+      assert(img->width0 == img->height0);
+   }
+
+   if (info->z_img)
+      assert(info->z_img->tiling == GEN6_TILING_Y);
+   if (info->s_img)
+      assert(info->s_img->tiling == GEN8_TILING_W);
+
+   return true;
+}
+
+static void
+get_gen6_max_extent(const struct ilo_dev *dev,
+                    const struct ilo_image *img,
+                    uint16_t *max_w, uint16_t *max_h)
+{
+   const uint16_t max_size = (ilo_dev_gen(dev) >= ILO_GEN(7)) ? 16384 : 8192;
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   switch (get_gen6_surface_type(dev, img)) {
+   case GEN6_SURFTYPE_1D:
+      *max_w = max_size;
+      *max_h = 1;
+      break;
+   case GEN6_SURFTYPE_2D:
+      *max_w = max_size;
+      *max_h = max_size;
+      break;
+   case GEN6_SURFTYPE_3D:
+      *max_w = 2048;
+      *max_h = 2048;
+      break;
+   default:
+      assert(!"invalid surface type");
+      *max_w = 1;
+      *max_h = 1;
+      break;
+   }
+}
+
+static void
+get_gen6_hiz_alignments(const struct ilo_dev *dev,
+                        const struct ilo_image *img,
+                        uint16_t *align_w, uint16_t *align_h)
+{
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 313:
+    *
+    *     "A rectangle primitive representing the clear area is delivered. The
+    *      primitive must adhere to the following restrictions on size:
+    *
+    *      - If Number of Multisamples is NUMSAMPLES_1, the rectangle must be
+    *        aligned to an 8x4 pixel block relative to the upper left corner
+    *        of the depth buffer, and contain an integer number of these pixel
+    *        blocks, and all 8x4 pixels must be lit.
+    *      - If Number of Multisamples is NUMSAMPLES_4, the rectangle must be
+    *        aligned to a 4x2 pixel block (8x4 sample block) relative to the
+    *        upper left corner of the depth buffer, and contain an integer
+    *        number of these pixel blocks, and all samples of the 4x2 pixels
+    *        must be lit
+    *      - If Number of Multisamples is NUMSAMPLES_8, the rectangle must be
+    *        aligned to a 2x2 pixel block (8x4 sample block) relative to the
+    *        upper left corner of the depth buffer, and contain an integer
+    *        number of these pixel blocks, and all samples of the 2x2 pixels
+    *        must be list."
+    *
+    * Experiments on Gen7.5 show that HiZ resolve also requires the rectangle
+    * to be aligned to 8x4 sample blocks.  But to be on the safe side, we
+    * always require a level to be aligned when HiZ is enabled.
+    */
+   switch (img->sample_count) {
+   case 1:
+      *align_w = 8;
+      *align_h = 4;
+      break;
+   case 2:
+      *align_w = 4;
+      *align_h = 4;
+      break;
+   case 4:
+      *align_w = 4;
+      *align_h = 2;
+      break;
+   case 8:
+      *align_w = 2;
+      *align_h = 2;
+      break;
+   case 16:
+      *align_w = 2;
+      *align_h = 1;
+      break;
+   default:
+      assert(!"unknown sample count");
+      *align_w = 1;
+      *align_h = 1;
+      break;
+   }
+}
+
+static bool
+zs_get_gen6_depth_extent(const struct ilo_dev *dev,
+                         const struct ilo_state_zs_info *info,
+                         uint16_t *width, uint16_t *height)
+{
+   const struct ilo_image *img = (info->z_img) ? info->z_img : info->s_img;
+   uint16_t w, h, max_w, max_h;
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   w = img->width0;
+   h = img->height0;
+
+   if (info->hiz_enable) {
+      uint16_t align_w, align_h;
+
+      get_gen6_hiz_alignments(dev, info->z_img, &align_w, &align_h);
+
+      /*
+       * We want to force 8x4 alignment, but we can do so only for level 0 and
+       * only when it is padded.  ilo_image should know all these.
+       */
+      if (info->level)
+         assert(w % align_w == 0 && h % align_h == 0);
+
+      w = align(w, align_w);
+      h = align(h, align_h);
+   }
+
+   get_gen6_max_extent(dev, img, &max_w, &max_h);
+   assert(w && h && w <= max_w && h <= max_h);
+
+   *width = w - 1;
+   *height = h - 1;
+
+   return true;
+}
+
+static bool
+zs_get_gen6_depth_slices(const struct ilo_dev *dev,
+                         const struct ilo_state_zs_info *info,
+                         uint16_t *depth, uint16_t *min_array_elem,
+                         uint16_t *rt_view_extent)
+{
+   const struct ilo_image *img = (info->z_img) ? info->z_img : info->s_img;
+   uint16_t max_slice, d;
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 325:
+    *
+    *     "This field (Depth) specifies the total number of levels for a
+    *      volume texture or the number of array elements allowed to be
+    *      accessed starting at the Minimum Array Element for arrayed
+    *      surfaces. If the volume texture is MIP-mapped, this field specifies
+    *      the depth of the base MIP level."
+    */
+   switch (get_gen6_surface_type(dev, img)) {
+   case GEN6_SURFTYPE_1D:
+   case GEN6_SURFTYPE_2D:
+      max_slice = (ilo_dev_gen(dev) >= ILO_GEN(7)) ? 2048 : 512;
+
+      assert(img->array_size <= max_slice);
+      max_slice = img->array_size;
+
+      d = info->slice_count;
+      if (info->is_cube_map) {
+         /*
+          * Minumum Array Element and Depth must be 0; Render Target View
+          * Extent is ignored.
+          */
+         if (info->slice_base || d != 6) {
+            ilo_warn("no cube array dpeth buffer\n");
+            return false;
+         }
+
+         d /= 6;
+      }
+      break;
+   case GEN6_SURFTYPE_3D:
+      max_slice = 2048;
+
+      assert(img->depth0 <= max_slice);
+      max_slice = u_minify(img->depth0, info->level);
+
+      d = img->depth0;
+      break;
+   default:
+      assert(!"invalid surface type");
+      return false;
+      break;
+   }
+
+   if (!info->slice_count ||
+       info->slice_base + info->slice_count > max_slice) {
+      ilo_warn("invalid slice range\n");
+      return false;
+   }
+
+   assert(d);
+   *depth = d - 1;
+
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 325:
+    *
+    *     "For 1D and 2D Surfaces:
+    *      This field (Minimum Array Element) indicates the minimum array
+    *      element that can be accessed as part of this surface. The delivered
+    *      array index is added to this field before being used to address the
+    *      surface.
+    *
+    *      For 3D Surfaces:
+    *      This field indicates the minimum `R' coordinate on the LOD
+    *      currently being rendered to.  This field is added to the delivered
+    *      array index before it is used to address the surface.
+    *
+    *      For Other Surfaces:
+    *      This field is ignored."
+    */
+   *min_array_elem = info->slice_base;
+
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 326:
+    *
+    *     "For 3D Surfaces:
+    *      This field (Render Target View Extent) indicates the extent of the
+    *      accessible `R' coordinates minus 1 on the LOD currently being
+    *      rendered to.
+    *
+    *      For 1D and 2D Surfaces:
+    *      This field must be set to the same value as the Depth field.
+    *
+    *      For Other Surfaces:
+    *      This field is ignored."
+    */
+   *rt_view_extent = info->slice_count - 1;
+
+   return true;
+}
+
+static bool
+zs_set_gen6_3DSTATE_DEPTH_BUFFER(struct ilo_state_zs *zs,
+                                 const struct ilo_dev *dev,
+                                 const struct ilo_state_zs_info *info)
+{
+   uint16_t width, height, depth, array_base, view_extent;
+   enum gen_surface_type type;
+   enum gen_depth_format format;
+   uint32_t dw1, dw2, dw3, dw4;
+
+   ILO_DEV_ASSERT(dev, 6, 6);
+
+   if (!zs_validate_gen6(dev, info) ||
+       !zs_get_gen6_depth_extent(dev, info, &width, &height) ||
+       !zs_get_gen6_depth_slices(dev, info, &depth, &array_base,
+                                 &view_extent))
+      return false;
+
+   type = (info->is_cube_map) ? GEN6_SURFTYPE_CUBE :
+          (info->z_img) ? get_gen6_surface_type(dev, info->z_img) :
+                          get_gen6_surface_type(dev, info->s_img);
+
+   format = (info->z_img) ? get_gen6_depth_format(dev, info->z_img) :
+      GEN6_ZFORMAT_D32_FLOAT;
+
+   /*
+    * From the Ironlake PRM, volume 2 part 1, page 330:
+    *
+    *     "If this field (Separate Stencil Buffer Enable) is disabled, the
+    *      Surface Format of the depth buffer cannot be D24_UNORM_X8_UINT."
+    *
+    * From the Sandy Bridge PRM, volume 2 part 1, page 321:
+    *
+    *     "[DevSNB]: This field (Separate Stencil Buffer Enable) must be set
+    *      to the same value (enabled or disabled) as Hierarchical Depth
+    *      Buffer Enable."
+    */
+   if (!info->hiz_enable && format == GEN6_ZFORMAT_D24_UNORM_X8_UINT)
+      format = GEN6_ZFORMAT_D24_UNORM_S8_UINT;
+
+   /* info->z_readonly and info->s_readonly are ignored on Gen6 */
+   dw1 = type << GEN6_DEPTH_DW1_TYPE__SHIFT |
+         GEN6_TILING_Y << GEN6_DEPTH_DW1_TILING__SHIFT |
+         format << GEN6_DEPTH_DW1_FORMAT__SHIFT;
+
+   if (info->z_img)
+      dw1 |= (info->z_img->bo_stride - 1) << GEN6_DEPTH_DW1_PITCH__SHIFT;
+
+   if (info->hiz_enable || !info->z_img) {
+      dw1 |= GEN6_DEPTH_DW1_HIZ_ENABLE |
+             GEN6_DEPTH_DW1_SEPARATE_STENCIL;
+   }
+
+   dw2 = 0;
+   dw3 = height << GEN6_DEPTH_DW3_HEIGHT__SHIFT |
+         width << GEN6_DEPTH_DW3_WIDTH__SHIFT |
+         info->level << GEN6_DEPTH_DW3_LOD__SHIFT |
+         GEN6_DEPTH_DW3_MIPLAYOUT_BELOW;
+   dw4 = depth << GEN6_DEPTH_DW4_DEPTH__SHIFT |
+         array_base << GEN6_DEPTH_DW4_MIN_ARRAY_ELEMENT__SHIFT |
+         view_extent << GEN6_DEPTH_DW4_RT_VIEW_EXTENT__SHIFT;
+
+   STATIC_ASSERT(ARRAY_SIZE(zs->depth) >= 5);
+   zs->depth[0] = dw1;
+   zs->depth[1] = dw2;
+   zs->depth[2] = dw3;
+   zs->depth[3] = dw4;
+   zs->depth[4] = 0;
+
+   zs->depth_format = format;
+
+   return true;
+}
+
+static bool
+zs_set_gen7_3DSTATE_DEPTH_BUFFER(struct ilo_state_zs *zs,
+                                 const struct ilo_dev *dev,
+                                 const struct ilo_state_zs_info *info)
+{
+   enum gen_surface_type type;
+   enum gen_depth_format format;
+   uint16_t width, height, depth;
+   uint16_t array_base, view_extent;
+   uint32_t dw1, dw2, dw3, dw4, dw6;
+
+   ILO_DEV_ASSERT(dev, 7, 8);
+
+   if (!zs_validate_gen6(dev, info) ||
+       !zs_get_gen6_depth_extent(dev, info, &width, &height) ||
+       !zs_get_gen6_depth_slices(dev, info, &depth, &array_base,
+                                 &view_extent))
+      return false;
+
+   type = (info->is_cube_map) ? GEN6_SURFTYPE_CUBE :
+          (info->z_img) ? get_gen6_surface_type(dev, info->z_img) :
+                          get_gen6_surface_type(dev, info->s_img);
+
+   format = (info->z_img) ? get_gen6_depth_format(dev, info->z_img) :
+      GEN6_ZFORMAT_D32_FLOAT;
+
+   dw1 = type << GEN7_DEPTH_DW1_TYPE__SHIFT |
+         format << GEN7_DEPTH_DW1_FORMAT__SHIFT;
+
+   if (info->z_img) {
+      if (!info->z_readonly)
+         dw1 |= GEN7_DEPTH_DW1_DEPTH_WRITE_ENABLE;
+      if (info->hiz_enable)
+         dw1 |= GEN7_DEPTH_DW1_HIZ_ENABLE;
+
+      dw1 |= (info->z_img->bo_stride - 1) << GEN7_DEPTH_DW1_PITCH__SHIFT;
+   }
+
+   if (info->s_img && !info->s_readonly)
+      dw1 |= GEN7_DEPTH_DW1_STENCIL_WRITE_ENABLE;
+
+   dw2 = 0;
+   dw3 = height << GEN7_DEPTH_DW3_HEIGHT__SHIFT |
+         width << GEN7_DEPTH_DW3_WIDTH__SHIFT |
+         info->level << GEN7_DEPTH_DW3_LOD__SHIFT;
+   dw4 = depth << GEN7_DEPTH_DW4_DEPTH__SHIFT |
+         array_base << GEN7_DEPTH_DW4_MIN_ARRAY_ELEMENT__SHIFT;
+   dw6 = view_extent << GEN7_DEPTH_DW6_RT_VIEW_EXTENT__SHIFT;
+
+   if (ilo_dev_gen(dev) >= ILO_GEN(8) && info->z_img) {
+      assert(info->z_img->walk_layer_height % 4 == 0);
+      /* note that DW is off-by-one for Gen8+ */
+      dw6 |= (info->z_img->walk_layer_height / 4) <<
+         GEN8_DEPTH_DW7_QPITCH__SHIFT;
+   }
+
+   STATIC_ASSERT(ARRAY_SIZE(zs->depth) >= 5);
+   zs->depth[0] = dw1;
+   zs->depth[1] = dw2;
+   zs->depth[2] = dw3;
+   zs->depth[3] = dw4;
+   zs->depth[4] = dw6;
+
+   zs->depth_format = format;
+
+   return true;
+}
+
+static bool
+zs_set_gen6_null_3DSTATE_STENCIL_BUFFER(struct ilo_state_zs *zs,
+                                        const struct ilo_dev *dev)
+{
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   STATIC_ASSERT(ARRAY_SIZE(zs->stencil) >= 3);
+   zs->stencil[0] = 0;
+   zs->stencil[1] = 0;
+   if (ilo_dev_gen(dev) >= ILO_GEN(8))
+      zs->stencil[2] = 0;
+
+   return true;
+}
+
+static bool
+zs_set_gen6_3DSTATE_STENCIL_BUFFER(struct ilo_state_zs *zs,
+                                   const struct ilo_dev *dev,
+                                   const struct ilo_state_zs_info *info)
+{
+   const struct ilo_image *img = info->s_img;
+   uint32_t dw1, dw2;
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   assert(img->bo_stride);
+
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 329:
+    *
+    *     "The pitch must be set to 2x the value computed based on width, as
+    *      the stencil buffer is stored with two rows interleaved."
+    *
+    * For Gen7+, we still dobule the stride because we did not double the
+    * slice widths when initializing ilo_image.
+    */
+   dw1 = (img->bo_stride * 2 - 1) << GEN6_STENCIL_DW1_PITCH__SHIFT;
+
+   if (ilo_dev_gen(dev) >= ILO_GEN(7.5))
+      dw1 |= GEN75_STENCIL_DW1_STENCIL_BUFFER_ENABLE;
+
+   dw2 = 0;
+   /* offset to the level as Gen6 does not support mipmapped stencil */
+   if (ilo_dev_gen(dev) == ILO_GEN(6)) {
+      unsigned x, y;
+
+      ilo_image_get_slice_pos(img, info->level, 0, &x, &y);
+      ilo_image_pos_to_mem(img, x, y, &x, &y);
+      dw2 |= ilo_image_mem_to_raw(img, x, y);
+   }
+
+   STATIC_ASSERT(ARRAY_SIZE(zs->stencil) >= 3);
+   zs->stencil[0] = dw1;
+   zs->stencil[1] = dw2;
+
+   if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
+      uint32_t dw4;
+
+      assert(img->walk_layer_height % 4 == 0);
+      dw4 = (img->walk_layer_height / 4) << GEN8_STENCIL_DW4_QPITCH__SHIFT;
+
+      zs->stencil[2] = dw4;
+   }
+
+   return true;
+}
+
+static bool
+zs_set_gen6_null_3DSTATE_HIER_DEPTH_BUFFER(struct ilo_state_zs *zs,
+                                           const struct ilo_dev *dev)
+{
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   STATIC_ASSERT(ARRAY_SIZE(zs->hiz) >= 3);
+   zs->hiz[0] = 0;
+   zs->hiz[1] = 0;
+   if (ilo_dev_gen(dev) >= ILO_GEN(8))
+      zs->hiz[2] = 0;
+
+   return true;
+}
+
+static bool
+zs_set_gen6_3DSTATE_HIER_DEPTH_BUFFER(struct ilo_state_zs *zs,
+                                      const struct ilo_dev *dev,
+                                      const struct ilo_state_zs_info *info)
+{
+   const struct ilo_image *img = info->z_img;
+   uint32_t dw1, dw2;
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   assert(img->aux.bo_stride);
+
+   dw1 = (img->aux.bo_stride - 1) << GEN6_HIZ_DW1_PITCH__SHIFT;
+
+   dw2 = 0;
+   /* offset to the level as Gen6 does not support mipmapped HiZ */
+   if (ilo_dev_gen(dev) == ILO_GEN(6))
+      dw2 |= img->aux.walk_lod_offsets[info->level];
+
+   STATIC_ASSERT(ARRAY_SIZE(zs->hiz) >= 3);
+   zs->hiz[0] = dw1;
+   zs->hiz[1] = dw2;
+
+   if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
+      uint32_t dw4;
+
+      assert(img->aux.walk_layer_height % 4 == 0);
+      dw4 = (img->aux.walk_layer_height / 4) << GEN8_HIZ_DW4_QPITCH__SHIFT;
+
+      zs->hiz[2] = dw4;
+   }
+
+   return true;
+}
+
+bool
+ilo_state_zs_init(struct ilo_state_zs *zs, const struct ilo_dev *dev,
+                  const struct ilo_state_zs_info *info)
+{
+   bool ret = true;
+
+   assert(ilo_is_zeroed(zs, sizeof(*zs)));
+
+   if (info->z_img || info->s_img) {
+      if (ilo_dev_gen(dev) >= ILO_GEN(7))
+         ret &= zs_set_gen7_3DSTATE_DEPTH_BUFFER(zs, dev, info);
+      else
+         ret &= zs_set_gen6_3DSTATE_DEPTH_BUFFER(zs, dev, info);
+   } else {
+      ret &= zs_set_gen6_null_3DSTATE_DEPTH_BUFFER(zs, dev);
+   }
+
+   if (info->s_img)
+      ret &= zs_set_gen6_3DSTATE_STENCIL_BUFFER(zs, dev, info);
+   else
+      ret &= zs_set_gen6_null_3DSTATE_STENCIL_BUFFER(zs, dev);
+
+   if (info->z_img && info->hiz_enable)
+      ret &= zs_set_gen6_3DSTATE_HIER_DEPTH_BUFFER(zs, dev, info);
+   else
+      ret &= zs_set_gen6_null_3DSTATE_HIER_DEPTH_BUFFER(zs, dev);
+
+   zs->z_readonly = info->z_readonly;
+   zs->s_readonly = info->s_readonly;
+
+   assert(ret);
+
+   return ret;
+}
+
+bool
+ilo_state_zs_init_for_null(struct ilo_state_zs *zs,
+                           const struct ilo_dev *dev)
+{
+   struct ilo_state_zs_info info;
+
+   memset(&info, 0, sizeof(info));
+
+   return ilo_state_zs_init(zs, dev, &info);
+}
+
+bool
+ilo_state_zs_disable_hiz(struct ilo_state_zs *zs,
+                         const struct ilo_dev *dev)
+{
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   /*
+    * Separate stencil must be disabled simultaneously on Gen6.  We can make
+    * it work when there is no stencil buffer, but it is probably not worth
+    * it.
+    */
+   assert(ilo_dev_gen(dev) >= ILO_GEN(7));
+
+   zs->depth[0] &= ~GEN7_DEPTH_DW1_HIZ_ENABLE;
+   zs_set_gen6_null_3DSTATE_HIER_DEPTH_BUFFER(zs, dev);
+
+   return true;
+}
diff --git a/src/gallium/drivers/ilo/core/ilo_state_zs.h b/src/gallium/drivers/ilo/core/ilo_state_zs.h
new file mode 100644 (file)
index 0000000..98212da
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2015 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#ifndef ILO_STATE_ZS_H
+#define ILO_STATE_ZS_H
+
+#include "genhw/genhw.h"
+#include "intel_winsys.h"
+
+#include "ilo_core.h"
+#include "ilo_dev.h"
+
+struct ilo_image;
+
+struct ilo_state_zs_info {
+   /* both are optional */
+   const struct ilo_image *z_img;
+   const struct ilo_image *s_img;
+
+   /* ignored prior to Gen7 */
+   bool z_readonly;
+   bool s_readonly;
+
+   bool hiz_enable;
+   bool is_cube_map;
+
+   uint8_t level;
+   uint16_t slice_base;
+   uint16_t slice_count;
+};
+
+struct ilo_state_zs {
+   uint32_t depth[5];
+   uint32_t stencil[3];
+   uint32_t hiz[3];
+
+   /* TODO move this to ilo_image */
+   enum gen_depth_format depth_format;
+
+   bool z_readonly;
+   bool s_readonly;
+
+   /* managed by users */
+   struct intel_bo *depth_bo;
+   struct intel_bo *stencil_bo;
+   struct intel_bo *hiz_bo;
+};
+
+bool
+ilo_state_zs_init(struct ilo_state_zs *zs,
+                  const struct ilo_dev *dev,
+                  const struct ilo_state_zs_info *info);
+
+bool
+ilo_state_zs_init_for_null(struct ilo_state_zs *zs,
+                           const struct ilo_dev *dev);
+
+bool
+ilo_state_zs_disable_hiz(struct ilo_state_zs *zs,
+                         const struct ilo_dev *dev);
+
+static inline enum gen_depth_format
+ilo_state_zs_get_depth_format(const struct ilo_state_zs *zs,
+                              const struct ilo_dev *dev)
+{
+   return zs->depth_format;
+}
+
+#endif /* ILO_STATE_ZS_H */