[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