Back out 6 changesets (bug 1227327) for Android reftest failures in 942672-1.html, background-position-2b.html and background-position-2c.html
authorPhil Ringnalda <philringnalda@gmail.com>
Tue, 03 May 2016 21:49:07 -0700
changeset 296049 d2b9a2c891fcfe0abacece691bfb76211ea593bf
parent 296048 54e84fa84d6defa32626421af67e634203256122
child 296050 311c7ea8803d326cec715404256c86beb8af3804
child 296086 7ac47a347557cc7a7c125ff0136ff0ce20c9cef7
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)
bugs1227327, 942672
milestone49.0a1
backs outc9b0ba301426227d8d820ba16e2f3c4e889db5ed
c857ad1fa01c43d0f2ad94f02a71c513c433c009
4ba58cd943103bdc60b57f23635b7514ba3ffc00
30e394faeb237d67c94950c7e019742dd0869ac5
ce7fd04cc749ce34a30737df0a3ea575bb1ef356
e0fe45294034f513f71b6587c72931a2f047c506
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
Back out 6 changesets (bug 1227327) for Android reftest failures in 942672-1.html, background-position-2b.html and background-position-2c.html CLOSED TREE Backed out changeset c9b0ba301426 (bug 1227327) Backed out changeset c857ad1fa01c (bug 1227327) Backed out changeset 4ba58cd94310 (bug 1227327) Backed out changeset 30e394faeb23 (bug 1227327) Backed out changeset ce7fd04cc749 (bug 1227327) Backed out changeset e0fe45294034 (bug 1227327)
layout/base/RestyleManager.cpp
layout/base/nsChangeHint.h
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/forms/nsButtonFrameRenderer.cpp
layout/forms/nsButtonFrameRenderer.h
layout/forms/nsFieldSetFrame.cpp
layout/forms/nsFieldSetFrame.h
layout/generic/nsCanvasFrame.h
layout/generic/nsFrame.cpp
layout/reftests/box-shadow/611574-2-ref.html
layout/reftests/box-shadow/611574-2.html
layout/reftests/invalidation/background-position-2-ref.html
layout/reftests/invalidation/background-position-2a.html
layout/reftests/invalidation/background-position-2b.html
layout/reftests/invalidation/background-position-2c.html
layout/reftests/invalidation/background-position-2d.html
layout/reftests/invalidation/background-position-2e.html
layout/reftests/invalidation/background-position-2f.html
layout/reftests/invalidation/reftest.list
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/tables/nsTableFrame.cpp
layout/xul/nsGroupBoxFrame.cpp
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -881,29 +881,16 @@ 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,25 +189,16 @@ 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
@@ -307,35 +298,33 @@ inline nsChangeHint operator^=(nsChangeH
           nsChangeHint_ChildrenOnlyTransform | \
           nsChangeHint_RecomputePosition | \
           nsChangeHint_UpdateContainingBlock | \
           nsChangeHint_BorderStyleNoneChange | \
           nsChangeHint_NeedReflow | \
           nsChangeHint_ReflowChangesSizeOrPosition | \
           nsChangeHint_ClearAncestorIntrinsics | \
           nsChangeHint_UpdateComputedBSize | \
-          nsChangeHint_UpdateUsesOpacity | \
-          nsChangeHint_UpdateBackgroundPosition)
+          nsChangeHint_UpdateUsesOpacity)
 
 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_UpdateBackgroundPosition));
+    nsChangeHint_UpdateUsesOpacity));
 
   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/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -2306,21 +2306,19 @@ RegisterThemeGeometry(nsDisplayListBuild
         borderBox.ToNearestPixels(
           aFrame->PresContext()->AppUnitsPerDevPixel())));
   }
 }
 
 nsDisplayBackgroundImage::nsDisplayBackgroundImage(nsDisplayListBuilder* aBuilder,
                                                    nsIFrame* aFrame,
                                                    uint32_t aLayer,
-                                                   const nsRect& aBackgroundRect,
                                                    const nsStyleBackground* aBackgroundStyle)
   : nsDisplayImageContainer(aBuilder, aFrame)
   , mBackgroundStyle(aBackgroundStyle)
-  , mBackgroundRect(aBackgroundRect)
   , mLayer(aLayer)
   , mIsRasterImage(false)
 {
   MOZ_COUNT_CTOR(nsDisplayBackgroundImage);
 
   nsPresContext* presContext = mFrame->PresContext();
   uint32_t flags = aBuilder->GetBackgroundPaintFlags();
   nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
@@ -2378,44 +2376,42 @@ static nsStyleContext* GetBackgroundStyl
   }
   return sc;
 }
 
 /* static */ void
 SetBackgroundClipRegion(DisplayListClipState::AutoSaveRestore& aClipState,
                         nsIFrame* aFrame, const nsPoint& aToReferenceFrame,
                         const nsStyleImageLayers::Layer& aLayer,
-                        const nsRect& aBackgroundRect,
                         bool aWillPaintBorder)
 {
+  nsRect borderBox = nsRect(aToReferenceFrame, aFrame->GetSize());
+
   nsCSSRendering::ImageLayerClipState clip;
   nsCSSRendering::GetImageLayerClip(aLayer, aFrame, *aFrame->StyleBorder(),
-                                    aBackgroundRect, aBackgroundRect, aWillPaintBorder,
+                                    borderBox, borderBox, aWillPaintBorder,
                                     aFrame->PresContext()->AppUnitsPerDevPixel(),
                                     &clip);
 
   if (clip.mHasAdditionalBGClipArea) {
     aClipState.ClipContentDescendants(clip.mAdditionalBGClipArea, clip.mBGClipArea,
                                       clip.mHasRoundedCorners ? clip.mRadii : nullptr);
   } else {
     aClipState.ClipContentDescendants(clip.mBGClipArea, clip.mHasRoundedCorners ? clip.mRadii : nullptr);
   }
 }
 
 
 /*static*/ bool
 nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
                                                      nsIFrame* aFrame,
-                                                     const nsRect& aBackgroundRect,
-                                                     nsDisplayList* aList,
-                                                     bool aAllowWillPaintBorderOptimization)
+                                                     nsDisplayList* aList)
 {
   nsStyleContext* bgSC = nullptr;
   const nsStyleBackground* bg = nullptr;
-  nsRect bgRect = aBackgroundRect + aBuilder->ToReferenceFrame(aFrame);
   nsPresContext* presContext = aFrame->PresContext();
   bool isThemed = aFrame->IsThemed();
   if (!isThemed) {
     bgSC = GetBackgroundStyleContext(aFrame);
     if (bgSC) {
       bg = bgSC->StyleBackground();
     }
   }
@@ -2430,18 +2426,17 @@ nsDisplayBackgroundImage::AppendBackgrou
       nsCSSRendering::DetermineBackgroundColor(presContext, bgSC, aFrame,
                                                drawBackgroundImage, drawBackgroundColor);
   }
 
   const nsStyleBorder* borderStyle = aFrame->StyleBorder();
   const nsStyleEffects* effectsStyle = aFrame->StyleEffects();
   bool hasInsetShadow = effectsStyle->mBoxShadow &&
                         effectsStyle->mBoxShadow->HasShadowWithInset(true);
-  bool willPaintBorder = aAllowWillPaintBorderOptimization &&
-                         !isThemed && !hasInsetShadow &&
+  bool willPaintBorder = !isThemed && !hasInsetShadow &&
                          borderStyle->HasBorder();
 
   nsPoint toRef = aBuilder->ToReferenceFrame(aFrame);
 
   // An auxiliary list is necessary in case we have background blending; if that
   // is the case, background items need to be wrapped by a blend container to
   // isolate blending to the background
   nsDisplayList bgItemList;
