[mutter/gbsneto/graphene-frustrum: 1/4] clutter/stage: Use multiple frusta depending on the redraw clip




commit 29e2e79351c5ac92dc04b6c64ad3c1712ab20f62
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Sat Oct 10 11:17:58 2020 -0300

    clutter/stage: Use multiple frusta depending on the redraw clip
    
    The redraw clip region may contain multiple clip rectangles. We currently
    only use the extents of this region, but having multiple frusta for each
    rectangle is a better alternative, and will allow us to remove the extra
    projection we currently do.
    
    Make the clip frustum an array, with multiple frusta.
    
    https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1489

 clutter/clutter/clutter-actor.c                 | 32 ++++++++++++++++-----
 clutter/clutter/clutter-paint-context-private.h | 12 ++++----
 clutter/clutter/clutter-paint-context.c         | 20 ++++++-------
 clutter/clutter/clutter-stage.c                 | 37 +++++++++++++++++++++----
 4 files changed, 73 insertions(+), 28 deletions(-)
---
diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c
index 911f5dbe4a..6ac478d7a0 100644
--- a/clutter/clutter/clutter-actor.c
+++ b/clutter/clutter/clutter-actor.c
@@ -3449,7 +3449,9 @@ cull_actor (ClutterActor        *self,
             ClutterCullResult   *result_out)
 {
   ClutterActorPrivate *priv = self->priv;
-  const graphene_frustum_t *clip_frustum;
+  const GArray *clip_frusta;
+  ClutterCullResult result;
+  int i;
 
   if (!priv->last_paint_volume_valid)
     {
@@ -3470,12 +3472,26 @@ cull_actor (ClutterActor        *self,
       return FALSE;
     }
 
-  clip_frustum = clutter_paint_context_get_clip_frustum (paint_context);
+  clip_frusta = clutter_paint_context_get_clip_frusta (paint_context);
+  if (!clip_frusta)
+    {
+      *result_out = CLUTTER_CULL_RESULT_IN;
+      return TRUE;
+    }
+
+  for (i = 0; i < clip_frusta->len; i++)
+    {
+      const graphene_frustum_t *clip_frustum =
+        &g_array_index (clip_frusta, graphene_frustum_t, i);
 
-  *result_out =
-    _clutter_paint_volume_cull (&priv->last_paint_volume, clip_frustum);
+      result = _clutter_paint_volume_cull (&priv->last_paint_volume,
+                                           clip_frustum);
 
-  if (*result_out != CLUTTER_CULL_RESULT_OUT)
+      if (result != CLUTTER_CULL_RESULT_OUT)
+        break;
+    }
+
+  if (result != CLUTTER_CULL_RESULT_OUT)
     {
       const cairo_region_t *redraw_clip;
 
@@ -3504,15 +3520,17 @@ cull_actor (ClutterActor        *self,
             {
             case CAIRO_REGION_OVERLAP_IN:
             case CAIRO_REGION_OVERLAP_PART:
-              *result_out = CLUTTER_CULL_RESULT_IN;
+              result = CLUTTER_CULL_RESULT_IN;
               break;
             case CAIRO_REGION_OVERLAP_OUT:
-              *result_out = CLUTTER_CULL_RESULT_OUT;
+              result = CLUTTER_CULL_RESULT_OUT;
               break;
             }
         }
     }
 
+  *result_out = result;
+
   return TRUE;
 }
 
diff --git a/clutter/clutter/clutter-paint-context-private.h b/clutter/clutter/clutter-paint-context-private.h
index ff26edf21c..25592a6fef 100644
--- a/clutter/clutter/clutter-paint-context-private.h
+++ b/clutter/clutter/clutter-paint-context-private.h
@@ -21,16 +21,16 @@
 #include "clutter-paint-context.h"
 
 ClutterPaintContext *
-clutter_paint_context_new_for_view (ClutterStageView         *view,
-                                    const cairo_region_t     *redraw_clip,
-                                    const graphene_frustum_t *clip_frustum,
-                                    ClutterPaintFlag          paint_flags);
+clutter_paint_context_new_for_view (ClutterStageView     *view,
+                                    const cairo_region_t *redraw_clip,
+                                    GArray               *clip_frusta,
+                                    ClutterPaintFlag      paint_flags);
 
 gboolean clutter_paint_context_is_drawing_off_stage (ClutterPaintContext *paint_context);
 
 CoglFramebuffer * clutter_paint_context_get_base_framebuffer (ClutterPaintContext *paint_context);
 
-const graphene_frustum_t *
-clutter_paint_context_get_clip_frustum (ClutterPaintContext *paint_context);
+const GArray *
+clutter_paint_context_get_clip_frusta (ClutterPaintContext *paint_context);
 
 #endif /* CLUTTER_PAINT_CONTEXT_PRIVATE_H */
diff --git a/clutter/clutter/clutter-paint-context.c b/clutter/clutter/clutter-paint-context.c
index d83dec157e..b56d92aa78 100644
--- a/clutter/clutter/clutter-paint-context.c
+++ b/clutter/clutter/clutter-paint-context.c
@@ -30,7 +30,7 @@ struct _ClutterPaintContext
   ClutterStageView *view;
 
   cairo_region_t *redraw_clip;
-  graphene_frustum_t clip_frustum;
+  GArray *clip_frusta;
 };
 
 G_DEFINE_BOXED_TYPE (ClutterPaintContext, clutter_paint_context,
@@ -38,10 +38,10 @@ G_DEFINE_BOXED_TYPE (ClutterPaintContext, clutter_paint_context,
                      clutter_paint_context_unref)
 
 ClutterPaintContext *
-clutter_paint_context_new_for_view (ClutterStageView         *view,
-                                    const cairo_region_t     *redraw_clip,
-                                    const graphene_frustum_t *clip_frustum,
-                                    ClutterPaintFlag          paint_flags)
+clutter_paint_context_new_for_view (ClutterStageView     *view,
+                                    const cairo_region_t *redraw_clip,
+                                    GArray               *clip_frusta,
+                                    ClutterPaintFlag      paint_flags)
 {
   ClutterPaintContext *paint_context;
   CoglFramebuffer *framebuffer;
@@ -50,9 +50,8 @@ clutter_paint_context_new_for_view (ClutterStageView         *view,
   g_ref_count_init (&paint_context->ref_count);
   paint_context->view = view;
   paint_context->redraw_clip = cairo_region_copy (redraw_clip);
+  paint_context->clip_frusta = g_array_ref (clip_frusta);
   paint_context->paint_flags = paint_flags;
-  graphene_frustum_init_from_frustum (&paint_context->clip_frustum,
-                                      clip_frustum);
 
   framebuffer = clutter_stage_view_get_framebuffer (view);
   clutter_paint_context_push_framebuffer (paint_context, framebuffer);
@@ -93,6 +92,7 @@ clutter_paint_context_dispose (ClutterPaintContext *paint_context)
   g_list_free_full (paint_context->framebuffers, g_object_unref);
   paint_context->framebuffers = NULL;
   g_clear_pointer (&paint_context->redraw_clip, cairo_region_destroy);
+  g_clear_pointer (&paint_context->clip_frusta, g_array_unref);
 }
 
 void
@@ -137,10 +137,10 @@ clutter_paint_context_get_redraw_clip (ClutterPaintContext *paint_context)
   return paint_context->redraw_clip;
 }
 
-const graphene_frustum_t *
-clutter_paint_context_get_clip_frustum (ClutterPaintContext *paint_context)
+const GArray *
+clutter_paint_context_get_clip_frusta (ClutterPaintContext *paint_context)
 {
-  return &paint_context->clip_frustum;
+  return paint_context->clip_frusta;
 }
 
 /**
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index ab1877f1db..a46ef5b3ff 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -77,6 +77,8 @@
 
 #include "cogl/cogl.h"
 
+#define MAX_FRUSTA 64
+
 struct _ClutterStageQueueRedrawEntry
 {
   ClutterActor *actor;
@@ -814,8 +816,6 @@ setup_view_for_paint (ClutterStage                *stage,
                                              &priv->inverse_projection,
                                              &priv->perspective,
                                              out_frustum);
-
-  _clutter_stage_paint_volume_stack_free_all (stage);
 }
 
 static void
@@ -826,7 +826,9 @@ clutter_stage_do_paint_view (ClutterStage         *stage,
   ClutterStagePrivate *priv = stage->priv;
   ClutterPaintContext *paint_context;
   cairo_rectangle_int_t clip_rect;
+  g_autoptr (GArray) clip_frusta = NULL;
   graphene_frustum_t clip_frustum;
+  int n_rectangles;
 
   /* Any mode of painting/picking invalidates the pick cache, unless we're
    * in the middle of building it. So we reset the cached flag but don't
@@ -834,12 +836,37 @@ clutter_stage_do_paint_view (ClutterStage         *stage,
    */
   priv->cached_pick_mode = CLUTTER_PICK_NONE;
 
-  cairo_region_get_extents (redraw_clip, &clip_rect);
-  setup_view_for_paint (stage, view, &clip_rect, &clip_frustum);
+  n_rectangles = redraw_clip ? cairo_region_num_rectangles (redraw_clip) : 1;
+  clip_frusta = g_array_sized_new (FALSE, FALSE,
+                                   sizeof (graphene_frustum_t),
+                                   n_rectangles);
+  if (redraw_clip && n_rectangles < MAX_FRUSTA)
+    {
+      int i;
+
+      for (i = 0; i < n_rectangles; i++)
+        {
+          cairo_region_get_rectangle (redraw_clip, i, &clip_rect);
+          setup_view_for_paint (stage, view, &clip_rect, &clip_frustum);
+          g_array_append_val (clip_frusta, clip_frustum);
+        }
+    }
+  else
+    {
+      if (redraw_clip)
+        cairo_region_get_extents (redraw_clip, &clip_rect);
+      else
+        clutter_stage_view_get_layout (view, &clip_rect);
+
+      setup_view_for_paint (stage, view, &clip_rect, &clip_frustum);
+      g_array_append_val (clip_frusta, clip_frustum);
+    }
+
+  _clutter_stage_paint_volume_stack_free_all (stage);
 
   paint_context = clutter_paint_context_new_for_view (view,
                                                       redraw_clip,
-                                                      &clip_frustum,
+                                                      clip_frusta,
                                                       CLUTTER_PAINT_FLAG_NONE);
 
   clutter_actor_paint (CLUTTER_ACTOR (stage), paint_context);


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