Handle PIPE_TRANSFER_DONT_BLOCK and PIPE_TRANSFER_MAP_DIRECTLY.
Make virgl_resource_transfer_prepare return an enum instead of a
bool for extensibility (e.g., instruct the callers to map
differently).
Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
Reviewed-by: Alexandros Frantzis <alexandros.frantzis@collabora.com>
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;
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);
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,
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;
return outbind;
}
-void
+enum virgl_transfer_map_type
virgl_resource_transfer_prepare(struct virgl_context *vctx,
struct virgl_transfer *xfer);
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);
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;