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

(cherry picked from commit 667e58c9cb2662aef5f44e580a9eda42dc8d0176)
This commit is contained in:
Robert Bragg 2013-04-16 23:46:03 +01:00
parent 816a5bc437
commit ed90c6fed9
29 changed files with 489 additions and 285 deletions

View File

@ -416,6 +416,7 @@ cogl_sources_c = \
$(srcdir)/cogl-boxed-value.c \ $(srcdir)/cogl-boxed-value.c \
$(srcdir)/cogl-snippet-private.h \ $(srcdir)/cogl-snippet-private.h \
$(srcdir)/cogl-snippet.c \ $(srcdir)/cogl-snippet.c \
$(srcdir)/cogl-poll-private.h \
$(srcdir)/cogl-poll.c \ $(srcdir)/cogl-poll.c \
$(srcdir)/gl-prototypes/cogl-all-functions.h \ $(srcdir)/gl-prototypes/cogl-all-functions.h \
$(srcdir)/gl-prototypes/cogl-gles1-functions.h \ $(srcdir)/gl-prototypes/cogl-gles1-functions.h \

View File

@ -206,6 +206,18 @@ cogl_context_new (CoglDisplay *display,
context->display = 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 /* This is duplicated data, but it's much more convenient to have
the driver attached to the context and the value is accessed a the driver attached to the context and the value is accessed a
lot throughout Cogl */ lot throughout Cogl */
@ -607,6 +619,12 @@ cogl_context_get_display (CoglContext *context)
return context->display; return context->display;
} }
CoglRenderer *
cogl_context_get_renderer (CoglContext *context)
{
return context->display->renderer;
}
#ifdef COGL_HAS_EGL_SUPPORT #ifdef COGL_HAS_EGL_SUPPORT
EGLDisplay EGLDisplay
cogl_egl_context_get_egl_display (CoglContext *context) cogl_egl_context_get_egl_display (CoglContext *context)

View File

