[Mesa-dev] [PATCH v2 1/5] gallium: Add helpers for MSAA resolves in pipe_transfer_map()/unmap().

Eric Anholt eric at anholt.net
Tue Nov 21 21:13:04 UTC 2017


I had replicated this code from vc4 to vc5, but it's something that most
drivers will need to do in a similar way.
---
 src/gallium/auxiliary/util/u_transfer.c | 119 ++++++++++++++++++++++++++++++++
 src/gallium/auxiliary/util/u_transfer.h |  10 +++
 2 files changed, 129 insertions(+)

diff --git a/src/gallium/auxiliary/util/u_transfer.c b/src/gallium/auxiliary/util/u_transfer.c
index 3089bcb1f340..104d0505aaa8 100644
--- a/src/gallium/auxiliary/util/u_transfer.c
+++ b/src/gallium/auxiliary/util/u_transfer.c
@@ -153,3 +153,122 @@ void u_transfer_unmap_vtbl( struct pipe_context *pipe,
    struct u_resource *ur = u_resource(transfer->resource);
    ur->vtbl->transfer_unmap(pipe, transfer);
 }
+
+struct u_transfer_msaa_helper {
+   struct pipe_transfer base;
+   struct pipe_resource *ss;
+   struct pipe_transfer *wrapped;
+};
+
+/**
+ * Helper to implement the implicit MSAA resolve necessary in the
+ * pipe_transfer API.
+ *
+ * The driver should call this when the resource is multisampled.  We create a
+ * temporary single-sampled texture, blit to do the resolve if needed, and
+ * then call back to the driver to map the single-sampled texture.
+ *
+ * Note that the driver's unmap will be called with our ptrans: They need to
+ * detect it and call u_transfer_unmap_msaa_helper() and return immediately.
+ */
+void *
+u_transfer_map_msaa_helper(struct pipe_context *pctx,
+                           struct pipe_resource *prsc,
+                           unsigned level, unsigned usage,
+                           const struct pipe_box *box,
+                           struct pipe_transfer **pptrans)
+{
+   struct pipe_screen *pscreen = pctx->screen;
+   assert(prsc->nr_samples > 1);
+
+   struct u_transfer_msaa_helper *trans = calloc(1, sizeof(*trans));
+   if (!trans)
+      return NULL;
+   struct pipe_transfer *ptrans = &trans->base;
+
+   pipe_resource_reference(&ptrans->resource, prsc);
+   ptrans->level = level;
+   ptrans->usage = usage;
+   ptrans->box = *box;
+
+   struct pipe_resource temp_setup = {
+      .target = prsc->target,
+      .format = prsc->format,
+      .width0 = box->width,
+      .height0 = box->height,
+      .depth0 = 1,
+      .array_size = 1,
+   };
+   trans->ss = pscreen->resource_create(pscreen, &temp_setup);
+   if (!trans->ss) {
+      free(trans);
+      return NULL;
+   }
+
+   if (usage & PIPE_TRANSFER_READ) {
+      struct pipe_blit_info blit;
+      memset(&blit, 0, sizeof(blit));
+
+      blit.src.resource = ptrans->resource;
+      blit.src.format = ptrans->resource->format;
+      blit.src.level = ptrans->level;
+      blit.src.box = *box;
+
+      blit.dst.resource = trans->ss;
+      blit.dst.format = trans->ss->format;
+      blit.dst.box.width = box->width;
+      blit.dst.box.height = box->height;
+      blit.dst.box.depth = 1;
+
+      blit.mask = util_format_get_mask(prsc->format);
+      blit.filter = PIPE_TEX_FILTER_NEAREST;
+
+      pctx->blit(pctx, &blit);
+   }
+
+   void *ss_map = pctx->transfer_map(pctx, trans->ss, 0, usage, box,
+                                     &trans->wrapped);
+   if (!ss_map) {
+      free(trans);
+      return NULL;
+   }
+
+   *pptrans = ptrans;
+   return ss_map;
+}
+
+void u_transfer_unmap_msaa_helper(struct pipe_context *pctx,
+                                  struct pipe_transfer *ptrans)
+{
+   struct u_transfer_msaa_helper *trans =
+      (struct u_transfer_msaa_helper *)ptrans;
+
+   /* Unmap the single-sample resource, finishing whatever driver side storing
+    * is necessary.
+    */
+   pipe_transfer_unmap(pctx, trans->wrapped);
+
+   if (ptrans->usage & PIPE_TRANSFER_WRITE) {
+      struct pipe_blit_info blit;
+      memset(&blit, 0, sizeof(blit));
+
+      blit.src.resource = trans->ss;
+      blit.src.format = trans->ss->format;
+      blit.src.box.width = ptrans->box.width;
+      blit.src.box.height = ptrans->box.height;
+      blit.src.box.depth = 1;
+
+      blit.dst.resource = ptrans->resource;
+      blit.dst.format = ptrans->resource->format;
+      blit.dst.level = ptrans->level;
+      blit.dst.box = ptrans->box;
+
+      blit.mask = util_format_get_mask(ptrans->resource->format);
+      blit.filter = PIPE_TEX_FILTER_NEAREST;
+
+      pctx->blit(pctx, &blit);
+   }
+
+   pipe_resource_reference(&trans->ss, NULL);
+   free(trans);
+}
diff --git a/src/gallium/auxiliary/util/u_transfer.h b/src/gallium/auxiliary/util/u_transfer.h
index 14084983daf9..237930c06007 100644
--- a/src/gallium/auxiliary/util/u_transfer.h
+++ b/src/gallium/auxiliary/util/u_transfer.h
@@ -14,6 +14,16 @@ struct winsys_handle;
 extern "C" {
 #endif
 
+void *
+u_transfer_map_msaa_helper(struct pipe_context *pctx,
+                           struct pipe_resource *prsc,
+                           unsigned level, unsigned usage,
+                           const struct pipe_box *box,
+                           struct pipe_transfer **pptrans);
+
+void u_transfer_unmap_msaa_helper(struct pipe_context *pctx,
+                                  struct pipe_transfer *ptrans);
+
 boolean u_default_resource_get_handle(struct pipe_screen *screen,
                                       struct pipe_resource *resource,
                                       struct winsys_handle *handle);
-- 
2.15.0



More information about the mesa-dev mailing list