Bug 1267656 - Disable paint skipping for scrollframes with background-attachment:local. r?mstange draft
authorKartikaya Gupta <kgupta@mozilla.com>
Fri, 15 Jul 2016 15:52:41 -0400
changeset 388423 7fc4ae0797c79019d160b8548931d04e7c04870c
parent 388397 2f9e69c982f1e67887a1834b36ff0af4ababb3af
child 525542 152f67a4d0cec7588c81333ea935ad74fea1ee3c
push id23168
push userkgupta@mozilla.com
push dateFri, 15 Jul 2016 19:53:06 +0000
reviewersmstange
bugs1267656
milestone50.0a1
Bug 1267656 - Disable paint skipping for scrollframes with background-attachment:local. r?mstange MozReview-Commit-ID: 8aa1fuiEMPJ
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
layout/style/nsStyleStruct.h
layout/style/nsStyleStructInlines.h
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -2114,16 +2114,23 @@ ScrollFrameHelper::HasPluginFrames()
 
 bool
 ScrollFrameHelper::HasPerspective() const
 {
   const nsStyleDisplay* disp = mOuter->StyleDisplay();
   return disp->mChildPerspective.GetUnit() != eStyleUnit_None;
 }
 
+bool
+ScrollFrameHelper::HasBgAttachmentLocal() const
+{
+  const nsStyleBackground* bg = mOuter->StyleBackground();
+  return bg->HasLocalBackground();
+}
+
 void
 ScrollFrameHelper::SetScrollsClipOnUnscrolledOutOfFlow()
 {
   mScrollsClipOnUnscrolledOutOfFlow = true;
 }
 
 void
 ScrollFrameHelper::ScrollToCSSPixels(const CSSIntPoint& aScrollPosition,
@@ -2757,21 +2764,24 @@ ScrollFrameHelper::ScrollToImpl(nsPoint 
     // that needs to be painted. So even if the final tile-aligned displayport
     // is the same, we force a repaint for these elements. Bug 1254260 tracks
     // fixing this properly.
     nsRect displayPort;
     bool usingDisplayPort =
       nsLayoutUtils::GetHighResolutionDisplayPort(content, &displayPort);
     displayPort.MoveBy(-mScrolledFrame->GetPosition());
 
-    PAINT_SKIP_LOG("New scrollpos %s usingDP %d dpEqual %d scrollableByApz %d plugins %d perspective %d clip %d\n",
+    PAINT_SKIP_LOG("New scrollpos %s usingDP %d dpEqual %d scrollableByApz %d plugins %d perspective %d clip %d bglocal %d\n",
         Stringify(CSSPoint::FromAppUnits(GetScrollPosition())).c_str(),
         usingDisplayPort, displayPort.IsEqualEdges(oldDisplayPort),
-        mScrollableByAPZ, HasPluginFrames(), HasPerspective(), mScrollsClipOnUnscrolledOutOfFlow);
-    if (usingDisplayPort && displayPort.IsEqualEdges(oldDisplayPort) && !HasPerspective() && !mScrollsClipOnUnscrolledOutOfFlow) {
+        mScrollableByAPZ, HasPluginFrames(), HasPerspective(),
+        mScrollsClipOnUnscrolledOutOfFlow, HasBgAttachmentLocal());
+    if (usingDisplayPort && displayPort.IsEqualEdges(oldDisplayPort) &&
+        !HasPerspective() && !mScrollsClipOnUnscrolledOutOfFlow &&
+        !HasBgAttachmentLocal()) {
       bool haveScrollLinkedEffects = content->GetComposedDoc()->HasScrollLinkedEffect();
       bool apzDisabled = haveScrollLinkedEffects && gfxPrefs::APZDisableForScrollLinkedEffects();
       if (!apzDisabled) {
         if (LastScrollOrigin() == nsGkAtoms::apz) {
           schedulePaint = false;
           PAINT_SKIP_LOG("Skipping due to APZ scroll\n");
         } else if (mScrollableByAPZ && !HasPluginFrames()) {
           nsIWidget* widget = presContext->GetNearestWidget();
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -624,16 +624,17 @@ protected:
    * Helper that notifies plugins about async smooth scroll operations managed
    * by nsGfxScrollFrame.
    */
   enum AsyncScrollEventType { BEGIN_DOM, BEGIN_APZ, END_DOM, END_APZ };
   void NotifyPluginFrames(AsyncScrollEventType aEvent);
   AsyncScrollEventType mAsyncScrollEvent;
   bool HasPluginFrames();
   bool HasPerspective() const;
+  bool HasBgAttachmentLocal() const;
   uint8_t GetScrolledFrameDir() const;
 
   static void EnsureFrameVisPrefsCached();
   static bool sFrameVisPrefsCached;
   // The number of scrollports wide/high to expand when tracking frame visibility.
   static uint32_t sHorzExpandScrollPort;
   static uint32_t sVertExpandScrollPort;
   // The fraction of the scrollport we allow to scroll by before we schedule
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -790,16 +790,20 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   bool IsTransparent() const;
 
   // We have to take slower codepaths for fixed background attachment,
   // but we don't want to do that when there's no image.
   // Not inline because it uses an nsCOMPtr<imgIRequest>
   // FIXME: Should be in nsStyleStructInlines.h.
   bool HasFixedBackground(nsIFrame* aFrame) const;
 
+  // Checks to see if this has a non-empty image with "local" attachment.
+  // This is defined in nsStyleStructInlines.h.
+  inline bool HasLocalBackground() const;
+
   const nsStyleImageLayers::Layer& BottomLayer() const { return mImage.BottomLayer(); }
 
   nsStyleImageLayers mImage;
   nscolor mBackgroundColor;       // [reset]
 };
 
 // See https://bugzilla.mozilla.org/show_bug.cgi?id=271586#c43 for why
 // this is hard to replace with 'currentColor'.
--- a/layout/style/nsStyleStructInlines.h
+++ b/layout/style/nsStyleStructInlines.h
@@ -188,9 +188,22 @@ nsStyleUserInterface::GetEffectivePointe
     nsIFrame* f = aFrame->GetContent()->GetPrimaryFrame();
     if (f) {
       return f->StyleUserInterface()->mPointerEvents;
     }
   }
   return mPointerEvents;
 }
 
+bool
+nsStyleBackground::HasLocalBackground() const
+{
+  NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, mImage) {
+    const nsStyleImageLayers::Layer& layer = mImage.mLayers[i];
+    if (!layer.mImage.IsEmpty() &&
+        layer.mAttachment == NS_STYLE_IMAGELAYER_ATTACHMENT_LOCAL) {
+      return true;
+    }
+  }
+  return false;
+}
+
 #endif /* !defined(nsStyleStructInlines_h_) */