From e4ffa9b774bdfd40f00f092cd9987cba07e91871 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Mon, 2 Nov 2015 17:36:35 +0100 Subject: [PATCH] Bug 1201327 - Don't repaint the whole frame subtree when background-position changes. r=dbaron --- .../background-position-1-ref.html | 31 ++++++++++++ .../invalidation/background-position-1.html | 41 +++++++++++++++ layout/reftests/invalidation/reftest.list | 1 + layout/style/nsStyleStruct.cpp | 50 ++++++++++++++----- layout/style/nsStyleStruct.h | 10 ++-- 5 files changed, 117 insertions(+), 16 deletions(-) create mode 100644 layout/reftests/invalidation/background-position-1-ref.html create mode 100644 layout/reftests/invalidation/background-position-1.html diff --git a/layout/reftests/invalidation/background-position-1-ref.html b/layout/reftests/invalidation/background-position-1-ref.html new file mode 100644 index 00000000000..a5862f039ef --- /dev/null +++ b/layout/reftests/invalidation/background-position-1-ref.html @@ -0,0 +1,31 @@ + + + +Changes to background-position should not cause things to repaint that don't intersect the background image. + + + +
+
+
diff --git a/layout/reftests/invalidation/background-position-1.html b/layout/reftests/invalidation/background-position-1.html new file mode 100644 index 00000000000..c5d296b008b --- /dev/null +++ b/layout/reftests/invalidation/background-position-1.html @@ -0,0 +1,41 @@ + + + +Changes to background-position should not cause things to repaint that don't intersect the background image. + + + +
+
+
+ + diff --git a/layout/reftests/invalidation/reftest.list b/layout/reftests/invalidation/reftest.list index ff1fae6be30..8f173c1da37 100644 --- a/layout/reftests/invalidation/reftest.list +++ b/layout/reftests/invalidation/reftest.list @@ -70,3 +70,4 @@ fuzzy-if(gtkWidget,2,4) fuzzy-if(asyncPan,2,3955) fuzzy-if(OSX,179,30) == image- != fractional-transform-1.html about:blank != fractional-transform-2.html about:blank != fractional-transform-3.html about:blank +== background-position-1.html background-position-1-ref.html diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index b3574e79723..9dca383f1bd 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -2251,27 +2251,32 @@ nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) const nsStyleBackground* lessLayers = mImageCount > aOther.mImageCount ? &aOther : this; - bool hasVisualDifference = false; + nsChangeHint hint = nsChangeHint(0); NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, moreLayers) { if (i < lessLayers->mImageCount) { - if (moreLayers->mLayers[i] != lessLayers->mLayers[i]) { - if ((moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element) || - (lessLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element)) - return NS_CombineHint(nsChangeHint_UpdateEffects, - nsChangeHint_RepaintFrame); - hasVisualDifference = true; + nsChangeHint layerDifference = moreLayers->mLayers[i].CalcDifference(lessLayers->mLayers[i]); + hint |= layerDifference; + if (layerDifference && + ((moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element) || + (lessLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element))) { + hint |= nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame; } } else { - if (moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element) - return NS_CombineHint(nsChangeHint_UpdateEffects, - nsChangeHint_RepaintFrame); - hasVisualDifference = true; + hint |= nsChangeHint_RepaintFrame; + if (moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element) { + hint |= nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame; + } } } - if (hasVisualDifference || mBackgroundColor != aOther.mBackgroundColor) - return nsChangeHint_RepaintFrame; + if (mBackgroundColor != aOther.mBackgroundColor) { + hint |= nsChangeHint_RepaintFrame; + } + + if (hint) { + return hint; + } if (mAttachmentCount != aOther.mAttachmentCount || mClipCount != aOther.mClipCount || @@ -2482,6 +2487,25 @@ nsStyleBackground::Layer::operator==(const Layer& aOther) const mImage == aOther.mImage; } +nsChangeHint +nsStyleBackground::Layer::CalcDifference(const Layer& aOther) const +{ + nsChangeHint hint = nsChangeHint(0); + if (mAttachment != aOther.mAttachment || + mClip != aOther.mClip || + mOrigin != aOther.mOrigin || + mRepeat != aOther.mRepeat || + mBlendMode != aOther.mBlendMode || + mSize != aOther.mSize || + mImage != aOther.mImage) { + hint |= nsChangeHint_RepaintFrame; + } + if (mPosition != aOther.mPosition) { + hint |= nsChangeHint_SchedulePaint; + } + return hint; +} + // -------------------- // nsStyleDisplay // diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index c33c3016f86..a996536329c 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -396,9 +396,10 @@ struct nsStyleBackground { nsChangeHint CalcDifference(const nsStyleBackground& aOther) const; static nsChangeHint MaxDifference() { - return NS_CombineHint(nsChangeHint_UpdateEffects, - NS_CombineHint(nsChangeHint_RepaintFrame, - nsChangeHint_NeutralChange)); + return nsChangeHint_UpdateEffects | + nsChangeHint_RepaintFrame | + nsChangeHint_SchedulePaint | + nsChangeHint_NeutralChange; } static nsChangeHint DifferenceAlwaysHandledForDescendants() { // CalcDifference never returns the reflow hints that are sometimes @@ -552,6 +553,9 @@ struct nsStyleBackground { // whose root node has a viewBox. bool RenderingMightDependOnPositioningAreaSizeChange() const; + // Compute the change hint required by changes in just this layer. + nsChangeHint CalcDifference(const Layer& aOther) const; + // An equality operator that compares the images using URL-equality // rather than pointer-equality. bool operator==(const Layer& aOther) const;