@@ -2456,33 +2451,33 @@ nsDisplayBackgroundImage::AppendBackgrou
       // doesn't help much (there are no tiling issues) and clipping the
       // background breaks detection of the element's border-box being
       // opaque. For nonzero border-radius we still need it because we
       // want to inset the background if possible to avoid antialiasing
       // artifacts along the rounded corners.
       bool useWillPaintBorderOptimization = willPaintBorder &&
           nsLayoutUtils::HasNonZeroCorner(borderStyle->mBorderRadius);
       SetBackgroundClipRegion(clipState, aFrame, toRef,
-                              bg->BottomLayer(), bgRect,
+                              bg->BottomLayer(),
                               useWillPaintBorderOptimization);
     }
     bgItemList.AppendNewToTop(
-        new (aBuilder) nsDisplayBackgroundColor(aBuilder, aFrame, bgRect, bg,
+        new (aBuilder) nsDisplayBackgroundColor(aBuilder, aFrame, bg,
                                                 drawBackgroundColor ? color : NS_RGBA(0, 0, 0, 0)));
   }
 
   if (isThemed) {
     nsITheme* theme = presContext->GetTheme();
     if (theme->NeedToClearBackgroundBehindWidget(aFrame, aFrame->StyleDisplay()->mAppearance) &&
         aBuilder->IsInRootChromeDocumentOrPopup() && !aBuilder->IsInTransform()) {
       bgItemList.AppendNewToTop(
         new (aBuilder) nsDisplayClearBackground(aBuilder, aFrame));
     }
     nsDisplayThemedBackground* bgItem =
-      new (aBuilder) nsDisplayThemedBackground(aBuilder, aFrame, bgRect);
+      new (aBuilder) nsDisplayThemedBackground(aBuilder, aFrame);
     bgItemList.AppendNewToTop(bgItem);
     aList->AppendToTop(&bgItemList);
     return true;
   }
 
   if (!bg) {
     aList->AppendToTop(&bgItemList);
     return false;
@@ -2503,22 +2498,22 @@ nsDisplayBackgroundImage::AppendBackgrou
     if (bg->mImage.mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) {
       needBlendContainer = true;
     }
 
     DisplayListClipState::AutoSaveRestore clipState(aBuilder);
     if (!aBuilder->IsForEventDelivery()) {
       const nsStyleImageLayers::Layer& layer = bg->mImage.mLayers[i];
       SetBackgroundClipRegion(clipState, aFrame, toRef,
-                              layer, bgRect, willPaintBorder);
+                              layer, willPaintBorder);
     }
 
     nsDisplayList thisItemList;
     nsDisplayBackgroundImage* bgItem =
-      new (aBuilder) nsDisplayBackgroundImage(aBuilder, aFrame, i, bgRect, bg);
+      new (aBuilder) nsDisplayBackgroundImage(aBuilder, aFrame, i, bg);
 
     if (bgItem->ShouldFixToViewport(aBuilder)) {
       thisItemList.AppendNewToTop(
         nsDisplayFixedPosition::CreateForFixedBackground(aBuilder, aFrame, bgItem, i));
     } else {
       thisItemList.AppendNewToTop(bgItem);
     }
 
