summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Franzke <benjaminfranzke@googlemail.com>2011-04-06 20:49:57 +0200
committerBenjamin Franzke <benjaminfranzke@googlemail.com>2011-04-06 22:15:18 +0200
commit3410333a82c2a132d4d3b716e7cefe5d367f0e66 (patch)
tree8cc35e4ac0a0f7087a5471afe36eef0078f95f66
parentfec09f83ddd76ce3aeeefdda1f816e0bf306a47a (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.am2
-rw-r--r--src/wfdapi.c19
-rw-r--r--src/wfdevent.c69
-rw-r--r--src/wfdevent.h6
-rw-r--r--test/test.c16
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);