Commit 84afbfbd authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

Unify graphics layer traversal functions

This makes them consistent to use the same skipping conditions as
what we do during PrePaint, to avoid access of null or stale layer
states.

Bug: 1110232
Change-Id: I50e3d997476e8fc8532c2b3cb931c5639c71044d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2342468Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#796152}
parent 839b6619
...@@ -109,7 +109,7 @@ TEST_P(FrameOverlayTest, AcceleratedCompositing) { ...@@ -109,7 +109,7 @@ TEST_P(FrameOverlayTest, AcceleratedCompositing) {
builder.EndRecording()->Playback(&canvas); builder.EndRecording()->Playback(&canvas);
} else { } else {
auto* graphics_layer = frame_overlay->GetGraphicsLayer(); auto* graphics_layer = frame_overlay->GetGraphicsLayer();
EXPECT_FALSE(graphics_layer->GetHitTestable()); EXPECT_FALSE(graphics_layer->IsHitTestable());
EXPECT_EQ(PropertyTreeState::Root(), EXPECT_EQ(PropertyTreeState::Root(),
graphics_layer->GetPropertyTreeState()); graphics_layer->GetPropertyTreeState());
graphics_layer->Paint(); graphics_layer->Paint();
...@@ -162,7 +162,7 @@ TEST_P(FrameOverlayTest, DeviceEmulationScale) { ...@@ -162,7 +162,7 @@ TEST_P(FrameOverlayTest, DeviceEmulationScale) {
check_paint_results(*paint_controller); check_paint_results(*paint_controller);
} else { } else {
auto* graphics_layer = frame_overlay->GetGraphicsLayer(); auto* graphics_layer = frame_overlay->GetGraphicsLayer();
EXPECT_FALSE(graphics_layer->GetHitTestable()); EXPECT_FALSE(graphics_layer->IsHitTestable());
EXPECT_EQ(state, graphics_layer->GetPropertyTreeState()); EXPECT_EQ(state, graphics_layer->GetPropertyTreeState());
graphics_layer->Paint(); graphics_layer->Paint();
check_paint_results(graphics_layer->GetPaintController()); check_paint_results(graphics_layer->GetPaintController());
......
...@@ -2657,14 +2657,6 @@ bool LocalFrameView::RunPrePaintLifecyclePhase( ...@@ -2657,14 +2657,6 @@ bool LocalFrameView::RunPrePaintLifecyclePhase(
return target_state > DocumentLifecycle::kPrePaintClean; return target_state > DocumentLifecycle::kPrePaintClean;
} }
template <typename Function>
static void ForAllGraphicsLayers(GraphicsLayer& layer,
const Function& function) {
function(layer);
for (auto* child : layer.Children())
ForAllGraphicsLayers(*child, function);
}
void LocalFrameView::RunPaintLifecyclePhase() { void LocalFrameView::RunPaintLifecyclePhase() {
TRACE_EVENT0("blink,benchmark", "LocalFrameView::RunPaintLifecyclePhase"); TRACE_EVENT0("blink,benchmark", "LocalFrameView::RunPaintLifecyclePhase");
// While printing or capturing a paint preview of a document, the paint walk // While printing or capturing a paint preview of a document, the paint walk
...@@ -2722,14 +2714,12 @@ void LocalFrameView::RunPaintLifecyclePhase() { ...@@ -2722,14 +2714,12 @@ void LocalFrameView::RunPaintLifecyclePhase() {
if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
auto* root = GetLayoutView()->Compositor()->PaintRootGraphicsLayer(); auto* root = GetLayoutView()->Compositor()->PaintRootGraphicsLayer();
if (root) { if (root) {
ForAllGraphicsLayers(*root, [](GraphicsLayer& layer) { ForAllPaintingGraphicsLayers(*root, [](GraphicsLayer& layer) {
if (layer.PaintsContentOrHitTest() && layer.HasLayerState()) {
// Notify the paint controller that the artifact has been pushed and // Notify the paint controller that the artifact has been pushed and
// some lifecycle state can be freed (such as raster invalidations). // some lifecycle state can be freed (such as raster invalidations).
layer.GetPaintController().FinishCycle(); layer.GetPaintController().FinishCycle();
layer.GetPaintController().ClearPropertyTreeChangedStateTo( layer.GetPaintController().ClearPropertyTreeChangedStateTo(
layer.GetPropertyTreeState()); layer.GetPropertyTreeState());
}
}); });
} }
} }
...@@ -2794,69 +2784,35 @@ void LocalFrameView::EnqueueScrollEvents() { ...@@ -2794,69 +2784,35 @@ void LocalFrameView::EnqueueScrollEvents() {
}); });
} }
template <typename MainLayerFunction, typename ContentsLayerFunction> static void CollectGraphicsLayersForLayerListRecursively(
static void ForAllDrawableGraphicsLayers(
const GraphicsLayer* layer,
const MainLayerFunction& main_layer_function,
const ContentsLayerFunction& contents_layer_function) {
if (!layer || layer->Client().ShouldThrottleRendering() ||
layer->Client().IsUnderSVGHiddenContainer()) {
return;
}
if (layer->Client().PaintBlockedByDisplayLockIncludingAncestors(
DisplayLockContextLifecycleTarget::kSelf)) {
// If we skip the layer, then we need to ensure to notify the
// display-lock, since we need to force recollect the layers when we commit.
layer->Client().NotifyDisplayLockNeedsGraphicsLayerCollection();
return;
}
// We need to collect all layers that draw content, as well as some layers
// that don't for the purposes of hit testing. For example, an empty div
// will not draw content but needs to create a layer to ensure scroll events
// do not pass through it.
if (layer->PaintsContentOrHitTest() || layer->GetHitTestable())
main_layer_function(layer);
if (auto* contents_layer = layer->ContentsLayer())
contents_layer_function(layer, contents_layer);
for (const auto* child : layer->Children()) {
ForAllDrawableGraphicsLayers(child, main_layer_function,
contents_layer_function);
}
}
static void CollectDrawableLayersForLayerListRecursively(
GraphicsContext& context, GraphicsContext& context,
const GraphicsLayer* root) { const GraphicsLayer& root) {
ForAllDrawableGraphicsLayers( ForAllActiveGraphicsLayers(
root, root,
[&](const GraphicsLayer* layer) { RecordGraphicsLayer(context, *layer); }, [&](const GraphicsLayer& layer) { RecordGraphicsLayer(context, layer); },
[&](const GraphicsLayer* layer, cc::Layer* contents_layer) { [&](const GraphicsLayer& layer, cc::Layer& contents_layer) {
RecordForeignLayer( RecordForeignLayer(
context, *layer, DisplayItem::kForeignLayerContentsWrapper, context, layer, DisplayItem::kForeignLayerContentsWrapper,
contents_layer, layer->GetContentsOffsetFromTransformNode(), &contents_layer, layer.GetContentsOffsetFromTransformNode(),
&layer->GetContentsPropertyTreeState()); &layer.GetContentsPropertyTreeState());
}); });
} }
static void UpdateLayerDebugInfoRecursively(const GraphicsLayer* root) { static void UpdateLayerDebugInfoRecursively(const GraphicsLayer& root) {
ForAllDrawableGraphicsLayers( ForAllActiveGraphicsLayers(
root, root,
[](const GraphicsLayer* layer) { [](const GraphicsLayer& layer) {
PaintArtifactCompositor::UpdateLayerDebugInfo( PaintArtifactCompositor::UpdateLayerDebugInfo(
layer->CcLayer(), *layer.CcLayer(),
PaintChunk::Id(*layer, DisplayItem::kGraphicsLayerWrapper), PaintChunk::Id(layer, DisplayItem::kGraphicsLayerWrapper),
layer->GetCompositingReasons(), layer.GetCompositingReasons(),
layer->GetRasterInvalidationTracking()); layer.GetRasterInvalidationTracking());
}, },
[](const GraphicsLayer* layer, cc::Layer* contents_layer) { [](const GraphicsLayer& layer, cc::Layer& contents_layer) {
PaintArtifactCompositor::UpdateLayerDebugInfo( PaintArtifactCompositor::UpdateLayerDebugInfo(
contents_layer, contents_layer,
PaintChunk::Id(*layer, DisplayItem::kForeignLayerContentsWrapper), PaintChunk::Id(layer, DisplayItem::kForeignLayerContentsWrapper),
layer->GetCompositingReasons(), nullptr); layer.GetCompositingReasons(), nullptr);
}); });
} }
...@@ -3005,8 +2961,8 @@ void LocalFrameView::PushPaintArtifactToCompositor() { ...@@ -3005,8 +2961,8 @@ void LocalFrameView::PushPaintArtifactToCompositor() {
if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
layer_debug_info_enabled_) { layer_debug_info_enabled_) {
UpdateLayerDebugInfoRecursively( if (auto* root = GetLayoutView()->Compositor()->PaintRootGraphicsLayer())
GetLayoutView()->Compositor()->PaintRootGraphicsLayer()); UpdateLayerDebugInfoRecursively(*root);
} }
// Skip updating property trees, pushing cc::Layers, and issuing raster // Skip updating property trees, pushing cc::Layers, and issuing raster
...@@ -3055,7 +3011,7 @@ void LocalFrameView::PushPaintArtifactToCompositor() { ...@@ -3055,7 +3011,7 @@ void LocalFrameView::PushPaintArtifactToCompositor() {
GraphicsContext context(*paint_controller_); GraphicsContext context(*paint_controller_);
auto* root = GetLayoutView()->Compositor()->PaintRootGraphicsLayer(); auto* root = GetLayoutView()->Compositor()->PaintRootGraphicsLayer();
CollectDrawableLayersForLayerListRecursively(context, root); CollectGraphicsLayersForLayerListRecursively(context, *root);
if (frame_->IsMainFrame()) { if (frame_->IsMainFrame()) {
if (root == GetLayoutView()->Compositor()->RootGraphicsLayer()) if (root == GetLayoutView()->Compositor()->RootGraphicsLayer())
......
...@@ -158,22 +158,6 @@ void ScrollingCoordinator::UpdateAfterPaint(LocalFrameView* frame_view) { ...@@ -158,22 +158,6 @@ void ScrollingCoordinator::UpdateAfterPaint(LocalFrameView* frame_view) {
} }
} }
template <typename Function>
static void ForAllPaintingGraphicsLayers(GraphicsLayer& layer,
const Function& function) {
// Don't recurse into display-locked elements.
if (layer.Client().PaintBlockedByDisplayLockIncludingAncestors(
DisplayLockContextLifecycleTarget::kSelf)) {
return;
}
if (layer.PaintsContentOrHitTest() && layer.HasLayerState())
function(layer);
for (auto* child : layer.Children())
ForAllPaintingGraphicsLayers(*child, function);
}
// Set the non-fast scrollable regions on |layer|'s cc layer. // Set the non-fast scrollable regions on |layer|'s cc layer.
static void UpdateLayerNonFastScrollableRegions(GraphicsLayer& layer) { static void UpdateLayerNonFastScrollableRegions(GraphicsLayer& layer) {
// CompositeAfterPaint does this update in PaintArtifactCompositor. // CompositeAfterPaint does this update in PaintArtifactCompositor.
...@@ -181,11 +165,6 @@ static void UpdateLayerNonFastScrollableRegions(GraphicsLayer& layer) { ...@@ -181,11 +165,6 @@ static void UpdateLayerNonFastScrollableRegions(GraphicsLayer& layer) {
DCHECK(layer.PaintsContentOrHitTest()); DCHECK(layer.PaintsContentOrHitTest());
if (layer.Client().ShouldThrottleRendering()) {
layer.CcLayer()->SetNonFastScrollableRegion(cc::Region());
return;
}
auto offset = layer.GetOffsetFromTransformNode(); auto offset = layer.GetOffsetFromTransformNode();
gfx::Vector2dF layer_offset = gfx::Vector2dF(offset.X(), offset.Y()); gfx::Vector2dF layer_offset = gfx::Vector2dF(offset.X(), offset.Y());
PaintChunkSubset paint_chunks = PaintChunkSubset paint_chunks =
...@@ -212,10 +191,10 @@ void ScrollingCoordinator::UpdateNonFastScrollableRegions(LocalFrame* frame) { ...@@ -212,10 +191,10 @@ void ScrollingCoordinator::UpdateNonFastScrollableRegions(LocalFrame* frame) {
// Set the touch action rects on the cc layer from the touch action data stored // Set the touch action rects on the cc layer from the touch action data stored
// on the GraphicsLayer's paint chunks. // on the GraphicsLayer's paint chunks.
static void UpdateLayerTouchActionRects(GraphicsLayer& layer) { static void UpdateLayerTouchActionRects(GraphicsLayer& layer) {
if (layer.Client().ShouldThrottleRendering()) { // CompositeAfterPaint does this update in PaintArtifactCompositor.
layer.CcLayer()->SetTouchActionRegion(cc::TouchActionRegion()); DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
return;
} DCHECK(layer.PaintsContentOrHitTest());
auto offset = layer.GetOffsetFromTransformNode(); auto offset = layer.GetOffsetFromTransformNode();
gfx::Vector2dF layer_offset = gfx::Vector2dF(offset.X(), offset.Y()); gfx::Vector2dF layer_offset = gfx::Vector2dF(offset.X(), offset.Y());
......
...@@ -1059,7 +1059,7 @@ TEST_F(CompositedLayerMappingTest, ...@@ -1059,7 +1059,7 @@ TEST_F(CompositedLayerMappingTest,
mapping->ForegroundLayer()->PaintingPhase()); mapping->ForegroundLayer()->PaintingPhase());
// Regression test for crbug.com/767908: a foreground layer should also // Regression test for crbug.com/767908: a foreground layer should also
// participates hit testing. // participates hit testing.
EXPECT_TRUE(mapping->ForegroundLayer()->GetHitTestable()); EXPECT_TRUE(mapping->ForegroundLayer()->IsHitTestable());
Element* negative_composited_child = Element* negative_composited_child =
GetDocument().getElementById("negative-composited-child"); GetDocument().getElementById("negative-composited-child");
......
...@@ -1376,7 +1376,7 @@ void PaintArtifactCompositor::Update( ...@@ -1376,7 +1376,7 @@ void PaintArtifactCompositor::Update(
.GetTracking(); .GetTracking();
} }
UpdateLayerDebugInfo( UpdateLayerDebugInfo(
layer.get(), pending_layer.FirstPaintChunk().id, *layer, pending_layer.FirstPaintChunk().id,
GetCompositingReasons(pending_layer, previous_pending_layer), GetCompositingReasons(pending_layer, previous_pending_layer),
tracking); tracking);
} }
...@@ -1593,11 +1593,11 @@ void PaintArtifactCompositor::SetLayerDebugInfoEnabled(bool enabled) { ...@@ -1593,11 +1593,11 @@ void PaintArtifactCompositor::SetLayerDebugInfoEnabled(bool enabled) {
} }
void PaintArtifactCompositor::UpdateLayerDebugInfo( void PaintArtifactCompositor::UpdateLayerDebugInfo(
cc::Layer* layer, cc::Layer& layer,
const PaintChunk::Id& id, const PaintChunk::Id& id,
CompositingReasons compositing_reasons, CompositingReasons compositing_reasons,
RasterInvalidationTracking* raster_invalidation_tracking) { RasterInvalidationTracking* raster_invalidation_tracking) {
cc::LayerDebugInfo& debug_info = layer->EnsureDebugInfo(); cc::LayerDebugInfo& debug_info = layer.EnsureDebugInfo();
debug_info.name = id.client.DebugName().Utf8(); debug_info.name = id.client.DebugName().Utf8();
if (id.type == DisplayItem::kForeignLayerContentsWrapper) { if (id.type == DisplayItem::kForeignLayerContentsWrapper) {
......
...@@ -210,7 +210,7 @@ class PLATFORM_EXPORT PaintArtifactCompositor final ...@@ -210,7 +210,7 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
// TODO(wangxianzhu): Make this private and refactor when removing // TODO(wangxianzhu): Make this private and refactor when removing
// pre-CompositeAfterPaint. // pre-CompositeAfterPaint.
static void UpdateLayerDebugInfo(cc::Layer* layer, static void UpdateLayerDebugInfo(cc::Layer& layer,
const PaintChunk::Id&, const PaintChunk::Id&,
CompositingReasons, CompositingReasons,
RasterInvalidationTracking*); RasterInvalidationTracking*);
......
...@@ -261,29 +261,13 @@ IntRect GraphicsLayer::InterestRect() { ...@@ -261,29 +261,13 @@ IntRect GraphicsLayer::InterestRect() {
} }
bool GraphicsLayer::PaintRecursively() { bool GraphicsLayer::PaintRecursively() {
// TODO(crbug.com/1033240): Debugging information for the referenced bug.
// Remove when it is fixed.
CHECK(&client_);
if (client_.PaintBlockedByDisplayLockIncludingAncestors(
DisplayLockContextLifecycleTarget::kSelf)) {
return false;
}
bool painted = false; bool painted = false;
if (PaintsContentOrHitTest()) { ForAllPaintingGraphicsLayers(
if (Paint()) *this, [&painted](GraphicsLayer& layer) { painted |= layer.Paint(); });
painted = true;
}
for (auto* child : Children())
painted |= child->PaintRecursively();
return painted; return painted;
} }
bool GraphicsLayer::Paint() { bool GraphicsLayer::Paint() {
if (client_.ShouldThrottleRendering())
return false;
#if !DCHECK_IS_ON() #if !DCHECK_IS_ON()
// TODO(crbug.com/853096): Investigate why we can ever reach here without // TODO(crbug.com/853096): Investigate why we can ever reach here without
// a valid layer state. Seems to only happen on Android builds. // a valid layer state. Seems to only happen on Android builds.
......
...@@ -149,7 +149,7 @@ class PLATFORM_EXPORT GraphicsLayer : public DisplayItemClient, ...@@ -149,7 +149,7 @@ class PLATFORM_EXPORT GraphicsLayer : public DisplayItemClient,
void SetContentsOpaqueForText(bool); void SetContentsOpaqueForText(bool);
void SetHitTestable(bool); void SetHitTestable(bool);
bool GetHitTestable() const { return hit_testable_; } bool IsHitTestable() const { return hit_testable_; }
// Some GraphicsLayers paint only the foreground or the background content // Some GraphicsLayers paint only the foreground or the background content
GraphicsLayerPaintingPhase PaintingPhase() const { return painting_phase_; } GraphicsLayerPaintingPhase PaintingPhase() const { return painting_phase_; }
...@@ -326,6 +326,59 @@ class PLATFORM_EXPORT GraphicsLayer : public DisplayItemClient, ...@@ -326,6 +326,59 @@ class PLATFORM_EXPORT GraphicsLayer : public DisplayItemClient,
DISALLOW_COPY_AND_ASSIGN(GraphicsLayer); DISALLOW_COPY_AND_ASSIGN(GraphicsLayer);
}; };
// Iterates all graphics layers that should be seen by the compositor in
// pre-order. |GraphicsLayerType| matches |GraphicsLayer&| or
// |const GraphicsLayer&|.
template <typename GraphicsLayerType,
typename GraphicsLayerFunction,
typename ContentsLayerFunction>
void ForAllActiveGraphicsLayers(
GraphicsLayerType& layer,
const GraphicsLayerFunction& graphics_layer_function,
const ContentsLayerFunction& contents_layer_function) {
if (layer.Client().ShouldThrottleRendering() ||
layer.Client().IsUnderSVGHiddenContainer()) {
return;
}
if (layer.Client().PaintBlockedByDisplayLockIncludingAncestors(
DisplayLockContextLifecycleTarget::kSelf)) {
// If we skip the layer, then we need to ensure to notify the
// display-lock, since we need to force recollect the layers when we commit.
layer.Client().NotifyDisplayLockNeedsGraphicsLayerCollection();
return;
}
DCHECK(layer.HasLayerState());
if (layer.PaintsContentOrHitTest() || layer.IsHitTestable())
graphics_layer_function(layer);
if (auto* contents_layer = layer.ContentsLayer())
contents_layer_function(layer, *contents_layer);
for (auto* child : layer.Children()) {
ForAllActiveGraphicsLayers(*child, graphics_layer_function,
contents_layer_function);
}
}
template <typename GraphicsLayerType, typename Function>
void ForAllActiveGraphicsLayers(GraphicsLayerType& layer,
const Function& function) {
ForAllActiveGraphicsLayers(layer, function,
[](GraphicsLayerType&, const cc::Layer&) {});
}
template <typename GraphicsLayerType, typename Function>
void ForAllPaintingGraphicsLayers(GraphicsLayerType& layer,
const Function& function) {
ForAllActiveGraphicsLayers(layer, [&function](GraphicsLayerType& layer) {
if (layer.PaintsContentOrHitTest())
function(layer);
});
}
} // namespace blink } // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GRAPHICS_LAYER_H_ #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GRAPHICS_LAYER_H_
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