summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Franzke <benjaminfranzke@googlemail.com>2011-04-06 20:49:57 +0200
committerBenjamin Franzke <benjaminfranzke@googlemail.com>2011-05-02 09:57:46 +0200
commitcc778286d65a368cbf20062b59c35024cba9a870 (patch)
treec0dbe91f2701f77eca1f01df31959531f8f78a1b
parent516d0e5806b40a731d107886cc92b4b0c7e82f7d (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.am2
-rw-r--r--src/wfdapi.c19
-rw-r--r--src/wfdevent.c70
-rw-r--r--src/wfdevent.h6
-rw-r--r--test/test.c16
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);