intel/isl: Add a helper to get a subimage surface
authorJason Ekstrand <jason.ekstrand@intel.com>
Tue, 11 Jul 2017 21:27:25 +0000 (14:27 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Sun, 23 Jul 2017 04:41:12 +0000 (21:41 -0700)
We already have a helper for doing this in BLORP, this just moves the
logic into ISL where we can share it with other components.

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
src/intel/blorp/blorp_blit.c
src/intel/isl/isl.c
src/intel/isl/isl.h

index 91d2a22794970c29bbe99612b938cb7900b22bca..ed005163733c7a2c3d6f11a2401adfd3ae9f3593 100644 (file)
@@ -1406,42 +1406,24 @@ blorp_surf_convert_to_single_slice(const struct isl_device *isl_dev,
       layer = info->view.base_array_layer;
 
    uint32_t byte_offset;
-   isl_surf_get_image_offset_B_tile_sa(&info->surf,
-                                       info->view.base_level, layer, z,
-                                       &byte_offset,
-                                       &info->tile_x_sa, &info->tile_y_sa);
+   isl_surf_get_image_surf(isl_dev, &info->surf,
+                           info->view.base_level, layer, z,
+                           &info->surf,
+                           &byte_offset, &info->tile_x_sa, &info->tile_y_sa);
    info->addr.offset += byte_offset;
 
-   const uint32_t slice_width_px =
-      minify(info->surf.logical_level0_px.width, info->view.base_level);
-   const uint32_t slice_height_px =
-      minify(info->surf.logical_level0_px.height, info->view.base_level);
-
    uint32_t tile_x_px, tile_y_px;
    surf_get_intratile_offset_px(info, &tile_x_px, &tile_y_px);
 
-   /* Even for cube maps there will be only single face, therefore drop the
-    * corresponding flag if present.
+   /* Instead of using the X/Y Offset fields in RENDER_SURFACE_STATE, we place
+    * the image at the tile boundary and offset our sampling or rendering.
+    * For this reason, we need to grow the image by the offset to ensure that
+    * the hardware doesn't think we've gone past the edge.
     */
-   const isl_surf_usage_flags_t without_cube_map_flag =
-      info->surf.usage & (~ISL_SURF_USAGE_CUBE_BIT);
-
-   struct isl_surf_init_info init_info = {
-      .dim = ISL_SURF_DIM_2D,
-      .format = info->surf.format,
-      .width = slice_width_px + tile_x_px,
-      .height = slice_height_px + tile_y_px,
-      .depth = 1,
-      .levels = 1,
-      .array_len = 1,
-      .samples = info->surf.samples,
-      .row_pitch = info->surf.row_pitch,
-      .usage = without_cube_map_flag,
-      .tiling_flags = 1 << info->surf.tiling,
-   };
-
-   ok = isl_surf_init_s(isl_dev, &info->surf, &init_info);
-   assert(ok);
+   info->surf.logical_level0_px.w += tile_x_px;
+   info->surf.logical_level0_px.h += tile_y_px;
+   info->surf.phys_level0_sa.w += info->tile_x_sa;
+   info->surf.phys_level0_sa.h += info->tile_y_sa;
 
    /* The view is also different now. */
    info->view.base_level = 0;
index fba40caff419f1b5f82871de2653f0dc98e014b9..5e3d279b0b64b9a8d1cbef048aee5f83b89b7850 100644 (file)
@@ -2317,6 +2317,47 @@ isl_surf_get_image_offset_B_tile_sa(const struct isl_surf *surf,
    }
 }
 
+void
+isl_surf_get_image_surf(const struct isl_device *dev,
+                        const struct isl_surf *surf,
+                        uint32_t level,
+                        uint32_t logical_array_layer,
+                        uint32_t logical_z_offset_px,
+                        struct isl_surf *image_surf,
+                        uint32_t *offset_B,
+                        uint32_t *x_offset_sa,
+                        uint32_t *y_offset_sa)
+{
+   isl_surf_get_image_offset_B_tile_sa(surf,
+                                       level,
+                                       logical_array_layer,
+                                       logical_z_offset_px,
+                                       offset_B,
+                                       x_offset_sa,
+                                       y_offset_sa);
+
+   /* Even for cube maps there will be only single face, therefore drop the
+    * corresponding flag if present.
+    */
+   const isl_surf_usage_flags_t usage =
+      surf->usage & (~ISL_SURF_USAGE_CUBE_BIT);
+
+   bool ok UNUSED;
+   ok = isl_surf_init(dev, image_surf,
+                      .dim = ISL_SURF_DIM_2D,
+                      .format = surf->format,
+                      .width = isl_minify(surf->logical_level0_px.w, level),
+                      .height = isl_minify(surf->logical_level0_px.h, level),
+                      .depth = 1,
+                      .levels = 1,
+                      .array_len = 1,
+                      .samples = surf->samples,
+                      .row_pitch = surf->row_pitch,
+                      .usage = usage,
+                      .tiling_flags = (1 << surf->tiling));
+   assert(ok);
+}
+
 void
 isl_tiling_get_intratile_offset_el(enum isl_tiling tiling,
                                    uint32_t bpb,
index 1e5b86895421824f5d8e93e64fe26f045499e34c..dafe952298e8876206e2607bc97e13f4e3b7f80f 100644 (file)
@@ -1841,6 +1841,29 @@ isl_surf_get_image_offset_B_tile_sa(const struct isl_surf *surf,
                                     uint32_t *x_offset_sa,
                                     uint32_t *y_offset_sa);
 
+/**
+ * Create an isl_surf that represents a particular subimage in the surface.
+ *
+ * The newly created surface will have a single miplevel and array slice.  The
+ * surface lives at the returned byte and intratile offsets, in samples.
+ *
+ * It is safe to call this function with surf == image_surf.
+ *
+ * @invariant level < surface levels
+ * @invariant logical_array_layer < logical array length of surface
+ * @invariant logical_z_offset_px < logical depth of surface at level
+ */
+void
+isl_surf_get_image_surf(const struct isl_device *dev,
+                        const struct isl_surf *surf,
+                        uint32_t level,
+                        uint32_t logical_array_layer,
+                        uint32_t logical_z_offset_px,
+                        struct isl_surf *image_surf,
+                        uint32_t *offset_B,
+                        uint32_t *x_offset_sa,
+                        uint32_t *y_offset_sa);
+
 /**
  * @brief Calculate the intratile offsets to a surface.
  *