Bug 969354. Track which ThebesLayers contain items which returned true from ShouldFixToViewport, and make sure each such item gets its own ThebesLayer. r=mattwoodrow

--HG--
extra : rebase_source : 629f91869bd4c4ad2e4e17c40c5fe0311532fb67
This commit is contained in:
Robert O'Callahan 2014-02-21 14:11:17 +13:00
parent 7cd361b19e
commit cdf3eb974c
2 changed files with 38 additions and 11 deletions

View File

@ -237,11 +237,13 @@ public:
mAnimatedGeometryRoot(nullptr), mReferenceFrame(nullptr),
mLayer(nullptr),
mIsSolidColorInVisibleRegion(false),
mSingleItemFixedToViewport(false),
mNeedComponentAlpha(false),
mForceTransparentSurface(false),
mImage(nullptr),
mCommonClipCount(-1),
mAllDrawingAbove(false) {}
mAllDrawingAbove(false)
{}
/**
* Record that an item has been added to the ThebesLayer, so we
* need to update our regions.
@ -384,6 +386,11 @@ public:
* True if every pixel in mVisibleRegion will have color mSolidColor.
*/
bool mIsSolidColorInVisibleRegion;
/**
* True if the layer contains exactly one item that returned true for
* ShouldFixToViewport.
*/
bool mSingleItemFixedToViewport;
/**
* True if there is any text visible in the layer that's over
* transparent pixels in the layer.
@ -607,10 +614,13 @@ protected:
* has a displayport. Updates *aVisibleRegion to be the intersection of
* aDrawRegion and the displayport, and updates *aIsSolidColorInVisibleRegion
* (if non-null) to false if the visible region grows.
* aDisplayItemFixedToViewport is true if the layer contains a single display
* item which returned true for ShouldFixToViewport.
* This can return the actual viewport frame for layers whose display items
* are directly on the viewport (e.g. background-attachment:fixed backgrounds).
*/
const nsIFrame* FindFixedPosFrameForLayerData(const nsIFrame* aAnimatedGeometryRoot,
bool aDisplayItemFixedToViewport,
const nsIntRegion& aDrawRegion,
nsIntRegion* aVisibleRegion,
bool* aIsSolidColorInVisibleRegion = nullptr);
@ -641,11 +651,15 @@ protected:
* @param aOpaqueRect if non-null, a region of the display item that is opaque
* @param aSolidColor if non-null, indicates that every pixel in aVisibleRect
* will be painted with aSolidColor by the item
* @param aShouldFixToViewport if true, aAnimatedGeometryRoot is the viewport
* and we will be adding fixed-pos metadata for this layer because the
* display item returned true from ShouldFixToViewport.
*/
ThebesLayerData* FindThebesLayerFor(nsDisplayItem* aItem,
const nsIntRect& aVisibleRect,
const nsIFrame* aAnimatedGeometryRoot,
const nsPoint& aTopLeft);
const nsPoint& aTopLeft,
bool aShouldFixToViewport);
ThebesLayerData* GetTopThebesLayerData()
{
return mThebesLayerDataStack.IsEmpty() ? nullptr
@ -1662,6 +1676,7 @@ ThebesLayerData::CanOptimizeImageLayer(nsDisplayListBuilder* aBuilder)
const nsIFrame*
ContainerState::FindFixedPosFrameForLayerData(const nsIFrame* aAnimatedGeometryRoot,
bool aDisplayItemFixedToViewport,
const nsIntRegion& aDrawRegion,
nsIntRegion* aVisibleRegion,
bool* aIsSolidColorInVisibleRegion)
@ -1676,7 +1691,7 @@ ContainerState::FindFixedPosFrameForLayerData(const nsIFrame* aAnimatedGeometryR
const nsIFrame* result = nullptr;
nsRect displayPort;
if (viewport == aAnimatedGeometryRoot &&
if (viewport == aAnimatedGeometryRoot && aDisplayItemFixedToViewport &&
nsLayoutUtils::ViewportHasDisplayPort(presContext, &displayPort)) {
// Probably a background-attachment:fixed item
result = viewport;
@ -1791,6 +1806,7 @@ ContainerState::PopThebesLayerData()
const nsIFrame* fixedPosFrameForLayerData =
FindFixedPosFrameForLayerData(data->mAnimatedGeometryRoot,
data->mSingleItemFixedToViewport,
data->mDrawRegion,
&data->mVisibleRegion,
&data->mIsSolidColorInVisibleRegion);
@ -2071,7 +2087,7 @@ ThebesLayerData::Accumulate(ContainerState* aState,
mDrawRegion.Or(mDrawRegion, aDrawRect);
mDrawRegion.SimplifyOutward(4);
}
bool snap;
nsRegion opaque = aItem->GetOpaqueRegion(aState->mBuilder, &snap);
if (!opaque.IsEmpty()) {
@ -2123,14 +2139,21 @@ ThebesLayerData*
ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
const nsIntRect& aVisibleRect,
const nsIFrame* aActiveScrolledRoot,
const nsPoint& aTopLeft)
const nsPoint& aTopLeft,
bool aShouldFixToViewport)
{
int32_t i;
int32_t lowestUsableLayerWithScrolledRoot = -1;
int32_t topmostLayerWithScrolledRoot = -1;
for (i = mThebesLayerDataStack.Length() - 1; i >= 0; --i) {
ThebesLayerData* data = mThebesLayerDataStack[i];
if (data->IsBelow(aVisibleRect)) {
// ThebesLayers for items returning true from ShouldFixToViewport should
// not be added to (or have content moved below them),
// since they will receive special treatment for async scrolling.
// If the item is going to be fixed to the viewport, don't let it combine
// with any existing layer.
if (data->IsBelow(aVisibleRect) || data->mSingleItemFixedToViewport ||
aShouldFixToViewport) {
++i;
break;
}
@ -2170,6 +2193,7 @@ ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
thebesLayerData->mLayer = layer;
thebesLayerData->mAnimatedGeometryRoot = aActiveScrolledRoot;
thebesLayerData->mReferenceFrame = aItem->ReferenceFrame();
thebesLayerData->mSingleItemFixedToViewport = aShouldFixToViewport;
NS_ASSERTION(!mNewChildLayers.Contains(layer), "Layer already in list???");
*mNewChildLayers.AppendElement() = layer.forget();
@ -2350,6 +2374,8 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
topLeft = animatedGeometryRoot->GetOffsetToCrossDoc(mContainerReferenceFrame);
}
}
bool shouldFixToViewport = !animatedGeometryRoot->GetParent() &&
item->ShouldFixToViewport(mBuilder);
if (maxLayers != -1 && layerCount >= maxLayers) {
forceInactive = true;
@ -2403,8 +2429,9 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
"Should never have created a dedicated Thebes layer!");
nsIntRegion visibleRegion(itemVisibleRect);
const nsIFrame* fixedPosFrame = FindFixedPosFrameForLayerData(animatedGeometryRoot,
nsIntRegion(itemDrawRect), &visibleRegion);
const nsIFrame* fixedPosFrame =
FindFixedPosFrameForLayerData(animatedGeometryRoot, shouldFixToViewport,
nsIntRegion(itemDrawRect), &visibleRegion);
if (fixedPosFrame) {
itemVisibleRect = visibleRegion.GetBounds();
}
@ -2487,7 +2514,8 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
dummy);
} else {
ThebesLayerData* data =
FindThebesLayerFor(item, itemVisibleRect, animatedGeometryRoot, topLeft);
FindThebesLayerFor(item, itemVisibleRect, animatedGeometryRoot, topLeft,
shouldFixToViewport);
if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) {
nsDisplayLayerEventRegions* eventRegions =

View File

@ -990,8 +990,7 @@ public:
{ return false; }
/**
* @return true if the contents of this item are rendered fixed relative
* to the nearest viewport *and* they cover the viewport's scrollport.
* Only return true if the contents actually vary when scrolling in the viewport.
* to the nearest viewport.
*/
virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder)
{ return false; }