@@ -2775,37 +2770,44 @@ nsDisplayBackgroundImage::ComputeVisibil
   // frame. We don't want this display item to show up and confuse
   // anything.
   return mBackgroundStyle;
 }
 
 /* static */ nsRegion
 nsDisplayBackgroundImage::GetInsideClipRegion(nsDisplayItem* aItem,
                                               uint8_t aClip,
-                                              const nsRect& aRect,
-                                              const nsRect& aBackgroundRect)
+                                              const nsRect& aRect)
 {
   nsRegion result;
   if (aRect.IsEmpty())
     return result;
 
   nsIFrame *frame = aItem->Frame();
 
-  nsRect clipRect = aBackgroundRect;
+  nsRect clipRect;
   if (frame->GetType() == nsGkAtoms::canvasFrame) {
     nsCanvasFrame* canvasFrame = static_cast<nsCanvasFrame*>(frame);
     clipRect = canvasFrame->CanvasArea() + aItem->ToReferenceFrame();
-  } else if (aClip == NS_STYLE_IMAGELAYER_CLIP_PADDING ||
-             aClip == NS_STYLE_IMAGELAYER_CLIP_CONTENT) {
-    nsMargin border = frame->GetUsedBorder();
-    if (aClip == NS_STYLE_IMAGELAYER_CLIP_CONTENT) {
-      border += frame->GetUsedPadding();
+  } else {
+    switch (aClip) {
+    case NS_STYLE_IMAGELAYER_CLIP_BORDER:
+    case NS_STYLE_IMAGELAYER_CLIP_TEXT:
+      clipRect = nsRect(aItem->ToReferenceFrame(), frame->GetSize());
+      break;
+    case NS_STYLE_IMAGELAYER_CLIP_PADDING:
+      clipRect = frame->GetPaddingRect() - frame->GetPosition() + aItem->ToReferenceFrame();
+      break;
+    case NS_STYLE_IMAGELAYER_CLIP_CONTENT:
+      clipRect = frame->GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
+      break;
+    default:
+      NS_NOTREACHED("Unknown clip type");
+      return result;
     }
-    border.ApplySkipSides(frame->GetSkipSides());
-    clipRect.Deflate(border);
   }
 
   return clipRect.Intersect(aRect);
 }
 
 nsRegion
 nsDisplayBackgroundImage::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                           bool* aSnap) {
@@ -2823,17 +2825,17 @@ nsDisplayBackgroundImage::GetOpaqueRegio
   // content order which we'll produce here.
   // Of course, if there's only one frame in the flow, it doesn't matter.
   if (mFrame->StyleBorder()->mBoxDecorationBreak ==
         NS_STYLE_BOX_DECORATION_BREAK_CLONE ||
       (!mFrame->GetPrevContinuation() && !mFrame->GetNextContinuation())) {
     const nsStyleImageLayers::Layer& layer = mBackgroundStyle->mImage.mLayers[mLayer];
     if (layer.mImage.IsOpaque() && layer.mBlendMode == NS_STYLE_BLEND_NORMAL &&
         layer.mClip != NS_STYLE_IMAGELAYER_CLIP_TEXT) {
-      result = GetInsideClipRegion(this, layer.mClip, mBounds, mBackgroundRect);
+      result = GetInsideClipRegion(this, layer.mClip, mBounds);
     }
   }
 
   return result;
 }
 
 bool
 nsDisplayBackgroundImage::IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) {
@@ -2849,17 +2851,17 @@ nsDisplayBackgroundImage::GetPositioning
 {
   if (!mBackgroundStyle) {
     return nsRect();
   }
   nsIFrame* attachedToFrame;
   bool transformedFixed;
   return nsCSSRendering::ComputeImageLayerPositioningArea(
       mFrame->PresContext(), mFrame,
-      mBackgroundRect,
+      nsRect(ToReferenceFrame(), mFrame->GetSize()),
       mBackgroundStyle->mImage.mLayers[mLayer],
       &attachedToFrame,
       &transformedFixed) + ToReferenceFrame();
 }
 
 bool
 nsDisplayBackgroundImage::RenderingMightDependOnPositioningAreaSizeChange()
 {
@@ -2901,28 +2903,29 @@ nsDisplayBackgroundImage::Paint(nsDispla
 
 void
 nsDisplayBackgroundImage::PaintInternal(nsDisplayListBuilder* aBuilder,
                                         nsRenderingContext* aCtx, const nsRect& aBounds,
                                         nsRect* aClipRect) {
   uint32_t flags = aBuilder->GetBackgroundPaintFlags();
   CheckForBorderItem(this, flags);
 
+  nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
   gfxContext* ctx = aCtx->ThebesContext();
   uint8_t clip = mBackgroundStyle->mImage.mLayers[mLayer].mClip;
 
   if (clip == NS_STYLE_IMAGELAYER_CLIP_TEXT) {
     ctx->Save();
-    ClipBackgroundByText(mFrame, aCtx, mBackgroundRect);
+    ClipBackgroundByText(mFrame, aCtx, borderBox);
   }
 
   image::DrawResult result =
     nsCSSRendering::PaintBackground(mFrame->PresContext(), *aCtx, mFrame,
                                     aBounds,
-                                    mBackgroundRect,
+                                    borderBox,
                                     flags, aClipRect, mLayer,
                                     CompositionOp::OP_OVER);
 
   if (clip == NS_STYLE_IMAGELAYER_CLIP_TEXT) {
     ctx->Restore();
   }
 
   nsDisplayBackgroundGeometry::UpdateDrawResult(this, result);
@@ -2987,48 +2990,47 @@ nsDisplayBackgroundImage::GetBounds(nsDi
 nsRect
 nsDisplayBackgroundImage::GetBoundsInternal(nsDisplayListBuilder* aBuilder) {
   nsPresContext* presContext = mFrame->PresContext();
 
   if (!mBackgroundStyle) {
     return nsRect();
   }
 
-  nsRect clipRect = mBackgroundRect;
+  nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
+  nsRect clipRect = borderBox;
   if (mFrame->GetType() == nsGkAtoms::canvasFrame) {
     nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
     clipRect = frame->CanvasArea() + ToReferenceFrame();
   } else if (nsLayoutUtils::UsesAsyncScrolling(mFrame) && IsNonEmptyFixedImage()) {
     // If this is a background-attachment:fixed image, and APZ is enabled,
     // async scrolling could reveal additional areas of the image, so don't
     // clip it beyond clipping to the document's viewport.
     nsIFrame* rootFrame = presContext->PresShell()->GetRootFrame();
     nsRect rootRect = rootFrame->GetRectRelativeToSelf();
     if (nsLayoutUtils::TransformRect(rootFrame, mFrame, rootRect) == nsLayoutUtils::TRANSFORM_SUCCEEDED) {
       clipRect = clipRect.Union(rootRect + aBuilder->ToReferenceFrame(mFrame));
     }
   }
   const nsStyleImageLayers::Layer& layer = mBackgroundStyle->mImage.mLayers[mLayer];
   return nsCSSRendering::GetBackgroundLayerRect(presContext, mFrame,
-                                                mBackgroundRect, clipRect, layer,
+                                                borderBox, clipRect, layer,
                                                 aBuilder->GetBackgroundPaintFlags());
 }
 
 uint32_t
 nsDisplayBackgroundImage::GetPerFrameKey()
 {
   return (mLayer << nsDisplayItem::TYPE_BITS) |
     nsDisplayItem::GetPerFrameKey();
 }
 
 nsDisplayThemedBackground::nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder,
-                                                     nsIFrame* aFrame,
-                                                     const nsRect& aBackgroundRect)
+                                                     nsIFrame* aFrame)
   : nsDisplayItem(aBuilder, aFrame)
-  , mBackgroundRect(aBackgroundRect)
 {
   MOZ_COUNT_CTOR(nsDisplayThemedBackground);
 
   const nsStyleDisplay* disp = mFrame->StyleDisplay();
   mAppearance = disp->mAppearance;
   mFrame->IsThemed(disp, &mThemeTransparency);
 
   // Perform necessary RegisterThemeGeometry
@@ -3061,30 +3063,30 @@ nsDisplayThemedBackground::WriteDebugInf
 }
 
 void
 nsDisplayThemedBackground::HitTest(nsDisplayListBuilder* aBuilder,
                                   const nsRect& aRect,
                                   HitTestState* aState,
                                   nsTArray<nsIFrame*> *aOutFrames)
 {
-  // Assume that any point in our background rect is a hit.
-  if (mBackgroundRect.Intersects(aRect)) {
+  // Assume that any point in our border rect is a hit.
+  if (nsRect(ToReferenceFrame(), mFrame->GetSize()).Intersects(aRect)) {
     aOutFrames->AppendElement(mFrame);
   }
 }
 
 nsRegion
 nsDisplayThemedBackground::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                            bool* aSnap) {
   nsRegion result;
   *aSnap = false;
 
   if (mThemeTransparency == nsITheme::eOpaque) {
-    result = mBackgroundRect;
+    result = nsRect(ToReferenceFrame(), mFrame->GetSize());
   }
   return result;
 }
 
 bool
 nsDisplayThemedBackground::IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) {
   if (mAppearance == NS_THEME_WIN_BORDERLESS_GLASS ||
       mAppearance == NS_THEME_WIN_GLASS) {
@@ -3099,17 +3101,17 @@ nsDisplayThemedBackground::ProvidesFontS
 {
   nsITheme* theme = mFrame->PresContext()->GetTheme();
   return theme->WidgetProvidesFontSmoothingBackgroundColor(mFrame, mAppearance, aColor);
 }
 
 nsRect
 nsDisplayThemedBackground::GetPositioningArea()
 {
-  return mBackgroundRect;
+  return nsRect(ToReferenceFrame(), mFrame->GetSize());
 }
 
 void
 nsDisplayThemedBackground::Paint(nsDisplayListBuilder* aBuilder,
                                  nsRenderingContext* aCtx)
 {
   PaintInternal(aBuilder, aCtx, mVisibleRect, nullptr);
 }
@@ -3118,21 +3120,22 @@ nsDisplayThemedBackground::Paint(nsDispl
 void
 nsDisplayThemedBackground::PaintInternal(nsDisplayListBuilder* aBuilder,
                                          nsRenderingContext* aCtx, const nsRect& aBounds,
                                          nsRect* aClipRect)
 {
   // XXXzw this ignores aClipRect.
   nsPresContext* presContext = mFrame->PresContext();
   nsITheme *theme = presContext->GetTheme();
-  nsRect drawing(mBackgroundRect);
+  nsRect borderArea(ToReferenceFrame(), mFrame->GetSize());
+  nsRect drawing(borderArea);
   theme->GetWidgetOverflow(presContext->DeviceContext(), mFrame, mAppearance,
                            &drawing);
   drawing.IntersectRect(drawing, aBounds);
-  theme->DrawWidgetBackground(aCtx, mFrame, mAppearance, mBackgroundRect, drawing);
+  theme->DrawWidgetBackground(aCtx, mFrame, mAppearance, borderArea, drawing);
 }
 
 bool nsDisplayThemedBackground::IsWindowActive()
 {
   EventStates docState = mFrame->GetContent()->OwnerDoc()->GetDocumentState();
   return !docState.HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE);
 }
 
@@ -3167,17 +3170,17 @@ nsDisplayThemedBackground::GetBounds(nsD
   *aSnap = true;
   return mBounds;
 }
 
 nsRect
 nsDisplayThemedBackground::GetBoundsInternal() {
   nsPresContext* presContext = mFrame->PresContext();
 
-  nsRect r = mBackgroundRect - ToReferenceFrame();
+  nsRect r(nsPoint(0,0), mFrame->GetSize());
   presContext->GetTheme()->
       GetWidgetOverflow(presContext->DeviceContext(), mFrame,
                         mFrame->StyleDisplay()->mAppearance, &r);
   return r + ToReferenceFrame();
 }
 
 void
 nsDisplayImageContainer::ConfigureLayer(ImageLayer* aLayer,
@@ -3312,50 +3315,52 @@ nsDisplayBackgroundColor::CanApplyOpacit
 void
 nsDisplayBackgroundColor::Paint(nsDisplayListBuilder* aBuilder,
                                 nsRenderingContext* aCtx)
 {
   if (mColor == Color()) {
     return;
   }
 
+  nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
+
 #if 0
   // See https://bugzilla.mozilla.org/show_bug.cgi?id=1148418#c21 for why this
   // results in a precision induced rounding issue that makes the rect one
   // pixel shorter in rare cases. Disabled in favor of the old code for now.
   // Note that the pref layout.css.devPixelsPerPx needs to be set to 1 to
   // reproduce the bug.
   //
   // TODO:
   // This new path does not include support for background-clip:text; need to
   // be fixed if/when we switch to this new code path.
 
   DrawTarget& aDrawTarget = *aCtx->GetDrawTarget();
 
-  Rect rect = NSRectToSnappedRect(mBackgroundRect,
+  Rect rect = NSRectToSnappedRect(borderBox,
                                   mFrame->PresContext()->AppUnitsPerDevPixel(),
                                   aDrawTarget);
   ColorPattern color(ToDeviceColor(mColor));
   aDrawTarget.FillRect(rect, color);
 #else
   gfxContext* ctx = aCtx->ThebesContext();
 
   uint8_t clip = mBackgroundStyle->mImage.mLayers[0].mClip;
   if (clip == NS_STYLE_IMAGELAYER_CLIP_TEXT) {
     gfxContextAutoSaveRestore save(ctx);
 
-    ClipBackgroundByText(mFrame, aCtx, mBackgroundRect);
+    ClipBackgroundByText(mFrame, aCtx, borderBox);
     ctx->SetColor(mColor);
     ctx->Fill();
 
     return;
   }
 
   gfxRect bounds =
-    nsLayoutUtils::RectToGfxRect(mBackgroundRect, mFrame->PresContext()->AppUnitsPerDevPixel());
+    nsLayoutUtils::RectToGfxRect(borderBox, mFrame->PresContext()->AppUnitsPerDevPixel());
 
   ctx->SetColor(mColor);
   ctx->NewPath();
   ctx->Rectangle(bounds, true);
   ctx->Fill();
 #endif
 }
 
@@ -3370,18 +3375,19 @@ nsDisplayBackgroundColor::GetOpaqueRegio
   }
 
   if (!mBackgroundStyle)
     return nsRegion();
 
   *aSnap = true;
 
   const nsStyleImageLayers::Layer& bottomLayer = mBackgroundStyle->BottomLayer();
+  nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
   return nsDisplayBackgroundImage::GetInsideClipRegion(this, bottomLayer.mClip,
-                                                       mBackgroundRect, mBackgroundRect);
+                                                       borderBox);
 }
 
 bool
 nsDisplayBackgroundColor::IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor)
 {
   *aColor = mColor.ToABGR();
   return true;
 }
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -2656,33 +2656,27 @@ private:
  */
 class nsDisplayBackgroundImage : public nsDisplayImageContainer {
 public:
   /**
    * aLayer signifies which background layer this item represents.
    * aIsThemed should be the value of aFrame->IsThemed.
    * aBackgroundStyle should be the result of
    * nsCSSRendering::FindBackground, or null if FindBackground returned false.
-   * aBackgroundRect is relative to aFrame.
    */
   nsDisplayBackgroundImage(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
-                           uint32_t aLayer, const nsRect& aBackgroundRect,
+                           uint32_t aLayer,
                            const nsStyleBackground* aBackgroundStyle);
   virtual ~nsDisplayBackgroundImage();
 
   // This will create and append new items for all the layers of the
   // background. Returns whether we appended a themed background.
-  // aAllowWillPaintBorderOptimization should usually be left at true, unless
-  // aFrame has special border drawing that causes opaque borders to not
-  // actually be opaque.
   static bool AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
                                          nsIFrame* aFrame,
-                                         const nsRect& aBackgroundRect,
-                                         nsDisplayList* aList,
-                                         bool aAllowWillPaintBorderOptimization = true);
+                                         nsDisplayList* aList);
 
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
@@ -2728,17 +2722,17 @@ public:
                                          nsRegion* aInvalidRegion) override;
   
   virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
                                        nsDisplayListBuilder* aBuilder) override;
   virtual already_AddRefed<imgIContainer> GetImage() override;
   virtual nsRect GetDestRect() override;
 
   static nsRegion GetInsideClipRegion(nsDisplayItem* aItem, uint8_t aClip,
-                                      const nsRect& aRect, const nsRect& aBackgroundRect);
+                                      const nsRect& aRect);
 
   virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) override;
 
 protected:
   typedef class mozilla::layers::ImageContainer ImageContainer;
   typedef class mozilla::layers::ImageLayer ImageLayer;
 
   bool TryOptimizeToImageLayer(LayerManager* aManager, nsDisplayListBuilder* aBuilder);
