Update some of the examples to use the dirty callback

This updates Cogland and the three hello examples to use the dirty
callback. For Cogland, this removes the manual handling of X events
and for the other examples it removes the need to redraw continously.

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

(cherry picked from commit 108e3c548b7866190845f163c84a05212718bd70)
This commit is contained in:
Neil Roberts 2013-05-14 13:41:29 +01:00
parent d0944b8fbd
commit 8282cee367
4 changed files with 94 additions and 94 deletions

View File

@ -8,18 +8,39 @@ typedef struct _Data
CoglFramebuffer *fb;
CoglPrimitive *triangle;
CoglPipeline *pipeline;
unsigned int redraw_idle;
CoglBool is_dirty;
CoglBool draw_ready;
} Data;
static CoglBool
static gboolean
paint_cb (void *user_data)
{
Data *data = user_data;
data->redraw_idle = 0;
data->is_dirty = FALSE;
data->draw_ready = FALSE;
cogl_framebuffer_clear4f (data->fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);
cogl_framebuffer_draw_primitive (data->fb, data->pipeline, data->triangle);
cogl_framebuffer_draw_primitive (data->fb,
data->pipeline,
data->triangle);
cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb));
return FALSE; /* remove the callback */
return G_SOURCE_REMOVE;
}
static void
maybe_redraw (Data *data)
{
if (data->is_dirty && data->draw_ready && data->redraw_idle == 0) {
/* We'll draw on idle instead of drawing immediately so that
* if Cogl reports multiple dirty rectangles we won't
* redundantly draw multiple frames */
data->redraw_idle = g_idle_add (paint_cb, data);
}
}
static void
@ -28,8 +49,23 @@ frame_event_cb (CoglOnscreen *onscreen,
CoglFrameInfo *info,
void *user_data)
{
if (event == COGL_FRAME_EVENT_SYNC)
paint_cb (user_data);
Data *data = user_data;
if (event == COGL_FRAME_EVENT_SYNC) {
data->draw_ready = TRUE;
maybe_redraw (data);
}
}
static void
dirty_cb (CoglOnscreen *onscreen,
const CoglOnscreenDirtyInfo *info,
void *user_data)
{
Data *data = user_data;
data->is_dirty = TRUE;
maybe_redraw (data);
}
int
@ -46,6 +82,10 @@ main (int argc, char **argv)
GSource *cogl_source;
GMainLoop *loop;
data.redraw_idle = 0;
data.is_dirty = FALSE;
data.draw_ready = TRUE;
data.ctx = cogl_context_new (NULL, &error);
if (!data.ctx) {
fprintf (stderr, "Failed to create context: %s\n", error->message);
@ -71,7 +111,10 @@ main (int argc, char **argv)
frame_event_cb,
&data,
NULL); /* destroy notify */
g_idle_add (paint_cb, &data);
cogl_onscreen_add_dirty_callback (COGL_ONSCREEN (data.fb),
dirty_cb,
&data,
NULL); /* destroy notify */
loop = g_main_loop_new (NULL, TRUE);
g_main_loop_run (loop);

View File

@ -32,15 +32,21 @@ redraw (Data *data)
cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb));
}
static void
dirty_cb (CoglOnscreen *onscreen,
const CoglOnscreenDirtyInfo *info,
void *user_data)
{
Data *data = user_data;
data->redraw_queued = TRUE;
}
static void
handle_event (Data *data, SDL_Event *event)
{
switch (event->type)
{
case SDL_VIDEOEXPOSE:
data->redraw_queued = TRUE;
break;
case SDL_MOUSEMOTION:
{
int width =
@ -101,6 +107,10 @@ main (int argc, char **argv)
frame_cb,
&data,
NULL /* destroy callback */);
cogl_onscreen_add_dirty_callback (onscreen,
dirty_cb,
&data,
NULL /* destroy callback */);
data.center_x = 0.0f;
data.center_y = 0.0f;
@ -112,7 +122,7 @@ main (int argc, char **argv)
3, triangle_vertices);
data.pipeline = cogl_pipeline_new (ctx);
data.redraw_queued = TRUE;
data.redraw_queued = FALSE;
data.ready_to_draw = TRUE;
while (!data.quit)

View File

@ -32,6 +32,16 @@ redraw (Data *data)
cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb));
}
static void
dirty_cb (CoglOnscreen *onscreen,
const CoglOnscreenDirtyInfo *info,
void *user_data)
{
Data *data = user_data;
data->redraw_queued = TRUE;
}
static void
handle_event (Data *data, SDL_Event *event)
{
@ -40,10 +50,6 @@ handle_event (Data *data, SDL_Event *event)
case SDL_WINDOWEVENT:
switch (event->window.event)
{
case SDL_WINDOWEVENT_EXPOSED:
data->redraw_queued = TRUE;
break;
case SDL_WINDOWEVENT_CLOSE:
data->quit = TRUE;
break;
@ -110,6 +116,10 @@ main (int argc, char **argv)
frame_cb,
&data,
NULL /* destroy callback */);
cogl_onscreen_add_dirty_callback (onscreen,
dirty_cb,
&data,
NULL /* destroy callback */);
data.center_x = 0.0f;
data.center_y = 0.0f;
@ -125,7 +135,7 @@ main (int argc, char **argv)
3, triangle_vertices);
data.pipeline = cogl_pipeline_new (ctx);
data.redraw_queued = TRUE;
data.redraw_queued = FALSE;
data.ready_to_draw = TRUE;
while (!data.quit)

View File

@ -8,10 +8,6 @@
#include <wayland-server.h>
#ifdef COGL_HAS_XLIB_SUPPORT
#include <cogl/cogl-xlib.h>
#endif
typedef struct _CoglandCompositor CoglandCompositor;
typedef struct
@ -781,6 +777,16 @@ bind_output (struct wl_client *client,
}
}
static void
dirty_cb (CoglOnscreen *onscreen,
const CoglOnscreenDirtyInfo *info,
void *user_data)
{
CoglandCompositor *compositor = user_data;
cogland_queue_redraw (compositor);
}
static void
cogland_compositor_create_output (CoglandCompositor *compositor,
int x,
@ -813,6 +819,11 @@ cogland_compositor_create_output (CoglandCompositor *compositor,
if (!cogl_framebuffer_allocate (fb, &error))
g_error ("Failed to allocate framebuffer: %s\n", error->message);
cogl_onscreen_add_dirty_callback (output->onscreen,
dirty_cb,
compositor,
NULL /* destroy */);
cogl_onscreen_show (output->onscreen);
cogl_framebuffer_set_viewport (fb, -x, -y,
compositor->virtual_width,
@ -1050,78 +1061,6 @@ create_cogl_context (CoglandCompositor *compositor,
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
main (int argc, char **argv)
{
@ -1228,8 +1167,6 @@ main (int argc, char **argv)
g_source_attach (cogl_source, NULL);
init_redraws (&compositor);
g_main_loop_run (loop);
return 0;