diff --git a/src/virgl_context.h b/src/virgl_context.h index 0393ba8..fa5e13d 100644 --- a/src/virgl_context.h +++ b/src/virgl_context.h @@ -31,6 +31,7 @@ struct virgl_resource; struct vrend_transfer_info; +struct pipe_resource; /** * Base class for renderer contexts. For example, vrend_decode_ctx is a @@ -54,6 +55,9 @@ struct virgl_context { 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/virgl_resource.c b/src/virgl_resource.c index abfaf48..4e9d640 100644 --- a/src/virgl_resource.c +++ b/src/virgl_resource.c @@ -24,6 +24,7 @@ #include "virgl_resource.h" +#include #include #include @@ -110,6 +111,26 @@ virgl_resource_create_from_pipe(uint32_t res_id, struct pipe_resource *pres) return 0; } +int +virgl_resource_create_from_iov(uint32_t res_id, + const struct iovec *iov, + int iov_count) +{ + struct virgl_resource *res; + + if (iov_count) + assert(iov); + + res = virgl_resource_create(res_id); + if (!res) + return ENOMEM; + + res->iov = iov; + res->iov_count = iov_count; + + return 0; +} + void virgl_resource_remove(uint32_t res_id) { diff --git a/src/virgl_resource.h b/src/virgl_resource.h index 8cbb982..c3e1438 100644 --- a/src/virgl_resource.h +++ b/src/virgl_resource.h @@ -73,6 +73,11 @@ virgl_resource_table_reset(void); int virgl_resource_create_from_pipe(uint32_t res_id, struct pipe_resource *pres); +int +virgl_resource_create_from_iov(uint32_t res_id, + const struct iovec *iov, + int iov_count); + void virgl_resource_remove(uint32_t res_id); diff --git a/src/virglrenderer.c b/src/virglrenderer.c index a540d1e..5f9ad56 100644 --- a/src/virglrenderer.c +++ b/src/virglrenderer.c @@ -633,3 +633,46 @@ int virgl_renderer_execute(void *execute_args, uint32_t execute_size) return -EINVAL; } } + +int virgl_renderer_resource_create_blob(const struct virgl_renderer_resource_create_blob_args *args) +{ + int ret; + uint32_t blob_mem = args->blob_mem; + uint64_t blob_id = args->blob_id; + uint32_t res_handle = args->res_handle; + struct pipe_resource *pipe_res; + + if (blob_mem == VIRGL_RENDERER_BLOB_MEM_HOST3D || + blob_mem == VIRGL_RENDERER_BLOB_MEM_HOST3D_GUEST) { + struct virgl_context *ctx = virgl_context_lookup(args->ctx_id); + if (!ctx) + return -EINVAL; + + pipe_res = ctx->get_blob_pipe(ctx, blob_id); + if (!pipe_res) + return -EINVAL; + + ret = virgl_resource_create_from_pipe(res_handle, pipe_res); + if (ret) { + vrend_renderer_resource_destroy((struct vrend_resource *)pipe_res); + return ret; + } + + if (blob_mem == VIRGL_RENDERER_BLOB_MEM_HOST3D_GUEST) { + ret = virgl_renderer_resource_attach_iov(res_handle, args->iovecs, args->num_iovs); + if (ret) { + virgl_resource_remove(res_handle); + return ret; + } + } + } else if (blob_mem == VIRGL_RENDERER_BLOB_MEM_GUEST) { + ret = virgl_resource_create_from_iov(res_handle, args->iovecs, args->num_iovs); + if (ret) + return -EINVAL; + } else { + return -EINVAL; + } + + + return 0; +} diff --git a/src/virglrenderer.h b/src/virglrenderer.h index bd96aa5..f91804d 100644 --- a/src/virglrenderer.h +++ b/src/virglrenderer.h @@ -236,4 +236,26 @@ VIRGL_EXPORT int virgl_renderer_get_poll_fd(void); VIRGL_EXPORT int virgl_renderer_execute(void *execute_args, uint32_t execute_size); +#define VIRGL_RENDERER_BLOB_MEM_GUEST 0x0001 +#define VIRGL_RENDERER_BLOB_MEM_HOST3D 0x0002 +#define VIRGL_RENDERER_BLOB_MEM_HOST3D_GUEST 0x0003 + +#define VIRGL_RENDERER_BLOB_FLAG_USE_MAPPABLE 0x0001 +#define VIRGL_RENDERER_BLOB_FLAG_USE_SHAREABLE 0x0002 +#define VIRGL_RENDERER_BLOB_FLAG_USE_CROSS_DEVICE 0x0004 + +struct virgl_renderer_resource_create_blob_args +{ + uint32_t res_handle; + uint32_t ctx_id; + uint32_t blob_mem; + uint32_t blob_flags; + uint64_t blob_id; + uint64_t size; + const struct iovec *iovecs; + uint32_t num_iovs; +}; + +VIRGL_EXPORT int +virgl_renderer_resource_create_blob(const struct virgl_renderer_resource_create_blob_args *args); #endif diff --git a/src/vrend_decode.c b/src/vrend_decode.c index 20abe02..d5a0254 100644 --- a/src/vrend_decode.c +++ b/src/vrend_decode.c @@ -1694,6 +1694,13 @@ 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) { @@ -1705,6 +1712,7 @@ static void vrend_decode_ctx_init_base(struct vrend_decode_ctx *dctx, ctx->detach_resource = vrend_decode_ctx_detach_resource; ctx->transfer_3d = vrend_decode_ctx_transfer_3d; ctx->submit_cmd = vrend_decode_ctx_submit_cmd; + ctx->get_blob_pipe = vrend_decode_get_blob_pipe; } void vrend_decode_reset(void) diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index b8b6526..cb5bd85 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -10349,3 +10349,21 @@ int vrend_renderer_pipe_resource_create(struct vrend_context *ctx, uint32_t blob list_addtail(&res->head, &ctx->vrend_resources); return 0; } + +struct pipe_resource *vrend_get_blob_pipe(struct vrend_context *ctx, uint64_t blob_id) +{ + uint32_t id = (uint32_t)blob_id; + struct vrend_resource *res, *stor; + + LIST_FOR_EACH_ENTRY_SAFE(res, stor, &ctx->vrend_resources, head) { + if (res->blob_id != id) + continue; + + list_del(&res->head); + /* Set the blob id to zero, since it won't be used anymore */ + res->blob_id = 0; + return &res->base; + } + + return NULL; +} diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h index 7ebfb3c..b14fae9 100644 --- a/src/vrend_renderer.h +++ b/src/vrend_renderer.h @@ -494,4 +494,7 @@ void vrend_sync_make_current(virgl_gl_context); int vrend_renderer_pipe_resource_create(struct vrend_context *ctx, uint32_t blob_id, struct vrend_renderer_resource_create_args *args); + +struct pipe_resource *vrend_get_blob_pipe(struct vrend_context *ctx, uint64_t blob_id); + #endif