Commit 03b9326d authored by Jeff Muizelaar's avatar Jeff Muizelaar
Browse files

Bug 1727814 - Drop mVisibleRegion from box shadow items. r=miko

mVisibleRegion was added in bug 530686 as an optimization for when the invalid
region was vertically discontiguous. WebRender doesn't call ComputeVisibility
and so never had an updated mVisibleRegion and so never used it during drawing.

WebRender fallback drawing has limited invalidation support and currently only
passes a rect to ComputeVisibility so it also wasn't taking advantage of this
optimization. This is also true of nsDisplayList::Paint.

In summary, we're not currently using this optimization and supporting it bloats
the display items. If we were to reintroduce it, I think it would make more sense
for the paint region to show up in the Paint function and not be stored in the
display item.

Differential Revision: https://phabricator.services.mozilla.com/D123791
parent 3d876bf1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -386,7 +386,7 @@ bool nsDisplayButtonBorder::CreateWebRenderCommands(
  aBuilder.StartGroup(this);
  const nsRect buttonRect = nsRect(ToReferenceFrame(), mFrame->GetSize());
  bool snap;
  nsRegion visible = GetBounds(aDisplayListBuilder, &snap);
  nsRect visible = GetBounds(aDisplayListBuilder, &snap);
  nsDisplayBoxShadowInner::CreateInsetBoxShadowWebRenderCommands(
      aBuilder, aSc, visible, mFrame, buttonRect);

+84 −159
Original line number Diff line number Diff line
@@ -4852,51 +4852,16 @@ nsRect nsDisplayBorder::GetBounds(nsDisplayListBuilder* aBuilder,
  return mBounds;
}

// Given a region, compute a conservative approximation to it as a list
// of rectangles that aren't vertically adjacent (i.e., vertically
// adjacent or overlapping rectangles are combined).
// Right now this is only approximate, some vertically overlapping rectangles
// aren't guaranteed to be combined.
static void ComputeDisjointRectangles(const nsRegion& aRegion,
                                      nsTArray<nsRect>* aRects) {
  nscoord accumulationMargin = nsPresContext::CSSPixelsToAppUnits(25);
  nsRect accumulated;

  for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
    const nsRect& r = iter.Get();
    if (accumulated.IsEmpty()) {
      accumulated = r;
      continue;
    }

    if (accumulated.YMost() >= r.y - accumulationMargin) {
      accumulated.UnionRect(accumulated, r);
    } else {
      aRects->AppendElement(accumulated);
      accumulated = r;
    }
  }

  // Finish the in-flight rectangle, if there is one.
  if (!accumulated.IsEmpty()) {
    aRects->AppendElement(accumulated);
  }
}

void nsDisplayBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
                                    gfxContext* aCtx) {
  nsPoint offset = ToReferenceFrame();
  nsRect borderRect = mFrame->VisualBorderRectRelativeToSelf() + offset;
  nsPresContext* presContext = mFrame->PresContext();
  AutoTArray<nsRect, 10> rects;
  ComputeDisjointRectangles(mVisibleRegion, &rects);

  AUTO_PROFILER_LABEL("nsDisplayBoxShadowOuter::Paint", GRAPHICS);

  for (uint32_t i = 0; i < rects.Length(); ++i) {
  nsCSSRendering::PaintBoxShadowOuter(presContext, *aCtx, mFrame, borderRect,
                                        rects[i], mOpacity);
  }
                                      GetPaintRect(), mOpacity);
}

nsRect nsDisplayBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder,
@@ -4928,16 +4893,6 @@ bool nsDisplayBoxShadowOuter::IsInvisibleInRect(const nsRect& aRect) const {
  return RoundedRectContainsRect(frameRect, twipsRadii, aRect);
}

bool nsDisplayBoxShadowOuter::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                                nsRegion* aVisibleRegion) {
  if (!nsPaintedDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion)) {
    return false;
  }

  mVisibleRegion.And(*aVisibleRegion, GetPaintRect());
  return true;
}