@ -125,6 +125,25 @@ cogl_context_new (CoglDisplay *display,
CoglDisplay * CoglDisplay *
cogl_context_get_display (CoglContext *context); 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 #ifdef COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT
/** /**
* cogl_android_set_native_window: * cogl_android_set_native_window:

View File

@ -32,31 +32,14 @@ typedef struct _CoglGLibSource
{ {
GSource source; GSource source;
CoglContext *context; CoglRenderer *renderer;
GArray *poll_fds; GArray *poll_fds;
int poll_fds_age;
int64_t expiration_time; int64_t expiration_time;
} CoglGLibSource; } 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 static CoglBool
cogl_glib_source_prepare (GSource *source, int *timeout) cogl_glib_source_prepare (GSource *source, int *timeout)
{ {
@ -64,18 +47,19 @@ cogl_glib_source_prepare (GSource *source, int *timeout)
CoglPollFD *poll_fds; CoglPollFD *poll_fds;
int n_poll_fds; int n_poll_fds;
int64_t cogl_timeout; int64_t cogl_timeout;
int age;
int i; int i;
cogl_poll_get_info (cogl_source->context, age = cogl_poll_renderer_get_info (cogl_source->renderer,
&poll_fds, &poll_fds,
&n_poll_fds, &n_poll_fds,
&cogl_timeout); &cogl_timeout);
/* We have to be careful not to call g_source_add/remove_poll unless /* 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 * the FDs have changed because it will cause the main loop to
immediately wake up. If we call it every time the source is * immediately wake up. If we call it every time the source is
prepared it will effectively never go idle. */ * prepared it will effectively never go idle. */
if (cogl_glib_source_poll_fds_changed (cogl_source, poll_fds, n_poll_fds)) if (age != cogl_source->poll_fds_age)
{ {
/* Remove any existing polls before adding the new ones */ /* Remove any existing polls before adding the new ones */
for (i = 0; i < cogl_source->poll_fds->len; i++) 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 */ /* Update the events */
for (i = 0; i < n_poll_fds; i++) for (i = 0; i < n_poll_fds; i++)
{ {
@ -147,9 +133,9 @@ cogl_glib_source_dispatch (GSource *source,
CoglPollFD *poll_fds = CoglPollFD *poll_fds =
(CoglPollFD *) &g_array_index (cogl_source->poll_fds, GPollFD, 0); (CoglPollFD *) &g_array_index (cogl_source->poll_fds, GPollFD, 0);
cogl_poll_dispatch (cogl_source->context, cogl_poll_renderer_dispatch (cogl_source->renderer,
poll_fds, poll_fds,
cogl_source->poll_fds->len); cogl_source->poll_fds->len);
return TRUE; return TRUE;
} }
@ -172,8 +158,8 @@ cogl_glib_source_funcs =
}; };
GSource * GSource *
cogl_glib_source_new (CoglContext *context, cogl_glib_renderer_source_new (CoglRenderer *renderer,
int priority) int priority)
{ {
GSource *source; GSource *source;
CoglGLibSource *cogl_source; CoglGLibSource *cogl_source;
@ -182,7 +168,7 @@ cogl_glib_source_new (CoglContext *context,
sizeof (CoglGLibSource)); sizeof (CoglGLibSource));
cogl_source = (CoglGLibSource *) source; cogl_source = (CoglGLibSource *) source;
cogl_source->context = context; cogl_source->renderer = renderer;
cogl_source->poll_fds = g_array_new (FALSE, FALSE, sizeof (GPollFD)); cogl_source->poll_fds = g_array_new (FALSE, FALSE, sizeof (GPollFD));
if (priority != G_PRIORITY_DEFAULT) if (priority != G_PRIORITY_DEFAULT)
@ -190,3 +176,13 @@ cogl_glib_source_new (CoglContext *context,
return source; return source;
} }
GSource *
cogl_glib_source_new (CoglContext *context,
int priority)
{
return cogl_glib_renderer_source_new (cogl_context_get_renderer (context),
priority);
}

View File

@ -40,11 +40,21 @@ G_BEGIN_DECLS
* *
* Creates a #GSource which handles Cogl's internal system event * Creates a #GSource which handles Cogl's internal system event
* processing. This can be used as a convenience instead of * processing. This can be used as a convenience instead of
* cogl_poll_get_info() and cogl_poll_dispatch() in applications that * cogl_poll_renderer_get_info() and cogl_poll_renderer_dispatch() in
* are already using the GLib main loop. After this is called the * applications that are already using the GLib main loop. After this
* #GSource should be attached to the main loop using * is called the #GSource should be attached to the main loop using
* g_source_attach(). * 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 * Return value: a new #GSource
* *
* Stability: unstable * Stability: unstable
@ -54,6 +64,27 @@ GSource *
cogl_glib_source_new (CoglContext *context, cogl_glib_source_new (CoglContext *context,
int priority); 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 G_END_DECLS
#endif /* __COGL_GSOURCE_H__ */ #endif /* __COGL_GSOURCE_H__ */

View File

@ -50,9 +50,6 @@ typedef struct _CoglGLXDisplay
GLXContext glx_context; GLXContext glx_context;
GLXWindow dummy_glxwin; GLXWindow dummy_glxwin;
Window dummy_xwin; Window dummy_xwin;
CoglBool pending_sync_notify;
CoglBool pending_complete_notify;
CoglBool pending_resize_notify;
} CoglGLXDisplay; } CoglGLXDisplay;
#endif /* __COGL_DISPLAY_GLX_PRIVATE_H */ #endif /* __COGL_DISPLAY_GLX_PRIVATE_H */

View File

@ -54,6 +54,13 @@ typedef struct _CoglGLXRenderer
/* GModule pointing to libGL which we use to get glX functions out of */ /* GModule pointing to libGL which we use to get glX functions out of */
GModule *libgl_module; 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 /* Copy of the winsys features that are based purely on the
* information we can get without using a GL context. We want to * 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 * determine this before we have a context so that we can use the

View File

@ -667,8 +667,8 @@ cogl_onscreen_get_resizable (CoglOnscreen *onscreen);
* *
* <note>A resize callback will only ever be called while dispatching * <note>A resize callback will only ever be called while dispatching
* Cogl events from the system mainloop; so for example during * Cogl events from the system mainloop; so for example during
* cogl_poll_dispatch(). This is so that callbacks shouldn't occur * cogl_poll_renderer_dispatch(). This is so that callbacks shouldn't
* while an application might have arbitrary locks held for * occur while an application might have arbitrary locks held for
* example.</note> * example.</note>
* *
* Since: 2.0 * Since: 2.0
@ -716,8 +716,8 @@ typedef struct _CoglOnscreenResizeClosure CoglOnscreenResizeClosure;
* *
* <note>A resize callback will only ever be called while dispatching * <note>A resize callback will only ever be called while dispatching
* Cogl events from the system mainloop; so for example during * Cogl events from the system mainloop; so for example during
* cogl_poll_dispatch(). This is so that callbacks shouldn't occur * cogl_poll_renderer_dispatch(). This is so that callbacks shouldn't
* while an application might have arbitrary locks held for * occur while an application might have arbitrary locks held for
* example.</note> * example.</note>
* *
* Return value: a #CoglOnscreenResizeClosure pointer that can be used to * Return value: a #CoglOnscreenResizeClosure pointer that can be used to

36
cogl/cogl-poll-private.h Normal file
View File

@ -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__ */

View File

@ -28,57 +28,116 @@
#endif #endif
#include "cogl-poll.h" #include "cogl-poll.h"
#include "cogl-poll-private.h"
#include "cogl-winsys-private.h" #include "cogl-winsys-private.h"
#include "cogl-renderer-private.h"
#include "cogl-context-private.h" #include "cogl-context-private.h"
void int
cogl_poll_get_info (CoglContext *context, cogl_poll_renderer_get_info (CoglRenderer *renderer,
CoglPollFD **poll_fds, CoglPollFD **poll_fds,
int *n_poll_fds, int *n_poll_fds,
int64_t *timeout) int64_t *timeout)
{ {
const CoglWinsysVtable *winsys; const CoglWinsysVtable *winsys;
_COGL_RETURN_IF_FAIL (cogl_is_context (context)); _COGL_RETURN_VAL_IF_FAIL (cogl_is_renderer (renderer), 0);
_COGL_RETURN_IF_FAIL (poll_fds != NULL); _COGL_RETURN_VAL_IF_FAIL (poll_fds != NULL, 0);
_COGL_RETURN_IF_FAIL (n_poll_fds != NULL); _COGL_RETURN_VAL_IF_FAIL (n_poll_fds != NULL, 0);
_COGL_RETURN_IF_FAIL (timeout != NULL); _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, if (!COGL_TAILQ_EMPTY (&renderer->context->onscreen_events_queue))
poll_fds, {
n_poll_fds, *timeout = 0;
timeout); return renderer->poll_fds_age;
}
} }
winsys = renderer->winsys_vtable;
if (winsys->get_dispatch_timeout)
*timeout = winsys->get_dispatch_timeout (renderer);
else else
{ *timeout = -1;
/* By default we'll assume Cogl doesn't need to block on anything */
*poll_fds = NULL;
*n_poll_fds = 0;
*timeout = -1; /* no timeout */
}
if (!COGL_TAILQ_EMPTY (&context->onscreen_events_queue)) return renderer->poll_fds_age;
*timeout = 0;
} }
void void
cogl_poll_dispatch (CoglContext *context, cogl_poll_renderer_dispatch (CoglRenderer *renderer,
const CoglPollFD *poll_fds, const CoglPollFD *poll_fds,
int n_poll_fds) int n_poll_fds)
{ {
const CoglWinsysVtable *winsys; 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)) /* FIXME: arbitrary cogl components should just be able to queue
_cogl_dispatch_onscreen_events (context); * 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) 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++;
} }

View File

@ -104,19 +104,23 @@ typedef struct {
} CoglPollFD; } CoglPollFD;
/** /**
* cogl_poll_get_info: * cogl_poll_renderer_get_info:
* @context: A #CoglContext * @renderer: A #CoglRenderer
* @poll_fds: A return location for a pointer to an array * @poll_fds: A return location for a pointer to an array
* of #CoglPollFD<!-- -->s * of #CoglPollFD<!-- -->s
* @n_poll_fds: A return location for the number of entries in *@poll_fds * @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 * @timeout: A return location for the maximum length of time to wait
* in microseconds, or -1 to wait indefinitely. * in microseconds, or -1 to wait indefinitely.
* *
* This should be called whenever an application is about to go idle * Is used to integrate Cogl with an application mainloop that is based
* so that Cogl has a chance to describe what state it needs to be * on the unix poll(2) api (or select() or something equivalent). This
* woken up on. The assumption is that the application is using a main * api should be called whenever an application is about to go idle so
* loop with something like the poll function call on Unix or the GLib * that Cogl has a chance to describe what file descriptor events it
* main loop. * 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 * After the function is called *@poll_fds will contain a pointer to
* an array of #CoglPollFD structs describing the file descriptors * 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 * accordingly. After the application has completed its idle it is
* expected to either update the revents members directly in this * expected to either update the revents members directly in this
* array or to create a copy of the array and update them * 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 * there.
* Cogl when calling cogl_poll_dispatch(). *
* 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 * When using the %COGL_WINSYS_ID_WGL winsys (where file descriptors
* don't make any sense) or %COGL_WINSYS_ID_SDL (where the event * 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 * @timeout will contain a maximum amount of time to wait in
* microseconds before the application should wake up or -1 if the * 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. * 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 * Stability: unstable
* Since: 1.10 * Since: 1.16
*/ */
void int
cogl_poll_get_info (CoglContext *context, cogl_poll_renderer_get_info (CoglRenderer *renderer,
CoglPollFD **poll_fds, CoglPollFD **poll_fds,
int *n_poll_fds, int *n_poll_fds,
int64_t *timeout); int64_t *timeout);
/** /**
* cogl_poll_dispatch: * cogl_poll_renderer_dispatch:
* @context: A #CoglContext * @renderer: A #CoglRenderer
* @poll_fds: An array of #CoglPollFD<!-- -->s describing the events * @poll_fds: An array of #CoglPollFD<!-- -->s describing the events
* that have occurred since the application went idle. * that have occurred since the application went idle.
* @n_poll_fds: The length of the @poll_fds array. * @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 * going idle in its main loop. The @poll_fds array should contain a
* list of file descriptors matched with the events that occurred in * list of file descriptors matched with the events that occurred in
* revents. The events field is ignored. It is safe to pass in extra * revents. The events field is ignored. It is safe to pass in extra
* file descriptors that Cogl didn't request from * file descriptors that Cogl didn't request when calling
* cogl_context_begin_idle() or a shorter array missing some file * cogl_poll_renderer_get_info() or a shorter array missing some file
* descriptors that Cogl requested. * 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 * Stability: unstable
* Since: 1.10 * Since: 1.16
*/ */
void void
cogl_poll_dispatch (CoglContext *context, cogl_poll_renderer_dispatch (CoglRenderer *renderer,
const CoglPollFD *poll_fds, const CoglPollFD *poll_fds,
int n_poll_fds); int n_poll_fds);
COGL_END_DECLS COGL_END_DECLS

