summaryrefslogtreecommitdiff
path: root/clutter/clutter/clutter-stage.c
diff options
context:
space:
mode:
Diffstat (limited to 'clutter/clutter/clutter-stage.c')
-rw-r--r--clutter/clutter/clutter-stage.c161
1 files changed, 93 insertions, 68 deletions
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 3808d2955..aa64c0277 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -1054,68 +1054,6 @@ is_full_stage_redraw_queued (ClutterStage *stage)
return TRUE;
}
-static gboolean
-clutter_stage_real_queue_redraw (ClutterActor *actor,
- ClutterActor *leaf,
- ClutterPaintVolume *redraw_clip)
-{
- ClutterStage *stage = CLUTTER_STAGE (actor);
- ClutterStageWindow *stage_window;
- ClutterActorBox bounding_box;
- ClutterActorBox intersection_box;
- cairo_rectangle_int_t geom, stage_clip;
-
- if (CLUTTER_ACTOR_IN_DESTRUCTION (actor))
- return TRUE;
-
- /* If the backend can't do anything with redraw clips (e.g. it already knows
- * it needs to redraw everything anyway) then don't spend time transforming
- * any clip volume into stage coordinates... */
- stage_window = _clutter_stage_get_window (stage);
- if (stage_window == NULL)
- return TRUE;
-
- if (is_full_stage_redraw_queued (stage))
- return FALSE;
-
- if (redraw_clip == NULL)
- {
- clutter_stage_add_redraw_clip (stage, NULL);
- return FALSE;
- }
-
- if (redraw_clip->is_empty)
- return TRUE;
-
- /* Convert the clip volume into stage coordinates and then into an
- * axis aligned stage coordinates bounding box... */
- _clutter_paint_volume_get_stage_paint_box (redraw_clip,
- stage,
- &bounding_box);
-
- _clutter_stage_window_get_geometry (stage_window, &geom);
-
- intersection_box.x1 = MAX (bounding_box.x1, 0);
- intersection_box.y1 = MAX (bounding_box.y1, 0);
- intersection_box.x2 = MIN (bounding_box.x2, geom.width);
- intersection_box.y2 = MIN (bounding_box.y2, geom.height);
-
- /* There is no need to track degenerate/empty redraw clips */
- if (intersection_box.x2 <= intersection_box.x1 ||
- intersection_box.y2 <= intersection_box.y1)
- return TRUE;
-
- /* when converting to integer coordinates make sure we round the edges of the
- * clip rectangle outwards... */
- stage_clip.x = intersection_box.x1;
- stage_clip.y = intersection_box.y1;
- stage_clip.width = intersection_box.x2 - stage_clip.x;
- stage_clip.height = intersection_box.y2 - stage_clip.y;
-
- clutter_stage_add_redraw_clip (stage, &stage_clip);
- return FALSE;
-}
-
gboolean
_clutter_stage_has_full_redraw_queued (ClutterStage *stage)
{
@@ -1437,7 +1375,6 @@ clutter_stage_class_init (ClutterStageClass *klass)
actor_class->hide = clutter_stage_hide;
actor_class->hide_all = clutter_stage_hide_all;
actor_class->queue_relayout = clutter_stage_real_queue_relayout;
- actor_class->queue_redraw = clutter_stage_real_queue_redraw;
actor_class->apply_transform = clutter_stage_real_apply_transform;
klass->paint_view = clutter_stage_real_paint_view;
@@ -2882,6 +2819,65 @@ _clutter_stage_queue_redraw_entry_invalidate (ClutterStageQueueRedrawEntry *entr
}
}
+static void
+add_to_stage_clip (ClutterStage *stage,
+ ClutterPaintVolume *redraw_clip)
+{
+ ClutterStageWindow *stage_window;
+ ClutterActorBox bounding_box;
+ ClutterActorBox intersection_box;
+ cairo_rectangle_int_t geom, stage_clip;
+
+ if (CLUTTER_ACTOR_IN_DESTRUCTION (CLUTTER_ACTOR (stage)))
+ return;
+
+ /* If the backend can't do anything with redraw clips (e.g. it already knows
+ * it needs to redraw everything anyway) then don't spend time transforming
+ * any clip volume into stage coordinates... */
+ stage_window = _clutter_stage_get_window (stage);
+ if (stage_window == NULL)
+ return;
+
+ if (is_full_stage_redraw_queued (stage))
+ return;
+
+ if (redraw_clip == NULL)
+ {
+ clutter_stage_add_redraw_clip (stage, NULL);
+ return;
+ }
+
+ if (redraw_clip->is_empty)
+ return;
+
+ /* Convert the clip volume into stage coordinates and then into an
+ * axis aligned stage coordinates bounding box... */
+ _clutter_paint_volume_get_stage_paint_box (redraw_clip,
+ stage,
+ &bounding_box);
+
+ _clutter_stage_window_get_geometry (stage_window, &geom);
+
+ intersection_box.x1 = MAX (bounding_box.x1, 0);
+ intersection_box.y1 = MAX (bounding_box.y1, 0);
+ intersection_box.x2 = MIN (bounding_box.x2, geom.width);
+ intersection_box.y2 = MIN (bounding_box.y2, geom.height);
+
+ /* There is no need to track degenerate/empty redraw clips */
+ if (intersection_box.x2 <= intersection_box.x1 ||
+ intersection_box.y2 <= intersection_box.y1)
+ return;
+
+ /* when converting to integer coordinates make sure we round the edges of the
+ * clip rectangle outwards... */
+ stage_clip.x = intersection_box.x1;
+ stage_clip.y = intersection_box.y1;
+ stage_clip.width = intersection_box.x2 - stage_clip.x;
+ stage_clip.height = intersection_box.y2 - stage_clip.y;
+
+ clutter_stage_add_redraw_clip (stage, &stage_clip);
+}
+
void
clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage)
{
@@ -2913,15 +2909,44 @@ clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage)
for (l = stolen_list; l; l = l->next)
{
ClutterStageQueueRedrawEntry *entry = l->data;
- ClutterPaintVolume *clip;
/* NB: Entries may be invalidated if the actor gets destroyed */
if (G_LIKELY (entry->actor != NULL))
- {
- clip = entry->has_clip ? &entry->clip : NULL;
+ {
+ ClutterPaintVolume old_actor_pv, new_actor_pv;
+
+ _clutter_actor_finish_queue_redraw (entry->actor);
- _clutter_actor_finish_queue_redraw (entry->actor, clip);
- }
+ _clutter_paint_volume_init_static (&old_actor_pv, NULL);
+ _clutter_paint_volume_init_static (&new_actor_pv, NULL);
+
+ if (entry->has_clip)
+ {
+ add_to_stage_clip (stage, &entry->clip);
+ }
+ else if (clutter_actor_get_redraw_clip (entry->actor,
+ &old_actor_pv,
+ &new_actor_pv))
+ {
+ /* Add both the old paint volume of the actor (which is
+ * currently visible on the screen) and the new paint volume
+ * (which will be visible on the screen after this redraw)
+ * to the redraw clip.
+ * The former we do to ensure the old texture on the screen
+ * will be fully painted over in case the actor was moved.
+ */
+ add_to_stage_clip (stage, &old_actor_pv);
+ add_to_stage_clip (stage, &new_actor_pv);
+ }
+ else
+ {
+ /* If there's no clip we can use, we have to trigger an
+ * unclipped full stage redraw.
+ */
+ add_to_stage_clip (stage, NULL);
+ }
+
+ }
free_queue_redraw_entry (entry);
}