[Cogl] [PATCH v2] poll: Add general way to hook into mainloop without fd
Robert Bragg
robert at sixbynine.org
Tue May 28 08:39:10 PDT 2013
From: Robert Bragg <robert at linux.intel.com>
Based on Neil's feedback this makes the following changes compared to my last
patch:
· renamed 'check' to 'prepare'
· return timeout from the prepare function and deal with the -1 || < *timeout
checks inside cogl-poll.c
· don't handle non fd based sources in a separate loop
. pass revents to dispatch functions so they can distinguish being dispatched
due to a timeout or some potentially un-related event.
A few things I didn't change:
I didn't rename 'dispatch' to 'check_and_dispatch' since that seemed a bit
verbose and it didn't seem that bad for the check to be implicit for these
internal dispatch functions.
I didn't re-work the idle functions to work in terms of adding a PollSource. It
seems like this can be handled as a separate patch if we really want this
though I'm not really sure it's necessary. It would mean only having one
mechanism which is arguably simpler but then adding/removing an idle function
would in itself be more complex than it is currently. If we did want to re-work
the code it might also be nice to switch to using an embedded linked list for
the sources, since currently removing a source implies searching for the source
from the start of the list whereas removing an idle callback can currently just
unlink a CoglClosure directly.
kind regards,
- Robert
--- >8 ---
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.
---
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 93ef752..3dfaa2b 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 1528f2c..e29d997 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 92f044d..7d65049 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 f7c65db..2cc74a5 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 fe8b938..21bd5df 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);
--
1.8.2.1
More information about the Cogl
mailing list