Bug 1349418 - Remove checkerboarding code and just use an opaque background color behind root scroll frames. r=kats
authorMarkus Stange <mstange@themasta.com>
Fri, 21 Apr 2017 14:02:15 +1200
changeset 355965 9316ff6512163e7d08e981de7ba4dc390ca6a926
parent 355964 e94824b92c00d84910271435ff8d19e256e3f6ee
child 355966 d083575592841cddd154b85598934c501db9886d
push id31752
push usercbook@mozilla.com
push dateTue, 02 May 2017 09:05:11 +0000
treeherdermozilla-central@48c0fd9c9ec5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1349418
milestone55.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 1349418 - Remove checkerboarding code and just use an opaque background color behind root scroll frames. r=kats
gfx/layers/LayerAttributes.h
gfx/layers/Layers.cpp
gfx/layers/Layers.h
gfx/layers/client/ClientTiledPaintedLayer.cpp
gfx/layers/client/TiledContentClient.cpp
gfx/layers/composite/ContainerLayerComposite.cpp
gfx/layers/composite/LayerManagerComposite.cpp
gfx/layers/composite/LayerManagerComposite.h
layout/base/PresShell.cpp
layout/painting/FrameLayerBuilder.cpp
layout/reftests/async-scrolling/checkerboard-2-ref.html
layout/reftests/async-scrolling/checkerboard-3-ref.html
--- a/gfx/layers/LayerAttributes.h
+++ b/gfx/layers/LayerAttributes.h
@@ -39,23 +39,16 @@ public:
   {
   }
 
   //
   // Setters.
   // All set methods return true if values changed, false otherwise.
   //
 
-  bool SetLayerBounds(const gfx::IntRect& aLayerBounds) {
-    if (mLayerBounds.IsEqualEdges(aLayerBounds)) {
-      return false;
-    }
-    mLayerBounds = aLayerBounds;
-    return true;
-  }
   bool SetPostScale(float aXScale, float aYScale) {
     if (mPostXScale == aXScale && mPostYScale == aYScale) {
       return false;
     }
     mPostXScale = aXScale;
     mPostYScale = aYScale;
     return true;
   }
@@ -190,19 +183,16 @@ public:
     }
     return true;
   }
 
   //
   // Getters.
   //
 
