Bug 1300864 - Disable paint skipping for scroll frames that contain out-of-flow content inside a CSS filter. r=mstange

MozReview-Commit-ID: 5TwC75wzOsm

--HG--
extra : rebase_source : 2c38372e452cf6b78b4906b42e4b9e93a1762d26
This commit is contained in:
Botond Ballo 2017-11-27 16:45:29 -05:00
Родитель 49dff2257e
Коммит f733efea1a
6 изменённых файлов: 69 добавлений и 3 удалений

Просмотреть файл

@ -2936,6 +2936,8 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
inTransformSetter(aBuilder, inTransform);
nsDisplayListBuilder::AutoSaveRestorePerspectiveIndex
perspectiveIndex(aBuilder, this);
nsDisplayListBuilder::AutoFilterASRSetter
filterASRSetter(aBuilder, usingFilter);
CheckForApzAwareEventHandlers(aBuilder, this);

Просмотреть файл

@ -1301,6 +1301,12 @@ ScrollFrameHelper::SetZoomableByAPZ(bool aZoomable)
}
}
void
ScrollFrameHelper::SetHasOutOfFlowContentInsideFilter()
{
mHasOutOfFlowContentInsideFilter = true;
}
bool
ScrollFrameHelper::WantAsyncScroll() const
{
@ -2075,6 +2081,7 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter,
, mTransformingByAPZ(false)
, mScrollableByAPZ(false)
, mZoomableByAPZ(false)
, mHasOutOfFlowContentInsideFilter(false)
, mSuppressScrollbarRepaints(false)
, mVelocityQueue(aOuter->PresContext())
{
@ -2879,13 +2886,15 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsAtom* aOrig
nsLayoutUtils::GetHighResolutionDisplayPort(content, &displayPort);
displayPort.MoveBy(-mScrolledFrame->GetPosition());
PAINT_SKIP_LOG("New scrollpos %s usingDP %d dpEqual %d scrollableByApz %d plugins %d perspective %d bglocal %d\n",
PAINT_SKIP_LOG("New scrollpos %s usingDP %d dpEqual %d scrollableByApz %d plugins"
"%d perspective %d bglocal %d filter %d\n",
Stringify(CSSPoint::FromAppUnits(GetScrollPosition())).c_str(),
usingDisplayPort, displayPort.IsEqualEdges(oldDisplayPort),
mScrollableByAPZ, HasPluginFrames(), HasPerspective(),
HasBgAttachmentLocal());
HasBgAttachmentLocal(), mHasOutOfFlowContentInsideFilter);
if (usingDisplayPort && displayPort.IsEqualEdges(oldDisplayPort) &&
!HasPerspective() && !HasBgAttachmentLocal()) {
!HasPerspective() && !HasBgAttachmentLocal() &&
!mHasOutOfFlowContentInsideFilter) {
bool haveScrollLinkedEffects = content->GetComposedDoc()->HasScrollLinkedEffect();
bool apzDisabled = haveScrollLinkedEffects && gfxPrefs::APZDisableForScrollLinkedEffects();
if (!apzDisabled && !HasPluginFrames()) {

Просмотреть файл

@ -426,6 +426,7 @@ public:
}
void SetScrollableByAPZ(bool aScrollable);
void SetZoomableByAPZ(bool aZoomable);
void SetHasOutOfFlowContentInsideFilter();
bool UsesContainerScrolling() const;
@ -632,6 +633,10 @@ public:
// True if the APZ is allowed to zoom this scrollframe.
bool mZoomableByAPZ:1;
// True if the scroll frame contains out-of-flow content and is inside
// a CSS filter.
bool mHasOutOfFlowContentInsideFilter:1;
// True if we don't want the scrollbar to repaint itself right now.
bool mSuppressScrollbarRepaints:1;
@ -1062,6 +1067,9 @@ public:
void SetZoomableByAPZ(bool aZoomable) override {
mHelper.SetZoomableByAPZ(aZoomable);
}
void SetHasOutOfFlowContentInsideFilter() override {
mHelper.SetHasOutOfFlowContentInsideFilter();
}
ScrollSnapInfo GetScrollSnapInfo() const override {
return mHelper.GetScrollSnapInfo();
@ -1497,6 +1505,9 @@ public:
void SetZoomableByAPZ(bool aZoomable) override {
mHelper.SetZoomableByAPZ(aZoomable);
}
void SetHasOutOfFlowContentInsideFilter() override {
mHelper.SetHasOutOfFlowContentInsideFilter();
}
virtual bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
nsRect* aVisibleRect,
nsRect* aDirtyRect,

Просмотреть файл

@ -448,6 +448,13 @@ public:
*/
virtual void SetZoomableByAPZ(bool aZoomable) = 0;
/**
* Mark this scroll frame as having out-of-flow content inside a CSS filter.
* Such content will move incorrectly during async-scrolling; to mitigate
* this, paint skipping is disabled for such scroll frames.
*/
virtual void SetHasOutOfFlowContentInsideFilter() = 0;
/**
* Whether or not this frame uses containerful scrolling.
*/

Просмотреть файл

@ -919,6 +919,17 @@ nsDisplayListBuilder::AutoCurrentActiveScrolledRootSetter::SetCurrentActiveScrol
mBuilder->mCurrentContainerASR = ActiveScrolledRoot::PickAncestor(
mBuilder->mCurrentContainerASR, finiteBoundsASR);
// If we are entering out-of-flow content inside a CSS filter, mark
// scroll frames wrt. which the content is fixed as containing such content.
if (mBuilder->mFilterASR &&
ActiveScrolledRoot::IsAncestor(aActiveScrolledRoot, mBuilder->mFilterASR)) {
for (const ActiveScrolledRoot* asr = mBuilder->mFilterASR;
asr && asr != aActiveScrolledRoot;
asr = asr->mParent) {
asr->mScrollableFrame->SetHasOutOfFlowContentInsideFilter();
}
}
mUsed = true;
}
@ -970,6 +981,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mCurrentScrollbarFlags(nsDisplayOwnLayerFlags::eNone),
mPerspectiveItemIndex(0),
mSVGEffectsBuildingDepth(0),
mFilterASR(nullptr),
mContainsBlendMode(false),
mIsBuildingScrollbar(false),
mCurrentScrollbarWillHaveLayer(false),

Просмотреть файл

@ -1125,6 +1125,28 @@ public:
bool mOldValue;
};
/**
* A helper class to temporarily set the value of mFilterASR.
*/
class AutoFilterASRSetter;
friend class AutoFilterASRSetter;
class AutoFilterASRSetter {
public:
AutoFilterASRSetter(nsDisplayListBuilder* aBuilder, bool aUsingFilter)
: mBuilder(aBuilder), mOldValue(aBuilder->mFilterASR)
{
if (!aBuilder->mFilterASR && aUsingFilter) {
aBuilder->mFilterASR = aBuilder->CurrentActiveScrolledRoot();
}
}
~AutoFilterASRSetter() {
mBuilder->mFilterASR = mOldValue;
}
private:
nsDisplayListBuilder* mBuilder;
const ActiveScrolledRoot* mOldValue;
};
class AutoSaveRestorePerspectiveIndex;
friend class AutoSaveRestorePerspectiveIndex;
class AutoSaveRestorePerspectiveIndex {
@ -1771,6 +1793,9 @@ private:
Preserves3DContext mPreserves3DCtx;
uint32_t mPerspectiveItemIndex;
int32_t mSVGEffectsBuildingDepth;
// When we are inside a filter, the current ASR at the time we entered the
// filter. Otherwise nullptr.
const ActiveScrolledRoot* mFilterASR;
bool mContainsBlendMode;
bool mIsBuildingScrollbar;
bool mCurrentScrollbarWillHaveLayer;