diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index f3ad78920675..64c6cd10b4b5 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -1488,9 +1488,9 @@ public: * This setter can be used anytime. The user data for all keys is * initially null. Ownership pases to the layer manager. */ - void SetUserData(void* aKey, LayerUserData* aData, void (*aDestroy)(void*) = LayerManager::LayerUserDataDestroy) + void SetUserData(void* aKey, LayerUserData* aData) { - mUserData.Add(static_cast(aKey), aData, aDestroy); + mUserData.Add(static_cast(aKey), aData, LayerManager::LayerUserDataDestroy); } /** * This can be used anytime. Ownership passes to the caller! diff --git a/layout/painting/DisplayItemClip.cpp b/layout/painting/DisplayItemClip.cpp index 4def94d26074..098f22a0551a 100644 --- a/layout/painting/DisplayItemClip.cpp +++ b/layout/painting/DisplayItemClip.cpp @@ -410,7 +410,7 @@ DisplayItemClip::AppendRoundedRects(nsTArray* aArray, uint32_t aCou } bool -DisplayItemClip::ComputeRegionInClips(const DisplayItemClip* aOldClip, +DisplayItemClip::ComputeRegionInClips(DisplayItemClip* aOldClip, const nsPoint& aShift, nsRegion* aCombined) const { diff --git a/layout/painting/DisplayItemClip.h b/layout/painting/DisplayItemClip.h index 1ef0601f193a..c3ed1a67aecc 100644 --- a/layout/painting/DisplayItemClip.h +++ b/layout/painting/DisplayItemClip.h @@ -121,7 +121,7 @@ public: * The result is stored in aCombined. If the result would be infinite * (because one or both of the clips does no clipping), returns false. */ - bool ComputeRegionInClips(const DisplayItemClip* aOldClip, + bool ComputeRegionInClips(DisplayItemClip* aOldClip, const nsPoint& aShift, nsRegion* aCombined) const; diff --git a/layout/painting/FrameLayerBuilder.cpp b/layout/painting/FrameLayerBuilder.cpp index 8dbff0b19229..3d3acbe3c2a3 100644 --- a/layout/painting/FrameLayerBuilder.cpp +++ b/layout/painting/FrameLayerBuilder.cpp @@ -117,6 +117,23 @@ static inline MaskLayerImageCache* GetMaskLayerImageCache() return gMaskLayerImageCache; } +FrameLayerBuilder::FrameLayerBuilder() + : mRetainingManager(nullptr) + , mContainingPaintedLayer(nullptr) + , mInactiveLayerClip(nullptr) + , mInvalidateAllLayers(false) + , mInLayerTreeCompressionMode(false) + , mIsInactiveLayerManager(false) +{ + MOZ_COUNT_CTOR(FrameLayerBuilder); +} + +FrameLayerBuilder::~FrameLayerBuilder() +{ + GetMaskLayerImageCache()->Sweep(); + MOZ_COUNT_DTOR(FrameLayerBuilder); +} + DisplayItemData::DisplayItemData(LayerManagerData* aParent, uint32_t aKey, Layer* aLayer, nsIFrame* aFrame) @@ -196,16 +213,6 @@ DisplayItemData::EndUpdate(nsAutoPtr aGeometry) void DisplayItemData::BeginUpdate(Layer* aLayer, LayerState aState, nsDisplayItem* aItem /* = nullptr */) -{ - BeginUpdate(aLayer, aState, aItem, - aItem ? aItem->IsReused() : false, - aItem ? aItem->HasMergedFrames() : false); -} - -void -DisplayItemData::BeginUpdate(Layer* aLayer, LayerState aState, - nsDisplayItem* aItem, bool aIsReused, - bool aIsMerged) { MOZ_RELEASE_ASSERT(mLayer); MOZ_RELEASE_ASSERT(aLayer); @@ -217,18 +224,13 @@ DisplayItemData::BeginUpdate(Layer* aLayer, LayerState aState, if (aLayer->AsPaintedLayer()) { mItem = aItem; - mReusedItem = aIsReused; + mReusedItem = aItem->IsReused(); } if (!aItem) { return; } - if (!aIsMerged && mFrameList.Length() == 1) { - MOZ_ASSERT(mFrameList[0] == aItem->Frame()); - return; - } - // We avoid adding or removing element unnecessarily // since we have to modify userdata each time AutoTArray copy(mFrameList); @@ -852,6 +854,11 @@ public: void FinishAllChildren() { FinishAllChildren(true); } protected: + /** + * Finish the topmost item in mPaintedLayerDataStack and pop it from the + * stack. + */ + void PopPaintedLayerData(); /** * Finish all items in mPaintedLayerDataStack and clear the stack. */ @@ -873,7 +880,7 @@ protected: /** * Our contents: a PaintedLayerData stack and our child nodes. */ - AutoTArray mPaintedLayerDataStack; + nsTArray mPaintedLayerDataStack; /** * UniquePtr is used here in the sense of "unique ownership", i.e. there is @@ -941,7 +948,6 @@ public: nscolor& aBackgroundColor) : mContainerState(aContainerState) , mContainerUniformBackgroundColor(aBackgroundColor) - , mForInactiveLayer(false) {} ~PaintedLayerDataTree() @@ -950,8 +956,6 @@ public: MOZ_ASSERT(mNodes.Count() == 0); } - void InitializeForInactiveLayer(AnimatedGeometryRoot* aAnimatedGeometryRoot); - /** * Notify our contents that some non-PaintedLayer content has been added. * *aRect needs to be a rectangle that doesn't move with respect to @@ -1039,7 +1043,7 @@ protected: AnimatedGeometryRoot** aOutAncestorChild); ContainerState& mContainerState; - Maybe mRoot; + UniquePtr mRoot; /** * The uniform opaque color from behind this container layer, or @@ -1054,8 +1058,6 @@ protected: * geometry root. */ nsDataHashtable, PaintedLayerDataNode*> mNodes; - - bool mForInactiveLayer; }; /** @@ -1387,10 +1389,9 @@ protected: * aRoundedRectClipCount is used when building mask layers for PaintedLayers, * SetupMaskLayer will build a mask layer for only the first * aRoundedRectClipCount rounded rects in aClip - * Returns the number of rounded rects included in the mask layer. */ - uint32_t SetupMaskLayer(Layer *aLayer, const DisplayItemClip& aClip, - uint32_t aRoundedRectClipCount = UINT32_MAX); + void SetupMaskLayer(Layer *aLayer, const DisplayItemClip& aClip, + uint32_t aRoundedRectClipCount = UINT32_MAX); /** * If |aClip| has rounded corners, create a mask layer for them, and @@ -1499,17 +1500,12 @@ class PaintedDisplayItemLayerUserData : public LayerUserData public: PaintedDisplayItemLayerUserData() : mMaskClipCount(0), - mLastCommonClipCount(0), mForcedBackgroundColor(NS_RGBA(0,0,0,0)), mXScale(1.f), mYScale(1.f), mAppUnitsPerDevPixel(0), mTranslation(0, 0), mAnimatedGeometryRootPosition(0, 0), - mLastItemCount(0), - mContainerLayerFrame(nullptr), - mHasExplicitLastPaintOffset(false) {} - - NS_INLINE_DECL_REFCOUNTING(PaintedDisplayItemLayerUserData); + mLastItemCount(0) {} /** * Record the number of clips in the PaintedLayer's mask layer. @@ -1518,12 +1514,6 @@ public: */ uint32_t mMaskClipCount; - /** - * Records the number of clips in the PaintedLayer's mask layer during - * the previous paint. Used for invalidation. - */ - uint32_t mLastCommonClipCount; - /** * A color that should be painted over the bounds of the layer's visible * region before any other content is painted. @@ -1581,54 +1571,12 @@ public: // The number of items assigned to this layer on the previous paint. size_t mLastItemCount; - // The translation set on this PaintedLayer before we started updating the - // layer tree. - nsIntPoint mLastPaintOffset; - - // Temporary state only valid during the FrameLayerBuilder's lifetime. - // FLB's mPaintedLayerItems is responsible for cleaning these up when - // we finish painting to avoid dangling pointers. - nsTArray mItems; - nsIFrame* mContainerLayerFrame; - - bool mHasExplicitLastPaintOffset; - /** * This is set when the painted layer has no component alpha. */ bool mDisabledAlpha; - -protected: - ~PaintedDisplayItemLayerUserData() = default; }; -FrameLayerBuilder::FrameLayerBuilder() - : mRetainingManager(nullptr) - , mContainingPaintedLayer(nullptr) - , mInactiveLayerClip(nullptr) - , mInvalidateAllLayers(false) - , mInLayerTreeCompressionMode(false) - , mIsInactiveLayerManager(false) -{ - MOZ_COUNT_CTOR(FrameLayerBuilder); -} - -FrameLayerBuilder::~FrameLayerBuilder() -{ - GetMaskLayerImageCache()->Sweep(); - for (PaintedDisplayItemLayerUserData* userData : mPaintedLayerItems) { - userData->mItems.Clear(); - userData->mContainerLayerFrame = nullptr; - } - MOZ_COUNT_DTOR(FrameLayerBuilder); -} - -void -FrameLayerBuilder::AddPaintedLayerItemsEntry(PaintedDisplayItemLayerUserData* aData) -{ - mPaintedLayerItems.AppendElement(aData); -} - /* * User data for layers which will be used as masks. */ @@ -2393,13 +2341,6 @@ ContainerState::AttemptToRecyclePaintedLayer(AnimatedGeometryRoot* aAnimatedGeom return layer.forget(); } -void ReleaseLayerUserData(void* aData) -{ - PaintedDisplayItemLayerUserData* userData = - static_cast(aData); - userData->Release(); -} - already_AddRefed ContainerState::CreatePaintedLayer(PaintedLayerData* aData) { @@ -2413,11 +2354,10 @@ ContainerState::CreatePaintedLayer(PaintedLayerData* aData) } // Mark this layer as being used for painting display items - RefPtr userData = new PaintedDisplayItemLayerUserData(); + PaintedDisplayItemLayerUserData* userData = new PaintedDisplayItemLayerUserData(); userData->mDisabledAlpha = mParameters.mDisableSubpixelAntialiasingInDescendants; - userData->AddRef(); - layer->SetUserData(&gPaintedDisplayItemLayerUserData, userData, ReleaseLayerUserData); + layer->SetUserData(&gPaintedDisplayItemLayerUserData, userData); ResetScrollPositionForLayerPixelAlignment(aData->mAnimatedGeometryRoot); PreparePaintedLayerForUse(layer, userData, aData->mAnimatedGeometryRoot, @@ -2495,9 +2435,7 @@ ContainerState::PreparePaintedLayerForUse(PaintedLayer* aLayer, aData->mAppUnitsPerDevPixel = mAppUnitsPerDevPixel; aLayer->SetAllowResidualTranslation(mParameters.AllowResidualTranslation()); - aData->mLastPaintOffset = GetTranslationForPaintedLayer(aLayer); - aData->mHasExplicitLastPaintOffset = true; - aData->mLastCommonClipCount = aData->mMaskClipCount; + mLayerBuilder->SavePreviousDataForLayer(aLayer, aData->mMaskClipCount); // Set up transform so that 0,0 in the PaintedLayer corresponds to the // (pixel-snapped) top-left of the aAnimatedGeometryRoot. @@ -2929,23 +2867,23 @@ PaintedLayerDataNode::SetAllDrawingAbove() } void -PaintedLayerDataNode::PopAllPaintedLayerData() +PaintedLayerDataNode::PopPaintedLayerData() { - for (int32_t index = mPaintedLayerDataStack.Length() - 1; index >= 0; index--) { - PaintedLayerData& data = mPaintedLayerDataStack[index]; - mTree.ContState().FinishPaintedLayerData(data, [this, &data, index]() { - return this->FindOpaqueBackgroundColor(data.mVisibleRegion, index); - }); - } - mPaintedLayerDataStack.Clear(); + MOZ_ASSERT(!mPaintedLayerDataStack.IsEmpty()); + size_t lastIndex = mPaintedLayerDataStack.Length() - 1; + PaintedLayerData& data = mPaintedLayerDataStack[lastIndex]; + mTree.ContState().FinishPaintedLayerData(data, [this, &data, lastIndex]() { + return this->FindOpaqueBackgroundColor(data.mVisibleRegion, lastIndex); + }); + mPaintedLayerDataStack.RemoveElementAt(lastIndex); } void -PaintedLayerDataTree::InitializeForInactiveLayer(AnimatedGeometryRoot* aAnimatedGeometryRoot) +PaintedLayerDataNode::PopAllPaintedLayerData() { - mForInactiveLayer = true; - mRoot.emplace(*this, nullptr, aAnimatedGeometryRoot); - + while (!mPaintedLayerDataStack.IsEmpty()) { + PopPaintedLayerData(); + } } nsDisplayListBuilder* @@ -2961,7 +2899,7 @@ PaintedLayerDataTree::Finish() mRoot->Finish(false); } MOZ_ASSERT(mNodes.Count() == 0); - mRoot.reset(); + mRoot = nullptr; } void @@ -2975,13 +2913,8 @@ PaintedLayerDataTree::AddingOwnLayer(AnimatedGeometryRoot* aAnimatedGeometryRoot const nsIntRect* aRect, nscolor* aOutUniformBackgroundColor) { - PaintedLayerDataNode* node = nullptr; - if (mForInactiveLayer) { - node = mRoot.ptr(); - } else { - FinishPotentiallyIntersectingNodes(aAnimatedGeometryRoot, aRect); - node = EnsureNodeFor(aAnimatedGeometryRoot); - } + FinishPotentiallyIntersectingNodes(aAnimatedGeometryRoot, aRect); + PaintedLayerDataNode* node = EnsureNodeFor(aAnimatedGeometryRoot); if (aRect) { if (aOutUniformBackgroundColor) { *aOutUniformBackgroundColor = node->FindOpaqueBackgroundColor(*aRect); @@ -3005,13 +2938,8 @@ PaintedLayerDataTree::FindPaintedLayerFor(AnimatedGeometryRoot* aAnimatedGeometr NewPaintedLayerCallbackType aNewPaintedLayerCallback) { const nsIntRect* bounds = &aVisibleRect; - PaintedLayerDataNode* node = nullptr; - if (mForInactiveLayer) { - node = mRoot.ptr(); - } else { - FinishPotentiallyIntersectingNodes(aAnimatedGeometryRoot, bounds); - node = EnsureNodeFor(aAnimatedGeometryRoot); - } + FinishPotentiallyIntersectingNodes(aAnimatedGeometryRoot, bounds); + PaintedLayerDataNode* node = EnsureNodeFor(aAnimatedGeometryRoot); PaintedLayerData* data = node->FindPaintedLayerFor(aVisibleRect, aBackfaceHidden, aASR, aClipChain, @@ -3080,8 +3008,8 @@ PaintedLayerDataTree::EnsureNodeFor(AnimatedGeometryRoot* aAnimatedGeometryRoot) if (!parentAnimatedGeometryRoot) { MOZ_ASSERT(!mRoot); MOZ_ASSERT(*aAnimatedGeometryRoot == Builder()->RootReferenceFrame()); - mRoot.emplace(*this, nullptr, aAnimatedGeometryRoot); - node = mRoot.ptr(); + mRoot = MakeUnique(*this, nullptr, aAnimatedGeometryRoot); + node = mRoot.get(); } else { PaintedLayerDataNode* parentNode = EnsureNodeFor(parentAnimatedGeometryRoot); MOZ_ASSERT(parentNode); @@ -3096,9 +3024,6 @@ bool PaintedLayerDataTree::IsClippedWithRespectToParentAnimatedGeometryRoot(AnimatedGeometryRoot* aAnimatedGeometryRoot, nsIntRect* aOutClip) { - if (mForInactiveLayer) { - return false; - } nsIScrollableFrame* scrollableFrame = nsLayoutUtils::GetScrollableFrameFor(*aAnimatedGeometryRoot); if (!scrollableFrame) { return false; @@ -3242,14 +3167,18 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_LAYER_EVENT_REGIONS); MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO); - InvalidateForLayerChange(item.mItem, data->mLayer, item.mDisplayItemData); - mLayerBuilder->AddPaintedDisplayItem(data, item, *this, - data->mAnimatedGeometryRootOffset); - item.mDisplayItemData = nullptr; + DisplayItemData* oldData = + mLayerBuilder->GetOldLayerForFrame(item.mItem->Frame(), + item.mItem->GetPerFrameKey(), + item.mItem->HasMergedFrames() ? nullptr : item.mItem->GetDisplayItemData()); + InvalidateForLayerChange(item.mItem, data->mLayer, oldData); + mLayerBuilder->AddPaintedDisplayItem(data, item.mItem, item.mClip, + *this, item.mLayerState, + data->mAnimatedGeometryRootOffset, + oldData, item); } PaintedDisplayItemLayerUserData* userData = GetPaintedDisplayItemLayerUserData(data->mLayer); - NS_ASSERTION(userData, "where did our user data go?"); userData->mLastItemCount = data->mAssignedDisplayItems.Length(); NewLayerEntry* newLayerEntry = &mNewChildLayers[data->mNewChildLayersIndex]; @@ -3325,7 +3254,9 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB } #endif - mLayerBuilder->AddPaintedLayerItemsEntry(userData); + FrameLayerBuilder::PaintedLayerItemsEntry* entry = mLayerBuilder-> + AddPaintedLayerItemsEntry(static_cast(layer.get())); + MOZ_ASSERT(entry); nsIntRegion transparentRegion; transparentRegion.Sub(data->mVisibleRegion, data->mOpaqueRegion); @@ -3343,6 +3274,9 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB } // Store the background color + PaintedDisplayItemLayerUserData* userData = + GetPaintedDisplayItemLayerUserData(data->mLayer); + NS_ASSERTION(userData, "where did our user data go?"); if (userData->mForcedBackgroundColor != backgroundColor) { // Invalidate the entire target PaintedLayer since we're changing // the background color @@ -3362,18 +3296,11 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB // use a mask layer for rounded rect clipping. // data->mCommonClipCount may be -1 if we haven't put any actual // drawable items in this layer (i.e. it's only catching events). - uint32_t commonClipCount; + int32_t commonClipCount; commonClipCount = std::max(0, data->mCommonClipCount); - - // if the number of clips we are going to mask has decreased, then aLayer might have - // cached graphics which assume the existence of a soon-to-be non-existent mask layer - // in that case, invalidate the whole layer. - if (commonClipCount < userData->mMaskClipCount) { - PaintedLayer* painted = layer->AsPaintedLayer(); - painted->InvalidateWholeLayer(); - } - - userData->mMaskClipCount = SetupMaskLayer(layer, data->mItemClip, commonClipCount); + SetupMaskLayer(layer, data->mItemClip, commonClipCount); + // copy commonClipCount to the entry + entry->mCommonClipCount = commonClipCount; } else { // mask layer for image and color layers SetupMaskLayer(layer, data->mItemClip); @@ -3396,8 +3323,8 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB } layer->SetContentFlags(flags); - userData->mItems = Move(data->mAssignedDisplayItems); - userData->mContainerLayerFrame = GetContainerFrame(); + entry->mItems = Move(data->mAssignedDisplayItems); + entry->mContainerLayerFrame = GetContainerFrame(); PaintedLayerData* containingPaintedLayerData = mLayerBuilder->GetContainingPaintedLayerData(); @@ -3545,11 +3472,7 @@ PaintedLayerData::Accumulate(ContainerState* aState, bool clipMatches = mItemClip == aClip; mItemClip = aClip; - DisplayItemData* oldData = - aState->mLayerBuilder->GetOldLayerForFrame(aItem->Frame(), - aItem->GetPerFrameKey(), - aItem->HasMergedFrames() ? nullptr : aItem->GetDisplayItemData()); - mAssignedDisplayItems.AppendElement(AssignedDisplayItem(aItem, aClip, aLayerState, oldData)); + mAssignedDisplayItems.AppendElement(AssignedDisplayItem(aItem, aClip, aLayerState)); if (aItem->MustPaintOnContentSide()) { mShouldPaintOnContentSide = true; @@ -4160,10 +4083,6 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList) bool hadCompositorHitTestInfo = false; #endif - if (!mManager->IsWidgetLayerManager()) { - mPaintedLayerDataTree.InitializeForInactiveLayer(mContainerAnimatedGeometryRoot); - } - AnimatedGeometryRoot* lastAnimatedGeometryRoot = nullptr; nsPoint lastTopLeft; FlattenedDisplayItemIterator iter(mBuilder, aList); @@ -4657,11 +4576,9 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList) * No need to allocate geometry for items that aren't * part of a PaintedLayer. */ - if (ownLayer->Manager() == mLayerBuilder->GetRetainingLayerManager()) { - oldData = - mLayerBuilder->GetOldLayerForFrame(item->Frame(), item->GetPerFrameKey()); - mLayerBuilder->StoreDataForFrame(item, ownLayer, layerState, oldData); - } + oldData = + mLayerBuilder->GetOldLayerForFrame(item->Frame(), item->GetPerFrameKey()); + mLayerBuilder->AddLayerDisplayItem(ownLayer, item, layerState, nullptr, oldData); } else { const bool backfaceHidden = item->In3DContextAndBackfaceIsHidden(); const nsIFrame* referenceFrame = item->ReferenceFrame(); @@ -4817,9 +4734,10 @@ FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData) if (!combined.IsEmpty() || aData->mLayerState == LAYER_INACTIVE) { geometry = item->AllocateGeometry(mDisplayListBuilder); } - aData->mClip.AddOffsetAndComputeDifference(layerData->mMaskClipCount, + PaintedLayerItemsEntry* entry = mPaintedLayerItems.GetEntry(paintedLayer); + aData->mClip.AddOffsetAndComputeDifference(entry->mCommonClipCount, shift, aData->mGeometry->ComputeInvalidationRegion(), - clip, layerData->mLastCommonClipCount, + clip, entry->mLastCommonClipCount, geometry ? geometry->ComputeInvalidationRegion() : aData->mGeometry->ComputeInvalidationRegion(), &combined); @@ -4852,9 +4770,13 @@ FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData) void FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, - AssignedDisplayItem& aItem, - ContainerState& aContainerState, - const nsPoint& aTopLeft) + nsDisplayItem* aItem, + const DisplayItemClip& aClip, + ContainerState& aContainerState, + LayerState aLayerState, + const nsPoint& aTopLeft, + DisplayItemData* aData, + AssignedDisplayItem& aAssignedDisplayItem) { PaintedLayer* layer = aLayerData->mLayer; PaintedDisplayItemLayerUserData* paintedData = @@ -4863,42 +4785,37 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, RefPtr tempManager; nsIntRect intClip; bool hasClip = false; - if (aItem.mLayerState != LAYER_NONE) { - if (aItem.mDisplayItemData) { - tempManager = aItem.mDisplayItemData->mInactiveManager; - - // We need to grab these before updating the DisplayItemData because it will overwrite them. - nsRegion clip; - if (aItem.mClip.ComputeRegionInClips(&aItem.mDisplayItemData->GetClip(), - aTopLeft - paintedData->mLastAnimatedGeometryRootOrigin, - &clip)) { - intClip = clip.GetBounds().ScaleToOutsidePixels(paintedData->mXScale, - paintedData->mYScale, - paintedData->mAppUnitsPerDevPixel); - } + if (aLayerState != LAYER_NONE) { + DisplayItemData *data = GetDisplayItemDataForManager(aItem, layer->Manager()); + if (data) { + tempManager = data->mInactiveManager; } if (!tempManager) { tempManager = new BasicLayerManager(BasicLayerManager::BLM_INACTIVE); } + + // We need to grab these before calling AddLayerDisplayItem because it will overwrite them. + nsRegion clip; + DisplayItemClip* oldClip = nullptr; + GetOldLayerFor(aItem, nullptr, &oldClip); + hasClip = aClip.ComputeRegionInClips(oldClip, + aTopLeft - paintedData->mLastAnimatedGeometryRootOrigin, + &clip); + + if (hasClip) { + intClip = clip.GetBounds().ScaleToOutsidePixels(paintedData->mXScale, + paintedData->mYScale, + paintedData->mAppUnitsPerDevPixel); + } } - if (layer->Manager() == mRetainingManager) { - DisplayItemData *data = aItem.mDisplayItemData; - if (data) { - if (!data->mUsed) { - data->BeginUpdate(layer, aItem.mLayerState, aItem.mItem, aItem.mReused, aItem.mMerged); - } - } else { - data = StoreDataForFrame(aItem.mItem, layer, aItem.mLayerState, nullptr); - } - data->mInactiveManager = tempManager; - } + AddLayerDisplayItem(layer, aItem, aLayerState, tempManager, aData); if (tempManager) { - FLB_LOG_PAINTED_LAYER_DECISION(aLayerData, "Creating nested FLB for item %p\n", aItem.mItem); + FLB_LOG_PAINTED_LAYER_DECISION(aLayerData, "Creating nested FLB for item %p\n", aItem); FrameLayerBuilder* layerBuilder = new FrameLayerBuilder(); layerBuilder->Init(mDisplayListBuilder, tempManager, aLayerData, true, - &aItem.mClip); + &aClip); tempManager->BeginTransaction(); if (mRetainingManager) { @@ -4907,24 +4824,24 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, UniquePtr props(LayerProperties::CloneFrom(tempManager->GetRoot())); RefPtr tmpLayer = - aItem.mItem->BuildLayer(mDisplayListBuilder, tempManager, ContainerLayerParameters()); + aItem->BuildLayer(mDisplayListBuilder, tempManager, ContainerLayerParameters()); // We have no easy way of detecting if this transaction will ever actually get finished. // For now, I've just silenced the warning with nested transactions in BasicLayers.cpp if (!tmpLayer) { tempManager->EndTransaction(nullptr, nullptr); tempManager->SetUserData(&gLayerManagerLayerBuilder, nullptr); - aItem.mItem = nullptr; + aAssignedDisplayItem.mItem = nullptr; return; } bool snap; nsRect visibleRect = - aItem.mItem->GetVisibleRect().Intersect(aItem.mItem->GetBounds(mDisplayListBuilder, &snap)); + aItem->GetVisibleRect().Intersect(aItem->GetBounds(mDisplayListBuilder, &snap)); nsIntRegion rgn = visibleRect.ToOutsidePixels(paintedData->mAppUnitsPerDevPixel); // Convert the visible rect to a region and give the item // a chance to try restrict it further. - nsRegion tightBounds = aItem.mItem->GetTightBounds(mDisplayListBuilder, &snap); + nsRegion tightBounds = aItem->GetTightBounds(mDisplayListBuilder, &snap); if (!tightBounds.IsEmpty()) { rgn.AndWith(tightBounds.ToOutsidePixels(paintedData->mAppUnitsPerDevPixel)); } @@ -4940,8 +4857,8 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, (tempManager->GetUserData(&gLayerManagerUserData)); lmd->mParent = parentLmd; #endif - DisplayItemData* data = layerBuilder->GetDisplayItemDataForManager(aItem.mItem, tempManager); - layerBuilder->StoreDataForFrame(aItem.mItem, tmpLayer, LAYER_ACTIVE, data); + DisplayItemData* data = layerBuilder->GetDisplayItemDataForManager(aItem, tempManager); + layerBuilder->StoreDataForFrame(aItem, tmpLayer, LAYER_ACTIVE, data); } tempManager->SetRoot(tmpLayer); @@ -4950,7 +4867,7 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, #ifdef MOZ_DUMP_PAINTING if (gfxUtils::DumpDisplayList() || gfxEnv::DumpPaint()) { - fprintf_stderr(gfxUtils::sDumpPaintFile, "Basic layer tree for painting contents of display item %s(%p):\n", aItem.mItem->Name(), aItem.mItem->Frame()); + fprintf_stderr(gfxUtils::sDumpPaintFile, "Basic layer tree for painting contents of display item %s(%p):\n", aItem->Name(), aItem->Frame()); std::stringstream stream; tempManager->Dump(stream, "", gfxEnv::DumpPaintToFile()); fprint_stderr(gfxUtils::sDumpPaintFile, stream); // not a typo, fprint_stderr declared in LayersLogging.h @@ -4963,18 +4880,18 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, tmpLayer->ComputeEffectiveTransforms(Matrix4x4()); nsIntRegion invalid; if (!props->ComputeDifferences(tmpLayer, invalid, nullptr)) { - nsRect visible = aItem.mItem->Frame()->GetVisualOverflowRect(); + nsRect visible = aItem->Frame()->GetVisualOverflowRect(); invalid = visible.ToOutsidePixels(paintedData->mAppUnitsPerDevPixel); } - if (aItem.mLayerState == LAYER_SVG_EFFECTS) { - invalid = nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(aItem.mItem->Frame(), - aItem.mItem->ToReferenceFrame(), + if (aLayerState == LAYER_SVG_EFFECTS) { + invalid = nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(aItem->Frame(), + aItem->ToReferenceFrame(), invalid); } if (!invalid.IsEmpty()) { #ifdef MOZ_DUMP_PAINTING if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { - printf_stderr("Inactive LayerManager(%p) for display item %s(%p) has an invalid region - invalidating layer %p\n", tempManager.get(), aItem.mItem->Name(), aItem.mItem->Frame(), layer); + printf_stderr("Inactive LayerManager(%p) for display item %s(%p) has an invalid region - invalidating layer %p\n", tempManager.get(), aItem->Name(), aItem->Frame(), layer); } #endif invalid.ScaleRoundOut(paintedData->mXScale, paintedData->mYScale); @@ -4987,7 +4904,7 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, GetTranslationForPaintedLayer(layer)); } } - aItem.mInactiveLayerManager = tempManager; + aAssignedDisplayItem.mInactiveLayerManager = tempManager; } DisplayItemData* @@ -5040,18 +4957,6 @@ FrameLayerBuilder::StoreDataForFrame(nsIFrame* aFrame, lmd->mDisplayItems.PutEntry(data); } -AssignedDisplayItem::AssignedDisplayItem(nsDisplayItem* aItem, - const DisplayItemClip& aClip, - LayerState aLayerState, - DisplayItemData* aData) - : mItem(aItem) - , mClip(aClip) - , mLayerState(aLayerState) - , mDisplayItemData(aData) - , mReused(aItem->IsReused()) - , mMerged(aItem->HasMergedFrames()) -{} - AssignedDisplayItem::~AssignedDisplayItem() { if (mInactiveLayerManager) { @@ -5059,17 +4964,62 @@ AssignedDisplayItem::~AssignedDisplayItem() } } +FrameLayerBuilder::PaintedLayerItemsEntry::PaintedLayerItemsEntry(const PaintedLayer *aKey) + : nsPtrHashKey(aKey) + , mContainerLayerFrame(nullptr) + , mLastCommonClipCount(0) + , mHasExplicitLastPaintOffset(false) + , mCommonClipCount(0) +{ +} + +FrameLayerBuilder::PaintedLayerItemsEntry::PaintedLayerItemsEntry(const PaintedLayerItemsEntry& aOther) + : nsPtrHashKey(aOther.mKey) + , mItems(aOther.mItems) +{ + NS_ERROR("Should never be called, since we ALLOW_MEMMOVE"); +} + +FrameLayerBuilder::PaintedLayerItemsEntry::~PaintedLayerItemsEntry() +{ +} + +void +FrameLayerBuilder::AddLayerDisplayItem(Layer* aLayer, + nsDisplayItem* aItem, + LayerState aLayerState, + BasicLayerManager* aManager, + DisplayItemData* aData) +{ + if (aLayer->Manager() != mRetainingManager) + return; + + DisplayItemData *data = StoreDataForFrame(aItem, aLayer, aLayerState, aData); + data->mInactiveManager = aManager; +} + nsIntPoint FrameLayerBuilder::GetLastPaintOffset(PaintedLayer* aLayer) { - PaintedDisplayItemLayerUserData* layerData = GetPaintedDisplayItemLayerUserData(aLayer); - MOZ_ASSERT(layerData); - if (layerData->mHasExplicitLastPaintOffset) { - return layerData->mLastPaintOffset; + PaintedLayerItemsEntry* entry = mPaintedLayerItems.PutEntry(aLayer); + if (entry) { + if (entry->mHasExplicitLastPaintOffset) + return entry->mLastPaintOffset; } return GetTranslationForPaintedLayer(aLayer); } +void +FrameLayerBuilder::SavePreviousDataForLayer(PaintedLayer* aLayer, uint32_t aClipCount) +{ + PaintedLayerItemsEntry* entry = mPaintedLayerItems.PutEntry(aLayer); + if (entry) { + entry->mLastPaintOffset = GetTranslationForPaintedLayer(aLayer); + entry->mHasExplicitLastPaintOffset = true; + entry->mLastCommonClipCount = aClipCount; + } +} + bool FrameLayerBuilder::CheckInLayerTreeCompressionMode() { @@ -5537,6 +5487,7 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder, const Matrix4x4* aTransform, const ContainerLayerParameters& aIncomingScale, ContainerLayer* aLayer, + LayerState aState, ContainerLayerParameters& aOutgoingScale) { nsIntPoint offset; @@ -5555,7 +5506,7 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder, } Matrix transform2d; if (aContainerFrame && - aLayerBuilder->GetContainingPaintedLayerData() && + (aState == LAYER_INACTIVE || aState == LAYER_SVG_EFFECTS) && (!aTransform || (aTransform->Is2D(&transform2d) && !transform2d.HasNonTranslation()))) { // When we have an inactive ContainerLayer, translate the container by the offset to the @@ -5736,7 +5687,13 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder, return nullptr; } - if (aContainerItem && aContainerItem->GetType() == DisplayItemType::TYPE_SCROLL_INFO_LAYER) { + LayerState layerState = aContainerItem ? aContainerItem->GetLayerState(aBuilder, aManager, aParameters) : LAYER_ACTIVE; + if (layerState == LAYER_INACTIVE && + nsDisplayItem::ForceActiveLayers()) { + layerState = LAYER_ACTIVE; + } + + if (aContainerItem && layerState == LAYER_ACTIVE_EMPTY) { // Empty layers only have metadata and should never have display items. We // early exit because later, invalidation will walk up the frame tree to // determine which painted layer gets invalidated. Since an empty layer @@ -5764,7 +5721,7 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder, aContainerItem, bounds.Intersect(childrenVisible), aTransform, aParameters, - containerLayer, scaleParameters)) { + containerLayer, layerState, scaleParameters)) { return nullptr; } @@ -6185,13 +6142,17 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer, FrameLayerBuilder *layerBuilder = aLayer->Manager()->GetLayerBuilder(); NS_ASSERTION(layerBuilder, "Unexpectedly null layer builder!"); + PaintedLayerItemsEntry* entry = layerBuilder->mPaintedLayerItems.GetEntry(aLayer); + NS_ASSERTION(entry, "We shouldn't be drawing into a layer with no items!"); + if (!entry->mContainerLayerFrame) { + return; + } + + PaintedDisplayItemLayerUserData* userData = static_cast (aLayer->GetUserData(&gPaintedDisplayItemLayerUserData)); NS_ASSERTION(userData, "where did our user data go?"); - if (!userData->mContainerLayerFrame) { - return; - } bool shouldDrawRectsSeparately = ShouldDrawRectsSeparately(&aDrawTarget, aClip); @@ -6209,7 +6170,7 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer, // PaintedLayer gfxContextMatrixAutoSaveRestore saveMatrix(aContext); nsIntPoint offset = GetTranslationForPaintedLayer(aLayer); - nsPresContext* presContext = userData->mContainerLayerFrame->PresContext(); + nsPresContext* presContext = entry->mContainerLayerFrame->PresContext(); if (!userData->mVisibilityComputedRegion.Contains(aDirtyRegion) && !layerBuilder->GetContainingPaintedLayerData()) { @@ -6219,7 +6180,7 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer, // PaintedLayers. If aDirtyRegion has not changed since the previous call // then we can skip this. int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); - RecomputeVisibilityForItems(userData->mItems, builder, aDirtyRegion, + RecomputeVisibilityForItems(entry->mItems, builder, aDirtyRegion, offset, appUnitsPerDevPixel, userData->mXScale, userData->mYScale); userData->mVisibilityComputedRegion = aDirtyRegion; @@ -6243,10 +6204,10 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer, aContext->CurrentMatrixDouble().PreTranslate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y)). PreScale(userData->mXScale, userData->mYScale)); - layerBuilder->PaintItems(userData->mItems, iterRect, aContext, + layerBuilder->PaintItems(entry->mItems, iterRect, aContext, builder, presContext, offset, userData->mXScale, userData->mYScale, - userData->mMaskClipCount); + entry->mCommonClipCount); if (gfxPrefs::GfxLoggingPaintedPixelCountEnabled()) { aLayer->Manager()->AddPaintedPixelCount(iterRect.Area()); } @@ -6259,10 +6220,10 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer, aContext->CurrentMatrixDouble().PreTranslate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y)). PreScale(userData->mXScale,userData->mYScale)); - layerBuilder->PaintItems(userData->mItems, aRegionToDraw.GetBounds(), aContext, + layerBuilder->PaintItems(entry->mItems, aRegionToDraw.GetBounds(), aContext, builder, presContext, offset, userData->mXScale, userData->mYScale, - userData->mMaskClipCount); + entry->mCommonClipCount); if (gfxPrefs::GfxLoggingPaintedPixelCountEnabled()) { aLayer->Manager()->AddPaintedPixelCount( aRegionToDraw.GetBounds().Area()); @@ -6339,26 +6300,47 @@ CalculateBounds(const nsTArray& aRects, int32_t aA return gfx::Rect(bounds.ToNearestPixels(aAppUnitsPerDevPixel)); } -uint32_t +static void +SetClipCount(PaintedDisplayItemLayerUserData* apaintedData, + uint32_t aClipCount) +{ + if (apaintedData) { + apaintedData->mMaskClipCount = aClipCount; + } +} + +void ContainerState::SetupMaskLayer(Layer *aLayer, const DisplayItemClip& aClip, uint32_t aRoundedRectClipCount) { + // if the number of clips we are going to mask has decreased, then aLayer might have + // cached graphics which assume the existence of a soon-to-be non-existent mask layer + // in that case, invalidate the whole layer. + PaintedDisplayItemLayerUserData* paintedData = GetPaintedDisplayItemLayerUserData(aLayer); + if (paintedData && + aRoundedRectClipCount < paintedData->mMaskClipCount) { + PaintedLayer* painted = aLayer->AsPaintedLayer(); + painted->InvalidateWholeLayer(); + } + // don't build an unnecessary mask if (aClip.GetRoundedRectCount() == 0 || aRoundedRectClipCount == 0) { - return 0; + SetClipCount(paintedData, 0); + return; } RefPtr maskLayer = CreateMaskLayer(aLayer, aClip, Nothing(), aRoundedRectClipCount); if (!maskLayer) { - return 0; + SetClipCount(paintedData, 0); + return; } aLayer->SetMaskLayer(maskLayer); - return aRoundedRectClipCount; + SetClipCount(paintedData, aRoundedRectClipCount); } MaskLayerUserData* diff --git a/layout/painting/FrameLayerBuilder.h b/layout/painting/FrameLayerBuilder.h index de4b7cc46485..c3baae6277e7 100644 --- a/layout/painting/FrameLayerBuilder.h +++ b/layout/painting/FrameLayerBuilder.h @@ -43,7 +43,6 @@ class FrameLayerBuilder; class LayerManagerData; class PaintedLayerData; class ContainerState; -class PaintedDisplayItemLayerUserData; /** * Retained data storage: @@ -69,7 +68,6 @@ public: uint32_t GetDisplayItemKey() { return mDisplayItemKey; } layers::Layer* GetLayer() const { return mLayer; } nsDisplayItemGeometry* GetGeometry() const { return mGeometry.get(); } - const DisplayItemClip& GetClip() const { return mClip; } void Invalidate() { mIsInvalid = true; } void ClearAnimationCompositorState(); @@ -156,8 +154,6 @@ private: */ void BeginUpdate(layers::Layer* aLayer, LayerState aState, nsDisplayItem* aItem = nullptr); - void BeginUpdate(layers::Layer* aLayer, LayerState aState, - nsDisplayItem* aItem, bool aIsReused, bool aIsMerged); /** * Completes the update of this, and removes any references to data that won't live @@ -214,14 +210,17 @@ struct AssignedDisplayItem { AssignedDisplayItem(nsDisplayItem* aItem, const DisplayItemClip& aClip, - LayerState aLayerState, - DisplayItemData* aData); + LayerState aLayerState) + : mItem(aItem) + , mClip(aClip) + , mLayerState(aLayerState) + {} + ~AssignedDisplayItem(); nsDisplayItem* mItem; DisplayItemClip mClip; LayerState mLayerState; - DisplayItemData* mDisplayItemData; /** * If the display item is being rendered as an inactive @@ -229,9 +228,6 @@ struct AssignedDisplayItem * used for the inactive transaction. */ RefPtr mInactiveLayerManager; - - bool mReused; - bool mMerged; }; @@ -503,6 +499,21 @@ public: * to be called by file-scope helper functions in FrameLayerBuilder.cpp. */ + /** + * Record aItem as a display item that is rendered by aLayer. + * + * @param aLayer Layer that the display item will be rendered into + * @param aItem Display item to be drawn. + * @param aLayerState What LayerState the item is using. + * @param aManager If the layer is in the LAYER_INACTIVE state, + * then this is the temporary layer manager to draw with. + */ + void AddLayerDisplayItem(Layer* aLayer, + nsDisplayItem* aItem, + LayerState aLayerState, + BasicLayerManager* aManager, + DisplayItemData* aData); + /** * Record aItem as a display item that is rendered by the PaintedLayer * aLayer, with aClipRect, where aContainerLayerFrame is the frame @@ -511,9 +522,13 @@ public: * @param aTopLeft offset from active scrolled root to reference frame */ void AddPaintedDisplayItem(PaintedLayerData* aLayer, - AssignedDisplayItem& aAssignedDisplayItem, - ContainerState& aContainerState, - const nsPoint& aTopLeft); + nsDisplayItem* aItem, + const DisplayItemClip& aClip, + ContainerState& aContainerState, + LayerState aLayerState, + const nsPoint& aTopLeft, + DisplayItemData* aData, + AssignedDisplayItem& aAssignedDisplayItem); /** * Calls GetOldLayerForFrame on the underlying frame of the display item, @@ -574,6 +589,12 @@ public: typedef void (*DisplayItemDataCallback)(nsIFrame *aFrame, DisplayItemData* aItem); + /** + * Save transform that was in aLayer when we last painted, and the position + * of the active scrolled root frame. It must be an integer + * translation. + */ + void SavePreviousDataForLayer(PaintedLayer* aLayer, uint32_t aClipCount); /** * Get the translation transform that was in aLayer when we last painted. It's either * the transform saved by SaveLastPaintTransform, or else the transform @@ -610,6 +631,10 @@ public: */ DisplayItemData* GetOldLayerForFrame(nsIFrame* aFrame, uint32_t aDisplayItemKey, DisplayItemData* aOldData = nullptr); +protected: + + friend class LayerManagerData; + /** * Stores DisplayItemData associated with aFrame, stores the data in * mNewDisplayItemData. @@ -621,9 +646,6 @@ public: Layer* aLayer, LayerState aState); -protected: - friend class LayerManagerData; - // Flash the area within the context clip if paint flashing is enabled. static void FlashPaint(gfxContext *aContext); @@ -682,11 +704,37 @@ protected: * the paint process. This is the hashentry for that hashtable. */ public: + class PaintedLayerItemsEntry : public nsPtrHashKey { + public: + explicit PaintedLayerItemsEntry(const PaintedLayer *key); + PaintedLayerItemsEntry(const PaintedLayerItemsEntry&); + ~PaintedLayerItemsEntry(); + + nsTArray mItems; + nsIFrame* mContainerLayerFrame; + // The translation set on this PaintedLayer before we started updating the + // layer tree. + nsIntPoint mLastPaintOffset; + uint32_t mLastCommonClipCount; + + bool mHasExplicitLastPaintOffset; + /** + * The first mCommonClipCount rounded rectangle clips are identical for + * all items in the layer. Computed in PaintedLayerData. + */ + uint32_t mCommonClipCount; + + enum { ALLOW_MEMMOVE = true }; + }; + /** - * Add the PaintedDisplayItemLayerUserData object as being used in this - * transaction so that we clean it up afterwards. + * Get the PaintedLayerItemsEntry object associated with aLayer in this + * FrameLayerBuilder */ - void AddPaintedLayerItemsEntry(PaintedDisplayItemLayerUserData* aData); + PaintedLayerItemsEntry* AddPaintedLayerItemsEntry(PaintedLayer* aLayer) + { + return mPaintedLayerItems.PutEntry(aLayer); + } PaintedLayerData* GetContainingPaintedLayerData() { @@ -728,12 +776,10 @@ protected: */ nsDisplayListBuilder* mDisplayListBuilder; /** - * An array of PaintedLayer user data objects containing the - * list of display items (plus clipping data) to be rendered in the - * layer. We clean these up at the end of the transaction to - * remove references to display items. + * A map from PaintedLayers to the list of display items (plus + * clipping data) to be rendered in the layer. */ - AutoTArray, 5> mPaintedLayerItems; + nsTHashtable mPaintedLayerItems; /** * When building layers for an inactive layer, this is where the diff --git a/layout/painting/nsDisplayList.cpp b/layout/painting/nsDisplayList.cpp index fbbb58fe249a..77456cad9775 100644 --- a/layout/painting/nsDisplayList.cpp +++ b/layout/painting/nsDisplayList.cpp @@ -3296,7 +3296,7 @@ nsDisplayItem::IntersectClip(nsDisplayListBuilder* aBuilder, const DisplayItemClipChain* aOther, bool aStore) { - if (!aOther || mClipChain == aOther) { + if (!aOther) { return; } @@ -6713,8 +6713,21 @@ nsDisplayOpacity::ShouldFlattenAway(nsDisplayListBuilder* aBuilder) } } + // When intersecting the children's clip, only intersect with the clip for + // our ASR and not with the whole clip chain, because the rest of the clip + // chain is usually already set on the children. In fact, opacity items + // usually never have their own clip because during display item creation + // time we propagated the clip to our contents, so maybe we should just + // remove the clip parameter from ApplyOpacity completely. + const DisplayItemClipChain* clip = nullptr; + + if (mClip) { + clip = aBuilder->AllocateDisplayItemClipChain(*mClip, mActiveScrolledRoot, + nullptr); + } + for (uint32_t i = 0; i < childCount; i++) { - children[i].item->ApplyOpacity(aBuilder, mOpacity, mClipChain); + children[i].item->ApplyOpacity(aBuilder, mOpacity, clip); } return true;