mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-26 06:38:36 +00:00
Bug 1134311 - Get rid of the draw region and always only use the visible region. r=roc
This commit is contained in:
parent
bd6cb854e2
commit
8ada7e4943
@ -269,7 +269,7 @@ public:
|
||||
mImage(nullptr),
|
||||
mCommonClipCount(-1),
|
||||
mNewChildLayersIndex(-1),
|
||||
mAllDrawingAbove(false)
|
||||
mVisibleAboveRegionIsInfinite(false)
|
||||
{}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
@ -291,12 +291,6 @@ public:
|
||||
* Record that an item has been added to the PaintedLayer, so we
|
||||
* need to update our regions.
|
||||
* @param aVisibleRect the area of the item that's visible
|
||||
* @param aDrawRect the area of the item that would be drawn if it
|
||||
* was completely visible
|
||||
* @param aOpaqueRect if non-null, the area of the item that's opaque.
|
||||
* We pass in a separate opaque rect because the opaque rect can be
|
||||
* bigger than the visible rect, and we want to have the biggest
|
||||
* opaque rect that we can.
|
||||
* @param aSolidColor if non-null, the visible area of the item is
|
||||
* a constant color given by *aSolidColor
|
||||
*/
|
||||
@ -304,7 +298,6 @@ public:
|
||||
nsDisplayItem* aItem,
|
||||
const nsIntRegion& aClippedOpaqueRegion,
|
||||
const nsIntRect& aVisibleRect,
|
||||
const nsIntRect& aDrawRect,
|
||||
const DisplayItemClip& aClip);
|
||||
const nsIFrame* GetAnimatedGeometryRoot() { return mAnimatedGeometryRoot; }
|
||||
|
||||
@ -328,17 +321,9 @@ public:
|
||||
*/
|
||||
already_AddRefed<ImageContainer> CanOptimizeImageLayer(nsDisplayListBuilder* aBuilder);
|
||||
|
||||
void AddDrawAboveRegion(const nsIntRegion& aAbove)
|
||||
{
|
||||
if (!mAllDrawingAbove) {
|
||||
mDrawAboveRegion.Or(mDrawAboveRegion, aAbove);
|
||||
mDrawAboveRegion.SimplifyOutward(8);
|
||||
}
|
||||
}
|
||||
|
||||
void AddVisibleAboveRegion(const nsIntRegion& aAbove)
|
||||
{
|
||||
if (!mAllDrawingAbove) {
|
||||
if (!mVisibleAboveRegionIsInfinite) {
|
||||
mVisibleAboveRegion.Or(mVisibleAboveRegion, aAbove);
|
||||
mVisibleAboveRegion.SimplifyOutward(8);
|
||||
}
|
||||
@ -346,58 +331,50 @@ public:
|
||||
|
||||
void CopyAboveRegion(PaintedLayerData* aOther)
|
||||
{
|
||||
if (mVisibleAboveRegionIsInfinite) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If aOther has a draw region and is subject to async transforms then the
|
||||
// layer can potentially be moved arbitrarily on the compositor. So we
|
||||
// should avoid moving display items from on top of the layer to below the
|
||||
// layer, which we do by calling SetAllDrawingAbove. Note that if the draw
|
||||
// region is empty (such as when aOther has only event-regions items) then
|
||||
// we don't need to do this.
|
||||
// layer, which we do by calling SetVisibleAboveRegionIsInfinite. Note that
|
||||
// if the draw region is empty (such as when aOther has only event-regions
|
||||
// items) then we don't need to do this.
|
||||
bool aOtherCanDrawAnywhere = aOther->IsSubjectToAsyncTransforms()
|
||||
&& !aOther->mDrawRegion.IsEmpty();
|
||||
&& !aOther->mVisibleRegion.IsEmpty();
|
||||
|
||||
if (aOther->mAllDrawingAbove || mAllDrawingAbove || aOtherCanDrawAnywhere) {
|
||||
SetAllDrawingAbove();
|
||||
if (aOther->mVisibleAboveRegionIsInfinite || aOtherCanDrawAnywhere) {
|
||||
SetVisibleAboveRegionIsInfinite();
|
||||
} else {
|
||||
mVisibleAboveRegion.Or(mVisibleAboveRegion, aOther->mVisibleAboveRegion);
|
||||
mVisibleAboveRegion.Or(mVisibleAboveRegion, aOther->mVisibleRegion);
|
||||
mVisibleAboveRegion.SimplifyOutward(8);
|
||||
mDrawAboveRegion.Or(mDrawAboveRegion, aOther->mDrawAboveRegion);
|
||||
mDrawAboveRegion.Or(mDrawAboveRegion, aOther->mDrawRegion);
|
||||
mDrawAboveRegion.SimplifyOutward(8);
|
||||
}
|
||||
}
|
||||
|
||||
void SetAllDrawingAbove()
|
||||
void SetVisibleAboveRegionIsInfinite()
|
||||
{
|
||||
mAllDrawingAbove = true;
|
||||
mDrawAboveRegion.SetEmpty();
|
||||
mVisibleAboveRegionIsInfinite = true;
|
||||
mVisibleAboveRegion.SetEmpty();
|
||||
}
|
||||
|
||||
bool DrawAboveRegionIntersects(const nsIntRect& aRect)
|
||||
bool VisibleAboveRegionIntersects(const nsIntRect& aRect) const
|
||||
{
|
||||
return mAllDrawingAbove || mDrawAboveRegion.Intersects(aRect);
|
||||
return mVisibleAboveRegionIsInfinite || mVisibleAboveRegion.Intersects(aRect);
|
||||
}
|
||||
|
||||
bool DrawRegionIntersects(const nsIntRect& aRect)
|
||||
bool VisibleAboveRegionIntersects(const nsIntRegion& aRegion) const
|
||||
{
|
||||
return IsSubjectToAsyncTransforms() || mDrawRegion.Intersects(aRect);
|
||||
return mVisibleAboveRegionIsInfinite || !mVisibleAboveRegion.Intersect(aRegion).IsEmpty();
|
||||
}
|
||||
|
||||
bool IntersectsVisibleAboveRegion(const nsIntRegion& aVisibleRegion)
|
||||
bool VisibleRegionIntersects(const nsIntRect& aRect) const
|
||||
{
|
||||
if (mAllDrawingAbove) {
|
||||
return true;
|
||||
}
|
||||
nsIntRegion visibleAboveIntersection;
|
||||
visibleAboveIntersection.And(mVisibleAboveRegion, aVisibleRegion);
|
||||
if (visibleAboveIntersection.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return IsSubjectToAsyncTransforms() || mVisibleRegion.Intersects(aRect);
|
||||
}
|
||||
|
||||
bool IsSubjectToAsyncTransforms()
|
||||
bool IsSubjectToAsyncTransforms() const
|
||||
{
|
||||
return mFixedPosFrameForLayerData != nullptr
|
||||
|| mIsAsyncScrollable;
|
||||
@ -409,13 +386,6 @@ public:
|
||||
* list reference frame).
|
||||
*/
|
||||
nsIntRegion mVisibleRegion;
|
||||
/**
|
||||
* The region containing the bounds of all display items in the layer,
|
||||
* regardless of visbility.
|
||||
* Same coordinate system as mVisibleRegion.
|
||||
* This is a conservative approximation: it contains the true region.
|
||||
*/
|
||||
nsIntRegion mDrawRegion;
|
||||
/**
|
||||
* The region of visible content in the layer that is opaque.
|
||||
* Same coordinate system as mVisibleRegion.
|
||||
@ -543,19 +513,10 @@ private:
|
||||
*/
|
||||
nsIntRegion mVisibleAboveRegion;
|
||||
/**
|
||||
* The region containing the bounds of all display items (regardless
|
||||
* of visibility) in the layer and below the next PaintedLayerData
|
||||
* currently in the stack, if any.
|
||||
* Note that not all PaintedLayers for the container are in the
|
||||
* PaintedLayerData stack.
|
||||
* Same coordinate system as mVisibleRegion.
|
||||
* True if mVisibleAboveRegion should be treated as infinite, and all
|
||||
* display items should be considered 'above' this layer.
|
||||
*/
|
||||
nsIntRegion mDrawAboveRegion;
|
||||
/**
|
||||
* True if mDrawAboveRegion and mVisibleAboveRegion should be treated
|
||||
* as infinite, and all display items should be considered 'above' this layer.
|
||||
*/
|
||||
bool mAllDrawingAbove;
|
||||
bool mVisibleAboveRegionIsInfinite;
|
||||
|
||||
};
|
||||
|
||||
@ -781,9 +742,7 @@ protected:
|
||||
/**
|
||||
* Find the fixed-pos frame, if any, containing (or equal to)
|
||||
* aAnimatedGeometryRoot. Only return a fixed-pos frame if its viewport
|
||||
* has a displayport. Updates *aVisibleRegion to be the intersection of
|
||||
* aDrawRegion and the displayport, and updates *aIsSolidColorInVisibleRegion
|
||||
* (if non-null) to false if the visible region grows.
|
||||
* has a displayport.
|
||||
* aDisplayItemFixedToViewport is true if the layer contains a single display
|
||||
* item which returned true for ShouldFixToViewport.
|
||||
* This can return the actual viewport frame for layers whose display items
|
||||
@ -791,10 +750,6 @@ protected:
|
||||
*/
|
||||
const nsIFrame* FindFixedPosFrameForLayerData(const nsIFrame* aAnimatedGeometryRoot,
|
||||
bool aDisplayItemFixedToViewport);
|
||||
void AdjustLayerDataForFixedPositioning(const nsIFrame* aFixedPosFrame,
|
||||
const nsIntRegion& aDrawRegion,
|
||||
nsIntRegion* aVisibleRegion,
|
||||
bool* aIsSolidColorInVisibleRegion = nullptr);
|
||||
/**
|
||||
* Set fixed-pos layer metadata on aLayer according to the data for aFixedPosFrame.
|
||||
*/
|
||||
@ -1891,7 +1846,7 @@ ContainerState::FindOpaqueBackgroundColorFor(int32_t aPaintedLayerIndex)
|
||||
PaintedLayerData* target = mPaintedLayerDataStack[aPaintedLayerIndex];
|
||||
for (int32_t i = aPaintedLayerIndex - 1; i >= 0; --i) {
|
||||
PaintedLayerData* candidate = mPaintedLayerDataStack[i];
|
||||
if (candidate->IntersectsVisibleAboveRegion(target->mVisibleRegion)) {
|
||||
if (candidate->VisibleAboveRegionIntersects(target->mVisibleRegion)) {
|
||||
// Some non-PaintedLayer content between target and candidate; this is
|
||||
// hopeless
|
||||
break;
|
||||
@ -2016,52 +1971,6 @@ ContainerState::FindFixedPosFrameForLayerData(const nsIFrame* aAnimatedGeometryR
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ContainerState::AdjustLayerDataForFixedPositioning(const nsIFrame* aFixedPosFrame,
|
||||
const nsIntRegion& aDrawRegion,
|
||||
nsIntRegion* aVisibleRegion,
|
||||
bool* aIsSolidColorInVisibleRegion)
|
||||
{
|
||||
if (!aFixedPosFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRect fixedVisibleRect;
|
||||
nsPresContext* presContext = aFixedPosFrame->PresContext();
|
||||
nsIPresShell* presShell = presContext->PresShell();
|
||||
DebugOnly<bool> hasDisplayPort =
|
||||
nsLayoutUtils::ViewportHasDisplayPort(presContext, &fixedVisibleRect);
|
||||
NS_ASSERTION(hasDisplayPort, "No fixed-pos layer data if there's no displayport");
|
||||
// Display ports are relative to the viewport, convert it to be relative
|
||||
// to our reference frame.
|
||||
nsIFrame* viewport = presShell->GetRootFrame();
|
||||
if (aFixedPosFrame != viewport) {
|
||||
// position: fixed items are reflowed into and only drawn inside the
|
||||
// viewport, or the scroll position clamping scrollport size, if one is
|
||||
// set. We differentiate background-attachment: fixed items from
|
||||
// position: fixed items by the fact that background-attachment: fixed
|
||||
// items use the viewport as their aFixedPosFrame.
|
||||
NS_ASSERTION(aFixedPosFrame->StyleDisplay()->mPosition == NS_STYLE_POSITION_FIXED,
|
||||
"should be position fixed items only");
|
||||
fixedVisibleRect.MoveTo(0, 0);
|
||||
if (presShell->IsScrollPositionClampingScrollPortSizeSet()) {
|
||||
fixedVisibleRect.SizeTo(presShell->GetScrollPositionClampingScrollPortSize());
|
||||
} else {
|
||||
fixedVisibleRect.SizeTo(viewport->GetSize());
|
||||
}
|
||||
}
|
||||
fixedVisibleRect += viewport->GetOffsetToCrossDoc(mContainerReferenceFrame);
|
||||
nsIntRegion newVisibleRegion;
|
||||
newVisibleRegion.And(ScaleToOutsidePixels(fixedVisibleRect, false),
|
||||
aDrawRegion);
|
||||
if (!aVisibleRegion->Contains(newVisibleRegion)) {
|
||||
if (aIsSolidColorInVisibleRegion) {
|
||||
*aIsSolidColorInVisibleRegion = false;
|
||||
}
|
||||
*aVisibleRegion = newVisibleRegion;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContainerState::SetFixedPositionLayerData(Layer* aLayer,
|
||||
const nsIFrame* aFixedPosFrame)
|
||||
@ -2141,11 +2050,6 @@ ContainerState::PopPaintedLayerData()
|
||||
int32_t lastIndex = mPaintedLayerDataStack.Length() - 1;
|
||||
PaintedLayerData* data = mPaintedLayerDataStack[lastIndex];
|
||||
|
||||
AdjustLayerDataForFixedPositioning(data->mFixedPosFrameForLayerData,
|
||||
data->mDrawRegion,
|
||||
&data->mVisibleRegion,
|
||||
&data->mIsSolidColorInVisibleRegion);
|
||||
|
||||
NewLayerEntry* newLayerEntry = &mNewChildLayers[data->mNewChildLayersIndex];
|
||||
nsRefPtr<Layer> layer;
|
||||
nsRefPtr<ImageContainer> imageContainer = data->CanOptimizeImageLayer(mBuilder);
|
||||
@ -2395,7 +2299,6 @@ PaintedLayerData::Accumulate(ContainerState* aState,
|
||||
nsDisplayItem* aItem,
|
||||
const nsIntRegion& aClippedOpaqueRegion,
|
||||
const nsIntRect& aVisibleRect,
|
||||
const nsIntRect& aDrawRect,
|
||||
const DisplayItemClip& aClip)
|
||||
{
|
||||
FLB_LOG_PAINTED_LAYER_DECISION(this, "Accumulating dp=%s(%p), f=%p against pld=%p\n", aItem->Name(), aItem, aItem->Frame(), this);
|
||||
@ -2417,17 +2320,16 @@ PaintedLayerData::Accumulate(ContainerState* aState,
|
||||
bool clipMatches = mItemClip == aClip;
|
||||
mItemClip = aClip;
|
||||
|
||||
if (!mIsSolidColorInVisibleRegion && mOpaqueRegion.Contains(aDrawRect) &&
|
||||
if (!mIsSolidColorInVisibleRegion && mOpaqueRegion.Contains(aVisibleRect) &&
|
||||
mVisibleRegion.Contains(aVisibleRect) && !mImage) {
|
||||
// A very common case! Most pages have a PaintedLayer with the page
|
||||
// background (opaque) visible and most or all of the page content over the
|
||||
// top of that background.
|
||||
// The rest of this method won't do anything. mVisibleRegion, mOpaqueRegion
|
||||
// and mDrawRegion don't need updating. mVisibleRegion contains aVisibleRect
|
||||
// already, mOpaqueRegion contains aDrawRect and therefore whatever
|
||||
// the opaque region of the item is. mDrawRegion must contain mOpaqueRegion
|
||||
// and therefore aDrawRect.
|
||||
NS_ASSERTION(mDrawRegion.Contains(aDrawRect), "Draw region not covered");
|
||||
// The rest of this method won't do anything. mVisibleRegion and mOpaqueRegion
|
||||
// don't need updating. mVisibleRegion contains aVisibleRect already,
|
||||
// mOpaqueRegion contains aVisibleRect and therefore whatever the opaque
|
||||
// region of the item is. mVisibleRegion must contain mOpaqueRegion
|
||||
// and therefore aVisibleRect.
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2492,9 +2394,6 @@ PaintedLayerData::Accumulate(ContainerState* aState,
|
||||
|
||||
mVisibleRegion.Or(mVisibleRegion, aVisibleRect);
|
||||
mVisibleRegion.SimplifyOutward(4);
|
||||
mDrawRegion.Or(mDrawRegion, mVisibleRegion);
|
||||
mDrawRegion.Or(mDrawRegion, aDrawRect);
|
||||
mDrawRegion.SimplifyOutward(4);
|
||||
}
|
||||
|
||||
if (!aClippedOpaqueRegion.IsEmpty()) {
|
||||
@ -2572,10 +2471,10 @@ ContainerState::FindPaintedLayerFor(nsDisplayItem* aItem,
|
||||
break;
|
||||
}
|
||||
PaintedLayerData* data = mPaintedLayerDataStack[i];
|
||||
// Give up if there is content drawn above (in z-order) this layer that
|
||||
// Give up if there is content visible above (in z-order) this layer that
|
||||
// intersects aItem's visible region; aItem must be placed in a
|
||||
// layer above this layer.
|
||||
if (data->DrawAboveRegionIntersects(aVisibleRect)) {
|
||||
if (data->VisibleAboveRegionIntersects(aVisibleRect)) {
|
||||
++i;
|
||||
break;
|
||||
}
|
||||
@ -2588,10 +2487,10 @@ ContainerState::FindPaintedLayerFor(nsDisplayItem* aItem,
|
||||
topmostLayerWithScrolledRoot = i;
|
||||
}
|
||||
}
|
||||
// If the layer's drawn region intersects the item, stop now since no
|
||||
// If the layer's visible region intersects the item, stop now since no
|
||||
// lower layer will be usable. Do the same if the layer is subject to
|
||||
// async transforms, since we don't know where it will really be drawn.
|
||||
if (data->DrawRegionIntersects(aVisibleRect))
|
||||
if (data->VisibleRegionIntersects(aVisibleRect))
|
||||
break;
|
||||
}
|
||||
if (topmostLayerWithScrolledRoot < 0) {
|
||||
@ -2911,8 +2810,6 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
|
||||
aList->SetNeedsTransparentSurface();
|
||||
}
|
||||
|
||||
nsIntRect itemVisibleRect =
|
||||
ScaleToOutsidePixels(item->GetVisibleRect(), false);
|
||||
bool snap;
|
||||
nsRect itemContent = item->GetBounds(mBuilder, &snap);
|
||||
if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) {
|
||||
@ -2944,7 +2841,11 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
|
||||
}
|
||||
((nsRect&)mAccumulatedChildBounds).UnionRect(mAccumulatedChildBounds, bounds);
|
||||
#endif
|
||||
itemVisibleRect.IntersectRect(itemVisibleRect, itemDrawRect);
|
||||
// We haven't computed visibility at this point, so item->GetVisibleRect()
|
||||
// is just the dirty rect that item was initialized with. We intersect it
|
||||
// with the clipped item bounds to get a tighter visible rect.
|
||||
nsIntRect itemVisibleRect = itemDrawRect.Intersect(
|
||||
ScaleToOutsidePixels(item->GetVisibleRect(), false));
|
||||
|
||||
LayerState layerState = item->GetLayerState(mBuilder, mManager, mParameters);
|
||||
if (layerState == LAYER_INACTIVE &&
|
||||
@ -3025,12 +2926,6 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
|
||||
|
||||
const nsIFrame* fixedPosFrame =
|
||||
FindFixedPosFrameForLayerData(animatedGeometryRoot, shouldFixToViewport);
|
||||
if (fixedPosFrame) {
|
||||
nsIntRegion visibleRegion(itemVisibleRect);
|
||||
AdjustLayerDataForFixedPositioning(fixedPosFrame,
|
||||
nsIntRegion(itemDrawRect), &visibleRegion);
|
||||
itemVisibleRect = visibleRegion.GetBounds();
|
||||
}
|
||||
SetFixedPositionLayerData(ownLayer, fixedPosFrame);
|
||||
|
||||
nsRect invalid;
|
||||
@ -3068,22 +2963,15 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
|
||||
if (!itemClip.HasClip()) {
|
||||
// The transform item can move anywhere, treat all other content
|
||||
// as being above this item.
|
||||
data->SetAllDrawingAbove();
|
||||
data->SetVisibleAboveRegionIsInfinite();
|
||||
} else {
|
||||
// The transform can't escape from the clip rect, and the clip
|
||||
// rect can't change without new layer building. Treat all content
|
||||
// that intersects the clip rect as being above this item.
|
||||
data->AddVisibleAboveRegion(clipRect);
|
||||
data->AddDrawAboveRegion(clipRect);
|
||||
}
|
||||
} else {
|
||||
data->AddVisibleAboveRegion(itemVisibleRect);
|
||||
|
||||
// Add the entire bounds rect to the mDrawAboveRegion.
|
||||
// The visible region may be excluding opaque content above the
|
||||
// item, and we need to ensure that that content is not placed
|
||||
// in a PaintedLayer below the item!
|
||||
data->AddDrawAboveRegion(itemDrawRect);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3174,8 +3062,10 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
|
||||
itemClip, aList,
|
||||
&paintedLayerData->mHideAllLayersBelow,
|
||||
&paintedLayerData->mOpaqueForAnimatedGeometryRootParent);
|
||||
MOZ_ASSERT(nsIntRegion(itemDrawRect).Contains(opaquePixels));
|
||||
opaquePixels.AndWith(itemVisibleRect);
|
||||
paintedLayerData->Accumulate(this, item, opaquePixels,
|
||||
itemVisibleRect, itemDrawRect, itemClip);
|
||||
itemVisibleRect, itemClip);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user