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-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 \

View File

@ -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)

View File

@ -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:

View File

@ -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,
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,7 +133,7 @@ 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,
cogl_poll_renderer_dispatch (cogl_source->renderer,
poll_fds,
cogl_source->poll_fds->len);
@ -172,7 +158,7 @@ cogl_glib_source_funcs =
};
GSource *
cogl_glib_source_new (CoglContext *context,
cogl_glib_renderer_source_new (CoglRenderer *renderer,
int priority)
{
GSource *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);
}

View File

@ -40,11 +40,21 @@ G_BEGIN_DECLS
*
* Creates a #GSource which handles Cogl's internal system event
* processing. This can be used as a convenience instead of
* cogl_poll_get_info() and cogl_poll_dispatch() in applications that
* are already using the GLib main loop. After this is called the
* #GSource should be attached to the main loop using
* cogl_poll_renderer_get_info() and cogl_poll_renderer_dispatch() in
* applications that are already using the GLib main loop. After this
* is called the #GSource should be attached to the main loop using
* g_source_attach().
*
* Applications that manually connect to a #CoglRenderer before they
* create a #CoglContext should instead use
* cogl_glib_renderer_source_new() so that events may be dispatched
* before a context has been created. In that case you don't need to
* use this api in addition later, it is simply enough to use
* cogl_glib_renderer_source_new() instead.
*
* <note>This api is actually just a thin convenience wrapper around
* cogl_glib_renderer_source_new()</note>
*
* Return value: a new #GSource
*
* Stability: unstable
@ -54,6 +64,27 @@ GSource *
cogl_glib_source_new (CoglContext *context,
int priority);
/**
* cogl_glib_renderer_source_new:
* @context: A #CoglContext
* @priority: The priority of the #GSource
*
* Creates a #GSource which handles Cogl's internal system event
* processing. This can be used as a convenience instead of
* cogl_poll_renderer_get_info() and cogl_poll_renderer_dispatch() in
* applications that are already using the GLib main loop. After this
* is called the #GSource should be attached to the main loop using
* g_source_attach().
*
* Return value: a new #GSource
*
* Stability: unstable
* Since: 1.16
*/
GSource *
cogl_glib_renderer_source_new (CoglRenderer *renderer,
int priority);
G_END_DECLS
#endif /* __COGL_GSOURCE_H__ */

View File

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

View File

@ -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

