[Cogl] [PATCH 1/3] Move event polling into CoglRenderer

Robert Bragg robert at sixbynine.org
Sat Apr 27 17:12:39 PDT 2013


From: Robert Bragg <robert at linux.intel.com>

This updates the cogl_poll_ apis to allow dispatching events before we
have a CoglContext and to also enables pollfd state to be changed in a
more add-hoc way by different Cogl components by replacing the
winsys->get_poll_info with _cogl_poll_renderer_add/remove_fd functions
and a winsys->get_dispatch_timeout vfunc.

One of the intentions here is that applications should be able to run
their mainloop before creating a CoglContext to potentially get events
relating to CoglOutputs.
---
 cogl/Makefile.am                       |   1 +
 cogl/cogl-context.c                    |  18 +++++
 cogl/cogl-context.h                    |  19 ++++++
 cogl/cogl-glib-source.c                |  62 ++++++++---------
 cogl/cogl-glib-source.h                |  37 +++++++++-
 cogl/cogl-glx-display-private.h        |   3 -
 cogl/cogl-glx-renderer-private.h       |   7 ++
 cogl/cogl-onscreen.h                   |   8 +--
 cogl/cogl-poll-private.h               |  36 ++++++++++
 cogl/cogl-poll.c                       | 121 ++++++++++++++++++++++++---------
 cogl/cogl-poll.h                       |  68 +++++++++++-------
 cogl/cogl-renderer-private.h           |  19 ++++++
 cogl/cogl-renderer.c                   |   4 ++
 cogl/cogl-sdl.c                        |   9 ++-
 cogl/cogl-xlib-renderer-private.h      |  10 +--
 cogl/cogl-xlib-renderer.c              |  28 ++++----
 cogl/cogl.symbols                      |   4 +-
 cogl/winsys/cogl-winsys-egl-kms.c      |  73 ++++++++++----------
 cogl/winsys/cogl-winsys-egl-private.h  |   4 +-
 cogl/winsys/cogl-winsys-egl-x11.c      |  53 ++++++++-------
 cogl/winsys/cogl-winsys-glx.c          |  79 +++++++++++----------
 cogl/winsys/cogl-winsys-private.h      |  10 ++-
 cogl/winsys/cogl-winsys-sdl.c          |  26 ++++---
 cogl/winsys/cogl-winsys-sdl2.c         |  27 +++++---
 doc/reference/cogl2/cogl2-sections.txt |   7 +-
 examples/cogl-crate.c                  |   7 +-
 examples/cogl-msaa.c                   |   6 +-
 examples/cogl-x11-foreign.c            |   6 +-
 28 files changed, 484 insertions(+), 268 deletions(-)
 create mode 100644 cogl/cogl-poll-private.h

diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index 897f899..ef83799 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -382,6 +382,7 @@ cogl_sources_c = \
 	$(srcdir)/cogl-boxed-value.c			\
 	$(srcdir)/cogl-snippet-private.h		\
 	$(srcdir)/cogl-snippet.c			\
+	$(srcdir)/cogl-poll-private.h			\
 	$(srcdir)/cogl-poll.c				\
 	$(srcdir)/gl-prototypes/cogl-all-functions.h	\
 	$(srcdir)/gl-prototypes/cogl-gles1-functions.h	\
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 926cff4..392865c 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -194,6 +194,18 @@ cogl_context_new (CoglDisplay *display,
 
   context->display = display;
 
+  /* Add a back reference to the context from the renderer because
+   * event dispatching is handled by the renderer and we don't
+   * currently have a generalized way of registering idle functions
+   * and such things internally so cogl_poll_renderer_dispatch()
+   * needs to poke inside the context if one is available to check
+   * if there are pending onscreen framebuffer events.
+   *
+   * FIXME: once we have a generalized way of registering idle
+   * functions then we can remove this back-reference.
+   */
+  display->renderer->context = context;
+
   /* This is duplicated data, but it's much more convenient to have
      the driver attached to the context and the value is accessed a
      lot throughout Cogl */
@@ -523,6 +535,12 @@ cogl_context_get_display (CoglContext *context)
   return context->display;
 }
 
+CoglRenderer *
+cogl_context_get_renderer (CoglContext *context)
+{
+  return context->display->renderer;
+}
+
 #ifdef COGL_HAS_EGL_SUPPORT
 EGLDisplay
 cogl_egl_context_get_egl_display (CoglContext *context)
diff --git a/cogl/cogl-context.h b/cogl/cogl-context.h
index 0f4c590..ff2ecfd 100644
--- a/cogl/cogl-context.h
+++ b/cogl/cogl-context.h
@@ -123,6 +123,25 @@ cogl_context_new (CoglDisplay *display,
 CoglDisplay *
 cogl_context_get_display (CoglContext *context);
 
+/**
+ * cogl_context_get_renderer:
+ * @context: A #CoglContext pointer
+ *
+ * Retrieves the #CoglRenderer that is internally associated with the
+ * given @context. This will return the same #CoglRenderer that was
+ * passed to cogl_display_new() or if %NULL was passed to
+ * cogl_display_new() or cogl_context_new() then this function returns
+ * a pointer to the renderer that was automatically connected
+ * internally.
+ *
+ * Return value: (transfer none): The #CoglRenderer associated with the
+ *               given @context.
+ * Since: 1.16
+ * Stability: unstable
+ */
+CoglRenderer *
+cogl_context_get_renderer (CoglContext *context);
+
 #ifdef COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT
 /**
  * cogl_android_set_native_window:
diff --git a/cogl/cogl-glib-source.c b/cogl/cogl-glib-source.c
index adbd4d8..bb426f0 100644
--- a/cogl/cogl-glib-source.c
+++ b/cogl/cogl-glib-source.c
@@ -32,50 +32,34 @@ typedef struct _CoglGLibSource
 {
   GSource source;
 
-  CoglContext *context;
+  CoglRenderer *renderer;
 
   GArray *poll_fds;
+  int poll_fds_age;
 
   int64_t expiration_time;
 } CoglGLibSource;
 
 static CoglBool
-cogl_glib_source_poll_fds_changed (CoglGLibSource *cogl_source,
-                                   const CoglPollFD *poll_fds,
-                                   int n_poll_fds)
-{
-  int i;
-
-  if (cogl_source->poll_fds->len != n_poll_fds)
-    return TRUE;
-
-  for (i = 0; i < n_poll_fds; i++)
-    if (g_array_index (cogl_source->poll_fds, CoglPollFD, i).fd !=
-        poll_fds[i].fd)
-      return TRUE;
-
-  return FALSE;
-}
-
-static CoglBool
 cogl_glib_source_prepare (GSource *source, int *timeout)
 {
   CoglGLibSource *cogl_source = (CoglGLibSource *) source;
   CoglPollFD *poll_fds;
   int n_poll_fds;
   int64_t cogl_timeout;
+  int age;
   int i;
 
-  cogl_poll_get_info (cogl_source->context,
-                      &poll_fds,
-                      &n_poll_fds,
-                      &cogl_timeout);
+  age = cogl_poll_renderer_get_info (cogl_source->renderer,
+                                     &poll_fds,
+                                     &n_poll_fds,
+                                     &cogl_timeout);
 
   /* We have to be careful not to call g_source_add/remove_poll unless
-     the FDs have changed because it will cause the main loop to
-     immediately wake up. If we call it every time the source is
-     prepared it will effectively never go idle. */
-  if (cogl_glib_source_poll_fds_changed (cogl_source, poll_fds, n_poll_fds))
+   * the FDs have changed because it will cause the main loop to
+   * immediately wake up. If we call it every time the source is
+   * prepared it will effectively never go idle. */
+  if (age != cogl_source->poll_fds_age)
     {
       /* Remove any existing polls before adding the new ones */
       for (i = 0; i < cogl_source->poll_fds->len; i++)
@@ -94,6 +78,8 @@ cogl_glib_source_prepare (GSource *source, int *timeout)
         }
     }
 
