Bug 1227327 - Invalidate table parts and MathML frames when background-position changes on them. r=dbaron
☠☠ backed out by 3b5d1530f701 ☠ ☠
authorMarkus Stange <mstange@themasta.com>
Thu, 28 Apr 2016 13:01:22 -0400
changeset 295754 2276fc059bf7977f4231c88d6060b8043ec95552
parent 295753 d338b07ac840c0e8a7b09929dc2250093c54016f
child 295755 1515512d3731ec8247f03312dcd349b4d7bebd21
push id76066
push usermstange@themasta.com
push dateMon, 02 May 2016 21:40:48 +0000
treeherdermozilla-inbound@529ff32ced48 [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
@@ -2633,17 +2633,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);
   }