Bug 1284586 - Disable paint-skipping for scrollframes that we detect as having a CSS-clipped descendant. r=mstange

MozReview-Commit-ID: AvjokFZMwdd
This commit is contained in:
Kartikaya Gupta 2016-07-13 16:05:53 -04:00
parent 4cc1c59009
commit 982bc8ba1f
7 changed files with 54 additions and 13 deletions

View File

@ -35,6 +35,24 @@ DisplayListClipState::GetCurrentCombinedClip(nsDisplayListBuilder* aBuilder)
return mCurrentCombinedClip;
}
void
DisplayListClipState::SetScrollClipForContainingBlockDescendants(
nsDisplayListBuilder* aBuilder,
const DisplayItemScrollClip* aScrollClip)
{
if (aBuilder->IsPaintingToWindow() &&
mClipContentDescendants &&
aScrollClip != mScrollClipContainingBlockDescendants &&
!DisplayItemScrollClip::IsAncestor(mClipContentDescendantsScrollClip, aScrollClip)) {
if (mClipContentDescendantsScrollClip && mClipContentDescendantsScrollClip->mScrollableFrame) {
mClipContentDescendantsScrollClip->mScrollableFrame->SetScrollsClipOnUnscrolledOutOfFlow();
}
mClipContentDescendantsScrollClip = nullptr;
}
mScrollClipContainingBlockDescendants = aScrollClip;
mStackingContextAncestorSC = DisplayItemScrollClip::PickAncestor(mStackingContextAncestorSC, aScrollClip);
}
void
DisplayListClipState::ClipContainingBlockDescendants(const nsRect& aRect,
const nscoord* aRadii,
@ -49,6 +67,7 @@ DisplayListClipState::ClipContainingBlockDescendants(const nsRect& aRect,
aClipOnStack.IntersectWith(*mClipContainingBlockDescendants);
}
mClipContainingBlockDescendants = &aClipOnStack;
mClipContentDescendantsScrollClip = GetCurrentInnermostScrollClip();
mCurrentCombinedClip = nullptr;
}

View File

