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




commit c447492adc10ea44cfb118a8a7bbf6dca2d36697
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                 | 33 +++++++++++++++++++++----
 4 files changed, 69 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 2153fdb6f6..7baa916c9b 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);
@@ -94,6 +93,7 @@ clutter_paint_context_dispose (ClutterPaintContext *paint_context)
                     cogl_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
@@ -138,10 +138,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 757647d9e4..e7b97bc9e5 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,6 +826,7 @@ 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;
 
   /* Any mode of painting/picking invalidates the pick cache, unless we're
@@ -834,12 +835,34 @@ 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);
+  clip_frusta = g_array_new (FALSE, FALSE, sizeof (graphene_frustum_t));
+  if (redraw_clip && cairo_region_num_rectangles (redraw_clip) < MAX_FRUSTA)
+    {
+      int i;
+
+      for (i = 0; i < cairo_region_num_rectangles (redraw_clip); 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]