summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d.c1
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d.h3
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_sync.c67
3 files changed, 71 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c
index 10e2170729b..02b9f6aec4f 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d.c
@@ -531,6 +531,7 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
dpy->Extensions.KHR_reusable_sync = EGL_TRUE;
+ dpy->Extensions.KHR_fence_sync = EGL_TRUE;
if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
_eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h
index dabcf841e2a..be450bbede3 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d.h
+++ b/src/gallium/state_trackers/egl/common/egl_g3d.h
@@ -111,6 +111,9 @@ struct egl_g3d_sync {
/* the mutex protects only the condvar, not the struct */
pipe_mutex mutex;
pipe_condvar condvar;
+
+ /* for fence sync */
+ struct pipe_fence_handle *fence;
};
_EGL_DRIVER_TYPECAST(egl_g3d_sync, _EGLSync, obj)
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_sync.c b/src/gallium/state_trackers/egl/common/egl_g3d_sync.c
index 3351973d83f..ec74e9eb94c 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_sync.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_sync.c
@@ -71,6 +71,60 @@ egl_g3d_signal_sync_condvar(struct egl_g3d_sync *gsync)
pipe_mutex_unlock(gsync->mutex);
}
+/**
+ * Insert a fence command to the command stream of the current context.
+ */
+static EGLint
+egl_g3d_insert_fence_sync(struct egl_g3d_sync *gsync)
+{
+ _EGLContext *ctx = _eglGetCurrentContext();
+ struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+
+ /* already checked in egl_g3d_create_sync */
+ assert(gctx);
+
+ /* insert the fence command */
+ gctx->stctxi->flush(gctx->stctxi, 0x0, &gsync->fence);
+ if (!gsync->fence)
+ gsync->base.SyncStatus = EGL_SIGNALED_KHR;
+
+ return EGL_SUCCESS;
+}
+
+/**
+ * Wait for the fence sync to be signaled.
+ */
+static EGLint
+egl_g3d_wait_fence_sync(struct egl_g3d_sync *gsync, EGLTimeKHR timeout)
+{
+ EGLint ret;
+
+ if (gsync->fence) {
+ _EGLDisplay *dpy = gsync->base.Resource.Display;
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ struct pipe_screen *screen = gdpy->native->screen;
+ struct pipe_fence_handle *fence = gsync->fence;
+
+ gsync->fence = NULL;
+
+ _eglUnlockMutex(&dpy->Mutex);
+ /* no timed finish? */
+ screen->fence_finish(screen, fence, 0x0);
+ ret = EGL_CONDITION_SATISFIED_KHR;
+ _eglLockMutex(&dpy->Mutex);
+
+ gsync->base.SyncStatus = EGL_SIGNALED_KHR;
+
+ screen->fence_reference(screen, &fence, NULL);
+ egl_g3d_signal_sync_condvar(gsync);
+ }
+ else {
+ ret = egl_g3d_wait_sync_condvar(gsync, timeout);
+ }
+
+ return ret;
+}
+
static INLINE void
egl_g3d_ref_sync(struct egl_g3d_sync *gsync)
{
@@ -84,6 +138,14 @@ egl_g3d_unref_sync(struct egl_g3d_sync *gsync)
pipe_condvar_destroy(gsync->condvar);
pipe_mutex_destroy(gsync->mutex);
+ if (gsync->fence) {
+ struct egl_g3d_display *gdpy =
+ egl_g3d_display(gsync->base.Resource.Display);
+ struct pipe_screen *screen = gdpy->native->screen;
+
+ screen->fence_reference(screen, &gsync->fence, NULL);
+ }
+
FREE(gsync);
}
}
@@ -116,6 +178,9 @@ egl_g3d_create_sync(_EGLDriver *drv, _EGLDisplay *dpy,
case EGL_SYNC_REUSABLE_KHR:
err = EGL_SUCCESS;
break;
+ case EGL_SYNC_FENCE_KHR:
+ err = egl_g3d_insert_fence_sync(gsync);
+ break;
default:
err = EGL_BAD_ATTRIBUTE;
break;
@@ -181,6 +246,8 @@ egl_g3d_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
case EGL_SYNC_REUSABLE_KHR:
ret = egl_g3d_wait_sync_condvar(gsync, timeout);
break;
+ case EGL_SYNC_FENCE_KHR:
+ ret = egl_g3d_wait_fence_sync(gsync, timeout);
default:
break;
}