@ -29,6 +29,7 @@ public:
, mCurrentCombinedClip(nullptr)
, mScrollClipContentDescendants(nullptr)
, mScrollClipContainingBlockDescendants(nullptr)
, mClipContentDescendantsScrollClip(nullptr)
, mStackingContextAncestorSC(nullptr)
{}
@ -74,11 +75,8 @@ private:
mCurrentCombinedClip = nullptr;
}
void SetScrollClipForContainingBlockDescendants(const DisplayItemScrollClip* aScrollClip)
{
mScrollClipContainingBlockDescendants = aScrollClip;
mStackingContextAncestorSC = DisplayItemScrollClip::PickAncestor(mStackingContextAncestorSC, aScrollClip);
}
void SetScrollClipForContainingBlockDescendants(nsDisplayListBuilder* aBuilder,
const DisplayItemScrollClip* aScrollClip);
void Clear()
{
@ -183,6 +181,11 @@ private:
const DisplayItemScrollClip* mScrollClipContentDescendants;
const DisplayItemScrollClip* mScrollClipContainingBlockDescendants;
/**
* The scroll clip that was in effect when mClipContentDescendants was set.
*/
const DisplayItemScrollClip* mClipContentDescendantsScrollClip;
/**
* A scroll clip that is an ancestor of all the scroll clips that were
* "current" on this clip state since EnterStackingContextContents was
@ -431,9 +434,10 @@ public:
mState.SetClipForContainingBlockDescendants(aClip);
}
void SetScrollClipForContainingBlockDescendants(const DisplayItemScrollClip* aScrollClip)
void SetScrollClipForContainingBlockDescendants(nsDisplayListBuilder* aBuilder,
const DisplayItemScrollClip* aScrollClip)
{
mState.SetScrollClipForContainingBlockDescendants(aScrollClip);
mState.SetScrollClipForContainingBlockDescendants(aBuilder, aScrollClip);
}
/**

View File

@ -2803,7 +2803,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
clipState.SetClipForContainingBlockDescendants(
&savedOutOfFlowData->mContainingBlockClip);
clipState.SetScrollClipForContainingBlockDescendants(
clipState.SetScrollClipForContainingBlockDescendants(aBuilder,
savedOutOfFlowData->mContainingBlockScrollClip);
} else if (GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO &&
isPlaceholder) {
@ -2818,7 +2818,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
// instead since we know we won't render anything, and the inner out-of-flow
// frame will setup the correct clip for itself.
clipState.SetClipForContainingBlockDescendants(nullptr);
clipState.SetScrollClipForContainingBlockDescendants(nullptr);
clipState.SetScrollClipForContainingBlockDescendants(aBuilder, nullptr);
}
// Setup clipping for the parent's overflow:-moz-hidden-unscrollable,

View File

@ -1891,6 +1891,7 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter,
, mTransformingByAPZ(false)
, mScrollableByAPZ(false)
, mZoomableByAPZ(false)
, mScrollsClipOnUnscrolledOutOfFlow(false)
, mVelocityQueue(aOuter->PresContext())
, mAsyncScrollEvent(END_DOM)
{
@ -2118,6 +2119,12 @@ ScrollFrameHelper::HasPerspective() const
return disp->mChildPerspective.GetUnit() != eStyleUnit_None;
}
void
ScrollFrameHelper::SetScrollsClipOnUnscrolledOutOfFlow()
{
mScrollsClipOnUnscrolledOutOfFlow = true;
}
void
ScrollFrameHelper::ScrollToCSSPixels(const CSSIntPoint& aScrollPosition,
nsIScrollableFrame::ScrollMode aMode)
@ -2755,11 +2762,11 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsIAtom* aOri
nsLayoutUtils::GetHighResolutionDisplayPort(content, &displayPort);
displayPort.MoveBy(-mScrolledFrame->GetPosition());
PAINT_SKIP_LOG("New scrollpos %s usingDP %d dpEqual %d scrollableByApz %d plugins %d perspective %d\n",
PAINT_SKIP_LOG("New scrollpos %s usingDP %d dpEqual %d scrollableByApz %d plugins %d perspective %d clip %d\n",
Stringify(CSSPoint::FromAppUnits(GetScrollPosition())).c_str(),
usingDisplayPort, displayPort.IsEqualEdges(oldDisplayPort),
mScrollableByAPZ, HasPluginFrames(), HasPerspective());
if (usingDisplayPort && displayPort.IsEqualEdges(oldDisplayPort) && !HasPerspective()) {
mScrollableByAPZ, HasPluginFrames(), HasPerspective(), mScrollsClipOnUnscrolledOutOfFlow);
if (usingDisplayPort && displayPort.IsEqualEdges(oldDisplayPort) && !HasPerspective() && !mScrollsClipOnUnscrolledOutOfFlow) {
bool haveScrollLinkedEffects = content->GetComposedDoc()->HasScrollLinkedEffect();
bool apzDisabled = haveScrollLinkedEffects && gfxPrefs::APZDisableForScrollLinkedEffects();
if (!apzDisabled) {

View File

@ -386,6 +386,7 @@ public:
}
void SetScrollableByAPZ(bool aScrollable);
void SetZoomableByAPZ(bool aZoomable);
void SetScrollsClipOnUnscrolledOutOfFlow();
bool UsesContainerScrolling() const;
@ -581,6 +582,8 @@ public:
// True if we don't want the scrollbar to repaint itself right now.
bool mSuppressScrollbarRepaints:1;
bool mScrollsClipOnUnscrolledOutOfFlow:1;
mozilla::layout::ScrollVelocityQueue mVelocityQueue;
protected:
@ -1006,6 +1009,9 @@ public:
void SetZoomableByAPZ(bool aZoomable) override {
mHelper.SetZoomableByAPZ(aZoomable);
}
void SetScrollsClipOnUnscrolledOutOfFlow() override {
mHelper.SetScrollsClipOnUnscrolledOutOfFlow();
}
ScrollSnapInfo GetScrollSnapInfo() const override {
return mHelper.GetScrollSnapInfo();
@ -1409,6 +1415,9 @@ public:
void SetZoomableByAPZ(bool aZoomable) override {
mHelper.SetZoomableByAPZ(aZoomable);
}
void SetScrollsClipOnUnscrolledOutOfFlow() override {
mHelper.SetScrollsClipOnUnscrolledOutOfFlow();
}
virtual bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
nsRect* aDirtyRect,
bool aAllowCreateDisplayPort) override {

View File

@ -464,6 +464,8 @@ public:
* Returns information required to determine where to snap to after a scroll.
*/
virtual ScrollSnapInfo GetScrollSnapInfo() const = 0;
virtual void SetScrollsClipOnUnscrolledOutOfFlow() = 0;
};
#endif

View File

@ -107,7 +107,7 @@ BuildDisplayListForTopLayerFrame(nsDisplayListBuilder* aBuilder,
clipState.SetClipForContainingBlockDescendants(
&savedOutOfFlowData->mContainingBlockClip);
clipState.SetScrollClipForContainingBlockDescendants(
savedOutOfFlowData->mContainingBlockScrollClip);
aBuilder, savedOutOfFlowData->mContainingBlockScrollClip);
}
nsDisplayList list;
aFrame->BuildDisplayListForStackingContext(aBuilder, dirty, &list);