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 <neil@linux.intel.com>

(cherry picked from commit 81c1ce0ffce4e75e08622e20848405987e00b3cc)
This commit is contained in:
Robert Bragg 2013-05-14 02:51:55 +01:00
parent c08fe74cd0
commit 7b14b5e3da
5 changed files with 90 additions and 23 deletions

View File

@ -32,17 +32,29 @@
void void
_cogl_poll_renderer_remove_fd (CoglRenderer *renderer, int fd); _cogl_poll_renderer_remove_fd (CoglRenderer *renderer, int fd);
typedef CoglBool (*CoglPollCheckCallback) (void *user_data); typedef int64_t (*CoglPollPrepareCallback) (void *user_data);
typedef void (*CoglPollDispatchCallback) (void *user_data); typedef void (*CoglPollDispatchCallback) (void *user_data, int revents);
void void
_cogl_poll_renderer_add_fd (CoglRenderer *renderer, _cogl_poll_renderer_add_fd (CoglRenderer *renderer,
int fd, int fd,
CoglPollFDEvent events, CoglPollFDEvent events,
CoglPollCheckCallback check, CoglPollPrepareCallback prepare,
CoglPollDispatchCallback dispatch, CoglPollDispatchCallback dispatch,
void *user_data); 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); typedef void (*CoglIdleCallback) (void *user_data);
CoglClosure * CoglClosure *

View File

