egl: Add support for EGL_KHR_reusable_sync.
authorChia-I Wu <olv@lunarg.com>
Sat, 14 Aug 2010 15:09:12 +0000 (23:09 +0800)
committerChia-I Wu <olv@lunarg.com>
Mon, 16 Aug 2010 16:06:19 +0000 (00:06 +0800)
Individual drivers still need to support and enable the extension.

src/egl/main/Makefile
src/egl/main/eglapi.c
src/egl/main/eglapi.h
src/egl/main/egldisplay.h
src/egl/main/egldriver.c
src/egl/main/eglmisc.c
src/egl/main/eglsync.c [new file with mode: 0644]
src/egl/main/eglsync.h [new file with mode: 0644]
src/egl/main/egltypedefs.h

index 41d301fc14056b6b3a02f659b354308a1b0f060d..d92fbf6d9a7e854393b66e1bf1478b4523dbb3d8 100644 (file)
@@ -26,7 +26,8 @@ HEADERS = \
        eglmutex.h \
        eglscreen.h \
        eglstring.h \
-       eglsurface.h
+       eglsurface.h \
+       eglsync.h
 
 SOURCES = \
        eglapi.c \
@@ -44,7 +45,8 @@ SOURCES = \
        eglmode.c \
        eglscreen.c \
        eglstring.c \
-       eglsurface.c
+       eglsurface.c \
+       eglsync.c
 
 OBJECTS = $(SOURCES:.c=.o)
 
index 4dc8707cfbc66afaaf30bf0862748065823b3491..53a5f6ed223a46226896c4b0909a5305e5a289aa 100644 (file)
@@ -68,6 +68,7 @@
 #include "eglscreen.h"
 #include "eglmode.h"
 #include "eglimage.h"
+#include "eglsync.h"
 
 
 /**
 #define _EGL_CHECK_MODE(disp, m, ret, drv) \
    _EGL_CHECK_OBJECT(disp, Mode, m, ret, drv)
 
+#define _EGL_CHECK_SYNC(disp, s, ret, drv) \
+   _EGL_CHECK_OBJECT(disp, Sync, s, ret, drv)
 
 
 static INLINE _EGLDriver *
@@ -185,6 +188,26 @@ _eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg)
 }
 
 
+#ifdef EGL_KHR_reusable_sync
+
+
+static INLINE _EGLDriver *
+_eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg)
+{
+   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
+   if (!drv)
+      return NULL;
+   if (!s) {
+      _eglError(EGL_BAD_PARAMETER, msg);
+      return NULL;
+   }
+   return drv;
+}
+
+
+#endif /* EGL_KHR_reusable_sync */
+
+
 #ifdef EGL_MESA_screen_surface
 
 
@@ -1245,6 +1268,90 @@ eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
 #endif /* EGL_KHR_image_base */
 
 
+#ifdef EGL_KHR_reusable_sync
+
+
+EGLSyncKHR EGLAPIENTRY
+eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLDriver *drv;
+   _EGLSync *sync;
+   EGLSyncKHR ret;
+
+   _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
+
+   sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list);
+   ret = (sync) ? _eglLinkSync(sync, disp) : EGL_NO_SYNC_KHR;
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+
+EGLBoolean EGLAPIENTRY
+eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSync *s = _eglLookupSync(sync, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
+   _eglUnlinkSync(s);
+   ret = drv->API.DestroySyncKHR(drv, disp, s);
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+
+EGLint EGLAPIENTRY
+eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSync *s = _eglLookupSync(sync, disp);
+   _EGLDriver *drv;
+   EGLint ret;
+
+   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
+   ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout);
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+
+EGLBoolean EGLAPIENTRY
+eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSync *s = _eglLookupSync(sync, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
+   ret = drv->API.SignalSyncKHR(drv, disp, s, mode);
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+
+EGLBoolean EGLAPIENTRY
+eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSync *s = _eglLookupSync(sync, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
+   ret = drv->API.GetSyncAttribKHR(drv, disp, s, attribute, value);
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+
+#endif /* EGL_KHR_reusable_sync */
+
+
 #ifdef EGL_NOK_swap_region
 
 EGLBoolean EGLAPIENTRY
index d8c8b49a49deef0be9cd7be2531700dd32d17fe0..5045a9a272f6bb0ed60df5b9663277fce546e38e 100644 (file)
@@ -76,6 +76,16 @@ typedef _EGLImage *(*CreateImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLCo
 typedef EGLBoolean (*DestroyImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image);
 #endif /* EGL_KHR_image_base */
 
+
+#ifdef EGL_KHR_reusable_sync
+typedef _EGLSync *(*CreateSyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLenum type, const EGLint *attrib_list);
+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 EGLBoolean (*SignalSyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, EGLenum mode);
+typedef EGLBoolean (*GetSyncAttribKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, EGLint attribute, EGLint *value);
+#endif /* EGL_KHR_reusable_sync */
+
+
 #ifdef EGL_NOK_swap_region
 typedef EGLBoolean (*SwapBuffersRegionNOK_t)(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, EGLint numRects, const EGLint *rects);
 #endif
@@ -138,6 +148,14 @@ struct _egl_api
    DestroyImageKHR_t DestroyImageKHR;
 #endif /* EGL_KHR_image_base */
 
+#ifdef EGL_KHR_reusable_sync
+   CreateSyncKHR_t CreateSyncKHR;
+   DestroySyncKHR_t DestroySyncKHR;
+   ClientWaitSyncKHR_t ClientWaitSyncKHR;
+   SignalSyncKHR_t SignalSyncKHR;
+   GetSyncAttribKHR_t GetSyncAttribKHR;
+#endif /* EGL_KHR_reusable_sync */
+
 #ifdef EGL_NOK_swap_region
    SwapBuffersRegionNOK_t SwapBuffersRegionNOK;
 #endif
index a2cee08bf6f76d07b1702b9abf0e84ab17e59b45..a5c14530676d5a5dc86b07b5ed51b1a84b57cddb 100644 (file)
@@ -24,6 +24,7 @@ enum _egl_resource_type {
    _EGL_RESOURCE_CONTEXT,
    _EGL_RESOURCE_SURFACE,
    _EGL_RESOURCE_IMAGE,
+   _EGL_RESOURCE_SYNC,
 
    _EGL_NUM_RESOURCES
 };
@@ -53,6 +54,7 @@ struct _egl_extensions
    EGLBoolean MESA_screen_surface;
    EGLBoolean MESA_copy_context;
    EGLBoolean MESA_drm_display;
+
    EGLBoolean KHR_image_base;
    EGLBoolean KHR_image_pixmap;
    EGLBoolean KHR_vg_parent_image;
@@ -60,9 +62,13 @@ struct _egl_extensions
    EGLBoolean KHR_gl_texture_cubemap_image;
    EGLBoolean KHR_gl_texture_3D_image;
    EGLBoolean KHR_gl_renderbuffer_image;
+
+   EGLBoolean KHR_reusable_sync;
+
    EGLBoolean KHR_surfaceless_gles1;
    EGLBoolean KHR_surfaceless_gles2;
    EGLBoolean KHR_surfaceless_opengl;
+
    EGLBoolean NOK_swap_region;
    EGLBoolean NOK_texture_from_pixmap;
 
index 8fc9e792b061f533c0591967c2689103f7515e56..67f1d3dbaa4d3041559be59b4fc7b8756c60168d 100644 (file)
@@ -21,6 +21,7 @@
 #include "eglstring.h"
 #include "eglsurface.h"
 #include "eglimage.h"
+#include "eglsync.h"
 #include "eglmutex.h"
 
 #if defined(_EGL_OS_UNIX)
@@ -722,6 +723,14 @@ _eglInitDriverFallbacks(_EGLDriver *drv)
    drv->API.CreateImageKHR = _eglCreateImageKHR;
    drv->API.DestroyImageKHR = _eglDestroyImageKHR;
 #endif /* EGL_KHR_image_base */
+
+#ifdef EGL_KHR_reusable_sync
+   drv->API.CreateSyncKHR = _eglCreateSyncKHR;
+   drv->API.DestroySyncKHR = _eglDestroySyncKHR;
+   drv->API.ClientWaitSyncKHR = _eglClientWaitSyncKHR;
+   drv->API.SignalSyncKHR = _eglSignalSyncKHR;
+   drv->API.GetSyncAttribKHR = _eglGetSyncAttribKHR;
+#endif /* EGL_KHR_reusable_sync */
 }
 
 
index 985d1e0069d723f6d3571de77c930e34bbfb3427..2ef6ba59e3473209cd1feeb2c1f3bcd8284cd4cb 100644 (file)
@@ -97,6 +97,8 @@ _eglUpdateExtensionsString(_EGLDisplay *dpy)
    _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image);
    _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image);
 
