Bug 1549751 - Part 2: Add nsPaintedDisplayItem r=mattwoodrow
authorMiko Mynttinen <mikokm@gmail.com>
Wed, 08 May 2019 13:49:56 +0000
changeset 531887 69a48ceb1ecb6c0857a5a258d653be3b0a7b93b6
parent 531886 61e59c0325ddeba0bfe6a3624a60d0e7150ac632
child 531888 b5a3f0b9ce243f5cb610ee849d35637d3402c35b
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1549751
milestone68.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 1549751 - Part 2: Add nsPaintedDisplayItem r=mattwoodrow Move ApplyOpacity(), CanApplyOpacity(), Paint() and PaintWithClip() methods to nsPaintedDisplayItem Differential Revision: https://phabricator.services.mozilla.com/D30225
layout/forms/nsButtonFrameRenderer.cpp
layout/forms/nsComboboxControlFrame.cpp
layout/forms/nsFieldSetFrame.cpp
layout/forms/nsRangeFrame.cpp
layout/forms/nsSelectsAreaFrame.cpp
layout/generic/TextOverflow.cpp
layout/generic/nsBulletFrame.cpp
layout/generic/nsCanvasFrame.cpp
layout/generic/nsColumnSetFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsFrameSetFrame.cpp
layout/generic/nsImageFrame.cpp
layout/generic/nsPageFrame.cpp
layout/generic/nsPluginFrame.h
layout/ipc/RenderFrame.cpp
layout/ipc/RenderFrame.h
layout/mathml/nsMathMLChar.cpp
layout/mathml/nsMathMLContainerFrame.cpp
layout/mathml/nsMathMLFrame.cpp
layout/mathml/nsMathMLmencloseFrame.cpp
layout/mathml/nsMathMLmfracFrame.cpp
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
layout/svg/SVGGeometryFrame.cpp
layout/svg/SVGTextFrame.cpp
layout/svg/nsSVGOuterSVGFrame.cpp
layout/tables/nsTableCellFrame.cpp
layout/tables/nsTableFrame.h
layout/xul/nsGroupBoxFrame.cpp
layout/xul/nsTextBoxFrame.cpp
layout/xul/tree/nsTreeBodyFrame.cpp
--- a/layout/forms/nsButtonFrameRenderer.cpp
+++ b/layout/forms/nsButtonFrameRenderer.cpp
@@ -55,21 +55,21 @@ void nsButtonFrameRenderer::SetDisabled(
     element->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, aNotify);
 }
 
 bool nsButtonFrameRenderer::isDisabled() {
   return mFrame->GetContent()->AsElement()->State().HasState(
       NS_EVENT_STATE_DISABLED);
 }
 
-class nsDisplayButtonBoxShadowOuter : public nsDisplayItem {
+class nsDisplayButtonBoxShadowOuter : public nsPaintedDisplayItem {
  public:
   nsDisplayButtonBoxShadowOuter(nsDisplayListBuilder* aBuilder,
                                 nsIFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayButtonBoxShadowOuter);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayButtonBoxShadowOuter() {
     MOZ_COUNT_DTOR(nsDisplayButtonBoxShadowOuter);
   }
 #endif
 
@@ -179,21 +179,21 @@ bool nsDisplayButtonBoxShadowOuter::Crea
     aBuilder.PushBoxShadow(deviceBoxRect, deviceClipRect, !BackfaceIsHidden(),
                            deviceBoxRect, wr::ToLayoutVector2D(shadowOffset),
                            wr::ToColorF(shadowColor), blurRadius, spreadRadius,
                            borderRadius, wr::BoxShadowClipMode::Outset);
   }
   return true;
 }
 
