mirror of
https://github.com/brl/mutter.git
synced 2024-11-23 00:20:42 -05:00
cogland: Don't redraw constantly
Instead of always drawing at 60FPS without ever going idle, Cogland now only redraws when a client commits a frame or a surface is destroyed. This is acheived using an idle handler on the glib main loop. Reviewed-by: Robert Bragg <robert@linux.intel.com> (cherry picked from commit 906e1b5eb535a86a849bed7a363f800ad71ab9bc) Conflicts: examples/cogland.c
This commit is contained in:
parent
666d0e100c
commit
53a684bf9e
@ -108,6 +108,8 @@ struct _CoglandCompositor
|
|||||||
GSource *wayland_event_source;
|
GSource *wayland_event_source;
|
||||||
|
|
||||||
GList *surfaces;
|
GList *surfaces;
|
||||||
|
|
||||||
|
unsigned int redraw_idle;
|
||||||
};
|
};
|
||||||
|
|
||||||
static CoglBool option_multiple_outputs = FALSE;
|
static CoglBool option_multiple_outputs = FALSE;
|
||||||
@ -264,6 +266,73 @@ wayland_event_source_new (struct wl_display *display)
|
|||||||
return &source->source;
|
return &source->source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _CoglandFrameCallback
|
||||||
|
{
|
||||||
|
struct wl_list link;
|
||||||
|
|
||||||
|
/* Pointer back to the compositor */
|
||||||
|
CoglandCompositor *compositor;
|
||||||
|
|
||||||
|
struct wl_resource resource;
|
||||||
|
} CoglandFrameCallback;
|
||||||
|
|
||||||
|
static CoglBool
|
||||||
|
paint_cb (void *user_data)
|
||||||
|
{
|
||||||
|
CoglandCompositor *compositor = user_data;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = compositor->outputs; l; l = l->next)
|
||||||
|
{
|
||||||
|
CoglandOutput *output = l->data;
|
||||||
|
CoglFramebuffer *fb = COGL_FRAMEBUFFER (output->onscreen);
|
||||||
|
GList *l2;
|
||||||
|
|
||||||
|
cogl_push_framebuffer (fb);
|
||||||
|
|
||||||
|
cogl_framebuffer_clear4f (fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);
|
||||||
|
|
||||||
|
cogl_framebuffer_draw_primitive (fb, compositor->triangle_pipeline,
|
||||||
|
compositor->triangle);
|
||||||
|
|
||||||
|
for (l2 = compositor->surfaces; l2; l2 = l2->next)
|
||||||
|
{
|
||||||
|
CoglandSurface *surface = l2->data;
|
||||||
|
|
||||||
|
if (surface->texture)
|
||||||
|
{
|
||||||
|
CoglTexture2D *texture = surface->texture;
|
||||||
|
cogl_set_source_texture (COGL_TEXTURE (texture));
|
||||||
|
cogl_rectangle (-1, 1, 1, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb));
|
||||||
|
|
||||||
|
cogl_pop_framebuffer ();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!wl_list_empty (&compositor->frame_callbacks))
|
||||||
|
{
|
||||||
|
CoglandFrameCallback *callback =
|
||||||
|
wl_container_of (compositor->frame_callbacks.next, callback, link);
|
||||||
|
|
||||||
|
wl_resource_post_event (&callback->resource,
|
||||||
|
WL_CALLBACK_DONE, get_time ());
|
||||||
|
wl_resource_destroy (&callback->resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
compositor->redraw_idle = 0;
|
||||||
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cogland_queue_redraw (CoglandCompositor *compositor)
|
||||||
|
{
|
||||||
|
if (compositor->redraw_idle == 0)
|
||||||
|
compositor->redraw_idle = g_idle_add (paint_cb, compositor);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
shm_buffer_damaged (CoglandSurface *surface,
|
shm_buffer_damaged (CoglandSurface *surface,
|
||||||
int32_t x,
|
int32_t x,
|
||||||
@ -335,6 +404,8 @@ cogland_surface_detach_buffer (CoglandSurface *surface)
|
|||||||
cogl_object_unref (surface->texture);
|
cogl_object_unref (surface->texture);
|
||||||
surface->texture = NULL;
|
surface->texture = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cogland_queue_redraw (surface->compositor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,16 +470,6 @@ cogland_surface_damage (struct wl_client *client,
|
|||||||
region_add (&surface->pending.damage, x, y, width, height);
|
region_add (&surface->pending.damage, x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _CoglandFrameCallback
|
|
||||||
{
|
|
||||||
struct wl_list link;
|
|
||||||
|
|
||||||
/* Pointer back to the compositor */
|
|
||||||
CoglandCompositor *compositor;
|
|
||||||
|
|
||||||
struct wl_resource resource;
|
|
||||||
} CoglandFrameCallback;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
destroy_frame_callback (struct wl_resource *callback_resource)
|
destroy_frame_callback (struct wl_resource *callback_resource)
|
||||||
{
|
{
|
||||||
@ -520,6 +581,8 @@ cogland_surface_commit (struct wl_client *client,
|
|||||||
wl_list_insert_list (&compositor->frame_callbacks,
|
wl_list_insert_list (&compositor->frame_callbacks,
|
||||||
&surface->pending.frame_callback_list);
|
&surface->pending.frame_callback_list);
|
||||||
wl_list_init (&surface->pending.frame_callback_list);
|
wl_list_init (&surface->pending.frame_callback_list);
|
||||||
|
|
||||||
|
cogland_queue_redraw (compositor);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -757,54 +820,6 @@ cogland_compositor_create_output (CoglandCompositor *compositor,
|
|||||||
compositor->outputs = g_list_prepend (compositor->outputs, output);
|
compositor->outputs = g_list_prepend (compositor->outputs, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CoglBool
|
|
||||||
paint_cb (void *user_data)
|
|
||||||
{
|
|
||||||
CoglandCompositor *compositor = user_data;
|
|
||||||
GList *l;
|
|
||||||
|
|
||||||
for (l = compositor->outputs; l; l = l->next)
|
|
||||||
{
|
|
||||||
CoglandOutput *output = l->data;
|
|
||||||
CoglFramebuffer *fb = COGL_FRAMEBUFFER (output->onscreen);
|
|
||||||
GList *l2;
|
|
||||||
|
|
||||||
cogl_push_framebuffer (fb);
|
|
||||||
|
|
||||||
cogl_framebuffer_clear4f (fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);
|
|
||||||
|
|
||||||
cogl_framebuffer_draw_primitive (fb, compositor->triangle_pipeline,
|
|
||||||
compositor->triangle);
|
|
||||||
|
|
||||||
for (l2 = compositor->surfaces; l2; l2 = l2->next)
|
|
||||||
{
|
|
||||||
CoglandSurface *surface = l2->data;
|
|
||||||
|
|
||||||
if (surface->texture)
|
|
||||||
{
|
|
||||||
CoglTexture2D *texture = surface->texture;
|
|
||||||
cogl_set_source_texture (COGL_TEXTURE (texture));
|
|
||||||
cogl_rectangle (-1, 1, 1, -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb));
|
|
||||||
|
|
||||||
cogl_pop_framebuffer ();
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!wl_list_empty (&compositor->frame_callbacks))
|
|
||||||
{
|
|
||||||
CoglandFrameCallback *callback =
|
|
||||||
wl_container_of (compositor->frame_callbacks.next, callback, link);
|
|
||||||
|
|
||||||
wl_resource_post_event (&callback->resource,
|
|
||||||
WL_CALLBACK_DONE, get_time ());
|
|
||||||
wl_resource_destroy (&callback->resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
const static struct wl_compositor_interface cogland_compositor_interface =
|
const static struct wl_compositor_interface cogland_compositor_interface =
|
||||||
{
|
{
|
||||||
cogland_compositor_create_surface,
|
cogland_compositor_create_surface,
|
||||||
@ -1079,13 +1094,13 @@ main (int argc, char **argv)
|
|||||||
3, triangle_vertices);
|
3, triangle_vertices);
|
||||||
compositor.triangle_pipeline = cogl_pipeline_new (compositor.cogl_context);
|
compositor.triangle_pipeline = cogl_pipeline_new (compositor.cogl_context);
|
||||||
|
|
||||||
g_timeout_add (16, paint_cb, &compositor);
|
|
||||||
|
|
||||||
cogl_source = cogl_glib_source_new (compositor.cogl_context,
|
cogl_source = cogl_glib_source_new (compositor.cogl_context,
|
||||||
G_PRIORITY_DEFAULT);
|
G_PRIORITY_DEFAULT);
|
||||||
|
|
||||||
g_source_attach (cogl_source, NULL);
|
g_source_attach (cogl_source, NULL);
|
||||||
|
|
||||||
|
cogland_queue_redraw (&compositor);
|
||||||
|
|
||||||
g_main_loop_run (loop);
|
g_main_loop_run (loop);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user