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:
parent
d0944b8fbd
commit
8282cee367
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user