mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
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:
parent
505701294d
commit
43054fe29c
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user