View File

@ -30,6 +30,7 @@
#include "cogl-winsys-private.h" #include "cogl-winsys-private.h"
#include "cogl-driver.h" #include "cogl-driver.h"
#include "cogl-texture-driver.h" #include "cogl-texture-driver.h"
#include "cogl-context.h"
#ifdef COGL_HAS_XLIB_SUPPORT #ifdef COGL_HAS_XLIB_SUPPORT
#include <X11/Xlib.h> #include <X11/Xlib.h>
@ -50,6 +51,24 @@ struct _CoglRenderer
CoglWinsysID winsys_id_override; CoglWinsysID winsys_id_override;
GList *constraints; 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; GList *outputs;
#ifdef COGL_HAS_XLIB_SUPPORT #ifdef COGL_HAS_XLIB_SUPPORT

View File

@ -168,6 +168,8 @@ _cogl_renderer_free (CoglRenderer *renderer)
NULL); NULL);
g_slist_free (renderer->event_filters); g_slist_free (renderer->event_filters);
g_array_free (renderer->poll_fds, TRUE);
g_free (renderer); g_free (renderer);
} }
@ -181,6 +183,8 @@ cogl_renderer_new (void)
renderer->connected = FALSE; renderer->connected = FALSE;
renderer->event_filters = NULL; renderer->event_filters = NULL;
renderer->poll_fds = g_array_new (FALSE, TRUE, sizeof (CoglPollFD));
#ifdef COGL_HAS_XLIB_SUPPORT #ifdef COGL_HAS_XLIB_SUPPORT
renderer->xlib_enable_event_retrieval = TRUE; renderer->xlib_enable_event_retrieval = TRUE;
#endif #endif

