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




commit 983d93251ce6a9e9e9fd7b53c3ad1baf44bd22b0
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..7cca989e34 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -77,6 +77,8 @@
 
 #include "cogl/cogl.h"
 
+#define MAX_FRUSTA 16
+
 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]