@@ -2759,35 +2753,33 @@ protected:
   };
   ImageLayerization ShouldCreateOwnLayer(nsDisplayListBuilder* aBuilder,
                                          LayerManager* aManager);
 
   // Cache the result of nsCSSRendering::FindBackground. Always null if
   // mIsThemed is true or if FindBackground returned false.
   const nsStyleBackground* mBackgroundStyle;
   nsCOMPtr<imgIContainer> mImage;
-  nsRect mBackgroundRect; // relative to the reference frame
   nsRect mFillRect;
   nsRect mDestRect;
   /* Bounds of this display item */
   nsRect mBounds;
   uint32_t mLayer;
   bool mIsRasterImage;
   /* Whether the image should be treated as fixed to the viewport. */
   bool mShouldTreatAsFixed;
 };
 
 
 /**
  * A display item to paint the native theme background for a frame.
  */
 class nsDisplayThemedBackground : public nsDisplayItem {
 public:
-  nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
-                            const nsRect& aBackgroundRect);
+  nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
   virtual ~nsDisplayThemedBackground();
 
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                        HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
   virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                    bool* aSnap) override;
   virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) override;
   virtual bool ProvidesFontSmoothingBackgroundColor(nscolor* aColor) override;
@@ -2823,33 +2815,30 @@ public:
 
   virtual void WriteDebugInfo(std::stringstream& aStream) override;
 protected:
   nsRect GetBoundsInternal();
 
   void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
                      const nsRect& aBounds, nsRect* aClipRect);
 
-  nsRect mBackgroundRect;
   nsRect mBounds;
   nsITheme::Transparency mThemeTransparency;
   uint8_t mAppearance;
 };
 
 class nsDisplayBackgroundColor : public nsDisplayItem
 {
   typedef mozilla::gfx::Color Color;
 
 public:
   nsDisplayBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
-                           const nsRect& aBackgroundRect,
                            const nsStyleBackground* aBackgroundStyle,
                            nscolor aColor)
     : nsDisplayItem(aBuilder, aFrame)
-    , mBackgroundRect(aBackgroundRect)
     , mBackgroundStyle(aBackgroundStyle)
     , mColor(Color::FromABGR(aColor))
   { }
 
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) override;
 
   virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                    bool* aSnap) override;
@@ -2860,17 +2849,17 @@ public:
   virtual void ApplyOpacity(nsDisplayListBuilder* aBuilder,
                             float aOpacity,
                             const DisplayItemClip* aClip) override;
   virtual bool CanApplyOpacity() const override;
 
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override
   {
     *aSnap = true;
-    return mBackgroundRect;
+    return nsRect(ToReferenceFrame(), Frame()->GetSize());
   }
 
   virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
   {
     return new nsDisplaySolidColorGeometry(this, aBuilder, mColor.ToABGR());
   }
 
   virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
@@ -2885,17 +2874,16 @@ public:
     }
     ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
   }
 
   NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR)
   virtual void WriteDebugInfo(std::stringstream& aStream) override;
 
 protected:
