From 7b14b5e3dadd78c86c6063ace359b119b940609f Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 14 May 2013 02:51:55 +0100 Subject: [PATCH] poll: Add general way to hook into mainloop without fd This adds a _cogl_poll_renderer_add_source() function that we can use within cogl to hook into the mainloop without necessarily having a file descriptor to poll. Since the intention is to use this to support polling for fence completions this also updates the CoglPollCheckCallback type to take a timeout pointer so sources can optionally update the timeout that will be passed to poll. Reviewed-by: Neil Roberts (cherry picked from commit 81c1ce0ffce4e75e08622e20848405987e00b3cc) --- cogl/cogl-poll-private.h | 18 +++++-- cogl/cogl-poll.c | 71 ++++++++++++++++++++++----- cogl/cogl-xlib-renderer.c | 10 ++-- cogl/winsys/cogl-winsys-egl-kms.c | 7 ++- cogl/winsys/cogl-winsys-egl-wayland.c | 7 ++- 5 files changed, 90 insertions(+), 23 deletions(-) diff --git a/cogl/cogl-poll-private.h b/cogl/cogl-poll-private.h index 93ef7520e..3dfaa2b79 100644 --- a/cogl/cogl-poll-private.h +++ b/cogl/cogl-poll-private.h @@ -32,17 +32,29 @@ void _cogl_poll_renderer_remove_fd (CoglRenderer *renderer, int fd); -typedef CoglBool (*CoglPollCheckCallback) (void *user_data); -typedef void (*CoglPollDispatchCallback) (void *user_data); +typedef int64_t (*CoglPollPrepareCallback) (void *user_data); +typedef void (*CoglPollDispatchCallback) (void *user_data, int revents); void _cogl_poll_renderer_add_fd (CoglRenderer *renderer, int fd, CoglPollFDEvent events, - CoglPollCheckCallback check, + CoglPollPrepareCallback prepare, CoglPollDispatchCallback dispatch, void *user_data); +typedef struct _CoglPollSource CoglPollSource; + +CoglPollSource * +_cogl_poll_renderer_add_source (CoglRenderer *renderer, + CoglPollPrepareCallback prepare, + CoglPollDispatchCallback dispatch, + void *user_data); + +void +_cogl_poll_renderer_remove_source (CoglRenderer *renderer, + CoglPollSource *source); + typedef void (*CoglIdleCallback) (void *user_data); CoglClosure * diff --git a/cogl/cogl-poll.c b/cogl/cogl-poll.c index 1528f2ccc..e29d9976c 100644 --- a/cogl/cogl-poll.c +++ b/cogl/cogl-poll.c @@ -31,15 +31,14 @@ #include "cogl-poll-private.h" #include "cogl-winsys-private.h" #include "cogl-renderer-private.h" -#include "cogl-context-private.h" -typedef struct _CoglPollSource +struct _CoglPollSource { int fd; - CoglPollCheckCallback check; + CoglPollPrepareCallback prepare; CoglPollDispatchCallback dispatch; void *user_data; -} CoglPollSource; +}; int cogl_poll_renderer_get_info (CoglRenderer *renderer, @@ -56,6 +55,7 @@ cogl_poll_renderer_get_info (CoglRenderer *renderer, *poll_fds = (void *)renderer->poll_fds->data; *n_poll_fds = renderer->poll_fds->len; + *timeout = -1; if (!COGL_LIST_EMPTY (&renderer->idle_closures)) { @@ -66,14 +66,20 @@ cogl_poll_renderer_get_info (CoglRenderer *renderer, for (l = renderer->poll_sources; l; l = l->next) { CoglPollSource *source = l->data; - if (source->check && source->check (source->user_data)) + if (source->prepare) { - *timeout = 0; - return renderer->poll_fds_age; + int64_t source_timeout = source->prepare (source->user_data); + if (source_timeout == 0) + { + *timeout = 0; + return renderer->poll_fds_age; + } + else if (source_timeout > 0 && + (*timeout == -1 || *timeout > source_timeout)) + *timeout = source_timeout; } } - *timeout = -1; return renderer->poll_fds_age; } @@ -93,13 +99,19 @@ cogl_poll_renderer_dispatch (CoglRenderer *renderer, CoglPollSource *source = l->data; int i; + if (source->fd == -1) + { + source->dispatch (source->user_data, 0); + continue; + } + for (i = 0; i < n_poll_fds; i++) { const CoglPollFD *pollfd = &poll_fds[i]; if (pollfd->fd == source->fd) { - source->dispatch (source->user_data); + source->dispatch (source->user_data, pollfd->revents); break; } } @@ -151,7 +163,7 @@ void _cogl_poll_renderer_add_fd (CoglRenderer *renderer, int fd, CoglPollFDEvent events, - CoglPollCheckCallback check, + CoglPollPrepareCallback prepare, CoglPollDispatchCallback dispatch, void *user_data) { @@ -165,7 +177,7 @@ _cogl_poll_renderer_add_fd (CoglRenderer *renderer, source = g_slice_new0 (CoglPollSource); source->fd = fd; - source->check = check; + source->prepare = prepare; source->dispatch = dispatch; source->user_data = user_data; @@ -175,6 +187,43 @@ _cogl_poll_renderer_add_fd (CoglRenderer *renderer, renderer->poll_fds_age++; } +CoglPollSource * +_cogl_poll_renderer_add_source (CoglRenderer *renderer, + CoglPollPrepareCallback prepare, + CoglPollDispatchCallback dispatch, + void *user_data) +{ + CoglPollSource *source; + + source = g_slice_new0 (CoglPollSource); + source->fd = -1; + source->prepare = prepare; + source->dispatch = dispatch; + source->user_data = user_data; + + renderer->poll_sources = g_list_prepend (renderer->poll_sources, source); + + return source; +} + +void +_cogl_poll_renderer_remove_source (CoglRenderer *renderer, + CoglPollSource *source) +{ + GList *l; + + for (l = renderer->poll_sources; l; l = l->next) + { + if (l->data == source) + { + renderer->poll_sources = + g_list_delete_link (renderer->poll_sources, l); + g_slice_free (CoglPollSource, source); + break; + } + } +} + CoglClosure * _cogl_poll_renderer_add_idle (CoglRenderer *renderer, CoglIdleCallback idle_cb, diff --git a/cogl/cogl-xlib-renderer.c b/cogl/cogl-xlib-renderer.c index 3aa70f20b..4d332fa8c 100644 --- a/cogl/cogl-xlib-renderer.c +++ b/cogl/cogl-xlib-renderer.c @@ -468,17 +468,17 @@ randr_filter (XEvent *event, return COGL_FILTER_CONTINUE; } -static CoglBool -check_xlib_events (void *user_data) +static int64_t +prepare_xlib_events_timeout (void *user_data) { CoglRenderer *renderer = user_data; CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer); - return XPending (xlib_renderer->xdpy) ? TRUE : FALSE; + return XPending (xlib_renderer->xdpy) ? 0 : -1; } static void -dispatch_xlib_events (void *user_data) +dispatch_xlib_events (void *user_data, int revents) { CoglRenderer *renderer = user_data; CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer); @@ -529,7 +529,7 @@ _cogl_xlib_renderer_connect (CoglRenderer *renderer, CoglError **error) _cogl_poll_renderer_add_fd (renderer, ConnectionNumber (xlib_renderer->xdpy), COGL_POLL_FD_EVENT_IN, - check_xlib_events, + prepare_xlib_events_timeout, dispatch_xlib_events, renderer); } diff --git a/cogl/winsys/cogl-winsys-egl-kms.c b/cogl/winsys/cogl-winsys-egl-kms.c index d24ef243a..0e704223c 100644 --- a/cogl/winsys/cogl-winsys-egl-kms.c +++ b/cogl/winsys/cogl-winsys-egl-kms.c @@ -242,12 +242,15 @@ handle_drm_event (CoglRendererKMS *kms_renderer) } static void -dispatch_kms_events (void *user_data) +dispatch_kms_events (void *user_data, int revents) { CoglRenderer *renderer = user_data; CoglRendererEGL *egl_renderer = renderer->winsys; CoglRendererKMS *kms_renderer = egl_renderer->platform; + if (!revents) + return; + handle_drm_event (kms_renderer); } @@ -299,7 +302,7 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer, _cogl_poll_renderer_add_fd (renderer, kms_renderer->fd, COGL_POLL_FD_EVENT_IN, - NULL, /* no check callback */ + NULL, /* no prepare callback */ dispatch_kms_events, renderer); diff --git a/cogl/winsys/cogl-winsys-egl-wayland.c b/cogl/winsys/cogl-winsys-egl-wayland.c index 4b7c8c154..28e599b42 100644 --- a/cogl/winsys/cogl-winsys-egl-wayland.c +++ b/cogl/winsys/cogl-winsys-egl-wayland.c @@ -110,12 +110,15 @@ static const struct wl_registry_listener registry_listener = { }; static void -dispatch_wayland_display_events (void *user_data) +dispatch_wayland_display_events (void *user_data, int revents) { CoglRenderer *renderer = user_data; CoglRendererEGL *egl_renderer = renderer->winsys; CoglRendererWayland *wayland_renderer = egl_renderer->platform; + if (!revents) + return; + wl_display_dispatch (wayland_renderer->wayland_display); } @@ -191,7 +194,7 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer, _cogl_poll_renderer_add_fd (renderer, wayland_renderer->fd, COGL_POLL_FD_EVENT_IN, - NULL, /* no check callback */ + NULL, /* no prepare callback */ dispatch_wayland_display_events, renderer);