Title: [295665] trunk
Revision
295665
Author
za...@apple.com
Date
2022-06-19 20:57:23 -0700 (Sun, 19 Jun 2022)

Log Message

REGRESSION (r294902): Content with continuation leaves decoration bits behind when removed
https://bugs.webkit.org/show_bug.cgi?id=241734
<rdar://95308322>

Reviewed by Simon Fraser.

This patch ensures that when a renderer is removed we always issue a repaint regardless of what the associated layer's repaint bit says.

1. after r294902, repaint is not issued anymore if either the associated or an ancestor layer have the "full repaint" bit set.
2. such layer-driven repaints happen after layout.

In some dynamic content cases, the layer may be removed before layout happens. This patch ensures that we preemptively issue such repaints.

* LayoutTests/fast/repaint/force-repaint-when-layer-is-destroyed-expected.txt: Added.
* LayoutTests/fast/repaint/force-repaint-when-layer-is-destroyed.html: Added.

* Source/WebCore/rendering/RenderLayerModelObject.cpp: Force (full) repaint when the renderer is being destroyed (detached -> non-internal move).
(WebCore::RenderLayerModelObject::willBeRemovedFromTree):
* Source/WebCore/rendering/RenderLayerModelObject.h:
* Source/WebCore/rendering/RenderObject.cpp: move duplicated code from repaint() and repaintRectangle() to issueRepaint().

Canonical link: https://commits.webkit.org/251670@main

Modified Paths

Added Paths

Diff

Added: trunk/LayoutTests/fast/repaint/force-repaint-when-layer-is-destroyed-expected.txt (0 => 295665)


--- trunk/LayoutTests/fast/repaint/force-repaint-when-layer-is-destroyed-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/repaint/force-repaint-when-layer-is-destroyed-expected.txt	2022-06-20 03:57:23 UTC (rev 295665)
@@ -0,0 +1 @@
+PASS

Added: trunk/LayoutTests/fast/repaint/force-repaint-when-layer-is-destroyed.html (0 => 295665)


--- trunk/LayoutTests/fast/repaint/force-repaint-when-layer-is-destroyed.html	                        (rev 0)
+++ trunk/LayoutTests/fast/repaint/force-repaint-when-layer-is-destroyed.html	2022-06-20 03:57:23 UTC (rev 295665)
@@ -0,0 +1,36 @@
+<style>
+.content {
+  transform: translateX(0px);
+  border: 10px solid red;
+  width: 120px;
+}
+
+.continuation {
+  width: 100px;
+  height: 100px;
+  background-color: green;
+  border: solid blue;
+}
+</style><div id=hide_this class=content><span><div class=continuation></div></span></div>
+<pre id=result></pre>
+<script>
+if (window.testRunner) {
+  testRunner.dumpAsText();
+  testRunner.waitUntilDone();
+}
+
+setTimeout(function() {
+  if (window.internals)
+    internals.startTrackingRepaints();
+
+  hide_this.style.display = "none";
+
+  if (window.internals) {
+    result.innerText = internals.repaintRectsAsText().indexOf("8 8 140 126") != -1 ? "PASS" : "FAIL";
+    internals.stopTrackingRepaints();
+  }
+
+  if (window.testRunner)
+    testRunner.notifyDone();
+}, 10);
+</script>
\ No newline at end of file

Modified: trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp (295664 => 295665)


--- trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp	2022-06-20 03:28:45 UTC (rev 295664)
+++ trunk/Source/WebCore/rendering/RenderLayerModelObject.cpp	2022-06-20 03:57:23 UTC (rev 295665)
@@ -77,6 +77,14 @@
     RenderElement::willBeDestroyed();
 }
 
+void RenderLayerModelObject::willBeRemovedFromTree(IsInternalMove isInternalMove)
+{
+    if (auto* layer = this->layer(); layer && layer->needsFullRepaint() && isInternalMove == IsInternalMove::No)
+        issueRepaint(std::nullopt, ClipRepaintToLayer::No, ForceRepaint::Yes);
+
+    RenderElement::willBeRemovedFromTree(isInternalMove);
+}
+
 void RenderLayerModelObject::destroyLayer()
 {
     ASSERT(!hasLayer());

Modified: trunk/Source/WebCore/rendering/RenderLayerModelObject.h (295664 => 295665)


--- trunk/Source/WebCore/rendering/RenderLayerModelObject.h	2022-06-20 03:28:45 UTC (rev 295664)
+++ trunk/Source/WebCore/rendering/RenderLayerModelObject.h	2022-06-20 03:57:23 UTC (rev 295665)
@@ -95,6 +95,7 @@
 
     void createLayer();
     void willBeDestroyed() override;
+    void willBeRemovedFromTree(IsInternalMove) override;
 
 private:
     std::unique_ptr<RenderLayer> m_layer;

Modified: trunk/Source/WebCore/rendering/RenderObject.cpp (295664 => 295665)


--- trunk/Source/WebCore/rendering/RenderObject.cpp	2022-06-20 03:28:45 UTC (rev 295664)
+++ trunk/Source/WebCore/rendering/RenderObject.cpp	2022-06-20 03:57:23 UTC (rev 295665)
@@ -977,45 +977,37 @@
     return false;
 }
 
