st/egl: Add support for EGL_KHR_fence_sync.
authorChia-I Wu <olv@lunarg.com>
Sun, 15 Aug 2010 09:24:14 +0000 (17:24 +0800)
committerChia-I Wu <olv@lunarg.com>
Mon, 16 Aug 2010 16:06:19 +0000 (00:06 +0800)
The extension is implemented by pipe_fence_handle.

src/gallium/state_trackers/egl/common/egl_g3d.c
src/gallium/state_trackers/egl/common/egl_g3d.h
src/gallium/state_trackers/egl/common/egl_g3d_sync.c

index 10e2170729bfbd67b153b4e44e49117c317d438b..02b9f6aec4f6bbbafe99d8ec66a43249cbab454b 100644 (file)
@@ -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)");
index dabcf841e2a364971b27c76d6d41cb033647ec7e..be450bbede35a700b585d955b9bc890e3d0837d2 100644 (file)
@@ -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)
 
index 3351973d83f9eb4f2aeb50b68b0cb88db39ee078..ec74e9eb94c85878709f7a8a9d165dc6ab6db714 100644 (file)
@@ -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;
          }