summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/virgl/virgl_buffer.c13
-rw-r--r--src/gallium/drivers/virgl/virgl_resource.c19
-rw-r--r--src/gallium/drivers/virgl/virgl_resource.h7
-rw-r--r--src/gallium/drivers/virgl/virgl_texture.c13
4 files changed, 45 insertions, 7 deletions
diff --git a/src/gallium/drivers/virgl/virgl_buffer.c b/src/gallium/drivers/virgl/virgl_buffer.c
index 2b559e58468..fce1ac496e7 100644
--- a/src/gallium/drivers/virgl/virgl_buffer.c
+++ b/src/gallium/drivers/virgl/virgl_buffer.c
@@ -38,13 +38,22 @@ static void *virgl_buffer_transfer_map(struct pipe_context *ctx,
struct virgl_screen *vs = virgl_screen(ctx->screen);
struct virgl_resource *vbuf = virgl_resource(resource);
struct virgl_transfer *trans;
+ enum virgl_transfer_map_type map_type;
trans = virgl_resource_create_transfer(&vctx->transfer_pool, resource,
&vbuf->metadata, level, usage, box);
- virgl_resource_transfer_prepare(vctx, trans);
+ map_type = virgl_resource_transfer_prepare(vctx, trans);
+ switch (map_type) {
+ case VIRGL_TRANSFER_MAP_HW_RES:
+ trans->hw_res_map = vs->vws->resource_map(vs->vws, vbuf->hw_res);
+ break;
+ case VIRGL_TRANSFER_MAP_ERROR:
+ default:
+ trans->hw_res_map = NULL;
+ break;
+ }
- trans->hw_res_map = vs->vws->resource_map(vs->vws, vbuf->hw_res);
if (!trans->hw_res_map) {
virgl_resource_destroy_transfer(&vctx->transfer_pool, trans);
return NULL;
diff --git a/src/gallium/drivers/virgl/virgl_resource.c b/src/gallium/drivers/virgl/virgl_resource.c
index 07ae20177bf..eaa50445d4f 100644
--- a/src/gallium/drivers/virgl/virgl_resource.c
+++ b/src/gallium/drivers/virgl/virgl_resource.c
@@ -103,16 +103,21 @@ static bool virgl_res_needs_readback(struct virgl_context *vctx,
return true;
}
-void
+enum virgl_transfer_map_type
virgl_resource_transfer_prepare(struct virgl_context *vctx,
struct virgl_transfer *xfer)
{
struct virgl_winsys *vws = virgl_screen(vctx->base.screen)->vws;
struct virgl_resource *res = virgl_resource(xfer->base.resource);
+ enum virgl_transfer_map_type map_type = VIRGL_TRANSFER_MAP_HW_RES;
bool flush;
bool readback;
bool wait;
+ /* there is no way to map the host storage currently */
+ if (xfer->base.usage & PIPE_TRANSFER_MAP_DIRECTLY)
+ return VIRGL_TRANSFER_MAP_ERROR;
+
flush = virgl_res_needs_flush(vctx, xfer);
readback = virgl_res_needs_readback(vctx, res, xfer->base.usage,
xfer->base.level);
@@ -138,8 +143,18 @@ virgl_resource_transfer_prepare(struct virgl_context *vctx,
xfer->l_stride, xfer->offset, xfer->base.level);
}
- if (wait)
+ if (wait) {
+ /* fail the mapping after flush and readback so that it will succeed in
+ * the future
+ */
+ if ((xfer->base.usage & PIPE_TRANSFER_DONTBLOCK) &&
+ vws->resource_is_busy(vws, res->hw_res))
+ return VIRGL_TRANSFER_MAP_ERROR;
+
vws->resource_wait(vws, res->hw_res);
+ }
+
+ return map_type;
}
static struct pipe_resource *virgl_resource_create(struct pipe_screen *screen,
diff --git a/src/gallium/drivers/virgl/virgl_resource.h b/src/gallium/drivers/virgl/virgl_resource.h
index fda795b6b5e..c17c753a596 100644
--- a/src/gallium/drivers/virgl/virgl_resource.h
+++ b/src/gallium/drivers/virgl/virgl_resource.h
@@ -52,6 +52,11 @@ struct virgl_resource {
struct virgl_resource_metadata metadata;
};
+enum virgl_transfer_map_type {
+ VIRGL_TRANSFER_MAP_ERROR = -1,
+ VIRGL_TRANSFER_MAP_HW_RES,
+};
+
struct virgl_transfer {
struct pipe_transfer base;
uint32_t offset, l_stride;
@@ -117,7 +122,7 @@ static inline unsigned pipe_to_virgl_bind(const struct virgl_screen *vs, unsigne
return outbind;
}
-void
+enum virgl_transfer_map_type
virgl_resource_transfer_prepare(struct virgl_context *vctx,
struct virgl_transfer *xfer);
diff --git a/src/gallium/drivers/virgl/virgl_texture.c b/src/gallium/drivers/virgl/virgl_texture.c
index c2bdc3ef9e2..bba5830d33c 100644
--- a/src/gallium/drivers/virgl/virgl_texture.c
+++ b/src/gallium/drivers/virgl/virgl_texture.c
@@ -126,6 +126,7 @@ static void *texture_transfer_map_plain(struct pipe_context *ctx,
struct virgl_winsys *vws = virgl_screen(ctx->screen)->vws;
struct virgl_resource *vtex = virgl_resource(resource);
struct virgl_transfer *trans;
+ enum virgl_transfer_map_type map_type;
trans = virgl_resource_create_transfer(&vctx->transfer_pool, resource,
&vtex->metadata, level, usage, box);
@@ -133,9 +134,17 @@ static void *texture_transfer_map_plain(struct pipe_context *ctx,
assert(resource->nr_samples <= 1);
- virgl_resource_transfer_prepare(vctx, trans);
+ map_type = virgl_resource_transfer_prepare(vctx, trans);
+ switch (map_type) {
+ case VIRGL_TRANSFER_MAP_HW_RES:
+ trans->hw_res_map = vws->resource_map(vws, vtex->hw_res);
+ break;
+ case VIRGL_TRANSFER_MAP_ERROR:
+ default:
+ trans->hw_res_map = NULL;
+ break;
+ }
- trans->hw_res_map = vws->resource_map(vws, vtex->hw_res);
if (!trans->hw_res_map) {
virgl_resource_destroy_transfer(&vctx->transfer_pool, trans);
return NULL;