Mesa (master): intel: Support mapping multisample miptrees

Chad Versace chadversary at kemper.freedesktop.org
Tue Aug 7 16:31:17 UTC 2012


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

Author: Chad Versace <chad.versace at linux.intel.com>
Date:   Fri Jul 27 20:42:31 2012 -0700

intel: Support mapping multisample miptrees

Add two new functions: intel_miptree_{map,unmap}_multisample, to which
intel_miptree_{map,unmap} dispatch. Only mapping flat, renderbuffer-like
miptrees are supported.

Reviewed-by: Eric Anholt <eric at anholt.net>
Signed-off-by: Chad Versace <chad.versace at linux.intel.com>

---

 src/mesa/drivers/dri/intel/intel_mipmap_tree.c |  114 ++++++++++++++++++++++--
 src/mesa/drivers/dri/intel/intel_mipmap_tree.h |   18 ++++
 2 files changed, 126 insertions(+), 6 deletions(-)

diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
index 9b0b4f7..e002c74 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
@@ -397,6 +397,8 @@ intel_miptree_create_for_renderbuffer(struct intel_context *intel,
    struct intel_mipmap_tree *mt;
    uint32_t depth = 1;
    enum intel_msaa_layout msaa_layout = INTEL_MSAA_LAYOUT_NONE;
+   const uint32_t singlesample_width = width;
+   const uint32_t singlesample_height = height;
    bool ok;
 
    if (num_samples > 1) {
@@ -476,6 +478,9 @@ intel_miptree_create_for_renderbuffer(struct intel_context *intel,
          goto fail;
    }
 
+   mt->singlesample_width0 = singlesample_width;
+   mt->singlesample_height0 = singlesample_height;
+
    return mt;
 
 fail:
@@ -1576,6 +1581,93 @@ intel_miptree_unmap_singlesample(struct intel_context *intel,
    intel_miptree_release_map(mt, level, slice);
 }
 
+static void
+intel_miptree_map_multisample(struct intel_context *intel,
+                              struct intel_mipmap_tree *mt,
+                              unsigned int level,
+                              unsigned int slice,
+                              unsigned int x,
+                              unsigned int y,
+                              unsigned int w,
+                              unsigned int h,
+                              GLbitfield mode,
+                              void **out_ptr,
+                              int *out_stride)
+{
+   struct intel_miptree_map *map;
+
+   assert(mt->num_samples > 1);
+
+   /* Only flat, renderbuffer-like miptrees are supported. */
+   if (mt->target != GL_TEXTURE_2D ||
+       mt->first_level != 0 ||
+       mt->last_level != 0) {
+      _mesa_problem(&intel->ctx, "attempt to map a multisample miptree for "
+                    "which (target, first_level, last_level != "
+                    "(GL_TEXTURE_2D, 0, 0)");
+      goto fail;
+   }
+
+   map = intel_miptree_attach_map(mt, level, slice, x, y, w, h, mode);
+   if (!map)
+      goto fail;
+
+   if (!mt->singlesample_mt) {
+      mt->singlesample_mt =
+         intel_miptree_create_for_renderbuffer(intel,
+                                               mt->format,
+                                               mt->singlesample_width0,
+                                               mt->singlesample_height0,
+                                               0 /*num_samples*/);
+      if (!mt->singlesample_mt)
+         goto fail;
+
+      map->singlesample_mt_is_tmp = true;
+      mt->need_downsample = true;
+   }
+
+   if (mode & GL_MAP_INVALIDATE_RANGE_BIT)
+      mt->need_downsample = false;
+
+   intel_miptree_downsample(intel, mt);
+   intel_miptree_map_singlesample(intel, mt->singlesample_mt,
+                                  level, slice,
+                                  x, y, w, h,
+                                  mode,
+                                  out_ptr, out_stride);
+   return;
+
+fail:
+   intel_miptree_release_map(mt, level, slice);
+   *out_ptr = NULL;
+   *out_stride = 0;
+}
+
+static void
+intel_miptree_unmap_multisample(struct intel_context *intel,
+                                struct intel_mipmap_tree *mt,
+                                unsigned int level,
+                                unsigned int slice)
+{
+   struct intel_miptree_map *map = mt->level[level].slice[slice].map;
+
+   assert(mt->num_samples > 1);
+
+   if (!map)
+      return;
+
+   intel_miptree_unmap_singlesample(intel, mt->singlesample_mt, level, slice);
+
+   mt->need_downsample = false;
+   if (map->mode & GL_MAP_WRITE_BIT)
+      intel_miptree_upsample(intel, mt);
+
+   if (map->singlesample_mt_is_tmp)
+      intel_miptree_release(&mt->singlesample_mt);
+
+   intel_miptree_release_map(mt, level, slice);
+}
+
 void
 intel_miptree_map(struct intel_context *intel,
 		  struct intel_mipmap_tree *mt,
@@ -1589,11 +1681,18 @@ intel_miptree_map(struct intel_context *intel,
 		  void **out_ptr,
 		  int *out_stride)
 {
-   intel_miptree_map_singlesample(intel, mt,
-                                  level, slice,
-                                  x, y, w, h,
-                                  mode,
-                                  out_ptr, out_stride);
+   if (mt->num_samples <= 1)
+      intel_miptree_map_singlesample(intel, mt,
+                                     level, slice,
+                                     x, y, w, h,
+                                     mode,
+                                     out_ptr, out_stride);
+   else
+      intel_miptree_map_multisample(intel, mt,
+                                    level, slice,
+                                    x, y, w, h,
+                                    mode,
+                                    out_ptr, out_stride);
 }
 
 void
@@ -1602,5 +1701,8 @@ intel_miptree_unmap(struct intel_context *intel,
 		    unsigned int level,
 		    unsigned int slice)
 {
-   intel_miptree_unmap_singlesample(intel, mt, level, slice);
+   if (mt->num_samples <= 1)
+      intel_miptree_unmap_singlesample(intel, mt, level, slice);
+   else
+      intel_miptree_unmap_multisample(intel, mt, level, slice);
 }
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
index 12c7b6a..0d0e757 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
@@ -79,6 +79,12 @@ struct intel_miptree_map {
    void *ptr;
    /** Stride of the mapping. */
    int stride;
+
+   /**
+    * intel_mipmap_tree::singlesample_mt is temporary storage that persists
+    * only for the duration of the map.
+    */
+   bool singlesample_mt_is_tmp;
 };
 
 /**
@@ -212,6 +218,18 @@ struct intel_mipmap_tree
    bool compressed;
 
    /**
+    * If num_samples > 0, then singlesample_width0 is the value that width0
+    * would have if instead a singlesample miptree were created. Note that,
+    * for non-interleaved msaa layouts, the two values are the same.
+    *
+    * If num_samples == 0, then singlesample_width0 is undefined.
+    */
+   uint32_t singlesample_width0;
+
+   /** \see singlesample_width0 */
+   uint32_t singlesample_height0;
+
+   /**
     * For 1D array, 2D array, cube, and 2D multisampled surfaces on Gen7: true
     * if the surface only contains LOD 0, and hence no space is for LOD's
     * other than 0 in between array slices.




More information about the mesa-commit mailing list