-void RenderObject::repaint() const
+void RenderObject::issueRepaint(std::optional<LayoutRect> partialRepaintRect, ClipRepaintToLayer clipRepaintToLayer, ForceRepaint forceRepaint) const
 {
-    // Don't repaint if we're unrooted (note that view() still returns the view when unrooted)
-    if (!isRooted())
-        return;
+    auto repaintContainer = containerForRepaint();
+    if (!repaintContainer.renderer)
+        repaintContainer = { fullRepaintIsScheduled(*this), &view() };
 
-    const RenderView& view = this->view();
-    if (view.printing())
+    if (repaintContainer.fullRepaintIsScheduled && forceRepaint == ForceRepaint::No)
         return;
 
-    auto repaintContainer = containerForRepaint();
-    if (!repaintContainer.renderer)
-        repaintContainer = { fullRepaintIsScheduled(*this), &view };
-
-    if (!repaintContainer.fullRepaintIsScheduled)
-        repaintUsingContainer(repaintContainer.renderer, clippedOverflowRectForRepaint(repaintContainer.renderer));
+    auto repaintRect = partialRepaintRect ? computeRectForRepaint(*partialRepaintRect, repaintContainer.renderer) : clippedOverflowRectForRepaint(repaintContainer.renderer);
+    repaintUsingContainer(repaintContainer.renderer, repaintRect, clipRepaintToLayer == ClipRepaintToLayer::Yes);
 }
 
-void RenderObject::repaintRectangle(const LayoutRect& r, bool shouldClipToLayer) const
+void RenderObject::repaint() const
 {
     // Don't repaint if we're unrooted (note that view() still returns the view when unrooted)
-    if (!isRooted())
+    if (!isRooted() || view().printing())
         return;
+    issueRepaint();
+}
 
-    const RenderView& view = this->view();
-    if (view.printing())
+void RenderObject::repaintRectangle(const LayoutRect& repaintRect, bool shouldClipToLayer) const
+{
+    // Don't repaint if we're unrooted (note that view() still returns the view when unrooted)
+    if (!isRooted() || view().printing())
         return;
-
-    LayoutRect dirtyRect(r);
     // FIXME: layoutDelta needs to be applied in parts before/after transforms and
     // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
-    dirtyRect.move(view.frameView().layoutContext().layoutDelta());
-
-    auto repaintContainer = containerForRepaint();
-    if (!repaintContainer.renderer)
-        repaintContainer = { fullRepaintIsScheduled(*this), &view };
-
-    if (!repaintContainer.fullRepaintIsScheduled)
-        repaintUsingContainer(repaintContainer.renderer, computeRectForRepaint(dirtyRect, repaintContainer.renderer), shouldClipToLayer);
+    auto dirtyRect = repaintRect;
+    dirtyRect.move(view().frameView().layoutContext().layoutDelta());
+    issueRepaint(dirtyRect, shouldClipToLayer ? ClipRepaintToLayer::Yes : ClipRepaintToLayer::No);
 }
 
 void RenderObject::repaintSlowRepaintObject() const

Modified: trunk/Source/WebCore/rendering/RenderObject.h (295664 => 295665)


--- trunk/Source/WebCore/rendering/RenderObject.h	2022-06-20 03:28:45 UTC (rev 295664)
+++ trunk/Source/WebCore/rendering/RenderObject.h	2022-06-20 03:57:23 UTC (rev 295665)
@@ -803,6 +803,10 @@
 
     bool isSetNeedsLayoutForbidden() const;
 
+    enum class ClipRepaintToLayer : uint8_t { No, Yes };
+    enum class ForceRepaint : uint8_t { No, Yes };
+    void issueRepaint(std::optional<LayoutRect> partialRepaintRect = std::nullopt, ClipRepaintToLayer = ClipRepaintToLayer::No, ForceRepaint = ForceRepaint::No) const;
+
 private:
     void addAbsoluteRectForLayer(LayoutRect& result);
     void setLayerNeedsFullRepaint();
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to