From 16f8d896d0fd15d183eeb35133f8a83e5f3ea65a Mon Sep 17 00:00:00 2001 From: David Stevens Date: Fri, 19 Jun 2020 11:38:47 +0900 Subject: [PATCH] vrend: build fences on EGLSyncKHR when possible This change is being done in preparation for exporting fences, so the fences are built on EGL_ANDROID_native_fence_sync instead of on EGL_KHR_fence_sync. Reviewed-by: Gert Wollny --- src/vrend_renderer.c | 48 ++++++++++++++++++++++++++++++++++++------ src/vrend_winsys_egl.c | 32 +++++++++++++++++++++++++--- src/vrend_winsys_egl.h | 8 +++++++ 3 files changed, 79 insertions(+), 9 deletions(-) diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 50edfd2..e9c3c77 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -68,7 +68,12 @@ const struct vrend_if_cbs *vrend_clicbs; struct vrend_fence { uint32_t fence_id; uint32_t ctx_id; - GLsync syncobj; + union { + GLsync glsyncobj; +#ifdef HAVE_EPOXY_EGL_H + EGLSyncKHR eglsyncobj; +#endif + }; struct list_head fences; }; @@ -283,6 +288,9 @@ struct global_renderer_state { bool use_core_profile; bool use_external_blob; bool use_integer; +#ifdef HAVE_EPOXY_EGL_H + bool use_egl_fence; +#endif bool features[feat_last]; @@ -5714,10 +5722,20 @@ static bool do_wait(struct vrend_fence *fence, bool can_block) { bool done = false; int timeout = can_block ? 1000000000 : 0; + +#ifdef HAVE_EPOXY_EGL_H + if (vrend_state.use_egl_fence) { + do { + done = virgl_egl_client_wait_fence(egl, fence->eglsyncobj, timeout); + } while (!done && can_block); + return done; + } +#endif + do { - GLenum glret = glClientWaitSync(fence->syncobj, 0, timeout); + GLenum glret = glClientWaitSync(fence->glsyncobj, 0, timeout); if (glret == GL_WAIT_FAILED) { - vrend_printf( "wait sync failed: illegal fence object %p\n", fence->syncobj); + vrend_printf( "wait sync failed: illegal fence object %p\n", fence->glsyncobj); } done = glret != GL_TIMEOUT_EXPIRED; } while (!done && can_block); @@ -6046,6 +6064,10 @@ int vrend_renderer_init(const struct vrend_if_cbs *cbs, uint32_t flags) if (flags & VREND_USE_EXTERNAL_BLOB) vrend_state.use_external_blob = true; +#ifdef HAVE_EPOXY_EGL_H + vrend_state.use_egl_fence = virgl_egl_supports_fences(egl); +#endif + return 0; } @@ -8956,10 +8978,17 @@ int vrend_renderer_create_fence(int client_fence_id, uint32_t ctx_id) fence->ctx_id = ctx_id; fence->fence_id = client_fence_id; - fence->syncobj = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); +#ifdef HAVE_EPOXY_EGL_H + if (vrend_state.use_egl_fence) { + fence->eglsyncobj = virgl_egl_fence_create(egl); + } else +#endif + { + fence->glsyncobj = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + } glFlush(); - if (fence->syncobj == NULL) + if (fence->glsyncobj == NULL) goto fail; if (vrend_state.sync_thread) { @@ -8980,7 +9009,14 @@ int vrend_renderer_create_fence(int client_fence_id, uint32_t ctx_id) static void free_fence_locked(struct vrend_fence *fence) { list_del(&fence->fences); - glDeleteSync(fence->syncobj); +#ifdef HAVE_EPOXY_EGL_H + if (vrend_state.use_egl_fence) { + virgl_egl_fence_destroy(egl, fence->eglsyncobj); + } else +#endif + { + glDeleteSync(fence->glsyncobj); + } free(fence); } diff --git a/src/vrend_winsys_egl.c b/src/vrend_winsys_egl.c index 3429539..4994a34 100644 --- a/src/vrend_winsys_egl.c +++ b/src/vrend_winsys_egl.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include "util/u_memory.h" @@ -53,7 +52,7 @@ #define EGL_KHR_GL_COLORSPACE BIT(5) #define EGL_EXT_IMAGE_DMA_BUF_IMPORT BIT(6) #define EGL_EXT_IMAGE_DMA_BUF_IMPORT_MODIFIERS BIT(7) -#define EGL_KHR_FENCE_SYNC BIT(8) +#define EGL_KHR_FENCE_SYNC_ANDROID BIT(8) static const struct { uint32_t bit; @@ -66,7 +65,7 @@ static const struct { { EGL_KHR_GL_COLORSPACE, "EGL_KHR_gl_colorspace" }, { EGL_EXT_IMAGE_DMA_BUF_IMPORT, "EGL_EXT_image_dma_buf_import" }, { EGL_EXT_IMAGE_DMA_BUF_IMPORT_MODIFIERS, "EGL_EXT_image_dma_buf_import_modifiers" }, - { EGL_KHR_FENCE_SYNC, "EGL_KHR_fence_sync"} + { EGL_KHR_FENCE_SYNC_ANDROID, "EGL_ANDROID_native_fence_sync"} }; struct virgl_egl { @@ -507,3 +506,30 @@ void virgl_egl_image_destroy(struct virgl_egl *egl, void *image) eglDestroyImageKHR(egl->egl_display, image); } #endif + +bool virgl_egl_supports_fences(struct virgl_egl *egl) +{ + return (egl && has_bit(egl->extension_bits, EGL_KHR_FENCE_SYNC_ANDROID)); +} + +EGLSyncKHR virgl_egl_fence_create(struct virgl_egl *egl) +{ + if (!egl || !has_bit(egl->extension_bits, EGL_KHR_FENCE_SYNC_ANDROID)) { + return EGL_NO_SYNC_KHR; + } + + return eglCreateSyncKHR(egl->egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); +} + +void virgl_egl_fence_destroy(struct virgl_egl *egl, EGLSyncKHR fence) { + eglDestroySyncKHR(egl->egl_display, fence); +} + +bool virgl_egl_client_wait_fence(struct virgl_egl *egl, EGLSyncKHR fence, uint64_t timeout) +{ + EGLint ret = eglClientWaitSyncKHR(egl->egl_display, fence, 0, timeout); + if (ret == EGL_FALSE) { + vrend_printf("wait sync failed\n"); + } + return ret != EGL_TIMEOUT_EXPIRED_KHR; +} diff --git a/src/vrend_winsys_egl.h b/src/vrend_winsys_egl.h index b52041b..7f0a2eb 100644 --- a/src/vrend_winsys_egl.h +++ b/src/vrend_winsys_egl.h @@ -26,6 +26,9 @@ #include "virglrenderer.h" #include "vrend_renderer.h" + +#include + struct virgl_egl; struct virgl_gbm; struct gbm_bo; @@ -56,4 +59,9 @@ int virgl_egl_get_fd_for_texture2(struct virgl_egl *egl, uint32_t tex_id, int *f void *virgl_egl_image_from_dmabuf(struct virgl_egl *egl, struct gbm_bo *bo); void *virgl_egl_aux_plane_image_from_dmabuf(struct virgl_egl *egl, struct gbm_bo *bo, int plane); void virgl_egl_image_destroy(struct virgl_egl *egl, void *image); + +bool virgl_egl_supports_fences(struct virgl_egl *egl); +EGLSyncKHR virgl_egl_fence_create(struct virgl_egl *egl); +void virgl_egl_fence_destroy(struct virgl_egl *egl, EGLSyncKHR fence); +bool virgl_egl_client_wait_fence(struct virgl_egl *egl, EGLSyncKHR fence, uint64_t timeout); #endif