Bug 805197 - Compute a region in LayerTreeInvalidation. r=roc

This commit is contained in:
Matt Woodrow
2012-11-12 10:31:15 -08:00
parent 3d2b337338
commit b49cb3820a
5 changed files with 67 additions and 40 deletions

View File

@@ -14,7 +14,7 @@ namespace layers {
struct LayerPropertiesBase;
LayerPropertiesBase* CloneLayerTreePropertiesInternal(Layer* aRoot);
static nsIntRect
static nsIntRect
TransformRect(const nsIntRect& aRect, const gfx3DMatrix& aTransform)
{
if (aRect.IsEmpty()) {
@@ -33,6 +33,32 @@ TransformRect(const nsIntRect& aRect, const gfx3DMatrix& aTransform)
return intRect;
}
static void
AddTransformedRegion(nsIntRegion& aDest, const nsIntRegion& aSource, const gfx3DMatrix& aTransform)
{
nsIntRegionRectIterator iter(aSource);
const nsIntRect *r;
while ((r = iter.Next())) {
aDest.Or(aDest, TransformRect(*r, aTransform));
}
aDest.SimplifyOutward(4);
}
static void
AddRegion(nsIntRegion& aDest, const nsIntRegion& aSource)
{
aDest.Or(aDest, aSource);
aDest.SimplifyOutward(4);
}
static nsIntRegion
TransformRegion(const nsIntRegion& aRegion, const gfx3DMatrix& aTransform)
{
nsIntRegion result;
AddTransformedRegion(result, aRegion, aTransform);
return result;
}
/**
* Walks over this layer, and all descendant layers.
* If any of these are a ContainerLayer that reports invalidations to a PresShell,
@@ -88,17 +114,17 @@ struct LayerPropertiesBase : public LayerProperties
MOZ_COUNT_DTOR(LayerPropertiesBase);
}
virtual nsIntRect ComputeDifferences(Layer* aRoot,
NotifySubDocInvalidationFunc aCallback);
virtual nsIntRegion ComputeDifferences(Layer* aRoot,
NotifySubDocInvalidationFunc aCallback);
virtual void MoveBy(const nsIntPoint& aOffset);
nsIntRect ComputeChange(NotifySubDocInvalidationFunc aCallback)
nsIntRegion ComputeChange(NotifySubDocInvalidationFunc aCallback)
{
bool transformChanged = !mTransform.FuzzyEqual(mLayer->GetTransform());
Layer* otherMask = mLayer->GetMaskLayer();
const nsIntRect* otherClip = mLayer->GetClipRect();
nsIntRect result;
nsIntRegion result;
if ((mMaskLayer ? mMaskLayer->mLayer : nullptr) != otherMask ||
(mUseClipRect != !!otherClip) ||
mLayer->GetOpacity() != mOpacity ||
@@ -106,7 +132,7 @@ struct LayerPropertiesBase : public LayerProperties
{
result = OldTransformedBounds();
if (transformChanged) {
result = result.Union(NewTransformedBounds());
AddRegion(result, NewTransformedBounds());
}
// If we don't have to generate invalidations separately for child
@@ -120,21 +146,20 @@ struct LayerPropertiesBase : public LayerProperties
nsIntRegion visible;
visible.Xor(mVisibleRegion, mLayer->GetVisibleRegion());
result = result.Union(TransformRect(visible.GetBounds(), mTransform));
AddTransformedRegion(result, visible, mTransform);
result = result.Union(ComputeChangeInternal(aCallback));
result = result.Union(TransformRect(mLayer->GetInvalidRegion().GetBounds(), mTransform));
AddRegion(result, ComputeChangeInternal(aCallback));
AddTransformedRegion(result, mLayer->GetInvalidRegion().GetBounds(), mTransform);
if (mMaskLayer && otherMask) {
nsIntRect maskDiff = mMaskLayer->ComputeChange(aCallback);
result = result.Union(TransformRect(maskDiff, mTransform));
AddTransformedRegion(result, mMaskLayer->ComputeChange(aCallback), mTransform);
}
if (mUseClipRect && otherClip) {
if (!mClipRect.IsEqualInterior(*otherClip)) {
nsIntRegion tmp;
tmp.Xor(mClipRect, *otherClip);
result = result.Union(tmp.GetBounds());
AddRegion(result, tmp);
}
}
@@ -152,7 +177,7 @@ struct LayerPropertiesBase : public LayerProperties
return TransformRect(mVisibleRegion.GetBounds(), mTransform);
}
virtual nsIntRect ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback) { return nsIntRect(); }
virtual nsIntRegion ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback) { return nsIntRect(); }
nsRefPtr<Layer> mLayer;
nsAutoPtr<LayerPropertiesBase> mMaskLayer;
@@ -173,7 +198,7 @@ struct ContainerLayerProperties : public LayerPropertiesBase
}
}
virtual nsIntRect ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback)
virtual nsIntRegion ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback)
{
ContainerLayer* container = mLayer->AsContainerLayer();
nsIntRegion result;
@@ -184,9 +209,9 @@ struct ContainerLayerProperties : public LayerPropertiesBase
// Child change. Invalidate the full areas.
// TODO: We could be smarter here if non-overlapping children
// swap order.
result.Or(result, TransformRect(child->GetVisibleRegion().GetBounds(), child->GetTransform()));
AddTransformedRegion(result, child->GetVisibleRegion(), child->GetTransform());
if (i < mChildren.Length()) {
result.Or(result, mChildren[i]->OldTransformedBounds());
AddRegion(result, mChildren[i]->OldTransformedBounds());
}
if (aCallback) {
NotifySubdocumentInvalidationRecursive(child, aCallback);
@@ -195,7 +220,7 @@ struct ContainerLayerProperties : public LayerPropertiesBase
}
} else {
// Same child, check for differences within the child
result.Or(result, mChildren[i]->ComputeChange(aCallback));
AddRegion(result, mChildren[i]->ComputeChange(aCallback));
}
i++;
@@ -203,7 +228,7 @@ struct ContainerLayerProperties : public LayerPropertiesBase
// Process remaining removed children.
while (i < mChildren.Length()) {
result.Or(result, mChildren[i]->OldTransformedBounds());
AddRegion(result, mChildren[i]->OldTransformedBounds());
i++;
}
@@ -211,7 +236,7 @@ struct ContainerLayerProperties : public LayerPropertiesBase
aCallback(container, result);
}
return TransformRect(result.GetBounds(), mLayer->GetTransform());
return TransformRegion(result, mLayer->GetTransform());
}
nsAutoTArray<nsAutoPtr<LayerPropertiesBase>,1> mChildren;
@@ -224,7 +249,7 @@ struct ColorLayerProperties : public LayerPropertiesBase
, mColor(aLayer->GetColor())
{ }
virtual nsIntRect ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback)
virtual nsIntRegion ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback)
{
ColorLayer* color = static_cast<ColorLayer*>(mLayer.get());
@@ -232,7 +257,7 @@ struct ColorLayerProperties : public LayerPropertiesBase
return NewTransformedBounds();
}
return nsIntRect();
return nsIntRegion();
}
gfxRGBA mColor;
@@ -250,7 +275,7 @@ struct ImageLayerProperties : public LayerPropertiesBase
{
}
virtual nsIntRect ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback)
virtual nsIntRegion ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback)
{
ImageLayer* imageLayer = static_cast<ImageLayer*>(mLayer.get());
@@ -318,7 +343,7 @@ LayerProperties::ClearInvalidations(Layer *aLayer)
}
}
nsIntRect
nsIntRegion
LayerPropertiesBase::ComputeDifferences(Layer* aRoot, NotifySubDocInvalidationFunc aCallback)
{
NS_ASSERTION(aRoot, "Must have a layer tree to compare against!");

View File

@@ -57,8 +57,8 @@ struct LayerProperties
* are invalidated.
* @return Painted area changed by the layer tree changes.
*/
virtual nsIntRect ComputeDifferences(Layer* aRoot,
NotifySubDocInvalidationFunc aCallback) = 0;
virtual nsIntRegion ComputeDifferences(Layer* aRoot,
NotifySubDocInvalidationFunc aCallback) = 0;
virtual void MoveBy(const nsIntPoint& aOffset) = 0;

View File

@@ -2425,16 +2425,16 @@ FrameLayerBuilder::AddThebesDisplayItem(ThebesLayer* aLayer,
nsIntPoint offset = GetLastPaintOffset(aLayer) - GetTranslationForThebesLayer(aLayer);
props->MoveBy(-offset);
nsIntRect invalid = props->ComputeDifferences(layer, nullptr);
nsIntRegion invalid = props->ComputeDifferences(layer, nullptr);
if (aLayerState == LAYER_SVG_EFFECTS) {
invalid = nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(aItem->GetUnderlyingFrame(), invalid);
invalid = nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(aItem->GetUnderlyingFrame(), invalid.GetBounds());
}
if (!invalid.IsEmpty()) {
#ifdef DEBUG_INVALIDATIONS
printf("Inactive LayerManager(%p) for display item %s(%p) has an invalid region - invalidating layer %p\n", tempManager.get(), aItem->Name(), aItem->GetUnderlyingFrame(), aLayer);
#endif
if (hasClip) {
invalid = invalid.Intersect(intClip);
invalid.And(invalid, intClip);
}
invalid.ScaleRoundOut(thebesData->mXScale, thebesData->mYScale);

View File

@@ -1128,7 +1128,7 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
aBuilder->SetIsCompositingCheap(temp);
layerBuilder->DidEndTransaction();
nsIntRect invalid;
nsIntRegion invalid;
if (props) {
invalid = props->ComputeDifferences(root, computeInvalidFunc);
} else if (widgetTransaction) {
@@ -1138,12 +1138,13 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
if (view) {
if (props) {
if (!invalid.IsEmpty()) {
nsRect rect(presContext->DevPixelsToAppUnits(invalid.x),
presContext->DevPixelsToAppUnits(invalid.y),
presContext->DevPixelsToAppUnits(invalid.width),
presContext->DevPixelsToAppUnits(invalid.height));
nsIntRect bounds = invalid.GetBounds();
nsRect rect(presContext->DevPixelsToAppUnits(bounds.x),
presContext->DevPixelsToAppUnits(bounds.y),
presContext->DevPixelsToAppUnits(bounds.width),
presContext->DevPixelsToAppUnits(bounds.height));
view->GetViewManager()->InvalidateViewNoSuppression(view, rect);
presContext->NotifyInvalidation(invalid, 0);
presContext->NotifyInvalidation(bounds, 0);
}
} else {
view->GetViewManager()->InvalidateView(view);

View File

@@ -5310,7 +5310,7 @@ PresShell::Paint(nsIView* aViewToPaint,
if (layerManager->EndEmptyTransaction((aFlags & PAINT_COMPOSITE) ?
LayerManager::END_DEFAULT : LayerManager::END_NO_COMPOSITE)) {
nsIntRect invalid;
nsIntRegion invalid;
if (props) {
invalid = props->ComputeDifferences(layerManager->GetRoot(), computeInvalidFunc);
} else {
@@ -5318,12 +5318,13 @@ PresShell::Paint(nsIView* aViewToPaint,
}
if (props) {
if (!invalid.IsEmpty()) {
nsRect rect(presContext->DevPixelsToAppUnits(invalid.x),
presContext->DevPixelsToAppUnits(invalid.y),
presContext->DevPixelsToAppUnits(invalid.width),
presContext->DevPixelsToAppUnits(invalid.height));
nsIntRect bounds = invalid.GetBounds();
nsRect rect(presContext->DevPixelsToAppUnits(bounds.x),
presContext->DevPixelsToAppUnits(bounds.y),
presContext->DevPixelsToAppUnits(bounds.width),
presContext->DevPixelsToAppUnits(bounds.height));
aViewToPaint->GetViewManager()->InvalidateViewNoSuppression(aViewToPaint, rect);
presContext->NotifyInvalidation(invalid, 0);
presContext->NotifyInvalidation(bounds, 0);
}
} else {
aViewToPaint->GetViewManager()->InvalidateView(aViewToPaint);