Bug 880031 - Make animated transforms force all above content to be in a separate ThebesLayer. r=roc

This commit is contained in:
Matt Woodrow 2013-11-08 19:04:12 +13:00
parent c1aa7dd3e7
commit 4984e7db61

View File

@ -329,7 +329,8 @@ protected:
mNeedComponentAlpha(false),
mForceTransparentSurface(false),
mImage(nullptr),
mCommonClipCount(-1) {}
mCommonClipCount(-1),
mAllDrawingAbove(false) {}
/**
* Record that an item has been added to the ThebesLayer, so we
* need to update our regions.
@ -357,20 +358,67 @@ protected:
*/
already_AddRefed<ImageContainer> CanOptimizeImageLayer(nsDisplayListBuilder* aBuilder);
void AddDrawAboveRegion(const nsIntRegion& aAbove)
{
if (!mAllDrawingAbove) {
mDrawAboveRegion.Or(mDrawAboveRegion, aAbove);
mDrawAboveRegion.SimplifyOutward(4);
}
}
void AddVisibleAboveRegion(const nsIntRegion& aAbove)
{
if (!mAllDrawingAbove) {
mVisibleAboveRegion.Or(mVisibleAboveRegion, aAbove);
mVisibleAboveRegion.SimplifyOutward(4);
}
}
void CopyAboveRegion(ThebesLayerData* aOther)
{
if (aOther->mAllDrawingAbove || mAllDrawingAbove) {
SetAllDrawingAbove();
} else {
mVisibleAboveRegion.Or(mVisibleAboveRegion, aOther->mVisibleAboveRegion);
mVisibleAboveRegion.Or(mVisibleAboveRegion, aOther->mVisibleRegion);
mVisibleAboveRegion.SimplifyOutward(4);
mDrawAboveRegion.Or(mDrawAboveRegion, aOther->mDrawAboveRegion);
mDrawAboveRegion.Or(mDrawAboveRegion, aOther->mDrawRegion);
mDrawAboveRegion.SimplifyOutward(4);
}
}
void SetAllDrawingAbove()
{
mAllDrawingAbove = true;
mDrawAboveRegion.SetEmpty();
mVisibleAboveRegion.SetEmpty();
}
bool IsBelow(const nsIntRect& aRect)
{
return mAllDrawingAbove || mDrawAboveRegion.Intersects(aRect);
}
bool IntersectsVisibleAboveRegion(const nsIntRegion& aVisibleRegion)
{
if (mAllDrawingAbove) {
return true;
}
nsIntRegion visibleAboveIntersection;
visibleAboveIntersection.And(mVisibleAboveRegion, aVisibleRegion);
if (visibleAboveIntersection.IsEmpty()) {
return false;
}
return true;
}
/**
* The region of visible content in the layer, relative to the
* container layer (which is at the snapped top-left of the display
* list reference frame).
*/
nsIntRegion mVisibleRegion;
/**
* The region of visible content above the layer and below the
* next ThebesLayerData currently in the stack, if any. Note that not
* all ThebesLayers for the container are in the ThebesLayerData stack.
* Same coordinate system as mVisibleRegion.
* This is a conservative approximation: it contains the true region.
*/
nsIntRegion mVisibleAboveRegion;
/**
* The region containing the bounds of all display items in the layer,
* regardless of visbility.
@ -378,15 +426,6 @@ protected:
* This is a conservative approximation: it contains the true region.
*/
nsIntRegion mDrawRegion;
/**
* The region containing the bounds of all display items (regardless
* of visibility) in the layer and below the next ThebesLayerData
* currently in the stack, if any.
* Note that not all ThebesLayers for the container are in the
* ThebesLayerData stack.
* Same coordinate system as mVisibleRegion.
*/
nsIntRegion mDrawAboveRegion;
/**
* The region of visible content in the layer that is opaque.
* Same coordinate system as mVisibleRegion.
@ -449,6 +488,30 @@ protected:
* in mItemClip).
*/
void UpdateCommonClipCount(const DisplayItemClip& aCurrentClip);
private:
/**
* The region of visible content above the layer and below the
* next ThebesLayerData currently in the stack, if any. Note that not
* all ThebesLayers for the container are in the ThebesLayerData stack.
* Same coordinate system as mVisibleRegion.
* This is a conservative approximation: it contains the true region.
*/
nsIntRegion mVisibleAboveRegion;
/**
* The region containing the bounds of all display items (regardless
* of visibility) in the layer and below the next ThebesLayerData
* currently in the stack, if any.
* Note that not all ThebesLayers for the container are in the
* ThebesLayerData stack.
* Same coordinate system as mVisibleRegion.
*/
nsIntRegion mDrawAboveRegion;
/**
* True if mDrawAboveRegion and mVisibleAboveRegion should be treated
* as infinite, and all display items should be considered 'above' this layer.
*/
bool mAllDrawingAbove;
};
friend class ThebesLayerData;
@ -1452,9 +1515,7 @@ ContainerState::FindOpaqueBackgroundColorFor(int32_t aThebesLayerIndex)
ThebesLayerData* target = mThebesLayerDataStack[aThebesLayerIndex];
for (int32_t i = aThebesLayerIndex - 1; i >= 0; --i) {
ThebesLayerData* candidate = mThebesLayerDataStack[i];
nsIntRegion visibleAboveIntersection;
visibleAboveIntersection.And(candidate->mVisibleAboveRegion, target->mVisibleRegion);
if (!visibleAboveIntersection.IsEmpty()) {
if (candidate->IntersectsVisibleAboveRegion(target->mVisibleRegion)) {
// Some non-Thebes content between target and candidate; this is
// hopeless
break;
@ -1663,16 +1724,7 @@ ContainerState::PopThebesLayerData()
// mVisibleAboveRegion of the second-to-last item will need to include
// the regions of the last item.
ThebesLayerData* nextData = mThebesLayerDataStack[lastIndex - 1];
nextData->mVisibleAboveRegion.Or(nextData->mVisibleAboveRegion,
data->mVisibleAboveRegion);
nextData->mVisibleAboveRegion.Or(nextData->mVisibleAboveRegion,
data->mVisibleRegion);
nextData->mVisibleAboveRegion.SimplifyOutward(4);
nextData->mDrawAboveRegion.Or(nextData->mDrawAboveRegion,
data->mDrawAboveRegion);
nextData->mDrawAboveRegion.Or(nextData->mDrawAboveRegion,
data->mDrawRegion);
nextData->mDrawAboveRegion.SimplifyOutward(4);
nextData->CopyAboveRegion(data);
}
mThebesLayerDataStack.RemoveElementAt(lastIndex);
@ -1850,7 +1902,7 @@ ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
int32_t topmostLayerWithScrolledRoot = -1;
for (i = mThebesLayerDataStack.Length() - 1; i >= 0; --i) {
ThebesLayerData* data = mThebesLayerDataStack[i];
if (data->mDrawAboveRegion.Intersects(aVisibleRect)) {
if (data->IsBelow(aVisibleRect)) {
++i;
break;
}
@ -2160,14 +2212,24 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
}
ThebesLayerData* data = GetTopThebesLayerData();
if (data) {
data->mVisibleAboveRegion.Or(data->mVisibleAboveRegion, itemVisibleRect);
data->mVisibleAboveRegion.SimplifyOutward(4);
// Add the entire bounds rect to the mDrawAboveRegion.
// The visible region may be excluding opaque content above the
// item, and we need to ensure that that content is not placed
// in a ThebesLayer below the item!
data->mDrawAboveRegion.Or(data->mDrawAboveRegion, itemDrawRect);
data->mDrawAboveRegion.SimplifyOutward(4);
// Prerendered transform items can be updated without layer building
// (async animations or an empty transaction), so we treat all other
// content as being above this so that the transformed layer can correctly
// move behind other content.
if (item->GetType() == nsDisplayItem::TYPE_TRANSFORM &&
nsDisplayTransform::ShouldPrerenderTransformedContent(mBuilder,
item->Frame(),
false)) {
data->SetAllDrawingAbove();
} else {
data->AddVisibleAboveRegion(itemVisibleRect);
// Add the entire bounds rect to the mDrawAboveRegion.
// The visible region may be excluding opaque content above the
// item, and we need to ensure that that content is not placed
// in a ThebesLayer below the item!
data->AddDrawAboveRegion(itemDrawRect);
}
}
itemVisibleRect.MoveBy(mParameters.mOffset);
if (setVisibleRegion) {