ilo: add ilo_state_surface
authorChia-I Wu <olvaffe@gmail.com>
Thu, 14 May 2015 01:46:42 +0000 (09:46 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Sun, 14 Jun 2015 15:00:04 +0000 (23:00 +0800)
We want to replace ilo_view_surface with ilo_state_surface.

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

index 943e29113ae1d0695b60ab8b1629393dd4a7b591..587850eafdb51888c108d70b60a7839ad78ceb00 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_surface.c \
+       core/ilo_state_surface.h \
        core/ilo_state_zs.c \
        core/ilo_state_zs.h \
        core/intel_winsys.h \
diff --git a/src/gallium/drivers/ilo/core/ilo_state_surface.c b/src/gallium/drivers/ilo/core/ilo_state_surface.c
new file mode 100644 (file)
index 0000000..be7225b
--- /dev/null
@@ -0,0 +1,1179 @@
+/*
+ * 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 "ilo_debug.h"
+#include "ilo_buffer.h"
+#include "ilo_image.h"
+#include "ilo_state_surface.h"
+
+static bool
+surface_set_gen6_null_SURFACE_STATE(struct ilo_state_surface *surf,
+                                    const struct ilo_dev *dev)
+{
+   uint32_t dw0, dw3;
+
+   ILO_DEV_ASSERT(dev, 6, 6);
+
+   /*
+    * From the Sandy Bridge PRM, volume 4 part 1, page 71:
+    *
+    *     "All of the remaining fields in surface state are ignored for null
+    *      surfaces, with the following exceptions:
+    *
+    *        - [DevSNB+]: Width, Height, Depth, and LOD fields must match the
+    *          depth buffer's corresponding state for all render target
+    *          surfaces, including null.
+    *        - Surface Format must be R8G8B8A8_UNORM."
+    *
+    * From the Sandy Bridge PRM, volume 4 part 1, page 82:
+    *
+    *     "If Surface Type is SURFTYPE_NULL, this field (Tiled Surface) must
+    *      be true"
+    *
+    * Note that we ignore the first exception for all surface types.
+    */
+   dw0 = GEN6_SURFTYPE_NULL << GEN6_SURFACE_DW0_TYPE__SHIFT |
+         GEN6_FORMAT_R8G8B8A8_UNORM << GEN6_SURFACE_DW0_FORMAT__SHIFT;
+   dw3 = GEN6_TILING_X << GEN6_SURFACE_DW3_TILING__SHIFT;
+
+   STATIC_ASSERT(ARRAY_SIZE(surf->surface) >= 6);
+   surf->surface[0] = dw0;
+   surf->surface[1] = 0;
+   surf->surface[2] = 0;
+   surf->surface[3] = dw3;
+   surf->surface[4] = 0;
+   surf->surface[5] = 0;
+
+   return true;
+}
+
+static bool
+surface_set_gen7_null_SURFACE_STATE(struct ilo_state_surface *surf,
+                                    const struct ilo_dev *dev)
+{
+   uint32_t dw0;
+
+   ILO_DEV_ASSERT(dev, 7, 8);
+
+   dw0 = GEN6_SURFTYPE_NULL << GEN7_SURFACE_DW0_TYPE__SHIFT |
+         GEN6_FORMAT_R8G8B8A8_UNORM << GEN7_SURFACE_DW0_FORMAT__SHIFT;
+   if (ilo_dev_gen(dev) >= ILO_GEN(8))
+      dw0 |= GEN6_TILING_X << GEN8_SURFACE_DW0_TILING__SHIFT;
+   else
+      dw0 |= GEN6_TILING_X << GEN7_SURFACE_DW0_TILING__SHIFT;
+
+   STATIC_ASSERT(ARRAY_SIZE(surf->surface) >= 13);
+   surf->surface[0] = dw0;
+   memset(&surf->surface[1], 0, sizeof(uint32_t) *
+         ((ilo_dev_gen(dev) >= ILO_GEN(8)) ? 13 : 8) - 1);
+
+   return true;
+}
+
+static bool
+surface_validate_gen6_buffer(const struct ilo_dev *dev,
+                             const struct ilo_state_surface_buffer_info *info)
+{
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   /* SVB writes are Gen6-only */
+   if (ilo_dev_gen(dev) >= ILO_GEN(7))
+      assert(info->access != ILO_STATE_SURFACE_ACCESS_DP_SVB);
+
+   if (info->offset + info->size > info->buf->bo_size) {
+      ilo_warn("invalid buffer range\n");
+      return false;
+   }
+
+   /*
+    * From the Sandy Bridge PRM, volume 4 part 1, page 81:
+    *
+    *     "For surfaces of type SURFTYPE_BUFFER: [0,2047] -> [1B, 2048B]
+    *      For surfaces of type SURFTYPE_STRBUF: [0,2047] -> [1B, 2048B]"
+    */
+   if (!info->struct_size || info->struct_size > 2048) {
+      ilo_warn("invalid buffer struct size\n");
+      return false;
+   }
+
+   /*
+    * From the Ivy Bridge PRM, volume 4 part 1, page 68:
+    *
+    *     "The Base Address for linear render target surfaces and surfaces
+    *      accessed with the typed surface read/write data port messages must
+    *      be element-size aligned, for non-YUV surface formats, or a multiple
+    *      of 2 element-sizes for YUV surface formats.  Other linear surfaces
+    *      have no alignment requirements (byte alignment is sufficient)."
+    *
+    *     "Certain message types used to access surfaces have more stringent
+    *      alignment requirements. Please refer to the specific message
+    *      documentation for additional restrictions."
+    *
+    * From the Ivy Bridge PRM, volume 4 part 1, page 233, 235, and 237:
+    *
+    *     "the surface base address must be OWord aligned"
+    *
+    * for OWord Block Read/Write, Unaligned OWord Block Read, and OWord Dual
+    * Block Read/Write.
+    *
+    * From the Ivy Bridge PRM, volume 4 part 1, page 246 and 249:
+    *
+    *     "The surface base address must be DWord aligned"
+    *
+    * for DWord Scattered Read/Write and Byte Scattered Read/Write.
+    *
+    * We have to rely on users to correctly set info->struct_size here.  DWord
+    * Scattered Read/Write has conflicting pitch and alignment, but we do not
+    * use them yet so we are fine.
+    *
+    * It is unclear if sampling engine surfaces require aligned offsets.
+    */
+   if (info->access != ILO_STATE_SURFACE_ACCESS_DP_SVB) {
+      assert(info->struct_size % info->format_size == 0);
+
+      if (info->offset % info->struct_size) {
+         ilo_warn("bad buffer offset\n");
+         return false;
+      }
+   }
+
+   if (info->format == GEN6_FORMAT_RAW) {
+      /*
+       * From the Sandy Bridge PRM, volume 4 part 1, page 97:
+       *
+       *     ""RAW" is supported only with buffers and structured buffers
+       *      accessed via the untyped surface read/write and untyped atomic
+       *      operation messages, which do not have a column in the table."
+       *
+       * We do not have a specific access mode for untyped messages.
+       */
+      assert(info->access == ILO_STATE_SURFACE_ACCESS_DP_UNTYPED);
+
+      /*
+       * Nothing is said about Untyped* messages, but I guess they require the
+       * base address to be DWord aligned.
+       */
+      if (info->offset % 4) {
+         ilo_warn("bad RAW buffer offset\n");
+         return false;
+      }
+
+      if (info->struct_size > 1) {
+         /* no STRBUF on Gen6 */
+         if (ilo_dev_gen(dev) == ILO_GEN(6)) {
+            ilo_warn("no STRBUF support\n");
+            return false;
+         }
+
+         /*
+          * From the Ivy Bridge PRM, volume 4 part 1, page 70:
+          *
+          *     "For linear surfaces with Surface Type of SURFTYPE_STRBUF, the
+          *      pitch must be a multiple of 4 bytes."
+          */
+         if (info->struct_size % 4) {
+            ilo_warn("bad STRBUF pitch\n");
+            return false;
+         }
+      }
+   }
+
+   return true;
+}
+
+static bool
+surface_get_gen6_buffer_struct_count(const struct ilo_dev *dev,
+                                     const struct ilo_state_surface_buffer_info *info,
+                                     uint32_t *count)
+{
+   uint32_t max_struct, c;
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   c = info->size / info->struct_size;
+   if (info->access == ILO_STATE_SURFACE_ACCESS_DP_SVB &&
+       info->format_size < info->size - info->struct_size * c)
+      c++;
+
+   /*
+    * From the Sandy Bridge PRM, volume 4 part 1, page 77:
+    *
+    *     "For buffer surfaces, the number of entries in the buffer ranges
+    *      from 1 to 2^27."
+    *
+    * From the Ivy Bridge PRM, volume 4 part 1, page 68:
+    *
+    *     "For typed buffer and structured buffer surfaces, the number of
+    *      entries in the buffer ranges from 1 to 2^27.  For raw buffer
+    *      surfaces, the number of entries in the buffer is the number of
+    *      bytes which can range from 1 to 2^30."
+    *
+    * From the Ivy Bridge PRM, volume 4 part 1, page 69:
+    *
+    *      For SURFTYPE_BUFFER: The low two bits of this field (Width) must be
+    *      11 if the Surface Format is RAW (the size of the buffer must be a
+    *      multiple of 4 bytes)."
+    */
+   max_struct = 1 << 27;
+   if (info->format == GEN6_FORMAT_RAW && info->struct_size == 1) {
+      if (ilo_dev_gen(dev) >= ILO_GEN(7))
+         max_struct = 1 << 30;
+
+      c &= ~3;
+   }
+
+   if (!c || c > max_struct) {
+      ilo_warn("too many or zero buffer structs\n");
+      return false;
+   }
+
+   *count = c - 1;
+
+   return true;
+}
+
+static bool
+surface_set_gen6_buffer_SURFACE_STATE(struct ilo_state_surface *surf,
+                                     const struct ilo_dev *dev,
+                                     const struct ilo_state_surface_buffer_info *info)
+{
+   uint32_t dw0, dw1, dw2, dw3;
+   uint32_t struct_count;
+   int width, height, depth;
+
+   ILO_DEV_ASSERT(dev, 6, 6);
+
+   if (!surface_validate_gen6_buffer(dev, info) ||
+       !surface_get_gen6_buffer_struct_count(dev, info, &struct_count))
+      return false;
+
+   /* bits [6:0] */
+   width  = (struct_count & 0x0000007f);
+   /* bits [19:7] */
+   height = (struct_count & 0x000fff80) >> 7;
+   /* bits [26:20] */
+   depth  = (struct_count & 0x07f00000) >> 20;
+
+   dw0 = GEN6_SURFTYPE_BUFFER << GEN6_SURFACE_DW0_TYPE__SHIFT |
+         info->format << GEN6_SURFACE_DW0_FORMAT__SHIFT;
+   dw1 = info->offset;
+   dw2 = height << GEN6_SURFACE_DW2_HEIGHT__SHIFT |
+         width << GEN6_SURFACE_DW2_WIDTH__SHIFT;
+   dw3 = depth << GEN6_SURFACE_DW3_DEPTH__SHIFT |
+         (info->struct_size - 1) << GEN6_SURFACE_DW3_PITCH__SHIFT;
+
+   STATIC_ASSERT(ARRAY_SIZE(surf->surface) >= 6);
+   surf->surface[0] = dw0;
+   surf->surface[1] = dw1;
+   surf->surface[2] = dw2;
+   surf->surface[3] = dw3;
+   surf->surface[4] = 0;
+   surf->surface[5] = 0;
+
+   surf->type = GEN6_SURFTYPE_BUFFER;
+   surf->min_lod = 0;
+   surf->mip_count = 0;
+
+   return true;
+}
+
+static bool
+surface_set_gen7_buffer_SURFACE_STATE(struct ilo_state_surface *surf,
+                                     const struct ilo_dev *dev,
+                                     const struct ilo_state_surface_buffer_info *info)
+{
+   uint32_t dw0, dw1, dw2, dw3, dw7;
+   enum gen_surface_type type;
+   uint32_t struct_count;
+   int width, height, depth;
+
+   ILO_DEV_ASSERT(dev, 7, 8);
+
+   if (!surface_validate_gen6_buffer(dev, info) ||
+       !surface_get_gen6_buffer_struct_count(dev, info, &struct_count))
+      return false;
+
+   type = (info->format == GEN6_FORMAT_RAW && info->struct_size > 1) ?
+      GEN7_SURFTYPE_STRBUF : GEN6_SURFTYPE_BUFFER;
+
+   /* bits [6:0] */
+   width  = (struct_count & 0x0000007f);
+   /* bits [20:7] */
+   height = (struct_count & 0x001fff80) >> 7;
+   /* bits [30:21] */
+   depth  = (struct_count & 0x7fe00000) >> 21;
+
+   dw0 = type << GEN7_SURFACE_DW0_TYPE__SHIFT |
+         info->format << GEN7_SURFACE_DW0_FORMAT__SHIFT;
+   dw1 = (ilo_dev_gen(dev) >= ILO_GEN(8)) ? 0 : info->offset;
+   dw2 = GEN_SHIFT32(height, GEN7_SURFACE_DW2_HEIGHT) |
+         GEN_SHIFT32(width, GEN7_SURFACE_DW2_WIDTH);
+   dw3 = GEN_SHIFT32(depth, GEN7_SURFACE_DW3_DEPTH) |
+         GEN_SHIFT32(info->struct_size - 1, GEN7_SURFACE_DW3_PITCH);
+
+   dw7 = 0;
+   if (ilo_dev_gen(dev) >= ILO_GEN(7.5)) {
+      dw7 |= GEN_SHIFT32(GEN75_SCS_RED,   GEN75_SURFACE_DW7_SCS_R) |
+             GEN_SHIFT32(GEN75_SCS_GREEN, GEN75_SURFACE_DW7_SCS_G) |
+             GEN_SHIFT32(GEN75_SCS_BLUE,  GEN75_SURFACE_DW7_SCS_B) |
+             GEN_SHIFT32(GEN75_SCS_ALPHA, GEN75_SURFACE_DW7_SCS_A);
+   }
+
+   STATIC_ASSERT(ARRAY_SIZE(surf->surface) >= 13);
+   surf->surface[0] = dw0;
+   surf->surface[1] = dw1;
+   surf->surface[2] = dw2;
+   surf->surface[3] = dw3;
+   surf->surface[4] = 0;
+   surf->surface[5] = 0;
+   surf->surface[6] = 0;
+   surf->surface[7] = dw7;
+   if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
+      surf->surface[8] = info->offset;
+      surf->surface[9] = 0;
+      surf->surface[10] = 0;
+      surf->surface[11] = 0;
+      surf->surface[12] = 0;
+   }
+
+   surf->type = type;
+   surf->min_lod = 0;
+   surf->mip_count = 0;
+
+   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 bool
+surface_validate_gen6_image(const struct ilo_dev *dev,
+                            const struct ilo_state_surface_image_info *info)
+{
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   switch (info->access) {
+   case ILO_STATE_SURFACE_ACCESS_SAMPLER:
+   case ILO_STATE_SURFACE_ACCESS_DP_RENDER:
+      break;
+   case ILO_STATE_SURFACE_ACCESS_DP_TYPED:
+      assert(ilo_dev_gen(dev) >= ILO_GEN(7));
+      break;
+   default:
+      assert(!"unsupported surface access");
+      break;
+   }
+
+   /*
+    * From the Sandy Bridge PRM, volume 4 part 1, page 78:
+    *
+    *     "For surface types other than SURFTYPE_BUFFER, the Width specified
+    *      by this field must be less than or equal to the surface pitch
+    *      (specified in bytes via the Surface Pitch field)."
+    */
+   assert(info->img->bo_stride && info->img->bo_stride <= 512 * 1024 &&
+          info->img->width0 <= info->img->bo_stride);
+
+   if (info->is_cube_map) {
+      assert(get_gen6_surface_type(dev, info->img) == GEN6_SURFTYPE_2D);
+
+      /*
+       * From the Sandy Bridge PRM, volume 4 part 1, page 78:
+       *
+       *     "For cube maps, Width must be set equal to the Height."
+       */
+      assert(info->img->width0 == info->img->height0);
+   }
+
+   /*
+    * From the Sandy Bridge PRM, volume 4 part 1, page 72:
+    *
+    *     "Tile Walk TILEWALK_YMAJOR is UNDEFINED for render target formats
+    *      that have 128 bits-per-element (BPE)."
+    *
+    *     "If Number of Multisamples is set to a value other than
+    *      MULTISAMPLECOUNT_1, this field cannot be set to the following
+    *      formats:
+    *
+    *      - any format with greater than 64 bits per element
+    *      - any compressed texture format (BC*)
+    *      - any YCRCB* format"
+    *
+    * From the Ivy Bridge PRM, volume 4 part 1, page 63:
+    *
+    *      If Number of Multisamples is set to a value other than
+    *      MULTISAMPLECOUNT_1, this field cannot be set to the following
+    *      formats: any format with greater than 64 bits per element, if
+    *      Number of Multisamples is MULTISAMPLECOUNT_8, any compressed
+    *      texture format (BC*), and any YCRCB* format.
+    *
+    * TODO
+    */
+
+   if (ilo_dev_gen(dev) < ILO_GEN(8) && info->img->tiling == GEN8_TILING_W) {
+      ilo_warn("tiling W is not supported\n");
+      return false;
+   }
+
+   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 bool
+surface_get_gen6_image_extent(const struct ilo_dev *dev,
+                              const struct ilo_state_surface_image_info *info,
+                              uint16_t *width, uint16_t *height)
+{
+   uint16_t w, h, max_w, max_h;
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   w = info->img->width0;
+   h = info->img->height0;
+
+   get_gen6_max_extent(dev, info->img, &max_w, &max_h);
+   assert(w && h && w <= max_w && h <= max_h);
+
+   *width = w - 1;
+   *height = h - 1;
+
+   return true;
+}
+
+static bool
+surface_get_gen6_image_slices(const struct ilo_dev *dev,
+                              const struct ilo_state_surface_image_info *info,
+                              uint16_t *depth, uint16_t *min_array_elem,
+                              uint16_t *rt_view_extent)
+{
+   uint16_t max_slice, d;
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   /*
+    * From the Ivy Bridge PRM, volume 4 part 1, page 63:
+    *
+    *     "If this field (Surface Array) is enabled, the Surface Type must be
+    *      SURFTYPE_1D, SURFTYPE_2D, or SURFTYPE_CUBE. If this field is
+    *      disabled and Surface Type is SURFTYPE_1D, SURFTYPE_2D, or
+    *      SURFTYPE_CUBE, the Depth field must be set to zero."
+    *
+    * From the Ivy Bridge PRM, volume 4 part 1, page 69:
+    *
+    *     "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."
+    *
+    *     "For SURFTYPE_CUBE:For Sampling Engine Surfaces, the range of this
+    *      field is [0,340], indicating the number of cube array elements
+    *      (equal to the number of underlying 2D array elements divided by 6).
+    *      For other surfaces, this field must be zero."
+    *
+    *     "Errata: For SURFTYPE_CUBE sampling engine surfaces, the range of
+    *      this field is limited to [0,85].
+    *
+    *      Errata: If Surface Array is enabled, and Depth is between 1024 and
+    *      2047, an incorrect array slice may be accessed if the requested
+    *      array index in the message is greater than or equal to 4096."
+    *
+    * The errata are for Gen7-specific, and they limit the number of useable
+    * layers to (86 * 6), about 512.
+    */
+
+   switch (get_gen6_surface_type(dev, info->img)) {
+   case GEN6_SURFTYPE_1D:
+   case GEN6_SURFTYPE_2D:
+      max_slice = (ilo_dev_gen(dev) >= ILO_GEN(7.5)) ? 2048 : 512;
+
+      assert(info->img->array_size <= max_slice);
+      max_slice = info->img->array_size;
+
+      d = info->slice_count;
+      if (info->is_cube_map) {
+         if (info->access == ILO_STATE_SURFACE_ACCESS_SAMPLER) {
+            if (!d || d % 6) {
+               ilo_warn("invalid cube slice count\n");
+               return false;
+            }
+
+            if (ilo_dev_gen(dev) == ILO_GEN(7) && d > 86 * 6) {
+               ilo_warn("cube slice count exceeds Gen7 limit\n");
+               return false;
+            }
+         } else {
+            /*
+             * Minumum Array Element and Depth must be 0; Render Target View
+             * Extent is ignored.
+             */
+            if (info->slice_base || d != 6) {
+               ilo_warn("no cube RT array support in data port\n");
+               return false;
+            }
+         }
+
+         d /= 6;
+      }
+
+      if (!info->is_array && d > 1) {
+         ilo_warn("non-array surface with non-zero depth\n");
+         return false;
+      }
+      break;
+   case GEN6_SURFTYPE_3D:
+      max_slice = 2048;
+
+      assert(info->img->depth0 <= max_slice);
+      max_slice = u_minify(info->img->depth0, info->level_base);
+
+      d = info->img->depth0;
+
+      if (info->is_array) {
+         ilo_warn("3D surfaces cannot be arrays\n");
+         return false;
+      }
+      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 4 part 1, page 84:
+    *
+    *     "For Sampling Engine and Render Target 1D and 2D Surfaces:
+    *      This field (Minimum Array Element) indicates the minimum array
+    *      element that can be accessed as part of this surface.  This field
+    *      is added to the delivered array index before it is used to address
+    *      the surface.
+    *
+    *      For Render Target 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 Sampling Engine Cube Surfaces on [DevSNB+] only:
+    *      This field indicates the minimum array element in the underlying 2D
+    *      surface array that can be accessed as part of this surface (the
+    *      cube array index is multipled by 6 to compute this value, although
+    *      this field is not restricted to only multiples of 6). This field is
+    *      added to the delivered array index before it is used to address the
+    *      surface.
+    *
+    *      For Other Surfaces:
+    *      This field must be set to zero."
+    *
+    * On Gen7+, typed sufaces are treated like sampling engine 1D and 2D
+    * surfaces.
+    */
+   *min_array_elem = info->slice_base;
+
+   /*
+    * From the Sandy Bridge PRM, volume 4 part 1, page 84:
+    *
+    *     "For Render Target 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 Render Target 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
+surface_get_gen6_image_levels(const struct ilo_dev *dev,
+                              const struct ilo_state_surface_image_info *info,
+                              uint8_t *min_lod, uint8_t *mip_count)
+{
+   uint8_t max_level = (ilo_dev_gen(dev) >= ILO_GEN(7)) ? 15 : 14;
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   assert(info->img->level_count <= max_level);
+   max_level = info->img->level_count;
+
+   if (!info->level_count ||
+       info->level_base + info->level_count > max_level) {
+      ilo_warn("invalid level range\n");
+      return false;
+   }
+
+   /*
+    * From the Sandy Bridge PRM, volume 4 part 1, page 79:
+    *
+    *     "For Sampling Engine Surfaces:
+    *      This field (MIP Count / LOD) indicates the number of MIP levels
+    *      allowed to be accessed starting at Surface Min LOD, which must be
+    *      less than or equal to the number of MIP levels actually stored in
+    *      memory for this surface.
+    *
+    *      Force the mip map access to be between the mipmap specified by the
+    *      integer bits of the Min LOD and the ceiling of the value specified
+    *      here.
+    *
+    *      For Render Target Surfaces:
+    *      This field defines the MIP level that is currently being rendered
+    *      into. This is the absolute MIP level on the surface and is not
+    *      relative to the Surface Min LOD field, which is ignored for render
+    *      target surfaces.
+    *
+    *      For Other Surfaces:
+    *      This field is reserved : MBZ"
+    *
+    * From the Sandy Bridge PRM, volume 4 part 1, page 83:
+    *
+    *     "For Sampling Engine Surfaces:
+    *
+    *      This field (Surface Min LOD) indicates the most detailed LOD that
+    *      can be accessed as part of this surface.  This field is added to
+    *      the delivered LOD (sample_l, ld, or resinfo message types) before
+    *      it is used to address the surface.
+    *
+    *      For Other Surfaces:
+    *      This field is ignored."
+    *
+    * On Gen7+, typed sufaces are treated like sampling engine surfaces.
+    */
+   if (info->access == ILO_STATE_SURFACE_ACCESS_DP_RENDER) {
+      assert(info->level_count == 1);
+
+      *min_lod = 0;
+      *mip_count = info->level_base;
+   } else {
+      *min_lod = info->level_base;
+      *mip_count = info->level_count - 1;
+   }
+
+   return true;
+}
+
+static bool
+surface_get_gen6_image_sample_count(const struct ilo_dev *dev,
+                                    const struct ilo_state_surface_image_info *info,
+                                    enum gen_sample_count *sample_count)
+{
+   int min_gen;
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   switch (info->img->sample_count) {
+   case 1:
+      *sample_count = GEN6_NUMSAMPLES_1;
+      min_gen = ILO_GEN(6);
+      break;
+   case 2:
+      *sample_count = GEN8_NUMSAMPLES_2;
+      min_gen = ILO_GEN(8);
+      break;
+   case 4:
+      *sample_count = GEN6_NUMSAMPLES_4;
+      min_gen = ILO_GEN(6);
+      break;
+   case 8:
+      *sample_count = GEN7_NUMSAMPLES_8;
+      min_gen = ILO_GEN(7);
+      break;
+   case 16:
+      *sample_count = GEN8_NUMSAMPLES_16;
+      min_gen = ILO_GEN(8);
+      break;
+   default:
+      assert(!"invalid sample count");
+      *sample_count = GEN6_NUMSAMPLES_1;
+      break;
+   }
+
+   assert(ilo_dev_gen(dev) >= min_gen);
+
+   return true;
+}
+
+static bool
+surface_get_gen6_image_alignments(const struct ilo_dev *dev,
+                                  const struct ilo_state_surface_image_info *info,
+                                  uint32_t *alignments)
+{
+   uint32_t a = 0;
+   bool err = false;
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
+      switch (info->img->align_i) {
+      case 4:
+         a |= GEN8_SURFACE_DW0_HALIGN_4;
+         break;
+      case 8:
+         a |= GEN8_SURFACE_DW0_HALIGN_8;
+         break;
+      case 16:
+         a |= GEN8_SURFACE_DW0_HALIGN_16;
+         break;
+      default:
+         err = true;
+         break;
+      }
+
+      switch (info->img->align_j) {
+      case 4:
+         a |= GEN7_SURFACE_DW0_VALIGN_4;
+         break;
+      case 8:
+         a |= GEN8_SURFACE_DW0_VALIGN_8;
+         break;
+      case 16:
+         a |= GEN8_SURFACE_DW0_VALIGN_16;
+         break;
+      default:
+         err = true;
+         break;
+      }
+   } else if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
+      switch (info->img->align_i) {
+      case 4:
+         a |= GEN7_SURFACE_DW0_HALIGN_4;
+         break;
+      case 8:
+         a |= GEN7_SURFACE_DW0_HALIGN_8;
+         break;
+      default:
+         err = true;
+         break;
+      }
+
+      switch (info->img->align_j) {
+      case 2:
+         a |= GEN7_SURFACE_DW0_VALIGN_2;
+         break;
+      case 4:
+         a |= GEN7_SURFACE_DW0_VALIGN_4;
+         break;
+      default:
+         err = true;
+         break;
+      }
+   } else {
+      if (info->img->align_i != 4)
+         err = true;
+
+      switch (info->img->align_j) {
+      case 2:
+         a |= GEN6_SURFACE_DW5_VALIGN_2;
+         break;
+      case 4:
+         a |= GEN6_SURFACE_DW5_VALIGN_4;
+         break;
+      default:
+         err = true;
+         break;
+      }
+   }
+
+   if (err)
+      assert(!"invalid HALIGN or VALIGN");
+
+   *alignments = a;
+
+   return true;
+}
+
+static bool
+surface_set_gen6_image_SURFACE_STATE(struct ilo_state_surface *surf,
+                                     const struct ilo_dev *dev,
+                                     const struct ilo_state_surface_image_info *info)
+{
+   uint16_t width, height, depth, array_base, view_extent;
+   uint8_t min_lod, mip_count;
+   enum gen_sample_count sample_count;
+   uint32_t alignments;
+   enum gen_surface_type type;
+   uint32_t dw0, dw2, dw3, dw4, dw5;
+
+   ILO_DEV_ASSERT(dev, 6, 6);
+
+   if (!surface_validate_gen6_image(dev, info) ||
+       !surface_get_gen6_image_extent(dev, info, &width, &height) ||
+       !surface_get_gen6_image_slices(dev, info, &depth, &array_base,
+                                      &view_extent) ||
+       !surface_get_gen6_image_levels(dev, info, &min_lod, &mip_count) ||
+       !surface_get_gen6_image_sample_count(dev, info, &sample_count) ||
+       !surface_get_gen6_image_alignments(dev, info, &alignments))
+      return false;
+
+   /* no ARYSPC_LOD0 */
+   assert(info->img->walk != ILO_IMAGE_WALK_LOD);
+   /* no UMS/CMS */
+   if (info->img->sample_count > 1)
+      assert(info->img->interleaved_samples);
+
+   type = (info->is_cube_map) ? GEN6_SURFTYPE_CUBE :
+      get_gen6_surface_type(dev, info->img);
+
+   dw0 = type << GEN6_SURFACE_DW0_TYPE__SHIFT |
+         info->format << GEN6_SURFACE_DW0_FORMAT__SHIFT |
+         GEN6_SURFACE_DW0_MIPLAYOUT_BELOW;
+
+   /*
+    * From the Sandy Bridge PRM, volume 4 part 1, page 74:
+    *
+    *     "CUBE_AVERAGE may only be selected if all of the Cube Face Enable
+    *      fields are equal to one."
+    *
+    * From the Sandy Bridge PRM, volume 4 part 1, page 75-76:
+    *
+    *     "For SURFTYPE_CUBE Surfaces accessed via the Sampling Engine:
+    *      Bits 5:0 of this field (Cube Face Enables) enable the individual
+    *      faces of a cube map.  Enabling a face indicates that the face is
+    *      present in the cube map, while disabling it indicates that that
+    *      face is represented by the texture map's border color. Refer to
+    *      Memory Data Formats for the correlation between faces and the cube
+    *      map memory layout. Note that storage for disabled faces must be
+    *      provided.
+    *
+    *      For other surfaces:
+    *      This field is reserved : MBZ"
+    *
+    *     "When TEXCOORDMODE_CLAMP is used when accessing a cube map, this
+    *      field must be programmed to 111111b (all faces enabled)."
+    */
+   if (info->is_cube_map &&
+       info->access == ILO_STATE_SURFACE_ACCESS_SAMPLER) {
+      dw0 |= GEN6_SURFACE_DW0_CUBE_MAP_CORNER_MODE_AVERAGE |
+             GEN6_SURFACE_DW0_CUBE_FACE_ENABLES__MASK;
+   }
+
+   dw2 = height << GEN6_SURFACE_DW2_HEIGHT__SHIFT |
+         width << GEN6_SURFACE_DW2_WIDTH__SHIFT |
+         mip_count << GEN6_SURFACE_DW2_MIP_COUNT_LOD__SHIFT;
+
+   dw3 = depth << GEN6_SURFACE_DW3_DEPTH__SHIFT |
+         (info->img->bo_stride - 1) << GEN6_SURFACE_DW3_PITCH__SHIFT |
+         info->img->tiling << GEN6_SURFACE_DW3_TILING__SHIFT;
+
+   dw4 = min_lod << GEN6_SURFACE_DW4_MIN_LOD__SHIFT |
+         array_base << GEN6_SURFACE_DW4_MIN_ARRAY_ELEMENT__SHIFT |
+         view_extent << GEN6_SURFACE_DW4_RT_VIEW_EXTENT__SHIFT |
+         sample_count << GEN6_SURFACE_DW4_MULTISAMPLECOUNT__SHIFT;
+
+   dw5 = alignments;
+
+   STATIC_ASSERT(ARRAY_SIZE(surf->surface) >= 6);
+   surf->surface[0] = dw0;
+   surf->surface[1] = 0;
+   surf->surface[2] = dw2;
+   surf->surface[3] = dw3;
+   surf->surface[4] = dw4;
+   surf->surface[5] = dw5;
+
+   surf->type = type;
+   surf->min_lod = min_lod;
+   surf->mip_count = mip_count;
+
+   return true;
+}
+
+static bool
+surface_set_gen7_image_SURFACE_STATE(struct ilo_state_surface *surf,
+                                     const struct ilo_dev *dev,
+                                     const struct ilo_state_surface_image_info *info)
+{
+   uint16_t width, height, depth, array_base, view_extent;
+   uint8_t min_lod, mip_count;
+   uint32_t alignments;
+   enum gen_sample_count sample_count;
+   enum gen_surface_type type;
+   uint32_t dw0, dw1, dw2, dw3, dw4, dw5, dw7;
+
+   ILO_DEV_ASSERT(dev, 7, 8);
+
+   if (!surface_validate_gen6_image(dev, info) ||
+       !surface_get_gen6_image_extent(dev, info, &width, &height) ||
+       !surface_get_gen6_image_slices(dev, info, &depth, &array_base,
+                                      &view_extent) ||
+       !surface_get_gen6_image_levels(dev, info, &min_lod, &mip_count) ||
+       !surface_get_gen6_image_sample_count(dev, info, &sample_count) ||
+       !surface_get_gen6_image_alignments(dev, info, &alignments))
+      return false;
+
+   type = (info->is_cube_map) ? GEN6_SURFTYPE_CUBE :
+      get_gen6_surface_type(dev, info->img);
+
+   dw0 = type << GEN7_SURFACE_DW0_TYPE__SHIFT |
+         info->format << GEN7_SURFACE_DW0_FORMAT__SHIFT |
+         alignments;
+
+   if (info->is_array)
+      dw0 |= GEN7_SURFACE_DW0_IS_ARRAY;
+
+   if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
+      dw0 |= info->img->tiling << GEN8_SURFACE_DW0_TILING__SHIFT;
+   } else {
+      dw0 |= info->img->tiling << GEN7_SURFACE_DW0_TILING__SHIFT;
+
+      if (info->img->walk == ILO_IMAGE_WALK_LOD)
+         dw0 |= GEN7_SURFACE_DW0_ARYSPC_LOD0;
+      else
+         dw0 |= GEN7_SURFACE_DW0_ARYSPC_FULL;
+   }
+
+   /*
+    * From the Ivy Bridge PRM, volume 4 part 1, page 67:
+    *
+    *     "For SURFTYPE_CUBE Surfaces accessed via the Sampling Engine: Bits
+    *      5:0 of this field (Cube Face Enables) enable the individual faces
+    *      of a cube map. Enabling a face indicates that the face is present
+    *      in the cube map, while disabling it indicates that that face is
+    *      represented by the texture map's border color. Refer to Memory Data
+    *      Formats for the correlation between faces and the cube map memory
+    *      layout. Note that storage for disabled faces must be provided. For
+    *      other surfaces this field is reserved and MBZ."
+    *
+    *     "When TEXCOORDMODE_CLAMP is used when accessing a cube map, this
+    *      field must be programmed to 111111b (all faces enabled). This field
+    *      is ignored unless the Surface Type is SURFTYPE_CUBE."
+    */
+   if (info->is_cube_map &&
+       info->access == ILO_STATE_SURFACE_ACCESS_SAMPLER)
+      dw0 |= GEN7_SURFACE_DW0_CUBE_FACE_ENABLES__MASK;
+
+   dw1 = 0;
+   if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
+      assert(info->img->walk_layer_height % 4 == 0);
+      dw1 |= info->img->walk_layer_height / 4 <<
+         GEN8_SURFACE_DW1_QPITCH__SHIFT;
+   }
+
+   dw2 = height << GEN7_SURFACE_DW2_HEIGHT__SHIFT |
+         width << GEN7_SURFACE_DW2_WIDTH__SHIFT;
+
+   dw3 = depth << GEN7_SURFACE_DW3_DEPTH__SHIFT |
+         (info->img->bo_stride - 1) << GEN7_SURFACE_DW3_PITCH__SHIFT;
+
+   if (ilo_dev_gen(dev) == ILO_GEN(7.5))
+      dw3 |= 0 << GEN75_SURFACE_DW3_INTEGER_SURFACE_FORMAT__SHIFT;
+
+   dw4 = array_base << GEN7_SURFACE_DW4_MIN_ARRAY_ELEMENT__SHIFT |
+         view_extent << GEN7_SURFACE_DW4_RT_VIEW_EXTENT__SHIFT |
+         sample_count << GEN7_SURFACE_DW4_MULTISAMPLECOUNT__SHIFT;
+
+   /*
+    * MSFMT_MSS means the samples are not interleaved and MSFMT_DEPTH_STENCIL
+    * means the samples are interleaved.  The layouts are the same when the
+    * number of samples is 1.
+    */
+   if (info->img->interleaved_samples && info->img->sample_count > 1) {
+      assert(info->access != ILO_STATE_SURFACE_ACCESS_DP_RENDER);
+      dw4 |= GEN7_SURFACE_DW4_MSFMT_DEPTH_STENCIL;
+   } else {
+      dw4 |= GEN7_SURFACE_DW4_MSFMT_MSS;
+   }
+
+   dw5 = min_lod << GEN7_SURFACE_DW5_MIN_LOD__SHIFT |
+         mip_count << GEN7_SURFACE_DW5_MIP_COUNT_LOD__SHIFT;
+
+   dw7 = 0;
+   if (ilo_dev_gen(dev) >= ILO_GEN(7.5)) {
+      dw7 |= GEN_SHIFT32(GEN75_SCS_RED,   GEN75_SURFACE_DW7_SCS_R) |
+             GEN_SHIFT32(GEN75_SCS_GREEN, GEN75_SURFACE_DW7_SCS_G) |
+             GEN_SHIFT32(GEN75_SCS_BLUE,  GEN75_SURFACE_DW7_SCS_B) |
+             GEN_SHIFT32(GEN75_SCS_ALPHA, GEN75_SURFACE_DW7_SCS_A);
+   }
+
+   STATIC_ASSERT(ARRAY_SIZE(surf->surface) >= 13);
+   surf->surface[0] = dw0;
+   surf->surface[1] = dw1;
+   surf->surface[2] = dw2;
+   surf->surface[3] = dw3;
+   surf->surface[4] = dw4;
+   surf->surface[5] = dw5;
+   surf->surface[6] = 0;
+   surf->surface[7] = dw7;
+   if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
+      surf->surface[8] = 0;
+      surf->surface[9] = 0;
+      surf->surface[10] = 0;
+      surf->surface[11] = 0;
+      surf->surface[12] = 0;
+   }
+
+   surf->type = type;
+   surf->min_lod = min_lod;
+   surf->mip_count = mip_count;
+
+   return true;
+}
+
+bool
+ilo_state_surface_init_for_null(struct ilo_state_surface *surf,
+                                const struct ilo_dev *dev)
+{
+   bool ret = true;
+
+   assert(ilo_is_zeroed(surf, sizeof(*surf)));
+
+   if (ilo_dev_gen(dev) >= ILO_GEN(7))
+      ret &= surface_set_gen7_null_SURFACE_STATE(surf, dev);
+   else
+      ret &= surface_set_gen6_null_SURFACE_STATE(surf, dev);
+
+   surf->type = GEN6_SURFTYPE_NULL;
+   surf->readonly = true;
+
+   assert(ret);
+
+   return ret;
+}
+
+bool
+ilo_state_surface_init_for_buffer(struct ilo_state_surface *surf,
+                                  const struct ilo_dev *dev,
+                                  const struct ilo_state_surface_buffer_info *info)
+{
+   bool ret = true;
+
+   assert(ilo_is_zeroed(surf, sizeof(*surf)));
+
+   if (ilo_dev_gen(dev) >= ILO_GEN(7))
+      ret &= surface_set_gen7_buffer_SURFACE_STATE(surf, dev, info);
+   else
+      ret &= surface_set_gen6_buffer_SURFACE_STATE(surf, dev, info);
+
+   surf->readonly = info->readonly;
+
+   assert(ret);
+
+   return ret;
+}
+
+bool
+ilo_state_surface_init_for_image(struct ilo_state_surface *surf,
+                                 const struct ilo_dev *dev,
+                                 const struct ilo_state_surface_image_info *info)
+{
+   bool ret = true;
+
+   assert(ilo_is_zeroed(surf, sizeof(*surf)));
+
+   if (ilo_dev_gen(dev) >= ILO_GEN(7))
+      ret &= surface_set_gen7_image_SURFACE_STATE(surf, dev, info);
+   else
+      ret &= surface_set_gen6_image_SURFACE_STATE(surf, dev, info);
+
+   surf->is_integer = info->is_integer;
+   surf->readonly = info->readonly;
+   surf->scanout = info->img->scanout;
+
+   assert(ret);
+
+   return ret;
+}
+
+bool
+ilo_state_surface_set_scs(struct ilo_state_surface *surf,
+                          const struct ilo_dev *dev,
+                          enum gen_surface_scs rgba[4])
+{
+   const uint32_t scs = GEN_SHIFT32(rgba[0], GEN75_SURFACE_DW7_SCS_R) |
+                        GEN_SHIFT32(rgba[1], GEN75_SURFACE_DW7_SCS_G) |
+                        GEN_SHIFT32(rgba[2], GEN75_SURFACE_DW7_SCS_B) |
+                        GEN_SHIFT32(rgba[3], GEN75_SURFACE_DW7_SCS_A);
+
+   ILO_DEV_ASSERT(dev, 6, 8);
+
+   assert(ilo_dev_gen(dev) >= ILO_GEN(7.5));
+
+   surf->surface[7] = (surf->surface[7] & ~GEN75_SURFACE_DW7_SCS__MASK) | scs;
+
+   return true;
+}
diff --git a/src/gallium/drivers/ilo/core/ilo_state_surface.h b/src/gallium/drivers/ilo/core/ilo_state_surface.h
new file mode 100644 (file)
index 0000000..deb0b54
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * 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_SURFACE_H
+#define ILO_STATE_SURFACE_H
+
+#include "genhw/genhw.h"
+#include "intel_winsys.h"
+
+#include "ilo_core.h"
+#include "ilo_dev.h"
+
+struct ilo_buffer;
+struct ilo_image;
+
+enum ilo_state_surface_access {
+   ILO_STATE_SURFACE_ACCESS_SAMPLER,      /* sampling engine surfaces */
+   ILO_STATE_SURFACE_ACCESS_DP_RENDER,    /* render target surfaces */
+   ILO_STATE_SURFACE_ACCESS_DP_TYPED,     /* typed surfaces */
+   ILO_STATE_SURFACE_ACCESS_DP_UNTYPED,   /* untyped surfaces */
+   ILO_STATE_SURFACE_ACCESS_DP_DATA,
+   ILO_STATE_SURFACE_ACCESS_DP_SVB,
+};
+
+struct ilo_state_surface_buffer_info {
+   const struct ilo_buffer *buf;
+
+   enum ilo_state_surface_access access;
+
+   enum gen_surface_format format;
+   uint8_t format_size;
+
+   bool readonly;
+   uint16_t struct_size;
+
+   uint32_t offset;
+   uint32_t size;
+};
+
+struct ilo_state_surface_image_info {
+   const struct ilo_image *img;
+
+   enum ilo_state_surface_access access;
+
+   enum gen_surface_format format;
+   bool is_integer;
+
+   bool readonly;
+   bool is_cube_map;
+   bool is_array;
+
+   uint8_t level_base;
+   uint8_t level_count;
+   uint16_t slice_base;
+   uint16_t slice_count;
+};
+
+struct ilo_state_surface {
+   uint32_t surface[13];
+
+   enum gen_surface_type type;
+   uint8_t min_lod;
+   uint8_t mip_count;
+   bool is_integer;
+
+   bool readonly;
+   bool scanout;
+
+   /* managed by users */
+   struct intel_bo *bo;
+};
+
+bool
+ilo_state_surface_init_for_null(struct ilo_state_surface *surf,
+                                const struct ilo_dev *dev);
+
+bool
+ilo_state_surface_init_for_buffer(struct ilo_state_surface *surf,
+                                  const struct ilo_dev *dev,
+                                  const struct ilo_state_surface_buffer_info *info);
+
+bool
+ilo_state_surface_init_for_image(struct ilo_state_surface *surf,
+                                 const struct ilo_dev *dev,
+                                 const struct ilo_state_surface_image_info *info);
+
+bool
+ilo_state_surface_set_scs(struct ilo_state_surface *surf,
+                          const struct ilo_dev *dev,
+                          enum gen_surface_scs rgba[4]);
+
+#endif /* ILO_STATE_SURFACE_H */