-  const gfx::IntRect& LayerBounds() const {
-    return mLayerBounds;
-  }
   float PostXScale() const {
     return mPostXScale;
   }
   float PostYScale() const {
     return mPostYScale;
   }
   uint32_t ContentFlags() const {
     return mContentFlags;
@@ -260,35 +250,33 @@ public:
   const LayerRect& StickyScrollRangeOuter() const {
     return mStickyPositionData->mOuter;
   }
   const LayerRect& StickyScrollRangeInner() const {
     return mStickyPositionData->mInner;
   }
 
   bool operator ==(const SimpleLayerAttributes& aOther) const {
-    return mLayerBounds == aOther.mLayerBounds &&
-           mTransform == aOther.mTransform &&
+    return mTransform == aOther.mTransform &&
            mTransformIsPerspective == aOther.mTransformIsPerspective &&
            mScrolledClip == aOther.mScrolledClip &&
            mPostXScale == aOther.mPostXScale &&
            mPostYScale == aOther.mPostYScale &&
            mContentFlags == aOther.mContentFlags &&
            mOpacity == aOther.mOpacity &&
            mIsFixedPosition == aOther.mIsFixedPosition &&
            mScrollbarTargetContainerId == aOther.mScrollbarTargetContainerId &&
            mScrollbarDirection == aOther.mScrollbarDirection &&
            mScrollbarThumbRatio == aOther.mScrollbarThumbRatio &&
            mIsScrollbarContainer == aOther.mIsScrollbarContainer &&
            mMixBlendMode == aOther.mMixBlendMode &&
            mForceIsolatedGroup == aOther.mForceIsolatedGroup;
   }
 
 private:
-  gfx::IntRect mLayerBounds;
   gfx::Matrix4x4 mTransform;
   bool mTransformIsPerspective;
   Maybe<LayerClip> mScrolledClip;
   float mPostXScale;
   float mPostYScale;
   uint32_t mContentFlags;
   float mOpacity;
   bool mIsFixedPosition;
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -571,18 +571,17 @@ Layer::CalculateScissorRect(const Render
   } else {
     currentClip = aCurrentScissorRect;
   }
 
   if (!clipLayer->GetLocalClipRect()) {
     return currentClip;
   }
 
-  if (GetLocalVisibleRegion().IsEmpty() &&
-      !(AsHostLayer() && AsHostLayer()->NeedToDrawCheckerboarding())) {
+  if (GetLocalVisibleRegion().IsEmpty()) {
     // When our visible region is empty, our parent may not have created the
     // intermediate surface that we would require for correct clipping; however,
     // this does not matter since we are invisible.
     // Make sure we still compute a clip rect if we want to draw checkboarding
     // for this layer, since we want to do this even if the layer is invisible.
     return RenderTargetIntRect(currentClip.TopLeft(), RenderTargetIntSize(0, 0));
   }
 
@@ -1845,19 +1844,16 @@ Layer::PrintInfo(std::stringstream& aStr
     AppendToString(aStream, GetBaseTransform(), " [transform=", "]");
   }
   if (!GetEffectiveTransform().IsIdentity()) {
     AppendToString(aStream, GetEffectiveTransform(), " [effective-transform=", "]");
   }
   if (GetTransformIsPerspective()) {
     aStream << " [perspective]";
   }
-  if (!GetLayerBounds().IsEmpty()) {
-    AppendToString(aStream, GetLayerBounds(), " [bounds=", "]");
-  }
   if (!mVisibleRegion.IsEmpty()) {
     AppendToString(aStream, mVisibleRegion.ToUnknownRegion(), " [visible=", "]");
   } else {
     aStream << " [not visible]";
   }
   if (!mEventRegions.IsEmpty()) {
     AppendToString(aStream, mEventRegions, " ", "");
   }
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -895,32 +895,16 @@ public:
     if (mSimpleAttrs.SetContentFlags(aFlags)) {
       MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ContentFlags", this));
       MutatedSimple();
     }
   }
 
   /**
    * CONSTRUCTION PHASE ONLY
-   * The union of the bounds of all the display item that got flattened
-   * into this layer. This is intended to be an approximation to the
-   * size of the layer if the nearest scrollable ancestor had an infinitely
-   * large displayport. Computing this more exactly is too expensive,
-   * but this approximation is sufficient for what we need to use it for.
-   */
-  virtual void SetLayerBounds(const gfx::IntRect& aLayerBounds)
-  {
-    if (mSimpleAttrs.SetLayerBounds(aLayerBounds)) {
-      MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) LayerBounds", this));
-      MutatedSimple();
-    }
-  }
-
-  /**
-   * CONSTRUCTION PHASE ONLY
    * Tell this layer which region will be visible. The visible region
    * is a region which contains all the contents of the layer that can
    * actually affect the rendering of the window. It can exclude areas
    * that are covered by opaque contents of other layers, and it can
    * exclude areas where this layer simply contains no content at all.
    * (This can be an overapproximation to the "true" visible region.)
    *
    * There is no general guarantee that drawing outside the bounds of the
@@ -1335,17 +1319,16 @@ public:
 
   // These getters can be used anytime.
   float GetOpacity() { return mSimpleAttrs.Opacity(); }
   gfx::CompositionOp GetMixBlendMode() const { return mSimpleAttrs.MixBlendMode(); }
   const Maybe<ParentLayerIntRect>& GetClipRect() const { return mClipRect; }
   const Maybe<LayerClip>& GetScrolledClip() const { return mSimpleAttrs.ScrolledClip(); }
   Maybe<ParentLayerIntRect> GetScrolledClipRect() const;
   uint32_t GetContentFlags() { return mSimpleAttrs.ContentFlags(); }
-  const gfx::IntRect& GetLayerBounds() const { return mSimpleAttrs.LayerBounds(); }
   const LayerIntRegion& GetVisibleRegion() const { return mVisibleRegion; }
   const ScrollMetadata& GetScrollMetadata(uint32_t aIndex) const;
   const FrameMetrics& GetFrameMetrics(uint32_t aIndex) const;
   uint32_t GetScrollMetadataCount() const { return mScrollMetadata.Length(); }
   const nsTArray<ScrollMetadata>& GetAllScrollMetadata() { return mScrollMetadata; }
   bool HasScrollableFrameMetrics() const;
   bool IsScrollInfoLayer() const;
   const EventRegions& GetEventRegions() const { return mEventRegions; }
--- a/gfx/layers/client/ClientTiledPaintedLayer.cpp
+++ b/gfx/layers/client/ClientTiledPaintedLayer.cpp
@@ -164,17 +164,17 @@ ClientTiledPaintedLayer::BeginPaint()
   const FrameMetrics& scrollMetrics = scrollAncestor.Metrics();
   const FrameMetrics& displayportMetrics = displayPortAncestor.Metrics();
 
   // Calculate the transform required to convert ParentLayer space of our
   // display port ancestor to the Layer space of this layer.
   ParentLayerToLayerMatrix4x4 transformDisplayPortToLayer =
     GetTransformToAncestorsParentLayer(this, displayPortAncestor).Inverse();
 
-  LayerRect layerBounds = ViewAs<LayerPixel>(Rect(GetLayerBounds()));
+  LayerRect layerBounds(GetVisibleRegion().GetBounds());
 
   // Compute the critical display port that applies to this layer in the
   // LayoutDevice space of this layer, but only if there is no OMT animation
   // on this layer. If there is an OMT animation then we need to draw the whole
   // visible region of this layer as determined by layout, because we don't know
   // what parts of it might move into view in the compositor.
   mPaintData.mHasTransformAnimation = hasTransformAnimation;
   if (!mPaintData.mHasTransformAnimation &&
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -1213,17 +1213,17 @@ ClientMultiTiledLayerBuffer::ComputeProg
       return aIsRepeated;
     }
   }
 
   Maybe<LayerRect> transformedCompositionBounds =
     GetCompositorSideCompositionBounds(scrollAncestor,
                                        aPaintData->mTransformToCompBounds,
                                        viewTransform,
-                                       ViewAs<LayerPixel>(Rect(mPaintedLayer.GetLayerBounds())));
+                                       LayerRect(mPaintedLayer.GetVisibleRegion().GetBounds()));
 
   if (!transformedCompositionBounds) {
     aPaintData->mPaintFinished = true;
     return false;
   }
 
   TILING_LOG("TILING %p: Progressive update transformed compositor bounds %s\n", &mPaintedLayer, Stringify(*transformedCompositionBounds).c_str());
 
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -207,18 +207,17 @@ ContainerPrepare(ContainerT* aContainer,
 
     if (layerToRender->GetLayer()->IsBackfaceHidden()) {
       continue;
     }
 
     // We don't want to skip container layers because otherwise their mPrepared
     // may be null which is not allowed.
     if (!layerToRender->GetLayer()->AsContainerLayer()) {
-      if (!layerToRender->GetLayer()->IsVisible() &&
-          !layerToRender->NeedToDrawCheckerboarding(nullptr)) {
+      if (!layerToRender->GetLayer()->IsVisible()) {
         CULLING_LOG("Sublayer %p has no effective visible region\n", layerToRender->GetLayer());
         continue;
       }
 
       if (clipRect.IsEmpty()) {
         CULLING_LOG("Sublayer %p has an empty world clip rect\n", layerToRender->GetLayer());
         continue;
       }
@@ -418,34 +417,16 @@ RenderLayers(ContainerT* aContainer, Lay
       for (const auto& metadata : layer->GetAllScrollMetadata()) {
         if (metadata.IsApzForceDisabled()) {
           aManager->DisabledApzWarning();
           break;
         }
       }
     }
 
-    Color color;
-    if (layerToRender->NeedToDrawCheckerboarding(&color)) {
-      if (gfxPrefs::APZHighlightCheckerboardedAreas()) {
-        color = Color(255 / 255.f, 188 / 255.f, 217 / 255.f, 1.f); // "Cotton Candy"
-      }
-      // Ideally we would want to intersect the checkerboard region from the APZ with the layer bounds
-      // and only fill in that area. However the layer bounds takes into account the base translation
-      // for the painted layer whereas the checkerboard region does not. One does not simply
-      // intersect areas in different coordinate spaces. So we do this a little more permissively
-      // and only fill in the background when we know there is checkerboard, which in theory
-      // should only occur transiently.
-      EffectChain effectChain(layer);
-      effectChain.mPrimaryEffect = new EffectSolidColor(color);
-      aManager->GetCompositor()->DrawGeometry(gfx::Rect(layer->GetLayerBounds()), clipRect,
-                                              effectChain, layer->GetEffectiveOpacity(),
-                                              layer->GetEffectiveTransform(), Nothing());
-    }
-
     if (layerToRender->HasLayerBeenComposited()) {
       // Composer2D will compose this layer so skip GPU composition
       // this time. The flag will be reset for the next composition phase
       // at the beginning of LayerManagerComposite::Rener().
       gfx::IntRect clearRect = layerToRender->GetClearRect();
       if (!clearRect.IsEmpty()) {
         // Clear layer's visible rect on FrameBuffer with transparent pixels
         gfx::Rect fbRect(clearRect.x, clearRect.y, clearRect.width, clearRect.height);
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -1496,45 +1496,16 @@ HostLayer::GetShadowTransform() {
 }
 
 bool
 LayerComposite::HasStaleCompositor() const
 {
   return mCompositeManager->GetCompositor() != mCompositor;
 }
 
-static bool
-LayerHasCheckerboardingAPZC(Layer* aLayer, Color* aOutColor)
-{
-  bool answer = false;
-  for (LayerMetricsWrapper i(aLayer, LayerMetricsWrapper::StartAt::BOTTOM); i; i = i.GetParent()) {
-    if (!i.Metrics().IsScrollable()) {
-      continue;
-    }
-    if (i.GetApzc() && i.GetApzc()->IsCurrentlyCheckerboarding()) {
-      if (aOutColor) {
-        *aOutColor = i.Metadata().GetBackgroundColor();
-      }
-      answer = true;
-      break;
-    }
-    break;
-  }
-  return answer;
-}
-
-bool
-LayerComposite::NeedToDrawCheckerboarding(gfx::Color* aOutCheckerboardingColor)
-{
-  return GetLayer()->Manager()->AsyncPanZoomEnabled() &&
-         (GetLayer()->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
-         GetLayer()->IsOpaqueForVisibility() &&
-         LayerHasCheckerboardingAPZC(GetLayer(), aOutCheckerboardingColor);
-}
-
 #ifndef MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS
 
 /*static*/ bool
 LayerManagerComposite::SupportsDirectTexturing()
 {
   return false;
 }
 