-  const nsRect mBackgroundRect;
   const nsStyleBackground* mBackgroundStyle;
   mozilla::gfx::Color mColor;
 };
 
 class nsDisplayClearBackground : public nsDisplayItem
 {
 public:
   nsDisplayClearBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
--- a/layout/forms/nsButtonFrameRenderer.cpp
+++ b/layout/forms/nsButtonFrameRenderer.cpp
@@ -107,28 +107,29 @@ nsDisplayButtonBoxShadowOuter::Paint(nsD
 
   nsRect buttonRect;
   mBFR->GetButtonRect(frameRect, buttonRect);
 
   nsCSSRendering::PaintBoxShadowOuter(mFrame->PresContext(), *aCtx, mFrame,
                                       buttonRect, mVisibleRect);
 }
 
-class nsDisplayButtonBorder : public nsDisplayItem {
+class nsDisplayButtonBorderBackground : public nsDisplayItem {
 public:
-  nsDisplayButtonBorder(nsDisplayListBuilder* aBuilder,
+  nsDisplayButtonBorderBackground(nsDisplayListBuilder* aBuilder,
                                   nsButtonFrameRenderer* aRenderer)
     : nsDisplayItem(aBuilder, aRenderer->GetFrame()), mBFR(aRenderer) {
-    MOZ_COUNT_CTOR(nsDisplayButtonBorder);
+    MOZ_COUNT_CTOR(nsDisplayButtonBorderBackground);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
-  virtual ~nsDisplayButtonBorder() {
-    MOZ_COUNT_DTOR(nsDisplayButtonBorder);
+  virtual ~nsDisplayButtonBorderBackground() {
+    MOZ_COUNT_DTOR(nsDisplayButtonBorderBackground);
   }
-#endif
+#endif  
+  
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                        HitTestState* aState,
                        nsTArray<nsIFrame*> *aOutFrames) override {
     aOutFrames->AppendElement(mFrame);
   }
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      nsRenderingContext* aCtx) override;
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
@@ -138,55 +139,55 @@ public:
                                          const nsDisplayItemGeometry* aGeometry,
                                          nsRegion *aInvalidRegion) override;
   NS_DISPLAY_DECL_NAME("ButtonBorderBackground", TYPE_BUTTON_BORDER_BACKGROUND)
 private:
   nsButtonFrameRenderer* mBFR;
 };
 
 nsDisplayItemGeometry*
-nsDisplayButtonBorder::AllocateGeometry(nsDisplayListBuilder* aBuilder)
+nsDisplayButtonBorderBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder)
 {
   return new nsDisplayItemGenericImageGeometry(this, aBuilder);
 }
 
 void
-nsDisplayButtonBorder::ComputeInvalidationRegion(
+nsDisplayButtonBorderBackground::ComputeInvalidationRegion(
   nsDisplayListBuilder* aBuilder,
   const nsDisplayItemGeometry* aGeometry,
   nsRegion *aInvalidRegion)
 {
   auto geometry =
     static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
 
   if (aBuilder->ShouldSyncDecodeImages() &&
       geometry->ShouldInvalidateToSyncDecodeImages()) {
     bool snap;
     aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
   }
 
   nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
 }
 
-void nsDisplayButtonBorder::Paint(nsDisplayListBuilder* aBuilder,
-                                  nsRenderingContext* aCtx)
+void nsDisplayButtonBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
+                                            nsRenderingContext* aCtx)
 {
   NS_ASSERTION(mFrame, "No frame?");
   nsPresContext* pc = mFrame->PresContext();
   nsRect r = nsRect(ToReferenceFrame(), mFrame->GetSize());
-
+  
   // draw the border and background inside the focus and outline borders
   DrawResult result =
-    mBFR->PaintBorder(aBuilder, pc, *aCtx, mVisibleRect, r);
+    mBFR->PaintBorderAndBackground(aBuilder, pc, *aCtx, mVisibleRect, r);
 
   nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
 }
 
 nsRect
-nsDisplayButtonBorder::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
+nsDisplayButtonBorderBackground::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
   *aSnap = false;
   return aBuilder->IsForEventDelivery() ? nsRect(ToReferenceFrame(), mFrame->GetSize())
           : mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
 }
 
 class nsDisplayButtonForeground : public nsDisplayItem {
 public:
   nsDisplayButtonForeground(nsDisplayListBuilder* aBuilder,
@@ -258,24 +259,20 @@ nsButtonFrameRenderer::DisplayButton(nsD
                                      nsDisplayList* aBackground,
                                      nsDisplayList* aForeground)
 {
   if (mFrame->StyleEffects()->mBoxShadow) {
     aBackground->AppendNewToTop(new (aBuilder)
       nsDisplayButtonBoxShadowOuter(aBuilder, this));
   }
 
-  nsRect buttonRect;
-  GetButtonRect(mFrame->GetRectRelativeToSelf(), buttonRect);
-
-  nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
-    aBuilder, mFrame, buttonRect, aBackground);
-
+  // Almost all buttons draw some kind of background so there's not much
+  // point in checking whether we should create this item.
   aBackground->AppendNewToTop(new (aBuilder)
-    nsDisplayButtonBorder(aBuilder, this));
+    nsDisplayButtonBorderBackground(aBuilder, this));
 
   // Only display focus rings if we actually have them. Since at most one
   // button would normally display a focus ring, most buttons won't have them.
   if ((mOuterFocusStyle && mOuterFocusStyle->StyleBorder()->HasBorder()) ||
       (mInnerFocusStyle && mInnerFocusStyle->StyleBorder()->HasBorder())) {
     aForeground->AppendNewToTop(new (aBuilder)
       nsDisplayButtonForeground(aBuilder, this));
   }
@@ -323,38 +320,44 @@ nsButtonFrameRenderer::PaintOutlineAndFo
     result &=
       nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, mFrame,
                                   aDirtyRect, rect, mInnerFocusStyle, flags);
   }
 
   return result;
 }
 
+
 DrawResult
-nsButtonFrameRenderer::PaintBorder(
+nsButtonFrameRenderer::PaintBorderAndBackground(
   nsDisplayListBuilder* aBuilder,
   nsPresContext* aPresContext,
   nsRenderingContext& aRenderingContext,
   const nsRect& aDirtyRect,
   const nsRect& aRect)
 {
   // get the button rect this is inside the focus and outline rects
   nsRect buttonRect;
   GetButtonRect(aRect, buttonRect);
 
   nsStyleContext* context = mFrame->StyleContext();
 
+  uint32_t bgFlags = aBuilder->GetBackgroundPaintFlags();
   PaintBorderFlags borderFlags = aBuilder->ShouldSyncDecodeImages()
                                ? PaintBorderFlags::SYNC_DECODE_IMAGES
                                : PaintBorderFlags();
 
+  DrawResult result =
+    nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, mFrame,
+                                    aDirtyRect, buttonRect, bgFlags);
+
   nsCSSRendering::PaintBoxShadowInner(aPresContext, aRenderingContext,
                                       mFrame, buttonRect);
 
-  DrawResult result =
+  result &=
     nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, mFrame,
                                 aDirtyRect, buttonRect, context, borderFlags);
 
   return result;
 }
 
 
 void
--- a/layout/forms/nsButtonFrameRenderer.h
+++ b/layout/forms/nsButtonFrameRenderer.h
@@ -40,21 +40,21 @@ public:
 
 
   DrawResult PaintOutlineAndFocusBorders(nsDisplayListBuilder* aBuilder,
                                          nsPresContext* aPresContext,
                                          nsRenderingContext& aRenderingContext,
                                          const nsRect& aDirtyRect,
                                          const nsRect& aRect);
 
-  DrawResult PaintBorder(nsDisplayListBuilder* aBuilder,
-                         nsPresContext* aPresContext,
-                         nsRenderingContext& aRenderingContext,
-                         const nsRect& aDirtyRect,
-                         const nsRect& aRect);
+  DrawResult PaintBorderAndBackground(nsDisplayListBuilder* aBuilder,
+                                      nsPresContext* aPresContext,
+                                      nsRenderingContext& aRenderingContext,
+                                      const nsRect& aDirtyRect,
+                                      const nsRect& aRect);
 
   void SetFrame(nsFrame* aFrame, nsPresContext* aPresContext);
  
   void SetDisabled(bool aDisabled, bool notify);
 
   bool isActive();
   bool isDisabled();
 
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -96,16 +96,17 @@ public:
     : nsDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayFieldSetBorderBackground);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayFieldSetBorderBackground() {
     MOZ_COUNT_DTOR(nsDisplayFieldSetBorderBackground);
   }
 #endif
+
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                        HitTestState* aState,
                        nsTArray<nsIFrame*> *aOutFrames) override;
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      nsRenderingContext* aCtx) override;
   virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override;
   virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                          const nsDisplayItemGeometry* aGeometry,
