intel: Support mapping multisample miptrees
authorChad Versace <chad.versace@linux.intel.com>
Sat, 28 Jul 2012 03:42:31 +0000 (20:42 -0700)
committerChad Versace <chad.versace@linux.intel.com>
Tue, 7 Aug 2012 16:30:33 +0000 (09:30 -0700)
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@anholt.net>
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
src/mesa/drivers/dri/intel/intel_mipmap_tree.c
src/mesa/drivers/dri/intel/intel_mipmap_tree.h

index 9b0b4f7f1f869d2b3d595550c2fabf5bd81a646e..e002c743b92b4ceca2c99a4ab0068ae9d81b9e46 100644 (file)
@@ -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);
 }
index 12c7b6afcb7feae974addb2d23beb5ec41883a07..0d0e7579460af521bf0496e444f5e3447938ed86 100644 (file)
@@ -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;
 };
 
 /**
@@ -211,6 +217,18 @@ struct intel_mipmap_tree
    GLuint num_samples;
    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