diff options
author | Benjamin Franzke <benjaminfranzke@googlemail.com> | 2011-04-06 20:49:57 +0200 |
---|---|---|
committer | Benjamin Franzke <benjaminfranzke@googlemail.com> | 2011-04-06 22:15:18 +0200 |
commit | 3410333a82c2a132d4d3b716e7cefe5d367f0e66 (patch) | |
tree | 8cc35e4ac0a0f7087a5471afe36eef0078f95f66 | |
parent | fec09f83ddd76ce3aeeefdda1f816e0bf306a47a (diff) |
wfdevent: Initial support wfdDeviceEventAsyncevent_async
Currently done using a seperate thread that signals
the EGLSync.
The idea is that later no threads are needed,
and we'd pass a pollable fd to a egl sync extension.
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/wfdapi.c | 19 | ||||
-rw-r--r-- | src/wfdevent.c | 69 | ||||
-rw-r--r-- | src/wfdevent.h | 6 | ||||
-rw-r--r-- | test/test.c | 16 |
5 files changed, 109 insertions, 3 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 6c89155..569f7ec 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,7 +10,7 @@ noinst_HEADERS = \ wfdevent.h -libWFD_la_LIBADD = $(OWFDRM_LIBS) +libWFD_la_LIBADD = $(OWFDRM_LIBS) -lpthread libWFD_la_SOURCES = \ wfdapi.c \ wfhandle.c \ diff --git a/src/wfdapi.c b/src/wfdapi.c index 39ccb76..c6f04b6 100644 --- a/src/wfdapi.c +++ b/src/wfdapi.c @@ -318,11 +318,26 @@ wfdDeviceEventGetFD(WFDDevice device_handle, WFD_API_CALL void WFD_APIENTRY -wfdDeviceEventAsync(WFDDevice device, - WFDEvent event, +wfdDeviceEventAsync(WFDDevice device_handle, + WFDEvent event_handle, WFDEGLDisplay dpy, WFDEGLSync sync) WFD_APIEXIT { + struct wfd_device *device; + struct wfd_event *event; + + device = wf_handle_get_object(device_handle, DEVICE_HANDLE); + if (device == NULL) + return; + wfd_device_set_error(device, WFD_ERROR_NONE); + + event = wf_handle_get_object(event_handle, EVENT_HANDLE); + if (event == NULL) { + wfd_device_set_error(device, WFD_ERROR_BAD_HANDLE); + return; + } + + wfd_event_async(device, event, dpy, sync); } WFD_API_CALL WFDEventType WFD_APIENTRY diff --git a/src/wfdevent.c b/src/wfdevent.c index e0abf27..042a38b 100644 --- a/src/wfdevent.c +++ b/src/wfdevent.c @@ -40,6 +40,11 @@ #include <glib.h> +#define EGL_EGLEXT_PROTOTYPES +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <pthread.h> + struct wfd_event { int epoll_fd; @@ -57,12 +62,25 @@ struct wfd_event { int source_bind_event_queue_fd; GQueue *bind_event_queue; + + EGLDisplay egl_display; + EGLSyncKHR egl_sync; + pthread_t thread; + int thread_destroy_fd; }; void wfd_event_destroy(struct wfd_device *device, struct wfd_event *event) { + if (event->thread_destroy_fd >= 0) { + int64_t value = 1; + write(event->thread_destroy_fd, &value, sizeof value); + pthread_join(event->thread, NULL); + close(event->thread_destroy_fd); + event->thread_destroy_fd = -1; + } + g_queue_free(event->bind_event_queue); close(event->drm_fd); udev_monitor_unref(event->udev_monitor); @@ -164,6 +182,7 @@ wfd_create_event(struct wfd_device *device, event->bind_event_queue = g_queue_new(); event->device = device; + event->thread_destroy_fd = -1; return event; } @@ -300,3 +319,53 @@ wfd_event_get_fd(struct wfd_device *device, { return event->epoll_fd; } + +static void * +signalling_thread(void *_event) +{ + struct wfd_event *event = _event; + struct epoll_event ep[16]; + int i, num; + + while (1) { + num = epoll_wait(event->epoll_fd, ep, 16, -1); + if (num < 0) + continue; + for (i = 0; i < num; ++i) { + if (ep[i].data.fd == event->thread_destroy_fd) + return NULL; + else + eglSignalSyncKHR(event->egl_display, + event->egl_sync, + EGL_SIGNALED_KHR); + } + } + + return NULL; +} + +int +wfd_event_async(struct wfd_device *device, + struct wfd_event *event, + WFDEGLDisplay *egl_display, + WFDEGLSync *egl_sync) +{ + struct epoll_event ep; + + if (event->egl_sync != NULL) + return -1; + + event->egl_display = (EGLDisplay) egl_display; + event->egl_sync = (EGLSyncKHR) egl_sync; + + event->thread_destroy_fd = eventfd(0, EFD_NONBLOCK | EFD_SEMAPHORE); + + memset(&ep, 0, sizeof ep); + ep.events = EPOLLIN; + ep.data.fd = event->thread_destroy_fd; + epoll_ctl(event->epoll_fd, EPOLL_CTL_ADD, ep.data.fd, &ep); + + pthread_create(&event->thread, NULL, signalling_thread, event); + + return 0; +} diff --git a/src/wfdevent.h b/src/wfdevent.h index abd43ea..ec4a8ab 100644 --- a/src/wfdevent.h +++ b/src/wfdevent.h @@ -50,4 +50,10 @@ int wfd_event_get_fd(struct wfd_device *device, struct wfd_event *event); +int +wfd_event_async(struct wfd_device *device, + struct wfd_event *event, + WFDEGLDisplay *egl_display, + WFDEGLSync *egl_sync); + #endif /* _WFD_EVENT_H_ */ diff --git a/test/test.c b/test/test.c index 2e8649d..c1e92d9 100644 --- a/test/test.c +++ b/test/test.c @@ -72,6 +72,7 @@ main(int argc, char *argv[]) EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, EGL_NONE }; + EGLSyncKHR esync; num = wfdEnumerateDevices(NULL, 0, NULL); printf("num: %d\n", num); @@ -208,13 +209,28 @@ main(int argc, char *argv[]) sleep(1); + esync = eglCreateSyncKHR(edpy, EGL_SYNC_REUSABLE_KHR, NULL); + wfdDeviceEventAsync(dev, event, edpy, esync); + wfdBindSourceToPipeline(dev, pipeline, source[0], WFD_TRANSITION_AT_VSYNC, NULL); /* commit entire device should work as well :) */ wfdDeviceCommit(dev, WFD_COMMIT_ENTIRE_DEVICE, WFD_INVALID_HANDLE); + EGLint status = eglClientWaitSyncKHR(edpy, esync, 0, EGL_FOREVER_KHR); + switch (status) { + case EGL_CONDITION_SATISFIED_KHR: + printf("condition satisfied\n"); + WFDEventType type = wfdDeviceEventWait(dev, event, WFD_FOREVER); + break; + default: + printf("ClientWaitSync badly returned: %d\n", status); + return 5; + } + sleep(1); + wfdDestroyEvent(dev, event); wfdDestroySource(dev, source[0]); wfdDestroySource(dev, source[1]); wfdDestroyEvent(dev, event); |