Commit 89621a5d authored by Vladimir Levin's avatar Vladimir Levin Committed by Commit Bot

content-visibility: Early out in PaintLayerCompositor if locked.

This patch ensures that we don't try and update assignments if
the layout view is locked in its parent frame.

If the view is locked, it means that we skipped processing prepaint
for it, which means that the contents here might not have the
LocalBorderBoxProperties (created during prepaint). However, the
assignment needs the properties to do its work.

Since the frame walk here is unconditional, there is no need to
keep track of the dirty bit flags, as long as we don't clear the
flags on the compositor itself. This is similar to how the throttling
logic behaves.

R=chrishtr@chromium.org

Bug: 1128790
Change-Id: Ic325b618161c68d5886d0a5c0926cbd29e81d38e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2422265
Commit-Queue: vmpstr <vmpstr@chromium.org>
Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#809314}
parent c3bf11fd
...@@ -597,4 +597,18 @@ bool DisplayLockUtilities::UpdateStyleAndLayoutForRangeIfNeeded( ...@@ -597,4 +597,18 @@ bool DisplayLockUtilities::UpdateStyleAndLayoutForRangeIfNeeded(
return !forced_context_list_.IsEmpty(); return !forced_context_list_.IsEmpty();
} }
bool DisplayLockUtilities::PrePaintBlockedInParentFrame(LayoutView* view) {
auto* owner = view->GetFrameView()->GetFrame().OwnerLayoutObject();
if (!owner)
return false;
auto* element = NearestLockedInclusiveAncestor(*owner);
while (element) {
if (!element->GetDisplayLockContext()->ShouldPrePaintChildren())
return true;
element = NearestLockedExclusiveAncestor(*element);
}
return false;
}
} // namespace blink } // namespace blink
...@@ -172,6 +172,8 @@ class CORE_EXPORT DisplayLockUtilities { ...@@ -172,6 +172,8 @@ class CORE_EXPORT DisplayLockUtilities {
const EphemeralRangeInFlatTree& new_selection); const EphemeralRangeInFlatTree& new_selection);
static void SelectionRemovedFromDocument(Document& document); static void SelectionRemovedFromDocument(Document& document);
static bool PrePaintBlockedInParentFrame(LayoutView* layout_view);
private: private:
static bool UpdateStyleAndLayoutForRangeIfNeeded( static bool UpdateStyleAndLayoutForRangeIfNeeded(
const EphemeralRangeInFlatTree& range, const EphemeralRangeInFlatTree& range,
......
...@@ -571,16 +571,17 @@ void Write(WTF::TextStream& ts, ...@@ -571,16 +571,17 @@ void Write(WTF::TextStream& ts,
continue; continue;
Write(ts, *child, indent + 1, behavior); Write(ts, *child, indent + 1, behavior);
} }
}
if (o.IsLayoutEmbeddedContent()) { if (o.IsLayoutEmbeddedContent()) {
FrameView* frame_view = ToLayoutEmbeddedContent(o).ChildFrameView(); FrameView* frame_view = ToLayoutEmbeddedContent(o).ChildFrameView();
if (auto* local_frame_view = DynamicTo<LocalFrameView>(frame_view)) { if (auto* local_frame_view = DynamicTo<LocalFrameView>(frame_view)) {
if (auto* layout_view = local_frame_view->GetLayoutView()) { if (auto* layout_view = local_frame_view->GetLayoutView()) {
layout_view->GetDocument().UpdateStyleAndLayout( layout_view->GetDocument().UpdateStyleAndLayout(
DocumentUpdateReason::kTest); DocumentUpdateReason::kTest);
if (auto* layer = layout_view->Layer()) { if (auto* layer = layout_view->Layer()) {
LayoutTreeAsText::WriteLayers(ts, layer, layer, indent + 1, behavior); LayoutTreeAsText::WriteLayers(ts, layer, layer, indent + 1,
behavior);
}
} }
} }
} }
...@@ -739,6 +740,9 @@ void LayoutTreeAsText::WriteLayers(WTF::TextStream& ts, ...@@ -739,6 +740,9 @@ void LayoutTreeAsText::WriteLayers(WTF::TextStream& ts,
} }
#endif #endif
bool should_paint_children =
!layer->GetLayoutObject().ChildLayoutBlockedByDisplayLock();
const auto& neg_list = ChildLayers(layer, kNegativeZOrderChildren); const auto& neg_list = ChildLayers(layer, kNegativeZOrderChildren);
bool paints_background_separately = !neg_list.IsEmpty(); bool paints_background_separately = !neg_list.IsEmpty();
if (should_paint && paints_background_separately) { if (should_paint && paints_background_separately) {
...@@ -747,7 +751,7 @@ void LayoutTreeAsText::WriteLayers(WTF::TextStream& ts, ...@@ -747,7 +751,7 @@ void LayoutTreeAsText::WriteLayers(WTF::TextStream& ts,
behavior, marked_layer); behavior, marked_layer);
} }
if (!neg_list.IsEmpty()) { if (should_paint_children && !neg_list.IsEmpty()) {
int curr_indent = indent; int curr_indent = indent;
if (behavior & kLayoutAsTextShowLayerNesting) { if (behavior & kLayoutAsTextShowLayerNesting) {
WriteIndent(ts, indent); WriteIndent(ts, indent);
...@@ -767,7 +771,7 @@ void LayoutTreeAsText::WriteLayers(WTF::TextStream& ts, ...@@ -767,7 +771,7 @@ void LayoutTreeAsText::WriteLayers(WTF::TextStream& ts,
} }
const auto& normal_flow_list = ChildLayers(layer, kNormalFlowChildren); const auto& normal_flow_list = ChildLayers(layer, kNormalFlowChildren);
if (!normal_flow_list.IsEmpty()) { if (should_paint_children && !normal_flow_list.IsEmpty()) {
int curr_indent = indent; int curr_indent = indent;
if (behavior & kLayoutAsTextShowLayerNesting) { if (behavior & kLayoutAsTextShowLayerNesting) {
WriteIndent(ts, indent); WriteIndent(ts, indent);
...@@ -779,7 +783,7 @@ void LayoutTreeAsText::WriteLayers(WTF::TextStream& ts, ...@@ -779,7 +783,7 @@ void LayoutTreeAsText::WriteLayers(WTF::TextStream& ts,
} }
const auto& pos_list = ChildLayers(layer, kPositiveZOrderChildren); const auto& pos_list = ChildLayers(layer, kPositiveZOrderChildren);
if (!pos_list.IsEmpty()) { if (should_paint_children && !pos_list.IsEmpty()) {
int curr_indent = indent; int curr_indent = indent;
if (behavior & kLayoutAsTextShowLayerNesting) { if (behavior & kLayoutAsTextShowLayerNesting) {
WriteIndent(ts, indent); WriteIndent(ts, indent);
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/animation/document_animations.h" #include "third_party/blink/renderer/core/animation/document_animations.h"
#include "third_party/blink/renderer/core/animation/document_timeline.h" #include "third_party/blink/renderer/core/animation/document_timeline.h"
#include "third_party/blink/renderer/core/animation/element_animations.h" #include "third_party/blink/renderer/core/animation/element_animations.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h" #include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h" #include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame.h"
...@@ -207,6 +208,9 @@ void PaintLayerCompositor::UpdateAssignmentsIfNeededRecursiveInternal( ...@@ -207,6 +208,9 @@ void PaintLayerCompositor::UpdateAssignmentsIfNeededRecursiveInternal(
if (layout_view_->GetFrameView()->ShouldThrottleRendering()) if (layout_view_->GetFrameView()->ShouldThrottleRendering())
return; return;
if (DisplayLockUtilities::PrePaintBlockedInParentFrame(layout_view_))
return;
Lifecycle().AdvanceTo(DocumentLifecycle::kInCompositingAssignmentsUpdate); Lifecycle().AdvanceTo(DocumentLifecycle::kInCompositingAssignmentsUpdate);
LocalFrameView* view = layout_view_->GetFrameView(); LocalFrameView* view = layout_view_->GetFrameView();
...@@ -245,7 +249,8 @@ void PaintLayerCompositor::UpdateAssignmentsIfNeededRecursiveInternal( ...@@ -245,7 +249,8 @@ void PaintLayerCompositor::UpdateAssignmentsIfNeededRecursiveInternal(
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
DCHECK_EQ(Lifecycle().GetState(), DCHECK_EQ(Lifecycle().GetState(),
DocumentLifecycle::kCompositingAssignmentsClean); DocumentLifecycle::kCompositingAssignmentsClean);
AssertNoUnresolvedDirtyBits(); if (!DisplayLockUtilities::PrePaintBlockedInParentFrame(layout_view_))
AssertNoUnresolvedDirtyBits();
for (Frame* child = for (Frame* child =
layout_view_->GetFrameView()->GetFrame().Tree().FirstChild(); layout_view_->GetFrameView()->GetFrame().Tree().FirstChild();
child; child = child->Tree().NextSibling()) { child; child = child->Tree().NextSibling()) {
...@@ -253,7 +258,9 @@ void PaintLayerCompositor::UpdateAssignmentsIfNeededRecursiveInternal( ...@@ -253,7 +258,9 @@ void PaintLayerCompositor::UpdateAssignmentsIfNeededRecursiveInternal(
if (!local_frame) if (!local_frame)
continue; continue;
if (local_frame->ShouldThrottleRendering() || if (local_frame->ShouldThrottleRendering() ||
!local_frame->ContentLayoutObject()) !local_frame->ContentLayoutObject() ||
DisplayLockUtilities::PrePaintBlockedInParentFrame(
local_frame->ContentLayoutObject()))
continue; continue;
local_frame->ContentLayoutObject() local_frame->ContentLayoutObject()
->Compositor() ->Compositor()
......
layer at (0,0) size 800x600
LayoutView at (0,0) size 800x600
layer at (0,0) size 800x200
LayoutNGBlockFlow {HTML} at (0,0) size 800x200
LayoutNGBlockFlow {BODY} at (0,0) size 800x200
layer at (0,0) size 800x0
LayoutNGBlockFlow {DIV} at (0,0) size 800x0 (display-locked)
<!DOCTYPE html>
<style>
iframe {
width: 10px;
height: 10px;
border: none;
padding: 0;
margin: 0;
}
body {
padding: 0;
margin: 0;
height: 200px;
}
</style>
<div id=d>
<iframe id=frame></iframe>
</div>
<script>
if (window.testRunner)
testRunner.waitUntilDone();
requestAnimationFrame(() => requestAnimationFrame(() => {
d.style = "content-visibility: hidden";
frame.srcdoc = '<table> <marquee></marquee></table>';
if (window.testRunner) {
testRunner.dumpAsLayout();
testRunner.notifyDone();
}
}));
</script>
layer at (0,0) size 800x600
LayoutView at (0,0) size 800x600
layer at (0,0) size 800x200
LayoutNGBlockFlow {HTML} at (0,0) size 800x200
LayoutNGBlockFlow {BODY} at (0,0) size 800x200
layer at (8,7) size 10x10
LayoutIFrame (positioned) {IFRAME} at (8,7) size 10x10 (display-locked)
<!DOCTYPE html>
<style>
iframe {
width: 10px;
height: 10px;
border: none;
padding: 0;
margin: 0;
position: absolute;
top: 7px;
left: 8px;
}
body {
padding: 0;
margin: 0;
height: 200px;
}
</style>
<iframe id=frame style="content-visibility: hidden" srcdoc='<table> <marquee></marquee></table>'></iframe>
<script>
if (window.testRunner)
testRunner.dumpAsLayout();
</script>
layer at (0,0) size 800x600
LayoutView at (0,0) size 800x600
layer at (0,0) size 800x200
LayoutBlockFlow {HTML} at (0,0) size 800x200
LayoutBlockFlow {BODY} at (0,0) size 800x200
layer at (0,0) size 800x0
LayoutBlockFlow {DIV} at (0,0) size 800x0 (display-locked)
layer at (0,0) size 800x600
LayoutView at (0,0) size 800x600
layer at (0,0) size 800x200
LayoutBlockFlow {HTML} at (0,0) size 800x200
LayoutBlockFlow {BODY} at (0,0) size 800x200
layer at (8,7) size 10x10
LayoutIFrame (positioned) {IFRAME} at (8,7) size 10x10 (display-locked)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment