--- /dev/null
+#include "e.h"
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+typedef struct _E_Egl_Sync_Mgr E_Egl_Sync_Mgr;
+
+struct _E_Egl_Sync_Mgr
+{
+ EGLDisplay egl_display;
+
+ PFNEGLCREATESYNCKHRPROC create_sync;
+ PFNEGLDESTROYSYNCKHRPROC destroy_sync;
+ PFNEGLDUPNATIVEFENCEFDTIZENPROC dup_native_fence_fd;
+ PFNEGLWAITSYNCKHRPROC wait_sync;
+};
+
+struct _E_Egl_Sync
+{
+ EGLSyncKHR sync;
+};
+
+static E_Egl_Sync_Mgr *_egl_sync_mgr = NULL;
+static Eina_Bool _egl_sync_enabled = EINA_FALSE;
+
+static Eina_Bool
+_e_egl_sync_extension_check(const char *extensions, const char *extension)
+{
+ size_t extlen = strlen(extension);
+ const char *end = extensions + strlen(extensions);
+
+ while (extensions < end)
+ {
+ size_t n = 0;
+
+ /* Skip whitespaces, if any */
+ if (*extensions == ' ')
+ {
+ extensions++;
+ continue;
+ }
+
+ n = strcspn(extensions, " ");
+
+ /* Compare strings */
+ if (n == extlen && strncmp(extension, extensions, n) == 0)
+ return EINA_TRUE;
+
+ extensions += n;
+ }
+
+ return EINA_FALSE;
+}
+
+EINTERN E_Egl_Sync *
+e_egl_sync_fence_create(void)
+{
+ E_Egl_Sync_Mgr *egl_sync_mgr;
+ E_Egl_Sync *egl_sync = NULL;
+ EGLint attribs[] = { EGL_NONE };
+ EGLSyncKHR sync = EGL_NO_SYNC_KHR;
+
+ egl_sync_mgr = _egl_sync_mgr;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(egl_sync_mgr, NULL);
+
+ sync = egl_sync_mgr->create_sync(egl_sync_mgr->egl_display,
+ EGL_SYNC_NATIVE_FENCE_TIZEN,
+ attribs);
+ if (sync == EGL_NO_SYNC_KHR)
+ {
+ ERR("Failed to create EGLSyncKHR object");
+ goto fail;
+ }
+
+ egl_sync = E_NEW(E_Egl_Sync, 1);
+ EINA_SAFETY_ON_NULL_GOTO(egl_sync, fail);
+
+ egl_sync->sync = sync;
+
+ return egl_sync;
+
+fail:
+ if (sync != EGL_NO_SYNC_KHR)
+ egl_sync_mgr->destroy_sync(egl_sync_mgr->egl_display, sync);
+
+ return NULL;
+}
+
+EINTERN E_Egl_Sync *
+e_egl_sync_fence_create_with_fd(int fd)
+{
+ E_Egl_Sync_Mgr *egl_sync_mgr;
+ E_Egl_Sync *egl_sync = NULL;
+ EGLint attribs[] = { EGL_SYNC_NATIVE_FENCE_FD_TIZEN, -1, EGL_NONE };
+ EGLSyncKHR sync = EGL_NO_SYNC_KHR;
+
+ egl_sync_mgr = _egl_sync_mgr;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(egl_sync_mgr, NULL);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(fd < 0, NULL);
+
+ attribs[1] = dup(fd);
+ if (attribs[1] < -1)
+ {
+ ERR("Failed to dup fd");
+ goto fail;
+ }
+
+ sync = egl_sync_mgr->create_sync(egl_sync_mgr->egl_display,
+ EGL_SYNC_NATIVE_FENCE_TIZEN,
+ attribs);
+ if (sync == EGL_NO_SYNC_KHR)
+ {
+ ERR("Failed to create EGLSyncKHR object");
+ goto fail;
+ }
+
+ egl_sync = E_NEW(E_Egl_Sync, 1);
+ EINA_SAFETY_ON_NULL_GOTO(egl_sync, fail);
+
+ egl_sync->sync = sync;
+
+ return egl_sync;
+
+fail:
+ if (attribs[1] >= 0)
+ close(attribs[1]);
+
+ if (sync != EGL_NO_SYNC_KHR)
+ egl_sync_mgr->destroy_sync(egl_sync_mgr->egl_display, sync);
+
+ return NULL;
+}
+
+EINTERN void
+e_egl_sync_destroy(E_Egl_Sync *egl_sync)
+{
+ E_Egl_Sync_Mgr *egl_sync_mgr;
+
+ egl_sync_mgr = _egl_sync_mgr;
+ EINA_SAFETY_ON_NULL_RETURN(egl_sync_mgr);
+
+ if (!egl_sync) return;
+
+ egl_sync_mgr->destroy_sync(egl_sync_mgr->egl_display, egl_sync->sync);
+
+ E_FREE(egl_sync);
+}
+
+EINTERN Eina_Bool
+e_egl_sync_wait(E_Egl_Sync *egl_sync)
+{
+ E_Egl_Sync_Mgr *egl_sync_mgr;
+ EGLint wait_ret;
+
+ egl_sync_mgr = _egl_sync_mgr;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(egl_sync_mgr, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(egl_sync, EINA_FALSE);
+
+ wait_ret = egl_sync_mgr->wait_sync(egl_sync_mgr->egl_display, egl_sync->sync, 0);
+ if (wait_ret == EGL_FALSE)
+ {
+ ERR("Failed to wait on EGLSyncKHR object");
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+EINTERN int
+e_egl_sync_fence_fd_dup(E_Egl_Sync *egl_sync)
+{
+ E_Egl_Sync_Mgr *egl_sync_mgr;
+ int fence_fd = -1;
+
+ egl_sync_mgr = _egl_sync_mgr;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(egl_sync_mgr, -1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(egl_sync, -1);
+
+ fence_fd = egl_sync_mgr->dup_native_fence_fd(egl_sync_mgr->egl_display, egl_sync->sync);
+ if (fence_fd == EGL_NO_NATIVE_FENCE_FD_TIZEN)
+ {
+ ERR("Failed to dup fence_fd");
+ return -1;
+ }
+
+ return fence_fd;
+}
+
+EINTERN Eina_Bool
+e_egl_sync_init(void)
+{
+ E_Egl_Sync_Mgr *egl_sync_mgr = NULL;
+ const char *extensions = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl->wl.disp, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp->e_comp_screen, EINA_FALSE);
+
+ if (_egl_sync_mgr) return EINA_TRUE;
+ if (!e_comp_gl_get()) return EINA_TRUE;
+
+ egl_sync_mgr = E_NEW(E_Egl_Sync_Mgr, 1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(egl_sync_mgr, EINA_FALSE);
+
+ egl_sync_mgr->egl_display = eglGetCurrentDisplay();
+ EINA_SAFETY_ON_NULL_GOTO(egl_sync_mgr->egl_display, fail);
+
+ extensions = (const char *)eglQueryString(egl_sync_mgr->egl_display, EGL_EXTENSIONS);
+ if (!extensions)
+ {
+ ERR("Failed to query eglExtensions");
+ goto fail;
+ }
+
+ if (!_e_egl_sync_extension_check(extensions, "EGL_KHR_fence_sync"))
+ {
+ INF("Not support EGL_KHR_fence_sync extension");
+ goto fail;
+ }
+
+ if (!_e_egl_sync_extension_check(extensions, "EGL_KHR_wait_sync"))
+ {
+ INF("Not support EGL_KHR_wait_sync extension");
+ goto fail;
+ }
+
+ if (!_e_egl_sync_extension_check(extensions, "EGL_TIZEN_native_fence_sync"))
+ {
+ INF("Not support EGL_TIZEN_native_fence_sync extension");
+ goto fail;
+ }
+
+ egl_sync_mgr->create_sync = (void *)eglGetProcAddress("eglCreateSyncKHR");
+ if (!egl_sync_mgr->create_sync)
+ {
+ ERR("Failed to get eglCreateSyncKHR");
+ goto fail;
+ }
+
+ egl_sync_mgr->destroy_sync = (void *)eglGetProcAddress("eglDestroySyncKHR");
+ if (!egl_sync_mgr->destroy_sync)
+ {
+ ERR("Failed to get eglDestroySyncKHR");
+ goto fail;
+ }
+
+ egl_sync_mgr->dup_native_fence_fd = (void *)eglGetProcAddress("eglDupNativeFenceFDTIZEN");
+ if (!egl_sync_mgr->dup_native_fence_fd)
+ {
+ ERR("Failed to get eglDupNativeFenceFDTIZEN");
+ goto fail;
+ }
+
+ egl_sync_mgr->wait_sync = (void *)eglGetProcAddress("eglWaitSyncKHR");
+ if (!egl_sync_mgr->wait_sync)
+ {
+ ERR("Failed to get eglWaitSyncKHR");
+ goto fail;
+ }
+
+ _egl_sync_mgr = egl_sync_mgr;
+ _egl_sync_enabled = EINA_TRUE;
+
+ return EINA_TRUE;
+
+fail:
+ E_FREE(egl_sync_mgr);
+
+ return EINA_FALSE;
+}
+
+EINTERN void
+e_egl_sync_deinit(void)
+{
+ E_Egl_Sync_Mgr *egl_sync_mgr;
+
+ egl_sync_mgr = _egl_sync_mgr;
+ if (!egl_sync_mgr) return;
+
+ E_FREE(egl_sync_mgr);
+
+ _egl_sync_mgr = NULL;
+}
+
+EINTERN Eina_Bool
+e_egl_sync_enabled_get(void)
+{
+ return _egl_sync_enabled;
+}