diff --git a/src/virgl_context.h b/src/virgl_context.h index fa5e13d..fa39fe9 100644 --- a/src/virgl_context.h +++ b/src/virgl_context.h @@ -29,10 +29,22 @@ #include #include -struct virgl_resource; +#include "virgl_resource.h" + struct vrend_transfer_info; struct pipe_resource; +struct virgl_context_blob { + /* valid fd or pipe resource */ + enum virgl_resource_fd_type type; + union { + int fd; + struct pipe_resource *pipe_resource; + } u; + + void *renderer_data; +}; + /** * Base class for renderer contexts. For example, vrend_decode_ctx is a * subclass of virgl_context. @@ -52,12 +64,26 @@ struct virgl_context { const struct vrend_transfer_info *info, int transfer_mode); + /* These are used to create a virgl_resource from a context object. + * + * get_blob returns a virgl_context_blob from which a virgl_resource can be + * created. get_blob_done is optional and allows the context to associate + * the newly created resource with the context object. + * + * Note that get_blob is a one-time thing. The context object might be + * destroyed or reject subsequent get_blob calls. + */ + int (*get_blob)(struct virgl_context *ctx, + uint64_t blob_id, + uint32_t blob_flags, + struct virgl_context_blob *blob); + void (*get_blob_done)(struct virgl_context *ctx, + uint32_t res_id, + struct virgl_context_blob *blob); + int (*submit_cmd)(struct virgl_context *ctx, const void *buffer, size_t size); - - struct pipe_resource *(*get_blob_pipe)(struct virgl_context *ctx, - uint64_t blob_id); }; struct virgl_context_foreach_args { diff --git a/src/virglrenderer.c b/src/virglrenderer.c index 71166c5..0674129 100644 --- a/src/virglrenderer.c +++ b/src/virglrenderer.c @@ -647,7 +647,7 @@ int virgl_renderer_execute(void *execute_args, uint32_t execute_size) int virgl_renderer_resource_create_blob(const struct virgl_renderer_resource_create_blob_args *args) { struct virgl_context *ctx; - struct pipe_resource *pipe_res; + struct virgl_context_blob blob; bool has_host_storage; bool has_guest_storage; int ret; @@ -694,19 +694,34 @@ int virgl_renderer_resource_create_blob(const struct virgl_renderer_resource_cre if (!ctx) return -EINVAL; - pipe_res = ctx->get_blob_pipe(ctx, args->blob_id); - if (!pipe_res) - return -EINVAL; - - ret = virgl_resource_create_from_pipe(args->res_handle, - pipe_res, - args->iovecs, - args->num_iovs); - if (ret) { - vrend_renderer_resource_destroy((struct vrend_resource *)pipe_res); + ret = ctx->get_blob(ctx, args->blob_id, args->blob_flags, &blob); + if (ret) return ret; + + if (blob.type != VIRGL_RESOURCE_FD_INVALID) { + ret = virgl_resource_create_from_fd(args->res_handle, + blob.type, + blob.u.fd, + args->iovecs, + args->num_iovs); + if (ret) { + close(blob.u.fd); + return ret; + } + } else { + ret = virgl_resource_create_from_pipe(args->res_handle, + blob.u.pipe_resource, + args->iovecs, + args->num_iovs); + if (ret) { + vrend_renderer_resource_destroy((struct vrend_resource *)blob.u.pipe_resource); + return ret; + } } + if (ctx->get_blob_done) + ctx->get_blob_done(ctx, args->res_handle, &blob); + return 0; } diff --git a/src/vrend_decode.c b/src/vrend_decode.c index d5a0254..52e9095 100644 --- a/src/vrend_decode.c +++ b/src/vrend_decode.c @@ -1502,6 +1502,20 @@ static int vrend_decode_ctx_transfer_3d(struct virgl_context *ctx, transfer_mode); } +static int vrend_decode_ctx_get_blob(struct virgl_context *ctx, + uint64_t blob_id, + UNUSED uint32_t blob_flags, + struct virgl_context_blob *blob) +{ + struct vrend_decode_ctx *dctx = (struct vrend_decode_ctx *)ctx; + + blob->type = VIRGL_RESOURCE_FD_INVALID; + /* this transfers ownership and blob_id is no longer valid */ + blob->u.pipe_resource = vrend_get_blob_pipe(dctx->grctx, blob_id); + + return blob->u.pipe_resource ? 0 : EINVAL; +} + static int vrend_decode_ctx_submit_cmd(struct virgl_context *ctx, const void *buffer, size_t size) @@ -1694,13 +1708,6 @@ static int vrend_decode_ctx_submit_cmd(struct virgl_context *ctx, return ret; } -static struct pipe_resource *vrend_decode_get_blob_pipe(struct virgl_context *ctx, - uint64_t blob_id) -{ - struct vrend_decode_ctx *dctx = (struct vrend_decode_ctx *)ctx; - return vrend_get_blob_pipe(dctx->grctx, blob_id); -} - static void vrend_decode_ctx_init_base(struct vrend_decode_ctx *dctx, uint32_t ctx_id) { @@ -1711,8 +1718,9 @@ static void vrend_decode_ctx_init_base(struct vrend_decode_ctx *dctx, ctx->attach_resource = vrend_decode_ctx_attach_resource; ctx->detach_resource = vrend_decode_ctx_detach_resource; ctx->transfer_3d = vrend_decode_ctx_transfer_3d; + ctx->get_blob = vrend_decode_ctx_get_blob; + ctx->get_blob_done = NULL; ctx->submit_cmd = vrend_decode_ctx_submit_cmd; - ctx->get_blob_pipe = vrend_decode_get_blob_pipe; } void vrend_decode_reset(void)