[mutter/gbsneto/graphene-frustrum: 4/4] clutter/stage: Replace _cogl_util_get_eye_planes_for_screen_poly()




commit bc41a88c92846020d06bbc9f03b6c0a55ce4c99f
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Tue Oct 13 16:07:14 2020 -0300

    clutter/stage: Replace _cogl_util_get_eye_planes_for_screen_poly()
    
    _cogl_util_get_eye_planes_for_screen_poly() is quite a complicated beast. Ever
    since Clutter became a compositor toolkit, and specially after we switched to
    graphene_frustum_t on paint volumes, we can brutally simplify this function.
    
    The new code assumes camera is at (0, 0, 0) at world coordinates (i.e. before
    applying the projection). We also consider that the redraw clip are at stage
    coordinates. That means that converting the clip rectangle to world rectangle
    is simply a matter of projecting the corresponding vertices using the "view"
    matrix. Furthermore, we only need to project the top-left, and bottom-right
    vertices, since top-right and bottom-left can be derived from those two.
    
    The frustum setup still uses triplets of vertices to setup the planes, except
    now the first vertex is always the camera (hardcoded to 0, 0, 0), and the other
    two vertices are the projected clip rectangle vertices.
    
    https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1489

 clutter/clutter/clutter-stage.c | 170 +++++++++-------------------------------
 1 file changed, 36 insertions(+), 134 deletions(-)
---
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 297d3b5020..70661ede0c 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -653,107 +653,58 @@ clutter_stage_allocate (ClutterActor           *self,
   clutter_stage_set_viewport (CLUTTER_STAGE (self), new_width, new_height);
 }
 
-typedef struct _Vector4
-{
-  float x, y, z, w;
-} Vector4;
-
 static void
