[mutter] stage: Compute view perspective when parameters changed



commit b69d2aa6a0e0e8d69354f6eda0bb9ab68a76f2ee
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Thu Sep 19 11:27:50 2019 +0200

    stage: Compute view perspective when parameters changed
    
    Clutter stage used to compute the initial projection using a fixed z
    translation which wasn't matching the one we computed in
    calculate_z_translation().
    This caused to have a wrong initial projection on startup which was then
    correctly recomputed only at the first paint.
    
    However, since this calculation doesn't depend on view, but only on viewport
    size, perspective's fovy and z_near we can safely do this at startup and
    only when any of those parameters change.
    
    Then we can move the computation out _clutter_stage_maybe_setup_viewport()
    since the cogl framebuffer viewport sizes aren't affecting this.
    
    Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1639
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/803

 clutter/clutter/clutter-stage.c | 104 ++++++++++++++++++----------------------
 1 file changed, 47 insertions(+), 57 deletions(-)
---
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 85dc406a8..245cb8997 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -226,6 +226,7 @@ static void capture_view_into (ClutterStage          *stage,
                                cairo_rectangle_int_t *rect,
                                uint8_t               *data,
                                int                    stride);
+static void clutter_stage_update_view_perspective (ClutterStage *stage);
 
 static void clutter_container_iface_init (ClutterContainerIface *iface);
 
@@ -2354,29 +2355,6 @@ clutter_stage_init (ClutterStage *self)
   clutter_actor_set_background_color (CLUTTER_ACTOR (self),
                                       &default_stage_color);
 
-  priv->perspective.fovy   = 60.0; /* 60 Degrees */
-  priv->perspective.aspect = (float) geom.width / (float) geom.height;
-  priv->perspective.z_near = 0.1;
-  priv->perspective.z_far  = 100.0;
-
-  cogl_matrix_init_identity (&priv->projection);
-  cogl_matrix_perspective (&priv->projection,
-                           priv->perspective.fovy,
-                           priv->perspective.aspect,
-                           priv->perspective.z_near,
-                           priv->perspective.z_far);
-  cogl_matrix_get_inverse (&priv->projection,
-                           &priv->inverse_projection);
-  cogl_matrix_init_identity (&priv->view);
-  cogl_matrix_view_2d_in_perspective (&priv->view,
-                                      priv->perspective.fovy,
-                                      priv->perspective.aspect,
-                                      priv->perspective.z_near,
-                                      50, /* distance to 2d plane */
-                                      geom.width,
-                                      geom.height);
-
-
   /* FIXME - remove for 2.0 */
   priv->fog.z_near = 1.0;
   priv->fog.z_far  = 2.0;
@@ -2544,6 +2522,7 @@ clutter_stage_set_perspective (ClutterStage       *stage,
   priv->has_custom_perspective = TRUE;
 
   clutter_stage_set_perspective_internal (stage, perspective);
+  clutter_stage_update_view_perspective (stage);
 }
 
 /**
@@ -2670,6 +2649,7 @@ _clutter_stage_set_viewport (ClutterStage *stage,
   priv->viewport[2] = width;
   priv->viewport[3] = height;
 
+  clutter_stage_update_view_perspective (stage);
   _clutter_stage_dirty_viewport (stage);
 
   queue_full_redraw (stage);
@@ -3506,6 +3486,50 @@ calculate_z_translation (float z_near)
        + z_near;
 }
 
+static void
+clutter_stage_update_view_perspective (ClutterStage *stage)
+{
+  ClutterStagePrivate *priv = stage->priv;
+  ClutterPerspective perspective;
+  float z_2d;
+
+  perspective = priv->perspective;
+
+  /* Ideally we want to regenerate the perspective matrix whenever
+   * the size changes but if the user has provided a custom matrix
+   * then we don't want to override it */
+  if (!priv->has_custom_perspective)
+    {
+      perspective.fovy = 60.0; /* 60 Degrees */
+      perspective.z_near = 0.1;
+      perspective.aspect = priv->viewport[2] / priv->viewport[3];
+      z_2d = calculate_z_translation (perspective.z_near);
+
+      /* NB: z_2d is only enough room for 85% of the stage_height between
+       * the stage and the z_near plane. For behind the stage plane we
+       * want a more consistent gap of 10 times the stage_height before
+       * hitting the far plane so we calculate that relative to the final
+       * height of the stage plane at the z_2d_distance we got... */
+      perspective.z_far = z_2d +
+        tanf (_DEG_TO_RAD (perspective.fovy / 2.0f)) * z_2d * 20.0f;
+
+      clutter_stage_set_perspective_internal (stage, &perspective);
+    }
+  else
+    {
+      z_2d = calculate_z_translation (perspective.z_near);
+    }
+
+  cogl_matrix_init_identity (&priv->view);
+  cogl_matrix_view_2d_in_perspective (&priv->view,
+                                      perspective.fovy,
+                                      perspective.aspect,
+                                      perspective.z_near,
+                                      z_2d,
+                                      priv->viewport[2],
+                                      priv->viewport[3]);
+}
+
 void
 _clutter_stage_maybe_setup_viewport (ClutterStage     *stage,
                                      ClutterStageView *view)
@@ -3516,7 +3540,6 @@ _clutter_stage_maybe_setup_viewport (ClutterStage     *stage,
   if (clutter_stage_view_is_dirty_viewport (view))
     {
       cairo_rectangle_int_t view_layout;
-      ClutterPerspective perspective;
       float fb_scale;
       float viewport_offset_x;
       float viewport_offset_y;
@@ -3524,7 +3547,6 @@ _clutter_stage_maybe_setup_viewport (ClutterStage     *stage,
       float viewport_y;
       float viewport_width;
       float viewport_height;
-      float z_2d;
 
       CLUTTER_NOTE (PAINT,
                     "Setting up the viewport { w:%f, h:%f }",
@@ -3544,38 +3566,6 @@ _clutter_stage_maybe_setup_viewport (ClutterStage     *stage,
                                      viewport_x, viewport_y,
                                      viewport_width, viewport_height);
 
-      perspective = priv->perspective;
-
-      /* Ideally we want to regenerate the perspective matrix whenever
-       * the size changes but if the user has provided a custom matrix
-       * then we don't want to override it */
-      if (!priv->has_custom_perspective)
-        {
-          perspective.aspect = priv->viewport[2] / priv->viewport[3];
-          z_2d = calculate_z_translation (perspective.z_near);
-
-          /* NB: z_2d is only enough room for 85% of the stage_height between
-           * the stage and the z_near plane. For behind the stage plane we
-           * want a more consistent gap of 10 times the stage_height before
-           * hitting the far plane so we calculate that relative to the final
-           * height of the stage plane at the z_2d_distance we got... */
-          perspective.z_far = z_2d +
-            tanf (_DEG_TO_RAD (perspective.fovy / 2.0f)) * z_2d * 20.0f;
-
-          clutter_stage_set_perspective_internal (stage, &perspective);
-        }
-      else
-        z_2d = calculate_z_translation (perspective.z_near);
-
-      cogl_matrix_init_identity (&priv->view);
-      cogl_matrix_view_2d_in_perspective (&priv->view,
-                                          perspective.fovy,
-                                          perspective.aspect,
-                                          perspective.z_near,
-                                          z_2d,
-                                          priv->viewport[2],
-                                          priv->viewport[3]);
-
       clutter_stage_view_set_dirty_viewport (view, FALSE);
     }
 


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