Bug 1169502 - Simplify visible regions to tiles, not to a number of rects. r=jrmuizel, r=roc

--HG--
extra : rebase_source : affd6655b864223cb1bb2ffe6e47a4759fd6b411
This commit is contained in:
Markus Stange 2015-06-10 15:54:20 -04:00
Родитель dc2a5c02ef
Коммит 1a786425ca
5 изменённых файлов: 103 добавлений и 38 удалений

Просмотреть файл

@ -51,6 +51,53 @@ class PaintedDisplayItemLayerUserData;
static nsTHashtable<nsPtrHashKey<FrameLayerBuilder::DisplayItemData>>* sAliveDisplayItemDatas;
static const nsIntSize kRegionTileSize(128, 128);
/**
* An alternative to nsIntRegion that keeps the region simple by snapping all
* accumulated rects outwards to tiles. It keeps track of the bounds of the
* true unsimplified region so that the result still has the bounds you'd
* expect.
* This approach doesn't guarantee a maximum number of rectangles in the
* region, but it has the advantage that region simplification doesn't merge
* rectangles that are very far apart; the simplification impact is local.
* This representation also has the property of being canonical: the result
* is independent of the order in which the rectangles are added.
*/
struct nsIntRegionSimplifiedToTiles
{
nsIntRegionSimplifiedToTiles(const nsIntPoint& aTileOrigin,
const nsIntSize& aTileSize)
: mTileOrigin(aTileOrigin)
, mTileSize(aTileSize)
{}
nsIntRegion Get() const { return mRegion.Intersect(mBounds); }
void Accumulate(const nsIntRect& aRect)
{
mBounds = mBounds.Union(aRect);
nsIntRect rect = aRect - mTileOrigin;
rect.InflateToMultiple(mTileSize);
mRegion.OrWith(rect + mTileOrigin);
}
bool IsEmpty() const { return mBounds.IsEmpty(); }
void SetEmpty()
{ mRegion.SetEmpty(); mBounds.SetEmpty(); }
nsIntRegion Intersect(const nsIntRegion& aRegion) const
{ return Get().Intersect(aRegion); }
bool Intersects(const nsIntRect& aRect) const
{ return mRegion.Intersects(mBounds.Intersect(aRect)); }
nsIntRect GetBounds() const { return mBounds; }
private:
nsIntRegion mRegion;
nsIntRect mBounds;
nsIntPoint mTileOrigin;
nsIntSize mTileSize;
};
FrameLayerBuilder::DisplayItemData::DisplayItemData(LayerManagerData* aParent, uint32_t aKey,
Layer* aLayer, nsIFrame* aFrame)
@ -286,8 +333,12 @@ struct AssignedDisplayItem
*/
class PaintedLayerData {
public:
PaintedLayerData() :
mAnimatedGeometryRoot(nullptr),
PaintedLayerData(const nsIFrame* aAnimatedGeometryRoot,
const nsPoint& aTopLeft,
const nsIntPoint& aSnappedOffset) :
mVisibleRegion(aSnappedOffset, kRegionTileSize),
mAnimatedGeometryRoot(aAnimatedGeometryRoot),
mAnimatedGeometryRootOffset(aTopLeft),
mFixedPosFrameForLayerData(nullptr),
mReferenceFrame(nullptr),
mLayer(nullptr),
@ -300,7 +351,8 @@ public:
mOpaqueForAnimatedGeometryRootParent(false),
mImage(nullptr),
mCommonClipCount(-1),
mNewChildLayersIndex(-1)
mNewChildLayersIndex(-1),
mVisibleAboveRegion(aSnappedOffset, kRegionTileSize)
{}
#ifdef MOZ_DUMP_PAINTING
@ -377,7 +429,7 @@ public:
* container layer (which is at the snapped top-left of the display
* list reference frame).
*/
nsIntRegion mVisibleRegion;
nsIntRegionSimplifiedToTiles mVisibleRegion;
/**
* The region of visible content in the layer that is opaque.
* Same coordinate system as mVisibleRegion.
@ -518,7 +570,7 @@ public:
* next PaintedLayerData currently in the stack, if any.
* This is a conservative approximation: it contains the true region.
*/
nsIntRegion mVisibleAboveRegion;
nsIntRegionSimplifiedToTiles mVisibleAboveRegion;
/**
* All the display items that have been assigned to this painted layer.
* These items get added by Accumulate().
@ -595,7 +647,8 @@ class PaintedLayerDataNode {
public:
PaintedLayerDataNode(PaintedLayerDataTree& aTree,
PaintedLayerDataNode* aParent,
const nsIFrame* aAnimatedGeometryRoot);
const nsIFrame* aAnimatedGeometryRoot,
const nsIntPoint& aSnappedOffset);
~PaintedLayerDataNode();
const nsIFrame* AnimatedGeometryRoot() const { return mAnimatedGeometryRoot; }
@ -693,6 +746,7 @@ protected:
PaintedLayerDataTree& mTree;
PaintedLayerDataNode* mParent;
const nsIFrame* mAnimatedGeometryRoot;
const nsIntPoint mSnappedAnimatedGeometryRootOffset;
/**
* Our contents: a PaintedLayerData stack and our child nodes.
@ -718,7 +772,7 @@ protected:
* should be considered infinite, mAllDrawingAboveBackground will be true and
* the value of mVisibleAboveBackgroundRegion will be meaningless.
*/
nsIntRegion mVisibleAboveBackgroundRegion;
nsIntRegionSimplifiedToTiles mVisibleAboveBackgroundRegion;
/**
* Our clip, if we have any. If not, that means we can move anywhere, and
@ -988,9 +1042,20 @@ public:
mAppUnitsPerDevPixel);
}
nsIntPoint SnapPointToPixels(const nsPoint& aPoint) const
{
return aPoint.ScaleToNearestPixels(mParameters.mXScale, mParameters.mYScale,
mAppUnitsPerDevPixel);
}
nsIFrame* GetContainerFrame() const { return mContainerFrame; }
nsDisplayListBuilder* Builder() const { return mBuilder; }
nsIntPoint GetSnappedOffsetToContainerReferenceFrame(const nsIFrame* aFrame)
{
return SnapPointToPixels(aFrame->GetOffsetToCrossDoc(mContainerReferenceFrame));
}
/**
* Sets aOuterVisibleRegion as aLayer's visible region. aOuterVisibleRegion
* is in the coordinate space of the container reference frame.
@ -2498,10 +2563,12 @@ PaintedLayerData::GetContainerForImageLayer(nsDisplayListBuilder* aBuilder)
PaintedLayerDataNode::PaintedLayerDataNode(PaintedLayerDataTree& aTree,
PaintedLayerDataNode* aParent,
const nsIFrame* aAnimatedGeometryRoot)
const nsIFrame* aAnimatedGeometryRoot,
const nsIntPoint& aSnappedOffset)
: mTree(aTree)
, mParent(aParent)
, mAnimatedGeometryRoot(aAnimatedGeometryRoot)
, mVisibleAboveBackgroundRegion(aSnappedOffset, kRegionTileSize)
, mAllDrawingAboveBackground(false)
{
MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(mTree.Builder()->RootReferenceFrame(), mAnimatedGeometryRoot));
@ -2518,8 +2585,9 @@ PaintedLayerDataNode*
PaintedLayerDataNode::AddChildNodeFor(const nsIFrame* aAnimatedGeometryRoot)
{
MOZ_ASSERT(mTree.GetParentAnimatedGeometryRoot(aAnimatedGeometryRoot) == mAnimatedGeometryRoot);
nsIntPoint snappedOffset = mTree.ContState().GetSnappedOffsetToContainerReferenceFrame(aAnimatedGeometryRoot);
UniquePtr<PaintedLayerDataNode> child =
MakeUnique<PaintedLayerDataNode>(mTree, this, aAnimatedGeometryRoot);
MakeUnique<PaintedLayerDataNode>(mTree, this, aAnimatedGeometryRoot, snappedOffset);
mChildren.AppendElement(Move(child));
return mChildren.LastElement().get();
}
@ -2595,11 +2663,10 @@ PaintedLayerDataNode::Finish(bool aParentNeedsAccurateVisibleAboveRegion)
void
PaintedLayerDataNode::AddToVisibleAboveRegion(const nsIntRect& aRect)
{
nsIntRegion& visibleAboveRegion = mPaintedLayerDataStack.IsEmpty()
nsIntRegionSimplifiedToTiles& visibleAboveRegion = mPaintedLayerDataStack.IsEmpty()
? mVisibleAboveBackgroundRegion
: mPaintedLayerDataStack.LastElement().mVisibleAboveRegion;
visibleAboveRegion.Or(visibleAboveRegion, aRect);
visibleAboveRegion.SimplifyOutward(8);
visibleAboveRegion.Accumulate(aRect);
}
void
@ -2617,7 +2684,7 @@ PaintedLayerDataNode::PopPaintedLayerData()
size_t lastIndex = mPaintedLayerDataStack.Length() - 1;
PaintedLayerData& data = mPaintedLayerDataStack[lastIndex];
mTree.ContState().FinishPaintedLayerData(data, [this, &data, lastIndex]() {
return this->FindOpaqueBackgroundColor(data.mVisibleRegion, lastIndex);
return this->FindOpaqueBackgroundColor(data.mVisibleRegion.Get(), lastIndex);
});
mPaintedLayerDataStack.RemoveElementAt(lastIndex);
}
@ -2774,7 +2841,8 @@ PaintedLayerDataTree::EnsureNodeFor(const nsIFrame* aAnimatedGeometryRoot)
if (!parentAnimatedGeometryRoot) {
MOZ_ASSERT(!mRoot);
MOZ_ASSERT(aAnimatedGeometryRoot == Builder()->RootReferenceFrame());
mRoot = MakeUnique<PaintedLayerDataNode>(*this, nullptr, aAnimatedGeometryRoot);
nsIntPoint snappedOffset = ContState().GetSnappedOffsetToContainerReferenceFrame(aAnimatedGeometryRoot);
mRoot = MakeUnique<PaintedLayerDataNode>(*this, nullptr, aAnimatedGeometryRoot, snappedOffset);
node = mRoot.get();
} else {
PaintedLayerDataNode* parentNode = EnsureNodeFor(parentAnimatedGeometryRoot);
@ -3045,12 +3113,12 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB
}
if (mLayerBuilder->IsBuildingRetainedLayers()) {
newLayerEntry->mVisibleRegion = data->mVisibleRegion;
newLayerEntry->mVisibleRegion = data->mVisibleRegion.Get();
newLayerEntry->mOpaqueRegion = data->mOpaqueRegion;
newLayerEntry->mHideAllLayersBelow = data->mHideAllLayersBelow;
newLayerEntry->mOpaqueForAnimatedGeometryRootParent = data->mOpaqueForAnimatedGeometryRootParent;
} else {
SetOuterVisibleRegionForLayer(layer, data->mVisibleRegion);
SetOuterVisibleRegionForLayer(layer, data->mVisibleRegion.Get());
}
nsIntRect layerBounds = data->mBounds;
@ -3068,7 +3136,7 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB
#endif
nsIntRegion transparentRegion;
transparentRegion.Sub(data->mVisibleRegion, data->mOpaqueRegion);
transparentRegion.Sub(data->mVisibleRegion.Get(), data->mOpaqueRegion);
bool isOpaque = transparentRegion.IsEmpty();
// For translucent PaintedLayers, try to find an opaque background
// color that covers the entire area beneath it so we can pull that
@ -3108,14 +3176,14 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB
// 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, data->mVisibleRegion, commonClipCount);
SetupMaskLayer(layer, data->mItemClip, data->mVisibleRegion.Get(), commonClipCount);
// copy commonClipCount to the entry
FrameLayerBuilder::PaintedLayerItemsEntry* entry = mLayerBuilder->
GetPaintedLayerItemsEntry(static_cast<PaintedLayer*>(layer.get()));
entry->mCommonClipCount = commonClipCount;
} else {
// mask layer for image and color layers
SetupMaskLayer(layer, data->mItemClip, data->mVisibleRegion);
SetupMaskLayer(layer, data->mItemClip, data->mVisibleRegion.Get());
}
uint32_t flags = 0;
@ -3251,7 +3319,7 @@ PaintedLayerData::Accumulate(ContainerState* aState,
mAssignedDisplayItems.AppendElement(AssignedDisplayItem(aItem, aClip, aLayerState));
if (!mIsSolidColorInVisibleRegion && mOpaqueRegion.Contains(aVisibleRect) &&
mVisibleRegion.Contains(aVisibleRect) && !mImage) {
mVisibleRegion.Get().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.
@ -3266,8 +3334,8 @@ PaintedLayerData::Accumulate(ContainerState* aState,
/* Mark as available for conversion to image layer if this is a nsDisplayImage and
* it's the only thing visible in this layer.
*/
if (nsIntRegion(aVisibleRect).Contains(mVisibleRegion) &&
aClippedOpaqueRegion.Contains(mVisibleRegion) &&
if (nsIntRegion(aVisibleRect).Contains(mVisibleRegion.Get()) &&
aClippedOpaqueRegion.Contains(mVisibleRegion.Get()) &&
aItem->SupportsOptimizingToImage()) {
mImage = static_cast<nsDisplayImageContainer*>(aItem);
FLB_LOG_PAINTED_LAYER_DECISION(this, " Tracking image: nsDisplayImageContainer covers the layer\n");
@ -3309,7 +3377,7 @@ PaintedLayerData::Accumulate(ContainerState* aState,
mSolidColor = uniformColor;
mIsSolidColorInVisibleRegion = true;
} else if (mIsSolidColorInVisibleRegion &&
mVisibleRegion.IsEqual(nsIntRegion(aVisibleRect)) &&
mVisibleRegion.Get().IsEqual(nsIntRegion(aVisibleRect)) &&
clipMatches) {
// we can just blend the colors together
mSolidColor = NS_ComposeColors(mSolidColor, uniformColor);
@ -3322,8 +3390,7 @@ PaintedLayerData::Accumulate(ContainerState* aState,
mIsSolidColorInVisibleRegion = false;
}
mVisibleRegion.Or(mVisibleRegion, aVisibleRect);
mVisibleRegion.SimplifyOutward(4);
mVisibleRegion.Accumulate(aVisibleRect);
}
if (!aClippedOpaqueRegion.IsEmpty()) {
@ -3369,9 +3436,7 @@ ContainerState::NewPaintedLayerData(nsDisplayItem* aItem,
const nsPoint& aTopLeft,
bool aShouldFixToViewport)
{
PaintedLayerData data;
data.mAnimatedGeometryRoot = aAnimatedGeometryRoot;
data.mAnimatedGeometryRootOffset = aTopLeft;
PaintedLayerData data(aAnimatedGeometryRoot, aTopLeft, SnapPointToPixels(aTopLeft));
data.mFixedPosFrameForLayerData =
FindFixedPosFrameForLayerData(aAnimatedGeometryRoot, aShouldFixToViewport);
data.mReferenceFrame = aItem->ReferenceFrame();

Просмотреть файл

@ -425,7 +425,7 @@ skip-if((B2G&&browserIsRemote)||Mulet) == 321402-6.xul 321402-6-ref.xul # bug 97
== 323656-4.html 323656-4-ref.html
== 323656-5.svg 323656-5-ref.svg
== 323656-6.html 323656-6-ref.html
fuzzy-if(Android,2,140) == 325292-1.html 325292-1-ref.html
fuzzy-if(Android,5,283) == 325292-1.html 325292-1-ref.html
== 325486-1.html 325486-1-ref.html
== 328111-1.html 328111-1-ref.html
random == 328829-1.xhtml 328829-1-ref.xhtml # bug 369046 (intermittent)
@ -695,7 +695,7 @@ skip-if(B2G||Mulet) fails-if(Android) random-if(cocoaWidget) random-if(/^Windows
== 379349-1c.xhtml 379349-1-ref.xhtml
== 379349-2a.xhtml 379349-2-ref.xhtml
== 379349-2b.xhtml 379349-2-ref.xhtml
skip-if(B2G||Mulet) fuzzy-if(Android,2,140) == 379349-3a.xhtml 379349-3-ref.xhtml # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fuzzy-if(Android,5,283) == 379349-3a.xhtml 379349-3-ref.xhtml # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fuzzy-if(Android,2,140) == 379349-3b.xhtml 379349-3-ref.xhtml # Initial mulet triage: parity with B2G/B2G Desktop
== 379361-1.html 379361-1-ref.html
== 379361-2.html 379361-2-ref.html
@ -1404,7 +1404,7 @@ skip-if(B2G||Mulet) == 502447-1.html 502447-1-ref.html # Initial mulet triage: p
needs-focus fails == 503531-1.html 503531-1-ref.html
== 504032-1.html 504032-1-ref.html
== 505743-1.html about:blank
skip-if(B2G||Mulet) fuzzy-if(Android,5,2800) == 506481-1.html 506481-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fuzzy-if(Android,5,2806) == 506481-1.html 506481-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
== 507187-1.html 507187-1-ref.html
== 507487-1.html 507487-1-ref.html
== 507487-2.xhtml 507487-2-ref.xhtml
@ -1417,7 +1417,7 @@ skip-if(B2G||Mulet) == 508816-2.html 508816-2-ref.html # Initial mulet triage: p
skip-if((B2G&&browserIsRemote)||Mulet) == 508908-1.xul 508908-1-ref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop
== 508919-1.xhtml 508919-1-ref.xhtml
== 509155-1.xhtml 509155-1-ref.xhtml
skip-if(B2G||Mulet) fuzzy-if(Android,5,1656) == 512410.html 512410-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fuzzy-if(Android,5,2555) == 512410.html 512410-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
== 512631-1.html 512631-1-ref.html
== 513153-1a.html 513153-1-ref.html
== 513153-1b.html 513153-1-ref.html
@ -1658,9 +1658,9 @@ skip-if(Android||B2G||Mulet) random-if(winWidget) == 632781-verybig.html 632781-
fuzzy-if(d2d&&/^Windows\x20NT\x206\.2/.test(http.oscpu),1,559) == 633344-1.html 633344-1-ref.html # bug 1103623
== 634232-1.html 634232-1-ref.html
fails-if(Android&&AndroidVersion<17&&AndroidVersion!=10) == 635302-1.html 635302-1-ref.html
fuzzy(1,68) skip-if(B2G||Mulet) fails-if(Android) == 635373-1.html 635373-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) random-if(d2d) fails-if(Android) fuzzy-if(winWidget&&!d2d,1,61) == 635373-2.html 635373-2-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) random-if(d2d) fails-if(Android) fuzzy-if(winWidget&&!d2d,1,60) == 635373-3.html 635373-3-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
fuzzy(1,68) skip-if(B2G||Mulet) == 635373-1.html 635373-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) random-if(d2d) fuzzy-if(winWidget&&!d2d,1,61) == 635373-2.html 635373-2-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) random-if(d2d) fuzzy-if(winWidget&&!d2d,1,60) == 635373-3.html 635373-3-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
HTTP(..) == 635639-1.html 635639-1-ref.html
HTTP(..) == 635639-2.html 635639-2-ref.html
random == 637597-1.html 637597-1-ref.html # bug 637597 was never really fixed!

Просмотреть файл

@ -4,7 +4,7 @@ fuzzy-if(Android,16,244) skip-if(B2G||Mulet) HTTP(..) == marker-basic.html marke
skip-if(B2G||Mulet) HTTP(..) == marker-string.html marker-string-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(Android||B2G) HTTP(..) == bidi-simple.html bidi-simple-ref.html # Fails on Android due to anti-aliasing
skip-if(!gtkWidget) fuzzy-if(gtkWidget,1,104) HTTP(..) == bidi-simple-scrolled.html bidi-simple-scrolled-ref.html # Fails on Windows and OSX due to anti-aliasing
skip-if(B2G||Mulet) fuzzy-if(Android&&AndroidVersion<15,9,2545) fuzzy-if(Android&&AndroidVersion>=15,24,4000) fuzzy-if(cocoaWidget,1,40) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,1770) HTTP(..) == scroll-rounding.html scroll-rounding-ref.html # bug 760264 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fuzzy-if(Android&&AndroidVersion<15,9,2545) fuzzy-if(Android&&AndroidVersion>=15,24,4000) fuzzy-if(cocoaWidget,1,40) fuzzy-if(!layersGPUAccelerated,102,2070) HTTP(..) == scroll-rounding.html scroll-rounding-ref.html # bug 760264 # Initial mulet triage: parity with B2G/B2G Desktop
fuzzy-if(OSX==1008,1,1) HTTP(..) == anonymous-block.html anonymous-block-ref.html
skip-if(B2G||Mulet) HTTP(..) == false-marker-overlap.html false-marker-overlap-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
HTTP(..) == visibility-hidden.html visibility-hidden-ref.html

Просмотреть файл

@ -11,7 +11,7 @@
== rotatex-perspective-1c.html rotatex-1-ref.html
== rotatex-perspective-3a.html rotatex-perspective-3-ref.html
== scalez-1a.html scalez-1-ref.html
fuzzy-if(cocoaWidget,17,3) == preserve3d-1a.html preserve3d-1-ref.html
fuzzy-if(cocoaWidget,17,3) fuzzy-if(!layersGPUAccelerated,102,243) == preserve3d-1a.html preserve3d-1-ref.html
== preserve3d-1b.html about:blank
== preserve3d-clipped.html about:blank
== preserve3d-2a.html preserve3d-2-ref.html

Просмотреть файл

@ -68,7 +68,7 @@ fuzzy-if(Android,158,32) == flexbox-align-self-vert-rtl-001.xhtml flexbox-align
== flexbox-basic-img-vert-001.xhtml flexbox-basic-img-vert-001-ref.xhtml
== flexbox-basic-textarea-horiz-001.xhtml flexbox-basic-textarea-horiz-001-ref.xhtml
== flexbox-basic-textarea-vert-001.xhtml flexbox-basic-textarea-vert-001-ref.xhtml
== flexbox-basic-video-horiz-001.xhtml flexbox-basic-video-horiz-001-ref.xhtml
fuzzy-if(cocoaWidget,1,300) == flexbox-basic-video-horiz-001.xhtml flexbox-basic-video-horiz-001-ref.xhtml
== flexbox-basic-video-vert-001.xhtml flexbox-basic-video-vert-001-ref.xhtml
# Tests for "page-break-before" / "page-break-after" on a flex item