View File

@ -69,15 +69,18 @@ void
cogl_sdl_handle_event (CoglContext *context, SDL_Event *event) cogl_sdl_handle_event (CoglContext *context, SDL_Event *event)
{ {
const CoglWinsysVtable *winsys; const CoglWinsysVtable *winsys;
CoglRenderer *renderer;
_COGL_RETURN_IF_FAIL (cogl_is_context (context)); _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) if (winsys->poll_dispatch)
winsys->poll_dispatch (context, NULL, 0); winsys->poll_dispatch (renderer, NULL, 0);
} }
static void static void

View File

@ -40,9 +40,6 @@ typedef struct _CoglXlibRenderer
these is expected to be allocated on the stack by the caller */ these is expected to be allocated on the stack by the caller */
CoglXlibTrapState *trap_state; CoglXlibTrapState *trap_state;
/* A poll FD for handling event retrieval within Cogl */
CoglPollFD poll_fd;
unsigned long outputs_update_serial; unsigned long outputs_update_serial;
} CoglXlibRenderer; } CoglXlibRenderer;
@ -84,11 +81,8 @@ _cogl_xlib_renderer_untrap_errors (CoglRenderer *renderer,
CoglXlibRenderer * CoglXlibRenderer *
_cogl_xlib_renderer_get_data (CoglRenderer *renderer); _cogl_xlib_renderer_get_data (CoglRenderer *renderer);
void int64_t
_cogl_xlib_renderer_poll_get_info (CoglRenderer *renderer, _cogl_xlib_renderer_get_dispatch_timeout (CoglRenderer *renderer);
CoglPollFD **poll_fds,
int *n_poll_fds,
int64_t *timeout);
void void
_cogl_xlib_renderer_poll_dispatch (CoglRenderer *renderer, _cogl_xlib_renderer_poll_dispatch (CoglRenderer *renderer,

View File

@ -38,6 +38,7 @@
#include "cogl-x11-renderer-private.h" #include "cogl-x11-renderer-private.h"
#include "cogl-winsys-private.h" #include "cogl-winsys-private.h"
#include "cogl-error-private.h" #include "cogl-error-private.h"
#include "cogl-poll-private.h"
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/extensions/Xdamage.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->trap_state = NULL;
xlib_renderer->poll_fd.fd = ConnectionNumber (xlib_renderer->xdpy); if (renderer->xlib_enable_event_retrieval)
xlib_renderer->poll_fd.events = COGL_POLL_FD_EVENT_IN; {
_cogl_poll_renderer_add_fd (renderer,
ConnectionNumber (xlib_renderer->xdpy),
COGL_POLL_FD_EVENT_IN);
}
XRRSelectInput(xlib_renderer->xdpy, XRRSelectInput(xlib_renderer->xdpy,
DefaultRootWindow (xlib_renderer->xdpy), DefaultRootWindow (xlib_renderer->xdpy),
@ -568,29 +573,20 @@ cogl_xlib_renderer_remove_filter (CoglRenderer *renderer,
(CoglNativeFilterFunc)func, data); (CoglNativeFilterFunc)func, data);
} }
void int64_t
_cogl_xlib_renderer_poll_get_info (CoglRenderer *renderer, _cogl_xlib_renderer_get_dispatch_timeout (CoglRenderer *renderer)
CoglPollFD **poll_fds,
int *n_poll_fds,
int64_t *timeout)
{ {
CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer); CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer);
if (renderer->xlib_enable_event_retrieval) if (renderer->xlib_enable_event_retrieval)
{ {
*n_poll_fds = 1;
*poll_fds = &xlib_renderer->poll_fd;
if (XPending (xlib_renderer->xdpy)) if (XPending (xlib_renderer->xdpy))
*timeout = 0; return 0;
else else
*timeout = -1; return -1;
} }
else else
{ return -1;
*n_poll_fds = 0;
*poll_fds = NULL;
*timeout = -1;
}
} }
void void

View File

@ -650,8 +650,8 @@ cogl_pixel_buffer_set_region
#endif #endif
cogl_pixel_format_get_type cogl_pixel_format_get_type
cogl_poll_dispatch cogl_poll_renderer_get_info
cogl_poll_get_info cogl_poll_renderer_dispatch
cogl_polygon cogl_polygon

View File

