Skip to content

Commit e81e995

Browse files
committed
Fixes related to actor allocations and new optimization
Fix some issues with allocations and add an optimization to bail out of allocation cycles if only the absolute origin changed (we can do this because now we no longer need to notify all actors about the absolute origin change using the allocation flag).
1 parent c21fe8c commit e81e995

3 files changed

Lines changed: 76 additions & 70 deletions

File tree

clutter/clutter/clutter-actor.c

Lines changed: 60 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2583,6 +2583,22 @@ clutter_actor_notify_if_geometry_changed (ClutterActor *self,
25832583
g_object_thaw_notify (obj);
25842584
}
25852585

2586+
static void
2587+
absolute_allocation_changed (ClutterActor *actor)
2588+
{
2589+
actor->priv->needs_compute_resource_scale = TRUE;
2590+
}
2591+
2592+
static ClutterActorTraverseVisitFlags
2593+
absolute_allocation_changed_cb (ClutterActor *actor,
2594+
int depth,
2595+
gpointer user_data)
2596+
{
2597+
absolute_allocation_changed (actor);
2598+
2599+
return CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE;
2600+
}
2601+
25862602
/*< private >
25872603
* clutter_actor_set_allocation_internal:
25882604
* @self: a #ClutterActor
@@ -2626,6 +2642,11 @@ clutter_actor_set_allocation_internal (ClutterActor *self,
26262642
priv->needs_height_request = FALSE;
26272643
priv->needs_allocation = FALSE;
26282644

2645+
priv->absolute_origin_changed |= x1_changed || y1_changed;
2646+
2647+
if (priv->absolute_origin_changed || x2_changed || y2_changed)
2648+
absolute_allocation_changed (self);
2649+
26292650
if (x1_changed ||
26302651
y1_changed ||
26312652
x2_changed ||
@@ -10246,7 +10267,6 @@ clutter_actor_allocate (ClutterActor *self,
1024610267
{
1024710268
ClutterActorBox old_allocation, real_allocation;
1024810269
gboolean origin_changed, size_changed;
10249-
gboolean stage_allocation_changed;
1025010270
ClutterActorPrivate *priv;
1025110271

1025210272
g_return_if_fail (CLUTTER_IS_ACTOR (self));
@@ -10258,11 +10278,25 @@ clutter_actor_allocate (ClutterActor *self,
1025810278
return;
1025910279
}
1026010280

10261-
if (!clutter_actor_is_visible (self))
10262-
return;
10263-
1026410281
priv = self->priv;
1026510282

10283+
priv->absolute_origin_changed = priv->parent
10284+
? priv->parent->priv->absolute_origin_changed
10285+
: FALSE;
10286+
10287+
if (!CLUTTER_ACTOR_IS_VISIBLE (self))
10288+
{
10289+
if (priv->absolute_origin_changed)
10290+
{
10291+
_clutter_actor_traverse (self,
10292+
CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST,
10293+
absolute_allocation_changed_cb,
10294+
NULL,
10295+
NULL);
10296+
}
10297+
goto out;
10298+
}
10299+
1026610300
old_allocation = priv->allocation;
1026710301
real_allocation = *box;
1026810302

@@ -10299,49 +10333,45 @@ clutter_actor_allocate (ClutterActor *self,
1029910333
size_changed = (real_allocation.x2 != old_allocation.x2 ||
1030010334
real_allocation.y2 != old_allocation.y2);
1030110335

10302-
priv->absolute_origin_changed = priv->parent
10303-
? priv->parent->priv->absolute_origin_changed
10304-
: FALSE;
10305-
10306-
priv->absolute_origin_changed |= origin_changed;
10307-
10308-
stage_allocation_changed = priv->absolute_origin_changed || size_changed;
10309-
10310-
/* If we get an allocation "out of the blue"
10311-
* (we did not queue relayout), then we want to
10312-
* ignore it. But if we have needs_allocation set,
10313-
* we want to guarantee that allocate() virtual
10314-
* method is always called, i.e. that queue_relayout()
10315-
* always results in an allocate() invocation on
10316-
* an actor.
10336+
/* When needs_allocation is set but we didn't move nor resize, we still
10337+
* want to call the allocate() vfunc because a child probably called
10338+
* queue_relayout() and needs a new allocation.
1031710339
*
10318-
* The optimization here is to avoid re-allocating
10319-
* actors that did not queue relayout and were
10320-
* not moved.
10340+
* In case needs_allocation isn't set and we didn't move nor resize, we
10341+
* can safely stop allocating, but we need to notify the sub-tree in case
10342+
* our absolute origin changed.
1032110343
*/
10322-
if (!priv->needs_allocation && !stage_allocation_changed)
10344+
if (!priv->needs_allocation && !origin_changed && !size_changed)
1032310345
{
10346+
if (priv->absolute_origin_changed)
10347+
{
10348+
_clutter_actor_traverse (self,
10349+
CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST,
10350+
absolute_allocation_changed_cb,
10351+
NULL,
10352+
NULL);
10353+
}
10354+
1032410355
CLUTTER_NOTE (LAYOUT, "No allocation needed");
10325-
return;
10356+
goto out;
1032610357
}
1032710358

1032810359
if (CLUTTER_ACTOR_IS_MAPPED (self))
1032910360
self->priv->needs_paint_volume_update = TRUE;
1033010361

10331-
if (stage_allocation_changed)
10332-
priv->needs_compute_resource_scale = TRUE;
10333-
10334-
if (!stage_allocation_changed)
10362+
if (!origin_changed && !size_changed)
1033510363
{
1033610364
/* If the actor didn't move but needs_allocation is set, we just
10337-
* need to allocate the children */
10365+
* need to allocate the children (see comment above) */
1033810366
clutter_actor_allocate_internal (self, &real_allocation);
10339-
return;
10367+
goto out;
1034010368
}
1034110369

