[Mesa-dev] [PATCH 25/30] i965/miptree: Allocate mcs_buf for an image's CCS

Jason Ekstrand jason at jlekstrand.net
Fri Jun 16 22:41:47 UTC 2017


From: Ben Widawsky <ben at bwidawsk.net>

This code will disable actually creating these buffers for the scanout,
but it puts the allocation in place.

Primarily this patch is split out for review, it can be squashed in
later if preferred.

v2:
assert(mt->offset == 0) in ccs creation (as requested by Topi)
Remove bogus is_scanout check in miptree_release

v3:
Remove is_scanout assert in intel_miptree_create. It doesn't work with
latest codebase - not sure it ever should have worked.

v4:
assert(mt->last_level == 0) and assert(mt->first_level == 0) in ccs setup
(Topi)

v5 (Jason Ekstrand):
 - Base the decision to allocate a CCS on the image modifier

Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
Acked-by: Daniel Stone <daniels at collabora.com>
Reviewed-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
---
 src/mesa/drivers/dri/i965/intel_mipmap_tree.c | 123 +++++++++++++++++++++++---
 1 file changed, 113 insertions(+), 10 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
index e3de386..608317a 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
@@ -59,6 +59,11 @@ intel_miptree_alloc_mcs(struct brw_context *brw,
                         struct intel_mipmap_tree *mt,
                         GLuint num_samples);
 