+  cogl_source->poll_fds_age = age;
+
   /* Update the events */
   for (i = 0; i < n_poll_fds; i++)
     {
@@ -147,9 +133,9 @@ cogl_glib_source_dispatch (GSource *source,
   CoglPollFD *poll_fds =
     (CoglPollFD *) &g_array_index (cogl_source->poll_fds, GPollFD, 0);
 
-  cogl_poll_dispatch (cogl_source->context,
-                      poll_fds,
-                      cogl_source->poll_fds->len);
+  cogl_poll_renderer_dispatch (cogl_source->renderer,
+                               poll_fds,
+                               cogl_source->poll_fds->len);
 
   return TRUE;
 }
@@ -172,8 +158,8 @@ cogl_glib_source_funcs =
   };
 
 GSource *
-cogl_glib_source_new (CoglContext *context,
-                      int priority)
+cogl_glib_renderer_source_new (CoglRenderer *renderer,
+                               int priority)
 {
   GSource *source;
   CoglGLibSource *cogl_source;
@@ -182,7 +168,7 @@ cogl_glib_source_new (CoglContext *context,
                          sizeof (CoglGLibSource));
   cogl_source = (CoglGLibSource *) source;
 
-  cogl_source->context = context;
+  cogl_source->renderer = renderer;
   cogl_source->poll_fds = g_array_new (FALSE, FALSE, sizeof (GPollFD));
 
   if (priority != G_PRIORITY_DEFAULT)
@@ -190,3 +176,13 @@ cogl_glib_source_new (CoglContext *context,
 
   return source;
 }
+
+GSource *
+cogl_glib_source_new (CoglContext *context,
+                      int priority)
+{
+  return cogl_glib_renderer_source_new (cogl_context_get_renderer (context),
+                                        priority);
+}
+
+
diff --git a/cogl/cogl-glib-source.h b/cogl/cogl-glib-source.h
index 1ce7d7e..d8d1725 100644
--- a/cogl/cogl-glib-source.h
+++ b/cogl/cogl-glib-source.h
@@ -40,11 +40,21 @@ G_BEGIN_DECLS
  *
  * Creates a #GSource which handles Cogl's internal system event
  * processing. This can be used as a convenience instead of
- * cogl_poll_get_info() and cogl_poll_dispatch() in applications that
- * are already using the GLib main loop. After this is called the
- * #GSource should be attached to the main loop using
+ * cogl_poll_renderer_get_info() and cogl_poll_renderer_dispatch() in
+ * applications that are already using the GLib main loop. After this
+ * is called the #GSource should be attached to the main loop using
  * g_source_attach().
  *
+ * Applications that manually connect to a #CoglRenderer before they
+ * create a #CoglContext should instead use
+ * cogl_glib_renderer_source_new() so that events may be dispatched
+ * before a context has been created. In that case you don't need to
+ * use this api in addition later, it is simply enough to use
+ * cogl_glib_renderer_source_new() instead.
+ *
+ * <note>This api is actually just a thin convenience wrapper around
+ * cogl_glib_renderer_source_new()</note>
+ *
  * Return value: a new #GSource
  *
  * Stability: unstable
@@ -54,6 +64,27 @@ GSource *
 cogl_glib_source_new (CoglContext *context,
                       int priority);
 
+/**
+ * cogl_glib_renderer_source_new:
+ * @context: A #CoglContext
+ * @priority: The priority of the #GSource
+ *
+ * Creates a #GSource which handles Cogl's internal system event
+ * processing. This can be used as a convenience instead of
+ * cogl_poll_renderer_get_info() and cogl_poll_renderer_dispatch() in
+ * applications that are already using the GLib main loop. After this
+ * is called the #GSource should be attached to the main loop using
+ * g_source_attach().
+ *
+ * Return value: a new #GSource
+ *
+ * Stability: unstable
+ * Since: 1.16
+ */
+GSource *
+cogl_glib_renderer_source_new (CoglRenderer *renderer,
+                               int priority);
+
 G_END_DECLS
 
 #endif /* __COGL_GSOURCE_H__ */
diff --git a/cogl/cogl-glx-display-private.h b/cogl/cogl-glx-display-private.h
index 69b1570..a29af85 100644
--- a/cogl/cogl-glx-display-private.h
+++ b/cogl/cogl-glx-display-private.h
@@ -50,9 +50,6 @@ typedef struct _CoglGLXDisplay
   GLXContext glx_context;
   GLXWindow dummy_glxwin;
   Window dummy_xwin;
-  CoglBool pending_sync_notify;
-  CoglBool pending_complete_notify;
-  CoglBool pending_resize_notify;
 } CoglGLXDisplay;
 
 #endif /* __COGL_DISPLAY_GLX_PRIVATE_H */
diff --git a/cogl/cogl-glx-renderer-private.h b/cogl/cogl-glx-renderer-private.h
index e43b443..cf4e02d 100644
--- a/cogl/cogl-glx-renderer-private.h
+++ b/cogl/cogl-glx-renderer-private.h
@@ -54,6 +54,13 @@ typedef struct _CoglGLXRenderer
   /* GModule pointing to libGL which we use to get glX functions out of */
   GModule *libgl_module;
 
+  /* Events get dispatched from the CoglRenderer and these are
+   * high-level flags that let us quickly check if there are any
+   * pending events to dispatch. */
+  CoglBool pending_sync_notify;
+  CoglBool pending_complete_notify;
+  CoglBool pending_resize_notify;
+
   /* Copy of the winsys features that are based purely on the
    * information we can get without using a GL context. We want to
    * determine this before we have a context so that we can use the
diff --git a/cogl/cogl-onscreen.h b/cogl/cogl-onscreen.h
index 11f29ad..97e0891 100644
--- a/cogl/cogl-onscreen.h
+++ b/cogl/cogl-onscreen.h
@@ -639,8 +639,8 @@ cogl_onscreen_get_resizable (CoglOnscreen *onscreen);
  *
  * <note>A resize callback will only ever be called while dispatching
  * Cogl events from the system mainloop; so for example during
- * cogl_poll_dispatch(). This is so that callbacks shouldn't occur
- * while an application might have arbitrary locks held for
+ * cogl_poll_renderer_dispatch(). This is so that callbacks shouldn't
+ * occur while an application might have arbitrary locks held for
  * example.</note>
  *
  * Since: 2.0
@@ -688,8 +688,8 @@ typedef struct _CoglOnscreenResizeClosure CoglOnscreenResizeClosure;
  *
  * <note>A resize callback will only ever be called while dispatching
  * Cogl events from the system mainloop; so for example during
- * cogl_poll_dispatch(). This is so that callbacks shouldn't occur
- * while an application might have arbitrary locks held for
+ * cogl_poll_renderer_dispatch(). This is so that callbacks shouldn't
+ * occur while an application might have arbitrary locks held for
  * example.</note>
  *
  * Return value: a #CoglOnscreenResizeClosure pointer that can be used to
diff --git a/cogl/cogl-poll-private.h b/cogl/cogl-poll-private.h
new file mode 100644
index 0000000..6e030fd
--- /dev/null
+++ b/cogl/cogl-poll-private.h
@@ -0,0 +1,36 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2013 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#ifndef __COGL_POLL_PRIVATE_H__
+#define __COGL_POLL_PRIVATE_H__
+
+void
+_cogl_poll_renderer_remove_fd (CoglRenderer *renderer, int fd);
+
+void
+_cogl_poll_renderer_add_fd (CoglRenderer *renderer,
+                            int fd,
+                            CoglPollFDEvent events);
+
+#endif /* __COGL_POLL_PRIVATE_H__ */
diff --git a/cogl/cogl-poll.c b/cogl/cogl-poll.c
index 277b9a7..8009f5f 100644
--- a/cogl/cogl-poll.c
+++ b/cogl/cogl-poll.c
@@ -28,57 +28,116 @@
 #endif
 
 #include "cogl-poll.h"
