mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 02:58:05 +02:00
egl/dri2: implement EGL_KHR_fence_sync
This commit is contained in:
parent
592ee249a1
commit
9a0bda2430
3 changed files with 133 additions and 5 deletions
|
|
@ -51,6 +51,7 @@
|
|||
#endif
|
||||
|
||||
#include "egl_dri2.h"
|
||||
#include "../util/u_atomic.h"
|
||||
|
||||
const __DRIuseInvalidateExtension use_invalidate = {
|
||||
.base = { __DRI_USE_INVALIDATE, 1 }
|
||||
|
|
@ -527,6 +528,10 @@ dri2_setup_screen(_EGLDisplay *disp)
|
|||
disp->Extensions.EXT_create_context_robustness = EGL_TRUE;
|
||||
}
|
||||
|
||||
if (dri2_dpy->fence) {
|
||||
disp->Extensions.KHR_fence_sync = EGL_TRUE;
|
||||
}
|
||||
|
||||
if (dri2_dpy->image) {
|
||||
if (dri2_dpy->image->base.version >= 10 &&
|
||||
dri2_dpy->image->getCapabilities != NULL) {
|
||||
|
|
@ -620,6 +625,9 @@ dri2_create_screen(_EGLDisplay *disp)
|
|||
if (strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0) {
|
||||
dri2_dpy->config = (__DRI2configQueryExtension *) extensions[i];
|
||||
}
|
||||
if (strcmp(extensions[i]->name, __DRI2_FENCE) == 0) {
|
||||
dri2_dpy->fence = (__DRI2fenceExtension *) extensions[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert(dri2_dpy->swrast);
|
||||
|
|
@ -2180,6 +2188,90 @@ dri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp,
|
|||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
dri2_egl_ref_sync(struct dri2_egl_sync *sync)
|
||||
{
|
||||
p_atomic_inc(&sync->refcount);
|
||||
}
|
||||
|
||||
static void
|
||||
dri2_egl_unref_sync(struct dri2_egl_display *dri2_dpy,
|
||||
struct dri2_egl_sync *dri2_sync)
|
||||
{
|
||||
if (p_atomic_dec_zero(&dri2_sync->refcount)) {
|
||||
dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, dri2_sync->fence);
|
||||
free(dri2_sync);
|
||||
}
|
||||
}
|
||||
|
||||
static _EGLSync *
|
||||
dri2_create_sync(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||
EGLenum type, const EGLint *attrib_list)
|
||||
{
|
||||
_EGLContext *ctx = _eglGetCurrentContext();
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
|
||||
struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
|
||||
struct dri2_egl_sync *dri2_sync;
|
||||
|
||||
dri2_sync = calloc(1, sizeof(struct dri2_egl_sync));
|
||||
if (!dri2_sync) {
|
||||
_eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_eglInitSync(&dri2_sync->base, dpy, type, attrib_list)) {
|
||||
free(dri2_sync);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case EGL_SYNC_FENCE_KHR:
|
||||
dri2_sync->fence = dri2_dpy->fence->create_fence(dri2_ctx->dri_context);
|
||||
break;
|
||||
}
|
||||
|
||||
p_atomic_set(&dri2_sync->refcount, 1);
|
||||
return &dri2_sync->base;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
dri2_destroy_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
|
||||
struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
|
||||
|
||||
dri2_egl_unref_sync(dri2_dpy, dri2_sync);
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static EGLint
|
||||
dri2_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
|
||||
EGLint flags, EGLTimeKHR timeout)
|
||||
{
|
||||
_EGLContext *ctx = _eglGetCurrentContext();
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
|
||||
struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
|
||||
struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync);
|
||||
unsigned wait_flags = 0;
|
||||
EGLint ret = EGL_CONDITION_SATISFIED_KHR;
|
||||
|
||||
if (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)
|
||||
wait_flags |= __DRI2_FENCE_FLAG_FLUSH_COMMANDS;
|
||||
|
||||
/* the sync object should take a reference while waiting */
|
||||
dri2_egl_ref_sync(dri2_sync);
|
||||
|
||||
if (dri2_dpy->fence->client_wait_sync(dri2_ctx->dri_context,
|
||||
dri2_sync->fence, wait_flags,
|
||||
timeout))
|
||||
dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
|
||||
else
|
||||
ret = EGL_TIMEOUT_EXPIRED_KHR;
|
||||
|
||||
dri2_egl_unref_sync(dri2_dpy, dri2_sync);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
dri2_unload(_EGLDriver *drv)
|
||||
{
|
||||
|
|
@ -2292,6 +2384,9 @@ _eglBuiltInDriverDRI2(const char *args)
|
|||
dri2_drv->base.API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl;
|
||||
#endif
|
||||
dri2_drv->base.API.GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium;
|
||||
dri2_drv->base.API.CreateSyncKHR = dri2_create_sync;
|
||||
dri2_drv->base.API.ClientWaitSyncKHR = dri2_client_wait_sync;
|
||||
dri2_drv->base.API.DestroySyncKHR = dri2_destroy_sync;
|
||||
|
||||
dri2_drv->base.Name = "DRI2";
|
||||
dri2_drv->base.Unload = dri2_unload;
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@
|
|||
#include "egllog.h"
|
||||
#include "eglsurface.h"
|
||||
#include "eglimage.h"
|
||||
#include "eglsync.h"
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
|
|
@ -164,6 +165,7 @@ struct dri2_egl_display
|
|||
const __DRIimageExtension *image;
|
||||
const __DRIrobustnessExtension *robustness;
|
||||
const __DRI2configQueryExtension *config;
|
||||
const __DRI2fenceExtension *fence;
|
||||
int fd;
|
||||
|
||||
int own_device;
|
||||
|
|
@ -283,6 +285,12 @@ struct dri2_egl_image
|
|||
__DRIimage *dri_image;
|
||||
};
|
||||
|
||||
struct dri2_egl_sync {
|
||||
_EGLSync base;
|
||||
int refcount;
|
||||
void *fence;
|
||||
};
|
||||
|
||||
/* From xmlpool/options.h, user exposed so should be stable */
|
||||
#define DRI_CONF_VBLANK_NEVER 0
|
||||
#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1
|
||||
|
|
@ -292,6 +300,7 @@ struct dri2_egl_image
|
|||
/* standard typecasts */
|
||||
_EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl)
|
||||
_EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj)
|
||||
_EGL_DRIVER_TYPECAST(dri2_egl_sync, _EGLSync, obj)
|
||||
|
||||
extern const __DRIimageLookupExtension image_lookup_extension;
|
||||
extern const __DRIuseInvalidateExtension use_invalidate;
|
||||
|
|
|
|||
|
|
@ -1657,13 +1657,30 @@ EGLSyncKHR EGLAPIENTRY
|
|||
eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
|
||||
{
|
||||
_EGLDisplay *disp = _eglLockDisplay(dpy);
|
||||
_EGLContext *ctx = _eglGetCurrentContext();
|
||||
_EGLDriver *drv;
|
||||
_EGLSync *sync;
|
||||
EGLSyncKHR ret;
|
||||
|
||||
_EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
|
||||
if (!disp->Extensions.KHR_reusable_sync)
|
||||
RETURN_EGL_EVAL(disp, EGL_NO_SYNC_KHR);
|
||||
|
||||
/* return an error if the client API doesn't support GL_OES_EGL_sync */
|
||||
if (!ctx || ctx->Resource.Display != dpy ||
|
||||
ctx->ClientAPI != EGL_OPENGL_ES_API)
|
||||
RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
|
||||
|
||||
switch (type) {
|
||||
case EGL_SYNC_FENCE_KHR:
|
||||
if (!disp->Extensions.KHR_fence_sync)
|
||||
RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
|
||||
break;
|
||||
case EGL_SYNC_REUSABLE_KHR:
|
||||
if (!disp->Extensions.KHR_reusable_sync)
|
||||
RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
|
||||
break;
|
||||
default:
|
||||
RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
|
||||
}
|
||||
|
||||
sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list);
|
||||
ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR;
|
||||
|
|
@ -1681,7 +1698,8 @@ eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
|
|||
EGLBoolean ret;
|
||||
|
||||
_EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
|
||||
assert(disp->Extensions.KHR_reusable_sync);
|
||||
assert(disp->Extensions.KHR_reusable_sync ||
|
||||
disp->Extensions.KHR_fence_sync);
|
||||
|
||||
_eglUnlinkSync(s);
|
||||
ret = drv->API.DestroySyncKHR(drv, disp, s);
|
||||
|
|
@ -1699,7 +1717,12 @@ eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR t
|
|||
EGLint ret;
|
||||
|
||||
_EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
|
||||
assert(disp->Extensions.KHR_reusable_sync);
|
||||
assert(disp->Extensions.KHR_reusable_sync ||
|
||||
disp->Extensions.KHR_fence_sync);
|
||||
|
||||
if (s->SyncStatus == EGL_SIGNALED_KHR)
|
||||
RETURN_EGL_EVAL(disp, EGL_CONDITION_SATISFIED_KHR);
|
||||
|
||||
ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout);
|
||||
|
||||
RETURN_EGL_EVAL(disp, ret);
|
||||
|
|
@ -1731,7 +1754,8 @@ eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *v
|
|||
EGLBoolean ret;
|
||||
|
||||
_EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
|
||||
assert(disp->Extensions.KHR_reusable_sync);
|
||||
assert(disp->Extensions.KHR_reusable_sync ||
|
||||
disp->Extensions.KHR_fence_sync);
|
||||
ret = drv->API.GetSyncAttribKHR(drv, disp, s, attribute, value);
|
||||
|
||||
RETURN_EGL_EVAL(disp, ret);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue