From ed90c6fed9f5eb924868fae1f0a87e4044a19f89 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 16 Apr 2013 23:46:03 +0100 Subject: [PATCH] Move event polling into CoglRenderer 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. Reviewed-by: Neil Roberts (cherry picked from commit 667e58c9cb2662aef5f44e580a9eda42dc8d0176) --- 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-wayland.c | 22 +--- 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 ++-- .../cogl-2.0-experimental-sections.txt | 7 +- examples/cogl-crate.c | 7 +- examples/cogl-msaa.c | 6 +- examples/cogl-x11-foreign.c | 6 +- 29 files changed, 489 insertions(+), 285 deletions(-) create mode 100644 cogl/cogl-poll-private.h diff --git a/cogl/Makefile.am b/cogl/Makefile.am index f48a1ad86..4629b4949 100644 --- a/cogl/Makefile.am +++ b/cogl/Makefile.am @@ -416,6 +416,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 175e69dd0..b18848b08 100644 --- a/cogl/cogl-context.c +++ b/cogl/cogl-context.c @@ -206,6 +206,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 */ @@ -607,6 +619,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 ec18c3886..f7eba11ae 100644 --- a/cogl/cogl-context.h +++ b/cogl/cogl-context.h @@ -125,6 +125,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 adbd4d851..bb426f051 100644 --- a/cogl/cogl-glib-source.c +++ b/cogl/cogl-glib-source.c @@ -32,31 +32,14 @@ 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) { @@ -64,18 +47,19 @@ cogl_glib_source_prepare (GSource *source, int *timeout) 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 1ce7d7e71..d8d17258a 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. + * + * This api is actually just a thin convenience wrapper around + * cogl_glib_renderer_source_new() + * * 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 69b1570e9..a29af8540 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 f430a40b8..ec8052aff 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 8b7973f3c..52fa4d1fb 100644 --- a/cogl/cogl-onscreen.h +++ b/cogl/cogl-onscreen.h @@ -667,8 +667,8 @@ cogl_onscreen_get_resizable (CoglOnscreen *onscreen); * * 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. * * Since: 2.0 @@ -716,8 +716,8 @@ typedef struct _CoglOnscreenResizeClosure CoglOnscreenResizeClosure; * * 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. * * 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 000000000..6e030fd51 --- /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 + * . + * + * + */ + +#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 277b9a71e..4b974804f 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)); - if (!COGL_TAILQ_EMPTY (&context->onscreen_events_queue)) - _cogl_dispatch_onscreen_events (context); + /* 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; - winsys = _cogl_context_get_winsys (context); + if (!COGL_TAILQ_EMPTY (&context->onscreen_events_queue)) + _cogl_dispatch_onscreen_events (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, + 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 7a7e311b5..1bf783805 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 #CoglPollFDs * @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. + * + * 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. * * 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 CoglPollFDs 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 #CoglPollFDs 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. * + * If your application didn't originally create a #CoglRenderer + * manually then you can easily get a #CoglRenderer pointer by calling + * cogl_get_renderer(). + * * 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 8648374af..b01a1c939 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 @@ -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 401cfd50c..f895d4671 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 8e04f1602..19f39429c 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 7990e6c6a..cec9cac09 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 18c0fe63c..09b0def55 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 #include @@ -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 3f9514790..dc2daabfb 100644 --- a/cogl/cogl.symbols +++ b/cogl/cogl.symbols @@ -650,8 +650,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 db2b4966a..098468a25 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); @@ -863,25 +867,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 @@ -910,14 +904,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; @@ -931,12 +921,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; } } @@ -977,7 +976,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 0d7606545..d21f1b0ca 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-wayland.c b/cogl/winsys/cogl-winsys-egl-wayland.c index e605b517c..965008956 100644 --- a/cogl/winsys/cogl-winsys-egl-wayland.c +++ b/cogl/winsys/cogl-winsys-egl-wayland.c @@ -601,29 +601,17 @@ cogl_wayland_onscreen_resize (CoglOnscreen *onscreen, _cogl_framebuffer_winsys_update_size (fb, width, height); } -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; - CoglRenderer *renderer = display->renderer; - CoglRendererEGL *egl_renderer = renderer->winsys; - CoglRendererWayland *wayland_renderer = egl_renderer->platform; - - *poll_fds = &wayland_renderer->poll_fd; - *n_poll_fds = 1; - *timeout = -1; + return -1; } 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; - CoglRenderer *renderer = display->renderer; CoglRendererEGL *egl_renderer = renderer->winsys; CoglRendererWayland *wayland_renderer = egl_renderer->platform; int i; @@ -671,7 +659,7 @@ _cogl_winsys_egl_wayland_get_vtable (void) 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-x11.c b/cogl/winsys/cogl-winsys-egl-x11.c index 3e91b9935..616a2c236 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; } @@ -623,22 +623,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 @@ -661,23 +654,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; } } @@ -827,7 +828,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 a58a6ce1b..dc40f28cb 100644 --- a/cogl/winsys/cogl-winsys-glx.c +++ b/cogl/winsys/cogl-winsys-glx.c @@ -308,9 +308,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; } @@ -319,9 +319,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; } @@ -388,8 +388,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; @@ -406,7 +405,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) @@ -2510,26 +2509,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 @@ -2576,30 +2568,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); + } } } @@ -2634,7 +2633,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 7cd2b247e..880aae529 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 8c4e2ac1c..ddaaff55a 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 ca4f5fd73..24ba3b299 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/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt index b923fd02f..006de1e71 100644 --- a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt +++ b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt @@ -236,12 +236,13 @@ COGL_PREMULT_BIT
cogl-poll -Main loop integeration +Main loop integration 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
diff --git a/examples/cogl-crate.c b/examples/cogl-crate.c index 47de34d04..cdd6a7cf1 100644 --- a/examples/cogl-crate.c +++ b/examples/cogl-crate.c @@ -274,6 +274,7 @@ main (int argc, char **argv) &data, NULL); /* destroy notify */ + while (1) { CoglPollFD *poll_fds; @@ -286,12 +287,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 4a388bc7d..49e395e37 100644 --- a/examples/cogl-msaa.c +++ b/examples/cogl-msaa.c @@ -105,9 +105,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 e9ac93d96..1622266c6 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);