--- a/gfx/layers/composite/LayerManagerComposite.h
+++ b/gfx/layers/composite/LayerManagerComposite.h
@@ -584,22 +584,16 @@ public:
   float GetShadowOpacity() { return mShadowOpacity; }
   const Maybe<ParentLayerIntRect>& GetShadowClipRect() { return mShadowClipRect; }
   const LayerIntRegion& GetShadowVisibleRegion() { return mShadowVisibleRegion; }
   const gfx::Matrix4x4& GetShadowBaseTransform() { return mShadowTransform; }
   gfx::Matrix4x4 GetShadowTransform();
   bool GetShadowTransformSetByAnimation() { return mShadowTransformSetByAnimation; }
   bool GetShadowOpacitySetByAnimation() { return mShadowOpacitySetByAnimation; }
 
-  /**
-   * Return true if a checkerboarding background color needs to be drawn
-   * for this layer.
-   */
-  virtual bool NeedToDrawCheckerboarding(gfx::Color* aOutCheckerboardingColor = nullptr) { return false; }
-
 protected:
   HostLayerManager* mCompositorManager;
 
   gfx::Matrix4x4 mShadowTransform;
   LayerIntRegion mShadowVisibleRegion;
   Maybe<ParentLayerIntRect> mShadowClipRect;
   float mShadowOpacity;
   bool mShadowTransformSetByAnimation;
