Bug 539356 - Avoid some causes of unnecessary painting. r=roc

This commit is contained in:
Matt Woodrow 2012-09-26 11:59:56 +12:00
Родитель 3724c42399
Коммит 58294c1b55
3 изменённых файлов: 86 добавлений и 35 удалений

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

@ -4642,7 +4642,18 @@ LayerActivityTracker::NotifyExpired(LayerActivity* aObject)
nsIFrame* f = aObject->mFrame; nsIFrame* f = aObject->mFrame;
aObject->mFrame = nullptr; aObject->mFrame = nullptr;
f->Properties().Delete(LayerActivityProperty()); f->Properties().Delete(LayerActivityProperty());
f->InvalidateFrameSubtree();
// if there are hints other than transform/opacity, invalidate, since we don't know what else to do.
if (aObject->mChangeHint & ~(nsChangeHint_UpdateOpacityLayer|nsChangeHint_UpdateTransformLayer)) {
f->InvalidateFrameSubtree();
} else {
if (aObject->mChangeHint & nsChangeHint_UpdateOpacityLayer) {
f->InvalidateFrameSubtree(nsDisplayItem::TYPE_OPACITY);
}
if (aObject->mChangeHint & nsChangeHint_UpdateTransformLayer) {
f->InvalidateFrameSubtree(nsDisplayItem::TYPE_TRANSFORM);
}
}
} }
void void
@ -4752,12 +4763,40 @@ nsIFrame::GetTransformMatrix(const nsIFrame* aStopAtAncestor,
0.0f); 0.0f);
} }
void static void InvalidateFrameInternal(nsIFrame *aFrame, bool aHasDisplayItem = true)
nsIFrame::InvalidateFrameSubtree()
{ {
InvalidateFrame(); if (aHasDisplayItem) {
aFrame->AddStateBits(NS_FRAME_NEEDS_PAINT);
}
nsSVGEffects::InvalidateDirectRenderingObservers(aFrame);
nsIFrame *parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
while (parent && !parent->HasAnyStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT)) {
if (aHasDisplayItem) {
parent->AddStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT);
}
nsSVGEffects::InvalidateDirectRenderingObservers(parent);
parent = nsLayoutUtils::GetCrossDocParentFrame(parent);
}
if (!aHasDisplayItem) {
return;
}
if (!parent) {
aFrame->SchedulePaint();
}
if (aFrame->HasAnyStateBits(NS_FRAME_HAS_INVALID_RECT)) {
aFrame->Properties().Delete(nsIFrame::InvalidationRect());
aFrame->RemoveStateBits(NS_FRAME_HAS_INVALID_RECT);
}
}
if (HasAnyStateBits(NS_FRAME_ALL_DESCENDANTS_NEED_PAINT)) { void
nsIFrame::InvalidateFrameSubtree(uint32_t aDisplayItemKey)
{
bool hasDisplayItem =
!aDisplayItemKey || FrameLayerBuilder::HasRetainedDataFor(this, aDisplayItemKey);
InvalidateFrameInternal(this, hasDisplayItem);
if (HasAnyStateBits(NS_FRAME_ALL_DESCENDANTS_NEED_PAINT) || !hasDisplayItem) {
return; return;
} }
@ -4796,41 +4835,30 @@ nsIFrame::ClearInvalidationStateBits()
NS_FRAME_ALL_DESCENDANTS_NEED_PAINT); NS_FRAME_ALL_DESCENDANTS_NEED_PAINT);
} }
static void InvalidateFrameInternal(nsIFrame *aFrame) void
nsIFrame::InvalidateFrame(uint32_t aDisplayItemKey)
{ {
aFrame->AddStateBits(NS_FRAME_NEEDS_PAINT); bool hasDisplayItem =
nsSVGEffects::InvalidateDirectRenderingObservers(aFrame); !aDisplayItemKey || FrameLayerBuilder::HasRetainedDataFor(this, aDisplayItemKey);
nsIFrame *parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame); InvalidateFrameInternal(this, hasDisplayItem);
while (parent && !parent->HasAnyStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT)) {
parent->AddStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT);
nsSVGEffects::InvalidateDirectRenderingObservers(parent);
parent = nsLayoutUtils::GetCrossDocParentFrame(parent);
}
if (!parent) {
aFrame->SchedulePaint();
}
if (aFrame->HasAnyStateBits(NS_FRAME_HAS_INVALID_RECT)) {
aFrame->Properties().Delete(nsIFrame::InvalidationRect());
aFrame->RemoveStateBits(NS_FRAME_HAS_INVALID_RECT);
}
} }
void void
nsIFrame::InvalidateFrame() nsIFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
{
InvalidateFrameInternal(this);
}
void
nsIFrame::InvalidateFrameWithRect(const nsRect& aRect)
{ {
bool hasDisplayItem =
!aDisplayItemKey || FrameLayerBuilder::HasRetainedDataFor(this, aDisplayItemKey);
bool alreadyInvalid = false; bool alreadyInvalid = false;
if (!HasAnyStateBits(NS_FRAME_NEEDS_PAINT)) { if (!HasAnyStateBits(NS_FRAME_NEEDS_PAINT)) {
InvalidateFrameInternal(this); InvalidateFrameInternal(this, hasDisplayItem);
} else { } else {
alreadyInvalid = true; alreadyInvalid = true;
} }
if (!hasDisplayItem) {
return;
}
nsRect *rect = static_cast<nsRect*>(Properties().Get(InvalidationRect())); nsRect *rect = static_cast<nsRect*>(Properties().Get(InvalidationRect()));
if (!rect) { if (!rect) {
if (alreadyInvalid) { if (alreadyInvalid) {
@ -4894,7 +4922,14 @@ nsIFrame::InvalidateLayer(uint32_t aDisplayItemKey, const nsIntRect* aDamageRect
} }
if (!layer) { if (!layer) {
InvalidateFrame(); // Plugins can transition from not rendering anything to rendering,
// and still only call this. So always invalidate, with specifying
// the display item type just in case.
if (aDisplayItemKey == nsDisplayItem::TYPE_PLUGIN) {
InvalidateFrame();
} else {
InvalidateFrame(aDisplayItemKey);
}
return nullptr; return nullptr;
} }

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

@ -2183,8 +2183,12 @@ public:
* *
* This includes all display items created by this frame, including * This includes all display items created by this frame, including
* container types. * container types.
*
* @param aDisplayItemKey If specified, only issues an invalidate
* if this frame painted a display item of that type during the
* previous paint. SVG rendering observers are always notified.
*/ */
virtual void InvalidateFrame(); virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0);
/** /**
* Same as InvalidateFrame(), but only mark a fixed rect as needing * Same as InvalidateFrame(), but only mark a fixed rect as needing
@ -2192,8 +2196,11 @@ public:
* *
* @param aRect The rect to invalidate, relative to the TopLeft of the * @param aRect The rect to invalidate, relative to the TopLeft of the
* frame's border box. * frame's border box.
* @param aDisplayItemKey If specified, only issues an invalidate
* if this frame painted a display item of that type during the
* previous paint. SVG rendering observers are always notified.
*/ */
virtual void InvalidateFrameWithRect(const nsRect& aRect); virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0);
/** /**
* Calls InvalidateFrame() on all frames descendant frames (including * Calls InvalidateFrame() on all frames descendant frames (including
@ -2201,12 +2208,17 @@ public:
* *
* This function doesn't walk through placeholder frames to invalidate * This function doesn't walk through placeholder frames to invalidate
* the out-of-flow frames. * the out-of-flow frames.
*
* @param aDisplayItemKey If specified, only issues an invalidate
* if this frame painted a display item of that type during the
* previous paint. SVG rendering observers are always notified.
*/ */
void InvalidateFrameSubtree(); void InvalidateFrameSubtree(uint32_t aDisplayItemKey = 0);
/** /**
* Called when a frame is about to be removed and needs to be invalidated. * Called when a frame is about to be removed and needs to be invalidated.
* Normally does nothing since DLBI handles removed frames. * Normally does nothing since DLBI handles removed frames.
*
*/ */
virtual void InvalidateFrameForRemoval() {} virtual void InvalidateFrameForRemoval() {}

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

@ -592,10 +592,14 @@ nsImageFrame::OnDataAvailable(imgIRequest *aRequest,
printf("Source rect (%d,%d,%d,%d)\n", printf("Source rect (%d,%d,%d,%d)\n",
aRect->x, aRect->y, aRect->width, aRect->height); aRect->x, aRect->y, aRect->width, aRect->height);
#endif #endif
if (aRect->IsEqualInterior(nsIntRect::GetMaxSizedIntRect())) { if (aRect->IsEqualInterior(nsIntRect::GetMaxSizedIntRect())) {
InvalidateFrame(); InvalidateFrame(nsDisplayItem::TYPE_IMAGE);
InvalidateFrame(nsDisplayItem::TYPE_ALT_FEEDBACK);
} else { } else {
InvalidateFrameWithRect(SourceRectToDest(*aRect)); nsRect invalid = SourceRectToDest(*aRect);
InvalidateFrameWithRect(invalid, nsDisplayItem::TYPE_IMAGE);
InvalidateFrameWithRect(invalid, nsDisplayItem::TYPE_ALT_FEEDBACK);
} }
return NS_OK; return NS_OK;