author | Kartikaya Gupta <kgupta@mozilla.com> |
Tue, 20 Jan 2015 09:49:30 -0500 | |
changeset 224719 | 9302dbf3d84b768d7a3099c2c9a9a3b9e146a0dc |
parent 224718 | 37a5836d9779690e705c12bbe65bfdba16c15ee3 |
child 224720 | 5c93233e6aeb406ae6c9a9816b1d22f7431cdb3b |
push id | 28143 |
push user | ryanvm@gmail.com |
push date | Wed, 21 Jan 2015 03:14:12 +0000 |
treeherder | mozilla-central@540077a30866 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | tnikkel, mattwoodrow |
bugs | 1119942 |
milestone | 38.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -287,16 +287,20 @@ APZCTreeManager::AttachNodeToTree(HitTes aNode->MakeRoot(); } } static EventRegions GetEventRegions(const LayerMetricsWrapper& aLayer) { if (gfxPrefs::LayoutEventRegionsEnabled()) { + if (aLayer.IsScrollInfoLayer()) { + return EventRegions(nsIntRegion(ParentLayerIntRect::ToUntyped( + RoundedToInt(aLayer.Metrics().mCompositionBounds)))); + } return aLayer.GetEventRegions(); } return EventRegions(aLayer.GetVisibleRegion()); } already_AddRefed<HitTestingTreeNode> APZCTreeManager::RecycleOrCreateNode(TreeBuildingState& aState, AsyncPanZoomController* aApzc)
--- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -638,16 +638,21 @@ public: // When AllowResidualTranslation is false, display items will be drawn // scaled with a translation by integer pixels, so we know how the snapping // will work. mSnappingEnabled = aManager->IsSnappingEffectiveTransforms() && !mParameters.AllowResidualTranslation(); CollectOldLayers(); } + ~ContainerState() + { + MOZ_ASSERT(mHoistedItems.IsEmpty()); + } + /** * This is the method that actually walks a display list and builds * the child layers. */ void ProcessDisplayItems(nsDisplayList* aList); /** * This finalizes all the open PaintedLayers by popping every element off * mPaintedLayerDataStack, then sets the children of the container layer @@ -714,16 +719,21 @@ public: * is in the coordinate space of the container reference frame. * aLayerContentsVisibleRect, if non-null, is in the layer's own * coordinate system. */ void SetOuterVisibleRegionForLayer(Layer* aLayer, const nsIntRegion& aOuterVisibleRegion, const nsIntRect* aLayerContentsVisibleRect = nullptr) const; + void AddHoistedItem(nsDisplayItem* aItem) + { + mHoistedItems.AppendToTop(aItem); + } + protected: friend class PaintedLayerData; /** * Grab the next recyclable PaintedLayer, or create one if there are no * more recyclable PaintedLayers. Does any necessary invalidation of * a recycled PaintedLayer, and sets up the transform on the PaintedLayer * to account for scrolling. @@ -920,16 +930,21 @@ protected: AutoLayersArray mNewChildLayers; nsTArray<nsRefPtr<PaintedLayer> > mRecycledPaintedLayers; nsDataHashtable<nsPtrHashKey<Layer>, nsRefPtr<ImageLayer> > mRecycledMaskImageLayers; uint32_t mNextFreeRecycledPaintedLayer; nscoord mAppUnitsPerDevPixel; bool mSnappingEnabled; bool mFlattenToSingleLayer; + /** + * In some cases we need to hoist nsDisplayScrollInfoLayer items out from a + * nested inactive container. This holds the items hoisted up from children. + */ + nsDisplayList mHoistedItems; }; class PaintedDisplayItemLayerUserData : public LayerUserData { public: PaintedDisplayItemLayerUserData() : mMaskClipCount(0), mForcedBackgroundColor(NS_RGBA(0,0,0,0)), @@ -1088,24 +1103,25 @@ FrameLayerBuilder::Shutdown() if (gMaskLayerImageCache) { delete gMaskLayerImageCache; gMaskLayerImageCache = nullptr; } } void FrameLayerBuilder::Init(nsDisplayListBuilder* aBuilder, LayerManager* aManager, - PaintedLayerData* aLayerData) + PaintedLayerData* aLayerData, ContainerState* aContainingContainerState) { mDisplayListBuilder = aBuilder; mRootPresContext = aBuilder->RootReferenceFrame()->PresContext()->GetRootPresContext(); if (mRootPresContext) { mInitialDOMGeneration = mRootPresContext->GetDOMGeneration(); } mContainingPaintedLayer = aLayerData; + mContainingContainerState = aContainingContainerState; aManager->SetUserData(&gLayerManagerLayerBuilder, this); } void FrameLayerBuilder::FlashPaint(gfxContext *aContext) { float r = float(rand()) / RAND_MAX; float g = float(rand()) / RAND_MAX; @@ -2862,31 +2878,44 @@ ContainerState::ProcessDisplayItems(nsDi nsDisplayList* itemSameCoordinateSystemChildren = item->GetSameCoordinateSystemChildren(); if (item->ShouldFlattenAway(mBuilder)) { aList->AppendToBottom(itemSameCoordinateSystemChildren); item->~nsDisplayItem(); continue; } + nsDisplayItem::Type itemType = item->GetType(); + if (itemType == nsDisplayItem::TYPE_SCROLL_INFO_LAYER && + mLayerBuilder->GetContainingContainerState()) { + // We have encountered a scrollable area inside a nested (inactive) + // layer manager, so we need to hoist the item out into the parent; that + // way we will still generate a scrollinfo layer for it and the APZ can + // drive main-thread sync scrolling. + // Note: |item| is removed from aList and will be attached into the parent + // list, so we don't delete it here. + static_cast<nsDisplayScrollInfoLayer*>(item)->MarkHoisted(); + mLayerBuilder->GetContainingContainerState()->AddHoistedItem(item); + continue; + } + savedItems.AppendToTop(item); NS_ASSERTION(mAppUnitsPerDevPixel == AppUnitsPerDevPixel(item), "items in a container layer should all have the same app units per dev pixel"); if (mBuilder->NeedToForceTransparentSurfaceForItem(item)) { aList->SetNeedsTransparentSurface(); } nsIntRect itemVisibleRect = ScaleToOutsidePixels(item->GetVisibleRect(), false); bool snap; nsRect itemContent = item->GetBounds(mBuilder, &snap); nsIntRect itemDrawRect = ScaleToOutsidePixels(itemContent, snap); - nsDisplayItem::Type itemType = item->GetType(); bool prerenderedTransform = itemType == nsDisplayItem::TYPE_TRANSFORM && static_cast<nsDisplayTransform*>(item)->ShouldPrerender(mBuilder); nsIntRect clipRect; const DisplayItemClip& itemClip = item->GetClip(); if (itemClip.HasClip()) { itemContent.IntersectRect(itemContent, itemClip.GetClipRect()); clipRect = ScaleToNearestPixels(itemClip.GetClipRect()); if (!prerenderedTransform) { @@ -3127,23 +3156,28 @@ ContainerState::ProcessDisplayItems(nsDi itemClip, aList, &paintedLayerData->mHideAllLayersBelow, &paintedLayerData->mOpaqueForAnimatedGeometryRootParent); paintedLayerData->Accumulate(this, item, opaquePixels, itemVisibleRect, itemDrawRect, itemClip); } } + // Finish the hoisting process by taking the items from the child and adding + // them to the list here. + aList->AppendToBottom(&mHoistedItems); + if (itemSameCoordinateSystemChildren && itemSameCoordinateSystemChildren->NeedsTransparentSurface()) { aList->SetNeedsTransparentSurface(); } } aList->AppendToTop(&savedItems); + MOZ_ASSERT(mHoistedItems.IsEmpty()); } void ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, PaintedLayer* aNewLayer) { NS_ASSERTION(aItem->GetPerFrameKey(), "Display items that render using Thebes must have a key"); nsDisplayItemGeometry* oldGeometry = nullptr; @@ -3278,17 +3312,17 @@ FrameLayerBuilder::ComputeGeometryChange aData->EndUpdate(geometry); } void FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, nsDisplayItem* aItem, const DisplayItemClip& aClip, const nsIntRect& aItemVisibleRect, - const ContainerState& aContainerState, + ContainerState& aContainerState, LayerState aLayerState, const nsPoint& aTopLeft) { PaintedLayer* layer = aLayerData->mLayer; PaintedDisplayItemLayerUserData* paintedData = static_cast<PaintedDisplayItemLayerUserData*> (layer->GetUserData(&gPaintedDisplayItemLayerUserData)); nsRefPtr<BasicLayerManager> tempManager; @@ -3324,17 +3358,17 @@ FrameLayerBuilder::AddPaintedDisplayItem if (entry) { entry->mContainerLayerFrame = aContainerState.GetContainerFrame(); if (entry->mContainerLayerGeneration == 0) { entry->mContainerLayerGeneration = mContainerLayerGeneration; } if (tempManager) { FLB_LOG_PAINTED_LAYER_DECISION(aLayerData, "Creating nested FLB for item %p\n", aItem); FrameLayerBuilder* layerBuilder = new FrameLayerBuilder(); - layerBuilder->Init(mDisplayListBuilder, tempManager, aLayerData); + layerBuilder->Init(mDisplayListBuilder, tempManager, aLayerData, &aContainerState); tempManager->BeginTransaction(); if (mRetainingManager) { layerBuilder->DidBeginRetainedLayerTransaction(tempManager); } UniquePtr<LayerProperties> props(LayerProperties::CloneFrom(tempManager->GetRoot())); nsRefPtr<Layer> tmpLayer =
--- a/layout/base/FrameLayerBuilder.h +++ b/layout/base/FrameLayerBuilder.h @@ -172,17 +172,18 @@ public: ~FrameLayerBuilder() { MOZ_COUNT_DTOR(FrameLayerBuilder); } static void Shutdown(); void Init(nsDisplayListBuilder* aBuilder, LayerManager* aManager, - PaintedLayerData* aLayerData = nullptr); + PaintedLayerData* aLayerData = nullptr, + ContainerState* aContainingContainerState = nullptr); /** * Call this to notify that we have just started a transaction on the * retained layer manager aManager. */ void DidBeginRetainedLayerTransaction(LayerManager* aManager); /** @@ -301,17 +302,17 @@ public: * 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 AddPaintedDisplayItem(PaintedLayerData* aLayer, nsDisplayItem* aItem, const DisplayItemClip& aClip, const nsIntRect& aItemVisibleRect, - const ContainerState& aContainerState, + ContainerState& aContainerState, LayerState aLayerState, const nsPoint& aTopLeft); /** * Gets the frame property descriptor for the given manager, or for the current * widget layer manager if nullptr is passed. */ static const FramePropertyDescriptor* GetDescriptorForManager(LayerManager* aManager); @@ -631,16 +632,21 @@ public: return mContainingPaintedLayer; } bool IsBuildingRetainedLayers() { return !mContainingPaintedLayer && mRetainingManager; } + ContainerState* GetContainingContainerState() + { + return mContainingContainerState; + } + /** * Attempt to build the most compressed layer tree possible, even if it means * throwing away existing retained buffers. */ void SetLayerTreeCompressionMode() { mInLayerTreeCompressionMode = true; } bool CheckInLayerTreeCompressionMode(); void ComputeGeometryChangeForItem(DisplayItemData* aData); @@ -684,17 +690,19 @@ protected: * clipping data) to be rendered in the layer. */ nsTHashtable<PaintedLayerItemsEntry> mPaintedLayerItems; /** * When building layers for an inactive layer, this is where the * inactive layer will be placed. */ - PaintedLayerData* mContainingPaintedLayer; + PaintedLayerData* mContainingPaintedLayer; + + ContainerState* mContainingContainerState; /** * Saved generation counter so we can detect DOM changes. */ uint32_t mInitialDOMGeneration; /** * Set to true if we have detected and reported DOM modification during * the current paint.
--- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -4597,16 +4597,17 @@ nsDisplayScrollLayer::WriteDebugInfo(std << " scrolledFrame " << mScrolledFrame << ")"; } nsDisplayScrollInfoLayer::nsDisplayScrollInfoLayer( nsDisplayListBuilder* aBuilder, nsIFrame* aScrolledFrame, nsIFrame* aScrollFrame) : nsDisplayScrollLayer(aBuilder, aScrollFrame, aScrolledFrame, aScrollFrame) + , mHoisted(false) { #ifdef NS_BUILD_REFCNT_LOGGING MOZ_COUNT_CTOR(nsDisplayScrollInfoLayer); #endif } nsDisplayScrollInfoLayer::~nsDisplayScrollInfoLayer() { @@ -4621,31 +4622,34 @@ nsDisplayScrollInfoLayer::GetBounds(nsDi already_AddRefed<Layer> nsDisplayScrollInfoLayer::BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager, const ContainerLayerParameters& aContainerParameters) { // Only build scrollinfo layers if event-regions are disabled, so that the // compositor knows where the inactive scrollframes are. When event-regions - // are enabled, the dispatch-to-content regions provide this information to - // the APZ code. - if (gfxPrefs::LayoutEventRegionsEnabled()) { + // are enabled, the dispatch-to-content regions generally provide this + // information to the APZ code. However, in some cases, there might be + // content that cannot be layerized, and so needs to scroll synchronously. + // To handle those cases (which are indicated by setting mHoisted to true), we + // still want to generate scrollinfo layers. + if (gfxPrefs::LayoutEventRegionsEnabled() && !mHoisted) { return nullptr; } return nsDisplayScrollLayer::BuildLayer(aBuilder, aManager, aContainerParameters); } LayerState nsDisplayScrollInfoLayer::GetLayerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager, const ContainerLayerParameters& aParameters) { // See comment in BuildLayer - if (gfxPrefs::LayoutEventRegionsEnabled()) { + if (gfxPrefs::LayoutEventRegionsEnabled() && !mHoisted) { return LAYER_NONE; } return LAYER_ACTIVE_EMPTY; } bool nsDisplayScrollInfoLayer::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem)
--- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -3218,16 +3218,21 @@ public: LayerManager* aManager, const ContainerLayerParameters& aParameters) MOZ_OVERRIDE; virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE { return true; } virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE; virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; + + void MarkHoisted() { mHoisted = true; } + +private: + bool mHoisted; }; /** * nsDisplayZoom is used for subdocuments that have a different full zoom than * their parent documents. This item creates a container layer. */ class nsDisplayZoom : public nsDisplaySubDocument { public: