diff --git a/src/virgl_egl.h b/src/virgl_egl.h index e7f0270..73df209 100644 --- a/src/virgl_egl.h +++ b/src/virgl_egl.h @@ -54,4 +54,5 @@ int virgl_egl_get_fd_for_texture2(struct virgl_egl *egl, uint32_t tex_id, int *f int *offset); void *virgl_egl_image_from_dmabuf(struct virgl_egl *egl, struct gbm_bo *bo); +void virgl_egl_image_destroy(struct virgl_egl *egl, void *image); #endif diff --git a/src/virgl_egl_context.c b/src/virgl_egl_context.c index 5a387fd..d70ca3b 100644 --- a/src/virgl_egl_context.c +++ b/src/virgl_egl_context.c @@ -435,3 +435,8 @@ out_close: return (void*)image; } + +void virgl_egl_image_destroy(struct virgl_egl *egl, void *image) +{ + eglDestroyImageKHR(egl->egl_display, image); +} diff --git a/src/virgl_gbm.c b/src/virgl_gbm.c index 054fd0e..5e3b1a0 100644 --- a/src/virgl_gbm.c +++ b/src/virgl_gbm.c @@ -356,3 +356,15 @@ int virgl_gbm_transfer(struct gbm_bo *bo, uint32_t direction, struct iovec *iove gbm_bo_unmap(bo, map_data); return 0; } + +uint32_t virgl_gbm_convert_flags(uint32_t virgl_bind_flags) +{ + uint32_t flags = 0; + if (virgl_bind_flags & VIRGL_BIND_RENDER_TARGET) + flags |= GBM_BO_USE_RENDERING; + if (virgl_bind_flags & VIRGL_BIND_SCANOUT) + flags |= GBM_BO_USE_SCANOUT; + if (virgl_bind_flags & VIRGL_BIND_CURSOR) + flags |= GBM_BO_USE_CURSOR; + return flags; +} diff --git a/src/virgl_gbm.h b/src/virgl_gbm.h index 02646b5..6f17a41 100644 --- a/src/virgl_gbm.h +++ b/src/virgl_gbm.h @@ -46,4 +46,7 @@ uint32_t virgl_gbm_convert_format(uint32_t virgl_format); int virgl_gbm_transfer(struct gbm_bo *bo, uint32_t direction, struct iovec *iovecs, uint32_t num_iovecs, const struct vrend_transfer_info *info); + +uint32_t virgl_gbm_convert_flags(uint32_t virgl_bind_flags); + #endif diff --git a/src/virglrenderer.c b/src/virglrenderer.c index ab68846..584be01 100644 --- a/src/virglrenderer.c +++ b/src/virglrenderer.c @@ -41,8 +41,8 @@ #ifdef HAVE_EPOXY_EGL_H #include "virgl_gbm.h" #include "virgl_egl.h" -static struct virgl_gbm *gbm = NULL; -static struct virgl_egl *egl = NULL; +struct virgl_gbm *gbm = NULL; +struct virgl_egl *egl = NULL; #endif #ifdef HAVE_EPOXY_GLX_H diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index dc4497d..ba807c5 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -6120,6 +6120,54 @@ vrend_renderer_resource_copy_args(struct vrend_renderer_resource_create_args *ar gr->base.array_size = args->array_size; } +static void *vrend_allocate_using_gbm(struct vrend_resource *gr) +{ +#ifdef ENABLE_GBM_ALLOCATION + uint32_t gbm_flags = virgl_gbm_convert_flags(gr->base.bind); + uint32_t gbm_format = virgl_gbm_convert_format(gr->base.format); + if (gr->base.depth0 != 1 || gr->base.last_level != 0 || gr->base.nr_samples != 0) + return NULL; + + if (!gbm_format) + return NULL; + + if (!gbm_flags) + return NULL; + + if ((gr->base.bind & (VIRGL_RES_BIND_SCANOUT | VIRGL_RES_BIND_SHARED)) == 0) + return NULL; + + if (!gbm_device_is_format_supported(gbm->device, gbm_format, gbm_flags)) + return NULL; + + /* + * loader_dri3_get_buffers requests 1x1 textures with the following flags: + * *_BIND_SCANOUT | *_BIND_SHARED | *_SAMPLER_VIEW | *_RENDER_TARGET. + * 32 x 32 buffers are also requested with the same flags and never sent to the + * display. TODO(gsingh): figure out how to optimize this. + */ + if (gr->base.width0 == 1 && gr->base.height0 == 1) + return NULL; + + struct gbm_bo *bo = gbm_bo_create(gbm->device, gr->base.width0, gr->base.height0, + gbm_format, gbm_flags); + if (!bo) + return NULL; + + void *image = virgl_egl_image_from_dmabuf(egl, bo); + if (!image) { + gbm_bo_destroy(bo); + return NULL; + } + + gr->egl_image = image; + gr->gbm_bo = bo; + return image; +#else + return NULL; +#endif +} + static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr, void *image_oes) { @@ -6132,6 +6180,9 @@ static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr, if (pr->width0 == 0) return EINVAL; + if (!image_oes) + image_oes = vrend_allocate_using_gbm(gr); + if (image_oes) gr->base.bind &= ~VIRGL_BIND_PREFER_EMULATED_BGRA; else @@ -6388,6 +6439,13 @@ void vrend_renderer_resource_destroy(struct vrend_resource *res) break; } +#ifdef ENABLE_GBM_ALLOCATION + if (res->egl_image) + virgl_egl_image_destroy(egl, res->egl_image); + if (res->gbm_bo) + gbm_bo_destroy(res->gbm_bo); +#endif + free(res); } @@ -7318,6 +7376,11 @@ int vrend_renderer_transfer_iov(const struct vrend_transfer_info *info, ctx = NULL; } +#ifdef ENABLE_GBM_ALLOCATION + if (res->gbm_bo) + return virgl_gbm_transfer(res->gbm_bo, transfer_mode, iov, num_iovs, info); +#endif + switch (transfer_mode) { case VIRGL_TRANSFER_TO_HOST: return vrend_renderer_transfer_write_iov(ctx, res, iov, num_iovs, info); diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h index f8c53d9..333ed28 100644 --- a/src/vrend_renderer.h +++ b/src/vrend_renderer.h @@ -84,6 +84,7 @@ struct vrend_resource { struct iovec *iov; uint32_t num_iovs; uint64_t mipmap_offsets[VR_MAX_TEXTURE_2D_LEVELS]; + void *gbm_bo, *egl_image; }; #define VIRGL_TEXTURE_NEED_SWIZZLE (1 << 0)