egl/dri2: implement EGL_KHR_cl_event2 (v2)
authorMarek Olšák <marek.olsak@amd.com>
Fri, 10 Apr 2015 11:16:30 +0000 (13:16 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Thu, 30 Apr 2015 12:38:38 +0000 (14:38 +0200)
v2: fix the SYNC_CONDITION query

src/egl/drivers/dri2/egl_dri2.c
src/egl/main/eglapi.c
src/egl/main/eglapi.h
src/egl/main/egldisplay.h
src/egl/main/eglsync.c
src/egl/main/eglsync.h

index e096a7df282666b4e69bf9256b0e9b10ba0694fc..34d6bfeefac2e23e0caf06725f37e32f6e5c2ea4 100644 (file)
@@ -531,6 +531,8 @@ dri2_setup_screen(_EGLDisplay *disp)
    if (dri2_dpy->fence) {
       disp->Extensions.KHR_fence_sync = EGL_TRUE;
       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->image) {
@@ -2207,7 +2209,8 @@ dri2_egl_unref_sync(struct dri2_egl_display *dri2_dpy,
 
 static _EGLSync *
 dri2_create_sync(_EGLDriver *drv, _EGLDisplay *dpy,
-                 EGLenum type, const EGLint *attrib_list)
+                 EGLenum type, const EGLint *attrib_list,
+                 const EGLAttribKHR *attrib_list64)
 {
    _EGLContext *ctx = _eglGetCurrentContext();
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
@@ -2220,7 +2223,8 @@ dri2_create_sync(_EGLDriver *drv, _EGLDisplay *dpy,
       return NULL;
    }
 
-   if (!_eglInitSync(&dri2_sync->base, dpy, type, attrib_list)) {
+   if (!_eglInitSync(&dri2_sync->base, dpy, type, attrib_list,
+                     attrib_list64)) {
       free(dri2_sync);
       return NULL;
    }
@@ -2229,6 +2233,23 @@ dri2_create_sync(_EGLDriver *drv, _EGLDisplay *dpy,
    case EGL_SYNC_FENCE_KHR:
       dri2_sync->fence = dri2_dpy->fence->create_fence(dri2_ctx->dri_context);
       break;
+
+   case EGL_SYNC_CL_EVENT_KHR:
+      dri2_sync->fence = dri2_dpy->fence->get_fence_from_cl_event(
+                                 dri2_dpy->dri_screen,
+                                 dri2_sync->base.CLEvent);
+      /* this can only happen if the cl_event passed in is invalid. */
+      if (!dri2_sync->fence) {
+         _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
+         free(dri2_sync);
+         return NULL;
+      }
+
+      /* the initial status must be "signaled" if the cl_event is signaled */
+      if (dri2_dpy->fence->client_wait_sync(dri2_ctx->dri_context,
+                                            dri2_sync->fence, 0, 0))
+         dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
+      break;
    }
 
    p_atomic_set(&dri2_sync->refcount, 1);
index 65a730abb5e28a43ba99483a560f817143936865..ec41aa3f15bfbd3f058560a2828681a20c0594cb 100644 (file)
@@ -407,6 +407,7 @@ _eglCreateExtensionsString(_EGLDisplay *dpy)
    _EGL_CHECK_EXTENSION(KHR_reusable_sync);
    _EGL_CHECK_EXTENSION(KHR_fence_sync);
    _EGL_CHECK_EXTENSION(KHR_wait_sync);
+   _EGL_CHECK_EXTENSION(KHR_cl_event2);
 
    _EGL_CHECK_EXTENSION(KHR_surfaceless_context);
    _EGL_CHECK_EXTENSION(KHR_create_context);
@@ -1215,6 +1216,7 @@ eglGetProcAddress(const char *procname)
       { "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
       { "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR },
       { "eglCreateSyncKHR", (_EGLProc) eglCreateSyncKHR },
+      { "eglCreateSync64KHR", (_EGLProc) eglCreateSync64KHR },
       { "eglDestroySyncKHR", (_EGLProc) eglDestroySyncKHR },
       { "eglClientWaitSyncKHR", (_EGLProc) eglClientWaitSyncKHR },
       { "eglWaitSyncKHR", (_EGLProc) eglWaitSyncKHR },
@@ -1655,8 +1657,9 @@ eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
 }
 
 
-EGLSyncKHR EGLAPIENTRY
-eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
+static EGLSyncKHR
+_eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list,
+               const EGLAttribKHR *attrib_list64, EGLBoolean is64)
 {
    _EGLDisplay *disp = _eglLockDisplay(dpy);
    _EGLContext *ctx = _eglGetCurrentContext();
@@ -1666,6 +1669,9 @@ eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
 
    _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
 
+   if (!disp->Extensions.KHR_cl_event2 && is64)
+      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)
@@ -1680,17 +1686,35 @@ eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
       if (!disp->Extensions.KHR_reusable_sync)
          RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
       break;
+   case EGL_SYNC_CL_EVENT_KHR:
+      if (!disp->Extensions.KHR_cl_event2)
+         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);
+   sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list, attrib_list64);
    ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR;
 
    RETURN_EGL_EVAL(disp, ret);
 }
 
 
+EGLSyncKHR EGLAPIENTRY
+eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
+{
+   return _eglCreateSync(dpy, type, attrib_list, NULL, EGL_FALSE);
+}
+
+
+EGLSyncKHR EGLAPIENTRY
+eglCreateSync64KHR(EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list)
+{
+   return _eglCreateSync(dpy, type, NULL, attrib_list, EGL_TRUE);
+}
+
+
 EGLBoolean EGLAPIENTRY
 eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
 {
index 7462b35d3ba16332ae6f877b1cb5696587714c15..522688673825f01a59c79708989f1b02478cf520 100644 (file)
@@ -102,7 +102,7 @@ typedef _EGLImage *(*CreateImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLCo
 typedef EGLBoolean (*DestroyImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image);
 
 
-typedef _EGLSync *(*CreateSyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLenum type, const EGLint *attrib_list);
+typedef _EGLSync *(*CreateSyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLenum type, const EGLint *attrib_list, const EGLAttribKHR *attrib_list64);
 typedef EGLBoolean (*DestroySyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync);
 typedef EGLint (*ClientWaitSyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, EGLint flags, EGLTimeKHR timeout);
 typedef EGLint (*WaitSyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync);
index 70381bcfe51b7ec30f64a00793c4621d7f9d6e93..b6b9ed8e2787c3475d8438082d61556116cb1868 100644 (file)
@@ -107,6 +107,7 @@ struct _egl_extensions
    EGLBoolean KHR_reusable_sync;
    EGLBoolean KHR_fence_sync;
    EGLBoolean KHR_wait_sync;
+   EGLBoolean KHR_cl_event2;
 
    EGLBoolean KHR_surfaceless_context;
    EGLBoolean KHR_create_context;
index 9d0067caa2df5c1e7281ef00e0726fde4076f721..3b4a88902fd21ac0e214992e5caa6869fc2a7790 100644 (file)
@@ -65,25 +65,76 @@ _eglParseSyncAttribList(_EGLSync *sync, const EGLint *attrib_list)
 }
 
 
+static EGLint
+_eglParseSyncAttribList64(_EGLSync *sync, const EGLAttribKHR *attrib_list)
+{
+   EGLint i, err = EGL_SUCCESS;
+
+   if (!attrib_list)
+      return EGL_SUCCESS;
+
+   for (i = 0; attrib_list[i] != EGL_NONE; i++) {
+      EGLint attr = attrib_list[i++];
+      EGLint val = attrib_list[i];
+
+      switch (attr) {
+      case EGL_CL_EVENT_HANDLE_KHR:
+         if (sync->Type == EGL_SYNC_CL_EVENT_KHR) {
+            sync->CLEvent = val;
+            break;
+         }
+         /* fall through */
+      default:
+         (void) val;
+         err = EGL_BAD_ATTRIBUTE;
+         break;
+      }
+
+      if (err != EGL_SUCCESS) {
+         _eglLog(_EGL_DEBUG, "bad sync attribute 0x%04x", attr);
+         break;
+      }
+   }
+
+   return err;
+}
+
+
 EGLBoolean
 _eglInitSync(_EGLSync *sync, _EGLDisplay *dpy, EGLenum type,
-             const EGLint *attrib_list)
+             const EGLint *attrib_list, const EGLAttribKHR *attrib_list64)
 {
    EGLint err;
 
    if (!(type == EGL_SYNC_REUSABLE_KHR && dpy->Extensions.KHR_reusable_sync) &&
-       !(type == EGL_SYNC_FENCE_KHR && dpy->Extensions.KHR_fence_sync))
+       !(type == EGL_SYNC_FENCE_KHR && dpy->Extensions.KHR_fence_sync) &&
+       !(type == EGL_SYNC_CL_EVENT_KHR && dpy->Extensions.KHR_cl_event2 &&
+         attrib_list64))
       return _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
 
    _eglInitResource(&sync->Resource, sizeof(*sync), dpy);
    sync->Type = type;
    sync->SyncStatus = EGL_UNSIGNALED_KHR;
-   sync->SyncCondition = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
 
-   err = _eglParseSyncAttribList(sync, attrib_list);
+   switch (type) {
+   case EGL_SYNC_CL_EVENT_KHR:
+      sync->SyncCondition = EGL_SYNC_CL_EVENT_COMPLETE_KHR;
+      break;
+   default:
+      sync->SyncCondition = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
+   }
+
+   if (attrib_list64)
+      err = _eglParseSyncAttribList64(sync, attrib_list64);
+   else
+      err = _eglParseSyncAttribList(sync, attrib_list);
+
    if (err != EGL_SUCCESS)
       return _eglError(err, "eglCreateSyncKHR");
 
+   if (type == EGL_SYNC_CL_EVENT_KHR && !sync->CLEvent)
+      return _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
+
    return EGL_TRUE;
 }
 
@@ -103,7 +154,8 @@ _eglGetSyncAttribKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
       *value = sync->SyncStatus;
       break;
    case EGL_SYNC_CONDITION_KHR:
-      if (sync->Type != EGL_SYNC_FENCE_KHR)
+      if (sync->Type != EGL_SYNC_FENCE_KHR &&
+          sync->Type != EGL_SYNC_CL_EVENT_KHR)
          return _eglError(EGL_BAD_ATTRIBUTE, "eglGetSyncAttribKHR");
       *value = sync->SyncCondition;
       break;
index c6cf8c6479e410bc396501171bfbcd4cba91a080..1d2eb11a7a06891e5e00d435b327be1e49c747a0 100644 (file)
@@ -47,12 +47,13 @@ struct _egl_sync
    EGLenum Type;
    EGLenum SyncStatus;
    EGLenum SyncCondition;
+   EGLAttribKHR CLEvent;
 };
 
 
 extern EGLBoolean
 _eglInitSync(_EGLSync *sync, _EGLDisplay *dpy, EGLenum type,
-             const EGLint *attrib_list);
+             const EGLint *attrib_list, const EGLAttribKHR *attrib_list64);
 
 
 extern EGLBoolean