virgl: handle DONT_BLOCK and MAP_DIRECTLY
authorChia-I Wu <olvaffe@gmail.com>
Sat, 11 May 2019 04:23:12 +0000 (21:23 -0700)
committerChia-I Wu <olvaffe@gmail.com>
Wed, 15 May 2019 20:51:28 +0000 (20:51 +0000)
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>
src/gallium/drivers/virgl/virgl_buffer.c
src/gallium/drivers/virgl/virgl_resource.c
src/gallium/drivers/virgl/virgl_resource.h
src/gallium/drivers/virgl/virgl_texture.c

index 2b559e584687589353e643e3c3532e216d0f5487..fce1ac496e746a282853b7591dc37522220839ff 100644 (file)
@@ -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;
index 07ae20177bf3f4094bf2614ebfc3b54820c5f1c6..eaa50445d4f7f9ade20e43add82e4e9e204bead4 100644 (file)
@@ -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,
index fda795b6b5e018d8e58afa06a9e6fe31fff5cce3..c17c753a59654c7add225b861f18e539477b1a69 100644 (file)
@@ -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);
 
index c2bdc3ef9e239f3b33bb0b0e97554662b9d286cd..bba5830d33c214624657e031eec846cd471521fa 100644 (file)
@@ -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;