+#include "cogl-poll-private.h"
 #include "cogl-winsys-private.h"
+#include "cogl-renderer-private.h"
 #include "cogl-context-private.h"
 
-void
-cogl_poll_get_info (CoglContext *context,
-                    CoglPollFD **poll_fds,
-                    int *n_poll_fds,
-                    int64_t *timeout)
+int
+cogl_poll_renderer_get_info (CoglRenderer *renderer,
+                             CoglPollFD **poll_fds,
+                             int *n_poll_fds,
+                             int64_t *timeout)
 {
   const CoglWinsysVtable *winsys;
 
-  _COGL_RETURN_IF_FAIL (cogl_is_context (context));
-  _COGL_RETURN_IF_FAIL (poll_fds != NULL);
-  _COGL_RETURN_IF_FAIL (n_poll_fds != NULL);
-  _COGL_RETURN_IF_FAIL (timeout != NULL);
+  _COGL_RETURN_VAL_IF_FAIL (cogl_is_renderer (renderer), 0);
+  _COGL_RETURN_VAL_IF_FAIL (poll_fds != NULL, 0);
+  _COGL_RETURN_VAL_IF_FAIL (n_poll_fds != NULL, 0);
+  _COGL_RETURN_VAL_IF_FAIL (timeout != NULL, 0);
 
-  winsys = _cogl_context_get_winsys (context);
+  *poll_fds = (void *)renderer->poll_fds->data;
+  *n_poll_fds = renderer->poll_fds->len;
 
-  if (winsys->poll_get_info)
+  /* NB: This will be NULL until the renderer has been connected,
+   * associated with a CoglDisplay and then a CoglContext is
+   * created from that display. */
+  if (renderer->context)
     {
-      winsys->poll_get_info (context,
-                             poll_fds,
-                             n_poll_fds,
-                             timeout);
+      if (!COGL_TAILQ_EMPTY (&renderer->context->onscreen_events_queue))
+        {
+          *timeout = 0;
+          return renderer->poll_fds_age;
+        }
     }
+
+  winsys = renderer->winsys_vtable;
+
+  if (winsys->get_dispatch_timeout)
+    *timeout = winsys->get_dispatch_timeout (renderer);
   else
-    {
-      /* By default we'll assume Cogl doesn't need to block on anything */
-      *poll_fds = NULL;
-      *n_poll_fds = 0;
-      *timeout = -1; /* no timeout */
-    }
+    *timeout = -1;
 
-  if (!COGL_TAILQ_EMPTY (&context->onscreen_events_queue))
-    *timeout = 0;
+  return renderer->poll_fds_age;
 }
 
 void
-cogl_poll_dispatch (CoglContext *context,
-                    const CoglPollFD *poll_fds,
-                    int n_poll_fds)
+cogl_poll_renderer_dispatch (CoglRenderer *renderer,
+                             const CoglPollFD *poll_fds,
+                             int n_poll_fds)
 {
   const CoglWinsysVtable *winsys;
 
-  _COGL_RETURN_IF_FAIL (cogl_is_context (context));
+  _COGL_RETURN_IF_FAIL (cogl_is_renderer (renderer));
+
+  /* FIXME: arbitrary cogl components should just be able to queue
+   * idle functions so that we don't have to explicitly poke into
+   * CoglContext here and understand about the CoglOnscreen event
+   * queue... */
+  if (renderer->context)
+    {
+      CoglContext *context = renderer->context;
 
-  if (!COGL_TAILQ_EMPTY (&context->onscreen_events_queue))
-    _cogl_dispatch_onscreen_events (context);
+      if (!COGL_TAILQ_EMPTY (&context->onscreen_events_queue))
+        _cogl_dispatch_onscreen_events (context);
+    }
 
-  winsys = _cogl_context_get_winsys (context);
+  winsys = renderer->winsys_vtable;
 
   if (winsys->poll_dispatch)
-    winsys->poll_dispatch (context, poll_fds, n_poll_fds);
+    winsys->poll_dispatch (renderer, poll_fds, n_poll_fds);
+}
+
+static int
+find_pollfd (CoglRenderer *renderer, int fd)
+{
+  int i;
+
+  for (i = 0; i < renderer->poll_fds->len; i++)
+    {
+      CoglPollFD *pollfd = &g_array_index (renderer->poll_fds, CoglPollFD, i);
+
+      if (pollfd->fd == fd)
+        return i;
+    }
+
+  return -1;
+}
+
+void
+_cogl_poll_renderer_remove_fd (CoglRenderer *renderer, int fd)
+{
+  int i = find_pollfd (renderer, fd);
+
+  if (i < 0)
+    return;
+
+  g_array_remove_index_fast (renderer->poll_fds, i);
+  renderer->poll_fds_age++;
+}
+
+void
+_cogl_poll_renderer_add_fd (CoglRenderer *renderer,
+                            int fd,
+                            CoglPollFDEvent events)
+{
+  CoglPollFD pollfd = {
+    .fd = fd,
+    .events = events
+  };
+
+  _cogl_poll_renderer_remove_fd (renderer, fd);
+
+  g_array_append_val (renderer->poll_fds, pollfd);
+  renderer->poll_fds_age++;
 }
diff --git a/cogl/cogl-poll.h b/cogl/cogl-poll.h
index 7a7e311..1bf7838 100644
--- a/cogl/cogl-poll.h
+++ b/cogl/cogl-poll.h
@@ -104,19 +104,23 @@ typedef struct {
 } CoglPollFD;
 
 /**
- * cogl_poll_get_info:
- * @context: A #CoglContext
+ * cogl_poll_renderer_get_info:
+ * @renderer: A #CoglRenderer
  * @poll_fds: A return location for a pointer to an array
  *            of #CoglPollFD<!-- -->s
  * @n_poll_fds: A return location for the number of entries in *@poll_fds
  * @timeout: A return location for the maximum length of time to wait
  *           in microseconds, or -1 to wait indefinitely.
  *
- * This should be called whenever an application is about to go idle
- * so that Cogl has a chance to describe what state it needs to be
- * woken up on. The assumption is that the application is using a main
- * loop with something like the poll function call on Unix or the GLib
- * main loop.
+ * Is used to integrate Cogl with an application mainloop that is based
+ * on the unix poll(2) api (or select() or something equivalent). This
+ * api should be called whenever an application is about to go idle so
+ * that Cogl has a chance to describe what file descriptor events it
+ * needs to be woken up for.
+ *
+ * <note>If your application is using the Glib mainloop then you
+ * should jump to the cogl_glib_source_new() api as a more convenient
+ * way of integrating Cogl with the mainloop.</note>
  *
  * After the function is called *@poll_fds will contain a pointer to
  * an array of #CoglPollFD structs describing the file descriptors
@@ -124,8 +128,12 @@ typedef struct {
  * accordingly. After the application has completed its idle it is
  * expected to either update the revents members directly in this
  * array or to create a copy of the array and update them
- * there. Either way it should pass a pointer to either array back to
- * Cogl when calling cogl_poll_dispatch().
+ * there.
+ *
+ * When the application mainloop returns from calling poll(2) (or its
+ * equivalent) then it should call cogl_poll_renderer_dispatch()
+ * passing a pointer the array of CoglPollFD<!-- -->s with updated
+ * revent values.
  *
  * When using the %COGL_WINSYS_ID_WGL winsys (where file descriptors
  * don't make any sense) or %COGL_WINSYS_ID_SDL (where the event
@@ -134,21 +142,29 @@ typedef struct {
  *
  * @timeout will contain a maximum amount of time to wait in
  * microseconds before the application should wake up or -1 if the
- * application should wait indefinitely. This can also be 0 zero if
+ * application should wait indefinitely. This can also be 0 if
  * Cogl needs to be woken up immediately.
  *
+ * Return value: A "poll fd state age" that changes whenever the set
+ *               of poll_fds has changed. If this API is being used to
+ *               integrate with another system mainloop api then
+ *               knowing if the set of file descriptors and events has
+ *               really changed can help avoid redundant work
+ *               depending the api. The age isn't guaranteed to change
+ *               when the timeout changes.
+ *
  * Stability: unstable
- * Since: 1.10
+ * Since: 1.16
  */
