Apply subcompositor optimizations for Firefox Nightly
* subcompositor.c (struct _View): Fix comment. (struct _Subcompositor): New field `additional_damage'. (MakeSubcompositor): Initialize that field. (SubcompositorUpdateBounds, SubcompositorUpdateBoundsForInsert): Only garbage subcompositor if bounds really changed. (SkipSlug): Move definition earlier. (ViewUnionInferiorBounds, DamageIncludingInferiors): New functions. (SubcompositorInsert, SubcompositorInsertBefore) (SubcompositorInsertAfter, ViewInsert, ViewInsertAfter) (ViewInsertBefore, ViewUnparent, ViewAfterSizeUpdate) (ViewAttachBuffer, ViewMove, ViewMoveFractional, ViewUnskip) (ViewSetScale, ViewSetTransform, ViewSetViewport) (ViewClearViewport, SubcompositorComposite, SubcompositorRedraw) (SubcompositorFree): Handle damage in a more detailed fashion; try to avoid garbaging upon subsurface movement, mapping, or unmapping. * wp_viewporter.c (SetSource, SetDestination): Don't set pending if things didn't actually change.
This commit is contained in:
parent
a05a62d9d0
commit
6f3941866a
2 changed files with 365 additions and 122 deletions
475
subcompositor.c
475
subcompositor.c
|
@ -261,7 +261,8 @@ struct _View
|
|||
/* Buffer data. */
|
||||
|
||||
#ifndef TEST
|
||||
/* Width and height of the view. Not valid until ViewAfterSizeUpdate! */
|
||||
/* Width and height of the view. Not valid until
|
||||
ViewAfterSizeUpdate! */
|
||||
int width, height;
|
||||
|
||||
/* The buffer associated with this view, or None if nothing is
|
||||
|
@ -350,6 +351,9 @@ struct _Subcompositor
|
|||
/* Buffers used to store that damage. */
|
||||
pixman_region32_t prior_damage[2];
|
||||
|
||||
/* Any additional damage to be applied to the subcompositor. */
|
||||
pixman_region32_t additional_damage;
|
||||
|
||||
/* The damage region of previous updates. last_damage is what the
|
||||
damage region was 1 update ago, and before_damage is what the
|
||||
damage region was 2 updates ago. */
|
||||
|
@ -469,6 +473,9 @@ MakeSubcompositor (void)
|
|||
pixman_region32_init (&subcompositor->prior_damage[0]);
|
||||
pixman_region32_init (&subcompositor->prior_damage[1]);
|
||||
|
||||
/* And the buffer used to store additional damage. */
|
||||
pixman_region32_init (&subcompositor->additional_damage);
|
||||
|
||||
return subcompositor;
|
||||
}
|
||||
|
||||
|
@ -541,6 +548,7 @@ SubcompositorUpdateBounds (Subcompositor *subcompositor, int doflags)
|
|||
{
|
||||
List *list;
|
||||
int min_x, min_y, max_x, max_y;
|
||||
int old_min_x, old_min_y, old_max_x, old_max_y;
|
||||
|
||||
/* Updates were optimized out. */
|
||||
if (!doflags)
|
||||
|
@ -548,6 +556,10 @@ SubcompositorUpdateBounds (Subcompositor *subcompositor, int doflags)
|
|||
|
||||
list = subcompositor->inferiors->next;
|
||||
min_x = max_x = min_y = max_y = 0;
|
||||
old_min_x = subcompositor->min_x;
|
||||
old_min_y = subcompositor->min_y;
|
||||
old_max_x = subcompositor->max_x;
|
||||
old_max_y = subcompositor->max_y;
|
||||
|
||||
while (list != subcompositor->inferiors)
|
||||
{
|
||||
|
@ -593,7 +605,11 @@ SubcompositorUpdateBounds (Subcompositor *subcompositor, int doflags)
|
|||
if (doflags & DoMaxY)
|
||||
subcompositor->max_y = max_y;
|
||||
|
||||
SetGarbaged (subcompositor);
|
||||
if (subcompositor->min_x != old_min_x
|
||||
|| subcompositor->min_y != old_min_y
|
||||
|| subcompositor->max_x != old_max_x
|
||||
|| subcompositor->max_y != old_max_y)
|
||||
SetGarbaged (subcompositor);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -609,16 +625,36 @@ SubcompositorUpdateBoundsForInsert (Subcompositor *subcompositor,
|
|||
/* Inserting a view cannot shrink the subcompositor. */
|
||||
|
||||
if (view->abs_x < subcompositor->min_x)
|
||||
subcompositor->min_x = view->abs_x;
|
||||
{
|
||||
subcompositor->min_x = view->abs_x;
|
||||
|
||||
/* Garbage the subcompositor for this change. */
|
||||
SetGarbaged (subcompositor);
|
||||
}
|
||||
|
||||
if (view->abs_x < view->subcompositor->min_y)
|
||||
subcompositor->min_y = view->abs_y;
|
||||
{
|
||||
subcompositor->min_y = view->abs_y;
|
||||
|
||||
/* Garbage the subcompositor for this change. */
|
||||
SetGarbaged (subcompositor);
|
||||
}
|
||||
|
||||
if (view->subcompositor->max_x < ViewMaxX (view))
|
||||
subcompositor->max_x = ViewMaxX (view);
|
||||
{
|
||||
subcompositor->max_x = ViewMaxX (view);
|
||||
|
||||
/* Garbage the subcompositor for this change. */
|
||||
SetGarbaged (subcompositor);
|
||||
}
|
||||
|
||||
if (view->subcompositor->max_y < ViewMaxY (view))
|
||||
subcompositor->max_y = ViewMaxY (view);
|
||||
{
|
||||
subcompositor->max_y = ViewMaxY (view);
|
||||
|
||||
/* Garbage the subcompositor for this change. */
|
||||
SetGarbaged (subcompositor);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -644,6 +680,101 @@ SubcompositorSetTarget (Subcompositor *compositor,
|
|||
|
||||
#endif
|
||||
|
||||
#define SkipSlug(list, view, next) \
|
||||
{ \
|
||||
if (!list->view) \
|
||||
goto next; \
|
||||
\
|
||||
if (IsViewUnmapped (list->view)) \
|
||||
{ \
|
||||
/* Skip the unmapped view. */ \
|
||||
list = list->view->inferior; \
|
||||
SetPartiallyMapped (subcompositor); \
|
||||
goto next; \
|
||||
} \
|
||||
\
|
||||
if (IsSkipped (list->view)) \
|
||||
{ \
|
||||
/* We must skip this view, as it represents (for \
|
||||
instance) a subsurface that has been added, but not \
|
||||
committed. */ \
|
||||
SetPartiallyMapped (subcompositor); \
|
||||
goto next; \
|
||||
} \
|
||||
\
|
||||
if (!list->view->buffer) \
|
||||
goto next; \
|
||||
\
|
||||
view = list->view; \
|
||||
} \
|
||||
|
||||
static void
|
||||
ViewUnionInferiorBounds (View *parent, pixman_region32_t *region)
|
||||
{
|
||||
List *list;
|
||||
View *view;
|
||||
Subcompositor *subcompositor;
|
||||
|
||||
/* Return the bounds of each of VIEW's inferiors in REGION. */
|
||||
list = parent->link;
|
||||
subcompositor = parent->subcompositor;
|
||||
|
||||
while (True)
|
||||
{
|
||||
SkipSlug (list, view, next);
|
||||
|
||||
/* Union the view bounds with the given region. */
|
||||
pixman_region32_union_rect (region, region, view->abs_x,
|
||||
view->abs_y, view->width,
|
||||
view->height);
|
||||
|
||||
next:
|
||||
|
||||
if (list == parent->inferior)
|
||||
/* Break if we are at the end of the list. */
|
||||
break;
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DamageIncludingInferiors (View *parent)
|
||||
{
|
||||
List *list;
|
||||
View *view;
|
||||
Subcompositor *subcompositor;
|
||||
|
||||
if (parent->subcompositor)
|
||||
/* No subcompositor is attached... */
|
||||
return;
|
||||
|
||||
pixman_region32_union_rect (&parent->damage, &parent->damage,
|
||||
0, 0, parent->width, parent->height);
|
||||
|
||||
/* Now, damage each inferior. */
|
||||
list = parent->link;
|
||||
subcompositor = parent->subcompositor;
|
||||
|
||||
while (True)
|
||||
{
|
||||
SkipSlug (list, view, next);
|
||||
|
||||
/* Union the view damage with its bounds. */
|
||||
pixman_region32_union_rect (&view->damage, &view->damage,
|
||||
view->abs_x, view->abs_y,
|
||||
view->width, view->height);
|
||||
|
||||
next:
|
||||
|
||||
if (list == parent->inferior)
|
||||
/* Break if we are at the end of the list. */
|
||||
break;
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_STATIC void
|
||||
SubcompositorInsert (Subcompositor *compositor, View *view)
|
||||
{
|
||||
|
@ -654,13 +785,14 @@ SubcompositorInsert (Subcompositor *compositor, View *view)
|
|||
ListRelinkBefore (view->link, view->inferior,
|
||||
compositor->last);
|
||||
|
||||
/* Now that the view hierarchy has been changed, garbage the
|
||||
subcompositor. */
|
||||
SetGarbaged (compositor);
|
||||
|
||||
#ifndef TEST
|
||||
/* And update bounds. */
|
||||
SubcompositorUpdateBoundsForInsert (compositor, view);
|
||||
|
||||
/* Now, if the subcompositor is still not garbaged, damage each
|
||||
inferior of the view. */
|
||||
if (!IsGarbaged (compositor))
|
||||
DamageIncludingInferiors (view);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -675,13 +807,14 @@ SubcompositorInsertBefore (Subcompositor *compositor, View *view,
|
|||
/* Make view's inferiors part of the compositor. */
|
||||
ListRelinkBefore (view->link, view->inferior, sibling->link);
|
||||
|
||||
/* Now that the view hierarchy has been changed, garbage the
|
||||
subcompositor. */
|
||||
SetGarbaged (compositor);
|
||||
|
||||
#ifndef TEST
|
||||
/* And update bounds. */
|
||||
SubcompositorUpdateBoundsForInsert (compositor, view);
|
||||
|
||||
/* Now, if the subcompositor is still not garbaged, damage each
|
||||
inferior of the view. */
|
||||
if (!IsGarbaged (compositor))
|
||||
DamageIncludingInferiors (view);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -695,13 +828,14 @@ SubcompositorInsertAfter (Subcompositor *compositor, View *view,
|
|||
/* Make view's inferiors part of the compositor. */
|
||||
ListRelinkAfter (view->link, view->inferior, sibling->inferior);
|
||||
|
||||
/* Now that the view hierarchy has been changed, garbage the
|
||||
subcompositor. */
|
||||
SetGarbaged (compositor);
|
||||
|
||||
#ifndef TEST
|
||||
/* And update bounds. */
|
||||
SubcompositorUpdateBoundsForInsert (compositor, view);
|
||||
|
||||
/* Now, if the subcompositor is still not garbaged, damage each
|
||||
inferior of the view. */
|
||||
if (!IsGarbaged (compositor))
|
||||
DamageIncludingInferiors (view);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -852,9 +986,6 @@ ViewInsert (View *view, View *child)
|
|||
/* Now that the view hierarchy has been changed, garbage the
|
||||
subcompositor. */
|
||||
|
||||
if (view->subcompositor)
|
||||
SetGarbaged (view->subcompositor);
|
||||
|
||||
#ifndef TEST
|
||||
/* Also update the absolute positions of the child. */
|
||||
child->abs_x = view->abs_x + child->x;
|
||||
|
@ -863,6 +994,12 @@ ViewInsert (View *view, View *child)
|
|||
|
||||
/* And update bounds. */
|
||||
ViewUpdateBoundsForInsert (view);
|
||||
|
||||
/* Now, if the subcompositor is still not garbaged, damage each
|
||||
inferior of the view. */
|
||||
if (view->subcompositor
|
||||
&& !IsGarbaged (view->subcompositor))
|
||||
DamageIncludingInferiors (view);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -901,12 +1038,6 @@ ViewInsertAfter (View *view, View *child, View *sibling)
|
|||
}
|
||||
}
|
||||
|
||||
/* Now that the view hierarchy has been changed, garbage the
|
||||
subcompositor. */
|
||||
|
||||
if (view->subcompositor)
|
||||
SetGarbaged (view->subcompositor);
|
||||
|
||||
#ifndef TEST
|
||||
/* Also update the absolute positions of the child. */
|
||||
child->abs_x = view->abs_x + child->x;
|
||||
|
@ -915,6 +1046,12 @@ ViewInsertAfter (View *view, View *child, View *sibling)
|
|||
|
||||
/* And update bounds. */
|
||||
ViewUpdateBoundsForInsert (view);
|
||||
|
||||
/* Now, if the subcompositor is still not garbaged, damage each
|
||||
inferior of the view. */
|
||||
if (view->subcompositor
|
||||
&& !IsGarbaged (view->subcompositor))
|
||||
DamageIncludingInferiors (view);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -931,12 +1068,6 @@ ViewInsertBefore (View *view, View *child, View *sibling)
|
|||
ListRelinkBefore (child->link, child->inferior,
|
||||
sibling->link);
|
||||
|
||||
/* Now that the view hierarchy has been changed, garbage the
|
||||
subcompositor. */
|
||||
|
||||
if (view->subcompositor)
|
||||
SetGarbaged (view->subcompositor);
|
||||
|
||||
#ifndef TEST
|
||||
/* Also update the absolute positions of the child. */
|
||||
child->abs_x = view->abs_x + child->x;
|
||||
|
@ -946,6 +1077,12 @@ ViewInsertBefore (View *view, View *child, View *sibling)
|
|||
/* Update subcompositor bounds. Inserting a view cannot shrink
|
||||
anything. */
|
||||
ViewUpdateBoundsForInsert (view);
|
||||
|
||||
/* Now, if the subcompositor is still not garbaged, damage each
|
||||
inferior of the view. */
|
||||
if (view->subcompositor
|
||||
&& !IsGarbaged (view->subcompositor))
|
||||
DamageIncludingInferiors (view);
|
||||
#endif
|
||||
|
||||
/* Inserting inferiors before a sibling can never bump the inferior
|
||||
|
@ -969,6 +1106,22 @@ TEST_STATIC void
|
|||
ViewUnparent (View *child)
|
||||
{
|
||||
View *parent;
|
||||
Bool mapped, attached;
|
||||
pixman_region32_t damage;
|
||||
|
||||
/* See if the view is attached or not. */
|
||||
attached = (ViewVisibilityState (child, &mapped)
|
||||
&& mapped);
|
||||
|
||||
if (attached)
|
||||
{
|
||||
/* Init the damage region. */
|
||||
pixman_region32_init (&damage);
|
||||
|
||||
/* And store what additional damage should be applied for this
|
||||
unparent. */
|
||||
ViewUnionInferiorBounds (child, &damage);
|
||||
}
|
||||
|
||||
/* Parent is either the subcompositor or another view. */
|
||||
ListUnlink (child->self, child->self);
|
||||
|
@ -1015,11 +1168,19 @@ ViewUnparent (View *child)
|
|||
#ifndef TEST
|
||||
/* Update the bounds of the subcompositor. */
|
||||
SubcompositorUpdateBounds (child->subcompositor, DoAll);
|
||||
#endif
|
||||
|
||||
/* Then, garbage the subcompositor. */
|
||||
SetGarbaged (child->subcompositor);
|
||||
/* If the subcompositor is not garbaged, then apply additional
|
||||
damage. */
|
||||
if (attached && !IsGarbaged (child->subcompositor))
|
||||
pixman_region32_union (&child->subcompositor->additional_damage,
|
||||
&child->subcompositor->additional_damage,
|
||||
&damage);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (attached)
|
||||
/* Finalize the damage region. */
|
||||
pixman_region32_fini (&damage);
|
||||
}
|
||||
|
||||
TEST_STATIC void
|
||||
|
@ -1244,12 +1405,16 @@ main (int argc, char **argv)
|
|||
static void
|
||||
ViewAfterSizeUpdate (View *view)
|
||||
{
|
||||
int doflags;
|
||||
int doflags, old_width, old_height;
|
||||
Bool mapped;
|
||||
|
||||
if (view->maybe_resized)
|
||||
view->maybe_resized (view);
|
||||
|
||||
/* These are used to decide how to damage the subcompositor. */
|
||||
old_width = view->width;
|
||||
old_height = view->height;
|
||||
|
||||
/* Calculate view->width and view->height again. */
|
||||
view->width = ViewWidth (view);
|
||||
view->height = ViewHeight (view);
|
||||
|
@ -1267,6 +1432,7 @@ ViewAfterSizeUpdate (View *view)
|
|||
if (view->subcompositor->max_x < ViewMaxX (view))
|
||||
{
|
||||
view->subcompositor->max_x = ViewMaxX (view);
|
||||
SetGarbaged (view->subcompositor);
|
||||
|
||||
/* We don't have to update max_x anymore. */
|
||||
doflags &= ~DoMaxX;
|
||||
|
@ -1275,6 +1441,7 @@ ViewAfterSizeUpdate (View *view)
|
|||
if (view->subcompositor->max_y < ViewMaxY (view))
|
||||
{
|
||||
view->subcompositor->max_y = ViewMaxY (view);
|
||||
SetGarbaged (view->subcompositor);
|
||||
|
||||
/* We don't have to update max_x anymore. */
|
||||
doflags &= ~DoMaxY;
|
||||
|
@ -1282,6 +1449,16 @@ ViewAfterSizeUpdate (View *view)
|
|||
|
||||
/* Finally, update the bounds. */
|
||||
SubcompositorUpdateBounds (view->subcompositor, doflags);
|
||||
|
||||
/* If the subcompositor is not garbaged and the view shrunk, damage
|
||||
the subcompositor accordingly. */
|
||||
if (!IsGarbaged (view->subcompositor)
|
||||
&& (view->width < old_width
|
||||
|| view->height < old_height))
|
||||
pixman_region32_union_rect (&view->subcompositor->additional_damage,
|
||||
&view->subcompositor->additional_damage,
|
||||
view->abs_x, view->abs_y, old_width,
|
||||
old_height);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1292,29 +1469,17 @@ ViewAttachBuffer (View *view, ExtBuffer *buffer)
|
|||
old = view->buffer;
|
||||
view->buffer = buffer;
|
||||
|
||||
if (!old != !buffer)
|
||||
{
|
||||
/* TODO: just damage intersecting views before view->link if the
|
||||
buffer was removed. */
|
||||
if (view->subcompositor)
|
||||
SetGarbaged (view->subcompositor);
|
||||
}
|
||||
|
||||
if (((buffer && !old)
|
||||
|| (old && !buffer)
|
||||
|| (buffer && old
|
||||
&& (XLBufferWidth (buffer) != XLBufferWidth (old)
|
||||
|| XLBufferHeight (buffer) != XLBufferHeight (old))))
|
||||
&& !IsViewported (view))
|
||||
{
|
||||
/* Recompute view and subcompositor bounds. */
|
||||
ViewAfterSizeUpdate (view);
|
||||
|
||||
if (view->subcompositor)
|
||||
/* A new buffer was attached, so garbage the subcompositor as
|
||||
well. */
|
||||
SetGarbaged (view->subcompositor);
|
||||
}
|
||||
if (!view->buffer && old && view->subcompositor)
|
||||
/* The view needs a size update, as it is now 0 by 0. */
|
||||
ViewAfterSizeUpdate (view);
|
||||
else if (((buffer && !old)
|
||||
|| (old && !buffer)
|
||||
|| (buffer && old
|
||||
&& (XLBufferWidth (buffer) != XLBufferWidth (old)
|
||||
|| XLBufferHeight (buffer) != XLBufferHeight (old))))
|
||||
&& !IsViewported (view))
|
||||
/* Recompute view and subcompositor bounds. */
|
||||
ViewAfterSizeUpdate (view);
|
||||
|
||||
if (buffer && IsViewUnmapped (view))
|
||||
{
|
||||
|
@ -1324,9 +1489,11 @@ ViewAttachBuffer (View *view, ExtBuffer *buffer)
|
|||
|
||||
if (view->subcompositor)
|
||||
{
|
||||
/* Garbage the subcompositor and recompute bounds. */
|
||||
SetGarbaged (view->subcompositor);
|
||||
/* Recompute subcompositor bounds. */
|
||||
SubcompositorUpdateBounds (view->subcompositor, DoAll);
|
||||
|
||||
/* Garbage the subcompositor. */
|
||||
SetGarbaged (view->subcompositor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1340,6 +1507,7 @@ ViewAttachBuffer (View *view, ExtBuffer *buffer)
|
|||
void
|
||||
ViewMove (View *view, int x, int y)
|
||||
{
|
||||
pixman_region32_t damage;
|
||||
int doflags;
|
||||
Bool mapped;
|
||||
|
||||
|
@ -1347,6 +1515,8 @@ ViewMove (View *view, int x, int y)
|
|||
|
||||
if (x != view->x || y != view->y)
|
||||
{
|
||||
pixman_region32_init (&damage);
|
||||
|
||||
view->x = x;
|
||||
view->y = y;
|
||||
|
||||
|
@ -1380,6 +1550,10 @@ ViewMove (View *view, int x, int y)
|
|||
/* min_x has already been updated so there is no need to
|
||||
recompute it later. */
|
||||
doflags &= ~DoMinX;
|
||||
|
||||
/* Also garbage the subcompositor since the bounds
|
||||
changed. */
|
||||
SetGarbaged (view->subcompositor);
|
||||
}
|
||||
|
||||
if (view->abs_y < view->subcompositor->min_x)
|
||||
|
@ -1389,6 +1563,10 @@ ViewMove (View *view, int x, int y)
|
|||
/* min_y has already been updated so there is no need to
|
||||
recompute it later. */
|
||||
doflags &= ~DoMinY;
|
||||
|
||||
/* Also garbage the subcompositor since the bounds
|
||||
changed. */
|
||||
SetGarbaged (view->subcompositor);
|
||||
}
|
||||
|
||||
/* If moving this biew bumps subcompositor.max_x and/or
|
||||
|
@ -1402,6 +1580,10 @@ ViewMove (View *view, int x, int y)
|
|||
recompute it later. If a child is bigger, then
|
||||
ViewRecomputeChildren will handle it as well. */
|
||||
doflags &= ~DoMaxX;
|
||||
|
||||
/* Also garbage the subcompositor since the bounds
|
||||
changed. */
|
||||
SetGarbaged (view->subcompositor);
|
||||
}
|
||||
|
||||
if (view->subcompositor->max_y < ViewMaxX (view))
|
||||
|
@ -1412,22 +1594,45 @@ ViewMove (View *view, int x, int y)
|
|||
recompute it later. If a child is bigger, then
|
||||
ViewRecomputeChildren will handle it as well. */
|
||||
doflags &= ~DoMaxY;
|
||||
}
|
||||
|
||||
/* Also garbage the subcompositor since those values
|
||||
changed. TODO: just damage intersecting views before
|
||||
view->link. */
|
||||
SetGarbaged (view->subcompositor);
|
||||
/* Also garbage the subcompositor since the bounds
|
||||
changed. */
|
||||
SetGarbaged (view->subcompositor);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now calculate the absolute position for this view and all of
|
||||
its children. N.B. that this operation can also update
|
||||
subcompositor.min_x or subcompositor.min_y. */
|
||||
ViewRecomputeChildren (view, &doflags);
|
||||
|
||||
/* Update subcompositor bounds. */
|
||||
/* If the subcompositor is not garbaged, then damage the union
|
||||
of the previous view bounds and the current view bounds. */
|
||||
if (view->subcompositor)
|
||||
SubcompositorUpdateBounds (view->subcompositor, doflags);
|
||||
{
|
||||
if (!IsGarbaged (view->subcompositor))
|
||||
ViewUnionInferiorBounds (view, &damage);
|
||||
|
||||
/* Update the subcompositor bounds. */
|
||||
SubcompositorUpdateBounds (view->subcompositor, doflags);
|
||||
|
||||
/* Now calculate the absolute position for this view and all of
|
||||
its children. N.B. that this operation can also update
|
||||
subcompositor.min_x or subcompositor.min_y. */
|
||||
ViewRecomputeChildren (view, &doflags);
|
||||
|
||||
/* If the subcompositor is still not garbaged, union damage
|
||||
the rest of the way and apply it. */
|
||||
if (!IsGarbaged (view->subcompositor))
|
||||
{
|
||||
ViewUnionInferiorBounds (view, &damage);
|
||||
|
||||
pixman_region32_union (&view->subcompositor->additional_damage,
|
||||
&view->subcompositor->additional_damage,
|
||||
&damage);
|
||||
}
|
||||
}
|
||||
else
|
||||
/* Now calculate the absolute position for this view and all
|
||||
of its children. */
|
||||
ViewRecomputeChildren (view, &doflags);
|
||||
|
||||
pixman_region32_fini (&damage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1436,13 +1641,18 @@ ViewMoveFractional (View *view, double x, double y)
|
|||
{
|
||||
XLAssert (x < 1.0 && y < 1.0);
|
||||
|
||||
if (view->fract_x == x || view->fract_y == y)
|
||||
return;
|
||||
|
||||
/* This does not necessitate adjustments to the view size, but does
|
||||
require that the subcompositor be garbaged. */
|
||||
require that the view be redrawn. */
|
||||
view->fract_x = x;
|
||||
view->fract_y = y;
|
||||
|
||||
if (view->subcompositor)
|
||||
SetGarbaged (view->subcompositor);
|
||||
/* Damage the entire view. */
|
||||
pixman_region32_union_rect (&view->damage, &view->damage,
|
||||
0, 0, view->width, view->height);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1508,12 +1718,10 @@ ViewUnskip (View *view)
|
|||
ClearSkipped (view);
|
||||
|
||||
if (view->subcompositor && view->buffer)
|
||||
{
|
||||
/* Garbage the subcompositor and recompute bounds, if something
|
||||
is attached to the view. */
|
||||
SetGarbaged (view->subcompositor);
|
||||
SubcompositorUpdateBounds (view->subcompositor, DoAll);
|
||||
}
|
||||
/* Damage the whole view bounds. */
|
||||
pixman_region32_union_rect (&view->damage, &view->damage,
|
||||
view->abs_x, view->abs_y,
|
||||
view->width, view->height);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1791,6 +1999,11 @@ ViewSetScale (View *view, int scale)
|
|||
|
||||
/* Recompute subcompositor bounds; they could've changed. */
|
||||
ViewAfterSizeUpdate (view);
|
||||
|
||||
/* The scale of the view changed, so prior damage cannot be trusted
|
||||
any longer. */
|
||||
pixman_region32_union_rect (&view->damage, &view->damage,
|
||||
0, 0, view->width, view->height);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1808,6 +2021,11 @@ ViewSetTransform (View *view, BufferTransform transform)
|
|||
!= RotatesDimensions (old_transform))
|
||||
/* Subcompositor bounds may have changed. */
|
||||
ViewAfterSizeUpdate (view);
|
||||
|
||||
/* The transform of the view changed, so prior damage cannot be
|
||||
trusted any longer. */
|
||||
pixman_region32_union_rect (&view->damage, &view->damage,
|
||||
0, 0, view->width, view->height);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1827,9 +2045,10 @@ ViewSetViewport (View *view, double src_x, double src_y,
|
|||
/* Update min_x and min_y. */
|
||||
ViewAfterSizeUpdate (view);
|
||||
|
||||
/* Garbage the subcompositor as damage can no longer be trusted. */
|
||||
if (view->subcompositor)
|
||||
SubcompositorGarbage (view->subcompositor);
|
||||
/* The transform of the view changed, so prior damage cannot be
|
||||
trusted any longer. */
|
||||
pixman_region32_union_rect (&view->damage, &view->damage,
|
||||
0, 0, view->width, view->height);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1840,9 +2059,10 @@ ViewClearViewport (View *view)
|
|||
/* Update min_x and min_y. */
|
||||
ViewAfterSizeUpdate (view);
|
||||
|
||||
/* Garbage the subcompositor as damage can no longer be trusted. */
|
||||
if (view->subcompositor)
|
||||
SubcompositorGarbage (view->subcompositor);
|
||||
/* The transform of the view changed, so prior damage cannot be
|
||||
trusted any longer. */
|
||||
pixman_region32_union_rect (&view->damage, &view->damage,
|
||||
0, 0, view->width, view->height);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2066,35 +2286,6 @@ RenderCompletedCallback (void *data)
|
|||
subcompositor->note_frame_data);
|
||||
}
|
||||
|
||||
#define SkipSlug(list, view, next) \
|
||||
{ \
|
||||
if (!list->view) \
|
||||
goto next; \
|
||||
\
|
||||
if (IsViewUnmapped (list->view)) \
|
||||
{ \
|
||||
/* Skip the unmapped view. */ \
|
||||
list = list->view->inferior; \
|
||||
SetPartiallyMapped (subcompositor); \
|
||||
goto next; \
|
||||
} \
|
||||
\
|
||||
if (IsSkipped (list->view)) \
|
||||
{ \
|
||||
/* We must skip this view, as it represents (for \
|
||||
instance) a subsurface that has been added, but not \
|
||||
committed. */ \
|
||||
SetPartiallyMapped (subcompositor); \
|
||||
goto next; \
|
||||
} \
|
||||
\
|
||||
if (!list->view->buffer) \
|
||||
goto next; \
|
||||
\
|
||||
view = list->view; \
|
||||
\
|
||||
}
|
||||
|
||||
/* Update ancillary data upon commit. This includes the input and
|
||||
opaque regions. */
|
||||
|
||||
|
@ -2741,6 +2932,20 @@ SubcompositorComposite (Subcompositor *subcompositor)
|
|||
{
|
||||
SkipSlug (list, view, next);
|
||||
|
||||
/* Subtract the view's opaque region from the output damage
|
||||
region. */
|
||||
|
||||
if (pixman_region32_not_empty (&view->opaque))
|
||||
{
|
||||
/* Avoid reporting damage that will be covered up by views
|
||||
above. */
|
||||
pixman_region32_intersect_rect (&temp, &view->opaque,
|
||||
0, 0, view->width,
|
||||
view->height);
|
||||
pixman_region32_translate (&temp, view->abs_x, view->abs_y);
|
||||
pixman_region32_subtract (&damage, &damage, &temp);
|
||||
}
|
||||
|
||||
/* Add the view's damage region to the output damage region. */
|
||||
pixman_region32_intersect_rect (&temp, &view->damage, 0, 0,
|
||||
view->width, view->height);
|
||||
|
@ -2751,18 +2956,34 @@ SubcompositorComposite (Subcompositor *subcompositor)
|
|||
list = list->next;
|
||||
}
|
||||
|
||||
/* Add damage caused by i.e. movement. */
|
||||
pixman_region32_union (&damage, &damage,
|
||||
&subcompositor->additional_damage);
|
||||
|
||||
/* If there is no damage, just return without drawing anything. */
|
||||
if (!pixman_region32_not_empty (&damage))
|
||||
return True;
|
||||
{
|
||||
pixman_region32_fini (&damage);
|
||||
pixman_region32_fini (&temp);
|
||||
return True;
|
||||
}
|
||||
|
||||
if (age == -1 || age > 2)
|
||||
/* The target is too old. */
|
||||
return False;
|
||||
{
|
||||
/* The target is too old. */
|
||||
pixman_region32_fini (&damage);
|
||||
pixman_region32_fini (&temp);
|
||||
return False;
|
||||
}
|
||||
|
||||
if ((age > 0 && !subcompositor->last_damage)
|
||||
|| (age > 1 && !subcompositor->before_damage))
|
||||
/* Damage required for incremental update is missing. */
|
||||
return False;
|
||||
{
|
||||
/* Damage required for incremental update is missing. */
|
||||
pixman_region32_fini (&damage);
|
||||
pixman_region32_fini (&temp);
|
||||
return False;
|
||||
}
|
||||
|
||||
/* Copy the damage so StorePreviousDamage gets the damage before it
|
||||
was unioned. */
|
||||
|
@ -2789,6 +3010,10 @@ SubcompositorComposite (Subcompositor *subcompositor)
|
|||
|
||||
pixman_region32_fini (&damage);
|
||||
|
||||
if (rc)
|
||||
/* Clear any additional damage applied. */
|
||||
pixman_region32_clear (&subcompositor->additional_damage);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -2804,6 +3029,9 @@ SubcompositorRedraw (Subcompositor *subcompositor)
|
|||
SubcompositorHeight (subcompositor));
|
||||
SubcompositorComposite1 (subcompositor, &damage, False);
|
||||
pixman_region32_fini (&damage);
|
||||
|
||||
/* Clear any additional damage applied. */
|
||||
pixman_region32_clear (&subcompositor->additional_damage);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2946,6 +3174,9 @@ SubcompositorFree (Subcompositor *subcompositor)
|
|||
pixman_region32_fini (&subcompositor->prior_damage[0]);
|
||||
pixman_region32_fini (&subcompositor->prior_damage[1]);
|
||||
|
||||
/* Finalize the region used to store additional damage. */
|
||||
pixman_region32_fini (&subcompositor->additional_damage);
|
||||
|
||||
/* Remove the presentation key. */
|
||||
if (subcompositor->present_key)
|
||||
RenderCancelPresentationCallback (subcompositor->present_key);
|
||||
|
|
|
@ -117,6 +117,13 @@ SetSource (struct wl_client *client, struct wl_resource *resource,
|
|||
wl_resource_post_error (resource, WP_VIEWPORT_ERROR_BAD_VALUE,
|
||||
"invalid source rectangle specified");
|
||||
|
||||
if (ext->surface->current_state.src_x == src_x
|
||||
&& ext->surface->current_state.src_y == src_y
|
||||
&& ext->surface->current_state.src_width == src_width
|
||||
&& ext->surface->current_state.src_height == src_height)
|
||||
/* No change happened. */
|
||||
return;
|
||||
|
||||
ext->surface->pending_state.pending |= PendingViewportSrc;
|
||||
ext->surface->pending_state.src_x = src_x;
|
||||
ext->surface->pending_state.src_y = src_y;
|
||||
|
@ -148,6 +155,11 @@ SetDestination (struct wl_client *client, struct wl_resource *resource,
|
|||
return;
|
||||
}
|
||||
|
||||
if (ext->surface->current_state.dest_width == width
|
||||
&& ext->surface->current_state.dest_height == height)
|
||||
/* No change happened. */
|
||||
return;
|
||||
|
||||
ext->surface->pending_state.pending |= PendingViewportDest;
|
||||
ext->surface->pending_state.dest_width = width;
|
||||
ext->surface->pending_state.dest_height = height;
|
||||
|
|
Loading…
Add table
Reference in a new issue