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
This commit is contained in:
parent
eb94490fe4
commit
bf5fe70e23
@ -71,6 +71,9 @@ struct _ClutterCanvasPrivate
|
|||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
|
||||||
|
CoglTexture *texture;
|
||||||
|
gboolean dirty;
|
||||||
|
|
||||||
CoglBitmap *buffer;
|
CoglBitmap *buffer;
|
||||||
|
|
||||||
int scale_factor;
|
int scale_factor;
|
||||||
@ -140,6 +143,8 @@ clutter_canvas_finalize (GObject *gobject)
|
|||||||
priv->buffer = NULL;
|
priv->buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_clear_pointer (&priv->texture, cogl_object_unref);
|
||||||
|
|
||||||
G_OBJECT_CLASS (clutter_canvas_parent_class)->finalize (gobject);
|
G_OBJECT_CLASS (clutter_canvas_parent_class)->finalize (gobject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,21 +362,26 @@ clutter_canvas_paint_content (ClutterContent *content,
|
|||||||
ClutterPaintNode *root)
|
ClutterPaintNode *root)
|
||||||
{
|
{
|
||||||
ClutterCanvas *self = CLUTTER_CANVAS (content);
|
ClutterCanvas *self = CLUTTER_CANVAS (content);
|
||||||
|
ClutterCanvasPrivate *priv = self->priv;
|
||||||
ClutterPaintNode *node;
|
ClutterPaintNode *node;
|
||||||
CoglTexture *texture;
|
|
||||||
ClutterActorBox box;
|
ClutterActorBox box;
|
||||||
ClutterColor color;
|
ClutterColor color;
|
||||||
guint8 paint_opacity;
|
guint8 paint_opacity;
|
||||||
ClutterScalingFilter min_f, mag_f;
|
ClutterScalingFilter min_f, mag_f;
|
||||||
ClutterContentRepeat repeat;
|
ClutterContentRepeat repeat;
|
||||||
|
|
||||||
if (self->priv->buffer == NULL)
|
if (priv->buffer == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
texture = cogl_texture_new_from_bitmap (self->priv->buffer,
|
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,
|
COGL_TEXTURE_NO_SLICING,
|
||||||
CLUTTER_CAIRO_FORMAT_ARGB32);
|
CLUTTER_CAIRO_FORMAT_ARGB32);
|
||||||
if (texture == NULL)
|
|
||||||
|
if (priv->texture == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
clutter_actor_get_content_box (actor, &box);
|
clutter_actor_get_content_box (actor, &box);
|
||||||
@ -384,8 +394,7 @@ clutter_canvas_paint_content (ClutterContent *content,
|
|||||||
color.blue = paint_opacity;
|
color.blue = paint_opacity;
|
||||||
color.alpha = paint_opacity;
|
color.alpha = paint_opacity;
|
||||||
|
|
||||||
node = clutter_texture_node_new (texture, &color, min_f, mag_f);
|
node = clutter_texture_node_new (priv->texture, &color, min_f, mag_f);
|
||||||
cogl_object_unref (texture);
|
|
||||||
|
|
||||||
clutter_paint_node_set_name (node, "Canvas");
|
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;
|
float t_w = 1.f, t_h = 1.f;
|
||||||
|
|
||||||
if ((repeat & CLUTTER_REPEAT_X_AXIS) != FALSE)
|
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)
|
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,
|
clutter_paint_node_add_texture_rectangle (node, &box,
|
||||||
0.f, 0.f,
|
0.f, 0.f,
|
||||||
@ -408,6 +417,8 @@ clutter_canvas_paint_content (ClutterContent *content,
|
|||||||
|
|
||||||
clutter_paint_node_add_child (root, node);
|
clutter_paint_node_add_child (root, node);
|
||||||
clutter_paint_node_unref (node);
|
clutter_paint_node_unref (node);
|
||||||
|
|
||||||
|
priv->dirty = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -425,6 +436,8 @@ clutter_canvas_emit_draw (ClutterCanvas *self)
|
|||||||
|
|
||||||
g_assert (priv->width > 0 && priv->width > 0);
|
g_assert (priv->width > 0 && priv->width > 0);
|
||||||
|
|
||||||
|
priv->dirty = TRUE;
|
||||||
|
|
||||||
if (priv->scale_factor_set)
|
if (priv->scale_factor_set)
|
||||||
window_scale = priv->scale_factor;
|
window_scale = priv->scale_factor;
|
||||||
else
|
else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user