-class nsDisplayButtonBorder final : public nsDisplayItem {
+class nsDisplayButtonBorder final : public nsPaintedDisplayItem {
  public:
   nsDisplayButtonBorder(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                         nsButtonFrameRenderer* aRenderer)
-      : nsDisplayItem(aBuilder, aFrame), mBFR(aRenderer) {
+      : nsPaintedDisplayItem(aBuilder, aFrame), mBFR(aRenderer) {
     MOZ_COUNT_CTOR(nsDisplayButtonBorder);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayButtonBorder() { MOZ_COUNT_DTOR(nsDisplayButtonBorder); }
 #endif
   virtual bool MustPaintOnContentSide() const override { return true; }
 
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
@@ -285,21 +285,21 @@ nsRect nsDisplayButtonBorder::GetBounds(
                                         bool* aSnap) const {
   *aSnap = false;
   return aBuilder->IsForEventDelivery()
              ? nsRect(ToReferenceFrame(), mFrame->GetSize())
              : mFrame->GetVisualOverflowRectRelativeToSelf() +
                    ToReferenceFrame();
 }
 
-class nsDisplayButtonForeground final : public nsDisplayItem {
+class nsDisplayButtonForeground final : public nsPaintedDisplayItem {
  public:
   nsDisplayButtonForeground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                             nsButtonFrameRenderer* aRenderer)
-      : nsDisplayItem(aBuilder, aFrame), mBFR(aRenderer) {
+      : nsPaintedDisplayItem(aBuilder, aFrame), mBFR(aRenderer) {
     MOZ_COUNT_CTOR(nsDisplayButtonForeground);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayButtonForeground() {
     MOZ_COUNT_DTOR(nsDisplayButtonForeground);
   }
 #endif
 
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -1416,21 +1416,21 @@ void nsComboboxControlFrame::RollupFromL
 int32_t nsComboboxControlFrame::UpdateRecentIndex(int32_t aIndex) {
   int32_t index = mRecentSelectedIndex;
   if (mRecentSelectedIndex == NS_SKIP_NOTIFY_INDEX ||
       aIndex == NS_SKIP_NOTIFY_INDEX)
     mRecentSelectedIndex = aIndex;
   return index;
 }
 
-class nsDisplayComboboxFocus : public nsDisplayItem {
+class nsDisplayComboboxFocus : public nsPaintedDisplayItem {
  public:
   nsDisplayComboboxFocus(nsDisplayListBuilder* aBuilder,
                          nsComboboxControlFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayComboboxFocus);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayComboboxFocus() { MOZ_COUNT_DTOR(nsDisplayComboboxFocus); }
 #endif
 
   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
   NS_DISPLAY_DECL_NAME("ComboboxFocus", TYPE_COMBOBOX_FOCUS)
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -85,21 +85,21 @@ nsIFrame* nsFieldSetFrame::GetLegend() c
     MOZ_ASSERT(mFrames.LastChild() == mFrames.FirstChild());
     return nullptr;
   }
   MOZ_ASSERT(mFrames.FirstChild() &&
              mFrames.FirstChild()->GetContentInsertionFrame()->IsLegendFrame());
   return mFrames.FirstChild();
 }
 
-class nsDisplayFieldSetBorder final : public nsDisplayItem {
+class nsDisplayFieldSetBorder final : public nsPaintedDisplayItem {
  public:
   nsDisplayFieldSetBorder(nsDisplayListBuilder* aBuilder,
                           nsFieldSetFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayFieldSetBorder);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayFieldSetBorder() {
     MOZ_COUNT_DTOR(nsDisplayFieldSetBorder);
   }
 #endif
   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
--- a/layout/forms/nsRangeFrame.cpp
+++ b/layout/forms/nsRangeFrame.cpp
@@ -143,20 +143,20 @@ void nsRangeFrame::AppendAnonymousConten
     aElements.AppendElement(mProgressDiv);
   }
 
   if (mThumbDiv) {
     aElements.AppendElement(mThumbDiv);
   }
 }
 
-class nsDisplayRangeFocusRing final : public nsDisplayItem {
+class nsDisplayRangeFocusRing final : public nsPaintedDisplayItem {
  public:
   nsDisplayRangeFocusRing(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayRangeFocusRing);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayRangeFocusRing() {
     MOZ_COUNT_DTOR(nsDisplayRangeFocusRing);
   }
 #endif
 
--- a/layout/forms/nsSelectsAreaFrame.cpp
+++ b/layout/forms/nsSelectsAreaFrame.cpp
@@ -95,20 +95,20 @@ static nsListControlFrame* GetEnclosingL
   while (frame) {
     if (frame->IsListControlFrame())
       return static_cast<nsListControlFrame*>(frame);
     frame = frame->GetParent();
   }
   return nullptr;
 }
 
-class nsDisplayListFocus : public nsDisplayItem {
+class nsDisplayListFocus : public nsPaintedDisplayItem {
  public:
   nsDisplayListFocus(nsDisplayListBuilder* aBuilder, nsSelectsAreaFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayListFocus);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayListFocus() { MOZ_COUNT_DTOR(nsDisplayListFocus); }
 #endif
 
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
                            bool* aSnap) const override {
--- a/layout/generic/TextOverflow.cpp
+++ b/layout/generic/TextOverflow.cpp
@@ -143,23 +143,23 @@ static bool IsFrameDescendantOfAny(
        f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
     if (aSetOfFrames.GetEntry(f)) {
       return true;
     }
   }
   return false;
 }
 
-class nsDisplayTextOverflowMarker final : public nsDisplayItem {
+class nsDisplayTextOverflowMarker final : public nsPaintedDisplayItem {
  public:
   nsDisplayTextOverflowMarker(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                               const nsRect& aRect, nscoord aAscent,
                               const nsStyleTextOverflowSide* aStyle,
                               uint32_t aLineNumber, uint16_t aIndex)
-      : nsDisplayItem(aBuilder, aFrame),
+      : nsPaintedDisplayItem(aBuilder, aFrame),
         mRect(aRect),
         mStyle(*aStyle),
         mAscent(aAscent),
         mIndex((aLineNumber << 1) + aIndex) {
     MOZ_COUNT_CTOR(nsDisplayTextOverflowMarker);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayTextOverflowMarker() {
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -538,20 +538,20 @@ bool BulletRenderer::CreateWebRenderComm
       new TextDrawTarget(aBuilder, aResources, aSc, aManager, aItem, bounds);
   RefPtr<gfxContext> captureCtx = gfxContext::CreateOrNull(textDrawer);
   PaintTextToContext(aItem->Frame(), captureCtx, aItem->IsSubpixelAADisabled());
   textDrawer->TerminateShadows();
 
   return textDrawer->Finish();
 }
 
-class nsDisplayBullet final : public nsDisplayItem {
+class nsDisplayBullet final : public nsPaintedDisplayItem {
  public:
   nsDisplayBullet(nsDisplayListBuilder* aBuilder, nsBulletFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayBullet);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayBullet() { MOZ_COUNT_DTOR(nsDisplayBullet); }
 #endif
 
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
                            bool* aSnap) const override {
@@ -599,18 +599,18 @@ class nsDisplayBullet final : public nsD
 
     nsCOMPtr<imgIContainer> image = f->GetImage();
     if (aBuilder->ShouldSyncDecodeImages() && image &&
         geometry->ShouldInvalidateToSyncDecodeImages()) {
       bool snap;
       aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
     }
 
-    return nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry,
-                                                    aInvalidRegion);
+    return nsPaintedDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry,
+                                                           aInvalidRegion);
   }
 
  protected:
   Maybe<BulletRenderer> mBulletRenderer;
 };
 
 bool nsDisplayBullet::CreateWebRenderCommands(
     wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -433,20 +433,20 @@ void nsDisplayCanvasThemedBackground::Pa
   PaintInternal(aBuilder, aCtx, GetPaintRect(), &bgClipRect);
 }
 
 /**
  * A display item to paint the focus ring for the document.
  *
  * The only reason this can't use nsDisplayGeneric is overriding GetBounds.
  */
-class nsDisplayCanvasFocus : public nsDisplayItem {
+class nsDisplayCanvasFocus : public nsPaintedDisplayItem {
  public:
   nsDisplayCanvasFocus(nsDisplayListBuilder* aBuilder, nsCanvasFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayCanvasFocus);
   }
   virtual ~nsDisplayCanvasFocus() { MOZ_COUNT_DTOR(nsDisplayCanvasFocus); }
 
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
                            bool* aSnap) const override {
     *aSnap = false;
     // This is an overestimate, but that's not a problem.
--- a/layout/generic/nsColumnSetFrame.cpp
+++ b/layout/generic/nsColumnSetFrame.cpp
@@ -16,20 +16,20 @@
 using namespace mozilla;
 using namespace mozilla::layout;
 
 // To see this log, use $ MOZ_LOG=ColumnSet:4 ./mach run
 static LazyLogModule sColumnSetLog("ColumnSet");
 #define COLUMN_SET_LOG(msg, ...) \
   MOZ_LOG(sColumnSetLog, LogLevel::Debug, (msg, ##__VA_ARGS__))
 
-class nsDisplayColumnRule : public nsDisplayItem {
+class nsDisplayColumnRule : public nsPaintedDisplayItem {
  public:
   nsDisplayColumnRule(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayColumnRule);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayColumnRule() {
     MOZ_COUNT_DTOR(nsDisplayColumnRule);
     mBorderRenderers.Clear();
   }
 #endif
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2163,21 +2163,22 @@ int16_t nsFrame::DisplaySelection(nsPres
     if (isOkToTurnOn && (selType == nsISelectionController::SELECTION_OFF)) {
       selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
       selType = nsISelectionController::SELECTION_ON;
     }
   }
   return selType;
 }
 
-class nsDisplaySelectionOverlay : public nsDisplayItem {
+class nsDisplaySelectionOverlay : public nsPaintedDisplayItem {
  public:
   nsDisplaySelectionOverlay(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
                             int16_t aSelectionValue)
-      : nsDisplayItem(aBuilder, aFrame), mSelectionValue(aSelectionValue) {
+      : nsPaintedDisplayItem(aBuilder, aFrame),
+        mSelectionValue(aSelectionValue) {
     MOZ_COUNT_CTOR(nsDisplaySelectionOverlay);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplaySelectionOverlay() {
     MOZ_COUNT_DTOR(nsDisplaySelectionOverlay);
   }
 #endif
 
--- a/layout/generic/nsFrameSetFrame.cpp
+++ b/layout/generic/nsFrameSetFrame.cpp
@@ -1323,21 +1323,21 @@ void nsHTMLFramesetBorderFrame::Reflow(n
 
   // Override Reflow(), since we don't want to deal with what our
   // computed values are.
   SizeToAvailSize(aReflowInput, aDesiredSize);
 
   aDesiredSize.SetOverflowAreasToDesiredBounds();
 }
 
-class nsDisplayFramesetBorder : public nsDisplayItem {
+class nsDisplayFramesetBorder : public nsPaintedDisplayItem {
  public:
   nsDisplayFramesetBorder(nsDisplayListBuilder* aBuilder,
                           nsHTMLFramesetBorderFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayFramesetBorder);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayFramesetBorder() {
     MOZ_COUNT_DTOR(nsDisplayFramesetBorder);
   }
 #endif
 
@@ -1511,20 +1511,20 @@ void nsHTMLFramesetBlankFrame::Reflow(ns
 
   // Override Reflow(), since we don't want to deal with what our
   // computed values are.
   SizeToAvailSize(aReflowInput, aDesiredSize);
 
   aDesiredSize.SetOverflowAreasToDesiredBounds();
 }
 
-class nsDisplayFramesetBlank : public nsDisplayItem {
+class nsDisplayFramesetBlank : public nsPaintedDisplayItem {
  public:
   nsDisplayFramesetBlank(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayFramesetBlank);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayFramesetBlank() { MOZ_COUNT_DTOR(nsDisplayFramesetBlank); }
 #endif
 
   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
   NS_DISPLAY_DECL_NAME("FramesetBlank", TYPE_FRAMESET_BLANK)
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -1290,20 +1290,20 @@ struct nsRecessedBorder : public nsStyle
       mBorder.Side(side) = aBorderWidth;
       // Note: use SetBorderStyle here because we want to affect
       // mComputedBorder
       SetBorderStyle(side, StyleBorderStyle::Inset);
     }
   }
 };
 
-class nsDisplayAltFeedback final : public nsDisplayItem {
+class nsDisplayAltFeedback final : public nsPaintedDisplayItem {
  public:
   nsDisplayAltFeedback(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {}
+      : nsPaintedDisplayItem(aBuilder, aFrame) {}
 
   virtual nsDisplayItemGeometry* AllocateGeometry(
       nsDisplayListBuilder* aBuilder) override {
     return new nsDisplayItemGenericImageGeometry(this, aBuilder);
   }
 
   virtual void ComputeInvalidationRegion(
       nsDisplayListBuilder* aBuilder, const nsDisplayItemGeometry* aGeometry,
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -435,20 +435,20 @@ static nsIFrame* GetNextPage(nsIFrame* a
 }
 
 static gfx::Matrix4x4 ComputePageTransform(nsIFrame* aFrame,
                                            float aAppUnitsPerPixel) {
   float scale = aFrame->PresContext()->GetPageScale();
   return gfx::Matrix4x4::Scaling(scale, scale, 1);
 }
 
-class nsDisplayHeaderFooter final : public nsDisplayItem {
+class nsDisplayHeaderFooter final : public nsPaintedDisplayItem {
  public:
   nsDisplayHeaderFooter(nsDisplayListBuilder* aBuilder, nsPageFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayHeaderFooter);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayHeaderFooter() { MOZ_COUNT_DTOR(nsDisplayHeaderFooter); }
 #endif
 
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      gfxContext* aCtx) override {
--- a/layout/generic/nsPluginFrame.h
+++ b/layout/generic/nsPluginFrame.h
@@ -348,20 +348,20 @@ class nsDisplayPluginGeometry : public n
   nsDisplayPluginGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
       : nsDisplayItemGenericGeometry(aItem, aBuilder) {}
 
   // Plugins MozPaintWait event depends on sync decode, so we always want
   // to rebuild the display list when sync decoding.
   virtual bool InvalidateForSyncDecodeImages() const override { return true; }
 };
 
-class nsDisplayPlugin final : public nsDisplayItem {
+class nsDisplayPlugin final : public nsPaintedDisplayItem {
  public:
   nsDisplayPlugin(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayPlugin);
     aBuilder->SetContainsPluginItem();
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayPlugin() { MOZ_COUNT_DTOR(nsDisplayPlugin); }
 #endif
 
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
--- a/layout/ipc/RenderFrame.cpp
+++ b/layout/ipc/RenderFrame.cpp
@@ -157,17 +157,17 @@ static mozilla::LayoutDeviceIntPoint Get
 inline static bool IsTempLayerManager(mozilla::layers::LayerManager* aManager) {
   return (mozilla::layers::LayersBackend::LAYERS_BASIC ==
               aManager->GetBackendType() &&
           !static_cast<BasicLayerManager*>(aManager)->IsRetained());
 }
 
 nsDisplayRemote::nsDisplayRemote(nsDisplayListBuilder* aBuilder,
                                  nsSubDocumentFrame* aFrame)
-    : nsDisplayItem(aBuilder, aFrame),
+    : nsPaintedDisplayItem(aBuilder, aFrame),
       mTabId{0},
       mEventRegionsOverride(EventRegionsOverride::NoOverride) {
   bool frameIsPointerEventsNone = aFrame->StyleUI()->GetEffectivePointerEvents(
                                       aFrame) == NS_STYLE_POINTER_EVENTS_NONE;
   if (aBuilder->IsInsidePointerEventsNoneDoc() || frameIsPointerEventsNone) {
     mEventRegionsOverride |= EventRegionsOverride::ForceEmptyHitRegion;
   }
   if (nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(
--- a/layout/ipc/RenderFrame.h
+++ b/layout/ipc/RenderFrame.h
@@ -84,17 +84,17 @@ class RenderFrame final {
 
 }  // namespace layout
 }  // namespace mozilla
 
 /**
  * A nsDisplayRemote will graft a remote frame's shadow layer tree (for a given
  * nsFrameLoader) into its parent frame's layer tree.
  */
-class nsDisplayRemote final : public nsDisplayItem {
+class nsDisplayRemote final : public nsPaintedDisplayItem {
   typedef mozilla::dom::TabId TabId;
   typedef mozilla::gfx::Matrix4x4 Matrix4x4;
   typedef mozilla::layers::EventRegionsOverride EventRegionsOverride;
   typedef mozilla::layers::Layer Layer;
   typedef mozilla::layers::LayersId LayersId;
   typedef mozilla::layers::RefLayer RefLayer;
   typedef mozilla::layout::RenderFrame RenderFrame;
   typedef mozilla::LayoutDeviceRect LayoutDeviceRect;
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -1677,21 +1677,21 @@ nscoord nsMathMLChar::GetMaxWidth(nsIFra
   const nsBoundingMetrics container;  // zero target size
 
   StretchInternal(aForFrame, aDrawTarget, aFontSizeInflation, direction,
                   container, bm, aStretchHint | NS_STRETCH_MAXWIDTH);
 
   return std::max(bm.width, bm.rightBearing) - std::min(0, bm.leftBearing);
 }
 
-class nsDisplayMathMLSelectionRect final : public nsDisplayItem {
+class nsDisplayMathMLSelectionRect final : public nsPaintedDisplayItem {
  public:
   nsDisplayMathMLSelectionRect(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                                const nsRect& aRect)
-      : nsDisplayItem(aBuilder, aFrame), mRect(aRect) {
+      : nsPaintedDisplayItem(aBuilder, aFrame), mRect(aRect) {
     MOZ_COUNT_CTOR(nsDisplayMathMLSelectionRect);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayMathMLSelectionRect() {
     MOZ_COUNT_DTOR(nsDisplayMathMLSelectionRect);
   }
 #endif
 
@@ -1708,22 +1708,22 @@ void nsDisplayMathMLSelectionRect::Paint
                                   mFrame->PresContext()->AppUnitsPerDevPixel(),
                                   *drawTarget);
   // get color to use for selection from the look&feel object
   nscolor bgColor = LookAndFeel::GetColor(
       LookAndFeel::eColorID_TextSelectBackground, NS_RGB(0, 0, 0));
   drawTarget->FillRect(rect, ColorPattern(ToDeviceColor(bgColor)));
 }
 
-class nsDisplayMathMLCharForeground final : public nsDisplayItem {
+class nsDisplayMathMLCharForeground final : public nsPaintedDisplayItem {
  public:
   nsDisplayMathMLCharForeground(nsDisplayListBuilder* aBuilder,
                                 nsIFrame* aFrame, nsMathMLChar* aChar,
                                 uint16_t aIndex, bool aIsSelected)
-      : nsDisplayItem(aBuilder, aFrame),
+      : nsPaintedDisplayItem(aBuilder, aFrame),
         mChar(aChar),
         mIndex(aIndex),
         mIsSelected(aIsSelected) {
     MOZ_COUNT_CTOR(nsDisplayMathMLCharForeground);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayMathMLCharForeground() {
     MOZ_COUNT_DTOR(nsDisplayMathMLCharForeground);
@@ -1762,21 +1762,21 @@ class nsDisplayMathMLCharForeground fina
 
  private:
   nsMathMLChar* mChar;
   uint16_t mIndex;
   bool mIsSelected;
 };
 
 #ifdef DEBUG
-class nsDisplayMathMLCharDebug final : public nsDisplayItem {
+class nsDisplayMathMLCharDebug final : public nsPaintedDisplayItem {
  public:
   nsDisplayMathMLCharDebug(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                            const nsRect& aRect)
-      : nsDisplayItem(aBuilder, aFrame), mRect(aRect) {
+      : nsPaintedDisplayItem(aBuilder, aFrame), mRect(aRect) {
     MOZ_COUNT_CTOR(nsDisplayMathMLCharDebug);
   }
 #  ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayMathMLCharDebug() {
     MOZ_COUNT_DTOR(nsDisplayMathMLCharDebug);
   }
 #  endif
 
--- a/layout/mathml/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/nsMathMLContainerFrame.cpp
@@ -63,20 +63,20 @@ nsresult nsMathMLContainerFrame::ReflowE
   aDesiredSize.ISize(wm) = mBoundingMetrics.width;
 
   // Also return our bounding metrics
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
 
   return NS_OK;
 }
 
-class nsDisplayMathMLError : public nsDisplayItem {
+class nsDisplayMathMLError : public nsPaintedDisplayItem {
  public:
   nsDisplayMathMLError(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayMathMLError);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayMathMLError() { MOZ_COUNT_DTOR(nsDisplayMathMLError); }
 #endif
 
   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
   NS_DISPLAY_DECL_NAME("MathMLError", TYPE_MATHML_ERROR)
--- a/layout/mathml/nsMathMLFrame.cpp
+++ b/layout/mathml/nsMathMLFrame.cpp
@@ -295,21 +295,21 @@ void nsMathMLFrame::DisplayBoundingMetri
   nscoord w = aMetrics.rightBearing - aMetrics.leftBearing;
   nscoord h = aMetrics.ascent + aMetrics.descent;
 
   aLists.Content()->AppendNewToTop<nsDisplayMathMLBoundingMetrics>(
       aBuilder, aFrame, nsRect(x, y, w, h));
 }
 #endif
 
-class nsDisplayMathMLBar final : public nsDisplayItem {
+class nsDisplayMathMLBar final : public nsPaintedDisplayItem {
  public:
   nsDisplayMathMLBar(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                      const nsRect& aRect, uint16_t aIndex)
-      : nsDisplayItem(aBuilder, aFrame), mRect(aRect), mIndex(aIndex) {
+      : nsPaintedDisplayItem(aBuilder, aFrame), mRect(aRect), mIndex(aIndex) {
     MOZ_COUNT_CTOR(nsDisplayMathMLBar);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayMathMLBar() { MOZ_COUNT_DTOR(nsDisplayMathMLBar); }
 #endif
 
   virtual uint16_t CalculatePerFrameKey() const override { return mIndex; }
 
--- a/layout/mathml/nsMathMLmencloseFrame.cpp
+++ b/layout/mathml/nsMathMLmencloseFrame.cpp
@@ -696,22 +696,22 @@ ComputedStyle* nsMathMLmencloseFrame::Ge
 
 void nsMathMLmencloseFrame::SetAdditionalComputedStyle(
     int32_t aIndex, ComputedStyle* aComputedStyle) {
   int32_t len = mMathMLChar.Length();
   if (aIndex >= 0 && aIndex < len)
     mMathMLChar[aIndex].SetComputedStyle(aComputedStyle);
 }
 
-class nsDisplayNotation final : public nsDisplayItem {
+class nsDisplayNotation final : public nsPaintedDisplayItem {
  public:
   nsDisplayNotation(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                     const nsRect& aRect, nscoord aThickness,
                     nsMencloseNotation aType)
-      : nsDisplayItem(aBuilder, aFrame),
+      : nsPaintedDisplayItem(aBuilder, aFrame),
         mRect(aRect),
         mThickness(aThickness),
         mType(aType) {
     MOZ_COUNT_CTOR(nsDisplayNotation);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayNotation() { MOZ_COUNT_DTOR(nsDisplayNotation); }
 #endif
--- a/layout/mathml/nsMathMLmfracFrame.cpp
+++ b/layout/mathml/nsMathMLmfracFrame.cpp
@@ -564,21 +564,21 @@ nsresult nsMathMLmfracFrame::PlaceIntern
            sizeDen.BlockStartAscent();
       FinishReflowChild(frameDen, presContext, sizeDen, nullptr, dx, dy, 0);
     }
   }
 
   return NS_OK;
 }
 
-class nsDisplayMathMLSlash : public nsDisplayItem {
+class nsDisplayMathMLSlash : public nsPaintedDisplayItem {
  public:
   nsDisplayMathMLSlash(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                        const nsRect& aRect, nscoord aThickness, bool aRTL)
-      : nsDisplayItem(aBuilder, aFrame),
+      : nsPaintedDisplayItem(aBuilder, aFrame),
         mRect(aRect),
         mThickness(aThickness),
         mRTL(aRTL) {
     MOZ_COUNT_CTOR(nsDisplayMathMLSlash);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayMathMLSlash() { MOZ_COUNT_DTOR(nsDisplayMathMLSlash); }
 #endif
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -4187,17 +4187,17 @@ void nsDisplayBackgroundImage::HitTest(n
                                        nsTArray<nsIFrame*>* aOutFrames) {
   if (RoundedBorderIntersectsRect(mFrame, ToReferenceFrame(), aRect)) {
     aOutFrames->AppendElement(mFrame);
   }
 }
 
 bool nsDisplayBackgroundImage::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                                  nsRegion* aVisibleRegion) {
-  if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion)) {
+  if (!nsDisplayImageContainer::ComputeVisibility(aBuilder, aVisibleRegion)) {
     return false;
   }
 
   // Return false if the background was propagated away from this
   // frame. We don't want this display item to show up and confuse
   // anything.
   return mBackgroundStyle;
 }
@@ -4424,17 +4424,17 @@ bool nsDisplayTableBackgroundImage::IsIn
   bool result = mStyleFrame ? mStyleFrame->IsInvalid(aRect) : false;
   aRect += ToReferenceFrame();
   return result;
 }
 
 nsDisplayThemedBackground::nsDisplayThemedBackground(
     nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
     const nsRect& aBackgroundRect)
-    : nsDisplayItem(aBuilder, aFrame), mBackgroundRect(aBackgroundRect) {
+    : nsPaintedDisplayItem(aBuilder, aFrame), mBackgroundRect(aBackgroundRect) {
   MOZ_COUNT_CTOR(nsDisplayThemedBackground);
 }
 
 void nsDisplayThemedBackground::Init(nsDisplayListBuilder* aBuilder) {
   const nsStyleDisplay* disp = StyleFrame()->StyleDisplay();
   mAppearance = disp->mAppearance;
   StyleFrame()->IsThemed(disp, &mThemeTransparency);
 
@@ -5124,26 +5124,27 @@ bool nsDisplayCompositorHitTestInfo::Cre
   return true;
 }
 
 uint16_t nsDisplayCompositorHitTestInfo::CalculatePerFrameKey() const {
   return mIndex;
 }
 
 int32_t nsDisplayCompositorHitTestInfo::ZIndex() const {
-  return mOverrideZIndex ? *mOverrideZIndex : nsDisplayItem::ZIndex();
+  return mOverrideZIndex ? *mOverrideZIndex
+                         : nsDisplayHitTestInfoItem::ZIndex();
 }
 
 void nsDisplayCompositorHitTestInfo::SetOverrideZIndex(int32_t aZIndex) {
   mOverrideZIndex = Some(aZIndex);
 }
 
 nsDisplayCaret::nsDisplayCaret(nsDisplayListBuilder* aBuilder,
                                nsIFrame* aCaretFrame)
-    : nsDisplayItem(aBuilder, aCaretFrame),
+    : nsPaintedDisplayItem(aBuilder, aCaretFrame),
       mCaret(aBuilder->GetCaret()),
       mBounds(aBuilder->GetCaretRect() + ToReferenceFrame()) {
   MOZ_COUNT_CTOR(nsDisplayCaret);
 }
 
 #ifdef NS_BUILD_REFCNT_LOGGING
 nsDisplayCaret::~nsDisplayCaret() { MOZ_COUNT_DTOR(nsDisplayCaret); }
 #endif
@@ -5196,17 +5197,17 @@ bool nsDisplayCaret::CreateWebRenderComm
   if (!devHookRect.IsEmpty()) {
     aBuilder.PushRect(hook, hook, !BackfaceIsHidden(), wr::ToColorF(color));
   }
   return true;
 }
 
 nsDisplayBorder::nsDisplayBorder(nsDisplayListBuilder* aBuilder,
                                  nsIFrame* aFrame)
-    : nsDisplayItem(aBuilder, aFrame) {
+    : nsPaintedDisplayItem(aBuilder, aFrame) {
   MOZ_COUNT_CTOR(nsDisplayBorder);
 
   mBounds = CalculateBounds<nsRect>(*mFrame->StyleBorder());
 }
 
 bool nsDisplayBorder::IsInvisibleInRect(const nsRect& aRect) const {
   nsRect paddingRect = GetPaddingRect();
   const nsStyleBorder* styleBorder;
@@ -5365,17 +5366,17 @@ bool nsDisplayBoxShadowOuter::IsInvisibl
   bool hasBorderRadii = mFrame->GetBorderRadii(twipsRadii);
   if (!hasBorderRadii) return true;
 
   return RoundedRectContainsRect(frameRect, twipsRadii, aRect);
 }
 
 bool nsDisplayBoxShadowOuter::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                                 nsRegion* aVisibleRegion) {
-  if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion)) {
+  if (!nsPaintedDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion)) {
     return false;
   }
 
   mVisibleRegion.And(*aVisibleRegion, GetPaintRect());
   return true;
 }
 
 bool nsDisplayBoxShadowOuter::CanBuildWebRenderDisplayItems() {
@@ -5632,17 +5633,17 @@ bool nsDisplayBoxShadowInner::CreateWebR
   nsDisplayBoxShadowInner::CreateInsetBoxShadowWebRenderCommands(
       aBuilder, aSc, visible, mFrame, borderRect);
 
   return true;
 }
 
 bool nsDisplayBoxShadowInner::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                                 nsRegion* aVisibleRegion) {
-  if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion)) {
+  if (!nsPaintedDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion)) {
     return false;
   }
 
   mVisibleRegion.And(*aVisibleRegion, GetPaintRect());
   return true;
 }
 
 nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
@@ -6053,71 +6054,76 @@ static const size_t kOpacityMaxListSize 
  * We need to do this recursively, because the child display items might contain
  * nested nsDisplayWrapLists.
  *
  * Returns false if there are more than |kOpacityMaxChildCount| items, or if an
  * item that returns false for CanApplyOpacity() is encountered.
  * Otherwise returns true.
  */
 static bool CollectItemsWithOpacity(nsDisplayList* aList,
-                                    nsTArray<nsDisplayItem*>& aArray) {
+                                    nsTArray<nsPaintedDisplayItem*>& aArray) {
   if (aList->Count() > kOpacityMaxListSize) {
     // Exit early, since |aList| will likely contain more than
     // |kOpacityMaxChildCount| items.
     return false;
   }
 
   for (nsDisplayItem* i : *aList) {
     const DisplayItemType type = i->GetType();
 
+    if (type == DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO) {
+      continue;
+    }
+
     // Descend only into wraplists.
     if (type == DisplayItemType::TYPE_WRAP_LIST) {
       // The current display item has children, process them first.
       if (!CollectItemsWithOpacity(i->GetChildren(), aArray)) {
         return false;
       }
 
       continue;
     }
 
-    if (type == DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO) {
-      continue;
-    }
-
-    if (!i->CanApplyOpacity() || aArray.Length() == kOpacityMaxChildCount) {
+    if (aArray.Length() == kOpacityMaxChildCount) {
       return false;
     }
 
-    aArray.AppendElement(i);
+    auto* item = i->AsPaintedDisplayItem();
+    if (!item || !item->CanApplyOpacity()) {
+      return false;
+    }
+
+    aArray.AppendElement(item);
   }
 
   return true;
 }
 
 bool nsDisplayOpacity::ApplyOpacityToChildren(nsDisplayListBuilder* aBuilder) {
   if (mChildOpacityState == ChildOpacityState::Deferred) {
     return false;
   }
 
   // Iterate through the child display list and copy at most
   // |kOpacityMaxChildCount| child display item pointers to a temporary list.
-  AutoTArray<nsDisplayItem*, kOpacityMaxChildCount> items;
+  AutoTArray<nsPaintedDisplayItem*, kOpacityMaxChildCount> items;
   if (!CollectItemsWithOpacity(&mList, items)) {
     mChildOpacityState = ChildOpacityState::Deferred;
     return false;
   }
 
   struct {
-    nsDisplayItem* item;
+    nsPaintedDisplayItem* item;
     nsRect bounds;
   } children[kOpacityMaxChildCount];
 
   bool snap;
   size_t childCount = 0;
-  for (nsDisplayItem* item : items) {
+  for (nsPaintedDisplayItem* item : items) {
     children[childCount].item = item;
     children[childCount].bounds = item->GetBounds(aBuilder, &snap);
     childCount++;
   }
 
   for (size_t i = 0; i < childCount; i++) {
     for (size_t j = i + 1; j < childCount; j++) {
       if (children[i].bounds.Intersects(children[j].bounds)) {
@@ -6721,17 +6727,17 @@ nsIFrame* nsDisplaySubDocument::FrameFor
   return mSubDocFrame ? mSubDocFrame : mFrame;
 }
 
 void nsDisplaySubDocument::RemoveFrame(nsIFrame* aFrame) {
   if (aFrame == mSubDocFrame) {
     mSubDocFrame = nullptr;
     SetDeletedFrame();
   }
-  nsDisplayItem::RemoveFrame(aFrame);
+  nsDisplayOwnLayer::RemoveFrame(aFrame);
 }
 
 void nsDisplaySubDocument::Disown() {
   if (mFrame) {
     mFrame->RemoveDisplayItem(this);
     mFrame = nullptr;
   }
   if (mSubDocFrame) {
@@ -8932,17 +8938,17 @@ bool nsDisplayPerspective::CreateWebRend
       GetChildren(), this, aDisplayListBuilder, sc, aBuilder, aResources);
 
   return true;
 }
 
 nsDisplayText::nsDisplayText(nsDisplayListBuilder* aBuilder,
                              nsTextFrame* aFrame,
                              const Maybe<bool>& aIsSelected)
-    : nsDisplayItem(aBuilder, aFrame),
+    : nsPaintedDisplayItem(aBuilder, aFrame),
       mOpacity(1.0f),
       mVisIStartEdge(0),
       mVisIEndEdge(0) {
   MOZ_COUNT_CTOR(nsDisplayText);
   mIsFrameSelected = aIsSelected;
   mBounds = mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
   // Bug 748228
   mBounds.Inflate(mFrame->PresContext()->AppUnitsPerDevPixel());
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -1989,17 +1989,16 @@ class nsDisplayListBuilder {
   bool mBuildAsyncZoomContainer;
 
   nsRect mHitTestArea;
   CompositorHitTestInfo mHitTestInfo;
 };
 
 class nsDisplayItem;
 class nsDisplayItemBase;
-class nsDisplayWrapList;
 class nsDisplayList;
 class RetainedDisplayList;
 
 // All types are defined in nsDisplayItemTypes.h
 #define NS_DISPLAY_DECL_NAME(n, e)                                           \
   const char* Name() const override { return n; }                            \
   constexpr static DisplayItemType ItemType() { return DisplayItemType::e; } \
                                                                              \
@@ -2032,18 +2031,20 @@ MOZ_ALWAYS_INLINE T* MakeClone(nsDisplay
 
 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
 void AssertUniqueItem(nsDisplayItem* aItem);
 #endif
 
 template <typename T, typename F, typename... Args>
 MOZ_ALWAYS_INLINE T* MakeDisplayItem(nsDisplayListBuilder* aBuilder, F* aFrame,
                                      Args&&... aArgs) {
+  static_assert(std::is_base_of<nsDisplayItem, T>::value,
+                "Display item should be derived from nsDisplayItem");
   static_assert(std::is_base_of<nsIFrame, F>::value,
-                "Frame type is not derived from nsIFrame");
+                "Frame type should be derived from nsIFrame");
 
   T* item = new (aBuilder) T(aBuilder, aFrame, std::forward<Args>(aArgs)...);
 
   if (T::ItemType() != DisplayItemType::TYPE_GENERIC) {
     item->SetType(T::ItemType());
   }
 
   item->SetPerFrameKey(item->CalculatePerFrameKey());
@@ -2105,16 +2106,19 @@ class nsDisplayItemLink {
   nsDisplayItemLink() : mAbove(nullptr) {}
   nsDisplayItemLink(const nsDisplayItemLink&) : mAbove(nullptr) {}
   ~nsDisplayItemLink() { MOZ_RELEASE_ASSERT(!mAbove); }
   nsDisplayItem* mAbove;
 
   friend class nsDisplayList;
 };
 
+class nsPaintedDisplayItem;
+class nsDisplayWrapList;
+
 /*
  * nsDisplayItemBase is a base-class for all display items. It is mainly
  * responsible for handling the frame-display item 1:n relationship, as well as
  * storing the state needed for display list merging.
  *
  * Display items are arena-allocated during display list construction.
  *
  * Display items can be containers --- i.e., they can perform hit testing
@@ -2123,16 +2127,37 @@ class nsDisplayItemLink {
  * Display items belong to a list at all times (except temporarily as they
  * move from one list to another).
  */
 class nsDisplayItemBase : public nsDisplayItemLink {
  public:
   nsDisplayItemBase() = delete;
 
   /**
+   * Downcasts this item to nsPaintedDisplayItem, if possible.
+   */
+  virtual nsPaintedDisplayItem* AsPaintedDisplayItem() { return nullptr; }
+  virtual const nsPaintedDisplayItem* AsPaintedDisplayItem() const {
+    return nullptr;
+  }
+
+  /**
+   * Downcasts this item to nsDisplayWrapList, if possible.
+   */
+  virtual nsDisplayWrapList* AsDisplayWrapList() { return nullptr; }
+  virtual const nsDisplayWrapList* AsDisplayWrapList() const { return nullptr; }
+
+  /**
+   * Create a clone of this item.
+   */
+  virtual nsDisplayItem* Clone(nsDisplayListBuilder* aBuilder) const {
+    return nullptr;
+  }
+
+  /**
    * Frees the memory allocated for this display item.
    * The given display list builder must have allocated this display item.
    */
   virtual void Destroy(nsDisplayListBuilder* aBuilder) {
     const DisplayItemType type = GetType();
     this->~nsDisplayItemBase();
     aBuilder->Destroy(type, this);
   }
@@ -2400,40 +2425,16 @@ class nsDisplayItem : public nsDisplayIt
   nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                 const ActiveScrolledRoot* aActiveScrolledRoot);
 
   virtual ~nsDisplayItem() {
     MOZ_COUNT_DTOR(nsDisplayItem);
     SetDisplayItemData(nullptr, nullptr);
   }
 
- public:
-  nsDisplayItem() = delete;
-
-  virtual void RestoreState() {
-    mClipChain = mState.mClipChain;
-    mClip = mState.mClip;
-    mItemFlags -= ItemFlag::DisableSubpixelAA;
-  }
-
-  /**
-   * Downcasts this item to nsDisplayWrapList, if possible.
-   */
-  virtual const nsDisplayWrapList* AsDisplayWrapList() const { return nullptr; }
-  virtual nsDisplayWrapList* AsDisplayWrapList() { return nullptr; }
-
-  /**
-   * Create a clone of this item.
-   */
-  virtual nsDisplayItem* Clone(nsDisplayListBuilder* aBuilder) const {
-    MOZ_ASSERT_UNREACHABLE("Clone() called on an incorrect item type!");
-    return nullptr;
-  }
-
-  nsDisplayItem(const nsDisplayItem&) = delete;
   /**
    * The custom copy-constructor is implemented to prevent copying the saved
    * state of the item.
    * This is currently only used when creating temporary items for merging.
    */
   nsDisplayItem(nsDisplayListBuilder* aBuilder, const nsDisplayItem& aOther)
       : nsDisplayItemBase(aBuilder, aOther),
         mClipChain(aOther.mClipChain),
@@ -2455,16 +2456,26 @@ class nsDisplayItem : public nsDisplayIt
     if (mFrame->In3DContextAndBackfaceIsHidden()) {
       mItemFlags += ItemFlag::BackfaceHidden;
     }
     if (aOther.Combines3DTransformWithAncestors()) {
       mItemFlags += ItemFlag::Combines3DTransformWithAncestors;
     }
   }
 
+ public:
+  nsDisplayItem() = delete;
+  nsDisplayItem(const nsDisplayItem&) = delete;
+
+  virtual void RestoreState() {
+    mClipChain = mState.mClipChain;
+    mClip = mState.mClip;
+    mItemFlags -= ItemFlag::DisableSubpixelAA;
+  }
+
   struct HitTestState {
     explicit HitTestState() : mInPreserves3D(false) {}
 
     ~HitTestState() {
       NS_ASSERTION(mItemBuffer.Length() == 0,
                    "mItemBuffer should have been cleared");
     }
 
@@ -2704,37 +2715,16 @@ class nsDisplayItem : public nsDisplayIt
    * true, change a returned value of LAYER_INACTIVE to LAYER_ACTIVE.
    */
   virtual LayerState GetLayerState(
       nsDisplayListBuilder* aBuilder, LayerManager* aManager,
       const ContainerLayerParameters& aParameters) {
     return mozilla::LAYER_NONE;
   }
 
-  /**
-   * Returns true if this item supports PaintWithClip, where the clipping
-   * is used directly as the primitive geometry instead of needing an explicit
-   * clip.
-   */
-  virtual bool CanPaintWithClip(const DisplayItemClip& aClip) { return false; }
-
-  /**
-   * Actually paint this item to some rendering context.
-   * Content outside mVisibleRect need not be painted.
-   * aCtx must be set up as for nsDisplayList::Paint.
-   */
-  virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) {}
-
-  /**
-   * Same as Paint, except provides a clip to use the geometry to draw with.
-   * Must not be called unless CanPaintWithClip returned true.
-   */
-  virtual void PaintWithClip(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
-                             const DisplayItemClip& aClip) {}
-
 #ifdef MOZ_DUMP_PAINTING
   /**
    * Mark this display item as being painted via
    * FrameLayerBuilder::DrawPaintedLayer.
    */
   bool Painted() const { return mItemFlags.contains(ItemFlag::Painted); }
 
   /**
@@ -2923,34 +2913,16 @@ class nsDisplayItem : public nsDisplayIt
    * reference frame. Can be different from mBuildingRect for
    * nsDisplayTransform, since the reference frame for the children is different
    * from the reference frame for the item itself.
    */
   virtual const nsRect& GetBuildingRectForChildren() const {
     return mBuildingRect;
   }
 
-  /**
-   * Stores the given opacity value to be applied when drawing. It is an error
-   * to call this if CanApplyOpacity returned false.
-   */
-  virtual void ApplyOpacity(nsDisplayListBuilder* aBuilder, float aOpacity,
-                            const DisplayItemClipChain* aClip) {
-    NS_ASSERTION(CanApplyOpacity(), "ApplyOpacity not supported on this type");
-  }
-  /**
-   * Returns true if this display item would return true from ApplyOpacity
-   * without actually applying the opacity. Otherwise returns false.
-   */
-  virtual bool CanApplyOpacity() const { return false; }
-
-  bool ForceNotVisible() const {
-    return mItemFlags.contains(ItemFlag::ForceNotVisible);
-  }
-
   virtual void WriteDebugInfo(std::stringstream& aStream) {}
 
   nsDisplayItem* GetAbove() { return mAbove; }
 
   /**
    * Like ComputeVisibility, but does the work that nsDisplayList
    * does per-item:
    * -- Intersects GetBounds with aVisibleRegion and puts the result
@@ -3048,16 +3020,20 @@ class nsDisplayItem : public nsDisplayIt
   bool BackfaceIsHidden() const {
     return mItemFlags.contains(ItemFlag::BackfaceHidden);
   }
 
   bool Combines3DTransformWithAncestors() const {
     return mItemFlags.contains(ItemFlag::Combines3DTransformWithAncestors);
   }
 
+  bool ForceNotVisible() const {
+    return mItemFlags.contains(ItemFlag::ForceNotVisible);
+  }
+
   bool In3DContextAndBackfaceIsHidden() const {
     return mItemFlags.contains(ItemFlag::BackfaceHidden) &&
            mItemFlags.contains(ItemFlag::Combines3DTransformWithAncestors);
   }
 
   bool HasDifferentFrame(const nsDisplayItem* aOther) const {
     return mFrame != aOther->mFrame;
   }
@@ -3153,16 +3129,75 @@ class nsDisplayItem : public nsDisplayIt
     // True if this frame has been painted.
     Painted,
 #endif
   };
 
   mozilla::EnumSet<ItemFlag, uint8_t> mItemFlags;
 };
 
+class nsPaintedDisplayItem : public nsDisplayItem {
+ public:
+  nsPaintedDisplayItem* AsPaintedDisplayItem() final { return this; }
+  const nsPaintedDisplayItem* AsPaintedDisplayItem() const final {
+    return this;
+  }
+
+  /**
+   * Stores the given opacity value to be applied when drawing. It is an error
+   * to call this if CanApplyOpacity returned false.
+   */
+  virtual void ApplyOpacity(nsDisplayListBuilder* aBuilder, float aOpacity,
+                            const DisplayItemClipChain* aClip) {
+    MOZ_ASSERT(CanApplyOpacity(), "ApplyOpacity is not supported on this type");
+  }
+
+  /**
+   * Returns true if this display item would return true from ApplyOpacity
+   * without actually applying the opacity. Otherwise returns false.
+   */
+  virtual bool CanApplyOpacity() const { return false; }
+
+  /**
+   * Returns true if this item supports PaintWithClip, where the clipping
+   * is used directly as the primitive geometry instead of needing an explicit
+   * clip.
+   */
+  virtual bool CanPaintWithClip(const DisplayItemClip& aClip) { return false; }
+
+  /**
+   * Same as |Paint()|, except provides a clip to use the geometry to draw with.
+   * Must not be called unless |CanPaintWithClip()| returned true.
+   */
+  virtual void PaintWithClip(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
+                             const DisplayItemClip& aClip) {
+    MOZ_ASSERT_UNREACHABLE("PaintWithClip() is not implemented!");
+  }
+
+  /**
+   * Paint this item to some rendering context.
+   */
+  virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) {
+    // TODO(miko): Make this a pure virtual function to force implementation.
+    MOZ_ASSERT_UNREACHABLE("Paint() is not implemented!");
+  }
+
+ protected:
+  nsPaintedDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
+      : nsDisplayItem(aBuilder, aFrame) {}
+
+  nsPaintedDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
+                       const ActiveScrolledRoot* aActiveScrolledRoot)
+      : nsDisplayItem(aBuilder, aFrame, aActiveScrolledRoot) {}
+
+  nsPaintedDisplayItem(nsDisplayListBuilder* aBuilder,
+                       const nsPaintedDisplayItem& aOther)
+      : nsDisplayItem(aBuilder, aOther) {}
+};
+
 /**
  * Manages a singly-linked list of display list items.
  *
  * mSentinel is the sentinel list value, the first value in the null-terminated
  * linked list of items. mTop is the last item in the list (whose 'above'
  * pointer is null). This class has no virtual methods. So list objects are just
  * two pointers.
  *
@@ -3882,34 +3917,34 @@ struct HitTestInfo {
   mozilla::gfx::CompositorHitTestInfo mFlags;
 
   AnimatedGeometryRoot* mAGR;
   const mozilla::ActiveScrolledRoot* mASR;
   RefPtr<const mozilla::DisplayItemClipChain> mClipChain;
   const mozilla::DisplayItemClip* mClip;
 };
 
-class nsDisplayHitTestInfoItem : public nsDisplayItem {
+class nsDisplayHitTestInfoItem : public nsPaintedDisplayItem {
  public:
   nsDisplayHitTestInfoItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {}
+      : nsPaintedDisplayItem(aBuilder, aFrame) {}
 
   nsDisplayHitTestInfoItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                            const ActiveScrolledRoot* aActiveScrolledRoot)
-      : nsDisplayItem(aBuilder, aFrame, aActiveScrolledRoot) {}
+      : nsPaintedDisplayItem(aBuilder, aFrame, aActiveScrolledRoot) {}
 
   nsDisplayHitTestInfoItem(nsDisplayListBuilder* aBuilder,
                            const nsDisplayHitTestInfoItem& aOther)
-      : nsDisplayItem(aBuilder, aOther) {}
+      : nsPaintedDisplayItem(aBuilder, aOther) {}
 
   const HitTestInfo& GetHitTestInfo() const { return *mHitTestInfo; }
 
   void SetActiveScrolledRoot(
       const ActiveScrolledRoot* aActiveScrolledRoot) override {
-    nsDisplayItem::SetActiveScrolledRoot(aActiveScrolledRoot);
+    nsPaintedDisplayItem::SetActiveScrolledRoot(aActiveScrolledRoot);
     UpdateHitTestInfoActiveScrolledRoot(aActiveScrolledRoot);
   }
 
   /**
    * Updates mASR and mClip fields using the given |aActiveScrolledRoot|.
    */
   void UpdateHitTestInfoActiveScrolledRoot(
       const ActiveScrolledRoot* aActiveScrolledRoot) {
@@ -3951,25 +3986,25 @@ class nsDisplayHitTestInfoItem : public 
 #ifdef DEBUG
   bool IsHitTestItem() const override { return true; }
 #endif
 
  protected:
   mozilla::UniquePtr<HitTestInfo> mHitTestInfo;
 };
 
-class nsDisplayImageContainer : public nsDisplayItem {
+class nsDisplayImageContainer : public nsPaintedDisplayItem {
  public:
   typedef mozilla::LayerIntPoint LayerIntPoint;
   typedef mozilla::LayoutDeviceRect LayoutDeviceRect;
   typedef mozilla::layers::ImageContainer ImageContainer;
   typedef mozilla::layers::ImageLayer ImageLayer;
 
   nsDisplayImageContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {}
+      : nsPaintedDisplayItem(aBuilder, aFrame) {}
 
   /**
    * @return true if this display item can be optimized into an image layer.
    * It is an error to call GetContainer() unless you've called
    * CanOptimizeToImageLayer() first and it returned true.
    */
   virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
                                        nsDisplayListBuilder* aBuilder);
@@ -3991,41 +4026,41 @@ class nsDisplayImageContainer : public n
  * that are not opaque, do not receive events, and are bounded by a frame's
  * border-rect.
  *
  * This should not be used for display items which are created frequently,
  * because each item is one or two pointers bigger than an item from a
  * custom display item class could be, and fractionally slower. However it does
  * save code size. We use this for infrequently-used item types.
  */
-class nsDisplayGeneric : public nsDisplayItem {
+class nsDisplayGeneric : public nsPaintedDisplayItem {
  public:
   typedef void (*PaintCallback)(nsIFrame* aFrame, DrawTarget* aDrawTarget,
                                 const nsRect& aDirtyRect, nsPoint aFramePt);
 
   // XXX: should be removed eventually
   typedef void (*OldPaintCallback)(nsIFrame* aFrame, gfxContext* aCtx,
                                    const nsRect& aDirtyRect, nsPoint aFramePt);
 
   nsDisplayGeneric(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                    PaintCallback aPaint, const char* aName,
                    DisplayItemType aType)
-      : nsDisplayItem(aBuilder, aFrame),
+      : nsPaintedDisplayItem(aBuilder, aFrame),
         mPaint(aPaint),
         mOldPaint(nullptr),
         mName(aName) {
     MOZ_COUNT_CTOR(nsDisplayGeneric);
     SetType(aType);
   }
 
   // XXX: should be removed eventually
   nsDisplayGeneric(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                    OldPaintCallback aOldPaint, const char* aName,
                    DisplayItemType aType)
-      : nsDisplayItem(aBuilder, aFrame),
+      : nsPaintedDisplayItem(aBuilder, aFrame),
         mPaint(nullptr),
         mOldPaint(aOldPaint),
         mName(aName) {
     MOZ_COUNT_CTOR(nsDisplayGeneric);
     SetType(aType);
   }
 
   constexpr static DisplayItemType ItemType() {
@@ -4075,21 +4110,21 @@ class nsDisplayGeneric : public nsDispla
  * and eliminate this class altogether in favor of nsDisplayGeneric, but for
  * the time being we can't pass args to a PaintCallback, so just have a
  * separate class to do the right thing.  Sadly, this alsmo means we need to
  * hack all leaf frame classes to handle this.
  *
  * XXXbz the color thing is a bit of a mess, but 0 basically means "not set"
  * here...  I could switch it all to nscolor, but why bother?
  */
-class nsDisplayReflowCount : public nsDisplayItem {
+class nsDisplayReflowCount : public nsPaintedDisplayItem {
  public:
   nsDisplayReflowCount(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                        const char* aFrameName, uint32_t aColor = 0)
-      : nsDisplayItem(aBuilder, aFrame),
+      : nsPaintedDisplayItem(aBuilder, aFrame),
         mFrameName(aFrameName),
         mColor(aColor) {
     MOZ_COUNT_CTOR(nsDisplayReflowCount);
   }
 
 #  ifdef NS_BUILD_REFCNT_LOGGING
   ~nsDisplayReflowCount() override { MOZ_COUNT_DTOR(nsDisplayReflowCount); }
 #  endif
@@ -4138,17 +4173,17 @@ class nsDisplayReflowCount : public nsDi
 #else  // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
 
 #  define DO_GLOBAL_REFLOW_COUNT_DSP(_name)
 #  define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color)
 #  define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super)
 
 #endif  // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
 
-class nsDisplayCaret : public nsDisplayItem {
+class nsDisplayCaret : public nsPaintedDisplayItem {
  public:
   nsDisplayCaret(nsDisplayListBuilder* aBuilder, nsIFrame* aCaretFrame);
 
 #ifdef NS_BUILD_REFCNT_LOGGING
   ~nsDisplayCaret() override;
 #endif
 
   NS_DISPLAY_DECL_NAME("Caret", TYPE_CARET)
@@ -4165,17 +4200,17 @@ class nsDisplayCaret : public nsDisplayI
  protected:
   RefPtr<nsCaret> mCaret;
   nsRect mBounds;
 };
 
 /**
  * The standard display item to paint the CSS borders of a frame.
  */
-class nsDisplayBorder : public nsDisplayItem {
+class nsDisplayBorder : public nsPaintedDisplayItem {
  public:
   nsDisplayBorder(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
 
 #ifdef NS_BUILD_REFCNT_LOGGING
   ~nsDisplayBorder() override { MOZ_COUNT_DTOR(nsDisplayBorder); }
 #endif
 
   NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER)
@@ -4275,21 +4310,21 @@ class nsDisplayBorder : public nsDisplay
  * drawing of the background color into this class (from nsDisplayBackground
  * via nsDisplayCanvasBackground). This is done so that we can always draw a
  * background color to avoid ugly flashes of white when we can't draw a full
  * frame tree (ie when a page is loading). The bounds can differ from the
  * frame's bounds -- this is needed when a frame/iframe is loading and there
  * is not yet a frame tree to go in the frame/iframe so we use the subdoc
  * frame of the parent document as a standin.
  */
-class nsDisplaySolidColorBase : public nsDisplayItem {
+class nsDisplaySolidColorBase : public nsPaintedDisplayItem {
  public:
   nsDisplaySolidColorBase(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                           nscolor aColor)
-      : nsDisplayItem(aBuilder, aFrame), mColor(aColor) {}
+      : nsPaintedDisplayItem(aBuilder, aFrame), mColor(aColor) {}
 
   nsDisplayItemGeometry* AllocateGeometry(
       nsDisplayListBuilder* aBuilder) override {
     return new nsDisplaySolidColorGeometry(this, aBuilder, mColor);
   }
 
   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                  const nsDisplayItemGeometry* aGeometry,
@@ -4375,23 +4410,23 @@ class nsDisplaySolidColor : public nsDis
   mozilla::Maybe<int32_t> mOverrideZIndex;
 };
 
 /**
  * A display item that renders a solid color over a region. This is not
  * exposed through CSS, its only purpose is efficient invalidation of
  * the find bar highlighter dimmer.
  */
-class nsDisplaySolidColorRegion : public nsDisplayItem {
+class nsDisplaySolidColorRegion : public nsPaintedDisplayItem {
   typedef mozilla::gfx::Color Color;
 
  public:
   nsDisplaySolidColorRegion(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                             const nsRegion& aRegion, nscolor aColor)
-      : nsDisplayItem(aBuilder, aFrame),
+      : nsPaintedDisplayItem(aBuilder, aFrame),
         mRegion(aRegion),
         mColor(Color::FromABGR(aColor)) {
     NS_ASSERTION(NS_GET_A(aColor) > 0,
                  "Don't create invisible nsDisplaySolidColorRegions!");
     MOZ_COUNT_CTOR(nsDisplaySolidColorRegion);
   }
 
 #ifdef NS_BUILD_REFCNT_LOGGING
@@ -4571,17 +4606,17 @@ class nsDisplayBackgroundImage : public 
       mDependentFrame->AddDisplayItem(this);
     }
   }
 
   void RemoveFrame(nsIFrame* aFrame) override {
     if (aFrame == mDependentFrame) {
       mDependentFrame = nullptr;
     }
-    nsDisplayItem::RemoveFrame(aFrame);
+    nsDisplayImageContainer::RemoveFrame(aFrame);
   }
 
  protected:
   typedef class mozilla::layers::ImageContainer ImageContainer;
   typedef class mozilla::layers::ImageLayer ImageLayer;
 
   bool CanBuildWebRenderDisplayItems(LayerManager* aManager,
                                      nsDisplayListBuilder* aBuilder);
@@ -4687,17 +4722,17 @@ class nsDisplayTableBackgroundImage : pu
 
   nsIFrame* mStyleFrame;
   TableType mTableType;
 };
 
 /**
  * A display item to paint the native theme background for a frame.
  */
-class nsDisplayThemedBackground : public nsDisplayItem {
+class nsDisplayThemedBackground : public nsPaintedDisplayItem {
  public:
   nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                             const nsRect& aBackgroundRect);
 
 #ifdef NS_BUILD_REFCNT_LOGGING
   ~nsDisplayThemedBackground() override {
     MOZ_COUNT_DTOR(nsDisplayThemedBackground);
   }
@@ -4706,17 +4741,17 @@ class nsDisplayThemedBackground : public
 #endif
 
   NS_DISPLAY_DECL_NAME("ThemedBackground", TYPE_THEMED_BACKGROUND)
 
   void Init(nsDisplayListBuilder* aBuilder);
 
   void Destroy(nsDisplayListBuilder* aBuilder) override {
     aBuilder->UnregisterThemeGeometry(this);
-    nsDisplayItem::Destroy(aBuilder);
+    nsPaintedDisplayItem::Destroy(aBuilder);
   }
 
   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override;
   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                            bool* aSnap) const override;
   mozilla::Maybe<nscolor> IsUniform(
       nsDisplayListBuilder* aBuilder) const override;
@@ -4810,25 +4845,25 @@ class nsDisplayTableThemedBackground : p
   }
 
  protected:
   nsIFrame* StyleFrame() const override { return mAncestorFrame; }
   nsIFrame* mAncestorFrame;
   TableType mTableType;
 };
 
-class nsDisplayBackgroundColor : public nsDisplayItem {
+class nsDisplayBackgroundColor : public nsPaintedDisplayItem {
   typedef mozilla::gfx::Color Color;
 
  public:
   nsDisplayBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                            const nsRect& aBackgroundRect,
                            const mozilla::ComputedStyle* aBackgroundStyle,
                            const nscolor& aColor)
-      : nsDisplayItem(aBuilder, aFrame),
+      : nsPaintedDisplayItem(aBuilder, aFrame),
         mBackgroundRect(aBackgroundRect),
         mHasStyle(aBackgroundStyle),
         mDependentFrame(nullptr),
         mColor(Color::FromABGR(aColor)) {
     mState.mColor = mColor;
 
     if (mHasStyle) {
       mBottomLayerClip =
@@ -4842,17 +4877,17 @@ class nsDisplayBackgroundColor : public 
     if (mDependentFrame) {
       mDependentFrame->RemoveDisplayItem(this);
     }
   }
 
   NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR)
 
   void RestoreState() override {
-    nsDisplayItem::RestoreState();
+    nsPaintedDisplayItem::RestoreState();
     mColor = mState.mColor;
   }
 
   bool HasBackgroundClipText() const {
     MOZ_ASSERT(mHasStyle);
     return mBottomLayerClip == mozilla::StyleGeometryBox::Text;
   }
 
@@ -4929,17 +4964,18 @@ class nsDisplayBackgroundColor : public 
       mDependentFrame->AddDisplayItem(this);
     }
   }
 
   void RemoveFrame(nsIFrame* aFrame) override {
     if (aFrame == mDependentFrame) {
       mDependentFrame = nullptr;
     }
-    nsDisplayItem::RemoveFrame(aFrame);
+
+    nsPaintedDisplayItem::RemoveFrame(aFrame);
   }
 
   void WriteDebugInfo(std::stringstream& aStream) override;
 
   bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
 
  protected:
   const nsRect mBackgroundRect;
@@ -4994,20 +5030,20 @@ class nsDisplayTableBackgroundColor : pu
     return false;
   }
 
  protected:
   nsIFrame* mAncestorFrame;
   TableType mTableType;
 };
 
-class nsDisplayClearBackground : public nsDisplayItem {
+class nsDisplayClearBackground : public nsPaintedDisplayItem {
  public:
   nsDisplayClearBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {}
+      : nsPaintedDisplayItem(aBuilder, aFrame) {}
 
   NS_DISPLAY_DECL_NAME("ClearBackground", TYPE_CLEAR_BACKGROUND)
 
   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override {
     *aSnap = true;
     return nsRect(ToReferenceFrame(), Frame()->GetSize());
   }
 
@@ -5040,34 +5076,34 @@ class nsDisplayClearBackground : public 
       const StackingContextHelper& aSc,
       mozilla::layers::RenderRootStateManager* aManager,
       nsDisplayListBuilder* aDisplayListBuilder) override;
 };
 
 /**
  * The standard display item to paint the outer CSS box-shadows of a frame.
  */
-class nsDisplayBoxShadowOuter final : public nsDisplayItem {
+class nsDisplayBoxShadowOuter final : public nsPaintedDisplayItem {
  public:
   nsDisplayBoxShadowOuter(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame), mOpacity(1.0f) {
+      : nsPaintedDisplayItem(aBuilder, aFrame), mOpacity(1.0f) {
     MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter);
     mBounds = GetBoundsInternal();
   }
 
 #ifdef NS_BUILD_REFCNT_LOGGING
   ~nsDisplayBoxShadowOuter() override {
     MOZ_COUNT_DTOR(nsDisplayBoxShadowOuter);
   }
 #endif
 
   NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER)
 
   void RestoreState() override {
-    nsDisplayItem::RestoreState();
+    nsPaintedDisplayItem::RestoreState();
     mVisibleRegion.SetEmpty();
     mOpacity = 1.0f;
   }
 
   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
   bool IsInvisibleInRect(const nsRect& aRect) const override;
   bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
@@ -5103,33 +5139,33 @@ class nsDisplayBoxShadowOuter final : pu
   nsRegion mVisibleRegion;
   nsRect mBounds;
   float mOpacity;
 };
 
 /**
  * The standard display item to paint the inner CSS box-shadows of a frame.
  */
-class nsDisplayBoxShadowInner : public nsDisplayItem {
+class nsDisplayBoxShadowInner : public nsPaintedDisplayItem {
  public:
   nsDisplayBoxShadowInner(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayBoxShadowInner);
   }
 
 #ifdef NS_BUILD_REFCNT_LOGGING
   ~nsDisplayBoxShadowInner() override {
     MOZ_COUNT_DTOR(nsDisplayBoxShadowInner);
   }
 #endif
 
   NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER)
 
   void RestoreState() override {
-    nsDisplayItem::RestoreState();
+    nsPaintedDisplayItem::RestoreState();
     mVisibleRegion.SetEmpty();
   }
 
   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
   bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                          nsRegion* aVisibleRegion) override;
 
   nsDisplayItemGeometry* AllocateGeometry(
@@ -5166,20 +5202,20 @@ class nsDisplayBoxShadowInner : public n
 
  private:
   nsRegion mVisibleRegion;
 };
 
 /**
  * The standard display item to paint the CSS outline of a frame.
  */
-class nsDisplayOutline : public nsDisplayItem {
+class nsDisplayOutline : public nsPaintedDisplayItem {
  public:
   nsDisplayOutline(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayOutline);
   }
 
 #ifdef NS_BUILD_REFCNT_LOGGING
   ~nsDisplayOutline() override { MOZ_COUNT_DTOR(nsDisplayOutline); }
 #endif
 
   NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE)
@@ -5194,20 +5230,20 @@ class nsDisplayOutline : public nsDispla
   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
   void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
 };
 
 /**
  * A class that lets you receive events within the frame bounds but never
  * paints.
  */
-class nsDisplayEventReceiver : public nsDisplayItem {
+class nsDisplayEventReceiver : public nsPaintedDisplayItem {
  public:
   nsDisplayEventReceiver(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayEventReceiver);
   }
 
 #ifdef NS_BUILD_REFCNT_LOGGING
   ~nsDisplayEventReceiver() override { MOZ_COUNT_DTOR(nsDisplayEventReceiver); }
 #endif
 
   NS_DISPLAY_DECL_NAME("EventReceiver", TYPE_EVENT_RECEIVER)
@@ -5345,23 +5381,22 @@ class nsDisplayWrapList : public nsDispl
         mClearingClipChain(aOther.mClearingClipChain) {
     MOZ_COUNT_CTOR(nsDisplayWrapList);
   }
 
   ~nsDisplayWrapList() override;
 
   NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST)
 
-  const nsDisplayWrapList* AsDisplayWrapList() const override { return this; }
-
-  nsDisplayWrapList* AsDisplayWrapList() override { return this; }
+  const nsDisplayWrapList* AsDisplayWrapList() const final { return this; }
+  nsDisplayWrapList* AsDisplayWrapList() final { return this; }
 
   void Destroy(nsDisplayListBuilder* aBuilder) override {
     mList.DeleteAll(aBuilder);
-    nsDisplayItem::Destroy(aBuilder);
+    nsDisplayHitTestInfoItem::Destroy(aBuilder);
   }
 
   /**
    * Creates a new nsDisplayWrapList that holds a pointer to the display list
    * owned by the given nsDisplayItem. The new nsDisplayWrapList will be added
    * to the bottom of this item's contents.
    */
   void MergeDisplayListFromItem(nsDisplayListBuilder* aBuilder,
@@ -5396,17 +5431,17 @@ class nsDisplayWrapList : public nsDispl
     SetBuildingRect(buildingRect);
   }
 
   void SetActiveScrolledRoot(
       const ActiveScrolledRoot* aActiveScrolledRoot) override {
     // Skip unnecessary call to
     // |nsDisplayHitTestInfoItem::UpdateHitTestInfoActiveScrolledRoot()|, since
     // callers will manually call that with different ASR.
-    nsDisplayItem::SetActiveScrolledRoot(aActiveScrolledRoot);
+    nsDisplayHitTestInfoItem::SetActiveScrolledRoot(aActiveScrolledRoot);
   }
 
   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override;
   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                            bool* aSnap) const override;
   mozilla::Maybe<nscolor> IsUniform(
@@ -5460,17 +5495,18 @@ class nsDisplayWrapList : public nsDispl
             mListPtr->GetBottom()->ReferenceFrame() == ReferenceFrame(),
         "Children must have same reference frame");
     return mListPtr;
   }
 
   RetainedDisplayList* GetChildren() const override { return mListPtr; }
 
   int32_t ZIndex() const override {
-    return (mHasZIndexOverride) ? mOverrideZIndex : nsDisplayItem::ZIndex();
+    return (mHasZIndexOverride) ? mOverrideZIndex
+                                : nsDisplayHitTestInfoItem::ZIndex();
   }
 
   void SetOverrideZIndex(int32_t aZIndex) {
     mHasZIndexOverride = true;
     mOverrideZIndex = aZIndex;
   }
 
   void SetReferenceFrame(const nsIFrame* aFrame);
@@ -5581,17 +5617,17 @@ class nsDisplayOpacity : public nsDispla
 
 #ifdef NS_BUILD_REFCNT_LOGGING
   ~nsDisplayOpacity() override { MOZ_COUNT_DTOR(nsDisplayOpacity); }
 #endif
 
   NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY)
 
   void RestoreState() override {
-    nsDisplayItem::RestoreState();
+    nsDisplayWrapList::RestoreState();
     mOpacity = mState.mOpacity;
   }
 
   void InvalidateCachedChildInfo(nsDisplayListBuilder* aBuilder) override {
     mChildOpacityState = ChildOpacityState::Unknown;
   }
 
   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
@@ -6485,17 +6521,20 @@ class nsDisplayEffectsBase : public nsDi
   ~nsDisplayEffectsBase() override { MOZ_COUNT_DTOR(nsDisplayEffectsBase); }
 #endif
 
   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                            bool* aSnap) const override;
   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) override;
 
-  void RestoreState() override { mHandleOpacity = false; }
+  void RestoreState() override {
+    nsDisplayWrapList::RestoreState();
+    mHandleOpacity = false;
+  }
 
   bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
     return false;
   }
 
   void SetHandleOpacity() { mHandleOpacity = true; }
   bool ShouldHandleOpacity() const { return mHandleOpacity; }
 
@@ -6754,31 +6793,34 @@ class nsDisplayTransform : public nsDisp
                      ComputeTransformFunction aTransformGetter);
 
 #ifdef NS_BUILD_REFCNT_LOGGING
   ~nsDisplayTransform() override { MOZ_COUNT_DTOR(nsDisplayTransform); }
 #endif
 
   NS_DISPLAY_DECL_NAME("nsDisplayTransform", TYPE_TRANSFORM)
 
-  void RestoreState() override { mShouldFlatten = false; }
+  void RestoreState() override {
+    nsDisplayHitTestInfoItem::RestoreState();
+    mShouldFlatten = false;
+  }
 
   void UpdateBounds(nsDisplayListBuilder* aBuilder) override;
 
   /**
    * This function updates bounds for items with a frame establishing
    * 3D rendering context.
    */
   void UpdateBoundsFor3D(nsDisplayListBuilder* aBuilder);
 
   void DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) override;
 
   void Destroy(nsDisplayListBuilder* aBuilder) override {
     GetChildren()->DeleteAll(aBuilder);
-    nsDisplayItem::Destroy(aBuilder);
+    nsDisplayHitTestInfoItem::Destroy(aBuilder);
   }
 
   nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const override;
 
   RetainedDisplayList* GetChildren() const override { return &mChildren; }
 
   nsRect GetUntransformedBounds(nsDisplayListBuilder* aBuilder,
                                 bool* aSnap) const override {
@@ -6845,17 +6887,17 @@ class nsDisplayTransform : public nsDisp
 
   const nsIFrame* ReferenceFrameForChildren() const override {
     // If we were created using a transform-getter, then we don't
     // belong to a transformed frame, and aren't a reference frame
     // for our children.
     if (!mTransformGetter) {
       return mFrame;
     }
-    return nsDisplayItem::ReferenceFrameForChildren();
+    return nsDisplayHitTestInfoItem::ReferenceFrameForChildren();
   }
 
   AnimatedGeometryRoot* AnimatedGeometryRootForScrollMetadata() const override {
     return mAnimatedGeometryRootForScrollMetadata;
   }
 
   const nsRect& GetBuildingRectForChildren() const override {
     return mChildrenBuildingRect;
@@ -7164,31 +7206,30 @@ class nsDisplayPerspective : public nsDi
  * The two members, mVisIStartEdge and mVisIEndEdge, are relative to the edges
  * of the frame's scrollable overflow rectangle and are the amount to suppress
  * on each side.
  *
  * Setting none, both or only one edge is allowed.
  * The values must be non-negative.
  * The default value for both edges is zero, which means everything is painted.
  */
-class nsDisplayText final : public nsDisplayItem {
+class nsDisplayText final : public nsPaintedDisplayItem {
  public:
   nsDisplayText(nsDisplayListBuilder* aBuilder, nsTextFrame* aFrame,
                 const mozilla::Maybe<bool>& aIsSelected);
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayText() { MOZ_COUNT_DTOR(nsDisplayText); }
 #endif
 
   NS_DISPLAY_DECL_NAME("Text", TYPE_TEXT)
 
   void RestoreState() final {
+    nsPaintedDisplayItem::RestoreState();
     mIsFrameSelected.reset();
     mOpacity = 1.0f;
-
-    nsDisplayItem::RestoreState();
   }
 
   nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const final {
     *aSnap = false;
     return mBounds;
   }
 
   void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
--- a/layout/svg/SVGGeometryFrame.cpp
+++ b/layout/svg/SVGGeometryFrame.cpp
@@ -51,22 +51,22 @@ NS_IMPL_FRAMEARENA_HELPERS(SVGGeometryFr
 NS_QUERYFRAME_HEAD(SVGGeometryFrame)
   NS_QUERYFRAME_ENTRY(nsSVGDisplayableFrame)
   NS_QUERYFRAME_ENTRY(SVGGeometryFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsFrame)
 
 //----------------------------------------------------------------------
 // Display list item:
 
-class nsDisplaySVGGeometry final : public nsDisplayItem {
+class nsDisplaySVGGeometry final : public nsPaintedDisplayItem {
   typedef mozilla::image::imgDrawingParams imgDrawingParams;
 
  public:
   nsDisplaySVGGeometry(nsDisplayListBuilder* aBuilder, SVGGeometryFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplaySVGGeometry);
     MOZ_ASSERT(aFrame, "Must have a frame!");
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplaySVGGeometry() { MOZ_COUNT_DTOR(nsDisplaySVGGeometry); }
 #endif
 
   NS_DISPLAY_DECL_NAME("nsDisplaySVGGeometry", TYPE_SVG_GEOMETRY)
@@ -129,17 +129,18 @@ void nsDisplaySVGGeometry::ComputeInvali
       static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
 
   if (aBuilder->ShouldSyncDecodeImages() &&
       geometry->ShouldInvalidateToSyncDecodeImages()) {
     bool snap;
     aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
   }
 
-  nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
+  nsPaintedDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry,
+                                                  aInvalidRegion);
 }
 
 namespace mozilla {
 
 //----------------------------------------------------------------------
 // nsIFrame methods
 
 void SVGGeometryFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -2802,20 +2802,20 @@ void SVGTextDrawPathCallbacks::StrokeGeo
 }  // namespace mozilla
 
 // ============================================================================
 // SVGTextFrame
 
 // ----------------------------------------------------------------------------
 // Display list item
 
-class nsDisplaySVGText final : public nsDisplayItem {
+class nsDisplaySVGText final : public nsPaintedDisplayItem {
  public:
   nsDisplaySVGText(nsDisplayListBuilder* aBuilder, SVGTextFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplaySVGText);
     MOZ_ASSERT(aFrame, "Must have a frame!");
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplaySVGText() { MOZ_COUNT_DTOR(nsDisplaySVGText); }
 #endif
 
   NS_DISPLAY_DECL_NAME("nsDisplaySVGText", TYPE_SVG_TEXT)
--- a/layout/svg/nsSVGOuterSVGFrame.cpp
+++ b/layout/svg/nsSVGOuterSVGFrame.cpp
@@ -522,20 +522,20 @@ void nsSVGOuterSVGFrame::UnionChildOverf
 }
 
 //----------------------------------------------------------------------
 // container methods
 
 /**
  * Used to paint/hit-test SVG when SVG display lists are disabled.
  */
-class nsDisplayOuterSVG final : public nsDisplayItem {
+class nsDisplayOuterSVG final : public nsPaintedDisplayItem {
  public:
   nsDisplayOuterSVG(nsDisplayListBuilder* aBuilder, nsSVGOuterSVGFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayOuterSVG);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayOuterSVG() { MOZ_COUNT_DTOR(nsDisplayOuterSVG); }
 #endif
 
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                        HitTestState* aState,
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -33,20 +33,20 @@
 // TABLECELL SELECTION
 #include "nsFrameSelection.h"
 #include "mozilla/LookAndFeel.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::image;
 
-class nsDisplayTableCellSelection final : public nsDisplayItem {
+class nsDisplayTableCellSelection final : public nsPaintedDisplayItem {
  public:
   nsDisplayTableCellSelection(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayTableCellSelection);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayTableCellSelection() {
     MOZ_COUNT_DTOR(nsDisplayTableCellSelection);
   }
 #endif
 
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -37,21 +37,21 @@ class StackingContextHelper;
 
 struct BCPropertyData;
 
 static inline bool IsTableCell(mozilla::LayoutFrameType frameType) {
   return frameType == mozilla::LayoutFrameType::TableCell ||
          frameType == mozilla::LayoutFrameType::BCTableCell;
 }
 
-class nsDisplayTableItem : public nsDisplayItem {
+class nsDisplayTableItem : public nsPaintedDisplayItem {
  public:
   nsDisplayTableItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                      bool aDrawsBackground = true)
-      : nsDisplayItem(aBuilder, aFrame),
+      : nsPaintedDisplayItem(aBuilder, aFrame),
         mPartHasFixedBackground(false),
         mDrawsBackground(aDrawsBackground) {}
 
   // With collapsed borders, parts of the collapsed border can extend outside
   // the table part frames, so allow this display element to blow out to our
   // overflow rect. This is also useful for row frames that have spanning
   // cells extending outside them.
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
--- a/layout/xul/nsGroupBoxFrame.cpp
+++ b/layout/xul/nsGroupBoxFrame.cpp
@@ -88,21 +88,21 @@ public:
 */
 
 nsIFrame* NS_NewGroupBoxFrame(PresShell* aPresShell, ComputedStyle* aStyle) {
   return new (aPresShell) nsGroupBoxFrame(aStyle, aPresShell->GetPresContext());
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsGroupBoxFrame)
 
-class nsDisplayXULGroupBorder final : public nsDisplayItem {
+class nsDisplayXULGroupBorder final : public nsPaintedDisplayItem {
  public:
   nsDisplayXULGroupBorder(nsDisplayListBuilder* aBuilder,
                           nsGroupBoxFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayXULGroupBorder);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayXULGroupBorder() {
     MOZ_COUNT_DTOR(nsDisplayXULGroupBorder);
   }
 #endif
 
--- a/layout/xul/nsTextBoxFrame.cpp
+++ b/layout/xul/nsTextBoxFrame.cpp
@@ -235,20 +235,20 @@ void nsTextBoxFrame::UpdateAttributes(ns
   }
 
   if (doUpdateTitle) {
     UpdateAccessTitle();
     aResize = true;
   }
 }
 
-class nsDisplayXULTextBox final : public nsDisplayItem {
+class nsDisplayXULTextBox final : public nsPaintedDisplayItem {
  public:
   nsDisplayXULTextBox(nsDisplayListBuilder* aBuilder, nsTextBoxFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayXULTextBox);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayXULTextBox() { MOZ_COUNT_DTOR(nsDisplayXULTextBox); }
 #endif
 
   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -2458,50 +2458,50 @@ nsresult nsTreeBodyFrame::HandleEvent(ns
                   nsITimer::TYPE_ONE_SHOT, getter_AddRefs(mSlots->mTimer),
                   "nsTreeBodyFrame::CloseCallback");
     }
   }
 
   return NS_OK;
 }
 
-class nsDisplayTreeBody final : public nsDisplayItem {
+class nsDisplayTreeBody final : public nsPaintedDisplayItem {
  public:
   nsDisplayTreeBody(nsDisplayListBuilder* aBuilder, nsFrame* aFrame)
-      : nsDisplayItem(aBuilder, aFrame) {
+      : nsPaintedDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayTreeBody);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayTreeBody() { MOZ_COUNT_DTOR(nsDisplayTreeBody); }
 #endif
 
   nsDisplayItemGeometry* AllocateGeometry(
       nsDisplayListBuilder* aBuilder) override {
     return new nsDisplayItemGenericImageGeometry(this, aBuilder);
   }
 
   void Destroy(nsDisplayListBuilder* aBuilder) override {
     aBuilder->UnregisterThemeGeometry(this);
-    nsDisplayItem::Destroy(aBuilder);
+    nsPaintedDisplayItem::Destroy(aBuilder);
   }
 
   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                  const nsDisplayItemGeometry* aGeometry,
                                  nsRegion* aInvalidRegion) const override {
     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);
+    nsPaintedDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry,
+                                                    aInvalidRegion);
   }
 
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      gfxContext* aCtx) override {
     MOZ_ASSERT(aBuilder);
     DrawTargetAutoDisableSubpixelAntialiasing disable(aCtx->GetDrawTarget(),
                                                       IsSubpixelAADisabled());