@ -53,6 +53,7 @@
#include "cogl-kms-display.h" #include "cogl-kms-display.h"
#include "cogl-version.h" #include "cogl-version.h"
#include "cogl-error-private.h" #include "cogl-error-private.h"
#include "cogl-poll-private.h"
static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable; static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable;
@ -62,7 +63,8 @@ typedef struct _CoglRendererKMS
{ {
int fd; int fd;
struct gbm_device *gbm; struct gbm_device *gbm;
CoglPollFD poll_fd;
CoglBool pending_swap_notify;
} CoglRendererKMS; } CoglRendererKMS;
typedef struct _CoglOutputKMS typedef struct _CoglOutputKMS
@ -80,7 +82,6 @@ typedef struct _CoglDisplayKMS
GList *outputs; GList *outputs;
int width, height; int width, height;
CoglBool pending_set_crtc; CoglBool pending_set_crtc;
CoglBool pending_swap_notify;
struct gbm_surface *dummy_gbm_surface; struct gbm_surface *dummy_gbm_surface;
} CoglDisplayKMS; } CoglDisplayKMS;
@ -159,8 +160,9 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
if (!_cogl_winsys_egl_renderer_connect_common (renderer, error)) if (!_cogl_winsys_egl_renderer_connect_common (renderer, error))
goto egl_terminate; goto egl_terminate;
kms_renderer->poll_fd.fd = kms_renderer->fd; _cogl_poll_renderer_add_fd (renderer,
kms_renderer->poll_fd.events = COGL_POLL_FD_EVENT_IN; kms_renderer->fd,
COGL_POLL_FD_EVENT_IN);
return TRUE; return TRUE;
@ -609,23 +611,25 @@ page_flip_handler (int fd,
void *data) void *data)
{ {
CoglFlipKMS *flip = 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 /* We're only ready to dispatch a swap notification once all outputs
* have flipped... */ * have flipped... */
flip->pending--; flip->pending--;
if (flip->pending == 0) if (flip->pending == 0)
{ {
/* We only want to notify that the swap is complete when the application CoglOnscreen *onscreen = flip->onscreen;
* calls cogl_context_dispatch so instead of immediately notifying we'll CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
* set a flag to remember to notify later */ CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
kms_display->pending_swap_notify = TRUE; 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; kms_onscreen->pending_swap_notify = TRUE;
free_current_bo (onscreen); free_current_bo (onscreen);
@ -863,25 +867,15 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
onscreen->winsys = NULL; onscreen->winsys = NULL;
} }
static void static int64_t
_cogl_winsys_poll_get_info (CoglContext *context, _cogl_winsys_get_dispatch_timeout (CoglRenderer *renderer)
CoglPollFD **poll_fds,
int *n_poll_fds,
int64_t *timeout)
{ {
CoglDisplay *display = context->display;
CoglDisplayEGL *egl_display = display->winsys;
CoglDisplayKMS *kms_display = egl_display->platform;
CoglRenderer *renderer = display->renderer;
CoglRendererEGL *egl_renderer = renderer->winsys; CoglRendererEGL *egl_renderer = renderer->winsys;
CoglRendererKMS *kms_renderer = egl_renderer->platform; 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 /* If we've already got a pending swap notify then we'll dispatch
immediately */ * immediately */
*timeout = kms_display->pending_swap_notify ? 0 : -1; return kms_renderer->pending_swap_notify ? 0 : -1;
} }
static void static void
@ -910,14 +904,10 @@ flush_pending_swap_notify_cb (void *data,
} }
static void static void
_cogl_winsys_poll_dispatch (CoglContext *context, _cogl_winsys_poll_dispatch (CoglRenderer *renderer,
const CoglPollFD *poll_fds, const CoglPollFD *poll_fds,
int n_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; CoglRendererEGL *egl_renderer = renderer->winsys;
CoglRendererKMS *kms_renderer = egl_renderer->platform; CoglRendererKMS *kms_renderer = egl_renderer->platform;
int i; int i;
@ -931,12 +921,21 @@ _cogl_winsys_poll_dispatch (CoglContext *context,
break; 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, g_list_foreach (context->framebuffers,
flush_pending_swap_notify_cb, flush_pending_swap_notify_cb,
NULL); 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_region = NULL;
vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers; 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.poll_dispatch = _cogl_winsys_poll_dispatch;
vtable_inited = TRUE; vtable_inited = TRUE;

View File

@ -82,6 +82,8 @@ typedef struct _CoglRendererEGL
EGLint egl_version_major; EGLint egl_version_major;
EGLint egl_version_minor; EGLint egl_version_minor;
CoglBool pending_resize_notify;
/* Data specific to the EGL platform */ /* Data specific to the EGL platform */
void *platform; void *platform;
/* vtable for platform specific parts */ /* vtable for platform specific parts */
@ -115,8 +117,6 @@ typedef struct _CoglDisplayEGL
EGLSurface current_draw_surface; EGLSurface current_draw_surface;
EGLContext current_context; EGLContext current_context;
CoglBool pending_resize_notify;
/* Platform specific display data */ /* Platform specific display data */
void *platform; void *platform;
} CoglDisplayEGL; } CoglDisplayEGL;

View File

@ -601,29 +601,17 @@ cogl_wayland_onscreen_resize (CoglOnscreen *onscreen,
_cogl_framebuffer_winsys_update_size (fb, width, height); _cogl_framebuffer_winsys_update_size (fb, width, height);
} }
static void static int64_t
_cogl_winsys_poll_get_info (CoglContext *context, _cogl_winsys_get_dispatch_timeout (CoglRenderer *renderer)
CoglPollFD **poll_fds,
int *n_poll_fds,
int64_t *timeout)
{ {
CoglDisplay *display = context->display; return -1;
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;
} }
static void static void
_cogl_winsys_poll_dispatch (CoglContext *context, _cogl_winsys_poll_dispatch (CoglRenderer *renderer,
const CoglPollFD *poll_fds, const CoglPollFD *poll_fds,
int n_poll_fds) int n_poll_fds)
{ {
CoglDisplay *display = context->display;
CoglRenderer *renderer = display->renderer;
CoglRendererEGL *egl_renderer = renderer->winsys; CoglRendererEGL *egl_renderer = renderer->winsys;
CoglRendererWayland *wayland_renderer = egl_renderer->platform; CoglRendererWayland *wayland_renderer = egl_renderer->platform;
int i; int i;
@ -671,7 +659,7 @@ _cogl_winsys_egl_wayland_get_vtable (void)
vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers; 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.poll_dispatch = _cogl_winsys_poll_dispatch;
vtable_inited = TRUE; vtable_inited = TRUE;

View File

@ -96,11 +96,11 @@ notify_resize (CoglContext *context,
int width, int width,
int height) int height)
{ {
CoglRenderer *renderer = context->display->renderer;
CoglRendererEGL *egl_renderer = renderer->winsys;
CoglOnscreen *onscreen = find_onscreen_for_xid (context, drawable); CoglOnscreen *onscreen = find_onscreen_for_xid (context, drawable);
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
CoglDisplay *display = context->display;
CoglDisplayEGL *egl_display = display->winsys;
CoglOnscreenEGL *egl_onscreen;
if (!onscreen) if (!onscreen)
return; return;
@ -110,9 +110,9 @@ notify_resize (CoglContext *context,
_cogl_framebuffer_winsys_update_size (framebuffer, width, height); _cogl_framebuffer_winsys_update_size (framebuffer, width, height);
/* We only want to notify that a resize happened when the /* We only want to notify that a resize happened when the
application calls cogl_context_dispatch so instead of immediately * application calls cogl_context_dispatch so instead of immediately
notifying we'll set a flag to remember to notify later */ * notifying we'll set a flag to remember to notify later */
egl_display->pending_resize_notify = TRUE; egl_renderer->pending_resize_notify = TRUE;
egl_onscreen->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); return get_visual_info (ctx->display, egl_display->egl_config);
} }
static void static int64_t
_cogl_winsys_poll_get_info (CoglContext *context, _cogl_winsys_get_dispatch_timeout (CoglRenderer *renderer)
CoglPollFD **poll_fds,
int *n_poll_fds,
int64_t *timeout)
{ {
CoglDisplay *display = context->display; CoglRendererEGL *egl_renderer = renderer->winsys;
CoglDisplayEGL *egl_display = display->winsys;
_cogl_xlib_renderer_poll_get_info (context->display->renderer, if (egl_renderer->pending_resize_notify)
poll_fds, return 0;
n_poll_fds,
timeout);
if (egl_display->pending_resize_notify) return _cogl_xlib_renderer_get_dispatch_timeout (renderer);
*timeout = 0;
} }
static void static void
@ -661,23 +654,31 @@ flush_pending_notifications_cb (void *data,
} }
static void static void
_cogl_winsys_poll_dispatch (CoglContext *context, _cogl_winsys_poll_dispatch (CoglRenderer *renderer,
const CoglPollFD *poll_fds, const CoglPollFD *poll_fds,
int n_poll_fds) int n_poll_fds)
{ {
CoglDisplay *display = context->display; CoglRendererEGL *egl_renderer = renderer->winsys;
CoglDisplayEGL *egl_display = display->winsys;
_cogl_xlib_renderer_poll_dispatch (context->display->renderer, _cogl_xlib_renderer_poll_dispatch (renderer,
poll_fds, poll_fds,
n_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, g_list_foreach (context->framebuffers,
flush_pending_notifications_cb, flush_pending_notifications_cb,
NULL); 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.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; vtable.poll_dispatch = _cogl_winsys_poll_dispatch;
#ifdef EGL_KHR_image_pixmap #ifdef EGL_KHR_image_pixmap

View File

@ -308,9 +308,9 @@ set_sync_pending (CoglOnscreen *onscreen)
{ {
CoglOnscreenGLX *glx_onscreen = onscreen->winsys; CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; 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; glx_onscreen->pending_sync_notify = TRUE;
} }
@ -319,9 +319,9 @@ set_complete_pending (CoglOnscreen *onscreen)
{ {
CoglOnscreenGLX *glx_onscreen = onscreen->winsys; CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; 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; glx_onscreen->pending_complete_notify = TRUE;
} }
@ -388,8 +388,7 @@ notify_resize (CoglContext *context,
CoglOnscreen *onscreen = find_onscreen_for_xid (context, CoglOnscreen *onscreen = find_onscreen_for_xid (context,
configure_event->window); configure_event->window);
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
CoglDisplay *display = context->display; CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
CoglGLXDisplay *glx_display = display->winsys;
CoglOnscreenGLX *glx_onscreen; CoglOnscreenGLX *glx_onscreen;
CoglOnscreenXlib *xlib_onscreen; CoglOnscreenXlib *xlib_onscreen;
@ -406,7 +405,7 @@ notify_resize (CoglContext *context,
/* We only want to notify that a resize happened when the /* We only want to notify that a resize happened when the
application calls cogl_context_dispatch so instead of immediately application calls cogl_context_dispatch so instead of immediately
notifying we'll set a flag to remember to notify later */ 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; glx_onscreen->pending_resize_notify = TRUE;
if (!xlib_onscreen->is_foreign_xwin) 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; return glx_tex_pixmap->glx_tex;
} }
static void static int64_t
_cogl_winsys_poll_get_info (CoglContext *context, _cogl_winsys_get_dispatch_timeout (CoglRenderer *renderer)
CoglPollFD **poll_fds,
int *n_poll_fds,
int64_t *timeout)
{ {
CoglDisplay *display = context->display; CoglGLXRenderer *glx_renderer = renderer->winsys;
CoglGLXDisplay *glx_display = display->winsys;
_cogl_xlib_renderer_poll_get_info (context->display->renderer,
poll_fds,
n_poll_fds,
timeout);
/* If we've already got a pending swap notify then we'll dispatch /* If we've already got a pending swap notify then we'll dispatch
immediately */ * immediately */
if (glx_display->pending_sync_notify || if (glx_renderer->pending_sync_notify ||
glx_display->pending_resize_notify || glx_renderer->pending_resize_notify ||
glx_display->pending_complete_notify) glx_renderer->pending_complete_notify)
*timeout = 0; return 0;
return _cogl_xlib_renderer_get_dispatch_timeout (renderer);
} }
static void static void
@ -2576,30 +2568,37 @@ flush_pending_notifications_cb (void *data,
} }
static void static void
_cogl_winsys_poll_dispatch (CoglContext *context, _cogl_winsys_poll_dispatch (CoglRenderer *renderer,
const CoglPollFD *poll_fds, const CoglPollFD *poll_fds,
int n_poll_fds) int n_poll_fds)
{ {
CoglDisplay *display = context->display; CoglGLXRenderer *glx_renderer = renderer->winsys;
CoglGLXDisplay *glx_display = display->winsys;
_cogl_xlib_renderer_poll_dispatch (context->display->renderer, _cogl_xlib_renderer_poll_dispatch (renderer,
poll_fds, poll_fds,
n_poll_fds); n_poll_fds);
if (glx_display->pending_sync_notify || /* FIXME: instead of requiring event dispatching which is handled at
glx_display->pending_resize_notify || * the CoglRenderer level to have to know about CoglContext we
glx_display->pending_complete_notify) * should have a generalized way of queuing an idle function */
if (renderer->context)
{ {
/* These need to be cleared before invoking the callbacks in CoglContext *context = renderer->context;
* 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;
g_list_foreach (context->framebuffers, if (glx_renderer->pending_sync_notify ||
flush_pending_notifications_cb, glx_renderer->pending_resize_notify ||
NULL); 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 = .onscreen_set_resizable =
_cogl_winsys_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, .poll_dispatch = _cogl_winsys_poll_dispatch,
/* X11 tfp support... */ /* X11 tfp support... */

View File

@ -154,13 +154,11 @@ typedef struct _CoglWinsysVtable
(*onscreen_win32_get_window) (CoglOnscreen *onscreen); (*onscreen_win32_get_window) (CoglOnscreen *onscreen);
#endif #endif
int64_t
(*get_dispatch_timeout) (CoglRenderer *renderer);
void void
(*poll_get_info) (CoglContext *context, (*poll_dispatch) (CoglRenderer *renderer,
CoglPollFD **poll_fds,
int *n_poll_fds,
int64_t *timeout);
void
(*poll_dispatch) (CoglContext *context,
const CoglPollFD *poll_fds, const CoglPollFD *poll_fds,
int n_poll_fds); int n_poll_fds);

View File

@ -41,7 +41,7 @@
typedef struct _CoglRendererSdl typedef struct _CoglRendererSdl
{ {
int stub; CoglBool pending_resize_notify;
} CoglRendererSdl; } CoglRendererSdl;
typedef struct _CoglDisplaySdl typedef struct _CoglDisplaySdl
@ -49,7 +49,6 @@ typedef struct _CoglDisplaySdl
SDL_Surface *surface; SDL_Surface *surface;
CoglOnscreen *onscreen; CoglOnscreen *onscreen;
Uint32 video_mode_flags; Uint32 video_mode_flags;
CoglBool pending_resize_notify;
} CoglDisplaySdl; } CoglDisplaySdl;
static CoglFuncPtr static CoglFuncPtr
@ -218,6 +217,7 @@ sdl_event_filter_cb (SDL_Event *event, void *data)
CoglContext *context = data; CoglContext *context = data;
CoglDisplay *display = context->display; CoglDisplay *display = context->display;
CoglDisplaySdl *sdl_display = display->winsys; CoglDisplaySdl *sdl_display = display->winsys;
CoglRendererSdl *sdl_renderer = display->renderer->winsys;
float width = event->resize.w; float width = event->resize.w;
float height = event->resize.h; float height = event->resize.h;
CoglFramebuffer *framebuffer; CoglFramebuffer *framebuffer;
@ -233,9 +233,10 @@ sdl_event_filter_cb (SDL_Event *event, void *data)
_cogl_framebuffer_winsys_update_size (framebuffer, width, height); _cogl_framebuffer_winsys_update_size (framebuffer, width, height);
/* We only want to notify that a resize happened when the /* We only want to notify that a resize happened when the
application calls cogl_context_dispatch so instead of immediately * application calls cogl_context_dispatch so instead of
notifying we'll set a flag to remember to notify later */ * immediately notifying we'll set a flag to remember to notify
sdl_display->pending_resize_notify = TRUE; * later */
sdl_renderer->pending_resize_notify = TRUE;
return COGL_FILTER_CONTINUE; return COGL_FILTER_CONTINUE;
} }
@ -378,22 +379,27 @@ _cogl_winsys_onscreen_set_resizable (CoglOnscreen *onscreen,
} }
static void static void
_cogl_winsys_poll_dispatch (CoglContext *context, _cogl_winsys_poll_dispatch (CoglRenderer *renderer,
const CoglPollFD *poll_fds, const CoglPollFD *poll_fds,
int n_poll_fds) int n_poll_fds)
{ {
CoglDisplay *display = context->display; CoglRendererSdl *sdl_renderer = renderer->winsys;
CoglDisplaySdl *sdl_display = display->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; CoglOnscreen *onscreen = sdl_display->onscreen;
g_return_if_fail (onscreen != NULL); g_return_if_fail (onscreen != NULL);
_cogl_onscreen_notify_resize (onscreen); _cogl_onscreen_notify_resize (onscreen);
sdl_display->pending_resize_notify = FALSE; sdl_renderer->pending_resize_notify = FALSE;
} }
} }

View File

@ -47,14 +47,13 @@ typedef struct _CoglContextSdl2
typedef struct _CoglRendererSdl2 typedef struct _CoglRendererSdl2
{ {
int stub; CoglBool pending_resize_notify;
} CoglRendererSdl2; } CoglRendererSdl2;
typedef struct _CoglDisplaySdl2 typedef struct _CoglDisplaySdl2
{ {
SDL_Window *dummy_window; SDL_Window *dummy_window;
SDL_GLContext *context; SDL_GLContext *context;
CoglBool pending_resize_notify;
} CoglDisplaySdl2; } CoglDisplaySdl2;
typedef struct _CoglOnscreenSdl2 typedef struct _CoglOnscreenSdl2
@ -274,7 +273,7 @@ sdl_event_filter_cb (SDL_Event *event, void *data)
{ {
CoglContext *context = data; CoglContext *context = data;
CoglDisplay *display = context->display; CoglDisplay *display = context->display;
CoglDisplaySdl2 *sdl_display = display->winsys; CoglRendererSdl2 *sdl_renderer = display->renderer->winsys;
float width = event->window.data1; float width = event->window.data1;
float height = event->window.data2; float height = event->window.data2;
CoglFramebuffer *framebuffer; CoglFramebuffer *framebuffer;
@ -296,9 +295,10 @@ sdl_event_filter_cb (SDL_Event *event, void *data)
sdl_onscreen = COGL_ONSCREEN (framebuffer)->winsys; sdl_onscreen = COGL_ONSCREEN (framebuffer)->winsys;
/* We only want to notify that a resize happened when the /* We only want to notify that a resize happened when the
application calls cogl_context_dispatch so instead of immediately * application calls cogl_context_dispatch so instead of
notifying we'll set a flag to remember to notify later */ * immediately notifying we'll set a flag to remember to notify
sdl_display->pending_resize_notify = TRUE; * later */
sdl_renderer->pending_resize_notify = TRUE;
sdl_onscreen->pending_resize_notify = TRUE; sdl_onscreen->pending_resize_notify = TRUE;
return COGL_FILTER_CONTINUE; return COGL_FILTER_CONTINUE;
@ -506,19 +506,24 @@ flush_pending_notifications_cb (void *data,
} }
static void static void
_cogl_winsys_poll_dispatch (CoglContext *context, _cogl_winsys_poll_dispatch (CoglRenderer *renderer,
const CoglPollFD *poll_fds, const CoglPollFD *poll_fds,
int n_poll_fds) int n_poll_fds)
{ {
CoglDisplay *display = context->display; CoglRendererSdl2 *sdl_renderer = renderer->winsys;
CoglDisplaySdl2 *sdl_display = display->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, g_list_foreach (context->framebuffers,
flush_pending_notifications_cb, flush_pending_notifications_cb,
NULL); NULL);
sdl_display->pending_resize_notify = FALSE; sdl_renderer->pending_resize_notify = FALSE;
} }
} }

