summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustavo Noronha Silva <gustavo.noronha@collabora.com>2014-04-28 16:03:13 -0300
committerGustavo Noronha Silva <gns@gnome.org>2014-05-01 11:48:51 -0300
commitbf5fe70e23287bfb08872cddf86266f43ac09f4c (patch)
tree8a072ec7afd85ab9b2079240c957bcd746b43897
parenteb94490fe41cb916132330eaab794b4e761fe25e (diff)
downloadclutter-bf5fe70e23287bfb08872cddf86266f43ac09f4c.tar.gz
clutter-canvas: cache the texture to avoid uploads
When an actor carrying canvas content is repainted, it will currently reupload the data from the buffer to a texture. While this is not a performance problem on a desktop, some mobile environments take a big performance hit. This change tracks data changes and only recreates the texture if necessary. https://bugzilla.gnome.org/show_bug.cgi?id=729144
-rw-r--r--clutter/clutter-canvas.c33
1 files changed, 23 insertions, 10 deletions
diff --git a/clutter/clutter-canvas.c b/clutter/clutter-canvas.c
index 82915165c..d61a54013 100644
--- a/clutter/clutter-canvas.c
+++ b/clutter/clutter-canvas.c
@@ -71,6 +71,9 @@ struct _ClutterCanvasPrivate
int width;
int height;
+ CoglTexture *texture;
+ gboolean dirty;
+
CoglBitmap *buffer;
int scale_factor;
@@ -140,6 +143,8 @@ clutter_canvas_finalize (GObject *gobject)
priv->buffer = NULL;
}
+ g_clear_pointer (&priv->texture, cogl_object_unref);
+
G_OBJECT_CLASS (clutter_canvas_parent_class)->finalize (gobject);
}
@@ -357,21 +362,26 @@ clutter_canvas_paint_content (ClutterContent *content,
ClutterPaintNode *root)
{
ClutterCanvas *self = CLUTTER_CANVAS (content);
+ ClutterCanvasPrivate *priv = self->priv;
ClutterPaintNode *node;
- CoglTexture *texture;
ClutterActorBox box;
ClutterColor color;
guint8 paint_opacity;
ClutterScalingFilter min_f, mag_f;
ClutterContentRepeat repeat;
- if (self->priv->buffer == NULL)
+ if (priv->buffer == NULL)
return;
- texture = cogl_texture_new_from_bitmap (self->priv->buffer,
- COGL_TEXTURE_NO_SLICING,
- CLUTTER_CAIRO_FORMAT_ARGB32);
- if (texture == NULL)
+ if (priv->texture && priv->dirty)
+ g_clear_pointer (&priv->texture, cogl_object_unref);
+
+ if (!priv->texture)
+ priv->texture = cogl_texture_new_from_bitmap (self->priv->buffer,
+ COGL_TEXTURE_NO_SLICING,
+ CLUTTER_CAIRO_FORMAT_ARGB32);
+
+ if (priv->texture == NULL)
return;
clutter_actor_get_content_box (actor, &box);
@@ -384,8 +394,7 @@ clutter_canvas_paint_content (ClutterContent *content,
color.blue = paint_opacity;
color.alpha = paint_opacity;
- node = clutter_texture_node_new (texture, &color, min_f, mag_f);
- cogl_object_unref (texture);
+ node = clutter_texture_node_new (priv->texture, &color, min_f, mag_f);
clutter_paint_node_set_name (node, "Canvas");
@@ -396,10 +405,10 @@ clutter_canvas_paint_content (ClutterContent *content,
float t_w = 1.f, t_h = 1.f;
if ((repeat & CLUTTER_REPEAT_X_AXIS) != FALSE)
- t_w = (box.x2 - box.x1) / cogl_texture_get_width (texture);
+ t_w = (box.x2 - box.x1) / cogl_texture_get_width (priv->texture);
if ((repeat & CLUTTER_REPEAT_Y_AXIS) != FALSE)
- t_h = (box.y2 - box.y1) / cogl_texture_get_height (texture);
+ t_h = (box.y2 - box.y1) / cogl_texture_get_height (priv->texture);
clutter_paint_node_add_texture_rectangle (node, &box,
0.f, 0.f,
@@ -408,6 +417,8 @@ clutter_canvas_paint_content (ClutterContent *content,
clutter_paint_node_add_child (root, node);
clutter_paint_node_unref (node);
+
+ priv->dirty = FALSE;
}
static void
@@ -425,6 +436,8 @@ clutter_canvas_emit_draw (ClutterCanvas *self)
g_assert (priv->width > 0 && priv->width > 0);
+ priv->dirty = TRUE;
+
if (priv->scale_factor_set)
window_scale = priv->scale_factor;
else