View File

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

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
#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,
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);
}
else
if (!COGL_TAILQ_EMPTY (&renderer->context->onscreen_events_queue))
{
/* 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))
*timeout = 0;
return renderer->poll_fds_age;
}
}
winsys = renderer->winsys_vtable;
if (winsys->get_dispatch_timeout)
*timeout = winsys->get_dispatch_timeout (renderer);
else
*timeout = -1;
return renderer->poll_fds_age;
}
void
cogl_poll_dispatch (CoglContext *context,
cogl_poll_renderer_dispatch (CoglRenderer *renderer,
const CoglPollFD *poll_fds,
int n_poll_fds)
{
const CoglWinsysVtable *winsys;
_COGL_RETURN_IF_FAIL (cogl_is_context (context));
_COGL_RETURN_IF_FAIL (cogl_is_renderer (renderer));
/* FIXME: arbitrary cogl components should just be able to queue
* idle functions so that we don't have to explicitly poke into
* CoglContext here and understand about the CoglOnscreen event
* queue... */
if (renderer->context)
{
CoglContext *context = renderer->context;
if (!COGL_TAILQ_EMPTY (&context->onscreen_events_queue))
_cogl_dispatch_onscreen_events (context);
}
winsys = _cogl_context_get_winsys (context);
winsys = renderer->winsys_vtable;
if (winsys->poll_dispatch)
winsys->poll_dispatch (context, poll_fds, n_poll_fds);
winsys->poll_dispatch (renderer, poll_fds, n_poll_fds);
}
static int
find_pollfd (CoglRenderer *renderer, int fd)
{
int i;
for (i = 0; i < renderer->poll_fds->len; i++)
{
CoglPollFD *pollfd = &g_array_index (renderer->poll_fds, CoglPollFD, i);
if (pollfd->fd == fd)
return i;
}
return -1;
}
void
_cogl_poll_renderer_remove_fd (CoglRenderer *renderer, int fd)
{
int i = find_pollfd (renderer, fd);
if (i < 0)
return;
g_array_remove_index_fast (renderer->poll_fds, i);
renderer->poll_fds_age++;
}
void
_cogl_poll_renderer_add_fd (CoglRenderer *renderer,
int fd,
CoglPollFDEvent events)
{
CoglPollFD pollfd = {
fd,
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;
/**
* cogl_poll_get_info:
* @context: A #CoglContext
* cogl_poll_renderer_get_info:
* @renderer: A #CoglRenderer
* @poll_fds: A return location for a pointer to an array
* of #CoglPollFD<!-- -->s
* @n_poll_fds: A return location for the number of entries in *@poll_fds
* @timeout: A return location for the maximum length of time to wait
* in microseconds, or -1 to wait indefinitely.
*
* This should be called whenever an application is about to go idle
* so that Cogl has a chance to describe what state it needs to be
* woken up on. The assumption is that the application is using a main
* loop with something like the poll function call on Unix or the GLib
* main loop.
* Is used to integrate Cogl with an application mainloop that is based
* on the unix poll(2) api (or select() or something equivalent). This
* api should be called whenever an application is about to go idle so
* that Cogl has a chance to describe what file descriptor events it
* needs to be woken up for.
*
* <note>If your application is using the Glib mainloop then you
* should jump to the cogl_glib_source_new() api as a more convenient
* way of integrating Cogl with the mainloop.</note>
*
* After the function is called *@poll_fds will contain a pointer to
* an array of #CoglPollFD structs describing the file descriptors
@ -124,8 +128,12 @@ typedef struct {
* accordingly. After the application has completed its idle it is
* expected to either update the revents members directly in this
* array or to create a copy of the array and update them
* there. Either way it should pass a pointer to either array back to
* Cogl when calling cogl_poll_dispatch().
* there.
*
* When the application mainloop returns from calling poll(2) (or its
* equivalent) then it should call cogl_poll_renderer_dispatch()
* passing a pointer the array of CoglPollFD<!-- -->s with updated
* revent values.
*
* When using the %COGL_WINSYS_ID_WGL winsys (where file descriptors
* don't make any sense) or %COGL_WINSYS_ID_SDL (where the event
@ -134,21 +142,29 @@ typedef struct {
*
* @timeout will contain a maximum amount of time to wait in
* microseconds before the application should wake up or -1 if the
* application should wait indefinitely. This can also be 0 zero if
* application should wait indefinitely. This can also be 0 if
* Cogl needs to be woken up immediately.
*
* Return value: A "poll fd state age" that changes whenever the set
* of poll_fds has changed. If this API is being used to
* integrate with another system mainloop api then
* knowing if the set of file descriptors and events has
* really changed can help avoid redundant work
* depending the api. The age isn't guaranteed to change
* when the timeout changes.
*
* Stability: unstable
* Since: 1.10
* Since: 1.16
*/
void
cogl_poll_get_info (CoglContext *context,
int
cogl_poll_renderer_get_info (CoglRenderer *renderer,
CoglPollFD **poll_fds,
int *n_poll_fds,
int64_t *timeout);
/**
* cogl_poll_dispatch:
* @context: A #CoglContext
* cogl_poll_renderer_dispatch:
* @renderer: A #CoglRenderer
* @poll_fds: An array of #CoglPollFD<!-- -->s describing the events
* that have occurred since the application went idle.
* @n_poll_fds: The length of the @poll_fds array.
@ -157,15 +173,19 @@ cogl_poll_get_info (CoglContext *context,
* going idle in its main loop. The @poll_fds array should contain a
* list of file descriptors matched with the events that occurred in
* revents. The events field is ignored. It is safe to pass in extra
* file descriptors that Cogl didn't request from
* cogl_context_begin_idle() or a shorter array missing some file
* file descriptors that Cogl didn't request when calling
* cogl_poll_renderer_get_info() or a shorter array missing some file
* descriptors that Cogl requested.
*
* <note>If your application didn't originally create a #CoglRenderer
* manually then you can easily get a #CoglRenderer pointer by calling
* cogl_get_renderer().</note>
*
* Stability: unstable
* Since: 1.10
* Since: 1.16
*/
void
cogl_poll_dispatch (CoglContext *context,
cogl_poll_renderer_dispatch (CoglRenderer *renderer,
const CoglPollFD *poll_fds,
int n_poll_fds);

View File

@ -30,6 +30,7 @@
#include "cogl-winsys-private.h"
#include "cogl-driver.h"
#include "cogl-texture-driver.h"
#include "cogl-context.h"
#ifdef COGL_HAS_XLIB_SUPPORT
#include <X11/Xlib.h>
@ -50,6 +51,24 @@ struct _CoglRenderer
CoglWinsysID winsys_id_override;
GList *constraints;
GArray *poll_fds;
int poll_fds_age;
/* NB: Currently a CoglContext can only be associated with 1
* CoglDisplay which itself can only be associated with 1
* CoglRenderer.
*
* We currently do event dispatching from the renderer but once we
* have fully setup a context then we need to refer to the context
* to dispatch context events.
*
* This gives us a back-reference to the CoglContext that can be
* referenced during event dispatching.
*
* We always need to consider that this may be NULL.
*/
CoglContext *context;
GList *outputs;
#ifdef COGL_HAS_XLIB_SUPPORT

View File

@ -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

View File

@ -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

View File

@ -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,

View File

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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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,32 +2568,39 @@ 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)
{
CoglContext *context = renderer->context;
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_display->pending_sync_notify = FALSE;
glx_display->pending_resize_notify = FALSE;
glx_display->pending_complete_notify = FALSE;
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);
}
}
}
static CoglWinsysVtable _cogl_winsys_vtable =
{
@ -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... */

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

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

View File

@ -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;

View File

@ -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;

View File

@ -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);