mirror of
https://github.com/brl/mutter.git
synced 2024-11-23 00:20:42 -05:00
actor: Cache per-actor transforms
Previously each time we needed to retrieve the model transform for a given actor we would call the apply_transform vfunc which would build up a transformation matrix based on the actor's current anchor point, its scale, its allocation and rotation. The apply_transform implementation would repeatedly call API like cogl_matrix_rotate, cogl_matrix_translate and cogl_matrix_scale. All this micro matrix manipulation APIs were starting to show up in the profiles of dynamic applications so this adds priv->transform matrix cache which maintains the combined result of the actors scale, rotation and anchor point etc. Whenever something like the rotation changes then then the matrix is marked as dirty, but so long as the matrix isn't dirty then the apply_transform vfunc now just calls cogl_matrix_multiply with the cached transform matrix.
This commit is contained in:
parent
19b8622983
commit
3b88029f38
@ -413,6 +413,7 @@ struct _ClutterActorPrivate
|
|||||||
guint paint_volume_valid : 1;
|
guint paint_volume_valid : 1;
|
||||||
guint last_paint_volume_valid : 1;
|
guint last_paint_volume_valid : 1;
|
||||||
guint in_clone_paint : 1;
|
guint in_clone_paint : 1;
|
||||||
|
guint transform_valid : 1;
|
||||||
|
|
||||||
gfloat clip[4];
|
gfloat clip[4];
|
||||||
|
|
||||||
@ -436,6 +437,8 @@ struct _ClutterActorPrivate
|
|||||||
/* depth */
|
/* depth */
|
||||||
gfloat z;
|
gfloat z;
|
||||||
|
|
||||||
|
CoglMatrix transform;
|
||||||
|
|
||||||
guint8 opacity;
|
guint8 opacity;
|
||||||
gint opacity_override;
|
gint opacity_override;
|
||||||
|
|
||||||
@ -1807,6 +1810,8 @@ clutter_actor_real_allocate (ClutterActor *self,
|
|||||||
CLUTTER_NOTE (LAYOUT, "Allocation for '%s' changed",
|
CLUTTER_NOTE (LAYOUT, "Allocation for '%s' changed",
|
||||||
_clutter_actor_get_debug_name (self));
|
_clutter_actor_get_debug_name (self));
|
||||||
|
|
||||||
|
priv->transform_valid = FALSE;
|
||||||
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ALLOCATION]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ALLOCATION]);
|
||||||
|
|
||||||
/* we also emit the ::allocation-changed signal for people
|
/* we also emit the ::allocation-changed signal for people
|
||||||
@ -2240,58 +2245,70 @@ clutter_actor_real_apply_transform (ClutterActor *self,
|
|||||||
{
|
{
|
||||||
ClutterActorPrivate *priv = self->priv;
|
ClutterActorPrivate *priv = self->priv;
|
||||||
|
|
||||||
cogl_matrix_translate (matrix,
|
if (!priv->transform_valid)
|
||||||
priv->allocation.x1,
|
|
||||||
priv->allocation.y1,
|
|
||||||
0.0);
|
|
||||||
|
|
||||||
if (priv->z)
|
|
||||||
cogl_matrix_translate (matrix, 0, 0, priv->z);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* because the rotation involves translations, we must scale before
|
|
||||||
* applying the rotations (if we apply the scale after the rotations,
|
|
||||||
* the translations included in the rotation are not scaled and so the
|
|
||||||
* entire object will move on the screen as a result of rotating it).
|
|
||||||
*/
|
|
||||||
if (priv->scale_x != 1.0 || priv->scale_y != 1.0)
|
|
||||||
{
|
{
|
||||||
TRANSFORM_ABOUT_ANCHOR_COORD (self, matrix,
|
CoglMatrix *transform = &priv->transform;
|
||||||
&priv->scale_center,
|
|
||||||
cogl_matrix_scale (matrix,
|
cogl_matrix_init_identity (transform);
|
||||||
priv->scale_x,
|
|
||||||
priv->scale_y,
|
cogl_matrix_translate (transform,
|
||||||
1.0));
|
priv->allocation.x1,
|
||||||
|
priv->allocation.y1,
|
||||||
|
0.0);
|
||||||
|
|
||||||
|
if (priv->z)
|
||||||
|
cogl_matrix_translate (transform, 0, 0, priv->z);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* because the rotation involves translations, we must scale
|
||||||
|
* before applying the rotations (if we apply the scale after
|
||||||
|
* the rotations, the translations included in the rotation are
|
||||||
|
* not scaled and so the entire object will move on the screen
|
||||||
|
* as a result of rotating it).
|
||||||
|
*/
|
||||||
|
if (priv->scale_x != 1.0 || priv->scale_y != 1.0)
|
||||||
|
{
|
||||||
|
TRANSFORM_ABOUT_ANCHOR_COORD (self, transform,
|
||||||
|
&priv->scale_center,
|
||||||
|
cogl_matrix_scale (transform,
|
||||||
|
priv->scale_x,
|
||||||
|
priv->scale_y,
|
||||||
|
1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->rzang)
|
||||||
|
TRANSFORM_ABOUT_ANCHOR_COORD (self, transform,
|
||||||
|
&priv->rz_center,
|
||||||
|
cogl_matrix_rotate (transform,
|
||||||
|
priv->rzang,
|
||||||
|
0, 0, 1.0));
|
||||||
|
|
||||||
|
if (priv->ryang)
|
||||||
|
TRANSFORM_ABOUT_ANCHOR_COORD (self, transform,
|
||||||
|
&priv->ry_center,
|
||||||
|
cogl_matrix_rotate (transform,
|
||||||
|
priv->ryang,
|
||||||
|
0, 1.0, 0));
|
||||||
|
|
||||||
|
if (priv->rxang)
|
||||||
|
TRANSFORM_ABOUT_ANCHOR_COORD (self, transform,
|
||||||
|
&priv->rx_center,
|
||||||
|
cogl_matrix_rotate (transform,
|
||||||
|
priv->rxang,
|
||||||
|
1.0, 0, 0));
|
||||||
|
|
||||||
|
if (!clutter_anchor_coord_is_zero (&priv->anchor))
|
||||||
|
{
|
||||||
|
gfloat x, y, z;
|
||||||
|
|
||||||
|
clutter_anchor_coord_get_units (self, &priv->anchor, &x, &y, &z);
|
||||||
|
cogl_matrix_translate (transform, -x, -y, -z);
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->transform_valid = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->rzang)
|
cogl_matrix_multiply (matrix, matrix, &priv->transform);
|
||||||
TRANSFORM_ABOUT_ANCHOR_COORD (self, matrix,
|
|
||||||
&priv->rz_center,
|
|
||||||
cogl_matrix_rotate (matrix,
|
|
||||||
priv->rzang,
|
|
||||||
0, 0, 1.0));
|
|
||||||
|
|
||||||
if (priv->ryang)
|
|
||||||
TRANSFORM_ABOUT_ANCHOR_COORD (self, matrix,
|
|
||||||
&priv->ry_center,
|
|
||||||
cogl_matrix_rotate (matrix,
|
|
||||||
priv->ryang,
|
|
||||||
0, 1.0, 0));
|
|
||||||
|
|
||||||
if (priv->rxang)
|
|
||||||
TRANSFORM_ABOUT_ANCHOR_COORD (self, matrix,
|
|
||||||
&priv->rx_center,
|
|
||||||
cogl_matrix_rotate (matrix,
|
|
||||||
priv->rxang,
|
|
||||||
1.0, 0, 0));
|
|
||||||
|
|
||||||
if (!clutter_anchor_coord_is_zero (&priv->anchor))
|
|
||||||
{
|
|
||||||
gfloat x, y, z;
|
|
||||||
|
|
||||||
clutter_anchor_coord_get_units (self, &priv->anchor, &x, &y, &z);
|
|
||||||
cogl_matrix_translate (matrix, -x, -y, -z);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Applies the transforms associated with this actor to the given
|
/* Applies the transforms associated with this actor to the given
|
||||||
@ -2740,6 +2757,8 @@ clutter_actor_set_rotation_internal (ClutterActor *self,
|
|||||||
|
|
||||||
g_object_freeze_notify (G_OBJECT (self));
|
g_object_freeze_notify (G_OBJECT (self));
|
||||||
|
|
||||||
|
priv->transform_valid = FALSE;
|
||||||
|
|
||||||
switch (axis)
|
switch (axis)
|
||||||
{
|
{
|
||||||
case CLUTTER_X_AXIS:
|
case CLUTTER_X_AXIS:
|
||||||
@ -4909,6 +4928,8 @@ clutter_actor_init (ClutterActor *self)
|
|||||||
_clutter_paint_volume_init_static (&priv->last_paint_volume, NULL);
|
_clutter_paint_volume_init_static (&priv->last_paint_volume, NULL);
|
||||||
priv->last_paint_volume_valid = TRUE;
|
priv->last_paint_volume_valid = TRUE;
|
||||||
|
|
||||||
|
priv->transform_valid = FALSE;
|
||||||
|
|
||||||
memset (priv->clip, 0, sizeof (gfloat) * 4);
|
memset (priv->clip, 0, sizeof (gfloat) * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6830,6 +6851,8 @@ clutter_actor_set_scale (ClutterActor *self,
|
|||||||
|
|
||||||
priv = self->priv;
|
priv = self->priv;
|
||||||
|
|
||||||
|
priv->transform_valid = FALSE;
|
||||||
|
|
||||||
g_object_freeze_notify (G_OBJECT (self));
|
g_object_freeze_notify (G_OBJECT (self));
|
||||||
|
|
||||||
priv->scale_x = scale_x;
|
priv->scale_x = scale_x;
|
||||||
@ -6874,6 +6897,8 @@ clutter_actor_set_scale_full (ClutterActor *self,
|
|||||||
|
|
||||||
clutter_actor_set_scale (self, scale_x, scale_y);
|
clutter_actor_set_scale (self, scale_x, scale_y);
|
||||||
|
|
||||||
|
priv->transform_valid = FALSE;
|
||||||
|
|
||||||
if (priv->scale_center.is_fractional)
|
if (priv->scale_center.is_fractional)
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SCALE_GRAVITY]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SCALE_GRAVITY]);
|
||||||
|
|
||||||
@ -6921,6 +6946,8 @@ clutter_actor_set_scale_with_gravity (ClutterActor *self,
|
|||||||
|
|
||||||
clutter_actor_set_scale (self, scale_x, scale_y);
|
clutter_actor_set_scale (self, scale_x, scale_y);
|
||||||
|
|
||||||
|
priv->transform_valid = FALSE;
|
||||||
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SCALE_GRAVITY]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SCALE_GRAVITY]);
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SCALE_CENTER_X]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SCALE_CENTER_X]);
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SCALE_CENTER_Y]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SCALE_CENTER_Y]);
|
||||||
@ -7212,6 +7239,8 @@ clutter_actor_set_depth (ClutterActor *self,
|
|||||||
clutter_container_sort_depth_order (parent);
|
clutter_container_sort_depth_order (parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->transform_valid = FALSE;
|
||||||
|
|
||||||
clutter_actor_queue_redraw (self);
|
clutter_actor_queue_redraw (self);
|
||||||
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_DEPTH]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_DEPTH]);
|
||||||
@ -7296,6 +7325,8 @@ clutter_actor_set_rotation (ClutterActor *self,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->transform_valid = FALSE;
|
||||||
|
|
||||||
g_object_thaw_notify (G_OBJECT (self));
|
g_object_thaw_notify (G_OBJECT (self));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8205,7 +8236,10 @@ clutter_actor_set_anchor_point (ClutterActor *self,
|
|||||||
clutter_anchor_coord_set_units (&priv->anchor, anchor_x, anchor_y, 0);
|
clutter_anchor_coord_set_units (&priv->anchor, anchor_x, anchor_y, 0);
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
clutter_actor_queue_redraw (self);
|
{
|
||||||
|
priv->transform_valid = FALSE;
|
||||||
|
clutter_actor_queue_redraw (self);
|
||||||
|
}
|
||||||
|
|
||||||
g_object_thaw_notify (G_OBJECT (self));
|
g_object_thaw_notify (G_OBJECT (self));
|
||||||
}
|
}
|
||||||
@ -8350,6 +8384,8 @@ clutter_actor_set_anchor_point_from_gravity (ClutterActor *self,
|
|||||||
{
|
{
|
||||||
clutter_anchor_coord_set_gravity (&self->priv->anchor, gravity);
|
clutter_anchor_coord_set_gravity (&self->priv->anchor, gravity);
|
||||||
|
|
||||||
|
self->priv->transform_valid = FALSE;
|
||||||
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ANCHOR_GRAVITY]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ANCHOR_GRAVITY]);
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ANCHOR_X]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ANCHOR_X]);
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ANCHOR_Y]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ANCHOR_Y]);
|
||||||
|
Loading…
Reference in New Issue
Block a user