[clutter/clutter-1.18] clutter-canvas: cache the texture to avoid uploads



commit bf5fe70e23287bfb08872cddf86266f43ac09f4c
Author: Gustavo Noronha Silva <gustavo noronha collabora com>
Date:   Mon Apr 28 16:03:13 2014 -0300

    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

 clutter/clutter-canvas.c |   33 +++++++++++++++++++++++----------
 1 files changed, 23 insertions(+), 10 deletions(-)
---
diff --git a/clutter/clutter-canvas.c b/clutter/clutter-canvas.c
index 8291516..d61a540 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]