Bug 1098654 - Improve layerization of display items when dealing with async scrollable layers. r=tnikkel

The function IsSubjectToAsyncTransforms() was not correctly reporting when a
layer was actually subject to async transforms. As a result, sometimes display
items from above such a layer would end up in a layer below. This could
manifest as page elements being improperly covered by async scrolling elements.
This commit is contained in:
Kartikaya Gupta 2014-12-30 09:39:39 -05:00
parent 505701294d
commit 43054fe29c
2 changed files with 51 additions and 3 deletions

View File

@ -254,6 +254,7 @@ class PaintedLayerData {
public:
PaintedLayerData() :
mAnimatedGeometryRoot(nullptr),
mIsAsyncScrollable(false),
mFixedPosFrameForLayerData(nullptr),
mReferenceFrame(nullptr),
mLayer(nullptr),
@ -342,7 +343,16 @@ public:
void CopyAboveRegion(PaintedLayerData* aOther)
{
if (aOther->mAllDrawingAbove || mAllDrawingAbove) {
// If aOther has a draw region and is subject to async transforms then the
// layer can potentially be moved arbitrarily on the compositor. So we
// should avoid moving display items from on top of the layer to below the
// layer, which we do by calling SetAllDrawingAbove. Note that if the draw
// region is empty (such as when aOther has only event-regions items) then
// we don't need to do this.
bool aOtherCanDrawAnywhere = aOther->IsSubjectToAsyncTransforms()
&& !aOther->mDrawRegion.IsEmpty();
if (aOther->mAllDrawingAbove || mAllDrawingAbove || aOtherCanDrawAnywhere) {
SetAllDrawingAbove();
} else {
mVisibleAboveRegion.Or(mVisibleAboveRegion, aOther->mVisibleAboveRegion);
@ -386,7 +396,8 @@ public:
bool IsSubjectToAsyncTransforms()
{
return mFixedPosFrameForLayerData != nullptr;
return mFixedPosFrameForLayerData != nullptr
|| mIsAsyncScrollable;
}
/**
@ -425,6 +436,12 @@ public:
* active scrolled root.
*/
const nsIFrame* mAnimatedGeometryRoot;
/**
* Whether or not this layer is async scrollable. If it is, that means display
* items above this layer should not end up in a layer below this one, as they
* might be obscured when they shouldn't be.
*/
bool mIsAsyncScrollable;
/**
* If non-null, the frame from which we'll extract "fixed positioning"
* metadata for this layer. This can be a position:fixed frame or a viewport
@ -815,6 +832,13 @@ protected:
* flag, and pop it off the stack.
*/
void PopPaintedLayerData();
/**
* Check if any of the animated geometry roots from aAnimatedGeometryRoot up
* to and including mContainerAnimatedGeometryRoot are async scrollable. If
* so, return true. This is used to flag a particular PaintedLayer as being
* subject to async transforms.
*/
bool HasAsyncScrollableGeometryInContainer(const nsIFrame* aAnimatedGeometryRoot);
/**
* Find the PaintedLayer to which we should assign the next display item.
* We scan the PaintedLayerData stack to find the topmost PaintedLayer
@ -2482,6 +2506,28 @@ PaintedLayerData::Accumulate(ContainerState* aState,
}
}
bool
ContainerState::HasAsyncScrollableGeometryInContainer(const nsIFrame* aAnimatedGeometryRoot)
{
const nsIFrame* f = aAnimatedGeometryRoot;
while (f) {
if (nsLayoutUtils::GetScrollableFrameFor(f) &&
nsLayoutUtils::GetDisplayPort(f->GetContent(), nullptr)) {
return true;
}
if (f == mContainerAnimatedGeometryRoot) {
break;
}
nsIFrame* fParent = nsLayoutUtils::GetCrossDocParentFrame(f);
if (!fParent) {
break;
}
f = nsLayoutUtils::GetAnimatedGeometryRootForFrame(
this->mBuilder, fParent, mContainerAnimatedGeometryRoot);
}
return false;
}
PaintedLayerData*
ContainerState::FindPaintedLayerFor(nsDisplayItem* aItem,
const nsIntRect& aVisibleRect,
@ -2549,6 +2595,8 @@ ContainerState::FindPaintedLayerFor(nsDisplayItem* aItem,
paintedLayerData->mAnimatedGeometryRoot = aAnimatedGeometryRoot;
paintedLayerData->mFixedPosFrameForLayerData =
FindFixedPosFrameForLayerData(aAnimatedGeometryRoot, aShouldFixToViewport);
paintedLayerData->mIsAsyncScrollable =
HasAsyncScrollableGeometryInContainer(aAnimatedGeometryRoot);
paintedLayerData->mReferenceFrame = aItem->ReferenceFrame();
paintedLayerData->mSingleItemFixedToViewport = aShouldFixToViewport;

View File

@ -1802,7 +1802,7 @@ fuzzy-if(B2G,1,7) == 942672-1.html 942672-1-ref.html
== 950436-1.html 950436-1-ref.html
== 957770-1.svg 957770-1-ref.svg
== 960277-1.html 960277-1-ref.html
pref(layout.css.overflow-clip-box.enabled,true) fuzzy(50,31) == 966992-1.html 966992-1-ref.html
pref(layout.css.overflow-clip-box.enabled,true) fuzzy(50,145) == 966992-1.html 966992-1-ref.html
skip-if(Android) == 966510-1.html 966510-1-ref.html # scrollable elements other than the root probably won't work well on android until bug 776030 is fixed
skip-if(Android) == 966510-2.html 966510-2-ref.html # same as above
== 978911-1.svg 978911-1-ref.svg