[Mesa-dev,10/10] st/dri: implement the fence interface for CL events

Submitted by Marek Olšák on April 14, 2015, 10:19 p.m.

Details

Message ID 1429049995-21768-11-git-send-email-maraeo@gmail.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Marek Olšák April 14, 2015, 10:19 p.m.
From: Marek Olšák <marek.olsak@amd.com>

---
 src/gallium/state_trackers/dri/dri2.c       | 71 ++++++++++++++++++++++++++++-
 src/gallium/state_trackers/dri/dri_screen.c |  1 +
 src/gallium/state_trackers/dri/dri_screen.h |  9 ++++
 3 files changed, 80 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/src/gallium/state_trackers/dri/dri2.c b/src/gallium/state_trackers/dri/dri2.c
index 9b56313..2953de9 100644
--- a/src/gallium/state_trackers/dri/dri2.c
+++ b/src/gallium/state_trackers/dri/dri2.c
@@ -29,6 +29,7 @@ 
  */
 
 #include <xf86drm.h>
+#include <dlfcn.h>
 #include "util/u_memory.h"
 #include "util/u_inlines.h"
 #include "util/u_format.h"
@@ -1252,8 +1253,48 @@  static __DRIimageExtension dri2ImageExtension = {
 };
 
 
+static bool
+dri2_is_opencl_interop_loaded_locked(struct dri_screen *screen)
+{
+   return screen->opencl_dri_event_add_ref &&
+          screen->opencl_dri_event_release &&
+          screen->opencl_dri_event_wait &&
+          screen->opencl_dri_event_get_fence;
+}
+
+static bool
+dri2_load_opencl_interop(struct dri_screen *screen)
+{
+#if defined(RTLD_DEFAULT)
+   bool success;
+
+   pipe_mutex_lock(screen->opencl_func_mutex);
+
+   if (dri2_is_opencl_interop_loaded_locked(screen)) {
+      pipe_mutex_unlock(screen->opencl_func_mutex);
+      return true;
+   }
+
+   screen->opencl_dri_event_add_ref =
+      dlsym(RTLD_DEFAULT, "opencl_dri_event_add_ref");
+   screen->opencl_dri_event_release =
+      dlsym(RTLD_DEFAULT, "opencl_dri_event_release");
+   screen->opencl_dri_event_wait =
+      dlsym(RTLD_DEFAULT, "opencl_dri_event_wait");
+   screen->opencl_dri_event_get_fence =
+      dlsym(RTLD_DEFAULT, "opencl_dri_event_get_fence");
+
+   success = dri2_is_opencl_interop_loaded_locked(screen);
+   pipe_mutex_unlock(screen->opencl_func_mutex);
+   return success;
+#else
+   return false;
+#endif
+}
+
 struct dri2_fence {
    struct pipe_fence_handle *pipe_fence;
+   intptr_t cl_event;
 };
 
 static void *
@@ -1278,7 +1319,23 @@  dri2_create_fence(__DRIcontext *_ctx)
 static void *
 dri2_get_fence_from_cl_event(__DRIscreen *_screen, intptr_t cl_event)
 {
-   return NULL;
+   struct dri_screen *driscreen = dri_screen(_screen);
+   struct dri2_fence *fence;
+
+   if (!dri2_load_opencl_interop(driscreen))
+      return NULL;
+
+   fence = CALLOC_STRUCT(dri2_fence);
+   if (!fence)
+      return NULL;
+
+   if (!driscreen->opencl_dri_event_add_ref(cl_event)) {
+      free(fence);
+      return NULL;
+   }
+
+   fence->cl_event = cl_event;
+   return fence;
 }
 
 static void
@@ -1290,6 +1347,8 @@  dri2_destroy_fence(__DRIscreen *_screen, void *_fence)
 
    if (fence->pipe_fence)
       screen->fence_reference(screen, &fence->pipe_fence, NULL);
+   else if (fence->cl_event)
+      driscreen->opencl_dri_event_release(fence->cl_event);
    else
       assert(0);
 
@@ -1308,6 +1367,15 @@  dri2_client_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags,
 
    if (fence->pipe_fence)
       return screen->fence_finish(screen, fence->pipe_fence, timeout);
+   else if (fence->cl_event) {
+      struct pipe_fence_handle *pipe_fence =
+         driscreen->opencl_dri_event_get_fence(fence->cl_event);
+
+      if (pipe_fence)
+         return screen->fence_finish(screen, pipe_fence, timeout);
+      else
+         return driscreen->opencl_dri_event_wait(fence->cl_event, timeout);
+   }
    else {
       assert(0);
       return false;
@@ -1365,6 +1433,7 @@  dri2_init_screen(__DRIscreen * sPriv)
 
    screen->sPriv = sPriv;
    screen->fd = sPriv->fd;
+   pipe_mutex_init(screen->opencl_func_mutex);
 
    sPriv->driverPrivate = (void *)screen;
 
diff --git a/src/gallium/state_trackers/dri/dri_screen.c b/src/gallium/state_trackers/dri/dri_screen.c
index 1b14ab1..85393d8 100644
--- a/src/gallium/state_trackers/dri/dri_screen.c
+++ b/src/gallium/state_trackers/dri/dri_screen.c
@@ -365,6 +365,7 @@  dri_destroy_screen_helper(struct dri_screen * screen)
       screen->base.screen->destroy(screen->base.screen);
 
    dri_destroy_option_cache(screen);
+   pipe_mutex_destroy(screen->opencl_func_mutex);
 }
 
 void
diff --git a/src/gallium/state_trackers/dri/dri_screen.h b/src/gallium/state_trackers/dri/dri_screen.h
index e4a1a39..bdab74f 100644
--- a/src/gallium/state_trackers/dri/dri_screen.h
+++ b/src/gallium/state_trackers/dri/dri_screen.h
@@ -39,6 +39,8 @@ 
 #include "pipe/p_context.h"
 #include "pipe/p_state.h"
 #include "state_tracker/st_api.h"
+#include "state_tracker/opencl_interop.h"
+#include "os/os_thread.h"
 #include "postprocess/filters.h"
 
 struct dri_context;
@@ -84,6 +86,13 @@  struct dri_screen
 
    /* hooks filled in by dri2 & drisw */
    __DRIimage * (*lookup_egl_image)(struct dri_screen *ctx, void *handle);
+
+   /* OpenCL interop */
+   pipe_mutex opencl_func_mutex;
+   opencl_dri_event_add_ref_t opencl_dri_event_add_ref;
+   opencl_dri_event_release_t opencl_dri_event_release;
+   opencl_dri_event_wait_t opencl_dri_event_wait;
+   opencl_dri_event_get_fence_t opencl_dri_event_get_fence;
 };
 
 /** cast wrapper */