Bug 564993. Part 3: Split nsDisplayList::Paint into PaintForFrame and PaintRoot. Set the visible rect on the root layer from PaintRoot, let the visible rects of other layers be set when they're placed in their containers. r=mats

This commit is contained in:
Robert O'Callahan 2010-03-11 09:55:05 +13:00
parent d1e569cf6b
commit 5b63e43695
5 changed files with 48 additions and 21 deletions

View File

@ -316,6 +316,8 @@ nsDisplayList::ComputeVisibility(nsDisplayListBuilder* aBuilder,
NS_ASSERTION((aVisibleRegionBeforeMove != nsnull) == aBuilder->HasMovingFrames(),
"Should have aVisibleRegionBeforeMove when there are moving frames");
mVisibleRect = aVisibleRegion->GetBounds();
nsAutoTArray<nsDisplayItem*, 512> elements;
FlattenTo(&elements);
@ -706,8 +708,6 @@ already_AddRefed<Layer>
nsDisplayList::BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
nsTArray<LayerItems>* aLayers) const {
BuildLayers(aBuilder, aManager, aLayers);
// If there's only one layer, then in principle we can try to flatten
// things by returning that layer here. But that adds complexity to
// retained layer management so we don't do it. Layer backends can
@ -717,29 +717,34 @@ nsDisplayList::BuildLayer(nsDisplayListBuilder* aBuilder,
if (!container)
return nsnull;
BuildLayers(aBuilder, aManager, aLayers);
Layer* lastChild = nsnull;
nsIntRect visibleRect;
for (PRUint32 i = 0; i < aLayers->Length(); ++i) {
LayerItems* layerItems = &aLayers->ElementAt(i);
visibleRect.UnionRect(visibleRect, layerItems->mVisibleRect);
Layer* child = layerItems->mLayer;
Layer* child = aLayers->ElementAt(i).mLayer;
container->InsertAfter(child, lastChild);
lastChild = child;
}
container->SetVisibleRegion(nsIntRegion(visibleRect));
container->SetIsOpaqueContent(mIsOpaque);
nsRefPtr<Layer> layer = container.forget();
return layer.forget();
}
void nsDisplayList::PaintRoot(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx,
PRUint32 aFlags) const {
PaintForFrame(aBuilder, aCtx, aBuilder->ReferenceFrame(), aFlags);
}
/**
* We paint by executing a layer manager transaction, constructing a
* single layer representing the display list, and then making it the
* root of the layer manager, drawing into the ThebesLayers.
*/
void nsDisplayList::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx,
PRUint32 aFlags) const {
void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx,
nsIFrame* aForFrame,
PRUint32 aFlags) const {
NS_ASSERTION(mDidComputeVisibility,
"Must call ComputeVisibility before calling Paint");
@ -774,6 +779,10 @@ void nsDisplayList::Paint(nsDisplayListBuilder* aBuilder,
if (!root)
return;
nsIntRect visible =
mVisibleRect.ToNearestPixels(aForFrame->PresContext()->AppUnitsPerDevPixel());
root->SetVisibleRegion(nsIntRegion(visible));
layerManager->SetRoot(root);
layerManager->EndConstruction();
PaintThebesLayers(aBuilder, layers);
@ -1533,7 +1542,7 @@ nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder,
if (!layer)
return nsnull;
layer->SetOpacity(mFrame->GetStyleDisplay()->mOpacity*layer->GetOpacity());
layer->SetOpacity(mFrame->GetStyleDisplay()->mOpacity);
return layer.forget();
}
@ -1853,7 +1862,8 @@ void nsDisplayTransform::Paint(nsDisplayListBuilder *aBuilder,
/* Now, send the paint call down.
*/
mStoredList.GetList()->Paint(aBuilder, aCtx, nsDisplayList::PAINT_DEFAULT);
mStoredList.GetList()->
PaintForFrame(aBuilder, aCtx, mFrame, nsDisplayList::PAINT_DEFAULT);
/* The AutoSaveRestore object will clean things up. */
}

View File

@ -861,13 +861,22 @@ public:
* not be null.
*
* ComputeVisibility must be called before Paint.
*
* This must only be called on the root display list of the display list
* tree.
*/
enum {
PAINT_DEFAULT = 0,
PAINT_USE_WIDGET_LAYERS = 0x01
};
void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
PRUint32 aFlags) const;
void PaintRoot(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
PRUint32 aFlags) const;
/**
* Like PaintRoot, but used for internal display sublists.
* aForFrame is the frame that the list is associated with.
*/
void PaintForFrame(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
nsIFrame* aForFrame, PRUint32 aFlags) const;
/**
* Get the bounds. Takes the union of the bounds of all children.
*/
@ -944,6 +953,7 @@ public:
* we construct layers belonging to aManager. The layers used to
* construct the layer tree (along with the display items associated
* with each layer) are returned in aLayers.
* The caller is responsible for setting the visible region on the layer.
*/
already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
@ -968,6 +978,8 @@ private:
nsDisplayItemLink mSentinel;
nsDisplayItemLink* mTop;
// This is set by ComputeVisibility
nsRect mVisibleRect;
// This is set to true by ComputeVisibility if the final visible region
// is empty (i.e. everything that was visible is covered by some
// opaque content in this list).