+   _EGL_CHECK_EXTENSION(KHR_reusable_sync);
+
    _EGL_CHECK_EXTENSION(KHR_surfaceless_gles1);
    _EGL_CHECK_EXTENSION(KHR_surfaceless_gles2);
    _EGL_CHECK_EXTENSION(KHR_surfaceless_opengl);
diff --git a/src/egl/main/eglsync.c b/src/egl/main/eglsync.c
new file mode 100644 (file)
index 0000000..3f51e89
--- /dev/null
@@ -0,0 +1,121 @@
+#include <string.h>
+
+#include "eglsync.h"
+#include "eglcurrent.h"
+#include "egllog.h"
+
+
+#ifdef EGL_KHR_reusable_sync
+
+
+/**
+ * Parse the list of sync attributes and return the proper error code.
+ */
+static EGLint
+_eglParseSyncAttribList(_EGLSync *sync, const EGLint *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) {
+      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)
+{
+   EGLint err;
+
+   if (!(type == EGL_SYNC_REUSABLE_KHR && dpy->Extensions.KHR_reusable_sync))
+      return _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
+
+   memset(sync, 0, sizeof(*sync));
+
+   sync->Resource.Display = dpy;
+
+   sync->Type = type;
+   sync->SyncStatus = EGL_UNSIGNALED_KHR;
+
+   err = _eglParseSyncAttribList(sync, attrib_list);
+   if (err != EGL_SUCCESS)
+      return _eglError(err, "eglCreateSyncKHR");
+
+   return EGL_TRUE;
+}
+
+
+_EGLSync *
+_eglCreateSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy,
+                  EGLenum type, const EGLint *attrib_list)
+{
+   return NULL;
+}
+
+
+EGLBoolean
+_eglDestroySyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync)
+{
+   return EGL_TRUE;
+}
+
+
+EGLint
+_eglClientWaitSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
+                      EGLint flags, EGLTimeKHR timeout)
+{
+   return EGL_FALSE;
+}
+
+
+EGLBoolean
+_eglSignalSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
+                  EGLenum mode)
+{
+   return EGL_FALSE;
+}
+
+
+EGLBoolean
+_eglGetSyncAttribKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
+                     EGLint attribute, EGLint *value)
+{
+   if (!value)
+      return _eglError(EGL_BAD_PARAMETER, "eglGetConfigs");
+
+   switch (attribute) {
+   case EGL_SYNC_TYPE_KHR:
+      *value = sync->Type;
+      break;
+   case EGL_SYNC_STATUS_KHR:
+      *value = sync->SyncStatus;
+      break;
+   default:
+      return _eglError(EGL_BAD_ATTRIBUTE, "eglGetSyncAttribKHR");
+      break;
+   }
+
+   return EGL_TRUE;
+}
+
+
+#endif /* EGL_KHR_reusable_sync */
diff --git a/src/egl/main/eglsync.h b/src/egl/main/eglsync.h
new file mode 100644 (file)
index 0000000..a013478
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef EGLSYNC_INCLUDED
+#define EGLSYNC_INCLUDED
+
+
+#include "egltypedefs.h"
+#include "egldisplay.h"
+
+
+#ifdef EGL_KHR_reusable_sync
+
+
+/**
+ * "Base" class for device driver syncs.
+ */
+struct _egl_sync
+{
+   /* A sync is a display resource */
+   _EGLResource Resource;
+
+   EGLenum Type;
+   EGLenum SyncStatus;
+};
+
+
+PUBLIC EGLBoolean
+_eglInitSync(_EGLSync *sync, _EGLDisplay *dpy, EGLenum type,
+             const EGLint *attrib_list);
+
+
+extern _EGLSync *
+_eglCreateSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy,
+                  EGLenum type, const EGLint *attrib_list);
+
+
+extern EGLBoolean
+_eglDestroySyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync);
+
+
+extern EGLint
+_eglClientWaitSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
+                      EGLint flags, EGLTimeKHR timeout);
+
+
+extern EGLBoolean
+_eglSignalSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
+                  EGLenum mode);
+
+
+extern EGLBoolean
+_eglGetSyncAttribKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
+                     EGLint attribute, EGLint *value);
+
+
+/**
+ * Link a sync to a display and return the handle of the link.
+ * The handle can be passed to client directly.
+ */
+static INLINE EGLSyncKHR
+_eglLinkSync(_EGLSync *sync, _EGLDisplay *dpy)
+{
+   _eglLinkResource(&sync->Resource, _EGL_RESOURCE_SYNC, dpy);
+   return (EGLSyncKHR) sync;
+}
+
+
+/**
+ * Unlink a linked sync from its display.
+ */
+static INLINE void
+_eglUnlinkSync(_EGLSync *sync)
+{
+   _eglUnlinkResource(&sync->Resource, _EGL_RESOURCE_SYNC);
+}
+
+
+/**
+ * Lookup a handle to find the linked sync.
+ * Return NULL if the handle has no corresponding linked sync.
+ */
+static INLINE _EGLSync *
+_eglLookupSync(EGLSyncKHR handle, _EGLDisplay *dpy)
+{
+   _EGLSync *sync = (_EGLSync *) handle;
+   if (!dpy || !_eglCheckResource((void *) sync, _EGL_RESOURCE_SYNC, dpy))
+      sync = NULL;
+   return sync;
+}
+
+
+/**
+ * Return the handle of a linked sync, or EGL_NO_SYNC_KHR.
+ */
+static INLINE EGLSyncKHR
+_eglGetSyncHandle(_EGLSync *sync)
+{
+   _EGLResource *res = (_EGLResource *) sync;
+   return (res && _eglIsResourceLinked(res)) ?
+      (EGLSyncKHR) sync : EGL_NO_SYNC_KHR;
+}
+
+
+/**
+ * Return true if the sync is linked to a display.
+ *
+ * The link is considered a reference to the sync (the display is owning the
+ * sync).  Drivers should not destroy a sync when it is linked.
+ */
+static INLINE EGLBoolean
+_eglIsSyncLinked(_EGLSync *sync)
+{
+   _EGLResource *res = (_EGLResource *) sync;
+   return (res && _eglIsResourceLinked(res));
+}
+
+
+#endif /* EGL_KHR_reusable_sync */
+
+
+#endif /* EGLSYNC_INCLUDED */
index 0e29e9aa47e9148a152a17228112cb99446d64ad..b65f3b72ae558205fb29b118ddecf9857393f13f 100644 (file)
@@ -32,6 +32,8 @@ typedef struct _egl_screen _EGLScreen;
 
 typedef struct _egl_surface _EGLSurface;
 
+typedef struct _egl_sync _EGLSync;
+
 typedef struct _egl_thread_info _EGLThreadInfo;
 
 #endif /* EGLTYPEDEFS_INCLUDED */