1034210370
_clutter_actor_create_transition (self, obj_props[PROP_ALLOCATION],
1034310371
&priv->allocation,
1034410372
&real_allocation);
10373+
out:
10374+
priv->absolute_origin_changed = FALSE;
1034510375
}
1034610376

1034710377
/**

clutter/clutter/clutter-stage-private.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,7 @@ ClutterStageWindow *_clutter_stage_get_window (ClutterStage
5353
void _clutter_stage_get_projection_matrix (ClutterStage *stage,
5454
CoglMatrix *projection);
5555
void _clutter_stage_dirty_projection (ClutterStage *stage);
56-
void _clutter_stage_set_viewport (ClutterStage *stage,
57-
float x,
58-
float y,
59-
float width,
60-
float height);
56+
6157
void _clutter_stage_get_viewport (ClutterStage *stage,
6258
float *x,
6359
float *y,

clutter/clutter/clutter-stage.c

Lines changed: 15 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,9 @@ static void capture_view_into (ClutterStage *stage,
215215
uint8_t *data,
216216
int stride);
217217
static void clutter_stage_update_view_perspective (ClutterStage *stage);
218+
static void clutter_stage_set_viewport (ClutterStage *stage,
219+
float width,
220+
float height);
218221

219222
static void clutter_container_iface_init (ClutterContainerIface *iface);
220223

@@ -645,7 +648,6 @@ clutter_stage_allocate (ClutterActor *self,
645648
{
646649
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
647650
ClutterActorBox alloc = CLUTTER_ACTOR_BOX_INIT_ZERO;
648-
float old_width, old_height;
649651
float new_width, new_height;
650652
float width, height;
651653
cairo_rectangle_int_t window_size;
@@ -654,10 +656,6 @@ clutter_stage_allocate (ClutterActor *self,
654656
if (priv->impl == NULL)
655657
return;
656658

657-
/* our old allocation */
658-
clutter_actor_get_allocation_box (self, &alloc);
659-
clutter_actor_box_get_size (&alloc, &old_width, &old_height);
660-
661659
/* the current allocation */
662660
clutter_actor_box_get_size (box, &width, &height);
663661

@@ -745,27 +743,11 @@ clutter_stage_allocate (ClutterActor *self,
745743
&override);
746744
}
747745

748-
/* reset the viewport if the allocation effectively changed */
746+
/* set the viewport to the new allocation */
749747
clutter_actor_get_allocation_box (self, &alloc);
750748
clutter_actor_box_get_size (&alloc, &new_width, &new_height);
751749

752-
if (CLUTTER_NEARBYINT (old_width) != CLUTTER_NEARBYINT (new_width) ||
753-
CLUTTER_NEARBYINT (old_height) != CLUTTER_NEARBYINT (new_height))
754-
{
755-
int real_width = CLUTTER_NEARBYINT (new_width);
756-
int real_height = CLUTTER_NEARBYINT (new_height);
757-
758-
_clutter_stage_set_viewport (CLUTTER_STAGE (self),
759-
0, 0,
760-
real_width,
761-
real_height);
762-
763-
/* Note: we don't assume that set_viewport will queue a full redraw
764-
* since it may bail-out early if something preemptively set the
765-
* viewport before the stage was really allocated its new size.
766-
*/
767-
queue_full_redraw (CLUTTER_STAGE (self));
768-
}
750+
clutter_stage_set_viewport (CLUTTER_STAGE (self), new_width, new_height);
769751
}
770752

771753
typedef struct _Vector4
@@ -2433,10 +2415,7 @@ clutter_stage_init (ClutterStage *self)
24332415
g_signal_connect (self, "notify::min-height",
24342416
G_CALLBACK (clutter_stage_notify_min_size), NULL);
24352417

2436-
_clutter_stage_set_viewport (self,
2437-
0, 0,
2438-
geom.width,
2439-
geom.height);
2418+
clutter_stage_set_viewport (self, geom.width, geom.height);
24402419

24412420
priv->paint_volume_stack =
24422421
g_array_new (FALSE, FALSE, sizeof (ClutterPaintVolume));
@@ -2653,8 +2632,6 @@ _clutter_stage_dirty_projection (ClutterStage *stage)
26532632
/*
26542633
* clutter_stage_set_viewport:
26552634
* @stage: A #ClutterStage
2656-
* @x: The X postition to render the stage at, in window coordinates
2657-
* @y: The Y position to render the stage at, in window coordinates
26582635
* @width: The width to render the stage at, in window coordinates
26592636
* @height: The height to render the stage at, in window coordinates
26602637
*
@@ -2687,19 +2664,22 @@ _clutter_stage_dirty_projection (ClutterStage *stage)
26872664
*
26882665
* Since: 1.6
26892666
*/
2690-
void
2691-
_clutter_stage_set_viewport (ClutterStage *stage,
2692-
float x,
2693-
float y,
2694-
float width,
2695-
float height)
2667+
static void
2668+
clutter_stage_set_viewport (ClutterStage *stage,
2669+
float width,
2670+
float height)
26962671
{
26972672
ClutterStagePrivate *priv;
2673+
float x, y;
26982674

26992675
g_return_if_fail (CLUTTER_IS_STAGE (stage));
27002676

27012677
priv = stage->priv;
27022678

2679+
x = 0.f;
2680+
y = 0.f;
2681+
width = roundf (width);
2682+
height = roundf (height);
27032683

27042684
if (x == priv->viewport[0] &&
27052685
y == priv->viewport[1] &&

0 commit comments

Comments
 (0)