diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index e49e6a23836a..0c5acd8c9cfe 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -138,16 +138,20 @@ public: LayerManager* aManager, FrameLayerBuilder* aLayerBuilder, nsIFrame* aContainerFrame, + nsDisplayItem* aContainerItem, ContainerLayer* aContainerLayer, const FrameLayerBuilder::ContainerParameters& aParameters) : mBuilder(aBuilder), mManager(aManager), mLayerBuilder(aLayerBuilder), - mContainerFrame(aContainerFrame), mContainerLayer(aContainerLayer), + mContainerFrame(aContainerFrame), + mContainerLayer(aContainerLayer), mParameters(aParameters), mNextFreeRecycledThebesLayer(0) { nsPresContext* presContext = aContainerFrame->PresContext(); mAppUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); + mContainerReferenceFrame = aContainerItem ? aContainerItem->ReferenceFrame() : + mBuilder->FindReferenceFrameFor(mContainerFrame); // When AllowResidualTranslation is false, display items will be drawn // scaled with a translation by integer pixels, so we know how the snapping // will work. @@ -306,7 +310,7 @@ protected: * be non-null; all content in a ThebesLayer must have the same * active scrolled root. */ - const nsIFrame* mActiveScrolledRoot; + const nsIFrame* mActiveScrolledRoot; ThebesLayer* mLayer; /** * If mIsSolidColorInVisibleRegion is true, this is the color of the visible @@ -367,7 +371,9 @@ protected: * a recycled ThebesLayer, and sets up the transform on the ThebesLayer * to account for scrolling. */ - already_AddRefed CreateOrRecycleThebesLayer(const nsIFrame* aActiveScrolledRoot, const nsIFrame *aReferenceFrame); + already_AddRefed CreateOrRecycleThebesLayer(const nsIFrame* aActiveScrolledRoot, + const nsIFrame *aReferenceFrame, + const nsPoint& aTopLeft); /** * Grab the next recyclable ColorLayer, or create one if there are no * more recyclable ColorLayers. @@ -432,7 +438,8 @@ protected: const nsIntRect& aVisibleRect, const nsIntRect& aDrawRect, const FrameLayerBuilder::Clip& aClip, - const nsIFrame* aActiveScrolledRoot); + const nsIFrame* aActiveScrolledRoot, + const nsPoint& aTopLeft); ThebesLayerData* GetTopThebesLayerData() { return mThebesLayerDataStack.IsEmpty() ? nullptr @@ -455,6 +462,7 @@ protected: LayerManager* mManager; FrameLayerBuilder* mLayerBuilder; nsIFrame* mContainerFrame; + const nsIFrame* mContainerReferenceFrame; ContainerLayer* mContainerLayer; FrameLayerBuilder::ContainerParameters mParameters; /** @@ -535,8 +543,9 @@ public: nsIntRegion mRegionToInvalidate; - // The result of GetPosition() for the active scrolled root of this layer - // for the previous and current paints respectively. + // The offset between the active scrolled root of this layer + // and the root of the container for the previous and current + // paints respectively. nsPoint mLastActiveScrolledRootOrigin; nsPoint mActiveScrolledRootOrigin; @@ -855,6 +864,7 @@ FrameLayerBuilder::RemoveFrameFromLayerManager(nsIFrame* aFrame, } } } + sDestroyedFrame = aFrame; data->mFramesWithLayers.RemoveEntry(aFrame); sDestroyedFrame = NULL; @@ -1361,7 +1371,9 @@ InvalidateEntireThebesLayer(ThebesLayer* aLayer, const nsIFrame* aActiveScrolled } already_AddRefed -ContainerState::CreateOrRecycleThebesLayer(const nsIFrame* aActiveScrolledRoot, const nsIFrame* aReferenceFrame) +ContainerState::CreateOrRecycleThebesLayer(const nsIFrame* aActiveScrolledRoot, + const nsIFrame* aReferenceFrame, + const nsPoint& aTopLeft) { // We need a new thebes layer nsRefPtr layer; @@ -1423,7 +1435,7 @@ ContainerState::CreateOrRecycleThebesLayer(const nsIFrame* aActiveScrolledRoot, data->mXScale = mParameters.mXScale; data->mYScale = mParameters.mYScale; data->mLastActiveScrolledRootOrigin = data->mActiveScrolledRootOrigin; - data->mActiveScrolledRootOrigin = aActiveScrolledRoot->GetPosition(); + data->mActiveScrolledRootOrigin = aTopLeft; data->mAppUnitsPerDevPixel = mAppUnitsPerDevPixel; layer->SetAllowResidualTranslation(mParameters.AllowResidualTranslation()); @@ -1513,30 +1525,6 @@ RestrictVisibleRegionForLayer(Layer* aLayer, const nsIntRect& aItemVisible) } } -static void -SetVisibleRegionForLayer(Layer* aLayer, const nsIntRect& aItemVisible, const nsIntRect& aChildBounds) -{ - gfx3DMatrix transform = aLayer->GetTransform(); - - // if 'transform' is not invertible, then nothing will be displayed - // for the layer, so it doesn't really matter what we do here - gfxRect itemVisible(aItemVisible.x, aItemVisible.y, aItemVisible.width, aItemVisible.height); - gfxRect layerVisible = transform.Inverse().ProjectRectBounds(itemVisible); - layerVisible.RoundOut(); - - nsIntRect visibleRect; - if (!gfxUtils::GfxRectToIntRect(layerVisible, &visibleRect)) - return; - - nsIntRegion rgn = aChildBounds; - if (!visibleRect.Contains(aChildBounds)) { - rgn.And(rgn, visibleRect); - aLayer->SetVisibleRegion(rgn); - } else { - aLayer->SetVisibleRegion(aChildBounds); - } -} - nscolor ContainerState::FindOpaqueBackgroundColorFor(int32_t aThebesLayerIndex) { @@ -1917,7 +1905,8 @@ ContainerState::FindThebesLayerFor(nsDisplayItem* aItem, const nsIntRect& aVisibleRect, const nsIntRect& aDrawRect, const FrameLayerBuilder::Clip& aClip, - const nsIFrame* aActiveScrolledRoot) + const nsIFrame* aActiveScrolledRoot, + const nsPoint& aTopLeft) { int32_t i; int32_t lowestUsableLayerWithScrolledRoot = -1; @@ -1957,7 +1946,7 @@ ContainerState::FindThebesLayerFor(nsDisplayItem* aItem, nsRefPtr layer; ThebesLayerData* thebesLayerData = nullptr; if (lowestUsableLayerWithScrolledRoot < 0) { - layer = CreateOrRecycleThebesLayer(aActiveScrolledRoot, aItem->ReferenceFrame()); + layer = CreateOrRecycleThebesLayer(aActiveScrolledRoot, aItem->ReferenceFrame(), aTopLeft); NS_ASSERTION(!mNewChildLayers.Contains(layer), "Layer already in list???"); mNewChildLayers.AppendElement(layer); @@ -2096,18 +2085,20 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList, bool isFixed; bool forceInactive; const nsIFrame* activeScrolledRoot; + nsPoint topLeft; if (aFlags & NO_COMPONENT_ALPHA) { // When NO_COMPONENT_ALPHA is set, items will be flattened onto the // reference frame. In this case, force the active scrolled root to // that frame. forceInactive = true; - activeScrolledRoot = mBuilder->FindReferenceFrameFor(mContainerFrame); + activeScrolledRoot = mContainerReferenceFrame; + topLeft = nsPoint(0, 0); isFixed = mBuilder->IsFixedItem(item, nullptr, activeScrolledRoot); } else { forceInactive = false; isFixed = mBuilder->IsFixedItem(item, &activeScrolledRoot); + topLeft = activeScrolledRoot->GetOffsetToCrossDoc(mContainerReferenceFrame); } - nsPoint topLeft = activeScrolledRoot->GetPosition(); // Assign the item to a layer if (layerState == LAYER_ACTIVE_FORCE || @@ -2200,7 +2191,7 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList, } else { ThebesLayerData* data = FindThebesLayerFor(item, itemVisibleRect, itemDrawRect, aClip, - activeScrolledRoot); + activeScrolledRoot, topLeft); data->mLayer->SetIsFixedPosition(isFixed); @@ -2233,10 +2224,7 @@ ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, Layer* oldLayer = mLayerBuilder->GetOldLayerFor(aItem, &oldGeometry, &oldClip); if (aNewLayer != oldLayer && oldLayer) { // The item has changed layers. - // Invalidate the bounds in the old layer and new layer. - // The bounds might have changed, but we assume that any difference - // in the bounds will have been invalidated for all Thebes layers - // in the container via regular frame invalidation. + // Invalidate the old bounds in the old layer and new bounds in the new layer. ThebesLayer* t = oldLayer->AsThebesLayer(); if (t) { // Note that whenever the layer's scale changes, we invalidate the whole thing, @@ -2754,36 +2742,6 @@ FrameLayerBuilder::RestoreThebesLayerItemEntries(ThebesLayerItemsEntry* aEntry, return PL_DHASH_NEXT; } -static nsDisplayTransform* FindTransformForContainerFrame(nsIFrame* aContainerFrame, - nsDisplayItem* aContainerItem) -{ - if (!aContainerFrame->IsTransformed() || - aContainerItem->GetType() == nsDisplayItem::TYPE_TRANSFORM) - return nullptr; - - nsTArray queue; - queue.AppendElement(aContainerItem); - while (queue.Length()) { - nsDisplayItem* item = queue[queue.Length() - 1]; - queue.RemoveElementAt(queue.Length() - 1); - - if (item->GetType() == nsDisplayItem::TYPE_TRANSFORM) { - return static_cast(item); - } - - if (item->GetList()) { - for (nsDisplayItem* child = item->GetList()->GetBottom(); child; - child = child->GetAbove()) { - if (child->GetUnderlyingFrame() == aContainerFrame) { - queue.AppendElement(child); - } - } - } - } - - return nullptr; -} - already_AddRefed FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder, LayerManager* aManager, @@ -2793,7 +2751,6 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder, const ContainerParameters& aParameters, const gfx3DMatrix* aTransform) { - FrameProperties props = aContainerFrame->Properties(); uint32_t containerDisplayItemKey = aContainerItem ? aContainerItem->GetPerFrameKey() : 0; NS_ASSERTION(aContainerFrame, "Container display items here should have a frame"); @@ -2904,7 +2861,8 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder, (aManager->GetUserData(&gLayerManagerUserData)); while (true) { ContainerState state(aBuilder, aManager, aManager->GetLayerBuilder(), - aContainerFrame, containerLayer, scaleParameters); + aContainerFrame, aContainerItem, + containerLayer, scaleParameters); Clip clip; state.ProcessDisplayItems(aChildren, clip, stateFlags); diff --git a/layout/base/FrameLayerBuilder.h b/layout/base/FrameLayerBuilder.h index 5d39d1fd61b2..a1204b9e961a 100644 --- a/layout/base/FrameLayerBuilder.h +++ b/layout/base/FrameLayerBuilder.h @@ -64,9 +64,7 @@ public: * The most important API in this class is BuildContainerLayerFor. This * method takes a display list as input and constructs a ContainerLayer * with child layers that render the contents of the display list. It - * also updates userdata for the retained layer manager, and - * DisplayItemDataProperty data for frames, to record the relationship - * between frames and layers. + * records the relationship between frames and layers. * * That data enables us to retain layer trees. When constructing a * ContainerLayer, we first check to see if there's an existing @@ -85,7 +83,7 @@ public: * FrameLayerBuilder sets up ThebesLayers so that 0,0 in the Thebes layer * corresponds to the (pixel-snapped) top-left of the aActiveScrolledRoot. * It sets up ContainerLayers so that 0,0 in the container layer - * corresponds to the snapped top-left of the display list reference frame. + * corresponds to the snapped top-left of the display item reference frame. * * When we construct a container layer, we know the transform that will be * applied to the layer. If the transform scales the content, we can get @@ -266,6 +264,7 @@ public: * @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 aTopLeft offset from active scrolled root to reference frame * @param aManager If the layer is in the LAYER_INACTIVE state, * then this is the temporary layer manager to draw with. */ @@ -282,6 +281,7 @@ public: * aLayer, with aClipRect, where aContainerLayerFrame is the frame * for the container layer this ThebesItem belongs to. * aItem must have an underlying frame. + * @param aTopLeft offset from active scrolled root to reference frame */ void AddThebesDisplayItem(ThebesLayer* aLayer, nsDisplayItem* aItem, @@ -574,8 +574,9 @@ protected: /** * We accumulate DisplayItemData elements in a hashtable during - * the paint process, and store them in the frame property only when - * paint is complete. This is the hashentry for that hashtable. + * the paint process, one per visible display item. + * There is one hashtable per layer manager, and one entry + * per frame. This is the hashentry for that hashtable. */ class DisplayItemDataEntry : public nsPtrHashKey { public: @@ -640,8 +641,7 @@ protected: /** * A useful hashtable iteration function that removes the - * DisplayItemData property for the frame, clears its - * NS_FRAME_HAS_CONTAINER_LAYER bit and returns PL_DHASH_REMOVE. + * DisplayItemData property for the frame and returns PL_DHASH_REMOVE. * aClosure is ignored. */ static PLDHashOperator RemoveDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,