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;
aObject->mFrame = nullptr;
f->Properties().Delete(LayerActivityProperty());
// 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
@ -4752,12 +4763,40 @@ nsIFrame::GetTransformMatrix(const nsIFrame* aStopAtAncestor,
0.0f);
}
void
nsIFrame::InvalidateFrameSubtree()
static void InvalidateFrameInternal(nsIFrame *aFrame, bool aHasDisplayItem = true)
{
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;
}
@ -4796,41 +4835,30 @@ nsIFrame::ClearInvalidationStateBits()
NS_FRAME_ALL_DESCENDANTS_NEED_PAINT);
}
static void InvalidateFrameInternal(nsIFrame *aFrame)
void
nsIFrame::InvalidateFrame(uint32_t aDisplayItemKey)
{
aFrame->AddStateBits(NS_FRAME_NEEDS_PAINT);
nsSVGEffects::InvalidateDirectRenderingObservers(aFrame);
nsIFrame *parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
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);
}
bool hasDisplayItem =
!aDisplayItemKey || FrameLayerBuilder::HasRetainedDataFor(this, aDisplayItemKey);
InvalidateFrameInternal(this, hasDisplayItem);
}
void
nsIFrame::InvalidateFrame()
{
InvalidateFrameInternal(this);
}
void
nsIFrame::InvalidateFrameWithRect(const nsRect& aRect)
nsIFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
{
bool hasDisplayItem =
!aDisplayItemKey || FrameLayerBuilder::HasRetainedDataFor(this, aDisplayItemKey);
bool alreadyInvalid = false;
if (!HasAnyStateBits(NS_FRAME_NEEDS_PAINT)) {
InvalidateFrameInternal(this);
InvalidateFrameInternal(this, hasDisplayItem);
} else {
alreadyInvalid = true;
}
if (!hasDisplayItem) {
return;
}
nsRect *rect = static_cast<nsRect*>(Properties().Get(InvalidationRect()));
if (!rect) {
if (alreadyInvalid) {
@ -4894,7 +4922,14 @@ nsIFrame::InvalidateLayer(uint32_t aDisplayItemKey, const nsIntRect* aDamageRect
}
if (!layer) {
// 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;
}

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

@ -2183,8 +2183,12 @@ public:
*
* This includes all display items created by this frame, including
* 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
@ -2192,8 +2196,11 @@ public:
*
* @param aRect The rect to invalidate, relative to the TopLeft of the
* 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
@ -2201,12 +2208,17 @@ public:
*
* This function doesn't walk through placeholder frames to invalidate
* 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.
* Normally does nothing since DLBI handles removed frames.
*
*/
virtual void InvalidateFrameForRemoval() {}

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

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