diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c index 911f5dbe4..6ac478d7a 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; + } - *result_out = - _clutter_paint_volume_cull (&priv->last_paint_volume, clip_frustum); + for (i = 0; i < clip_frusta->len; i++) + { + const graphene_frustum_t *clip_frustum = + &g_array_index (clip_frusta, graphene_frustum_t, i); - if (*result_out != CLUTTER_CULL_RESULT_OUT) + result = _clutter_paint_volume_cull (&priv->last_paint_volume, + clip_frustum); + + 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 ff26edf21..25592a6fe 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 d83dec157..b56d92aa7 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 ab1877f1d..9726ba0ba 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,41 @@ 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) : 0; + if (redraw_clip && n_rectangles < MAX_FRUSTA) + { + int i; + + clip_frusta = g_array_sized_new (FALSE, FALSE, + sizeof (graphene_frustum_t), + n_rectangles); + + 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 + { + clip_frusta = g_array_sized_new (FALSE, FALSE, + sizeof (graphene_frustum_t), + 1); + 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);