Bug 1019737 - Only layerize the scrollbar thumb if the target scroll frame has active scrolling. r=roc
authorMarkus Stange <mstange@themasta.com>
Wed, 04 Jun 2014 14:44:26 +0200
changeset 206924 083854f3d590d4ba69923ce0f6d77dd2447d99df
parent 206923 6b973f2ae66484bc07593f4f80fdbc1f04df884d
child 206925 9c65721ef16b5f06ea3464b11c4dac174c3ab039
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs1019737
milestone32.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 1019737 - Only layerize the scrollbar thumb if the target scroll frame has active scrolling. r=roc
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/generic/nsGfxScrollFrame.cpp
layout/xul/nsBoxFrame.cpp
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1599,16 +1599,31 @@ nsLayoutUtils::IsFixedPosFrameInDisplayP
   nsIFrame* parent = aFrame->GetParent();
   if (!parent || parent->GetParent() ||
       aFrame->StyleDisplay()->mPosition != NS_STYLE_POSITION_FIXED) {
     return false;
   }
   return ViewportHasDisplayPort(aFrame->PresContext(), aDisplayPort);
 }
 
+NS_DECLARE_FRAME_PROPERTY(ScrollbarThumbLayerized, nullptr)
+
+/* static */ void
+nsLayoutUtils::SetScrollbarThumbLayerization(nsIFrame* aThumbFrame, bool aLayerize)
+{
+  aThumbFrame->Properties().Set(ScrollbarThumbLayerized(),
+    reinterpret_cast<void*>(intptr_t(aLayerize)));
+}
+
+static bool
+IsScrollbarThumbLayerized(nsIFrame* aThumbFrame)
+{
+  return reinterpret_cast<intptr_t>(aThumbFrame->Properties().Get(ScrollbarThumbLayerized()));
+}
+
 static nsIFrame*
 GetAnimatedGeometryRootForFrame(nsIFrame* aFrame,
                                 const nsIFrame* aStopAtAncestor)
 {
   nsIFrame* f = aFrame;
   nsIFrame* stickyFrame = nullptr;
   while (f != aStopAtAncestor) {
     if (nsLayoutUtils::IsPopup(f))
@@ -1620,20 +1635,21 @@ GetAnimatedGeometryRootForFrame(nsIFrame
       // Viewport frames in a display port need to be animated geometry roots
       // for background-attachment:fixed elements.
       break;
     }
     nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(f);
     if (!parent)
       break;
     nsIAtom* parentType = parent->GetType();
-    // Treat the slider thumb as being as an active scrolled root
-    // so that it can move without repainting.
-    if (parentType == nsGkAtoms::sliderFrame)
+    // Treat the slider thumb as being as an active scrolled root when it wants
+    // its own layer so that it can move without repainting.
+    if (parentType == nsGkAtoms::sliderFrame && IsScrollbarThumbLayerized(f)) {
       break;
+    }
     // Sticky frames are active if their nearest scrollable frame
     // is also active, just keep a record of sticky frames that we
     // encounter for now.
     if (f->StyleDisplay()->mPosition == NS_STYLE_POSITION_STICKY &&
         !stickyFrame) {
       stickyFrame = f;
     }
     if (parentType == nsGkAtoms::scrollFrame) {
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -476,16 +476,22 @@ public:
    * which has a displayport. These frames get special treatment from the compositor.
    * aDisplayPort, if non-null, is set to the display port rectangle (relative to
    * the viewport).
    */
   static bool IsFixedPosFrameInDisplayPort(const nsIFrame* aFrame,
                                            nsRect* aDisplayPort = nullptr);
 
   /**
+   * Store whether aThumbFrame wants its own layer. This sets a property on
+   * the frame.
+   */
+  static void SetScrollbarThumbLayerization(nsIFrame* aThumbFrame, bool aLayerize);
+
+  /**
    * Finds the nearest ancestor frame to aItem that is considered to have (or
    * will have) "animated geometry". For example the scrolled frames of
    * scrollframes which are actively being scrolled fall into this category.
    * Frames with certain CSS properties that are being animated (e.g.
    * 'left'/'top' etc) are also placed in this category.
    * Frames with different active geometry roots are in different ThebesLayers,
    * so that we can animate the geometry root by changing its transform (either
    * on the main thread or in the compositor).
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -2174,18 +2174,19 @@ ScrollFrameHelper::AppendScrollPartsTo(n
   for (nsIFrame* kid = mOuter->GetFirstPrincipalChild(); kid; kid = kid->GetNextSibling()) {
     if (kid == mScrolledFrame ||
         (kid->IsPositioned() || overlayScrollbars) != aPositioned)
       continue;
 
     scrollParts.AppendElement(kid);
   }
 
-  mozilla::layers::FrameMetrics::ViewID scrollTargetId =
-    nsLayoutUtils::FindOrCreateIDFor(mScrolledFrame->GetContent());
+  mozilla::layers::FrameMetrics::ViewID scrollTargetId = IsScrollingActive()
+    ? nsLayoutUtils::FindOrCreateIDFor(mScrolledFrame->GetContent())
+    : mozilla::layers::FrameMetrics::NULL_SCROLL_ID;
 
   scrollParts.Sort(HoveredStateComparator());
 
   for (uint32_t i = 0; i < scrollParts.Length(); ++i) {
     uint32_t flags = 0;
     if (scrollParts[i] == mVScrollbarBox) {
       flags |= nsDisplayOwnLayer::VERTICAL_SCROLLBAR;
     }
--- a/layout/xul/nsBoxFrame.cpp
+++ b/layout/xul/nsBoxFrame.cpp
@@ -1306,18 +1306,19 @@ nsBoxFrame::BuildDisplayList(nsDisplayLi
 
   if (GetContent()->IsXUL()) {
     // forcelayer is only supported on XUL elements with box layout
     if (GetContent()->HasAttr(kNameSpaceID_None, nsGkAtoms::layer)) {
       forceLayer = true;
     } else {
       nsIFrame* parent = GetParentBox(this);
       if (parent && parent->GetType() == nsGkAtoms::sliderFrame) {
-        forceLayer = true;
         aBuilder->GetScrollbarInfo(&scrollTargetId, &flags);
+        forceLayer = (scrollTargetId != layers::FrameMetrics::NULL_SCROLL_ID);
+        nsLayoutUtils::SetScrollbarThumbLayerization(this, forceLayer);
       }
     }
     // Check for frames that are marked as a part of the region used
     // in calculating glass margins on Windows.
     const nsStyleDisplay* styles = StyleDisplay();
     if (styles && styles->mAppearance == NS_THEME_WIN_EXCLUDE_GLASS) {
       nsRect rect = nsRect(aBuilder->ToReferenceFrame(this), GetSize());
       aBuilder->AddExcludedGlassRegion(rect);