зеркало из https://github.com/mozilla/gecko-dev.git
Bug 579349. Track the 'drawn region' of content in layers, whhich ignores visibility, and use it to determine which layer a display item should be placed in. r=tnikkel
This commit is contained in:
Родитель
f348001399
Коммит
1524120859
|
@ -94,8 +94,8 @@ AppendToString(nsACString& s, const gfx3DMatrix& m,
|
|||
gfxMatrix matrix;
|
||||
if (m.Is2D(&matrix)) {
|
||||
s += nsPrintfCString(
|
||||
"[ %g %g; %g %g; %g %g; ]",
|
||||
96, matrix.xx, matrix.yx, matrix.xy, matrix.yy, matrix.x0, matrix.y0);
|
||||
96, "[ %g %g; %g %g; %g %g; ]",
|
||||
matrix.xx, matrix.yx, matrix.xy, matrix.yy, matrix.x0, matrix.y0);
|
||||
} else {
|
||||
s += nsPrintfCString(
|
||||
256, "[ %g %g %g %g; %g %g %g %g; %g %g %g %g; %g %g %g %g; ]",
|
||||
|
@ -218,10 +218,13 @@ Layer::PrintInfo(nsACString& aTo, const char* aPrefix)
|
|||
aTo += aPrefix;
|
||||
aTo += nsPrintfCString(64, "%s%s (0x%p)", mManager->Name(), Name(), this);
|
||||
|
||||
if (!mVisibleRegion.IsEmpty())
|
||||
AppendToString(aTo, mVisibleRegion, " [visible=", "]");
|
||||
if (mUseClipRect) {
|
||||
AppendToString(aTo, mClipRect, " [clip=", "]");
|
||||
}
|
||||
if (!mTransform.IsIdentity())
|
||||
AppendToString(aTo, mTransform, " [transform=", "]");
|
||||
if (!mVisibleRegion.IsEmpty())
|
||||
AppendToString(aTo, mVisibleRegion, " [visible=", "]");
|
||||
if (1.0 != mOpacity)
|
||||
aTo.AppendPrintf(" [opacity=%g]", mOpacity);
|
||||
if (IsOpaqueContent())
|
||||
|
@ -250,7 +253,9 @@ nsACString&
|
|||
CanvasLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
|
||||
{
|
||||
Layer::PrintInfo(aTo, aPrefix);
|
||||
AppendToString(aTo, mFilter, " [filter=", "]");
|
||||
if (mFilter != gfxPattern::FILTER_GOOD) {
|
||||
AppendToString(aTo, mFilter, " [filter=", "]");
|
||||
}
|
||||
return aTo;
|
||||
}
|
||||
|
||||
|
@ -258,7 +263,9 @@ nsACString&
|
|||
ImageLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
|
||||
{
|
||||
Layer::PrintInfo(aTo, aPrefix);
|
||||
AppendToString(aTo, mFilter, " [filter=", "]");
|
||||
if (mFilter != gfxPattern::FILTER_GOOD) {
|
||||
AppendToString(aTo, mFilter, " [filter=", "]");
|
||||
}
|
||||
return aTo;
|
||||
}
|
||||
|
||||
|
|
|
@ -152,6 +152,8 @@ protected:
|
|||
* Record that an item has been added to the ThebesLayer, 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
|
||||
|
@ -160,6 +162,7 @@ protected:
|
|||
* a constant color given by *aSolidColor
|
||||
*/
|
||||
void Accumulate(const nsIntRect& aVisibleRect,
|
||||
const nsIntRect& aDrawRect,
|
||||
const nsIntRect* aOpaqueRect,
|
||||
nscolor* aSolidColor);
|
||||
nsIFrame* GetActiveScrolledRoot() { return mActiveScrolledRoot; }
|
||||
|
@ -177,6 +180,21 @@ protected:
|
|||
* Same coordinate system as mVisibleRegion.
|
||||
*/
|
||||
nsIntRegion mVisibleAboveRegion;
|
||||
/**
|
||||
* The region containing the bounds of all display items in the layer,
|
||||
* regardless of visbility.
|
||||
* Same coordinate system as mVisibleRegion.
|
||||
*/
|
||||
nsIntRegion mDrawRegion;
|
||||
/**
|
||||
* The region containing the bounds of all display items (regardless
|
||||
* of visibility) in the layer and below the next ThebesLayerData
|
||||
* currently in the stack, if any.
|
||||
* Note that not all ThebesLayers for the container are in the
|
||||
* ThebesLayerData stack.
|
||||
* Same coordinate system as mVisibleRegion.
|
||||
*/
|
||||
nsIntRegion mDrawAboveRegion;
|
||||
/**
|
||||
* The region of visible content in the layer that is opaque.
|
||||
* Same coordinate system as mVisibleRegion.
|
||||
|
@ -231,10 +249,14 @@ protected:
|
|||
void PopThebesLayerData();
|
||||
/**
|
||||
* Find the ThebesLayer to which we should assign the next display item.
|
||||
* We scan the ThebesLayerData stack to find the topmost ThebesLayer
|
||||
* that is compatible with the display item (i.e., has the same
|
||||
* active scrolled root), and that has no content from other layers above
|
||||
* it and intersecting the aVisibleRect.
|
||||
* Returns the layer, and also updates the ThebesLayerData. Will
|
||||
* push a new ThebesLayerData onto the stack if necessary. If we choose
|
||||
* a ThebesLayer that's already on the ThebesLayerData stack,
|
||||
* later elements on the stack will be popped off.
|
||||
* push a new ThebesLayerData onto the stack if no suitable existing
|
||||
* layer is found. If we choose a ThebesLayer that's already on the
|
||||
* ThebesLayerData stack, later elements on the stack will be popped off.
|
||||
* @param aVisibleRect the area of the next display item that's visible
|
||||
* @param aActiveScrolledRoot the active scrolled root for the next
|
||||
* display item
|
||||
|
@ -243,6 +265,7 @@ protected:
|
|||
* will be painted with aSolidColor by the item
|
||||
*/
|
||||
already_AddRefed<ThebesLayer> FindThebesLayerFor(const nsIntRect& aVisibleRect,
|
||||
const nsIntRect& aDrawRect,
|
||||
nsIFrame* aActiveScrolledRoot,
|
||||
const nsIntRect* aOpaqueRect,
|
||||
nscolor* aSolidColor);
|
||||
|
@ -674,6 +697,10 @@ ContainerState::PopThebesLayerData()
|
|||
data->mVisibleAboveRegion);
|
||||
nextData->mVisibleAboveRegion.Or(nextData->mVisibleAboveRegion,
|
||||
data->mVisibleRegion);
|
||||
nextData->mDrawAboveRegion.Or(nextData->mDrawAboveRegion,
|
||||
data->mDrawAboveRegion);
|
||||
nextData->mDrawAboveRegion.Or(nextData->mDrawAboveRegion,
|
||||
data->mDrawRegion);
|
||||
}
|
||||
|
||||
Layer* layer;
|
||||
|
@ -728,7 +755,8 @@ ContainerState::PopThebesLayerData()
|
|||
}
|
||||
|
||||
void
|
||||
ContainerState::ThebesLayerData::Accumulate(const nsIntRect& aRect,
|
||||
ContainerState::ThebesLayerData::Accumulate(const nsIntRect& aVisibleRect,
|
||||
const nsIntRect& aDrawRect,
|
||||
const nsIntRect* aOpaqueRect,
|
||||
nscolor* aSolidColor)
|
||||
{
|
||||
|
@ -738,7 +766,7 @@ ContainerState::ThebesLayerData::Accumulate(const nsIntRect& aRect,
|
|||
mSolidColor = *aSolidColor;
|
||||
mIsSolidColorInVisibleRegion = PR_TRUE;
|
||||
} else if (mIsSolidColorInVisibleRegion &&
|
||||
mVisibleRegion.IsEqual(nsIntRegion(aRect))) {
|
||||
mVisibleRegion.IsEqual(nsIntRegion(aVisibleRect))) {
|
||||
// we can just blend the colors together
|
||||
mSolidColor = NS_ComposeColors(mSolidColor, *aSolidColor);
|
||||
} else {
|
||||
|
@ -748,8 +776,10 @@ ContainerState::ThebesLayerData::Accumulate(const nsIntRect& aRect,
|
|||
mIsSolidColorInVisibleRegion = PR_FALSE;
|
||||
}
|
||||
|
||||
mVisibleRegion.Or(mVisibleRegion, aRect);
|
||||
mVisibleRegion.Or(mVisibleRegion, aVisibleRect);
|
||||
mVisibleRegion.SimplifyOutward(4);
|
||||
mDrawRegion.Or(mDrawRegion, aDrawRect);
|
||||
mDrawRegion.SimplifyOutward(4);
|
||||
if (aOpaqueRect) {
|
||||
// We don't use SimplifyInward here since it's not defined exactly
|
||||
// what it will discard. For our purposes the most important case
|
||||
|
@ -766,6 +796,7 @@ ContainerState::ThebesLayerData::Accumulate(const nsIntRect& aRect,
|
|||
|
||||
already_AddRefed<ThebesLayer>
|
||||
ContainerState::FindThebesLayerFor(const nsIntRect& aVisibleRect,
|
||||
const nsIntRect& aDrawRect,
|
||||
nsIFrame* aActiveScrolledRoot,
|
||||
const nsIntRect* aOpaqueRect,
|
||||
nscolor* aSolidColor)
|
||||
|
@ -775,7 +806,7 @@ ContainerState::FindThebesLayerFor(const nsIntRect& aVisibleRect,
|
|||
PRInt32 topmostLayerWithScrolledRoot = -1;
|
||||
for (i = mThebesLayerDataStack.Length() - 1; i >= 0; --i) {
|
||||
ThebesLayerData* data = mThebesLayerDataStack[i];
|
||||
if (data->mVisibleAboveRegion.Intersects(aVisibleRect)) {
|
||||
if (data->mDrawAboveRegion.Intersects(aVisibleRect)) {
|
||||
++i;
|
||||
break;
|
||||
}
|
||||
|
@ -785,7 +816,7 @@ ContainerState::FindThebesLayerFor(const nsIntRect& aVisibleRect,
|
|||
topmostLayerWithScrolledRoot = i;
|
||||
}
|
||||
}
|
||||
if (data->mVisibleRegion.Intersects(aVisibleRect))
|
||||
if (data->mDrawRegion.Intersects(aVisibleRect))
|
||||
break;
|
||||
}
|
||||
if (topmostLayerWithScrolledRoot < 0) {
|
||||
|
@ -822,7 +853,7 @@ ContainerState::FindThebesLayerFor(const nsIntRect& aVisibleRect,
|
|||
layer = thebesLayerData->mLayer;
|
||||
}
|
||||
|
||||
thebesLayerData->Accumulate(aVisibleRect, aOpaqueRect, aSolidColor);
|
||||
thebesLayerData->Accumulate(aVisibleRect, aDrawRect, aOpaqueRect, aSolidColor);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
|
@ -857,6 +888,11 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
|
|||
PRInt32 appUnitsPerDevPixel = AppUnitsPerDevPixel(item);
|
||||
nsIntRect itemVisibleRect =
|
||||
item->GetVisibleRect().ToNearestPixels(appUnitsPerDevPixel);
|
||||
nsRect itemContent = item->GetBounds(mBuilder);
|
||||
if (aClipRect) {
|
||||
itemContent.IntersectRect(*aClipRect, itemContent);
|
||||
}
|
||||
nsIntRect itemDrawRect = itemContent.ToNearestPixels(appUnitsPerDevPixel);
|
||||
nsDisplayItem::LayerState layerState =
|
||||
item->GetLayerState(mBuilder, mManager);
|
||||
|
||||
|
@ -890,6 +926,11 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
|
|||
ThebesLayerData* data = GetTopThebesLayerData();
|
||||
if (data) {
|
||||
data->mVisibleAboveRegion.Or(data->mVisibleAboveRegion, 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 ThebesLayer below the item!
|
||||
data->mDrawAboveRegion.Or(data->mDrawAboveRegion, itemDrawRect);
|
||||
}
|
||||
SetVisibleRectForLayer(ownLayer, itemVisibleRect);
|
||||
ContainerLayer* oldContainer = ownLayer->GetParent();
|
||||
|
@ -932,7 +973,7 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
|
|||
opaqueRect = item->GetBounds(mBuilder).ToNearestPixels(appUnitsPerDevPixel);
|
||||
}
|
||||
nsRefPtr<ThebesLayer> thebesLayer =
|
||||
FindThebesLayerFor(itemVisibleRect, activeScrolledRoot,
|
||||
FindThebesLayerFor(itemVisibleRect, itemDrawRect, activeScrolledRoot,
|
||||
isOpaque ? &opaqueRect : nsnull,
|
||||
isUniform ? &uniformColor : nsnull);
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<div style="width:500px; height:500px; background:blue;"></div>
|
||||
<div style="position:absolute; left:0; top:0; height:100px; width:100%; background:yellow"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<canvas id="c" width="500" height="200"></canvas>
|
||||
<div style="position:absolute; left:0; top:0; height:100px; width:100%; background:yellow"></div>
|
||||
<script>
|
||||
var c = document.getElementById("c");
|
||||
var ctx = c.getContext("2d");
|
||||
ctx.fillStyle = "blue;";
|
||||
ctx.fillRect(0, 0, c.width, c.height);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1459,3 +1459,4 @@ random-if(!haveTestPlugin) == 546071-1.html 546071-1-ref.html
|
|||
== 571347-3.html 571347-3-ref.html
|
||||
== 572598-1.html 572598-ref.html
|
||||
== 574898-1.html 574898-ref.html
|
||||
== 579349-1.html 579349-1-ref.html
|
||||
|
|
Загрузка…
Ссылка в новой задаче