View File

@ -236,12 +236,13 @@ COGL_PREMULT_BIT
<SECTION> <SECTION>
<FILE>cogl-poll</FILE> <FILE>cogl-poll</FILE>
<TITLE>Main loop integeration</TITLE> <TITLE>Main loop integration</TITLE>
CoglPollFDEvent CoglPollFDEvent
CoglPollFD CoglPollFD
cogl_poll_get_info cogl_poll_renderer_get_info
cogl_poll_dispatch cogl_poll_renderer_dispatch
cogl_glib_source_new cogl_glib_source_new
cogl_glib_renderer_source_new
</SECTION> </SECTION>
<SECTION> <SECTION>

View File

@ -274,6 +274,7 @@ main (int argc, char **argv)
&data, &data,
NULL); /* destroy notify */ NULL); /* destroy notify */
while (1) while (1)
{ {
CoglPollFD *poll_fds; CoglPollFD *poll_fds;
@ -286,12 +287,14 @@ main (int argc, char **argv)
cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb)); 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, g_poll ((GPollFD *) poll_fds, n_poll_fds,
timeout == -1 ? -1 : timeout / 1000); 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; return 0;

View File

@ -105,9 +105,11 @@ main (int argc, char **argv)
cogl_onscreen_swap_buffers (onscreen); 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); 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; return 0;

View File

@ -188,9 +188,11 @@ main (int argc, char **argv)
* then allow Cogl to dispatch any corresponding event * then allow Cogl to dispatch any corresponding event
* callbacks, such as resize notification callbacks... * 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); 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_clear4f (fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);
cogl_framebuffer_draw_primitive (fb, pipeline, triangle); cogl_framebuffer_draw_primitive (fb, pipeline, triangle);