@@ -122,17 +123,17 @@ void nsDisplayFieldSetBorderBackground::
   aOutFrames->AppendElement(mFrame);
 }
 
 void
 nsDisplayFieldSetBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
                                          nsRenderingContext* aCtx)
 {
   DrawResult result = static_cast<nsFieldSetFrame*>(mFrame)->
-    PaintBorder(aBuilder, *aCtx, ToReferenceFrame(), mVisibleRect);
+    PaintBorderBackground(aBuilder, *aCtx, ToReferenceFrame(), mVisibleRect);
 
   nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
 }
 
 nsDisplayItemGeometry*
 nsDisplayFieldSetBorderBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder)
 {
   return new nsDisplayItemGenericImageGeometry(this, aBuilder);
@@ -165,21 +166,18 @@ nsFieldSetFrame::BuildDisplayList(nsDisp
   // we need to paint the outline
   if (!(GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) &&
       IsVisibleForPainting(aBuilder)) {
     if (StyleEffects()->mBoxShadow) {
       aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
         nsDisplayBoxShadowOuter(aBuilder, this));
     }
 
-    nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
-      aBuilder, this, VisualBorderRectRelativeToSelf(),
-      aLists.BorderBackground(),
-      /* aAllowWillPaintBorderOptimization = */ false);
-
+    // don't bother checking to see if we really have a border or background.
+    // we usually will have a border.
     aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
       nsDisplayFieldSetBorderBackground(aBuilder, this));
   
     DisplayOutlineUnconditional(aBuilder, aLists);
 
     DO_GLOBAL_REFLOW_COUNT_DSP("nsFieldSetFrame");
   }
 
@@ -206,37 +204,40 @@ nsFieldSetFrame::BuildDisplayList(nsDisp
   // Put the inner frame's display items on the master list. Note that this
   // moves its border/background display items to our BorderBackground() list,
   // which isn't really correct, but it's OK because the inner frame is
   // anonymous and can't have its own border and background.
   contentDisplayItems.MoveTo(aLists);
 }
 
 DrawResult
-nsFieldSetFrame::PaintBorder(
+nsFieldSetFrame::PaintBorderBackground(
   nsDisplayListBuilder* aBuilder,
   nsRenderingContext& aRenderingContext,
   nsPoint aPt,
   const nsRect& aDirtyRect)
 {
   // if the border is smaller than the legend. Move the border down
   // to be centered on the legend.
   // FIXME: This means border-radius clamping is incorrect; we should
   // override nsIFrame::GetBorderRadii.
   WritingMode wm = GetWritingMode();
   nsRect rect = VisualBorderRectRelativeToSelf();
   nscoord off = wm.IsVertical() ? rect.x : rect.y;
   rect += aPt;
   nsPresContext* presContext = PresContext();
 
+  uint32_t bgFlags = aBuilder->GetBackgroundPaintFlags();
   PaintBorderFlags borderFlags = aBuilder->ShouldSyncDecodeImages()
                                ? PaintBorderFlags::SYNC_DECODE_IMAGES
                                : PaintBorderFlags();
 
-  DrawResult result = DrawResult::SUCCESS;
+  DrawResult result =
+    nsCSSRendering::PaintBackground(presContext, aRenderingContext, this,
+                                    aDirtyRect, rect, bgFlags);
 
   nsCSSRendering::PaintBoxShadowInner(presContext, aRenderingContext,
                                       this, rect);
 
   if (nsIFrame* legend = GetLegend()) {
     css::Side legendSide = wm.PhysicalSide(eLogicalSideBStart);
     nscoord legendBorderWidth =
       StyleBorder()->GetComputedBorderWidth(legendSide);
--- a/layout/forms/nsFieldSetFrame.h
+++ b/layout/forms/nsFieldSetFrame.h
@@ -45,19 +45,19 @@ public:
                       nsHTMLReflowMetrics&     aDesiredSize,
                       const nsHTMLReflowState& aReflowState,
                       nsReflowStatus&          aStatus) override;
                                
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
-  DrawResult PaintBorder(nsDisplayListBuilder* aBuilder,
-                         nsRenderingContext& aRenderingContext,
-                         nsPoint aPt, const nsRect& aDirtyRect);
+  DrawResult PaintBorderBackground(nsDisplayListBuilder* aBuilder,
+                                   nsRenderingContext& aRenderingContext,
+                                   nsPoint aPt, const nsRect& aDirtyRect);
 
 #ifdef DEBUG
   virtual void SetInitialChildList(ChildListID    aListID,
                                    nsFrameList&   aChildList) override;
   virtual void AppendFrames(ChildListID    aListID,
                             nsFrameList&   aFrameList) override;
   virtual void InsertFrames(ChildListID    aListID,
                             nsIFrame*      aPrevFrame,
--- a/layout/generic/nsCanvasFrame.h
+++ b/layout/generic/nsCanvasFrame.h
@@ -194,19 +194,17 @@ public:
   virtual void WriteDebugInfo(std::stringstream& aStream) override;
 #endif
 };
 
 class nsDisplayCanvasBackgroundImage : public nsDisplayBackgroundImage {
 public:
   nsDisplayCanvasBackgroundImage(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                                  uint32_t aLayer, const nsStyleBackground* aBg)
-    : nsDisplayBackgroundImage(aBuilder, aFrame, aLayer,
-                               aFrame->GetRectRelativeToSelf() + aBuilder->ToReferenceFrame(aFrame),
-                               aBg)
+    : nsDisplayBackgroundImage(aBuilder, aFrame, aLayer, aBg)
   {
     if (ShouldFixToViewport(aBuilder)) {
       mAnimatedGeometryRoot = aBuilder->FindAnimatedGeometryRootFor(this);
     }
   }
 
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) override;
 
@@ -236,18 +234,17 @@ public:
   
   
   NS_DISPLAY_DECL_NAME("CanvasBackgroundImage", TYPE_CANVAS_BACKGROUND_IMAGE)
 };
 
 class nsDisplayCanvasThemedBackground : public nsDisplayThemedBackground {
 public:
   nsDisplayCanvasThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
-    : nsDisplayThemedBackground(aBuilder, aFrame,
-                                aFrame->GetRectRelativeToSelf() + aBuilder->ToReferenceFrame(aFrame))
+    : nsDisplayThemedBackground(aBuilder, aFrame)
   {}
 
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) override;
 
   NS_DISPLAY_DECL_NAME("CanvasThemedBackground", TYPE_CANVAS_THEMED_BACKGROUND)
 };
 
 #endif /* nsCanvasFrame_h___ */
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1870,17 +1870,17 @@ nsFrame::DisplayBackgroundUnconditional(
                                         bool aForceBackground)
 {
   // Here we don't try to detect background propagation. Frames that might
   // receive a propagated background should just set aForceBackground to
   // true.
   if (aBuilder->IsForEventDelivery() || aForceBackground ||
       !StyleBackground()->IsTransparent() || StyleDisplay()->mAppearance) {
     return nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
-        aBuilder, this, GetRectRelativeToSelf(), aLists.BorderBackground());
+        aBuilder, this, aLists.BorderBackground());
   }
   return false;
 }
 
 void
 nsFrame::DisplayBorderBackgroundOutline(nsDisplayListBuilder*   aBuilder,
                                         const nsDisplayListSet& aLists,
                                         bool                    aForceBackground)