bool nsDisplayBoxShadowOuter::CanBuildWebRenderDisplayItems() {
  auto shadows = mFrame->StyleEffects()->mBoxShadow.AsSpan();
  if (shadows.IsEmpty()) {
@@ -4965,10 +4920,8 @@ bool nsDisplayBoxShadowOuter::CreateWebRenderCommands(
  int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
  nsPoint offset = ToReferenceFrame();
  nsRect borderRect = mFrame->VisualBorderRectRelativeToSelf() + offset;
  AutoTArray<nsRect, 10> rects;
  bool snap;
  nsRect bounds = GetBounds(aDisplayListBuilder, &snap);
  ComputeDisjointRectangles(bounds, &rects);

  bool hasBorderRadius;
  bool nativeTheme =
@@ -4987,9 +4940,8 @@ bool nsDisplayBoxShadowOuter::CreateWebRenderCommands(
  }

  // Everything here is in app units, change to device units.
  for (uint32_t i = 0; i < rects.Length(); ++i) {
  LayoutDeviceRect clipRect =
        LayoutDeviceRect::FromAppUnits(rects[i], appUnitsPerDevPixel);
      LayoutDeviceRect::FromAppUnits(bounds, appUnitsPerDevPixel);
  auto shadows = mFrame->StyleEffects()->mBoxShadow.AsSpan();
  MOZ_ASSERT(!shadows.IsEmpty());

@@ -5036,7 +4988,6 @@ bool nsDisplayBoxShadowOuter::CreateWebRenderCommands(
                           blurRadius, spreadRadius, borderRadius,
                           wr::BoxShadowClipMode::Outset);
  }
  }

  return true;
}
@@ -5071,21 +5022,10 @@ void nsDisplayBoxShadowInner::Paint(nsDisplayListBuilder* aBuilder,
  nsPoint offset = ToReferenceFrame();
  nsRect borderRect = nsRect(offset, mFrame->GetSize());
  nsPresContext* presContext = mFrame->PresContext();
  AutoTArray<nsRect, 10> rects;
  ComputeDisjointRectangles(mVisibleRegion, &rects);

  AUTO_PROFILER_LABEL("nsDisplayBoxShadowInner::Paint", GRAPHICS);

  DrawTarget* drawTarget = aCtx->GetDrawTarget();
  gfxContext* gfx = aCtx;
  int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();

  for (uint32_t i = 0; i < rects.Length(); ++i) {
    gfx->Save();
    gfx->Clip(NSRectToSnappedRect(rects[i], appUnitsPerDevPixel, *drawTarget));
  nsCSSRendering::PaintBoxShadowInner(presContext, *aCtx, mFrame, borderRect);
    gfx->Restore();
  }
}

bool nsDisplayBoxShadowInner::CanCreateWebRenderCommands(
@@ -5109,21 +5049,17 @@ bool nsDisplayBoxShadowInner::CanCreateWebRenderCommands(
/* static */
void nsDisplayBoxShadowInner::CreateInsetBoxShadowWebRenderCommands(
    wr::DisplayListBuilder& aBuilder, const StackingContextHelper& aSc,
    nsRegion& aVisibleRegion, nsIFrame* aFrame, const nsRect& aBorderRect) {
    nsRect& aVisibleRect, nsIFrame* aFrame, const nsRect& aBorderRect) {
  if (!nsCSSRendering::ShouldPaintBoxShadowInner(aFrame)) {
    return;
  }

  int32_t appUnitsPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel();

  AutoTArray<nsRect, 10> rects;
  ComputeDisjointRectangles(aVisibleRegion, &rects);

  auto shadows = aFrame->StyleEffects()->mBoxShadow.AsSpan();

  for (uint32_t i = 0; i < rects.Length(); ++i) {
  LayoutDeviceRect clipRect =
        LayoutDeviceRect::FromAppUnits(rects[i], appUnitsPerDevPixel);
      LayoutDeviceRect::FromAppUnits(aVisibleRect, appUnitsPerDevPixel);

  for (const auto& shadow : Reversed(shadows)) {
    if (!shadow.inset) {
@@ -5167,7 +5103,6 @@ void nsDisplayBoxShadowInner::CreateInsetBoxShadowWebRenderCommands(
        borderRadius, wr::BoxShadowClipMode::Inset);
  }
}
}

bool nsDisplayBoxShadowInner::CreateWebRenderCommands(
    wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
@@ -5179,7 +5114,7 @@ bool nsDisplayBoxShadowInner::CreateWebRenderCommands(
  }

  bool snap;
  nsRegion visible = GetBounds(aDisplayListBuilder, &snap);
  nsRect visible = GetBounds(aDisplayListBuilder, &snap);
  nsPoint offset = ToReferenceFrame();
  nsRect borderRect = nsRect(offset, mFrame->GetSize());
  nsDisplayBoxShadowInner::CreateInsetBoxShadowWebRenderCommands(
@@ -5188,16 +5123,6 @@ bool nsDisplayBoxShadowInner::CreateWebRenderCommands(
  return true;
}

bool nsDisplayBoxShadowInner::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                                nsRegion* aVisibleRegion) {
  if (!nsPaintedDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion)) {
    return false;
  }

  mVisibleRegion.And(*aVisibleRegion, GetPaintRect());
  return true;
}

nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
                                     nsIFrame* aFrame, nsDisplayList* aList)
    : nsDisplayWrapList(aBuilder, aFrame, aList,
+2 −20
Original line number Diff line number Diff line
@@ -4855,12 +4855,10 @@ class nsDisplayBoxShadowOuter final : public nsPaintedDisplayItem {
  NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER)

  bool RestoreState() override {
    if (!nsPaintedDisplayItem::RestoreState() && mOpacity == 1.0f &&
        mVisibleRegion.IsEmpty()) {
    if (!nsPaintedDisplayItem::RestoreState() && mOpacity == 1.0f) {
      return false;
    }

    mVisibleRegion.SetEmpty();
    mOpacity = 1.0f;
    return true;
  }
@@ -4868,8 +4866,6 @@ class nsDisplayBoxShadowOuter final : public nsPaintedDisplayItem {
  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,
                         nsRegion* aVisibleRegion) override;
  void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                 const nsDisplayItemGeometry* aGeometry,
                                 nsRegion* aInvalidRegion) const override;
@@ -4897,7 +4893,6 @@ class nsDisplayBoxShadowOuter final : public nsPaintedDisplayItem {
  nsRect GetBoundsInternal();

 private:
  nsRegion mVisibleRegion;
  nsRect mBounds;
  float mOpacity;
};
@@ -4916,18 +4911,7 @@ class nsDisplayBoxShadowInner : public nsPaintedDisplayItem {

  NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER)

  bool RestoreState() override {
    if (!nsPaintedDisplayItem::RestoreState() && mVisibleRegion.IsEmpty()) {
      return false;
    }

    mVisibleRegion.SetEmpty();
    return true;
  }

  void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
  bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                         nsRegion* aVisibleRegion) override;

  nsDisplayItemGeometry* AllocateGeometry(
      nsDisplayListBuilder* aBuilder) override {
@@ -4952,15 +4936,13 @@ class nsDisplayBoxShadowInner : public nsPaintedDisplayItem {
                                         const nsPoint& aReferenceOffset);
  static void CreateInsetBoxShadowWebRenderCommands(
      wr::DisplayListBuilder& aBuilder, const StackingContextHelper& aSc,
      nsRegion& aVisibleRegion, nsIFrame* aFrame, const nsRect& aBorderRect);
      nsRect& aVisibleRect, nsIFrame* aFrame, const nsRect& aBorderRect);
  bool CreateWebRenderCommands(
      wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
      const StackingContextHelper& aSc,
      layers::RenderRootStateManager* aManager,
      nsDisplayListBuilder* aDisplayListBuilder) override;

 private:
  nsRegion mVisibleRegion;
};

/**