[Mesa-dev] [PATCH 3/6] egl: add EGL_ANDROID_native_fence_sync
Rob Clark
robdclark at gmail.com
Fri Apr 1 20:29:47 UTC 2016
From: Rob Clark <robclark at freedesktop.org>
Signed-off-by: Rob Clark <robclark at freedesktop.org>
---
src/egl/drivers/dri2/egl_dri2.c | 48 +++++++++++++++++++++++++++++++++++++++++
src/egl/main/eglapi.c | 36 ++++++++++++++++++++++++++++---
src/egl/main/eglapi.h | 2 ++
src/egl/main/egldisplay.h | 1 +
src/egl/main/eglfallbacks.c | 1 +
src/egl/main/eglsync.c | 22 +++++++++++++++++--
src/egl/main/eglsync.h | 1 +
7 files changed, 106 insertions(+), 5 deletions(-)
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 8f50f0c..8f6115d 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -621,6 +621,12 @@ dri2_setup_screen(_EGLDisplay *disp)
disp->Extensions.KHR_wait_sync = EGL_TRUE;
if (dri2_dpy->fence->get_fence_from_cl_event)
disp->Extensions.KHR_cl_event2 = EGL_TRUE;
+ if (dri2_dpy->fence->base.version >= 2) {
+ unsigned capabilities =
+ dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen);
+ disp->Extensions.ANDROID_native_fence_sync =
+ (capabilities & __DRI_FENCE_CAP_NATIVE_FD) != 0;
+ }
}
if (dri2_dpy->image) {
@@ -2450,6 +2456,19 @@ dri2_create_sync(_EGLDriver *drv, _EGLDisplay *dpy,
dri2_sync->fence, 0, 0))
dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
break;
+
+ case EGL_SYNC_NATIVE_FENCE_ANDROID:
+ if (dri2_dpy->fence->create_fence_fd) {
+ dri2_sync->fence = dri2_dpy->fence->create_fence_fd(
+ dri2_ctx->dri_context,
+ dri2_sync->base.SyncFd);
+ }
+ if (!dri2_sync->fence) {
+ _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
+ free(dri2_sync);
+ return NULL;
+ }
+ break;
}
p_atomic_set(&dri2_sync->refcount, 1);
@@ -2462,11 +2481,39 @@ 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);
+ if (sync->SyncFd != EGL_NO_NATIVE_FENCE_FD_ANDROID)
+ close(sync->SyncFd);
+
dri2_egl_unref_sync(dri2_dpy, dri2_sync);
return EGL_TRUE;
}
static EGLint
+dri2_dup_native_fence_fd(_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);
+
+ assert(sync->Type == EGL_SYNC_NATIVE_FENCE_ANDROID);
+
+ if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+ /* try to retrieve the actual native fence fd.. if rendering is
+ * not flushed this will just return -1, aka NO_NATIVE_FENCE_FD:
+ */
+ sync->SyncFd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen,
+ dri2_sync->fence);
+ }
+
+ if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+ /* if native fence fd still not created, return an error: */
+ _eglError(EGL_BAD_PARAMETER, "eglDupNativeFenceFDANDROID");
+ return EGL_NO_NATIVE_FENCE_FD_ANDROID;
+ }
+
+ return dup(sync->SyncFd);
+}
+
+static EGLint
dri2_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
EGLint flags, EGLTime timeout)
{
@@ -2622,6 +2669,7 @@ _eglBuiltInDriverDRI2(const char *args)
dri2_drv->base.API.ClientWaitSyncKHR = dri2_client_wait_sync;
dri2_drv->base.API.WaitSyncKHR = dri2_server_wait_sync;
dri2_drv->base.API.DestroySyncKHR = dri2_destroy_sync;
+ dri2_drv->base.API.DupNativeFenceFDANDROID = dri2_dup_native_fence_fd;
dri2_drv->base.Name = "DRI2";
dri2_drv->base.Unload = dri2_unload;
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 8886759..e97c38e 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -383,6 +383,7 @@ _eglCreateExtensionsString(_EGLDisplay *dpy)
/* Please keep these sorted alphabetically. */
_EGL_CHECK_EXTENSION(ANDROID_framebuffer_target);
_EGL_CHECK_EXTENSION(ANDROID_image_native_buffer);
+ _EGL_CHECK_EXTENSION(ANDROID_native_fence_sync);
_EGL_CHECK_EXTENSION(ANDROID_recordable);
_EGL_CHECK_EXTENSION(CHROMIUM_sync_control);
@@ -1400,6 +1401,10 @@ _eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list,
if (!disp->Extensions.KHR_cl_event2)
RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
break;
+ case EGL_SYNC_NATIVE_FENCE_ANDROID:
+ if (!disp->Extensions.ANDROID_native_fence_sync)
+ RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
+ break;
default:
RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
}
@@ -1445,7 +1450,8 @@ eglDestroySync(EGLDisplay dpy, EGLSync sync)
_EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
assert(disp->Extensions.KHR_reusable_sync ||
- disp->Extensions.KHR_fence_sync);
+ disp->Extensions.KHR_fence_sync ||
+ disp->Extensions.ANDROID_native_fence_sync);
_eglUnlinkSync(s);
ret = drv->API.DestroySyncKHR(drv, disp, s);
@@ -1464,7 +1470,8 @@ eglClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout)
_EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
assert(disp->Extensions.KHR_reusable_sync ||
- disp->Extensions.KHR_fence_sync);
+ disp->Extensions.KHR_fence_sync ||
+ disp->Extensions.ANDROID_native_fence_sync);
if (s->SyncStatus == EGL_SIGNALED_KHR)
RETURN_EGL_EVAL(disp, EGL_CONDITION_SATISFIED_KHR);
@@ -1538,7 +1545,8 @@ eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *valu
_EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
assert(disp->Extensions.KHR_reusable_sync ||
- disp->Extensions.KHR_fence_sync);
+ disp->Extensions.KHR_fence_sync ||
+ disp->Extensions.ANDROID_native_fence_sync);
ret = drv->API.GetSyncAttrib(drv, disp, s, attribute, value);
RETURN_EGL_EVAL(disp, ret);
@@ -1568,6 +1576,27 @@ eglGetSyncAttribKHR(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint *valu
return result;
}
+static EGLint EGLAPIENTRY
+eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync)
+{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLSync *s = _eglLookupSync(sync, disp);
+ _EGLDriver *drv;
+ EGLBoolean ret;
+
+ /* the spec doesn't seem to specify what happens if the fence
+ * type is not EGL_SYNC_NATIVE_FENCE_ANDROID, but this seems
+ * sensible:
+ */
+ if (s->Type != EGL_SYNC_NATIVE_FENCE_ANDROID)
+ RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_NATIVE_FENCE_FD_ANDROID);
+
+ _EGL_CHECK_SYNC(disp, s, EGL_NO_NATIVE_FENCE_FD_ANDROID, drv);
+ assert(disp->Extensions.ANDROID_native_fence_sync);
+ ret = drv->API.DupNativeFenceFDANDROID(drv, disp, s);
+
+ RETURN_EGL_EVAL(disp, ret);
+}
static EGLBoolean EGLAPIENTRY
eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
@@ -1875,6 +1904,7 @@ eglGetProcAddress(const char *procname)
{ "eglGetSyncValuesCHROMIUM", (_EGLProc) eglGetSyncValuesCHROMIUM },
{ "eglExportDMABUFImageQueryMESA", (_EGLProc) eglExportDMABUFImageQueryMESA },
{ "eglExportDMABUFImageMESA", (_EGLProc) eglExportDMABUFImageMESA },
+ { "eglDupNativeFenceFDANDROID", (_EGLProc) eglDupNativeFenceFDANDROID },
{ NULL, NULL }
};
EGLint i;
diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
index 3f6d3c2..c5595e7 100644
--- a/src/egl/main/eglapi.h
+++ b/src/egl/main/eglapi.h
@@ -144,6 +144,8 @@ struct _egl_api
EGLBoolean (*GetSyncAttrib)(_EGLDriver *drv, _EGLDisplay *dpy,
_EGLSync *sync, EGLint attribute,
EGLAttrib *value);
+ EGLint (*DupNativeFenceFDANDROID)(_EGLDriver *drv, _EGLDisplay *dpy,
+ _EGLSync *sync);
EGLBoolean (*SwapBuffersRegionNOK)(_EGLDriver *drv, _EGLDisplay *disp,
_EGLSurface *surf, EGLint numRects,
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 6bfc858..66251df 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -92,6 +92,7 @@ struct _egl_extensions
/* Please keep these sorted alphabetically. */
EGLBoolean ANDROID_framebuffer_target;
EGLBoolean ANDROID_image_native_buffer;
+ EGLBoolean ANDROID_native_fence_sync;
EGLBoolean ANDROID_recordable;
EGLBoolean CHROMIUM_sync_control;
diff --git a/src/egl/main/eglfallbacks.c b/src/egl/main/eglfallbacks.c
index d0fce8c..017d337 100644
--- a/src/egl/main/eglfallbacks.c
+++ b/src/egl/main/eglfallbacks.c
@@ -92,6 +92,7 @@ _eglInitDriverFallbacks(_EGLDriver *drv)
drv->API.WaitSyncKHR = NULL;
drv->API.SignalSyncKHR = NULL;
drv->API.GetSyncAttrib = _eglGetSyncAttrib;
+ drv->API.DupNativeFenceFDANDROID = NULL;
drv->API.CreateDRMImageMESA = NULL;
drv->API.ExportDRMImageMESA = NULL;
diff --git a/src/egl/main/eglsync.c b/src/egl/main/eglsync.c
index 1d6810d..c1a91c0 100644
--- a/src/egl/main/eglsync.c
+++ b/src/egl/main/eglsync.c
@@ -50,8 +50,14 @@ _eglParseSyncAttribList(_EGLSync *sync, const EGLint *attrib_list)
EGLint val = attrib_list[i];
switch (attr) {
+ case EGL_SYNC_NATIVE_FENCE_FD_ANDROID:
+ if (sync->Type == EGL_SYNC_NATIVE_FENCE_ANDROID) {
+ /* we take ownership of the native fd, so no dup(): */
+ sync->SyncFd = val;
+ break;
+ }
+ /* fallthrough */
default:
- (void) val;
err = EGL_BAD_ATTRIBUTE;
break;
}
@@ -109,6 +115,8 @@ _eglInitSync(_EGLSync *sync, _EGLDisplay *dpy, EGLenum type,
if (!(type == EGL_SYNC_REUSABLE_KHR && dpy->Extensions.KHR_reusable_sync) &&
!(type == EGL_SYNC_FENCE_KHR && dpy->Extensions.KHR_fence_sync) &&
+ !(type == EGL_SYNC_NATIVE_FENCE_ANDROID &&
+ dpy->Extensions.ANDROID_native_fence_sync) &&
!(type == EGL_SYNC_CL_EVENT_KHR && dpy->Extensions.KHR_cl_event2 &&
attrib_list64))
return _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
@@ -116,6 +124,7 @@ _eglInitSync(_EGLSync *sync, _EGLDisplay *dpy, EGLenum type,
_eglInitResource(&sync->Resource, sizeof(*sync), dpy);
sync->Type = type;
sync->SyncStatus = EGL_UNSIGNALED_KHR;
+ sync->SyncFd = EGL_NO_NATIVE_FENCE_FD_ANDROID;
if (attrib_list64)
err = _eglParseSyncAttribList64(sync, attrib_list64);
@@ -126,6 +135,13 @@ _eglInitSync(_EGLSync *sync, _EGLDisplay *dpy, EGLenum type,
case EGL_SYNC_CL_EVENT_KHR:
sync->SyncCondition = EGL_SYNC_CL_EVENT_COMPLETE_KHR;
break;
+ case EGL_SYNC_NATIVE_FENCE_ANDROID:
+ sync->SyncCondition = EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID;
+ if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID)
+ sync->SyncCondition = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
+ else
+ sync->SyncCondition = EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID;
+ break;
default:
sync->SyncCondition = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
}
@@ -159,10 +175,12 @@ _eglGetSyncAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
break;
case EGL_SYNC_CONDITION_KHR:
if (sync->Type != EGL_SYNC_FENCE_KHR &&
- sync->Type != EGL_SYNC_CL_EVENT_KHR)
+ sync->Type != EGL_SYNC_CL_EVENT_KHR &&
+ sync->Type != EGL_SYNC_NATIVE_FENCE_ANDROID)
return _eglError(EGL_BAD_ATTRIBUTE, "eglGetSyncAttribKHR");
*value = sync->SyncCondition;
break;
+
default:
return _eglError(EGL_BAD_ATTRIBUTE, "eglGetSyncAttribKHR");
break;
diff --git a/src/egl/main/eglsync.h b/src/egl/main/eglsync.h
index 9b2aac8..681503f 100644
--- a/src/egl/main/eglsync.h
+++ b/src/egl/main/eglsync.h
@@ -48,6 +48,7 @@ struct _egl_sync
EGLenum SyncStatus;
EGLenum SyncCondition;
EGLAttrib CLEvent;
+ EGLint SyncFd;
};
--
2.5.5
More information about the mesa-dev
mailing list