Bug 1227327 - Invalidate table parts and MathML frames when background-position changes on them. r=dbaron
☠☠ backed out by d2b9a2c891fc ☠ ☠
authorMarkus Stange <mstange@themasta.com>
Thu, 28 Apr 2016 13:01:22 -0400
changeset 296002 e0fe45294034f513f71b6587c72931a2f047c506
parent 296001 d90072777443aa7b16f30d966cdad45fea88e210
child 296003 ce7fd04cc749ce34a30737df0a3ea575bb1ef356
push id30230
push usercbook@mozilla.com
push dateWed, 04 May 2016 09:55:16 +0000
treeherdermozilla-central@311c7ea8803d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs1227327
milestone49.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1227327 - Invalidate table parts and MathML frames when background-position changes on them. r=dbaron Theoretically we should do the same for nsTreeBodyFrame, but that frame type is harder to detect and I'm not sure it's worth adding code to support updating background-position on XUL trees. MozReview-Commit-ID: 8HPT53MX6bO
layout/base/RestyleManager.cpp
layout/base/nsChangeHint.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -881,16 +881,29 @@ RestyleManager::ProcessRestyledFrames(ns
         // backgrounds (and those of table parts inside of it) are
         // painted as part of the table's nsDisplayTableBorderBackground
         // display item, or part of its own display item.  That requires
         // invalidation, so change UpdateOpacityLayer to RepaintFrame.
         hint &= ~nsChangeHint_UpdateOpacityLayer;
         hint |= nsChangeHint_RepaintFrame;
       }
 
+      if (hint & nsChangeHint_UpdateBackgroundPosition) {
+        // For most frame types, DLBI can detect background position changes,
+        // so we only need to schedule a paint.
+        hint |= nsChangeHint_SchedulePaint;
+        if (frame->IsFrameOfType(nsIFrame::eTablePart) ||
+            frame->IsFrameOfType(nsIFrame::eMathML)) {
+          // Table parts and MathML frames don't build display items for their
+          // backgrounds, so DLBI can't detect background-position changes for
+          // these frames. Repaint the whole frame.
+          hint |= nsChangeHint_RepaintFrame;
+        }
+      }
+
       if (hint & (nsChangeHint_RepaintFrame | nsChangeHint_SyncFrameView |
                   nsChangeHint_UpdateOpacityLayer | nsChangeHint_UpdateTransformLayer |
                   nsChangeHint_ChildrenOnlyTransform | nsChangeHint_SchedulePaint)) {
         ApplyRenderingChangeToTree(mPresContext, frame, hint);
       }
       if ((hint & nsChangeHint_RecomputePosition) && !didReflowThisFrame) {
         ActiveLayerTracker::NotifyOffsetRestyle(frame);
         // It is possible for this to fall back to a reflow
--- a/layout/base/nsChangeHint.h
+++ b/layout/base/nsChangeHint.h
@@ -189,16 +189,25 @@ enum nsChangeHint {
    *
    * Used as extra data for handling UpdateOpacityLayer hints.
    *
    * Note that we do not send this hint if the non-1 value was 0.99 or
    * greater, since in that case we send a RepaintFrame hint instead.
    */
   nsChangeHint_UpdateUsesOpacity = 1 << 25,
 
+  /**
+   * Indicates that the 'background-position' property changed.
+   * Regular frames can invalidate these changes using DLBI, but
+   * for some frame types we need to repaint the whole frame because
+   * the frame does not build individual background image display items
+   * for each background layer.
+   */
+  nsChangeHint_UpdateBackgroundPosition = 1 << 26,
+
   // IMPORTANT NOTE: When adding new hints, consider whether you need to
   // add them to NS_HintsNotHandledForDescendantsIn() below.  Please also
   // add them to RestyleManager::ChangeHintToString.
 };
 
 // Redefine these operators to return nothing. This will catch any use
 // of these operators on hints. We should not be using these operators
 // on nsChangeHints
@@ -298,33 +307,35 @@ inline nsChangeHint operator^=(nsChangeH
           nsChangeHint_ChildrenOnlyTransform | \
           nsChangeHint_RecomputePosition | \
           nsChangeHint_UpdateContainingBlock | \
           nsChangeHint_BorderStyleNoneChange | \
           nsChangeHint_NeedReflow | \
           nsChangeHint_ReflowChangesSizeOrPosition | \
           nsChangeHint_ClearAncestorIntrinsics | \
           nsChangeHint_UpdateComputedBSize | \
-          nsChangeHint_UpdateUsesOpacity)
+          nsChangeHint_UpdateUsesOpacity | \
+          nsChangeHint_UpdateBackgroundPosition)
 
 inline nsChangeHint NS_HintsNotHandledForDescendantsIn(nsChangeHint aChangeHint) {
   nsChangeHint result = nsChangeHint(aChangeHint & (
     nsChangeHint_UpdateTransformLayer |
     nsChangeHint_UpdateEffects |
     nsChangeHint_InvalidateRenderingObservers |
     nsChangeHint_UpdateOpacityLayer |
     nsChangeHint_UpdateOverflow |
     nsChangeHint_UpdatePostTransformOverflow |
     nsChangeHint_UpdateParentOverflow |
     nsChangeHint_ChildrenOnlyTransform |
     nsChangeHint_RecomputePosition |
     nsChangeHint_UpdateContainingBlock |
     nsChangeHint_BorderStyleNoneChange |
     nsChangeHint_UpdateComputedBSize |
-    nsChangeHint_UpdateUsesOpacity));
+    nsChangeHint_UpdateUsesOpacity | \
+    nsChangeHint_UpdateBackgroundPosition));
 
   if (!NS_IsHintSubset(nsChangeHint_NeedDirtyReflow, aChangeHint)) {
     if (NS_IsHintSubset(nsChangeHint_NeedReflow, aChangeHint)) {
       // If NeedDirtyReflow is *not* set, then NeedReflow is a
       // non-inherited hint.
       NS_UpdateHint(result, nsChangeHint_NeedReflow);
     }
 
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2646,17 +2646,17 @@ nsStyleImageLayers::Layer::CalcDifferenc
              mSize != aOther.mSize ||
              mImage != aOther.mImage ||
              mMaskMode != aOther.mMaskMode ||
              mComposite != aOther.mComposite) {
     hint |= nsChangeHint_RepaintFrame;
   }
 
   if (mPosition != aOther.mPosition) {
-    hint |= nsChangeHint_SchedulePaint;
+    hint |= nsChangeHint_UpdateBackgroundPosition;
   }
 
   return hint;
 }
 
 // --------------------
 // nsStyleBackground
 //
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -796,17 +796,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBackground, sz);
   }
   void Destroy(nsPresContext* aContext);
 
   nsChangeHint CalcDifference(const nsStyleBackground& aOther) const;
   static nsChangeHint MaxDifference() {
      return nsChangeHint_UpdateEffects |
            nsChangeHint_RepaintFrame |
-           nsChangeHint_SchedulePaint |
+           nsChangeHint_UpdateBackgroundPosition |
            nsChangeHint_NeutralChange;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
     // handled for descendants at all.
     return nsChangeHint(0);
   }