[mutter] clutter/actor: Cache transformations applied using apply_transform vfunc



commit 64304b0b68d22325cbd6196612793323937c6f32
Author: Jonas Dreßler <verdre v0yd nl>
Date:   Thu Mar 12 12:13:53 2020 +0100

    clutter/actor: Cache transformations applied using apply_transform vfunc
    
    If we want to invalidate the stage-views list reliably on changes to the
    actors transformation matrices, we also need to get notified about
    changes to the custom transformations applied using the
    apply_transform() vfunc.
    
    So provide a new API that allows invalidating the transformation matrix
    for actors implementing custom transformations, too. This in turn allows
    us to cache the matrix applied using the apply_transform() vfunc by
    moving responsibility of keeping track of the caching from
    clutter_actor_real_apply_transform() to
    _clutter_actor_apply_modelview_transform().
    
    https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1343

 clutter/clutter/clutter-actor.c | 60 ++++++++++++++++++++++++++---------------
 clutter/clutter/clutter-actor.h |  8 +++++-
 clutter/clutter/clutter-clone.c |  1 +
 clutter/clutter/clutter-stage.c |  2 ++
 4 files changed, 48 insertions(+), 23 deletions(-)
---
diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c
index 86ffe2f1f0..052c84a166 100644
--- a/clutter/clutter/clutter-actor.c
+++ b/clutter/clutter/clutter-actor.c
@@ -3034,14 +3034,9 @@ clutter_actor_real_apply_transform (ClutterActor  *self,
                                     ClutterMatrix *matrix)
 {
   ClutterActorPrivate *priv = self->priv;
-  CoglMatrix *transform = &priv->transform;
   const ClutterTransformInfo *info;
   float pivot_x = 0.f, pivot_y = 0.f;
 
-  /* we already have a cached transformation */
-  if (priv->transform_valid)
-    goto multiply_and_return;
-
   info = _clutter_actor_get_transform_info_or_defaults (self);
 
   /* compute the pivot point given the allocated size */
@@ -3067,10 +3062,10 @@ clutter_actor_real_apply_transform (ClutterActor  *self,
       const ClutterTransformInfo *parent_info;
 
       parent_info = _clutter_actor_get_transform_info_or_defaults (priv->parent);
-      clutter_matrix_init_from_matrix (transform, &(parent_info->child_transform));
+      clutter_matrix_init_from_matrix (matrix, &(parent_info->child_transform));
     }
   else
-    clutter_matrix_init_identity (transform);
+    clutter_matrix_init_identity (matrix);
 
   /* if we have an overriding transformation, we use that, and get out */
   if (info->transform_set)
@@ -3079,11 +3074,11 @@ clutter_actor_real_apply_transform (ClutterActor  *self,
        * translations, since :transform is relative to the actor's coordinate
        * space, and to the pivot point
        */
-      cogl_matrix_translate (transform,
+      cogl_matrix_translate (matrix,
                              priv->allocation.x1 + pivot_x,
                              priv->allocation.y1 + pivot_y,
                              info->pivot_z);
-      cogl_matrix_multiply (transform, transform, &info->transform);
+      cogl_matrix_multiply (matrix, matrix, &info->transform);
       goto roll_back_pivot;
     }
 
@@ -3091,7 +3086,7 @@ clutter_actor_real_apply_transform (ClutterActor  *self,
    * of decomposing the pivot and translation info separate operations,
    * we just compose everything into a single translation
    */
-  cogl_matrix_translate (transform,
+  cogl_matrix_translate (matrix,
                          priv->allocation.x1 + pivot_x + info->translation.x,
                          priv->allocation.y1 + pivot_y + info->translation.y,
                          info->z_position + info->pivot_z + info->translation.z);
@@ -3108,27 +3103,21 @@ clutter_actor_real_apply_transform (ClutterActor  *self,
    * code we use when interpolating transformations
    */
   if (info->scale_x != 1.0 || info->scale_y != 1.0 || info->scale_z != 1.0)
-    cogl_matrix_scale (transform, info->scale_x, info->scale_y, info->scale_z);
+    cogl_matrix_scale (matrix, info->scale_x, info->scale_y, info->scale_z);
 
   if (info->rz_angle)
-    cogl_matrix_rotate (transform, info->rz_angle, 0, 0, 1.0);
+    cogl_matrix_rotate (matrix, info->rz_angle, 0, 0, 1.0);
 
   if (info->ry_angle)
-    cogl_matrix_rotate (transform, info->ry_angle, 0, 1.0, 0);
+    cogl_matrix_rotate (matrix, info->ry_angle, 0, 1.0, 0);
 
   if (info->rx_angle)
-    cogl_matrix_rotate (transform, info->rx_angle, 1.0, 0, 0);
+    cogl_matrix_rotate (matrix, info->rx_angle, 1.0, 0, 0);
 
 roll_back_pivot:
   /* roll back the pivot translation */
   if (pivot_x != 0.f || pivot_y != 0.f || info->pivot_z != 0.f)
-    cogl_matrix_translate (transform, -pivot_x, -pivot_y, -info->pivot_z);
-
-  /* we have a valid modelview */
-  priv->transform_valid = TRUE;
-
-multiply_and_return:
-  cogl_matrix_multiply (matrix, matrix, &priv->transform);
+    cogl_matrix_translate (matrix, -pivot_x, -pivot_y, -info->pivot_z);
 }
 
 /* Applies the transforms associated with this actor to the given
@@ -3137,7 +3126,17 @@ void
 _clutter_actor_apply_modelview_transform (ClutterActor  *self,
                                           ClutterMatrix *matrix)
 {
-  CLUTTER_ACTOR_GET_CLASS (self)->apply_transform (self, matrix);
+  ClutterActorPrivate *priv = self->priv;
+
+  if (priv->transform_valid)
+    goto out;
+
+  CLUTTER_ACTOR_GET_CLASS (self)->apply_transform (self, &priv->transform);
+
+  priv->transform_valid = TRUE;
+
+out:
+  cogl_matrix_multiply (matrix, matrix, &priv->transform);
 }
 
 /*
@@ -19739,3 +19738,20 @@ clutter_actor_queue_immediate_relayout (ClutterActor *self)
   if (stage)
     clutter_stage_set_actor_needs_immediate_relayout (stage);
 }
+
+/**
+ * clutter_actor_invalidate_transform:
+ * @self: A #ClutterActor
+ *
+ * Invalidate the cached transformation matrix of @self.
+ * This is needed for implementations overriding the apply_transform()
+ * vfunc and has to be called if the matrix returned by apply_transform()
+ * would change.
+ */
+void
+clutter_actor_invalidate_transform (ClutterActor *self)
+{
+  g_return_if_fail (CLUTTER_IS_ACTOR (self));
+
+  self->priv->transform_valid = FALSE;
+}
diff --git a/clutter/clutter/clutter-actor.h b/clutter/clutter/clutter-actor.h
index 67d327b5b4..128acac1a3 100644
--- a/clutter/clutter/clutter-actor.h
+++ b/clutter/clutter/clutter-actor.h
@@ -178,7 +178,10 @@ struct _ClutterActor
  *   implementation.
  * @apply_transform: virtual function, used when applying the transformations
  *   to an actor before painting it or when transforming coordinates or
- *   the allocation; it must chain up to the parent's implementation
+ *   the allocation; if the transformation calculated by this function may
+ *   have changed, the cached transformation must be invalidated by calling
+ *   clutter_actor_invalidate_transform(); it must chain up to the parent's
+ *   implementation
  * @parent_set: signal class handler for the #ClutterActor::parent-set
  * @destroy: signal class handler for #ClutterActor::destroy. It must
  *   chain up to the parent's implementation
@@ -918,6 +921,9 @@ void clutter_actor_pick_box (ClutterActor          *self,
 CLUTTER_EXPORT
 GList * clutter_actor_peek_stage_views (ClutterActor *self);
 
+CLUTTER_EXPORT
+void clutter_actor_invalidate_transform (ClutterActor *self);
+
 G_END_DECLS
 
 #endif /* __CLUTTER_ACTOR_H__ */
diff --git a/clutter/clutter/clutter-clone.c b/clutter/clutter/clutter-clone.c
index fe34359d8e..f130a3c98e 100644
--- a/clutter/clutter/clutter-clone.c
+++ b/clutter/clutter/clutter-clone.c
@@ -262,6 +262,7 @@ clutter_clone_allocate (ClutterActor           *self,
     {
       priv->x_scale = x_scale;
       priv->y_scale = y_scale;
+      clutter_actor_invalidate_transform (CLUTTER_ACTOR (self));
     }
 
 #if 0
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 8d3fc8b800..df3a4c3c33 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -2905,6 +2905,8 @@ clutter_stage_update_view_perspective (ClutterStage *stage)
                                       z_2d,
                                       priv->viewport[2],
                                       priv->viewport[3]);
+
+  clutter_actor_invalidate_transform (CLUTTER_ACTOR (stage));
 }
 
 void


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