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); 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. * Iterate through the non-clip items in aList and its descendants.
* For each item we compute the effective clip rect. Each item is assigned * For each item we compute the effective clip rect. Each item is assigned
@ -4204,8 +4211,9 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
mPaintedLayerDataTree.AddingOwnLayer(clipAGR, mPaintedLayerDataTree.AddingOwnLayer(clipAGR,
&scrolledClipRect, &scrolledClipRect,
uniformColorPtr); uniformColorPtr);
} else if (*animatedGeometryRoot == item->Frame() && } else if ((*animatedGeometryRoot == item->Frame() &&
*animatedGeometryRoot != mBuilder->RootReferenceFrame()) { *animatedGeometryRoot != mBuilder->RootReferenceFrame()) ||
(IsScrollThumbLayer(item) && mManager->IsWidgetLayerManager())) {
// This is the case for scrollbar thumbs, for example. In that case the // 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. // clip we care about is the overflow:hidden clip on the scrollbar.
mPaintedLayerDataTree.AddingOwnLayer(animatedGeometryRoot->mParentAGR, mPaintedLayerDataTree.AddingOwnLayer(animatedGeometryRoot->mParentAGR,

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

@ -6110,6 +6110,14 @@ nsDisplayOwnLayer::nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder,
, mForceActive(aForceActive) , mForceActive(aForceActive)
{ {
MOZ_COUNT_CTOR(nsDisplayOwnLayer); 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 #ifdef NS_BUILD_REFCNT_LOGGING
@ -6130,6 +6138,20 @@ nsDisplayOwnLayer::GetLayerState(nsDisplayListBuilder* aBuilder,
return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList, mAnimatedGeometryRoot); 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 // nsDisplayOpacity uses layers for rendering
already_AddRefed<Layer> already_AddRefed<Layer>
nsDisplayOwnLayer::BuildLayer(nsDisplayListBuilder* aBuilder, nsDisplayOwnLayer::BuildLayer(nsDisplayListBuilder* aBuilder,

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

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

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

@ -421,6 +421,22 @@ nsSliderFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
nsRect dirty = aDirtyRect.Intersect(thumbRect); nsRect dirty = aDirtyRect.Intersect(thumbRect);
dirty = nsLayoutUtils::ComputePartialPrerenderArea(aDirtyRect, overflow, refSize); 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); nsDisplayListBuilder::AutoContainerASRTracker contASRTracker(aBuilder);
nsDisplayListCollection tempLists; nsDisplayListCollection tempLists;
nsBoxFrame::BuildDisplayListForChildren(aBuilder, dirty, tempLists); nsBoxFrame::BuildDisplayListForChildren(aBuilder, dirty, tempLists);
@ -435,10 +451,11 @@ nsSliderFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
masterList.AppendToTop(tempLists.PositionedDescendants()); masterList.AppendToTop(tempLists.PositionedDescendants());
masterList.AppendToTop(tempLists.Outlines()); 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. // Wrap the list to make it its own layer.
const ActiveScrolledRoot* ownLayerASR = contASRTracker.GetContainerASR(); const ActiveScrolledRoot* ownLayerASR = contASRTracker.GetContainerASR();
DisplayListClipState::AutoSaveRestore ownLayerClipState(aBuilder);
ownLayerClipState.ClearUpToASR(ownLayerASR);
aLists.Content()->AppendNewToTop(new (aBuilder) aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayOwnLayer(aBuilder, this, &masterList, ownLayerASR, nsDisplayOwnLayer(aBuilder, this, &masterList, ownLayerASR,
flags, scrollTargetId, flags, scrollTargetId,