@ -31,15 +31,14 @@
#include "cogl-poll-private.h" #include "cogl-poll-private.h"
#include "cogl-winsys-private.h" #include "cogl-winsys-private.h"
#include "cogl-renderer-private.h" #include "cogl-renderer-private.h"
#include "cogl-context-private.h"
typedef struct _CoglPollSource struct _CoglPollSource
{ {
int fd; int fd;
CoglPollCheckCallback check; CoglPollPrepareCallback prepare;
CoglPollDispatchCallback dispatch; CoglPollDispatchCallback dispatch;
void *user_data; void *user_data;
} CoglPollSource; };
int int
cogl_poll_renderer_get_info (CoglRenderer *renderer, 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; *poll_fds = (void *)renderer->poll_fds->data;
*n_poll_fds = renderer->poll_fds->len; *n_poll_fds = renderer->poll_fds->len;
*timeout = -1;
if (!COGL_LIST_EMPTY (&renderer->idle_closures)) 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) for (l = renderer->poll_sources; l; l = l->next)
{ {
CoglPollSource *source = l->data; CoglPollSource *source = l->data;
if (source->check && source->check (source->user_data)) if (source->prepare)
{
int64_t source_timeout = source->prepare (source->user_data);
if (source_timeout == 0)
{ {
*timeout = 0; *timeout = 0;
return renderer->poll_fds_age; 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; return renderer->poll_fds_age;
} }
@ -93,13 +99,19 @@ cogl_poll_renderer_dispatch (CoglRenderer *renderer,
CoglPollSource *source = l->data; CoglPollSource *source = l->data;
int i; int i;
if (source->fd == -1)
{
source->dispatch (source->user_data, 0);
continue;
}
for (i = 0; i < n_poll_fds; i++) for (i = 0; i < n_poll_fds; i++)
{ {
const CoglPollFD *pollfd = &poll_fds[i]; const CoglPollFD *pollfd = &poll_fds[i];
if (pollfd->fd == source->fd) if (pollfd->fd == source->fd)
{ {
source->dispatch (source->user_data); source->dispatch (source->user_data, pollfd->revents);
break; break;
} }
} }
@ -151,7 +163,7 @@ void
_cogl_poll_renderer_add_fd (CoglRenderer *renderer, _cogl_poll_renderer_add_fd (CoglRenderer *renderer,
int fd, int fd,
CoglPollFDEvent events, CoglPollFDEvent events,
CoglPollCheckCallback check, CoglPollPrepareCallback prepare,
CoglPollDispatchCallback dispatch, CoglPollDispatchCallback dispatch,
void *user_data) void *user_data)
{ {
@ -165,7 +177,7 @@ _cogl_poll_renderer_add_fd (CoglRenderer *renderer,
source = g_slice_new0 (CoglPollSource); source = g_slice_new0 (CoglPollSource);
source->fd = fd; source->fd = fd;
source->check = check; source->prepare = prepare;
source->dispatch = dispatch; source->dispatch = dispatch;
source->user_data = user_data; source->user_data = user_data;
@ -175,6 +187,43 @@ _cogl_poll_renderer_add_fd (CoglRenderer *renderer,
renderer->poll_fds_age++; 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 * CoglClosure *
_cogl_poll_renderer_add_idle (CoglRenderer *renderer, _cogl_poll_renderer_add_idle (CoglRenderer *renderer,
CoglIdleCallback idle_cb, CoglIdleCallback idle_cb,

View File

@ -468,17 +468,17 @@ randr_filter (XEvent *event,
return COGL_FILTER_CONTINUE; return COGL_FILTER_CONTINUE;
} }
static CoglBool static int64_t
check_xlib_events (void *user_data) prepare_xlib_events_timeout (void *user_data)
{ {
CoglRenderer *renderer = user_data; CoglRenderer *renderer = user_data;
CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer); 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 static void
dispatch_xlib_events (void *user_data) dispatch_xlib_events (void *user_data, int revents)
{ {
CoglRenderer *renderer = user_data; CoglRenderer *renderer = user_data;
CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer); 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, _cogl_poll_renderer_add_fd (renderer,
ConnectionNumber (xlib_renderer->xdpy), ConnectionNumber (xlib_renderer->xdpy),
COGL_POLL_FD_EVENT_IN, COGL_POLL_FD_EVENT_IN,
check_xlib_events, prepare_xlib_events_timeout,
dispatch_xlib_events, dispatch_xlib_events,
renderer); renderer);
} }

View File

@ -242,12 +242,15 @@ handle_drm_event (CoglRendererKMS *kms_renderer)
} }
static void static void
dispatch_kms_events (void *user_data) dispatch_kms_events (void *user_data, int revents)
{ {
CoglRenderer *renderer = user_data; CoglRenderer *renderer = user_data;
CoglRendererEGL *egl_renderer = renderer->winsys; CoglRendererEGL *egl_renderer = renderer->winsys;
CoglRendererKMS *kms_renderer = egl_renderer->platform; CoglRendererKMS *kms_renderer = egl_renderer->platform;
if (!revents)
return;
handle_drm_event (kms_renderer); handle_drm_event (kms_renderer);
} }
@ -299,7 +302,7 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
_cogl_poll_renderer_add_fd (renderer, _cogl_poll_renderer_add_fd (renderer,
kms_renderer->fd, kms_renderer->fd,
COGL_POLL_FD_EVENT_IN, COGL_POLL_FD_EVENT_IN,
NULL, /* no check callback */ NULL, /* no prepare callback */
dispatch_kms_events, dispatch_kms_events,
renderer); renderer);

View File

@ -110,12 +110,15 @@ static const struct wl_registry_listener registry_listener = {
}; };
static void static void
dispatch_wayland_display_events (void *user_data) dispatch_wayland_display_events (void *user_data, int revents)
{ {
CoglRenderer *renderer = user_data; CoglRenderer *renderer = user_data;
CoglRendererEGL *egl_renderer = renderer->winsys; CoglRendererEGL *egl_renderer = renderer->winsys;
CoglRendererWayland *wayland_renderer = egl_renderer->platform; CoglRendererWayland *wayland_renderer = egl_renderer->platform;
if (!revents)
return;
wl_display_dispatch (wayland_renderer->wayland_display); wl_display_dispatch (wayland_renderer->wayland_display);
} }
@ -191,7 +194,7 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
_cogl_poll_renderer_add_fd (renderer, _cogl_poll_renderer_add_fd (renderer,
wayland_renderer->fd, wayland_renderer->fd,
COGL_POLL_FD_EVENT_IN, COGL_POLL_FD_EVENT_IN,
NULL, /* no check callback */ NULL, /* no prepare callback */
dispatch_wayland_display_events, dispatch_wayland_display_events,
renderer); renderer);