diff options
author | Benjamin Franzke <benjaminfranzke@googlemail.com> | 2011-04-06 20:49:57 +0200 |
---|---|---|
committer | Benjamin Franzke <benjaminfranzke@googlemail.com> | 2011-05-02 09:57:46 +0200 |
commit | cc778286d65a368cbf20062b59c35024cba9a870 (patch) | |
tree | c0dbe91f2701f77eca1f01df31959531f8f78a1b | |
parent | 516d0e5806b40a731d107886cc92b4b0c7e82f7d (diff) |
wfdevent: Initial support wfdDeviceEventAsync
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 | 70 | ||||
-rw-r--r-- | src/wfdevent.h | 6 | ||||
-rw-r--r-- | test/test.c | 16 |
5 files changed, 110 insertions, 3 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index c3fa526..91c317a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,7 +11,7 @@ noinst_HEADERS = \ wfdevent.h -libWFD_la_LIBADD = $(OWFDRM_LIBS) -lm +libWFD_la_LIBADD = $(OWFDRM_LIBS) -lm -lpthread libWFD_la_SOURCES = \ wfdapi.c \ wfhandle.c \ diff --git a/src/wfdapi.c b/src/wfdapi.c index f0a550c..79b8c74 100644 --- a/src/wfdapi.c +++ b/src/wfdapi.c @@ -313,11 +313,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 5feb903..7156d00 100644 --- a/src/wfdevent.c +++ b/src/wfdevent.c @@ -50,6 +50,11 @@ struct bind_event { struct wf_list link; }; +#define EGL_EGLEXT_PROTOTYPES +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <pthread.h> + struct wfd_event { uint32_t start_time_msec; int epoll_fd; @@ -71,6 +76,11 @@ struct wfd_event { struct wf_list bind_event_queue; WFDEventType current_event_type; + + EGLDisplay egl_display; + EGLSyncKHR egl_sync; + pthread_t thread; + int thread_destroy_fd; }; static int @@ -261,6 +271,14 @@ 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; + } + wfd_event_update(device, event, 0); close(event->epoll_fd); @@ -292,6 +310,8 @@ wfd_create_event(struct wfd_device *device, event->current_event_type = WFD_EVENT_NONE; event->filter = 0; + event->thread_destroy_fd = -1; + if (wfd_event_update(device, event, WFD_EVENT_ALL_MASK) < 0) { wfd_event_destroy(device, event); return NULL; @@ -491,3 +511,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 554e447..cb79078 100644 --- a/src/wfdevent.h +++ b/src/wfdevent.h @@ -55,4 +55,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 06d8657..11ed104 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); @@ -213,13 +214,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); |