[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