@@ -689,18 +683,16 @@ public:
 
   /**
    * Return the part of the visible region that has been fully rendered.
    * While progressive drawing is in progress this region will be
    * a subset of the shadow visible region.
    */
   virtual nsIntRegion GetFullyRenderedRegion();
 
-  virtual bool NeedToDrawCheckerboarding(gfx::Color* aOutCheckerboardingColor = nullptr);
-
 protected:
   LayerManagerComposite* mCompositeManager;
 
   RefPtr<Compositor> mCompositor;
   bool mDestroyed;
   bool mLayerComposited;
   gfx::IntRect mClearRect;
 };
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -5308,30 +5308,39 @@ PresShell::AddCanvasBackgroundColorItem(
   nscolor bgcolor = NS_ComposeColors(aBackstopColor, mCanvasBackgroundColor);
   if (NS_GET_A(bgcolor) == 0)
     return;
 
   // To make layers work better, we want to avoid having a big non-scrolled
   // color background behind a scrolled transparent background. Instead,
   // we'll try to move the color background into the scrolled content
   // by making nsDisplayCanvasBackground paint it.
+  bool addedScrollingBackgroundColor = false;
   if (!aFrame->GetParent()) {
     nsIScrollableFrame* sf =
       aFrame->PresContext()->PresShell()->GetRootScrollFrameAsScrollable();
     if (sf) {
       nsCanvasFrame* canvasFrame = do_QueryFrame(sf->GetScrolledFrame());
       if (canvasFrame && canvasFrame->IsVisibleForPainting(&aBuilder)) {
-        if (AddCanvasBackgroundColor(aList, canvasFrame, bgcolor, mHasCSSBackgroundColor))
-          return;
-      }
-    }
-  }
-
-  aList.AppendNewToBottom(
-    new (&aBuilder) nsDisplaySolidColor(&aBuilder, aFrame, aBounds, bgcolor));
+        addedScrollingBackgroundColor =
+          AddCanvasBackgroundColor(aList, canvasFrame, bgcolor, mHasCSSBackgroundColor);
+      }
+    }
+  }
+
+  if (!addedScrollingBackgroundColor ||
+      (nsLayoutUtils::UsesAsyncScrolling(aFrame) && NS_GET_A(bgcolor) == 255)) {
+    // With async scrolling, we'd like to have two instances of the background
+    // color: one that scrolls with the content (for the reasons stated above),
+    // and one underneath which does not scroll with the content, but which can
+    // be shown during checkerboarding and overscroll.
+    // We can only do that if the color is opaque.
+    aList.AppendNewToBottom(
+      new (&aBuilder) nsDisplaySolidColor(&aBuilder, aFrame, aBounds, bgcolor));
+  }
 }
 
 static bool IsTransparentContainerElement(nsPresContext* aPresContext)
 {
   nsCOMPtr<nsIDocShell> docShell = aPresContext->GetDocShell();
   if (!docShell) {
     return false;
   }
--- a/layout/painting/FrameLayerBuilder.cpp
+++ b/layout/painting/FrameLayerBuilder.cpp
@@ -656,20 +656,16 @@ public:
   /*
    * Updates mCommonClipCount by checking for rounded rect clips in common
    * between the clip on a new item (aCurrentClip) and the common clips
    * on items already in the layer (the first mCommonClipCount rounded rects
    * in mItemClip).
    */
   void UpdateCommonClipCount(const DisplayItemClip& aCurrentClip);
   /**
-   * The union of all the bounds of the display items in this layer.
-   */
-  nsIntRect mBounds;
-  /**
    * The region of visible content above the layer and below the
    * next PaintedLayerData currently in the stack, if any.
    * This is a conservative approximation: it contains the true region.
    */
   nsIntRegion mVisibleAboveRegion;
   /**
    * All the display items that have been assigned to this painted layer.
    * These items get added by Accumulate().
@@ -3236,20 +3232,16 @@ void ContainerState::FinishPaintedLayerD
     newLayerEntry->mVisibleRegion = data->mVisibleRegion;
     newLayerEntry->mOpaqueRegion = data->mOpaqueRegion;
     newLayerEntry->mHideAllLayersBelow = data->mHideAllLayersBelow;
     newLayerEntry->mOpaqueForAnimatedGeometryRootParent = data->mOpaqueForAnimatedGeometryRootParent;
   } else {
     SetOuterVisibleRegionForLayer(layer, data->mVisibleRegion);
   }
 
-  nsIntRect layerBounds = data->mBounds;
-  layerBounds.MoveBy(-GetTranslationForPaintedLayer(data->mLayer));
-  layer->SetLayerBounds(layerBounds);
-
 #ifdef MOZ_DUMP_PAINTING
   if (!data->mLog.IsEmpty()) {
     if (PaintedLayerData* containingPld = mLayerBuilder->GetContainingPaintedLayerData()) {
       containingPld->mLayer->AddExtraDumpInfo(nsCString(data->mLog));
     } else {
       layer->AddExtraDumpInfo(nsCString(data->mLog));
     }
   }
@@ -3436,20 +3428,16 @@ PaintedLayerData::Accumulate(ContainerSt
                             nsDisplayItem* aItem,
                             const nsIntRegion& aClippedOpaqueRegion,
                             const nsIntRect& aVisibleRect,
                             const DisplayItemClip& aClip,
                             LayerState aLayerState)
 {
   FLB_LOG_PAINTED_LAYER_DECISION(this, "Accumulating dp=%s(%p), f=%p against pld=%p\n", aItem->Name(), aItem, aItem->Frame(), this);
 
-  bool snap;
-  nsRect itemBounds = aItem->GetBounds(aState->mBuilder, &snap);
-  mBounds = mBounds.Union(aState->ScaleToOutsidePixels(itemBounds, snap));
-
   if (aState->mBuilder->NeedToForceTransparentSurfaceForItem(aItem)) {
     mForceTransparentSurface = true;
   }
   if (aState->mParameters.mDisableSubpixelAntialiasingInDescendants) {
     // Disable component alpha.
     // Note that the transform (if any) on the PaintedLayer is always an integer translation so
     // we don't have to factor that in here.
     aItem->DisableComponentAlpha();
@@ -3761,17 +3749,17 @@ ContainerState::GetDisplayPortForAnimate
 {
   if (mLastDisplayPortAGR == aAnimatedGeometryRoot) {
     return mLastDisplayPortRect;
   }
 
   mLastDisplayPortAGR = aAnimatedGeometryRoot;
 
   nsIScrollableFrame* sf = nsLayoutUtils::GetScrollableFrameFor(*aAnimatedGeometryRoot);
-  if (sf == nullptr) {
+  if (sf == nullptr || nsLayoutUtils::UsesAsyncScrolling(*aAnimatedGeometryRoot)) {
     mLastDisplayPortRect = nsRect();
     return mLastDisplayPortRect;
   }
 
   bool usingDisplayport =
     nsLayoutUtils::GetDisplayPort((*aAnimatedGeometryRoot)->GetContent(), &mLastDisplayPortRect,
                                   RelativeTo::ScrollFrame);
   if (!usingDisplayport) {
--- a/layout/reftests/async-scrolling/checkerboard-2-ref.html
+++ b/layout/reftests/async-scrolling/checkerboard-2-ref.html
@@ -1,6 +1,7 @@
 <!DOCTYPE HTML>
 <html>
 <body style="background-color: green; overflow:hidden">
+  <div style="position:fixed; left: 0px; top: 0px; width: 100px; height: 500px; background-color: purple; z-index: -1"></div>
   <div style="position:absolute; left: 0px; top: 0px; background-color: yellow; width: 100px; height: 200px"></div>
   <div style="position:fixed; left: 10px; top: 10px; width: 10px; height: 10px; background-color: blue"></div>
 </body>
--- a/layout/reftests/async-scrolling/checkerboard-3-ref.html
+++ b/layout/reftests/async-scrolling/checkerboard-3-ref.html
@@ -1,5 +1,6 @@
 <!DOCTYPE HTML>
 <html>
 <body style="background-color: green; overflow:hidden">
+  <div style="position:fixed; left: 0px; top: 0px; width: 100px; height: 500px; background-color: purple; z-index: -1"></div>
   <div style="position:fixed; left: 10px; top: 10px; width: 10px; height: 10px; background-color: blue"></div>
 </body>