st/dri: implement the fence interface for CL events
authorMarek Olšák <marek.olsak@amd.com>
Fri, 10 Apr 2015 17:45:50 +0000 (19:45 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Thu, 30 Apr 2015 12:38:38 +0000 (14:38 +0200)
src/gallium/state_trackers/dri/dri2.c
src/gallium/state_trackers/dri/dri_screen.c
src/gallium/state_trackers/dri/dri_screen.h

index 9b5631326d436e2576e2c85e2b8c74e0a5ae5aa4..8b6fe67dc914c6a3d59fa56174e7fdbab5c32068 100644 (file)
@@ -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;
+   void *cl_event;
 };
 
 static void *
@@ -1278,7 +1319,24 @@ 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;
+
+   fence->cl_event = (void*)cl_event;
+
+   if (!driscreen->opencl_dri_event_add_ref(fence->cl_event)) {
+      free(fence);
+      return NULL;
+   }
+
+   return fence;
 }
 
 static void
@@ -1290,6 +1348,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 +1368,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 +1434,7 @@ dri2_init_screen(__DRIscreen * sPriv)
 
    screen->sPriv = sPriv;
    screen->fd = sPriv->fd;
+   pipe_mutex_init(screen->opencl_func_mutex);
 
    sPriv->driverPrivate = (void *)screen;
 
index 1b14ab162f14c12b8d7e6a867428d505a85b84ee..85393d867e4f2018256fc29d79aac89dbdc84b40 100644 (file)
@@ -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
index e4a1a39aa219eb68fdf083acdb025bd2839d8be9..bdab74f2802cd91897dd9c0b818f76496a280e92 100644 (file)
@@ -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 */