-_cogl_util_get_eye_planes_for_screen_poly (float                    *polygon,
-                                           int                       n_vertices,
-                                           float                    *viewport,
-                                           const graphene_matrix_t  *projection,
-                                           const graphene_matrix_t  *inverse_project,
-                                           const ClutterPerspective *perspective,
-                                           graphene_frustum_t       *frustum)
+setup_clip_frustum (ClutterStage                *stage,
+                    const cairo_rectangle_int_t *clip,
+                    graphene_frustum_t          *frustum)
 {
+  ClutterStagePrivate *priv = stage->priv;
+  cairo_rectangle_int_t geom;
+  graphene_point3d_t camera_position;
+  graphene_point3d_t p[4];
   graphene_plane_t planes[6];
   graphene_vec4_t v;
-  float Wc;
-  Vector4 *tmp_poly;
   int i;
-  Vector4 *poly;
-  float zw, ww;
 
-  tmp_poly = g_alloca (sizeof (Vector4) * n_vertices * 2);
+  _clutter_stage_window_get_geometry (priv->impl, &geom);
 
-#define DEPTH -50
+  CLUTTER_NOTE (CLIPPING, "Creating stage clip frustum for "
+                "x=%d, y=%d, width=%d, height=%d",
+                clip->x, clip->y, clip->width, clip->height);
 
-  /* Determine W in clip-space (Wc) for a point (0, 0, DEPTH, 1)
-   *
-   * Note: the depth could be anything except 0.
-   *
-   * We will transform the polygon into clip coordinates using this
-   * depth and then into eye coordinates. Our clip planes will be
-   * defined by triangles that extend between points of the polygon at
-   * DEPTH and corresponding points of the same polygon at DEPTH * 2.
-   *
-   * NB: Wc defines the position of the clip planes in clip
-   * coordinates. Given a screen aligned cross section through the
-   * frustum; coordinates range from [-Wc,Wc] left to right on the
-   * x-axis and [Wc,-Wc] top to bottom on the y-axis.
-   */
-  zw = graphene_matrix_get_value (projection, 2, 3);
-  ww = graphene_matrix_get_value (projection, 3, 3);
-  Wc = DEPTH * zw + ww;
+  camera_position = GRAPHENE_POINT3D_INIT_ZERO;
 
-#define CLIP_X(X) ((((float)X - viewport[0]) * (2.0 / viewport[2])) - 1) * Wc
-#define CLIP_Y(Y) ((((float)Y - viewport[1]) * (2.0 / viewport[3])) - 1) * -Wc
+  p[0] = GRAPHENE_POINT3D_INIT (MAX (clip->x, 0), MAX (clip->y, 0), 0.f);
+  p[2] = GRAPHENE_POINT3D_INIT (MIN (clip->x + clip->width, geom.width),
+                                MIN (clip->y + clip->height, geom.height),
+                                0.f);
 
-  for (i = 0; i < n_vertices; i++)
+  for (i = 0; i < 2; i++)
     {
-      tmp_poly[i].x = CLIP_X (polygon[i * 2]);
-      tmp_poly[i].y = CLIP_Y (polygon[i * 2 + 1]);
-      tmp_poly[i].z = DEPTH;
-      tmp_poly[i].w = Wc;
+      float w = 1.0;
+      cogl_graphene_matrix_project_point (&priv->view,
+                                          &p[2 * i].x,
+                                          &p[2 * i].y,
+                                          &p[2 * i].z,
+                                          &w);
     }
 
-  Wc = DEPTH * 2 * zw + ww;
+  graphene_point3d_init (&p[1], p[2].x, p[0].y, p[0].z);
+  graphene_point3d_init (&p[3], p[0].x, p[2].y, p[0].z);
 
-  /* FIXME: technically we don't need to project all of the points
-   * twice, it would be enough project every other point since
-   * we can share points in this set to define the plane vectors. */
-  for (i = 0; i < n_vertices; i++)
+  for (i = 0; i < 4; i++)
     {
-      tmp_poly[n_vertices + i].x = CLIP_X (polygon[i * 2]);
-      tmp_poly[n_vertices + i].y = CLIP_Y (polygon[i * 2 + 1]);
-      tmp_poly[n_vertices + i].z = DEPTH * 2;
-      tmp_poly[n_vertices + i].w = Wc;
+      graphene_plane_init_from_points (&planes[i],
+                                       &camera_position,
+                                       &p[i],
+                                       &p[(i + 1) % 4]);
     }
 
-#undef CLIP_X
-#undef CLIP_Y
-
-  cogl_graphene_matrix_project_points (inverse_project,
-                                       4,
-                                       sizeof (Vector4),
-                                       tmp_poly,
-                                       sizeof (Vector4),
-                                       tmp_poly,
-                                       n_vertices * 2);
-
-  for (i = 0; i < n_vertices; i++)
-    {
-      graphene_point3d_t p[3];
-
-      poly = &tmp_poly[i];
-      graphene_point3d_init (&p[0], poly->x, poly->y, poly->z);
-
-      poly = &tmp_poly[n_vertices + i];
-      graphene_point3d_init (&p[1], poly->x, poly->y, poly->z);
-
-      poly = &tmp_poly[n_vertices + ((i + 1) % n_vertices)];
-      graphene_point3d_init (&p[2], poly->x, poly->y, poly->z);
-
-      graphene_plane_init_from_points (&planes[i], &p[0], &p[1], &p[2]);
-    }
+  graphene_vec4_init (&v, 0.f, 0.f, -1.f, priv->perspective.z_near);
+  graphene_plane_init_from_vec4 (&planes[4], &v);
 
-  graphene_plane_init_from_vec4 (&planes[4],
-                                 graphene_vec4_init (&v, 0.f, 0.f, -1.f,
-                                                     perspective->z_near));
-  graphene_plane_init_from_vec4 (&planes[5],
-                                 graphene_vec4_init (&v, 0.f, 0.f, 1.f,
-                                                     perspective->z_far));
+  graphene_vec4_init (&v, 0.f, 0.f, 1.f, priv->perspective.z_far);
+  graphene_plane_init_from_vec4 (&planes[5], &v);
 
   graphene_frustum_init (frustum,
                          &planes[0], &planes[1],
@@ -761,55 +712,6 @@ _cogl_util_get_eye_planes_for_screen_poly (float                    *polygon,
                          &planes[4], &planes[5]);
 }
 
-/* XXX: Instead of having a toplevel 2D clip region, it might be
- * better to have a clip volume within the view frustum. This could
- * allow us to avoid projecting actors into window coordinates to
- * be able to cull them.
- */
-static void
-setup_view_for_paint (ClutterStage                *stage,
-                      const cairo_rectangle_int_t *clip,
-                      graphene_frustum_t          *out_frustum)
-{
-  ClutterStagePrivate *priv = stage->priv;
-  float clip_poly[8];
-  float viewport[4];
-  cairo_rectangle_int_t geom;
-
-  _clutter_stage_window_get_geometry (priv->impl, &geom);
-
-  viewport[0] = priv->viewport[0];
-  viewport[1] = priv->viewport[1];
-  viewport[2] = priv->viewport[2];
-  viewport[3] = priv->viewport[3];
-
-  clip_poly[0] = MAX (clip->x, 0);
-  clip_poly[1] = MAX (clip->y, 0);
-
-  clip_poly[2] = MIN (clip->x + clip->width, geom.width);
-  clip_poly[3] = clip_poly[1];
-
-  clip_poly[4] = clip_poly[2];
-  clip_poly[5] = MIN (clip->y + clip->height, geom.height);
-
-  clip_poly[6] = clip_poly[0];
-  clip_poly[7] = clip_poly[5];
-
-  CLUTTER_NOTE (CLIPPING, "Setting stage clip too: "
-                "x=%f, y=%f, width=%f, height=%f",
-                clip_poly[0], clip_poly[1],
-                clip_poly[2] - clip_poly[0],
-                clip_poly[5] - clip_poly[1]);
-
-  _cogl_util_get_eye_planes_for_screen_poly (clip_poly,
-                                             4,
-                                             viewport,
-                                             &priv->projection,
-                                             &priv->inverse_projection,
-                                             &priv->perspective,
-                                             out_frustum);
-}
-
 static void
 clutter_stage_do_paint_view (ClutterStage         *stage,
                              ClutterStageView     *view,
@@ -840,7 +742,7 @@ clutter_stage_do_paint_view (ClutterStage         *stage,
       for (i = 0; i < n_rectangles; i++)
         {
           cairo_region_get_rectangle (redraw_clip, i, &clip_rect);
-          setup_view_for_paint (stage, &clip_rect, &clip_frustum);
+          setup_clip_frustum (stage, &clip_rect, &clip_frustum);
           g_array_append_val (clip_frusta, clip_frustum);
         }
     }
@@ -854,7 +756,7 @@ clutter_stage_do_paint_view (ClutterStage         *stage,
       else
         clutter_stage_view_get_layout (view, &clip_rect);
 
-      setup_view_for_paint (stage, &clip_rect, &clip_frustum);
+      setup_clip_frustum (stage, &clip_rect, &clip_frustum);
       g_array_append_val (clip_frusta, clip_frustum);
     }
 


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