-void
-cogl_poll_get_info (CoglContext *context,
-                    CoglPollFD **poll_fds,
-                    int *n_poll_fds,
-                    int64_t *timeout);
+int
+cogl_poll_renderer_get_info (CoglRenderer *renderer,
+                             CoglPollFD **poll_fds,
+                             int *n_poll_fds,
+                             int64_t *timeout);
 
 /**
- * cogl_poll_dispatch:
- * @context: A #CoglContext
+ * cogl_poll_renderer_dispatch:
+ * @renderer: A #CoglRenderer
  * @poll_fds: An array of #CoglPollFD<!-- -->s describing the events
  *            that have occurred since the application went idle.
  * @n_poll_fds: The length of the @poll_fds array.
@@ -157,17 +173,21 @@ cogl_poll_get_info (CoglContext *context,
  * going idle in its main loop. The @poll_fds array should contain a
  * list of file descriptors matched with the events that occurred in
  * revents. The events field is ignored. It is safe to pass in extra
- * file descriptors that Cogl didn't request from
- * cogl_context_begin_idle() or a shorter array missing some file
+ * file descriptors that Cogl didn't request when calling
+ * cogl_poll_renderer_get_info() or a shorter array missing some file
  * descriptors that Cogl requested.
  *
+ * <note>If your application didn't originally create a #CoglRenderer
+ * manually then you can easily get a #CoglRenderer pointer by calling
+ * cogl_get_renderer().</note>
+ *
  * Stability: unstable
- * Since: 1.10
+ * Since: 1.16
  */
 void
-cogl_poll_dispatch (CoglContext *context,
-                    const CoglPollFD *poll_fds,
-                    int n_poll_fds);
+cogl_poll_renderer_dispatch (CoglRenderer *renderer,
+                             const CoglPollFD *poll_fds,
+                             int n_poll_fds);
 
 COGL_END_DECLS
 
diff --git a/cogl/cogl-renderer-private.h b/cogl/cogl-renderer-private.h
index 8648374..b01a1c9 100644
--- a/cogl/cogl-renderer-private.h
+++ b/cogl/cogl-renderer-private.h
@@ -30,6 +30,7 @@
 #include "cogl-winsys-private.h"
 #include "cogl-driver.h"
 #include "cogl-texture-driver.h"
+#include "cogl-context.h"
 
 #ifdef COGL_HAS_XLIB_SUPPORT
 #include <X11/Xlib.h>
@@ -50,6 +51,24 @@ struct _CoglRenderer
   CoglWinsysID winsys_id_override;
   GList *constraints;
 
+  GArray *poll_fds;
+  int poll_fds_age;
+
+  /* NB: Currently a CoglContext can only be associated with 1
+   * CoglDisplay which itself can only be associated with 1
+   * CoglRenderer.
+   *
+   * We currently do event dispatching from the renderer but once we
+   * have fully setup a context then we need to refer to the context
+   * to dispatch context events.
+   *
+   * This gives us a back-reference to the CoglContext that can be
+   * referenced during event dispatching.
+   *
+   * We always need to consider that this may be NULL.
+   */
+  CoglContext *context;
+
   GList *outputs;
 
 #ifdef COGL_HAS_XLIB_SUPPORT
diff --git a/cogl/cogl-renderer.c b/cogl/cogl-renderer.c
index 2535e6a..10bd5ea 100644
--- a/cogl/cogl-renderer.c
+++ b/cogl/cogl-renderer.c
@@ -168,6 +168,8 @@ _cogl_renderer_free (CoglRenderer *renderer)
                    NULL);
   g_slist_free (renderer->event_filters);
 
+  g_array_free (renderer->poll_fds, TRUE);
+
   g_free (renderer);
 }
 
@@ -181,6 +183,8 @@ cogl_renderer_new (void)
   renderer->connected = FALSE;
   renderer->event_filters = NULL;
 
+  renderer->poll_fds = g_array_new (FALSE, TRUE, sizeof (CoglPollFD));
+
 #ifdef COGL_HAS_XLIB_SUPPORT
   renderer->xlib_enable_event_retrieval = TRUE;
 #endif
diff --git a/cogl/cogl-sdl.c b/cogl/cogl-sdl.c
index 8e04f16..19f3942 100644
--- a/cogl/cogl-sdl.c
+++ b/cogl/cogl-sdl.c
@@ -69,15 +69,18 @@ void
 cogl_sdl_handle_event (CoglContext *context, SDL_Event *event)
 {
   const CoglWinsysVtable *winsys;
+  CoglRenderer *renderer;
 
   _COGL_RETURN_IF_FAIL (cogl_is_context (context));
 
-  winsys = _cogl_context_get_winsys (context);
+  renderer = context->display->renderer;
 
-  _cogl_renderer_handle_native_event (context->display->renderer, event);
+  winsys = renderer->winsys_vtable;
+
+  _cogl_renderer_handle_native_event (renderer, event);
 
   if (winsys->poll_dispatch)
-    winsys->poll_dispatch (context, NULL, 0);
+    winsys->poll_dispatch (renderer, NULL, 0);
 }
 
 static void
diff --git a/cogl/cogl-xlib-renderer-private.h b/cogl/cogl-xlib-renderer-private.h
index 7990e6c..cec9cac 100644
--- a/cogl/cogl-xlib-renderer-private.h
+++ b/cogl/cogl-xlib-renderer-private.h
@@ -40,9 +40,6 @@ typedef struct _CoglXlibRenderer
      these is expected to be allocated on the stack by the caller */
   CoglXlibTrapState *trap_state;
 
-  /* A poll FD for handling event retrieval within Cogl */
-  CoglPollFD poll_fd;
-
   unsigned long outputs_update_serial;
 } CoglXlibRenderer;
 
