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 <gert.wollny@collabora.com>
macos/master
David Stevens 4 years ago committed by Gurchetan Singh
parent 1fbffadc7d
commit 16f8d896d0
  1. 48
      src/vrend_renderer.c
  2. 32
      src/vrend_winsys_egl.c
  3. 8
      src/vrend_winsys_egl.h

@ -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 {
GLenum glret = glClientWaitSync(fence->syncobj, 0, timeout);
done = virgl_egl_client_wait_fence(egl, fence->eglsyncobj, timeout);
} while (!done && can_block);
return done;
}
#endif
do {
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);
}

@ -34,7 +34,6 @@
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <epoxy/egl.h>
#include <xf86drm.h>
#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;
}

@ -26,6 +26,9 @@
#include "virglrenderer.h"
#include "vrend_renderer.h"
#include <epoxy/egl.h>
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

Loading…
Cancel
Save