[Mesa-dev] [PATCH 04/15] intel: Allocate miptree for multisample DRI2 buffers (v3)

Chad Versace chad.versace at linux.intel.com
Mon Aug 6 17:19:11 PDT 2012


Immediately after obtaining, with DRI2GetBuffersWithFormat, the DRM buffer
handle for a DRI2 buffer, we wrap that DRM buffer handle with a region and
a miptree. This patch additionally allocates an accompanying multisample
miptree if the DRI2 buffer is multisampled.

Since we do not yet advertise multisample GL configs, the code for
allocating the multisample miptree is currently inactive.

This patch adds the following fields to intel_mipmap_tree:
    singlesample_mt
    needs_downsample
and the following function stubs:
    intel_miptree_downsample
    intel_miptree_upsample

v2:
    - Fix typo 'miptre'.
    - Upsample when rendering to the front buffer, per Paul.
v3:
    - Fold introduction of new fields into this patch, per Anholt.

CC: Eric Anholt <eric at anholt.net>
CC: Paul Berry <stereotype441 at gmail.com>
Signed-off-by: Chad Versace <chad.versace at linux.intel.com>
---
 src/mesa/drivers/dri/intel/intel_context.c     | 27 ++++++---
 src/mesa/drivers/dri/intel/intel_mipmap_tree.c | 84 ++++++++++++++++++++++++++
 src/mesa/drivers/dri/intel/intel_mipmap_tree.h | 59 ++++++++++++++++++
 3 files changed, 162 insertions(+), 8 deletions(-)

diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c
index 378859c..b32daa3 100644
--- a/src/mesa/drivers/dri/intel/intel_context.c
+++ b/src/mesa/drivers/dri/intel/intel_context.c
@@ -893,14 +893,24 @@ intel_process_dri2_buffer(struct intel_context *intel,
    if (!rb)
       return;
 
+   unsigned num_samples = rb->Base.Base.NumSamples;
+
    /* We try to avoid closing and reopening the same BO name, because the first
     * use of a mapping of the buffer involves a bunch of page faulting which is
     * moderately expensive.
     */
-   if (rb->mt &&
-       rb->mt->region &&
-       rb->mt->region->name == buffer->name)
-      return;
+   if (num_samples == 0) {
+       if (rb->mt &&
+           rb->mt->region &&
+           rb->mt->region->name == buffer->name)
+          return;
+   } else {
+       if (rb->mt &&
+           rb->mt->singlesample_mt &&
+           rb->mt->singlesample_mt->region &&
+           rb->mt->singlesample_mt->region->name == buffer->name)
+          return;
+   }
 
    if (unlikely(INTEL_DEBUG & DEBUG_DRI)) {
       fprintf(stderr,
@@ -920,9 +930,10 @@ intel_process_dri2_buffer(struct intel_context *intel,
    if (!region)
       return;
 
-   rb->mt = intel_miptree_create_for_region(intel,
-                                            GL_TEXTURE_2D,
-                                            intel_rb_format(rb),
-                                            region);
+   rb->mt = intel_miptree_create_for_dri2_buffer(intel,
+                                                 buffer->attachment,
+                                                 intel_rb_format(rb),
+                                                 num_samples,
+                                                 region);
    intel_region_release(&region);
 }
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
index b6ecbca..5da24f2 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
@@ -25,6 +25,9 @@
  * 
  **************************************************************************/
 
+#include <GL/gl.h>
+#include <GL/internal/dri_interface.h>
+
 #include "intel_batchbuffer.h"
 #include "intel_context.h"
 #include "intel_mipmap_tree.h"
@@ -324,6 +327,62 @@ compute_msaa_layout(struct intel_context *intel, gl_format format)
    }
 }
 
+/**
+ * For a singlesample DRI2 buffer, this simply wraps the given region with a miptree.
+ *
+ * For a multisample DRI2 buffer, this wraps the given region with
+ * a singlesample miptree, then creates a multisample miptree into which the
+ * singlesample miptree is embedded as a child.
+ */
+struct intel_mipmap_tree*
+intel_miptree_create_for_dri2_buffer(struct intel_context *intel,
+                                     unsigned dri_attachment,
+                                     gl_format format,
+                                     uint32_t num_samples,
+                                     struct intel_region *region)
+{
+   struct intel_mipmap_tree *singlesample_mt = NULL;
+   struct intel_mipmap_tree *multisample_mt = NULL;
+   GLenum base_format = _mesa_get_format_base_format(format);
+
+   /* Only the front and back buffers, which are color buffers, are shared
+    * through DRI2.
+    */
+   assert(dri_attachment == __DRI_BUFFER_BACK_LEFT ||
+          dri_attachment == __DRI_BUFFER_FRONT_LEFT ||
+          dri_attachment == __DRI_BUFFER_FAKE_FRONT_LEFT);
+   assert(base_format == GL_RGB || base_format == GL_RGBA);
+
+   singlesample_mt = intel_miptree_create_for_region(intel, GL_TEXTURE_2D,
+                                                     format, region);
+   if (!singlesample_mt)
+      return NULL;
+
+   if (num_samples == 0)
+      return singlesample_mt;
+
+   multisample_mt = intel_miptree_create_for_renderbuffer(intel,
+                                                          format,
+                                                          region->width,
+                                                          region->height,
+                                                          num_samples);
+   if (!multisample_mt) {
+      intel_miptree_release(&singlesample_mt);
+      return NULL;
+   }
+
+   multisample_mt->singlesample_mt = singlesample_mt;
+   multisample_mt->need_downsample = false;
+
+   if (intel->is_front_buffer_rendering &&
+       (dri_attachment == __DRI_BUFFER_FRONT_LEFT ||
+        dri_attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)) {
+      intel_miptree_upsample(intel, multisample_mt);
+   }
+
+   return multisample_mt;
+}
+
 struct intel_mipmap_tree*
 intel_miptree_create_for_renderbuffer(struct intel_context *intel,
                                       gl_format format,
@@ -454,6 +513,7 @@ intel_miptree_release(struct intel_mipmap_tree **mt)
       intel_miptree_release(&(*mt)->stencil_mt);
       intel_miptree_release(&(*mt)->hiz_mt);
       intel_miptree_release(&(*mt)->mcs_mt);
+      intel_miptree_release(&(*mt)->singlesample_mt);
       intel_resolve_map_clear(&(*mt)->hiz_map);
 
       for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
@@ -899,6 +959,30 @@ intel_miptree_all_slices_resolve_depth(struct intel_context *intel,
 					   GEN6_HIZ_OP_DEPTH_RESOLVE);
 }
 
+/**
+ * \brief Downsample from mt to mt->singlesample_mt.
+ *
+ * If the miptree needs no downsample, then skip.
+ */
+void
+intel_miptree_downsample(struct intel_context *intel,
+                         struct intel_mipmap_tree *mt)
+{
+   /* TODO: stub */
+}
+
+/**
+ * \brief Upsample from mt->singlesample_mt to mt.
+ *
+ * The upsample is done unconditionally.
+ */
+void
+intel_miptree_upsample(struct intel_context *intel,
+                       struct intel_mipmap_tree *mt)
+{
+   /* TODO: stub */
+}
+
 static void
 intel_miptree_map_gtt(struct intel_context *intel,
 		      struct intel_mipmap_tree *mt,
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
index bfeb69c..12c7b6a 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
@@ -248,6 +248,50 @@ struct intel_mipmap_tree
    uint32_t offset;
 
    /**
+    * \brief Singlesample miptree.
+    *
+    * This is used under two cases.
+    *
+    * --- Case 1: As persistent singlesample storage for multisample window
+    *  system front and back buffers ---
+    *
+    * Suppose that the window system FBO was created with a multisample
+    * config.  Let `back_irb` be the `intel_renderbuffer` for the FBO's back
+    * buffer. Then `back_irb` contains two miptrees: a parent multisample
+    * miptree (back_irb->mt) and a child singlesample miptree
+    * (back_irb->mt->singlesample_mt).  The DRM buffer shared with DRI2
+    * belongs to `back_irb->mt->singlesample_mt` and contains singlesample
+    * data.  The singlesample miptree is created at the same time as and
+    * persists for the lifetime of its parent multisample miptree.
+    *
+    * When access to the singlesample data is needed, such as at
+    * eglSwapBuffers and glReadPixels, an automatic downsample occurs from
+    * `back_rb->mt` to `back_rb->mt->singlesample_mt` when necessary.
+    *
+    * This description of the back buffer applies analogously to the front
+    * buffer.
+    *
+    *
+    * --- Case 2: As temporary singlesample storage for mapping multisample
+    *  miptrees ---
+    *
+    * Suppose the intel_miptree_map is called on a multisample miptree, `mt`,
+    * for which case 1 does not apply (that is, `mt` does not belong to
+    * a front or back buffer).  Then `mt->singlesample_mt` is null at the
+    * start of the call. intel_miptree_map will create a temporary
+    * singlesample miptree, store it at `mt->singlesample_mt`, downsample from
+    * `mt` to `mt->singlesample_mt` if necessary, then map
+    * `mt->singlesample_mt`. The temporary miptree is later deleted during
+    * intel_miptree_unmap.
+    */
+   struct intel_mipmap_tree *singlesample_mt;
+
+   /**
+    * \brief A downsample is needed from this miptree to singlesample_mt.
+    */
+   bool need_downsample;
+
+   /**
     * \brief HiZ miptree
     *
     * This is non-null only if HiZ is enabled for this miptree.
@@ -325,6 +369,13 @@ intel_miptree_create_for_region(struct intel_context *intel,
 				gl_format format,
 				struct intel_region *region);
 
+struct intel_mipmap_tree*
+intel_miptree_create_for_dri2_buffer(struct intel_context *intel,
+                                     unsigned dri_attachment,
+                                     gl_format format,
+                                     uint32_t num_samples,
+                                     struct intel_region *region);
+
 /**
  * Create a miptree appropriate as the storage for a non-texture renderbuffer.
  * The miptree has the following properties:
@@ -484,6 +535,14 @@ intel_miptree_all_slices_resolve_depth(struct intel_context *intel,
 
 /**\}*/
 
+void
+intel_miptree_downsample(struct intel_context *intel,
+                         struct intel_mipmap_tree *mt);
+
+void
+intel_miptree_upsample(struct intel_context *intel,
+                       struct intel_mipmap_tree *mt);
+
 /* i915_mipmap_tree.c:
  */
 void i915_miptree_layout(struct intel_mipmap_tree *mt);
-- 
1.7.11.4



More information about the mesa-dev mailing list