View File

@ -1259,7 +1259,7 @@ nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFra
widget->UpdatePossiblyTransparentRegion(dirtyWindowRegion, visibleWindowRegion);
}
list.Paint(&builder, aRenderingContext, flags);
list.PaintRoot(&builder, aRenderingContext, flags);
// Flush the list so we don't trigger the IsEmpty-on-destruction assertion
list.DeleteAll();
return NS_OK;

View File

@ -5146,7 +5146,7 @@ PresShell::RenderDocument(const nsRect& aRect, PRUint32 aFlags,
if (aFlags & RENDER_USE_WIDGET_LAYERS) {
flags |= nsDisplayList::PAINT_USE_WIDGET_LAYERS;
}
list.Paint(&builder, rc, flags);
list.PaintRoot(&builder, rc, flags);
// Flush the list so we don't trigger the IsEmpty-on-destruction assertion
list.DeleteAll();
@ -5439,7 +5439,7 @@ PresShell::PaintRangePaintInfo(nsTArray<nsAutoPtr<RangePaintInfo> >* aItems,
aArea.MoveBy(-rangeInfo->mRootOffset.x, -rangeInfo->mRootOffset.y);
nsRegion visible(aArea);
rangeInfo->mList.ComputeVisibility(&rangeInfo->mBuilder, &visible, nsnull);
rangeInfo->mList.Paint(&rangeInfo->mBuilder, rc, nsDisplayList::PAINT_DEFAULT);
rangeInfo->mList.PaintRoot(&rangeInfo->mBuilder, rc, nsDisplayList::PAINT_DEFAULT);
aArea.MoveBy(rangeInfo->mRootOffset.x, rangeInfo->mRootOffset.y);
}

View File

@ -202,20 +202,23 @@ class RegularFramePaintCallback : public nsSVGFilterPaintCallback
public:
RegularFramePaintCallback(nsDisplayListBuilder* aBuilder,
nsDisplayList* aInnerList,
nsIFrame* aFrame,
const nsPoint& aOffset)
: mBuilder(aBuilder), mInnerList(aInnerList), mOffset(aOffset) {}
: mBuilder(aBuilder), mInnerList(aInnerList), mFrame(aFrame),
mOffset(aOffset) {}
virtual void Paint(nsSVGRenderState *aContext, nsIFrame *aTarget,
const nsIntRect* aDirtyRect)
{
nsIRenderingContext* ctx = aContext->GetRenderingContext(aTarget);
nsIRenderingContext::AutoPushTranslation push(ctx, -mOffset.x, -mOffset.y);
mInnerList->Paint(mBuilder, ctx, nsDisplayList::PAINT_DEFAULT);
mInnerList->PaintForFrame(mBuilder, ctx, mFrame, nsDisplayList::PAINT_DEFAULT);
}
private:
nsDisplayListBuilder* mBuilder;
nsDisplayList* mInnerList;
nsIFrame* mFrame;
nsPoint mOffset;
};
@ -298,12 +301,14 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsIRenderingContext* aCtx,
/* Paint the child */
if (filterFrame) {
RegularFramePaintCallback paint(aBuilder, aInnerList, userSpaceRect.TopLeft());
RegularFramePaintCallback paint(aBuilder, aInnerList, aEffectsFrame,
userSpaceRect.TopLeft());
nsIntRect r = (aDirtyRect - userSpaceRect.TopLeft()).ToOutsidePixels(appUnitsPerDevPixel);
filterFrame->FilterPaint(&svgContext, aEffectsFrame, &paint, &r);
} else {
gfx->SetMatrix(savedCTM);
aInnerList->Paint(aBuilder, aCtx, nsDisplayList::PAINT_DEFAULT);
aInnerList->PaintForFrame(aBuilder, aCtx, aEffectsFrame,
nsDisplayList::PAINT_DEFAULT);
aCtx->Translate(userSpaceRect.x, userSpaceRect.y);
}