@@ -84,11 +81,8 @@ _cogl_xlib_renderer_untrap_errors (CoglRenderer *renderer,
 CoglXlibRenderer *
 _cogl_xlib_renderer_get_data (CoglRenderer *renderer);
 
-void
-_cogl_xlib_renderer_poll_get_info (CoglRenderer *renderer,
-                                   CoglPollFD **poll_fds,
-                                   int *n_poll_fds,
-                                   int64_t *timeout);
+int64_t
+_cogl_xlib_renderer_get_dispatch_timeout (CoglRenderer *renderer);
 
 void
 _cogl_xlib_renderer_poll_dispatch (CoglRenderer *renderer,
diff --git a/cogl/cogl-xlib-renderer.c b/cogl/cogl-xlib-renderer.c
index 18c0fe6..09b0def 100644
--- a/cogl/cogl-xlib-renderer.c
+++ b/cogl/cogl-xlib-renderer.c
@@ -38,6 +38,7 @@
 #include "cogl-x11-renderer-private.h"
 #include "cogl-winsys-private.h"
 #include "cogl-error-private.h"
+#include "cogl-poll-private.h"
 
 #include <X11/Xlib.h>
 #include <X11/extensions/Xdamage.h>
@@ -497,8 +498,12 @@ _cogl_xlib_renderer_connect (CoglRenderer *renderer, CoglError **error)
 
   xlib_renderer->trap_state = NULL;
 
-  xlib_renderer->poll_fd.fd = ConnectionNumber (xlib_renderer->xdpy);
-  xlib_renderer->poll_fd.events = COGL_POLL_FD_EVENT_IN;
+  if (renderer->xlib_enable_event_retrieval)
+    {
+      _cogl_poll_renderer_add_fd (renderer,
+                                  ConnectionNumber (xlib_renderer->xdpy),
+                                  COGL_POLL_FD_EVENT_IN);
+    }
 
   XRRSelectInput(xlib_renderer->xdpy,
                  DefaultRootWindow (xlib_renderer->xdpy),
@@ -568,29 +573,20 @@ cogl_xlib_renderer_remove_filter (CoglRenderer *renderer,
                                        (CoglNativeFilterFunc)func, data);
 }
 
-void
-_cogl_xlib_renderer_poll_get_info (CoglRenderer *renderer,
-                                   CoglPollFD **poll_fds,
-                                   int *n_poll_fds,
-                                   int64_t *timeout)
+int64_t
+_cogl_xlib_renderer_get_dispatch_timeout (CoglRenderer *renderer)
 {
   CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer);
 
   if (renderer->xlib_enable_event_retrieval)
     {
-      *n_poll_fds = 1;
-      *poll_fds = &xlib_renderer->poll_fd;
       if (XPending (xlib_renderer->xdpy))
-        *timeout = 0;
+        return 0;
       else
-        *timeout = -1;
+        return -1;
     }
   else
-    {
-      *n_poll_fds = 0;
-      *poll_fds = NULL;
-      *timeout = -1;
-    }
+    return -1;
 }
 
 void
diff --git a/cogl/cogl.symbols b/cogl/cogl.symbols
index b272d62..cd176f7 100644
--- a/cogl/cogl.symbols
+++ b/cogl/cogl.symbols
@@ -422,8 +422,8 @@ cogl_pixel_buffer_set_region
 #endif
 cogl_pixel_format_get_type
 
-cogl_poll_dispatch
-cogl_poll_get_info
+cogl_poll_renderer_get_info
+cogl_poll_renderer_dispatch
 
 cogl_polygon
 
diff --git a/cogl/winsys/cogl-winsys-egl-kms.c b/cogl/winsys/cogl-winsys-egl-kms.c
index 76f0990..288d652 100644
--- a/cogl/winsys/cogl-winsys-egl-kms.c
+++ b/cogl/winsys/cogl-winsys-egl-kms.c
@@ -53,6 +53,7 @@
 #include "cogl-kms-display.h"
 #include "cogl-version.h"
 #include "cogl-error-private.h"
+#include "cogl-poll-private.h"
 
 static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable;
 
@@ -62,7 +63,8 @@ typedef struct _CoglRendererKMS
 {
   int fd;
   struct gbm_device *gbm;
-  CoglPollFD poll_fd;
+
+  CoglBool pending_swap_notify;
 } CoglRendererKMS;
 
 typedef struct _CoglOutputKMS
@@ -80,7 +82,6 @@ typedef struct _CoglDisplayKMS
   GList *outputs;
   int width, height;
   CoglBool pending_set_crtc;
-  CoglBool pending_swap_notify;
   struct gbm_surface *dummy_gbm_surface;
 } CoglDisplayKMS;
 
@@ -159,8 +160,9 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
   if (!_cogl_winsys_egl_renderer_connect_common (renderer, error))
     goto egl_terminate;
 
-  kms_renderer->poll_fd.fd = kms_renderer->fd;
-  kms_renderer->poll_fd.events = COGL_POLL_FD_EVENT_IN;
+  _cogl_poll_renderer_add_fd (renderer,
+                              kms_renderer->fd,
+                              COGL_POLL_FD_EVENT_IN);
 
   return TRUE;
 
