Bug 642246 Don't build ThebesLayers for elements with no displayports r=roc

This commit is contained in:
Benjamin Stover 2011-04-11 13:53:01 -07:00
parent 60e6f52fc8
commit bd3081c90a
7 changed files with 87 additions and 26 deletions

View File

@ -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; }

View File

@ -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
};
/**

View File

@ -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,

View File

@ -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)

View File

@ -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

View File

@ -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);
}

View File

@ -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<ContainerLayer*>(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<ContainerLayer*>(aLayer);
const FrameMetrics metrics = container->GetFrameMetrics();
const ViewID scrollId = metrics.mScrollId;