--- a/layout/reftests/box-shadow/611574-2-ref.html
+++ b/layout/reftests/box-shadow/611574-2-ref.html
@@ -1,13 +1,12 @@
 <!DOCTYPE HTML>
 <html>
 <head><style>
 button,span,fieldset { border-radius: 7px 3px;  background-color: #0F0; }
-button { border: none; outline: 3px solid black; -moz-outline-radius: 7px 3px; outline-offset: -2px; }
 </style></head>
 <body style="margin:30px">
 <div style="-moz-column-count:3">
 <p><button>No Blur Radius</button>
 <p><button>No Blur Radius</button>
 <p><button>No Blur Radius</button>
 <p><button>No Blur Radius</button>
 <p><button>No Blur Radius</button>
--- a/layout/reftests/box-shadow/611574-2.html
+++ b/layout/reftests/box-shadow/611574-2.html
@@ -1,13 +1,12 @@
 <!DOCTYPE HTML>
 <html>
 <head><style>
 button,span,fieldset { border-radius: 7px 3px;  background-color: #0F0; }
-button { border: none; outline: 3px solid black; -moz-outline-radius: 7px 3px; outline-offset: -2px; }
 </style></head>
 <body style="margin:30px">
 <div style="-moz-column-count:3">
 <p><button style="box-shadow: inset -20px 10px 0 #0F0;">No Blur Radius</button>
 <p><button style="box-shadow: inset  20px 10px 0 #0F0;">No Blur Radius</button>
 <p><button style="box-shadow: inset -20px 10px 0 4px #0F0;">No Blur Radius</button>
 <p><button style="box-shadow: inset 200px 100px 0 4px #0F0;">No Blur Radius</button>
 <p><button style="box-shadow: inset 200px -100px 0 4px #0F0;">No Blur Radius</button>
deleted file mode 100644
--- a/layout/reftests/invalidation/background-position-2-ref.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<meta charset="utf-8">
-<title>Reference for properly handled background-position changes.</title>
-
-<style>
-
-body {
-  margin: 0;
-}
-
-#background {
-  width: 100px;
-  height: 100px;
-  background-color: lime;
-}
-
-</style>
-
-<div id="background"></div>
deleted file mode 100644
--- a/layout/reftests/invalidation/background-position-2a.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE html>
-<html lang="en" class="reftest-wait">
-<meta charset="utf-8">
-<title>Changes to background-position should invalidate properly.</title>
-
-<style>
-
-body {
-  margin: 0;
-}
-
-#background {
-  width: 100px;
-  height: 100px;
-  background-image: url(image_rgrg-256x256.png);
-  background-repeat: no-repeat;
-  background-position: 0 0;
-}
-
-</style>
-
-<div id="background"></div>
-
-<script>
-
-function doTest() {
-  document.querySelector("#background").style.backgroundPosition = "-140px 0";
-  document.documentElement.removeAttribute("class");
-}
-document.addEventListener("MozReftestInvalidate", doTest);
-
-</script>
deleted file mode 100644
--- a/layout/reftests/invalidation/background-position-2b.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-<html lang="en" class="reftest-wait">
-<meta charset="utf-8">
-<title>Changes to background-position should invalidate properly for input type=text.</title>
-
-<style>
-
-body {
-  margin: 0;
-}
-
-#background {
-  width: 100px;
-  height: 100px;
-  background-image: url(image_rgrg-256x256.png);
-  background-repeat: no-repeat;
-  background-position: 0 0;
-
-  border: 0;
-  padding: 0;
-}
-
-</style>
-
-<input type="text" id="background"></div>
-
-<script>
-
-function doTest() {
-  document.querySelector("#background").style.backgroundPosition = "-140px 0";
-  document.documentElement.removeAttribute("class");
-}
-document.addEventListener("MozReftestInvalidate", doTest);
-
-</script>
deleted file mode 100644
--- a/layout/reftests/invalidation/background-position-2c.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-<html lang="en" class="reftest-wait">
-<meta charset="utf-8">
-<title>Changes to background-position should invalidate properly for input type=button.</title>
-
-<style>
-
-body {
-  margin: 0;
-}
-
-#background {
-  width: 100px;
-  height: 100px;
-  background-image: url(image_rgrg-256x256.png);
-  background-repeat: no-repeat;
-  background-position: 0 0;
-
-  border: 0;
-  padding: 0;
-}
-
-</style>
-
-<input type="button" id="background"></div>
-
-<script>
-
-function doTest() {
-  document.querySelector("#background").style.backgroundPosition = "-140px 0";
-  document.documentElement.removeAttribute("class");
-}
-document.addEventListener("MozReftestInvalidate", doTest);
-
-</script>
deleted file mode 100644
--- a/layout/reftests/invalidation/background-position-2d.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!DOCTYPE html>
-<html lang="en" class="reftest-wait">
-<meta charset="utf-8">
-<title>Changes to background-position should invalidate properly for table rows.</title>
-
-<style>
-
-body {
-  margin: 0;
-}
-
-#background {
-  width: 100px;
-  height: 100px;
-  background-image: url(image_rgrg-256x256.png);
-  background-repeat: no-repeat;
-  background-position: 0 0;
-
-  border: 0;
-  padding: 0;
-}
-
-table, tr, td {
-  width: 100px;
-  height: 100px;
-  border: 0;
-  padding: 0;
-  border-spacing: 0;
-}
-
-</style>
-
-<table><tr id="background"><td></td></table>
-
-<script>
-
-function doTest() {
-  document.querySelector("#background").style.backgroundPosition = "-140px 0";
-  document.documentElement.removeAttribute("class");
-}
-document.addEventListener("MozReftestInvalidate", doTest);
-
-</script>
deleted file mode 100644
--- a/layout/reftests/invalidation/background-position-2e.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!DOCTYPE html>
-<html lang="en" class="reftest-wait">
-<meta charset="utf-8">
-<title>Changes to background-position should invalidate properly for table cells.</title>
-
-<style>
-
-body {
-  margin: 0;
-}
-
-#background {
-  width: 100px;
-  height: 100px;
-  background-image: url(image_rgrg-256x256.png);
-  background-repeat: no-repeat;
-  background-position: 0 0;
-
-  border: 0;
-  padding: 0;
-}
-
-table, tr, td {
-  width: 100px;
-  height: 100px;
-  border: 0;
-  padding: 0;
-  border-spacing: 0;
-}
-
-</style>
-
-<table><tr><td id="background"></td></table>
-
-<script>
-
-function doTest() {
-  document.querySelector("#background").style.backgroundPosition = "-140px 0";
-  document.documentElement.removeAttribute("class");
-}
-document.addEventListener("MozReftestInvalidate", doTest);
-
-</script>
deleted file mode 100644
--- a/layout/reftests/invalidation/background-position-2f.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-<html lang="en" class="reftest-wait">
-<meta charset="utf-8">
-<title>Changes to background-position should invalidate properly for fieldsets.</title>
-
-<style>
-
-body {
-  margin: 0;
-}
-
-#background {
-  width: 100px;
-  height: 100px;
-  background-image: url(image_rgrg-256x256.png);
-  background-repeat: no-repeat;
-  background-position: 0 0;
-
-  border: 0;
-  padding: 0;
-  margin: 0;
-}
-
-</style>
-
-<fieldset id="background"><legend></legend></fieldset>
-
-<script>
-
-function doTest() {
-  document.querySelector("#background").style.backgroundPosition = "-140px 0";
-  document.documentElement.removeAttribute("class");
-}
-document.addEventListener("MozReftestInvalidate", doTest);
-
-</script>
--- a/layout/reftests/invalidation/reftest.list
+++ b/layout/reftests/invalidation/reftest.list
@@ -64,17 +64,11 @@ pref(layers.single-tile.enabled,false) !
 != layer-splitting-4.html about:blank
 != layer-splitting-5.html about:blank
 != layer-splitting-6.html about:blank
 != layer-splitting-7.html about:blank
 fuzzy-if(gtkWidget,2,4) fuzzy-if(asyncPan,2,3955) fuzzy-if(OSX,179,30) fuzzy-if(skiaContent,16,3230) == image-scrolling-zoom-1.html image-scrolling-zoom-1-ref.html
 != image-scrolling-zoom-1-ref.html image-scrolling-zoom-1-notref.html
 pref(layers.single-tile.enabled,false) != fast-scrolling.html about:blank
 == background-position-1.html background-position-1-ref.html
-== background-position-2a.html background-position-2-ref.html
-== background-position-2b.html background-position-2-ref.html
-== background-position-2c.html background-position-2-ref.html
-== background-position-2d.html background-position-2-ref.html
-== background-position-2e.html background-position-2-ref.html
-== background-position-2f.html background-position-2-ref.html
 == zero-opacity-animation.html about:blank
 == zero-opacity-text.html about:blank
 == negative-w-component.html negative-w-component-ref.html
--- 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_UpdateBackgroundPosition;
+    hint |= nsChangeHint_SchedulePaint;
   }
 
   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_UpdateBackgroundPosition |
+           nsChangeHint_SchedulePaint |
            nsChangeHint_NeutralChange;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
     // handled for descendants at all.
     return nsChangeHint(0);
   }
 
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -1248,17 +1248,16 @@ nsTableFrame::DisplayGenericTablePart(ns
         new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, aFrame));
     }
 
     // Create dedicated background display items per-frame when we're
     // handling events.
     // XXX how to handle collapsed borders?
     if (aBuilder->IsForEventDelivery()) {
       nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame,
-                                                           aFrame->GetRectRelativeToSelf(),
                                                            lists->BorderBackground());
     }
 
     // Paint the inset box-shadows for the table frames
     if (hasBoxShadow) {
       lists->BorderBackground()->AppendNewToTop(
         new (aBuilder) nsDisplayBoxShadowInner(aBuilder, aFrame));
     }
--- a/layout/xul/nsGroupBoxFrame.cpp
+++ b/layout/xul/nsGroupBoxFrame.cpp
@@ -34,20 +34,19 @@ public:
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override {
     return MakeFrameName(NS_LITERAL_STRING("GroupBoxFrame"), aResult);
   }
 #endif
 
   virtual bool HonorPrintBackgroundSettings() override { return false; }
 
-  DrawResult PaintBorder(nsRenderingContext& aRenderingContext,
+  DrawResult PaintBorderBackground(nsRenderingContext& aRenderingContext,
                                    nsPoint aPt,
                                    const nsRect& aDirtyRect);
-  nsRect GetBackgroundRectRelativeToSelf(nscoord* aOutYOffset = nullptr, nsRect* aOutGroupRect = nullptr);
 
   // make sure we our kids get our orient and align instead of us.
   // our child box has no content node so it will search for a parent with one.
   // that will be us.
   virtual void GetInitialOrientation(bool& aHorizontal) override { aHorizontal = false; }
   virtual bool GetInitialHAlignment(Halignment& aHalign) override { aHalign = hAlign_Left; return true; } 
   virtual bool GetInitialVAlignment(Valignment& aValign) override { aValign = vAlign_Top; return true; } 
   virtual bool GetInitialAutoStretch(bool& aStretch) override { aStretch = true; return true; } 
@@ -78,26 +77,26 @@ public:
 nsIFrame*
 NS_NewGroupBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsGroupBoxFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsGroupBoxFrame)
 
-class nsDisplayXULGroupBorder : public nsDisplayItem {
+class nsDisplayXULGroupBackground : public nsDisplayItem {
 public:
-  nsDisplayXULGroupBorder(nsDisplayListBuilder* aBuilder,
+  nsDisplayXULGroupBackground(nsDisplayListBuilder* aBuilder,
                               nsGroupBoxFrame* aFrame) :
     nsDisplayItem(aBuilder, aFrame) {
-    MOZ_COUNT_CTOR(nsDisplayXULGroupBorder);
+    MOZ_COUNT_CTOR(nsDisplayXULGroupBackground);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
-  virtual ~nsDisplayXULGroupBorder() {
-    MOZ_COUNT_DTOR(nsDisplayXULGroupBorder);
+  virtual ~nsDisplayXULGroupBackground() {
+    MOZ_COUNT_DTOR(nsDisplayXULGroupBackground);
   }
 #endif
 
   nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override;
   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                  const nsDisplayItemGeometry* aGeometry,
                                  nsRegion *aInvalidRegion) override;
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
@@ -105,23 +104,23 @@ public:
     aOutFrames->AppendElement(mFrame);
   }
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      nsRenderingContext* aCtx) override;
   NS_DISPLAY_DECL_NAME("XULGroupBackground", TYPE_XUL_GROUP_BACKGROUND)
 };
 
 nsDisplayItemGeometry*
-nsDisplayXULGroupBorder::AllocateGeometry(nsDisplayListBuilder* aBuilder)
+nsDisplayXULGroupBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder)
 {
   return new nsDisplayItemGenericImageGeometry(this, aBuilder);
 }
 
 void
-nsDisplayXULGroupBorder::ComputeInvalidationRegion(
+nsDisplayXULGroupBackground::ComputeInvalidationRegion(
   nsDisplayListBuilder* aBuilder,
   const nsDisplayItemGeometry* aGeometry,
   nsRegion* aInvalidRegion)
 {
   auto geometry =
     static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
 
   if (aBuilder->ShouldSyncDecodeImages() &&
@@ -129,95 +128,77 @@ nsDisplayXULGroupBorder::ComputeInvalida
     bool snap;
     aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
   }
 
   nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
 }
 
 void
-nsDisplayXULGroupBorder::Paint(nsDisplayListBuilder* aBuilder,
+nsDisplayXULGroupBackground::Paint(nsDisplayListBuilder* aBuilder,
                                    nsRenderingContext* aCtx)
 {
   DrawResult result = static_cast<nsGroupBoxFrame*>(mFrame)
-    ->PaintBorder(*aCtx, ToReferenceFrame(), mVisibleRect);
+    ->PaintBorderBackground(*aCtx, ToReferenceFrame(), mVisibleRect);
 
   nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
 }
 
 void
 nsGroupBoxFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                   const nsRect&           aDirtyRect,
                                   const nsDisplayListSet& aLists)
 {
   // Paint our background and border
   if (IsVisibleForPainting(aBuilder)) {
-    nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
-      aBuilder, this, GetBackgroundRectRelativeToSelf(),
-      aLists.BorderBackground());
     aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
-      nsDisplayXULGroupBorder(aBuilder, this));
+      nsDisplayXULGroupBackground(aBuilder, this));
     
     DisplayOutline(aBuilder, aLists);
   }
 
   BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists);
 }
 
-nsRect
-nsGroupBoxFrame::GetBackgroundRectRelativeToSelf(nscoord* aOutYOffset, nsRect* aOutGroupRect)
-{
-  const nsMargin& border = StyleBorder()->GetComputedBorder();
-
-  nsRect groupRect;
-  nsIFrame* groupBox = GetCaptionBox(groupRect);
-
-  nscoord yoff = 0;
-  if (groupBox) {
-    // If the border is smaller than the legend, move the border down
-    // to be centered on the legend.
-    nsMargin groupMargin;
-    groupBox->StyleMargin()->GetMargin(groupMargin);
-    groupRect.Inflate(groupMargin);
-
-    if (border.top < groupRect.height) {
-      yoff = (groupRect.height - border.top) / 2 + groupRect.y;
-    }
-  }
-
-  if (aOutYOffset) {
-    *aOutYOffset = yoff;
-  }
-  if (aOutGroupRect) {
-    *aOutGroupRect = groupRect;
-  }
-
-  return nsRect(0, yoff, mRect.width, mRect.height - yoff);
-}
-
 DrawResult
-nsGroupBoxFrame::PaintBorder(nsRenderingContext& aRenderingContext,
+nsGroupBoxFrame::PaintBorderBackground(nsRenderingContext& aRenderingContext,
     nsPoint aPt, const nsRect& aDirtyRect) {
 
   DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
   gfxContext* gfx = aRenderingContext.ThebesContext();
 
   Sides skipSides;
   const nsStyleBorder* borderStyleData = StyleBorder();
   const nsMargin& border = borderStyleData->GetComputedBorder();
+  nscoord yoff = 0;
   nsPresContext* presContext = PresContext();
 
   nsRect groupRect;
   nsIFrame* groupBox = GetCaptionBox(groupRect);
 
-  nscoord yoff = 0;
-  nsRect rect = GetBackgroundRectRelativeToSelf(&yoff, &groupRect) + aPt;
+  if (groupBox) {        
+    // if the border is smaller than the legend. Move the border down
+    // to be centered on the legend. 
+    nsMargin groupMargin;
+    groupBox->StyleMargin()->GetMargin(groupMargin);
+    groupRect.Inflate(groupMargin);
+ 
+    if (border.top < groupRect.height)
+        yoff = (groupRect.height - border.top)/2 + groupRect.y;
+  }
+
+  nsRect rect(aPt.x, aPt.y + yoff, mRect.width, mRect.height - yoff);
+
   groupRect += aPt;
 
-  DrawResult result = DrawResult::SUCCESS;
+  DrawResult result =
+    nsCSSRendering::PaintBackground(presContext, aRenderingContext, this,
+                                    aDirtyRect, rect,
+                                    nsCSSRendering::PAINTBG_SYNC_DECODE_IMAGES);
+
   if (groupBox) {
     int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
 
     // we should probably use PaintBorderEdges to do this but for now just use clipping
     // to achieve the same effect.
 
     // draw left side
     nsRect clipRect(rect);