diff --git a/src/virgl_gbm.c b/src/virgl_gbm.c index 5e3b1a0..23db98e 100644 --- a/src/virgl_gbm.c +++ b/src/virgl_gbm.c @@ -368,3 +368,62 @@ uint32_t virgl_gbm_convert_flags(uint32_t virgl_bind_flags) flags |= GBM_BO_USE_CURSOR; return flags; } + +int virgl_gbm_export_query(struct gbm_bo *bo, struct virgl_renderer_export_query *query) +{ + int ret = -1; + uint32_t handles[4] = {0, 0, 0, 0}; + struct gbm_device *gbm = gbm_bo_get_device(bo); + int num_planes = gbm_bo_get_plane_count(bo); + if (num_planes < 0 || num_planes > 4) + return ret; + + query->out_num_fds = 0; + query->out_fourcc = 0; + query->out_modifier = 0; + for (int plane = 0; plane < 4; plane++) { + query->out_fds[plane] = -1; + query->out_strides[plane] = 0; + query->out_offsets[plane] = 0; + } + + for (int plane = 0; plane < num_planes; plane++) { + uint32_t i, handle; + query->out_strides[plane] = gbm_bo_get_stride_for_plane(bo, plane); + query->out_offsets[plane] = gbm_bo_get_offset(bo, plane); + handle = gbm_bo_get_handle_for_plane(bo, plane).u32; + + for (i = 0; i < query->out_num_fds; i++) { + if (handles[query->out_num_fds] == handle) + break; + } + + if (i == query->out_num_fds) { + if (query->in_export_fds) { + ret = drmPrimeHandleToFD(gbm_device_get_fd(gbm), handle, DRM_CLOEXEC, + &query->out_fds[query->out_num_fds]); + if (ret) + goto err_close; + } + query->out_num_fds++; + } + } + + query->out_modifier = gbm_bo_get_modifier(bo); + query->out_fourcc = gbm_bo_get_format(bo); + return 0; + +err_close: + for (int plane = 0; plane < 4; plane++) { + if (query->out_fds[plane] >= 0) { + close(query->out_fds[plane]); + query->out_fds[plane] = -1; + } + + query->out_strides[plane] = 0; + query->out_offsets[plane] = 0; + } + + query->out_num_fds = 0; + return ret; +} diff --git a/src/virgl_gbm.h b/src/virgl_gbm.h index 6f17a41..a852718 100644 --- a/src/virgl_gbm.h +++ b/src/virgl_gbm.h @@ -27,6 +27,7 @@ #include #include "vrend_iov.h" +#include "virglrenderer.h" /* * If fd >= 0, virglrenderer owns the fd since it was opened via a rendernode @@ -49,4 +50,6 @@ int virgl_gbm_transfer(struct gbm_bo *bo, uint32_t direction, struct iovec *iove uint32_t virgl_gbm_convert_flags(uint32_t virgl_bind_flags); +int virgl_gbm_export_query(struct gbm_bo *bo, struct virgl_renderer_export_query *query); + #endif diff --git a/src/virglrenderer.c b/src/virglrenderer.c index 584be01..7347004 100644 --- a/src/virglrenderer.c +++ b/src/virglrenderer.c @@ -422,3 +422,8 @@ virgl_debug_callback_type virgl_set_debug_callback(virgl_debug_callback_type cb) { return vrend_set_debug_callback(cb); } + +int virgl_renderer_execute(void *execute_args, uint32_t execute_size) +{ + return vrend_renderer_execute(execute_args, execute_size); +} diff --git a/src/virglrenderer.h b/src/virglrenderer.h index dbf0675..a57cc03 100644 --- a/src/virglrenderer.h +++ b/src/virglrenderer.h @@ -98,6 +98,11 @@ VIRGL_EXPORT int virgl_renderer_get_fd_for_texture2(uint32_t tex_id, int *fd, in #define VIRGL_RES_BIND_SCANOUT (1 << 18) #define VIRGL_RES_BIND_SHARED (1 << 20) +enum virgl_renderer_structure_type_v0 { + VIRGL_RENDERER_STRUCTURE_TYPE_NONE = 0x00000000, + VIRGL_RENDERER_STRUCTURE_TYPE_EXPORT_QUERY = 0x00000001, +}; + struct virgl_renderer_resource_create_args { uint32_t handle; uint32_t target; @@ -112,6 +117,33 @@ struct virgl_renderer_resource_create_args { uint32_t flags; }; +struct virgl_renderer_hdr { + uint32_t stype; + uint32_t stype_version; + uint32_t size; +}; + +/* + * "out_num_fds" represents the number of distinct kernel buffers backing an + * allocation. If this number or 'out_fourcc' is zero, the resource is not + * exportable. The "out_fds" field will be populated with "out_num_fds" file + * descriptors if "in_export_fds" is non-zero. + */ +struct virgl_renderer_export_query { + struct virgl_renderer_hdr hdr; + uint32_t in_resource_id; + + uint32_t out_num_fds; + uint32_t in_export_fds; + uint32_t out_fourcc; + uint32_t pad; + + int32_t out_fds[4]; + uint32_t out_strides[4]; + uint32_t out_offsets[4]; + uint64_t out_modifier; +}; + /* new API */ /* This typedef must be kept in sync with vrend_debug.h */ typedef void (*virgl_debug_callback_type)(const char *fmt, va_list ap); @@ -190,4 +222,6 @@ VIRGL_EXPORT void virgl_renderer_reset(void); VIRGL_EXPORT int virgl_renderer_get_poll_fd(void); +VIRGL_EXPORT int virgl_renderer_execute(void *execute_args, uint32_t execute_size); + #endif diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 570fc86..c38ee0f 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -50,6 +50,7 @@ #include "vrend_debug.h" #include "virgl_hw.h" +#include "virglrenderer.h" #include "tgsi/tgsi_text.h" @@ -9625,6 +9626,7 @@ void *vrend_renderer_get_cursor_contents(uint32_t res_handle, uint32_t *width, u return data2; } + void vrend_renderer_force_ctx_0(void) { struct vrend_context *ctx0 = vrend_lookup_renderer_ctx(0); @@ -9922,3 +9924,39 @@ int vrend_renderer_get_poll_fd(void) return vrend_state.eventfd; } + +int vrend_renderer_execute(void *execute_args, uint32_t execute_size) +{ + /* + * This function only supports VIRGL_RENDERER_STRUCTURE_TYPE_RESOURCE_QUERY currently. + */ + struct vrend_resource *res; + struct virgl_renderer_export_query *export_query = execute_args; + if (execute_size != sizeof(struct virgl_renderer_export_query)) + return -EINVAL; + + if (export_query->hdr.stype != VIRGL_RENDERER_STRUCTURE_TYPE_EXPORT_QUERY || + export_query->hdr.stype_version != 0 || + export_query->hdr.size != sizeof(struct virgl_renderer_export_query)) + return -EINVAL; + + res = vrend_resource_lookup(export_query->in_resource_id, 0); + if (!res) + return -EINVAL; + +#ifdef ENABLE_GBM_ALLOCATION + if (res->gbm_bo) + return virgl_gbm_export_query(res->gbm_bo, export_query); +#endif + + /* + * Implementations that support eglExportDMABUFImageMESA can also export certain resources. + * This is omitted currently since virgl_renderer_get_fd_for_texture supports that use case. + */ + export_query->out_num_fds = 0; + export_query->out_fourcc = 0; + if (export_query->in_export_fds) + return -EINVAL; + + return 0; +} diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h index 333ed28..e89c05d 100644 --- a/src/vrend_renderer.h +++ b/src/vrend_renderer.h @@ -452,4 +452,7 @@ static const struct gl_version gl_versions[] = { {4,5}, {4,4}, {4,3}, {4,2}, {4, {3,3}, {3,2}, {3,1}, {3,0} }; extern struct vrend_if_cbs *vrend_clicbs; + +int vrend_renderer_execute(void *execute_args, uint32_t execute_size); + #endif