+static void
+intel_miptree_init_mcs(struct brw_context *brw,
+                       struct intel_mipmap_tree *mt,
+                       int init_value);
+
 /**
  * Determine which MSAA layout should be used by the MSAA surface being
  * created, based on the chip generation and the surface type.
@@ -886,27 +891,99 @@ miptree_create_for_planar_image(struct brw_context *brw,
    return planar_mt;
 }
 
+static bool
+create_ccs_buf_for_image(struct brw_context *brw,
+                         __DRIimage *image,
+                         struct intel_mipmap_tree *mt,
+                         enum isl_aux_state initial_state)
+{
+   struct isl_surf temp_main_surf, temp_ccs_surf;
+
+   /* There isn't anything specifically wrong with there being an offset, in
+    * which case, the CCS miptree's offset should be mt->offset +
+    * image->aux_offset. However, the code today only will have an offset when
+    * this miptree is pointing to a slice from another miptree, and in that case
+    * we'd need to offset within the AUX CCS buffer properly. It's questionable
+    * whether our code handles that case properly, and since it can never happen
+    * for scanout, just use the assertion to prevent it.
+    */
+   assert(mt->offset == 0);
+
+   /* CCS is only supported for very simple miptrees */
+   assert(image->aux_offset && image->aux_pitch);
+   assert(image->tile_x == 0 && image->tile_y == 0);
+   assert(mt->num_samples <= 1);
+   assert(mt->first_level == 0);
+   assert(mt->last_level == 0);
+   assert(mt->logical_depth0 == 1);
+
+   /* We shouldn't already have a CCS */
+   assert(!mt->mcs_buf);
+
+   intel_miptree_get_isl_surf(brw, mt, &temp_main_surf);
+   if (!isl_surf_get_ccs_surf(&brw->isl_dev, &temp_main_surf, &temp_ccs_surf))
+      return false;
+
+   assert(temp_ccs_surf.size <= image->bo->size - image->aux_offset);
+   assert(temp_ccs_surf.row_pitch <= image->aux_pitch);
+
+   mt->mcs_buf = calloc(sizeof(*mt->mcs_buf), 1);
+   if (mt->mcs_buf == NULL)
+      return false;
+
+   mt->aux_state = create_aux_state_map(mt, initial_state);
+   if (!mt->aux_state) {
+      free(mt->mcs_buf);
+      mt->mcs_buf = NULL;
+      return false;
+   }
+
+   mt->mcs_buf->bo = image->bo;
+   brw_bo_reference(image->bo);
+
+   mt->mcs_buf->offset = image->aux_offset;
+   mt->mcs_buf->size = image->bo->size - image->aux_offset;
+   mt->mcs_buf->pitch = image->aux_pitch;
+   mt->mcs_buf->qpitch = 0;
+
+   intel_miptree_init_mcs(brw, mt, 0);
+   mt->msaa_layout = INTEL_MSAA_LAYOUT_CMS;
+
+   return true;
+}
+
 struct intel_mipmap_tree *
 intel_miptree_create_for_dri_image(struct brw_context *brw,
                                    __DRIimage *image, GLenum target,
                                    mesa_format format,
                                    bool is_winsys_image)
 {
+   uint32_t mt_layout_flags = 0;
+
    if (image->planar_format && image->planar_format->nplanes > 0)
       return miptree_create_for_planar_image(brw, image, target);
 
    if (!brw->ctx.TextureFormatSupported[format])
       return NULL;
 
+   const struct isl_drm_modifier_info *mod_info =
+      isl_drm_modifier_get_info(image->modifier);
+
+   /* If this image comes in from a window system, then it may get promoted to
+    * scanout at any time so we need to set the flag accordingly.
+    */
+   if (is_winsys_image)
+      mt_layout_flags |= MIPTREE_LAYOUT_FOR_SCANOUT;
+
    /* If this image comes in from a window system, we have different
     * requirements than if it comes in via an EGL import operation.  Window
     * system images can use any form of auxiliary compression we wish because
     * they get "flushed" before being handed off to the window system and we
-    * have the opportunity to do resolves.  Window system buffers also may be
-    * used for scanout so we need to flag that appropriately.
+    * have the opportunity to do resolves.
     */
-   const uint32_t mt_layout_flags =
-      is_winsys_image ? MIPTREE_LAYOUT_FOR_SCANOUT : MIPTREE_LAYOUT_DISABLE_AUX;
+   if (!is_winsys_image &&
+       (!mod_info || mod_info->aux_usage == ISL_AUX_USAGE_NONE))
+      mt_layout_flags |= MIPTREE_LAYOUT_DISABLE_AUX;
 
    /* Disable creation of the texture's aux buffers because the driver exposes
     * no EGL API to manage them. That is, there is no API for resolving the aux
@@ -943,15 +1020,41 @@ intel_miptree_create_for_dri_image(struct brw_context *brw,
       }
    }
 
-   /* Since CCS_E can compress more than just clear color, we create the
-    * CCS for it up-front.  For CCS_D which only compresses clears, we
-    * create the CCS on-demand when a clear occurs that wants one.
-    */
-   if (mt->aux_usage == ISL_AUX_USAGE_CCS_E) {
-      if (!intel_miptree_alloc_ccs(brw, mt)) {
+   if (mod_info && mod_info->aux_usage != ISL_AUX_USAGE_NONE) {
+      assert(mod_info->aux_usage == ISL_AUX_USAGE_CCS_E);
+
+      mt->aux_usage = mod_info->aux_usage;
+      /* If we are a window system buffer, then we can support fast-clears
+       * even if the modifier doesn't support them by doing a partial resolve
+       * as part of the flush operation.
+       */
+      mt->supports_fast_clear =
+         is_winsys_image || mod_info->supports_clear_color;
+
+      /* We don't know the actual state of the surface when we get it but we
+       * can make a pretty good guess based on the modifier.  What we do know
+       * for sure is that it isn't in the AUX_INVALID state, so we just assume
+       * a worst case of compression.
+       */
+      enum isl_aux_state initial_state =
+         mod_info->supports_clear_color ? ISL_AUX_STATE_COMPRESSED_CLEAR :
+                                          ISL_AUX_STATE_COMPRESSED_NO_CLEAR;
+
+      if (!create_ccs_buf_for_image(brw, image, mt, initial_state)) {
          intel_miptree_release(&mt);
          return NULL;
       }
+   } else if (mt->aux_usage != ISL_AUX_USAGE_NONE) {
+      /* Since CCS_E can compress more than just clear color, we create the
+       * CCS for it up-front.  For CCS_D which only compresses clears, we
+       * create the CCS on-demand when a clear occurs that wants one.
+       */
+      if (mt->aux_usage == ISL_AUX_USAGE_CCS_E) {
+         if (!intel_miptree_alloc_ccs(brw, mt)) {
+            intel_miptree_release(&mt);
+            return NULL;
+         }
+      }
    }
 
    return mt;
-- 
2.5.0.400.gff86faf



More information about the mesa-dev mailing list