mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Bug 1022612. Part 31: Perform layer-level occlusion culling in FrameLayerBuilder. r=mattwoodrow
We need this to avoid constructing and painting unncecessarily large ThebesLayers. --HG-- extra : rebase_source : 38cbd0b0dd7724cfdb98f3e215bd0f220a687f3c
This commit is contained in:
parent
9a2fe1598a
commit
d43195c660
@ -37,8 +37,6 @@ using namespace mozilla::gfx;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ContainerState;
|
||||
|
||||
FrameLayerBuilder::DisplayItemData::DisplayItemData(LayerManagerData* aParent, uint32_t aKey,
|
||||
Layer* aLayer, LayerState aLayerState, uint32_t aGeneration)
|
||||
|
||||
@ -244,8 +242,10 @@ public:
|
||||
mSingleItemFixedToViewport(false),
|
||||
mNeedComponentAlpha(false),
|
||||
mForceTransparentSurface(false),
|
||||
mHideAllLayersBelow(false),
|
||||
mImage(nullptr),
|
||||
mCommonClipCount(-1),
|
||||
mNewChildLayersIndex(-1),
|
||||
mAllDrawingAbove(false)
|
||||
{}
|
||||
/**
|
||||
@ -424,6 +424,10 @@ public:
|
||||
* part of its surface.
|
||||
*/
|
||||
bool mForceTransparentSurface;
|
||||
/**
|
||||
* Set if all layers below this ThebesLayer should be hidden.
|
||||
*/
|
||||
bool mHideAllLayersBelow;
|
||||
|
||||
/**
|
||||
* Stores the pointer to the nsDisplayImage if we want to
|
||||
@ -446,6 +450,10 @@ public:
|
||||
* data is popped from the stack.
|
||||
*/
|
||||
int32_t mCommonClipCount;
|
||||
/**
|
||||
* Index of this layer in mNewChildLayers.
|
||||
*/
|
||||
int32_t mNewChildLayersIndex;
|
||||
/*
|
||||
* Updates mCommonClipCount by checking for rounded rect clips in common
|
||||
* between the clip on a new item (aCurrentClip) and the common clips
|
||||
@ -479,6 +487,39 @@ private:
|
||||
bool mAllDrawingAbove;
|
||||
};
|
||||
|
||||
struct NewLayerEntry {
|
||||
NewLayerEntry()
|
||||
: mAnimatedGeometryRoot(nullptr)
|
||||
, mFixedPosFrameForLayerData(nullptr)
|
||||
, mLayerContentsVisibleRect(0, 0, -1, -1)
|
||||
, mHideAllLayersBelow(false)
|
||||
, mOpaqueForAnimatedGeometryRootParent(false)
|
||||
{}
|
||||
// mLayer is null if the previous entry is for a ThebesLayer that hasn't
|
||||
// been optimized to some other form (yet).
|
||||
nsRefPtr<Layer> mLayer;
|
||||
const nsIFrame* mAnimatedGeometryRoot;
|
||||
const nsIFrame* mFixedPosFrameForLayerData;
|
||||
// The following are only used for retained layers (for occlusion
|
||||
// culling of those layers). These regions are all relative to the
|
||||
// container reference frame.
|
||||
nsIntRegion mVisibleRegion;
|
||||
nsIntRegion mOpaqueRegion;
|
||||
// This rect is in the layer's own coordinate space. The computed visible
|
||||
// region for the layer cannot extend beyond this rect.
|
||||
nsIntRect mLayerContentsVisibleRect;
|
||||
bool mHideAllLayersBelow;
|
||||
// When mOpaqueForAnimatedGeometryRootParent is true, the opaque region of
|
||||
// this layer is opaque in the same position even subject to the animation of
|
||||
// geometry of mAnimatedGeometryRoot. For example when mAnimatedGeometryRoot
|
||||
// is a scrolled frame and the scrolled content is opaque everywhere in the
|
||||
// displayport, we can set this flag.
|
||||
// When this flag is set, we can treat this opaque region as covering
|
||||
// content whose animated geometry root is the animated geometry root for
|
||||
// mAnimatedGeometryRoot->GetParent().
|
||||
bool mOpaqueForAnimatedGeometryRootParent;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a helper object used to build up the layer children for
|
||||
* a ContainerLayer.
|
||||
@ -509,6 +550,10 @@ public:
|
||||
mContainerAnimatedGeometryRoot = aContainerItem
|
||||
? nsLayoutUtils::GetAnimatedGeometryRootFor(aContainerItem, aBuilder)
|
||||
: mContainerReferenceFrame;
|
||||
NS_ASSERTION(!aContainerItem || !aContainerItem->ShouldFixToViewport(aBuilder),
|
||||
"Container items never return true for ShouldFixToViewport");
|
||||
mContainerFixedPosFrame =
|
||||
FindFixedPosFrameForLayerData(mContainerAnimatedGeometryRoot, false);
|
||||
// When AllowResidualTranslation is false, display items will be drawn
|
||||
// scaled with a translation by integer pixels, so we know how the snapping
|
||||
// will work.
|
||||
@ -534,7 +579,9 @@ public:
|
||||
* @param aTextContentFlags if any child layer has CONTENT_COMPONENT_ALPHA,
|
||||
* set *aTextContentFlags to CONTENT_COMPONENT_ALPHA
|
||||
*/
|
||||
void Finish(uint32_t *aTextContentFlags, LayerManagerData* aData);
|
||||
void Finish(uint32_t *aTextContentFlags, LayerManagerData* aData,
|
||||
const nsIntRect& aContainerPixelBounds,
|
||||
nsDisplayList* aChildItems);
|
||||
|
||||
nscoord GetAppUnitsPerDevPixel() { return mAppUnitsPerDevPixel; }
|
||||
|
||||
@ -583,6 +630,18 @@ public:
|
||||
mAppUnitsPerDevPixel);
|
||||
}
|
||||
|
||||
nsIFrame* GetContainerFrame() const { return mContainerFrame; }
|
||||
|
||||
/**
|
||||
* Sets aOuterVisibleRegion as aLayer's visible region. aOuterVisibleRegion
|
||||
* 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;
|
||||
|
||||
protected:
|
||||
friend class ThebesLayerData;
|
||||
|
||||
@ -655,6 +714,36 @@ protected:
|
||||
*/
|
||||
void SetFixedPositionLayerData(Layer* aLayer,
|
||||
const nsIFrame* aFixedPosFrame);
|
||||
|
||||
/**
|
||||
* Returns true if aItem's opaque area (in aOpaque) covers the entire
|
||||
* scrollable area of its presshell.
|
||||
*/
|
||||
bool ItemCoversScrollableArea(nsDisplayItem* aItem, const nsRegion& aOpaque);
|
||||
|
||||
/**
|
||||
* For each layer in mNewChildLayers, remove from its visible region the
|
||||
* opaque regions of the layers at higher z-index, but only if they have
|
||||
* the same animated geometry root and fixed-pos frame ancestor.
|
||||
* The opaque region for the child layers that share the same animated
|
||||
* geometry root as the container frame is returned in
|
||||
* *aOpaqueRegionForContainer.
|
||||
*/
|
||||
void ApplyOcclusionCulling(nsIntRegion* aOpaqueRegionForContainer);
|
||||
|
||||
/**
|
||||
* Computes the snapped opaque area of aItem. Sets aList's opaque flag
|
||||
* if it covers the entire list bounds. Sets *aHideAllLayersBelow to true
|
||||
* this item covers the entire viewport so that all layers below are
|
||||
* permanently invisible.
|
||||
*/
|
||||
nsIntRegion ComputeOpaqueRect(nsDisplayItem* aItem,
|
||||
const nsIFrame* aAnimatedGeometryRoot,
|
||||
const nsIFrame* aFixedPosFrame,
|
||||
const DisplayItemClip& aClip,
|
||||
nsDisplayList* aList,
|
||||
bool* aHideAllLayersBelow);
|
||||
|
||||
/**
|
||||
* Indicate that we are done adding items to the ThebesLayer at the top of
|
||||
* mThebesLayerDataStack. Set the final visible region and opaque-content
|
||||
@ -697,11 +786,14 @@ protected:
|
||||
* Builds an ImageLayer for the appropriate backend; the mask is relative to
|
||||
* aLayer's visible region.
|
||||
* aLayer is the layer to be clipped.
|
||||
* aLayerVisibleRegion is the region that will be set as aLayer's visible region,
|
||||
* relative to the container reference frame
|
||||
* aRoundedRectClipCount is used when building mask layers for ThebesLayers,
|
||||
* SetupMaskLayer will build a mask layer for only the first
|
||||
* aRoundedRectClipCount rounded rects in aClip
|
||||
*/
|
||||
void SetupMaskLayer(Layer *aLayer, const DisplayItemClip& aClip,
|
||||
const nsIntRegion& aLayerVisibleRegion,
|
||||
uint32_t aRoundedRectClipCount = UINT32_MAX);
|
||||
|
||||
bool ChooseAnimatedGeometryRoot(const nsDisplayList& aList,
|
||||
@ -713,6 +805,7 @@ protected:
|
||||
nsIFrame* mContainerFrame;
|
||||
nsIFrame* mContainerReferenceFrame;
|
||||
const nsIFrame* mContainerAnimatedGeometryRoot;
|
||||
const nsIFrame* mContainerFixedPosFrame;
|
||||
ContainerLayer* mContainerLayer;
|
||||
nsRect mContainerBounds;
|
||||
DebugOnly<nsRect> mAccumulatedChildBounds;
|
||||
@ -727,8 +820,12 @@ protected:
|
||||
* We collect the list of children in here. During ProcessDisplayItems,
|
||||
* the layers in this array either have mContainerLayer as their parent,
|
||||
* or no parent.
|
||||
* ThebesLayers have two entries in this array: the second one is used only if
|
||||
* the ThebesLayer is optimized away to a ColorLayer or ImageLayer.
|
||||
* It's essential that this array is only appended to, since ThebesLayerData
|
||||
* records the index of its ThebesLayer in this array.
|
||||
*/
|
||||
typedef nsAutoTArray<nsRefPtr<Layer>,1> AutoLayersArray;
|
||||
typedef nsAutoTArray<NewLayerEntry,1> AutoLayersArray;
|
||||
AutoLayersArray mNewChildLayers;
|
||||
nsTArray<nsRefPtr<ThebesLayer> > mRecycledThebesLayers;
|
||||
nsDataHashtable<nsPtrHashKey<Layer>, nsRefPtr<ImageLayer> >
|
||||
@ -1604,38 +1701,49 @@ AppUnitsPerDevPixel(nsDisplayItem* aItem)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Restrict the visible region of aLayer to the region that is actually visible.
|
||||
* Because we only reduce the visible region here, we don't need to worry
|
||||
* about whether CONTENT_OPAQUE is set; if layer was opaque in the old
|
||||
* visible region, it will still be opaque in the new one.
|
||||
* @param aLayerVisibleRect if non-null, the visible rect of the layer, in
|
||||
* the layer's coordinate space
|
||||
* @param aOuterVisibleRect the rect to restrict the visible region to, in the
|
||||
* parent's coordinate system
|
||||
* Set the visible region for aLayer.
|
||||
* aOuterVisibleRegion is the visible region relative to the parent layer.
|
||||
* Consumes *aOuterVisibleRegion.
|
||||
*/
|
||||
static void
|
||||
SetVisibleRegionForLayer(Layer* aLayer, const nsIntRect* aLayerVisibleRect,
|
||||
const nsIntRect& aOuterVisibleRect)
|
||||
SetOuterVisibleRegion(Layer* aLayer, nsIntRegion* aOuterVisibleRegion,
|
||||
const nsIntRect* aLayerContentsVisibleRect = nullptr)
|
||||
{
|
||||
gfx3DMatrix transform;
|
||||
To3DMatrix(aLayer->GetTransform(), transform);
|
||||
|
||||
// if 'transform' is not invertible, then nothing will be displayed
|
||||
// for the layer, so it doesn't really matter what we do here
|
||||
gfxRect outerVisible(aOuterVisibleRect.x, aOuterVisibleRect.y,
|
||||
aOuterVisibleRect.width, aOuterVisibleRect.height);
|
||||
gfxRect layerVisible = transform.Inverse().ProjectRectBounds(outerVisible);
|
||||
layerVisible.RoundOut();
|
||||
|
||||
nsIntRect visibleRect;
|
||||
if (!gfxUtils::GfxRectToIntRect(layerVisible, &visibleRect)) {
|
||||
aLayer->SetVisibleRegion(nsIntRegion());
|
||||
gfxMatrix transform2D;
|
||||
if (transform.Is2D(&transform2D) && !transform2D.HasNonIntegerTranslation()) {
|
||||
aOuterVisibleRegion->MoveBy(-int(transform2D._31), -int(transform2D._32));
|
||||
} else {
|
||||
if (aLayerVisibleRect) {
|
||||
visibleRect.IntersectRect(visibleRect, *aLayerVisibleRect);
|
||||
nsIntRect outerRect = aOuterVisibleRegion->GetBounds();
|
||||
// if 'transform' is not invertible, then nothing will be displayed
|
||||
// for the layer, so it doesn't really matter what we do here
|
||||
gfxRect outerVisible(outerRect.x, outerRect.y, outerRect.width, outerRect.height);
|
||||
gfxRect layerVisible = transform.Inverse().ProjectRectBounds(outerVisible);
|
||||
layerVisible.RoundOut();
|
||||
nsIntRect visRect;
|
||||
if (gfxUtils::GfxRectToIntRect(layerVisible, &visRect)) {
|
||||
*aOuterVisibleRegion = visRect;
|
||||
} else {
|
||||
aOuterVisibleRegion->SetEmpty();
|
||||
}
|
||||
aLayer->SetVisibleRegion(nsIntRegion(visibleRect));
|
||||
}
|
||||
|
||||
if (aLayerContentsVisibleRect && aLayerContentsVisibleRect->width >= 0) {
|
||||
aOuterVisibleRegion->And(*aOuterVisibleRegion, *aLayerContentsVisibleRect);
|
||||
}
|
||||
|
||||
aLayer->SetVisibleRegion(*aOuterVisibleRegion);
|
||||
}
|
||||
|
||||
void
|
||||
ContainerState::SetOuterVisibleRegionForLayer(Layer* aLayer,
|
||||
const nsIntRegion& aOuterVisibleRegion,
|
||||
const nsIntRect* aLayerContentsVisibleRect) const
|
||||
{
|
||||
nsIntRegion visRegion = aOuterVisibleRegion;
|
||||
visRegion.MoveBy(mParameters.mOffset);
|
||||
SetOuterVisibleRegion(aLayer, &visRegion, aLayerContentsVisibleRect);
|
||||
}
|
||||
|
||||
nscolor
|
||||
@ -1844,8 +1952,7 @@ static bool
|
||||
CanOptimizeAwayThebesLayer(ThebesLayerData* aData,
|
||||
FrameLayerBuilder* aLayerBuilder)
|
||||
{
|
||||
bool isRetained = aData->mLayer->Manager()->IsWidgetLayerManager();
|
||||
if (!isRetained) {
|
||||
if (!aLayerBuilder->IsBuildingRetainedLayers()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1863,6 +1970,19 @@ CanOptimizeAwayThebesLayer(ThebesLayerData* aData,
|
||||
return aLayerBuilder->CheckInLayerTreeCompressionMode();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static int32_t FindIndexOfLayerIn(nsTArray<NewLayerEntry>& aArray,
|
||||
Layer* aLayer)
|
||||
{
|
||||
for (uint32_t i = 0; i < aArray.Length(); ++i) {
|
||||
if (aArray[i].mLayer == aLayer) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ContainerState::PopThebesLayerData()
|
||||
{
|
||||
@ -1875,9 +1995,10 @@ ContainerState::PopThebesLayerData()
|
||||
data->mDrawRegion,
|
||||
&data->mVisibleRegion,
|
||||
&data->mIsSolidColorInVisibleRegion);
|
||||
|
||||
NewLayerEntry* newLayerEntry = &mNewChildLayers[data->mNewChildLayersIndex];
|
||||
nsRefPtr<Layer> layer;
|
||||
nsRefPtr<ImageContainer> imageContainer = data->CanOptimizeImageLayer(mBuilder);
|
||||
|
||||
if ((data->mIsSolidColorInVisibleRegion || imageContainer) &&
|
||||
CanOptimizeAwayThebesLayer(data, mLayerBuilder)) {
|
||||
NS_ASSERTION(!(data->mIsSolidColorInVisibleRegion && imageContainer),
|
||||
@ -1913,10 +2034,16 @@ ContainerState::PopThebesLayerData()
|
||||
layer = colorLayer;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mNewChildLayers.Contains(layer), "Layer already in list???");
|
||||
AutoLayersArray::index_type index = mNewChildLayers.IndexOf(data->mLayer);
|
||||
NS_ASSERTION(index != AutoLayersArray::NoIndex, "Thebes layer not found?");
|
||||
mNewChildLayers.InsertElementAt(index + 1, layer);
|
||||
NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, layer) < 0,
|
||||
"Layer already in list???");
|
||||
NS_ASSERTION(newLayerEntry->mLayer == data->mLayer,
|
||||
"Thebes layer at wrong index");
|
||||
// Store optimized layer in reserved slot
|
||||
newLayerEntry = &mNewChildLayers[data->mNewChildLayersIndex + 1];
|
||||
NS_ASSERTION(!newLayerEntry->mLayer, "Slot already occupied?");
|
||||
newLayerEntry->mLayer = layer;
|
||||
newLayerEntry->mAnimatedGeometryRoot = data->mAnimatedGeometryRoot;
|
||||
newLayerEntry->mFixedPosFrameForLayerData = data->mFixedPosFrameForLayerData;
|
||||
|
||||
// Hide the ThebesLayer. We leave it in the layer tree so that we
|
||||
// can find and recycle it later.
|
||||
@ -1930,20 +2057,18 @@ ContainerState::PopThebesLayerData()
|
||||
layer->SetClipRect(nullptr);
|
||||
}
|
||||
|
||||
Matrix transform;
|
||||
if (!layer->GetTransform().Is2D(&transform)) {
|
||||
NS_ERROR("Only 2D transformations currently supported");
|
||||
}
|
||||
|
||||
// ImageLayers are already configured with a visible region
|
||||
if (!imageContainer) {
|
||||
NS_ASSERTION(!transform.HasNonIntegerTranslation(),
|
||||
"Matrix not just an integer translation?");
|
||||
// Convert from relative to the container to relative to the
|
||||
// ThebesLayer itself.
|
||||
nsIntRegion rgn = data->mVisibleRegion;
|
||||
rgn.MoveBy(-GetTranslationForThebesLayer(data->mLayer));
|
||||
layer->SetVisibleRegion(rgn);
|
||||
if (mLayerBuilder->IsBuildingRetainedLayers()) {
|
||||
newLayerEntry->mVisibleRegion = data->mVisibleRegion;
|
||||
newLayerEntry->mOpaqueRegion = data->mOpaqueRegion;
|
||||
newLayerEntry->mHideAllLayersBelow = data->mHideAllLayersBelow;
|
||||
if (nsLayoutUtils::GetScrollableFrameFor(newLayerEntry->mAnimatedGeometryRoot) &&
|
||||
!nsDisplayScrollLayer::IsConstructingScrollLayerForScrolledFrame(newLayerEntry->mAnimatedGeometryRoot)) {
|
||||
// Async scrolling not currently active so we can propagate our opaque region
|
||||
// up to the parent animated geometry root.
|
||||
newLayerEntry->mOpaqueForAnimatedGeometryRootParent = true;
|
||||
}
|
||||
} else {
|
||||
SetOuterVisibleRegionForLayer(layer, data->mVisibleRegion);
|
||||
}
|
||||
|
||||
nsIntRegion transparentRegion;
|
||||
@ -1985,14 +2110,14 @@ ContainerState::PopThebesLayerData()
|
||||
// data->mCommonClipCount may be -1 if we haven't put any actual
|
||||
// drawable items in this layer (i.e. it's only catching events).
|
||||
int32_t commonClipCount = std::max(0, data->mCommonClipCount);
|
||||
SetupMaskLayer(layer, data->mItemClip, commonClipCount);
|
||||
SetupMaskLayer(layer, data->mItemClip, data->mVisibleRegion, commonClipCount);
|
||||
// copy commonClipCount to the entry
|
||||
FrameLayerBuilder::ThebesLayerItemsEntry* entry = mLayerBuilder->
|
||||
GetThebesLayerItemsEntry(static_cast<ThebesLayer*>(layer.get()));
|
||||
entry->mCommonClipCount = commonClipCount;
|
||||
} else {
|
||||
// mask layer for image and color layers
|
||||
SetupMaskLayer(layer, data->mItemClip);
|
||||
SetupMaskLayer(layer, data->mItemClip, data->mVisibleRegion);
|
||||
}
|
||||
|
||||
uint32_t flags = 0;
|
||||
@ -2280,8 +2405,18 @@ ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
|
||||
thebesLayerData->mReferenceFrame = aItem->ReferenceFrame();
|
||||
thebesLayerData->mSingleItemFixedToViewport = aShouldFixToViewport;
|
||||
|
||||
NS_ASSERTION(!mNewChildLayers.Contains(layer), "Layer already in list???");
|
||||
*mNewChildLayers.AppendElement() = layer.forget();
|
||||
NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, layer) < 0,
|
||||
"Layer already in list???");
|
||||
thebesLayerData->mNewChildLayersIndex = mNewChildLayers.Length();
|
||||
NewLayerEntry* newLayerEntry = mNewChildLayers.AppendElement();
|
||||
newLayerEntry->mLayer = layer.forget();
|
||||
newLayerEntry->mAnimatedGeometryRoot = aAnimatedGeometryRoot;
|
||||
newLayerEntry->mFixedPosFrameForLayerData = thebesLayerData->mFixedPosFrameForLayerData;
|
||||
// newLayerEntry->mOpaqueRegion is filled in later from
|
||||
// thebesLayerData->mOpaqueRegion, if necessary.
|
||||
|
||||
// Allocate another entry for this layer's optimization to ColorLayer/ImageLayer
|
||||
mNewChildLayers.AppendElement();
|
||||
} else {
|
||||
thebesLayerData = mThebesLayerDataStack[lowestUsableLayerWithScrolledRoot];
|
||||
}
|
||||
@ -2411,6 +2546,55 @@ IsScrollLayerItemAndOverlayScrollbarForScrollFrame(
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ContainerState::ItemCoversScrollableArea(nsDisplayItem* aItem, const nsRegion& aOpaque)
|
||||
{
|
||||
nsIPresShell* presShell = aItem->Frame()->PresContext()->PresShell();
|
||||
nsIFrame* rootFrame = presShell->GetRootFrame();
|
||||
if (mContainerFrame != rootFrame) {
|
||||
return false;
|
||||
}
|
||||
nsRect scrollableArea;
|
||||
if (presShell->IsScrollPositionClampingScrollPortSizeSet()) {
|
||||
scrollableArea = nsRect(nsPoint(0, 0),
|
||||
presShell->GetScrollPositionClampingScrollPortSize());
|
||||
} else {
|
||||
scrollableArea = rootFrame->GetRectRelativeToSelf();
|
||||
}
|
||||
return aOpaque.Contains(scrollableArea);
|
||||
}
|
||||
|
||||
nsIntRegion
|
||||
ContainerState::ComputeOpaqueRect(nsDisplayItem* aItem,
|
||||
const nsIFrame* aAnimatedGeometryRoot,
|
||||
const nsIFrame* aFixedPosFrame,
|
||||
const DisplayItemClip& aClip,
|
||||
nsDisplayList* aList,
|
||||
bool* aHideAllLayersBelow)
|
||||
{
|
||||
bool snapOpaque;
|
||||
nsRegion opaque = aItem->GetOpaqueRegion(mBuilder, &snapOpaque);
|
||||
nsIntRegion opaquePixels;
|
||||
if (!opaque.IsEmpty()) {
|
||||
nsRegion opaqueClipped;
|
||||
nsRegionRectIterator iter(opaque);
|
||||
for (const nsRect* r = iter.Next(); r; r = iter.Next()) {
|
||||
opaqueClipped.Or(opaqueClipped, aClip.ApproximateIntersectInward(*r));
|
||||
}
|
||||
if (aAnimatedGeometryRoot == mContainerAnimatedGeometryRoot &&
|
||||
aFixedPosFrame == mContainerFixedPosFrame &&
|
||||
!aList->IsOpaque() &&
|
||||
opaqueClipped.Contains(mContainerBounds)) {
|
||||
aList->SetIsOpaque();
|
||||
}
|
||||
opaquePixels = ScaleRegionToInsidePixels(opaqueClipped, snapOpaque);
|
||||
if (aFixedPosFrame && ItemCoversScrollableArea(aItem, opaque)) {
|
||||
*aHideAllLayersBelow = true;
|
||||
}
|
||||
}
|
||||
return opaquePixels;
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate through the non-clip items in aList and its descendants.
|
||||
* For each item we compute the effective clip rect. Each item is assigned
|
||||
@ -2504,7 +2688,6 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList,
|
||||
((nsRect&)mAccumulatedChildBounds).UnionRect(mAccumulatedChildBounds, itemContent);
|
||||
#endif
|
||||
itemVisibleRect.IntersectRect(itemVisibleRect, itemDrawRect);
|
||||
ThebesLayerData* accumulateIntoThebesLayerData = nullptr;
|
||||
|
||||
LayerState layerState = item->GetLayerState(mBuilder, mManager, mParameters);
|
||||
if (layerState == LAYER_INACTIVE &&
|
||||
@ -2569,13 +2752,9 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (itemType == nsDisplayItem::TYPE_TRANSFORM) {
|
||||
mParameters.mAncestorClipRect = itemClip.HasClip() ? &clipRect : nullptr;
|
||||
} else {
|
||||
mParameters.mAncestorClipRect = nullptr;
|
||||
}
|
||||
|
||||
// Just use its layer.
|
||||
nsIntRect layerContentsVisibleRect(0, 0, -1, -1);
|
||||
mParameters.mLayerContentsVisibleRect = &layerContentsVisibleRect;
|
||||
nsRefPtr<Layer> ownLayer = item->BuildLayer(mBuilder, mManager, mParameters);
|
||||
if (!ownLayer) {
|
||||
continue;
|
||||
@ -2650,25 +2829,39 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList,
|
||||
data->AddDrawAboveRegion(itemDrawRect);
|
||||
}
|
||||
}
|
||||
itemVisibleRect.MoveBy(mParameters.mOffset);
|
||||
if (item->SetVisibleRegionOnLayer()) {
|
||||
SetVisibleRegionForLayer(ownLayer, nullptr, itemVisibleRect);
|
||||
}
|
||||
|
||||
// rounded rectangle clipping using mask layers
|
||||
// (must be done after visible rect is set on layer)
|
||||
if (itemClip.IsRectClippedByRoundedCorner(itemContent)) {
|
||||
SetupMaskLayer(ownLayer, itemClip);
|
||||
SetupMaskLayer(ownLayer, itemClip, itemVisibleRect);
|
||||
}
|
||||
|
||||
ContainerLayer* oldContainer = ownLayer->GetParent();
|
||||
if (oldContainer && oldContainer != mContainerLayer) {
|
||||
oldContainer->RemoveChild(ownLayer);
|
||||
}
|
||||
NS_ASSERTION(!mNewChildLayers.Contains(ownLayer),
|
||||
NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, ownLayer) < 0,
|
||||
"Layer already in list???");
|
||||
|
||||
mNewChildLayers.AppendElement(ownLayer);
|
||||
NewLayerEntry* newLayerEntry = mNewChildLayers.AppendElement();
|
||||
newLayerEntry->mLayer = ownLayer;
|
||||
newLayerEntry->mAnimatedGeometryRoot = animatedGeometryRoot;
|
||||
newLayerEntry->mFixedPosFrameForLayerData = fixedPosFrame;
|
||||
if (mLayerBuilder->IsBuildingRetainedLayers()) {
|
||||
newLayerEntry->mLayerContentsVisibleRect = layerContentsVisibleRect;
|
||||
newLayerEntry->mVisibleRegion = itemVisibleRect;
|
||||
newLayerEntry->mOpaqueRegion = ComputeOpaqueRect(item,
|
||||
animatedGeometryRoot, fixedPosFrame, itemClip, aList,
|
||||
&newLayerEntry->mHideAllLayersBelow);
|
||||
} else {
|
||||
SetOuterVisibleRegionForLayer(ownLayer, itemVisibleRect,
|
||||
&layerContentsVisibleRect);
|
||||
}
|
||||
if (itemType == nsDisplayItem::TYPE_SCROLL_LAYER) {
|
||||
nsDisplayScrollLayer* scrollItem = static_cast<nsDisplayScrollLayer*>(item);
|
||||
newLayerEntry->mOpaqueForAnimatedGeometryRootParent =
|
||||
scrollItem->IsDisplayPortOpaque();
|
||||
}
|
||||
|
||||
/**
|
||||
* No need to allocate geometry for items that aren't
|
||||
@ -2698,33 +2891,17 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList,
|
||||
nsAutoPtr<nsDisplayItemGeometry> geometry(item->AllocateGeometry(mBuilder));
|
||||
InvalidateForLayerChange(item, thebesLayerData->mLayer, itemClip, topLeft, geometry);
|
||||
|
||||
mLayerBuilder->AddThebesDisplayItem(thebesLayerData, item, itemClip,
|
||||
mContainerFrame,
|
||||
layerState, topLeft,
|
||||
geometry);
|
||||
accumulateIntoThebesLayerData = thebesLayerData;
|
||||
mLayerBuilder->AddThebesDisplayItem(thebesLayerData, item, itemClip, itemVisibleRect,
|
||||
*this, layerState, topLeft, geometry);
|
||||
nsIntRegion opaquePixels = ComputeOpaqueRect(item,
|
||||
animatedGeometryRoot, thebesLayerData->mFixedPosFrameForLayerData,
|
||||
itemClip, aList,
|
||||
&thebesLayerData->mHideAllLayersBelow);
|
||||
thebesLayerData->Accumulate(this, item, opaquePixels,
|
||||
itemVisibleRect, itemDrawRect, itemClip);
|
||||
}
|
||||
}
|
||||
|
||||
bool snapOpaque;
|
||||
nsRegion opaque = item->GetOpaqueRegion(mBuilder, &snapOpaque);
|
||||
nsRegion opaqueClipped;
|
||||
if (!opaque.IsEmpty()) {
|
||||
nsRegionRectIterator iter(opaque);
|
||||
for (const nsRect* r = iter.Next(); r; r = iter.Next()) {
|
||||
opaqueClipped.Or(opaqueClipped, itemClip.ApproximateIntersectInward(*r));
|
||||
}
|
||||
if (opaqueClipped.Contains(mContainerBounds)) {
|
||||
aList->SetIsOpaque();
|
||||
}
|
||||
}
|
||||
if (accumulateIntoThebesLayerData) {
|
||||
nsIntRegion opaquePixels =
|
||||
ScaleRegionToInsidePixels(opaqueClipped, snapOpaque);
|
||||
accumulateIntoThebesLayerData->Accumulate(this, item,
|
||||
opaquePixels, itemVisibleRect, itemDrawRect, itemClip);
|
||||
}
|
||||
|
||||
if (itemSameCoordinateSystemChildren &&
|
||||
itemSameCoordinateSystemChildren->NeedsTransparentSurface()) {
|
||||
aList->SetNeedsTransparentSurface();
|
||||
@ -2873,7 +3050,8 @@ void
|
||||
FrameLayerBuilder::AddThebesDisplayItem(ThebesLayerData* aLayerData,
|
||||
nsDisplayItem* aItem,
|
||||
const DisplayItemClip& aClip,
|
||||
nsIFrame* aContainerLayerFrame,
|
||||
const nsIntRect& aItemVisibleRect,
|
||||
const ContainerState& aContainerState,
|
||||
LayerState aLayerState,
|
||||
const nsPoint& aTopLeft,
|
||||
nsAutoPtr<nsDisplayItemGeometry> aGeometry)
|
||||
@ -2913,7 +3091,7 @@ FrameLayerBuilder::AddThebesDisplayItem(ThebesLayerData* aLayerData,
|
||||
|
||||
ThebesLayerItemsEntry* entry = mThebesLayerItems.PutEntry(layer);
|
||||
if (entry) {
|
||||
entry->mContainerLayerFrame = aContainerLayerFrame;
|
||||
entry->mContainerLayerFrame = aContainerState.GetContainerFrame();
|
||||
if (entry->mContainerLayerGeneration == 0) {
|
||||
entry->mContainerLayerGeneration = mContainerLayerGeneration;
|
||||
}
|
||||
@ -2937,6 +3115,12 @@ FrameLayerBuilder::AddThebesDisplayItem(ThebesLayerData* aLayerData,
|
||||
return;
|
||||
}
|
||||
|
||||
bool snap;
|
||||
nsRect visibleRect =
|
||||
aItem->GetVisibleRect().Intersect(aItem->GetBounds(mDisplayListBuilder, &snap));
|
||||
nsIntRegion rgn = visibleRect.ToOutsidePixels(thebesData->mAppUnitsPerDevPixel);
|
||||
SetOuterVisibleRegion(tmpLayer, &rgn);
|
||||
|
||||
// If BuildLayer didn't call BuildContainerLayerFor, then our new layer won't have been
|
||||
// stored in layerBuilder. Manually add it now.
|
||||
if (mRetainingManager) {
|
||||
@ -3129,8 +3313,99 @@ ContainerState::CollectOldLayers()
|
||||
}
|
||||
}
|
||||
|
||||
struct OpaqueRegionEntry {
|
||||
const nsIFrame* mAnimatedGeometryRoot;
|
||||
const nsIFrame* mFixedPosFrameForLayerData;
|
||||
nsIntRegion mOpaqueRegion;
|
||||
};
|
||||
|
||||
static OpaqueRegionEntry*
|
||||
FindOpaqueRegionEntry(nsTArray<OpaqueRegionEntry>& aEntries,
|
||||
const nsIFrame* aAnimatedGeometryRoot,
|
||||
const nsIFrame* aFixedPosFrameForLayerData)
|
||||
{
|
||||
for (uint32_t i = 0; i < aEntries.Length(); ++i) {
|
||||
OpaqueRegionEntry* d = &aEntries[i];
|
||||
if (d->mAnimatedGeometryRoot == aAnimatedGeometryRoot &&
|
||||
d->mFixedPosFrameForLayerData == aFixedPosFrameForLayerData) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ContainerState::Finish(uint32_t* aTextContentFlags, LayerManagerData* aData)
|
||||
ContainerState::ApplyOcclusionCulling(nsIntRegion* aOpaqueRegionForContainer)
|
||||
{
|
||||
nsAutoTArray<OpaqueRegionEntry,4> opaqueRegions;
|
||||
bool hideAll = false;
|
||||
int32_t opaqueRegionForContainer = -1;
|
||||
|
||||
for (int32_t i = mNewChildLayers.Length() - 1; i >= 0; --i) {
|
||||
NewLayerEntry* e = &mNewChildLayers.ElementAt(i);
|
||||
if (!e->mLayer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
OpaqueRegionEntry* data = FindOpaqueRegionEntry(opaqueRegions,
|
||||
e->mAnimatedGeometryRoot, e->mFixedPosFrameForLayerData);
|
||||
|
||||
if (hideAll) {
|
||||
e->mVisibleRegion.SetEmpty();
|
||||
} else if (data) {
|
||||
e->mVisibleRegion.Sub(e->mVisibleRegion, data->mOpaqueRegion);
|
||||
}
|
||||
|
||||
if (!e->mOpaqueRegion.IsEmpty()) {
|
||||
const nsIFrame* animatedGeometryRootToCover = e->mAnimatedGeometryRoot;
|
||||
if (e->mOpaqueForAnimatedGeometryRootParent &&
|
||||
nsLayoutUtils::GetAnimatedGeometryRootForFrame(e->mAnimatedGeometryRoot->GetParent(),
|
||||
mContainerAnimatedGeometryRoot)
|
||||
== mContainerAnimatedGeometryRoot) {
|
||||
animatedGeometryRootToCover = mContainerAnimatedGeometryRoot;
|
||||
data = FindOpaqueRegionEntry(opaqueRegions,
|
||||
animatedGeometryRootToCover, e->mFixedPosFrameForLayerData);
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
if (animatedGeometryRootToCover == mContainerAnimatedGeometryRoot &&
|
||||
!e->mFixedPosFrameForLayerData) {
|
||||
NS_ASSERTION(opaqueRegionForContainer == -1, "Already found it?");
|
||||
opaqueRegionForContainer = opaqueRegions.Length();
|
||||
}
|
||||
data = opaqueRegions.AppendElement();
|
||||
data->mAnimatedGeometryRoot = animatedGeometryRootToCover;
|
||||
data->mFixedPosFrameForLayerData = e->mFixedPosFrameForLayerData;
|
||||
}
|
||||
data->mOpaqueRegion.Or(data->mOpaqueRegion, e->mOpaqueRegion);
|
||||
if (e->mHideAllLayersBelow) {
|
||||
hideAll = true;
|
||||
}
|
||||
}
|
||||
|
||||
SetOuterVisibleRegionForLayer(e->mLayer, e->mVisibleRegion,
|
||||
e->mLayerContentsVisibleRect.width >= 0 ? &e->mLayerContentsVisibleRect : nullptr);
|
||||
|
||||
if (e->mLayer->GetType() == Layer::TYPE_READBACK) {
|
||||
// ReadbackLayers need to accurately read what's behind them. So,
|
||||
// we don't want to do any occlusion culling of layers behind them.
|
||||
// Theoretically we could just punch out the ReadbackLayer's rectangle
|
||||
// from all mOpaqueRegions, but that's probably not worth doing.
|
||||
opaqueRegions.Clear();
|
||||
opaqueRegionForContainer = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (opaqueRegionForContainer >= 0) {
|
||||
aOpaqueRegionForContainer->Or(*aOpaqueRegionForContainer,
|
||||
opaqueRegions[opaqueRegionForContainer].mOpaqueRegion);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContainerState::Finish(uint32_t* aTextContentFlags, LayerManagerData* aData,
|
||||
const nsIntRect& aContainerPixelBounds,
|
||||
nsDisplayList* aChildItems)
|
||||
{
|
||||
while (!mThebesLayerDataStack.IsEmpty()) {
|
||||
PopThebesLayerData();
|
||||
@ -3140,12 +3415,24 @@ ContainerState::Finish(uint32_t* aTextContentFlags, LayerManagerData* aData)
|
||||
"Bounds computation mismatch");
|
||||
uint32_t textContentFlags = 0;
|
||||
|
||||
if (mLayerBuilder->IsBuildingRetainedLayers()) {
|
||||
nsIntRegion containerOpaqueRegion;
|
||||
ApplyOcclusionCulling(&containerOpaqueRegion);
|
||||
if (containerOpaqueRegion.Contains(aContainerPixelBounds)) {
|
||||
aChildItems->SetIsOpaque();
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that current/existing layers are added to the parent and are
|
||||
// in the correct order.
|
||||
Layer* layer = nullptr;
|
||||
for (uint32_t i = 0; i < mNewChildLayers.Length(); ++i) {
|
||||
Layer* prevChild = i == 0 ? nullptr : mNewChildLayers[i - 1].get();
|
||||
layer = mNewChildLayers[i];
|
||||
Layer* prevChild = nullptr;
|
||||
for (uint32_t i = 0; i < mNewChildLayers.Length(); ++i, prevChild = layer) {
|
||||
if (!mNewChildLayers[i].mLayer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
layer = mNewChildLayers[i].mLayer;
|
||||
|
||||
if (!layer->GetVisibleRegion().IsEmpty()) {
|
||||
textContentFlags |= layer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA;
|
||||
@ -3333,8 +3620,8 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
|
||||
aOutgoingScale.mInActiveTransformedSubtree = true;
|
||||
}
|
||||
}
|
||||
bool isRetained = aLayer->Manager()->IsWidgetLayerManager();
|
||||
if (isRetained && (!canDraw2D || transform2d.HasNonIntegerTranslation())) {
|
||||
if (aLayerBuilder->IsBuildingRetainedLayers() &&
|
||||
(!canDraw2D || transform2d.HasNonIntegerTranslation())) {
|
||||
aOutgoingScale.mDisableSubpixelAntialiasingInDescendants = true;
|
||||
}
|
||||
return true;
|
||||
@ -3471,7 +3758,7 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
nsRect bounds = aChildren->GetBounds(aBuilder);
|
||||
nsIntRect pixBounds;
|
||||
int32_t appUnitsPerDevPixel;
|
||||
nscoord appUnitsPerDevPixel;
|
||||
uint32_t stateFlags = 0;
|
||||
if ((aContainerFrame->GetStateBits() & NS_FRAME_NO_COMPONENT_ALPHA) &&
|
||||
mRetainingManager && !mRetainingManager->AreComponentAlphaLayersEnabled()) {
|
||||
@ -3488,10 +3775,9 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
|
||||
// Set CONTENT_COMPONENT_ALPHA if any of our children have it.
|
||||
// This is suboptimal ... a child could have text that's over transparent
|
||||
// pixels in its own layer, but over opaque parts of previous siblings.
|
||||
state.Finish(&flags, data);
|
||||
|
||||
pixBounds = state.ScaleToOutsidePixels(bounds, false);
|
||||
appUnitsPerDevPixel = state.GetAppUnitsPerDevPixel();
|
||||
state.Finish(&flags, data, pixBounds, aChildren);
|
||||
|
||||
if ((flags & Layer::CONTENT_COMPONENT_ALPHA) &&
|
||||
mRetainingManager &&
|
||||
@ -3512,13 +3798,6 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
|
||||
break;
|
||||
}
|
||||
|
||||
pixBounds.MoveBy(nsIntPoint(scaleParameters.mOffset.x, scaleParameters.mOffset.y));
|
||||
if (aParameters.mAncestorClipRect && !(aFlags & CONTAINER_NOT_CLIPPED_BY_ANCESTORS)) {
|
||||
SetVisibleRegionForLayer(containerLayer, &pixBounds,
|
||||
*aParameters.mAncestorClipRect);
|
||||
} else {
|
||||
containerLayer->SetVisibleRegion(pixBounds);
|
||||
}
|
||||
// Make sure that rounding the visible region out didn't add any area
|
||||
// we won't paint
|
||||
if (aChildren->IsOpaque() && !aChildren->NeedsTransparentSurface()) {
|
||||
@ -3529,6 +3808,14 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
|
||||
}
|
||||
}
|
||||
containerLayer->SetContentFlags(flags);
|
||||
// If aContainerItem is non-null some BuildContainerLayer further up the
|
||||
// call stack is responsible for setting containerLayer's visible region.
|
||||
if (!aContainerItem) {
|
||||
containerLayer->SetVisibleRegion(pixBounds);
|
||||
}
|
||||
if (aParameters.mLayerContentsVisibleRect) {
|
||||
*aParameters.mLayerContentsVisibleRect = pixBounds + scaleParameters.mOffset;
|
||||
}
|
||||
|
||||
mContainerLayerGeneration = oldGeneration;
|
||||
nsPresContext::ClearNotifySubDocInvalidationData(containerLayer);
|
||||
@ -4052,7 +4339,9 @@ SetClipCount(ThebesDisplayItemLayerUserData* aThebesData,
|
||||
}
|
||||
|
||||
void
|
||||
ContainerState::SetupMaskLayer(Layer *aLayer, const DisplayItemClip& aClip,
|
||||
ContainerState::SetupMaskLayer(Layer *aLayer,
|
||||
const DisplayItemClip& aClip,
|
||||
const nsIntRegion& aLayerVisibleRegion,
|
||||
uint32_t aRoundedRectClipCount)
|
||||
{
|
||||
// if the number of clips we are going to mask has decreased, then aLayer might have
|
||||
@ -4066,7 +4355,7 @@ ContainerState::SetupMaskLayer(Layer *aLayer, const DisplayItemClip& aClip,
|
||||
}
|
||||
|
||||
// don't build an unnecessary mask
|
||||
nsIntRect layerBounds = aLayer->GetVisibleRegion().GetBounds();
|
||||
nsIntRect layerBounds = aLayerVisibleRegion.GetBounds();
|
||||
if (aClip.GetRoundedRectCount() == 0 ||
|
||||
aRoundedRectClipCount == 0 ||
|
||||
layerBounds.IsEmpty()) {
|
||||
|
@ -32,6 +32,7 @@ class ThebesLayer;
|
||||
class FrameLayerBuilder;
|
||||
class LayerManagerData;
|
||||
class ThebesLayerData;
|
||||
class ContainerState;
|
||||
|
||||
enum LayerState {
|
||||
LAYER_NONE,
|
||||
@ -57,34 +58,44 @@ public:
|
||||
bool mIsInfinite;
|
||||
};
|
||||
|
||||
struct NewLayerEntry;
|
||||
|
||||
struct ContainerLayerParameters {
|
||||
ContainerLayerParameters() :
|
||||
mXScale(1), mYScale(1), mAncestorClipRect(nullptr),
|
||||
mInTransformedSubtree(false), mInActiveTransformedSubtree(false),
|
||||
mDisableSubpixelAntialiasingInDescendants(false)
|
||||
ContainerLayerParameters()
|
||||
: mXScale(1)
|
||||
, mYScale(1)
|
||||
, mLayerContentsVisibleRect(nullptr)
|
||||
, mInTransformedSubtree(false)
|
||||
, mInActiveTransformedSubtree(false)
|
||||
, mDisableSubpixelAntialiasingInDescendants(false)
|
||||
{}
|
||||
ContainerLayerParameters(float aXScale, float aYScale) :
|
||||
mXScale(aXScale), mYScale(aYScale), mAncestorClipRect(nullptr),
|
||||
mInTransformedSubtree(false), mInActiveTransformedSubtree(false),
|
||||
mDisableSubpixelAntialiasingInDescendants(false)
|
||||
ContainerLayerParameters(float aXScale, float aYScale)
|
||||
: mXScale(aXScale)
|
||||
, mYScale(aYScale)
|
||||
, mLayerContentsVisibleRect(nullptr)
|
||||
, mInTransformedSubtree(false)
|
||||
, mInActiveTransformedSubtree(false)
|
||||
, mDisableSubpixelAntialiasingInDescendants(false)
|
||||
{}
|
||||
ContainerLayerParameters(float aXScale, float aYScale,
|
||||
const nsIntPoint& aOffset,
|
||||
const ContainerLayerParameters& aParent) :
|
||||
mXScale(aXScale), mYScale(aYScale), mAncestorClipRect(nullptr),
|
||||
mOffset(aOffset),
|
||||
mInTransformedSubtree(aParent.mInTransformedSubtree),
|
||||
mInActiveTransformedSubtree(aParent.mInActiveTransformedSubtree),
|
||||
mDisableSubpixelAntialiasingInDescendants(aParent.mDisableSubpixelAntialiasingInDescendants)
|
||||
const ContainerLayerParameters& aParent)
|
||||
: mXScale(aXScale)
|
||||
, mYScale(aYScale)
|
||||
, mLayerContentsVisibleRect(nullptr)
|
||||
, mOffset(aOffset)
|
||||
, mInTransformedSubtree(aParent.mInTransformedSubtree)
|
||||
, mInActiveTransformedSubtree(aParent.mInActiveTransformedSubtree)
|
||||
, mDisableSubpixelAntialiasingInDescendants(aParent.mDisableSubpixelAntialiasingInDescendants)
|
||||
{}
|
||||
float mXScale, mYScale;
|
||||
/**
|
||||
* An ancestor clip rect that can be applied to restrict the visibility
|
||||
* of this container. Null if none available.
|
||||
* If non-null, the rectangle in which BuildContainerLayerFor stores the
|
||||
* visible rect of the layer, in the coordinate system of the created layer.
|
||||
*/
|
||||
const nsIntRect* mAncestorClipRect;
|
||||
nsIntRect* mLayerContentsVisibleRect;
|
||||
/**
|
||||
* An offset to append to the transform set on all child layers created.
|
||||
* An offset to apply to all child layers created.
|
||||
*/
|
||||
nsIntPoint mOffset;
|
||||
|
||||
@ -208,6 +219,8 @@ public:
|
||||
* The container layer is transformed by aTransform (if non-null), and
|
||||
* the result is transformed by the scale factors in aContainerParameters.
|
||||
* aChildren is modified due to display item merging and flattening.
|
||||
* The visible region of the returned layer is set only if aContainerItem
|
||||
* is null.
|
||||
*/
|
||||
already_AddRefed<ContainerLayer>
|
||||
BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
|
||||
@ -300,7 +313,8 @@ public:
|
||||
void AddThebesDisplayItem(ThebesLayerData* aLayer,
|
||||
nsDisplayItem* aItem,
|
||||
const DisplayItemClip& aClip,
|
||||
nsIFrame* aContainerLayerFrame,
|
||||
const nsIntRect& aItemVisibleRect,
|
||||
const ContainerState& aContainerState,
|
||||
LayerState aLayerState,
|
||||
const nsPoint& aTopLeft,
|
||||
nsAutoPtr<nsDisplayItemGeometry> aGeometry);
|
||||
@ -597,6 +611,11 @@ public:
|
||||
return mContainingThebesLayer;
|
||||
}
|
||||
|
||||
bool IsBuildingRetainedLayers()
|
||||
{
|
||||
return !mContainingThebesLayer && mRetainingManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to build the most compressed layer tree possible, even if it means
|
||||
* throwing away existing retained buffers.
|
||||
|
Loading…
Reference in New Issue
Block a user