From 885567bc0f8f52ad6d04aa41481253980d82e881 Mon Sep 17 00:00:00 2001 From: Benjamin Stover Date: Sat, 9 Apr 2011 12:38:28 -0700 Subject: [PATCH] Bug 642246 Don't build ThebesLayers for elements with no displayports r=roc --- gfx/layers/Layers.h | 8 ++++++ layout/base/FrameLayerBuilder.h | 4 ++- layout/base/nsDisplayItemTypes.h | 1 + layout/base/nsDisplayList.cpp | 19 +++++++++++++ layout/base/nsDisplayList.h | 24 ++++++++++++++++ layout/generic/nsGfxScrollFrame.cpp | 43 +++++++++++++++++++---------- layout/ipc/RenderFrameParent.cpp | 14 +++------- 7 files changed, 87 insertions(+), 26 deletions(-) diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index ef01d4950f5..09d1dddb0ef 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -762,6 +762,12 @@ public: */ virtual ThebesLayer* AsThebesLayer() { return nsnull; } + /** + * Dynamic cast to a ContainerLayer. Returns null if this is not + * a ContainerLayer. + */ + virtual ContainerLayer* AsContainerLayer() { return nsnull; } + /** * Dynamic cast to a ShadowLayer. Return null if this is not a * ShadowLayer. Can be used anytime. @@ -1029,6 +1035,8 @@ public: // These getters can be used anytime. + virtual ContainerLayer* AsContainerLayer() { return this; } + virtual Layer* GetFirstChild() { return mFirstChild; } virtual Layer* GetLastChild() { return mLastChild; } const FrameMetrics& GetFrameMetrics() { return mFrameMetrics; } diff --git a/layout/base/FrameLayerBuilder.h b/layout/base/FrameLayerBuilder.h index 0256195827e..898c1cd2746 100644 --- a/layout/base/FrameLayerBuilder.h +++ b/layout/base/FrameLayerBuilder.h @@ -59,7 +59,9 @@ enum LayerState { LAYER_ACTIVE, // Force an active layer even if it causes incorrect rendering, e.g. // when the layer has rounded rect clips. - LAYER_ACTIVE_FORCE + LAYER_ACTIVE_FORCE, + // Special layer that is metadata only. + LAYER_ACTIVE_EMPTY }; /** diff --git a/layout/base/nsDisplayItemTypes.h b/layout/base/nsDisplayItemTypes.h index ee1406b2d53..1acdb21e134 100644 --- a/layout/base/nsDisplayItemTypes.h +++ b/layout/base/nsDisplayItemTypes.h @@ -84,6 +84,7 @@ enum Type { TYPE_REMOTE, TYPE_REMOTE_SHADOW, TYPE_SCROLL_LAYER, + TYPE_SCROLL_INFO_LAYER, TYPE_SELECTION_OVERLAY, TYPE_SOLID_COLOR, TYPE_TABLE_CELL_BACKGROUND, diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 1559870c6fb..ee439287d0c 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1836,6 +1836,25 @@ nsDisplayScrollLayer::~nsDisplayScrollLayer() } #endif +nsDisplayScrollInfoLayer::nsDisplayScrollInfoLayer( + nsDisplayListBuilder* aBuilder, + nsDisplayList* aList, + nsIFrame* aForFrame, + nsIFrame* aViewportFrame) + : nsDisplayScrollLayer(aBuilder, aList, aForFrame, aViewportFrame) +{ +#ifdef NS_BUILD_REFCNT_LOGGING + MOZ_COUNT_CTOR(nsDisplayScrollInfoLayer); +#endif +} + +#ifdef NS_BUILD_REFCNT_LOGGING +nsDisplayScrollInfoLayer::~nsDisplayScrollInfoLayer() +{ + MOZ_COUNT_DTOR(nsDisplayScrollInfoLayer); +} +#endif + nsDisplayClip::nsDisplayClip(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayItem* aItem, const nsRect& aRect) diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index cf8a72c1cc4..82b8cb85420 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -1836,6 +1836,30 @@ private: nsIFrame* mViewportFrame; }; +/** + * Like nsDisplayScrollLayer, but only has metadata on the scroll frame. This + * creates a layer that has no Thebes child layer, but still allows the + * compositor process to know of the scroll frame's existence. + */ +class nsDisplayScrollInfoLayer : public nsDisplayScrollLayer +{ +public: + nsDisplayScrollInfoLayer(nsDisplayListBuilder* aBuilder, nsDisplayList* aList, + nsIFrame* aForFrame, nsIFrame* aViewportFrame); + NS_DISPLAY_DECL_NAME("ScrollInfoLayer", TYPE_SCROLL_INFO_LAYER) + +#ifdef NS_BUILD_REFCNT_LOGGING + virtual ~nsDisplayScrollInfoLayer(); +#endif + + virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, + LayerManager* aManager) + { + return mozilla::LAYER_ACTIVE_EMPTY; + } + +}; + /** * nsDisplayClip can clip a list of items, but we take a single item * initially and then later merge other items into it when we merge diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 120cac4e34b..fa4dd392d6b 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1961,7 +1961,8 @@ nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder, dirtyRect.IntersectRect(aDirtyRect, mScrollPort); // Override the dirty rectangle if the displayport has been set. - nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &dirtyRect); + PRBool usingDisplayport = + nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &dirtyRect); nsDisplayListCollection set; @@ -1976,30 +1977,42 @@ nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder, // range of 20 pixels to eliminate many gfx scroll frames from becoming a // layer. // - PRInt32 appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); nsRect scrollRange = GetScrollRange(); ScrollbarStyles styles = GetScrollbarStylesFromFrame(); mShouldBuildLayer = (XRE_GetProcessType() == GeckoProcessType_Content && (styles.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN || styles.mVertical != NS_STYLE_OVERFLOW_HIDDEN) && - (scrollRange.width >= NSIntPixelsToAppUnits(20, appUnitsPerDevPixel) || - scrollRange.height >= NSIntPixelsToAppUnits(20, appUnitsPerDevPixel))) && - (!mIsRoot || !mOuter->PresContext()->IsRootContentDocument()); + (!mIsRoot || !mOuter->PresContext()->IsRootContentDocument())); if (ShouldBuildLayer()) { - // Note that using StackingContext breaks z order, so the resulting - // rendering can be incorrect for weird edge cases! - nsDisplayList list; - rv = mScrolledFrame->BuildDisplayListForStackingContext( - aBuilder, dirtyRect + mOuter->GetOffsetTo(mScrolledFrame), &list); + if (usingDisplayport) { + // Once a displayport is set, assume that scrolling needs to be fast + // so create a layer with all the content inside. The compositor + // process will be able to scroll the content asynchronously. + // + // Note that using StackingContext breaks z order, so the resulting + // rendering can be incorrect for weird edge cases! - nsDisplayScrollLayer* layerItem = new (aBuilder) nsDisplayScrollLayer( - aBuilder, &list, mScrolledFrame, mOuter); - set.Content()->AppendNewToTop(layerItem); - } else - { + rv = mScrolledFrame->BuildDisplayListForStackingContext( + aBuilder, dirtyRect + mOuter->GetOffsetTo(mScrolledFrame), &list); + + nsDisplayScrollLayer* layerItem = new (aBuilder) nsDisplayScrollLayer( + aBuilder, &list, mScrolledFrame, mOuter); + set.Content()->AppendNewToTop(layerItem); + } else { + // If there is no displayport set, there is no reason here to force a + // layer that needs a memory-expensive allocation, but the compositor + // process would still like to know that it exists. + + nsDisplayScrollLayer* layerItem = new (aBuilder) nsDisplayScrollInfoLayer( + aBuilder, &list, mScrolledFrame, mOuter); + set.Content()->AppendNewToTop(layerItem); + + rv = mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, set); + } + } else { rv = mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, set); } diff --git a/layout/ipc/RenderFrameParent.cpp b/layout/ipc/RenderFrameParent.cpp index 8054ab29eb0..3586aa7d231 100644 --- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -139,13 +139,8 @@ FindViewForId(const ViewMap& aMap, ViewID aId) static const FrameMetrics* GetFrameMetrics(Layer* aLayer) { - // Children are not container layers, so they don't have frame metrics. Give - // them a blank metric. - if (!aLayer->GetFirstChild()) - return NULL; - - ContainerLayer* container = static_cast(aLayer); - return &container->GetFrameMetrics(); + ContainerLayer* container = aLayer->AsContainerLayer(); + return container ? &container->GetFrameMetrics() : NULL; } static nsIntPoint @@ -346,10 +341,9 @@ BuildViewMap(ViewMap& oldContentViews, ViewMap& newContentViews, nsFrameLoader* aFrameLoader, Layer* aLayer, float aXScale = 1, float aYScale = 1) { - if (!aLayer->GetFirstChild()) + ContainerLayer* container = aLayer->AsContainerLayer(); + if (!container) return; - - ContainerLayer* container = static_cast(aLayer); const FrameMetrics metrics = container->GetFrameMetrics(); const ViewID scrollId = metrics.mScrollId;