@@ -609,23 +611,25 @@ page_flip_handler (int fd,
                    void *data)
 {
   CoglFlipKMS *flip = data;
-  CoglOnscreen *onscreen = flip->onscreen;
-  CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
-  CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
-  CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
-  CoglDisplay *display = context->display;
-  CoglDisplayEGL *egl_display = display->winsys;
-  CoglDisplayKMS *kms_display = egl_display->platform;
 
   /* We're only ready to dispatch a swap notification once all outputs
    * have flipped... */
   flip->pending--;
   if (flip->pending == 0)
     {
-      /* We only want to notify that the swap is complete when the application
-       * calls cogl_context_dispatch so instead of immediately notifying we'll
-       * set a flag to remember to notify later */
-      kms_display->pending_swap_notify = TRUE;
+      CoglOnscreen *onscreen = flip->onscreen;
+      CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
+      CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
+      CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
+      CoglRenderer *renderer = context->display->renderer;
+      CoglRendererEGL *egl_renderer = renderer->winsys;
+      CoglRendererKMS *kms_renderer = egl_renderer->platform;
+
+      /* We only want to notify that the swap is complete when the
+       * application calls cogl_context_dispatch so instead of
+       * immediately notifying we'll set a flag to remember to notify
+       * later */
+      kms_renderer->pending_swap_notify = TRUE;
       kms_onscreen->pending_swap_notify = TRUE;
 
       free_current_bo (onscreen);
@@ -857,25 +861,15 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
   onscreen->winsys = NULL;
 }
 
-static void
-_cogl_winsys_poll_get_info (CoglContext *context,
-                            CoglPollFD **poll_fds,
-                            int *n_poll_fds,
-                            int64_t *timeout)
+static int64_t
+_cogl_winsys_get_dispatch_timeout (CoglRenderer *renderer)
 {
-  CoglDisplay *display = context->display;
-  CoglDisplayEGL *egl_display = display->winsys;
-  CoglDisplayKMS *kms_display = egl_display->platform;
-  CoglRenderer *renderer = display->renderer;
   CoglRendererEGL *egl_renderer = renderer->winsys;
   CoglRendererKMS *kms_renderer = egl_renderer->platform;
 
-  *poll_fds = &kms_renderer->poll_fd;
-  *n_poll_fds = 1;
-
   /* If we've already got a pending swap notify then we'll dispatch
-     immediately */
-  *timeout = kms_display->pending_swap_notify ? 0 : -1;
+   * immediately */
+  return kms_renderer->pending_swap_notify ? 0 : -1;
 }
 
 static void
@@ -904,14 +898,10 @@ flush_pending_swap_notify_cb (void *data,
 }
 
 static void
-_cogl_winsys_poll_dispatch (CoglContext *context,
+_cogl_winsys_poll_dispatch (CoglRenderer *renderer,
                             const CoglPollFD *poll_fds,
                             int n_poll_fds)
 {
-  CoglDisplay *display = context->display;
-  CoglDisplayEGL *egl_display = display->winsys;
-  CoglDisplayKMS *kms_display = egl_display->platform;
-  CoglRenderer *renderer = display->renderer;
   CoglRendererEGL *egl_renderer = renderer->winsys;
   CoglRendererKMS *kms_renderer = egl_renderer->platform;
   int i;
@@ -925,12 +915,21 @@ _cogl_winsys_poll_dispatch (CoglContext *context,
         break;
       }
 
-  if (kms_display->pending_swap_notify)
+  /* FIXME: instead of requiring event dispatching which is handled at
+   * the CoglRenderer level to have to know about CoglContext we
+   * should have a generalized way of queuing an idle function */
+  if (renderer->context &&
+      kms_renderer->pending_swap_notify)
     {
+      CoglContext *context = renderer->context;
+
+      /* This needs to be cleared before invoking the callbacks in
+       * case the callbacks cause it to be set again */
+      kms_renderer->pending_swap_notify = FALSE;
+
       g_list_foreach (context->framebuffers,
                       flush_pending_swap_notify_cb,
                       NULL);
-      kms_display->pending_swap_notify = FALSE;
     }
 }
 
@@ -971,7 +970,7 @@ _cogl_winsys_egl_kms_get_vtable (void)
       vtable.onscreen_swap_region = NULL;
       vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers;
 
-      vtable.poll_get_info = _cogl_winsys_poll_get_info;
+      vtable.get_dispatch_timeout = _cogl_winsys_get_dispatch_timeout;
       vtable.poll_dispatch = _cogl_winsys_poll_dispatch;
 
       vtable_inited = TRUE;
diff --git a/cogl/winsys/cogl-winsys-egl-private.h b/cogl/winsys/cogl-winsys-egl-private.h
index 0d76065..d21f1b0 100644
--- a/cogl/winsys/cogl-winsys-egl-private.h
+++ b/cogl/winsys/cogl-winsys-egl-private.h
@@ -82,6 +82,8 @@ typedef struct _CoglRendererEGL
   EGLint egl_version_major;
   EGLint egl_version_minor;
 
+  CoglBool pending_resize_notify;
+
   /* Data specific to the EGL platform */
   void *platform;
   /* vtable for platform specific parts */
@@ -115,8 +117,6 @@ typedef struct _CoglDisplayEGL
   EGLSurface current_draw_surface;
   EGLContext current_context;
 
-  CoglBool pending_resize_notify;
-
   /* Platform specific display data */
   void *platform;
 } CoglDisplayEGL;
diff --git a/cogl/winsys/cogl-winsys-egl-x11.c b/cogl/winsys/cogl-winsys-egl-x11.c
index d792f07..ec1ae1a 100644
--- a/cogl/winsys/cogl-winsys-egl-x11.c
+++ b/cogl/winsys/cogl-winsys-egl-x11.c
@@ -96,11 +96,11 @@ notify_resize (CoglContext *context,
                int width,
                int height)
 {
+  CoglRenderer *renderer = context->display->renderer;
+  CoglRendererEGL *egl_renderer = renderer->winsys;
   CoglOnscreen *onscreen = find_onscreen_for_xid (context, drawable);
+  CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
-  CoglDisplay *display = context->display;
-  CoglDisplayEGL *egl_display = display->winsys;
-  CoglOnscreenEGL *egl_onscreen;
 
   if (!onscreen)
     return;
@@ -110,9 +110,9 @@ notify_resize (CoglContext *context,
   _cogl_framebuffer_winsys_update_size (framebuffer, width, height);
 
   /* We only want to notify that a resize happened when the
-     application calls cogl_context_dispatch so instead of immediately
-     notifying we'll set a flag to remember to notify later */
-  egl_display->pending_resize_notify = TRUE;
+   * application calls cogl_context_dispatch so instead of immediately
+   * notifying we'll set a flag to remember to notify later */
+  egl_renderer->pending_resize_notify = TRUE;
   egl_onscreen->pending_resize_notify = TRUE;
 }
 
@@ -622,22 +622,15 @@ _cogl_winsys_xlib_get_visual_info (void)
   return get_visual_info (ctx->display, egl_display->egl_config);
 }
 
-static void
-_cogl_winsys_poll_get_info (CoglContext *context,
-                            CoglPollFD **poll_fds,
-                            int *n_poll_fds,
-                            int64_t *timeout)
+static int64_t
+_cogl_winsys_get_dispatch_timeout (CoglRenderer *renderer)
 {
-  CoglDisplay *display = context->display;
-  CoglDisplayEGL *egl_display = display->winsys;
+  CoglRendererEGL *egl_renderer = renderer->winsys;
 
-  _cogl_xlib_renderer_poll_get_info (context->display->renderer,
-                                     poll_fds,
-                                     n_poll_fds,
-                                     timeout);
+  if (egl_renderer->pending_resize_notify)
+    return 0;
 
-  if (egl_display->pending_resize_notify)
-    *timeout = 0;
+  return _cogl_xlib_renderer_get_dispatch_timeout (renderer);
 }
 
 static void
@@ -660,23 +653,31 @@ flush_pending_notifications_cb (void *data,
 }
 
 static void
-_cogl_winsys_poll_dispatch (CoglContext *context,
+_cogl_winsys_poll_dispatch (CoglRenderer *renderer,
                             const CoglPollFD *poll_fds,
                             int n_poll_fds)
 {
-  CoglDisplay *display = context->display;
-  CoglDisplayEGL *egl_display = display->winsys;
+  CoglRendererEGL *egl_renderer = renderer->winsys;
 
-  _cogl_xlib_renderer_poll_dispatch (context->display->renderer,
+  _cogl_xlib_renderer_poll_dispatch (renderer,
                                      poll_fds,
                                      n_poll_fds);
 
-  if (egl_display->pending_resize_notify)
+  /* FIXME: instead of requiring event dispatching which is handled at
+   * the CoglRenderer level to have to know about CoglContext we
+   * should have a generalized way of queuing an idle function */
+  if (renderer->context &&
+      egl_renderer->pending_resize_notify)
     {
+      CoglContext *context = renderer->context;
+
+      /* This needs to be cleared before invoking the callbacks in
+       * case the callbacks cause it to be set again */
+      egl_renderer->pending_resize_notify = FALSE;
+
       g_list_foreach (context->framebuffers,
                       flush_pending_notifications_cb,
                       NULL);
-      egl_display->pending_resize_notify = FALSE;
     }
 }
 
@@ -826,7 +827,7 @@ _cogl_winsys_egl_xlib_get_vtable (void)
 
       vtable.xlib_get_visual_info = _cogl_winsys_xlib_get_visual_info;
 
-      vtable.poll_get_info = _cogl_winsys_poll_get_info;
+      vtable.get_dispatch_timeout = _cogl_winsys_get_dispatch_timeout;
       vtable.poll_dispatch = _cogl_winsys_poll_dispatch;
 
 #ifdef EGL_KHR_image_pixmap
diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c
index affc3ba..15d34c2 100644
--- a/cogl/winsys/cogl-winsys-glx.c
+++ b/cogl/winsys/cogl-winsys-glx.c
@@ -305,9 +305,9 @@ set_sync_pending (CoglOnscreen *onscreen)
 {
   CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
   CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
-  CoglGLXDisplay *glx_display = context->display->winsys;
+  CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
 
-  glx_display->pending_sync_notify = TRUE;
+  glx_renderer->pending_sync_notify = TRUE;
   glx_onscreen->pending_sync_notify = TRUE;
 }
 
@@ -316,9 +316,9 @@ set_complete_pending (CoglOnscreen *onscreen)
 {
   CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
   CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
-  CoglGLXDisplay *glx_display = context->display->winsys;
+  CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
 
-  glx_display->pending_complete_notify = TRUE;
+  glx_renderer->pending_complete_notify = TRUE;
   glx_onscreen->pending_complete_notify = TRUE;
 }
 
@@ -385,8 +385,7 @@ notify_resize (CoglContext *context,
   CoglOnscreen *onscreen = find_onscreen_for_xid (context,
                                                   configure_event->window);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
-  CoglDisplay *display = context->display;
-  CoglGLXDisplay *glx_display = display->winsys;
+  CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
   CoglOnscreenGLX *glx_onscreen;
   CoglOnscreenXlib *xlib_onscreen;
 
@@ -403,7 +402,7 @@ notify_resize (CoglContext *context,
   /* We only want to notify that a resize happened when the
      application calls cogl_context_dispatch so instead of immediately
      notifying we'll set a flag to remember to notify later */
-  glx_display->pending_resize_notify = TRUE;
+  glx_renderer->pending_resize_notify = TRUE;
   glx_onscreen->pending_resize_notify = TRUE;
 
   if (!xlib_onscreen->is_foreign_xwin)
@@ -2497,26 +2496,19 @@ _cogl_winsys_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap)
   return glx_tex_pixmap->glx_tex;
 }
 
-static void
-_cogl_winsys_poll_get_info (CoglContext *context,
-                            CoglPollFD **poll_fds,
-                            int *n_poll_fds,
-                            int64_t *timeout)
+static int64_t
+_cogl_winsys_get_dispatch_timeout (CoglRenderer *renderer)
 {
-  CoglDisplay *display = context->display;
-  CoglGLXDisplay *glx_display = display->winsys;
-
-  _cogl_xlib_renderer_poll_get_info (context->display->renderer,
-                                     poll_fds,
-                                     n_poll_fds,
-                                     timeout);
+  CoglGLXRenderer *glx_renderer = renderer->winsys;
 
   /* If we've already got a pending swap notify then we'll dispatch
-     immediately */
-  if (glx_display->pending_sync_notify ||
-      glx_display->pending_resize_notify ||
-      glx_display->pending_complete_notify)
-    *timeout = 0;
+   * immediately */
+  if (glx_renderer->pending_sync_notify ||
+      glx_renderer->pending_resize_notify ||
+      glx_renderer->pending_complete_notify)
+    return 0;
+
+  return _cogl_xlib_renderer_get_dispatch_timeout (renderer);
 }
 
 static void
@@ -2563,30 +2555,37 @@ flush_pending_notifications_cb (void *data,
 }
 
 static void
-_cogl_winsys_poll_dispatch (CoglContext *context,
+_cogl_winsys_poll_dispatch (CoglRenderer *renderer,
                             const CoglPollFD *poll_fds,
                             int n_poll_fds)
 {
-  CoglDisplay *display = context->display;
-  CoglGLXDisplay *glx_display = display->winsys;
+  CoglGLXRenderer *glx_renderer = renderer->winsys;
 
-  _cogl_xlib_renderer_poll_dispatch (context->display->renderer,
+  _cogl_xlib_renderer_poll_dispatch (renderer,
                                      poll_fds,
                                      n_poll_fds);
 
-  if (glx_display->pending_sync_notify ||
-      glx_display->pending_resize_notify ||
-      glx_display->pending_complete_notify)
+  /* FIXME: instead of requiring event dispatching which is handled at
+   * the CoglRenderer level to have to know about CoglContext we
+   * should have a generalized way of queuing an idle function */
+  if (renderer->context)
     {
-      /* These need to be cleared before invoking the callbacks in
-       * case the callbacks cause them to be set again */
-      glx_display->pending_sync_notify = FALSE;
-      glx_display->pending_resize_notify = FALSE;
-      glx_display->pending_complete_notify = FALSE;
+      CoglContext *context = renderer->context;
 
-      g_list_foreach (context->framebuffers,
-                      flush_pending_notifications_cb,
-                      NULL);
+      if (glx_renderer->pending_sync_notify ||
+          glx_renderer->pending_resize_notify ||
+          glx_renderer->pending_complete_notify)
+        {
+          /* These need to be cleared before invoking the callbacks in
+           * case the callbacks cause them to be set again */
+          glx_renderer->pending_sync_notify = FALSE;
+          glx_renderer->pending_resize_notify = FALSE;
+          glx_renderer->pending_complete_notify = FALSE;
+
+          g_list_foreach (context->framebuffers,
+                          flush_pending_notifications_cb,
+                          NULL);
+        }
     }
 }
 
@@ -2621,7 +2620,7 @@ static CoglWinsysVtable _cogl_winsys_vtable =
     .onscreen_set_resizable =
       _cogl_winsys_onscreen_set_resizable,
 
-    .poll_get_info = _cogl_winsys_poll_get_info,
+    .get_dispatch_timeout = _cogl_winsys_get_dispatch_timeout,
     .poll_dispatch = _cogl_winsys_poll_dispatch,
 
     /* X11 tfp support... */
diff --git a/cogl/winsys/cogl-winsys-private.h b/cogl/winsys/cogl-winsys-private.h
index 36676e3..037bb77 100644
--- a/cogl/winsys/cogl-winsys-private.h
+++ b/cogl/winsys/cogl-winsys-private.h
@@ -154,13 +154,11 @@ typedef struct _CoglWinsysVtable
   (*onscreen_win32_get_window) (CoglOnscreen *onscreen);
 #endif
 
+  int64_t
+  (*get_dispatch_timeout) (CoglRenderer *renderer);
+
   void
-  (*poll_get_info) (CoglContext *context,
-                    CoglPollFD **poll_fds,
-                    int *n_poll_fds,
-                    int64_t *timeout);
-  void
-  (*poll_dispatch) (CoglContext *context,
+  (*poll_dispatch) (CoglRenderer *renderer,
                     const CoglPollFD *poll_fds,
                     int n_poll_fds);
 
diff --git a/cogl/winsys/cogl-winsys-sdl.c b/cogl/winsys/cogl-winsys-sdl.c
index 8c4e2ac..ddaaff5 100644
--- a/cogl/winsys/cogl-winsys-sdl.c
+++ b/cogl/winsys/cogl-winsys-sdl.c
@@ -41,7 +41,7 @@
 
 typedef struct _CoglRendererSdl
 {
-  int stub;
+  CoglBool pending_resize_notify;
 } CoglRendererSdl;
 
 typedef struct _CoglDisplaySdl
@@ -49,7 +49,6 @@ typedef struct _CoglDisplaySdl
   SDL_Surface *surface;
   CoglOnscreen *onscreen;
   Uint32 video_mode_flags;
-  CoglBool pending_resize_notify;
 } CoglDisplaySdl;
 
 static CoglFuncPtr
@@ -218,6 +217,7 @@ sdl_event_filter_cb (SDL_Event *event, void *data)
       CoglContext *context = data;
       CoglDisplay *display = context->display;
       CoglDisplaySdl *sdl_display = display->winsys;
+      CoglRendererSdl *sdl_renderer = display->renderer->winsys;
       float width = event->resize.w;
       float height = event->resize.h;
       CoglFramebuffer *framebuffer;
@@ -233,9 +233,10 @@ sdl_event_filter_cb (SDL_Event *event, void *data)
       _cogl_framebuffer_winsys_update_size (framebuffer, width, height);
 
       /* We only want to notify that a resize happened when the
-         application calls cogl_context_dispatch so instead of immediately
-         notifying we'll set a flag to remember to notify later */
-      sdl_display->pending_resize_notify = TRUE;
+       * application calls cogl_context_dispatch so instead of
+       * immediately notifying we'll set a flag to remember to notify
+       * later */
+      sdl_renderer->pending_resize_notify = TRUE;
 
       return COGL_FILTER_CONTINUE;
     }
@@ -378,22 +379,27 @@ _cogl_winsys_onscreen_set_resizable (CoglOnscreen *onscreen,
 }
 
 static void
-_cogl_winsys_poll_dispatch (CoglContext *context,
+_cogl_winsys_poll_dispatch (CoglRenderer *renderer,
                             const CoglPollFD *poll_fds,
                             int n_poll_fds)
 {
-  CoglDisplay *display = context->display;
-  CoglDisplaySdl *sdl_display = display->winsys;
+  CoglRendererSdl *sdl_renderer = renderer->winsys;
 
-  if (sdl_display->pending_resize_notify)
+  /* FIXME: instead of requiring event dispatching which is handled at
+   * the CoglRenderer level to have to know about CoglContext we
+   * should have a generalized way of queuing an idle function */
+  if (renderer->context &&
+      sdl_renderer->pending_resize_notify)
     {
+      CoglContext *context = renderer->context;
+      CoglDisplaySdl *sdl_display = context->display->winsys;
       CoglOnscreen *onscreen = sdl_display->onscreen;
 
       g_return_if_fail (onscreen != NULL);
 
       _cogl_onscreen_notify_resize (onscreen);
 
-      sdl_display->pending_resize_notify = FALSE;
+      sdl_renderer->pending_resize_notify = FALSE;
     }
 }
 
diff --git a/cogl/winsys/cogl-winsys-sdl2.c b/cogl/winsys/cogl-winsys-sdl2.c
index ca4f5fd..24ba3b2 100644
--- a/cogl/winsys/cogl-winsys-sdl2.c
+++ b/cogl/winsys/cogl-winsys-sdl2.c
@@ -47,14 +47,13 @@ typedef struct _CoglContextSdl2
 
 typedef struct _CoglRendererSdl2
 {
-  int stub;
+  CoglBool pending_resize_notify;
 } CoglRendererSdl2;
 
 typedef struct _CoglDisplaySdl2
 {
   SDL_Window *dummy_window;
   SDL_GLContext *context;
-  CoglBool pending_resize_notify;
 } CoglDisplaySdl2;
 
 typedef struct _CoglOnscreenSdl2
@@ -274,7 +273,7 @@ sdl_event_filter_cb (SDL_Event *event, void *data)
     {
       CoglContext *context = data;
       CoglDisplay *display = context->display;
-      CoglDisplaySdl2 *sdl_display = display->winsys;
+      CoglRendererSdl2 *sdl_renderer = display->renderer->winsys;
       float width = event->window.data1;
       float height = event->window.data2;
       CoglFramebuffer *framebuffer;
@@ -296,9 +295,10 @@ sdl_event_filter_cb (SDL_Event *event, void *data)
       sdl_onscreen = COGL_ONSCREEN (framebuffer)->winsys;
 
       /* We only want to notify that a resize happened when the
-         application calls cogl_context_dispatch so instead of immediately
-         notifying we'll set a flag to remember to notify later */
-      sdl_display->pending_resize_notify = TRUE;
+       * application calls cogl_context_dispatch so instead of
+       * immediately notifying we'll set a flag to remember to notify
+       * later */
+      sdl_renderer->pending_resize_notify = TRUE;
       sdl_onscreen->pending_resize_notify = TRUE;
 
       return COGL_FILTER_CONTINUE;
@@ -506,19 +506,24 @@ flush_pending_notifications_cb (void *data,
 }
 
 static void
-_cogl_winsys_poll_dispatch (CoglContext *context,
+_cogl_winsys_poll_dispatch (CoglRenderer *renderer,
                             const CoglPollFD *poll_fds,
                             int n_poll_fds)
 {
-  CoglDisplay *display = context->display;
-  CoglDisplaySdl2 *sdl_display = display->winsys;
+  CoglRendererSdl2 *sdl_renderer = renderer->winsys;
 
-  if (sdl_display->pending_resize_notify)
+  /* FIXME: instead of requiring event dispatching which is handled at
+   * the CoglRenderer level to have to know about CoglContext we
+   * should have a generalized way of queuing an idle function */
+  if (renderer->context &&
+      sdl_renderer->pending_resize_notify)
     {
+      CoglContext *context = renderer->context;
+
       g_list_foreach (context->framebuffers,
                       flush_pending_notifications_cb,
                       NULL);
-      sdl_display->pending_resize_notify = FALSE;
+      sdl_renderer->pending_resize_notify = FALSE;
     }
 }
 
diff --git a/doc/reference/cogl2/cogl2-sections.txt b/doc/reference/cogl2/cogl2-sections.txt
index e160a74..be9d691 100644
--- a/doc/reference/cogl2/cogl2-sections.txt
+++ b/doc/reference/cogl2/cogl2-sections.txt
@@ -198,12 +198,13 @@ COGL_PREMULT_BIT
 
 <SECTION>
 <FILE>cogl-poll</FILE>
-<TITLE>Main loop integeration</TITLE>
+<TITLE>Main loop integration</TITLE>
 CoglPollFDEvent
 CoglPollFD
-cogl_poll_get_info
-cogl_poll_dispatch
+cogl_poll_renderer_get_info
+cogl_poll_renderer_dispatch
 cogl_glib_source_new
+cogl_glib_renderer_source_new
 </SECTION>
 
 <SECTION>
diff --git a/examples/cogl-crate.c b/examples/cogl-crate.c
index 81f06a8..806ef43 100644
--- a/examples/cogl-crate.c
+++ b/examples/cogl-crate.c
@@ -276,6 +276,7 @@ main (int argc, char **argv)
                                     &data,
                                     NULL); /* destroy notify */
 
+
   while (1)
     {
       CoglPollFD *poll_fds;
@@ -288,12 +289,14 @@ main (int argc, char **argv)
           cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb));
         }
 
-      cogl_poll_get_info (ctx, &poll_fds, &n_poll_fds, &timeout);
+      cogl_poll_renderer_get_info (cogl_context_get_renderer (ctx),
+                                   &poll_fds, &n_poll_fds, &timeout);
 
       g_poll ((GPollFD *) poll_fds, n_poll_fds,
               timeout == -1 ? -1 : timeout / 1000);
 
-      cogl_poll_dispatch (ctx, poll_fds, n_poll_fds);
+      cogl_poll_renderer_dispatch (cogl_context_get_renderer (ctx),
+                                   poll_fds, n_poll_fds);
     }
 
   return 0;
diff --git a/examples/cogl-msaa.c b/examples/cogl-msaa.c
index 5e7412f..9fa7a3a 100644
--- a/examples/cogl-msaa.c
+++ b/examples/cogl-msaa.c
@@ -106,9 +106,11 @@ main (int argc, char **argv)
 
         cogl_onscreen_swap_buffers (onscreen);
 
-        cogl_poll_get_info (ctx, &poll_fds, &n_poll_fds, &timeout);
+        cogl_poll_renderer_get_info (cogl_context_get_renderer (ctx),
+                                     &poll_fds, &n_poll_fds, &timeout);
         g_poll ((GPollFD *) poll_fds, n_poll_fds, 0);
-        cogl_poll_dispatch (ctx, poll_fds, n_poll_fds);
+        cogl_poll_renderer_dispatch (cogl_context_get_renderer (ctx),
+                                     poll_fds, n_poll_fds);
     }
 
     return 0;
diff --git a/examples/cogl-x11-foreign.c b/examples/cogl-x11-foreign.c
index e9ac93d..1622266 100644
--- a/examples/cogl-x11-foreign.c
+++ b/examples/cogl-x11-foreign.c
@@ -188,9 +188,11 @@ main (int argc, char **argv)
        * then allow Cogl to dispatch any corresponding event
        * callbacks, such as resize notification callbacks...
        */
-      cogl_poll_get_info (ctx, &poll_fds, &n_poll_fds, &timeout);
+      cogl_poll_renderer_get_info (cogl_context_get_renderer (ctx),
+                                   &poll_fds, &n_poll_fds, &timeout);
       g_poll ((GPollFD *) poll_fds, n_poll_fds, 0);
-      cogl_poll_dispatch (ctx, poll_fds, n_poll_fds);
+      cogl_poll_renderer_dispatch (cogl_context_get_renderer (ctx),
+                                   poll_fds, n_poll_fds);
 
       cogl_framebuffer_clear4f (fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);
       cogl_framebuffer_draw_primitive (fb, pipeline, triangle);
-- 
1.8.2.1



More information about the Cogl mailing list