Bug 1367488 - Pre-render offscreen portions of scrollbar thumbs inside an iframe. r=mstange

MozReview-Commit-ID: LCBHnFJdGtp

--HG--
extra : rebase_source : 1ab1d812674d321d76e634953284b3983774d798
This commit is contained in:
Botond Ballo 2017-05-29 18:05:05 -04:00
Родитель 4564af3454
Коммит 539791ed1e
4 изменённых файлов: 54 добавлений и 5 удалений

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

@ -3935,6 +3935,13 @@ ContainerState::SetupMaskLayerForCSSMask(Layer* aLayer,
aLayer->SetMaskLayer(maskLayer);
}
static bool
IsScrollThumbLayer(nsDisplayItem* aItem)
{
return aItem->GetType() == nsDisplayItem::TYPE_OWN_LAYER &&
static_cast<nsDisplayOwnLayer*>(aItem)->IsScrollThumbLayer();
}
/*
* Iterate through the non-clip items in aList and its descendants.
* For each item we compute the effective clip rect. Each item is assigned
@ -4204,8 +4211,9 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
mPaintedLayerDataTree.AddingOwnLayer(clipAGR,
&scrolledClipRect,
uniformColorPtr);
} else if (*animatedGeometryRoot == item->Frame() &&
*animatedGeometryRoot != mBuilder->RootReferenceFrame()) {
} else if ((*animatedGeometryRoot == item->Frame() &&
*animatedGeometryRoot != mBuilder->RootReferenceFrame()) ||
(IsScrollThumbLayer(item) && mManager->IsWidgetLayerManager())) {
// This is the case for scrollbar thumbs, for example. In that case the
// clip we care about is the overflow:hidden clip on the scrollbar.
mPaintedLayerDataTree.AddingOwnLayer(animatedGeometryRoot->mParentAGR,

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

@ -6110,6 +6110,14 @@ nsDisplayOwnLayer::nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder,
, mForceActive(aForceActive)
{
MOZ_COUNT_CTOR(nsDisplayOwnLayer);
// For scroll thumb layers, override the AGR to be the thumb's AGR rather
// than the AGR for mFrame (which is the slider frame).
if (IsScrollThumbLayer()) {
if (nsIFrame* thumbFrame = nsBox::GetChildXULBox(mFrame)) {
mAnimatedGeometryRoot = aBuilder->FindAnimatedGeometryRootFor(thumbFrame);
}
}
}
#ifdef NS_BUILD_REFCNT_LOGGING
@ -6130,6 +6138,20 @@ nsDisplayOwnLayer::GetLayerState(nsDisplayListBuilder* aBuilder,
return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList, mAnimatedGeometryRoot);
}
bool
nsDisplayOwnLayer::IsScrollThumbLayer() const
{
return (mFlags & VERTICAL_SCROLLBAR) || (mFlags & HORIZONTAL_SCROLLBAR);
}
bool
nsDisplayOwnLayer::ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder)
{
// Render scroll thumb layers even if they are invisible, because async
// scrolling might bring them into view.
return IsScrollThumbLayer();
}
// nsDisplayOpacity uses layers for rendering
already_AddRefed<Layer>
nsDisplayOwnLayer::BuildLayer(nsDisplayListBuilder* aBuilder,

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

@ -1428,6 +1428,7 @@ private:
AnimatedGeometryRoot* FindAnimatedGeometryRootFor(nsDisplayItem* aItem);
friend class nsDisplayItem;
friend class nsDisplayOwnLayer;
AnimatedGeometryRoot* FindAnimatedGeometryRootFor(nsIFrame* aFrame);
AnimatedGeometryRoot* WrapAGRForFrame(nsIFrame* aAnimatedGeometryRoot,
@ -4079,7 +4080,7 @@ public:
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayOwnLayer();
#endif
virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) override;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
@ -4095,6 +4096,7 @@ public:
return false;
}
uint32_t GetFlags() { return mFlags; }
bool IsScrollThumbLayer() const;
NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER)
protected:
uint32_t mFlags;

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

@ -421,6 +421,22 @@ nsSliderFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
nsRect dirty = aDirtyRect.Intersect(thumbRect);
dirty = nsLayoutUtils::ComputePartialPrerenderArea(aDirtyRect, overflow, refSize);
// Clip the thumb layer to the slider track. This is necessary to ensure
// FrameLayerBuilder is able to merge content before and after the
// scrollframe into the same layer (otherwise it thinks the thumb could
// potentially move anywhere within the existing clip).
DisplayListClipState::AutoSaveRestore thumbClipState(aBuilder);
aBuilder->GetCurrentReferenceFrame();
thumbClipState.ClipContainingBlockDescendants(
GetRectRelativeToSelf() + aBuilder->ToReferenceFrame(this));
// Have the thumb's container layer capture the current clip, so
// it doesn't apply to the thumb's contents. This allows the contents
// to be fully rendered even if they're partially or fully offscreen,
// so async scrolling can still bring it into view.
DisplayListClipState::AutoSaveRestore thumbContentsClipState(aBuilder);
thumbContentsClipState.Clear();
nsDisplayListBuilder::AutoContainerASRTracker contASRTracker(aBuilder);
nsDisplayListCollection tempLists;
nsBoxFrame::BuildDisplayListForChildren(aBuilder, dirty, tempLists);
@ -435,10 +451,11 @@ nsSliderFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
masterList.AppendToTop(tempLists.PositionedDescendants());
masterList.AppendToTop(tempLists.Outlines());
// Restore the saved clip so it applies to the thumb container layer.
thumbContentsClipState.Restore();
// Wrap the list to make it its own layer.
const ActiveScrolledRoot* ownLayerASR = contASRTracker.GetContainerASR();
DisplayListClipState::AutoSaveRestore ownLayerClipState(aBuilder);
ownLayerClipState.ClearUpToASR(ownLayerASR);
aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayOwnLayer(aBuilder, this, &masterList, ownLayerASR,
flags, scrollTargetId,