cogland: Listen for Expose events when Cogl is using X

Since 906e1b5eb535a86 Cogland no longer redraws constantly but instead
only draws once at startup and then again whenever a client attaches a
new buffer. Sometimes however it seems that the first paint will get
lost perhaps because it is sent before the window is fully mapped. As
it was previously not handling expose events it would not paint again
until the first client is connected so there would be a blank window
which looks broken.

This patch makes it handle Expose events when it detects that Cogl is
using an X backend. On other backends it will resort to queuing a
redraw every 16ms as it did before.

Although this is probably a bit overkill for such a small example, it
seems like a good idea to only redraw when we think it's necessary so
that we can be sure that the mechanism works. Handling the expose
events means we can have at least one platform where we can test this.

Reviewed-by: Robert Bragg <robert@linux.intel.com>

(cherry picked from commit 99cf15b285302243395873d78f05a5895c173eef)
This commit is contained in:
Neil Roberts 2013-05-13 16:53:17 +01:00
parent f002e4e78f
commit f7c3c2dc95

View File

@ -8,6 +8,10 @@
#include <wayland-server.h> #include <wayland-server.h>
#ifdef COGL_HAS_XLIB_SUPPORT
#include <cogl/cogl-xlib.h>
#endif
typedef struct _CoglandCompositor CoglandCompositor; typedef struct _CoglandCompositor CoglandCompositor;
typedef struct typedef struct
@ -1046,6 +1050,78 @@ create_cogl_context (CoglandCompositor *compositor,
return context; return context;
} }
#ifdef COGL_HAS_XLIB_SUPPORT
static CoglFilterReturn
x_event_cb (XEvent *event,
void *data)
{
CoglandCompositor *compositor = data;
if (event->type == Expose)
cogland_queue_redraw (compositor);
return COGL_FILTER_CONTINUE;
}
#endif /* COGL_HAS_XLIB_SUPPORT */
static gboolean
timeout_cb (void *data)
{
cogland_queue_redraw (data);
return TRUE;
}
static void
init_redraws (CoglandCompositor *compositor)
{
#ifdef COGL_HAS_XLIB_SUPPORT
CoglRenderer *renderer = cogl_context_get_renderer (compositor->cogl_context);
CoglWinsysID winsys = cogl_renderer_get_winsys_id (renderer);
/* If Cogl is using X then we can listen for Expose events to know
* when to repaint the window. Otherwise we don't have any code to
* know when the contents of the window is dirty so we'll just
* redraw constantly */
switch (winsys)
{
case COGL_WINSYS_ID_GLX:
case COGL_WINSYS_ID_EGL_XLIB:
{
Display *display = cogl_xlib_renderer_get_display (renderer);
GList *l;
for (l = compositor->outputs; l; l = l->next)
{
CoglandOutput *output = l->data;
XWindowAttributes win_attribs;
Window win;
win = cogl_x11_onscreen_get_window_xid (output->onscreen);
if (XGetWindowAttributes (display, win, &win_attribs))
{
XSelectInput (display,
win,
win_attribs.your_event_mask | ExposureMask);
cogl_xlib_renderer_add_filter (renderer,
x_event_cb,
compositor);
}
}
}
return;
default:
break;
}
#endif /* COGL_HAS_XLIB_SUPPORT */
g_timeout_add (16, timeout_cb, compositor);
}
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
@ -1152,7 +1228,7 @@ main (int argc, char **argv)
g_source_attach (cogl_source, NULL); g_source_attach (cogl_source, NULL);
cogland_queue_redraw (&compositor); init_redraws (&compositor);
g_main_loop_run (loop); g_main_loop_run (loop);