1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights
3  * reserved.
4  *
5  * Portions are Copyright (C) 1998 Netscape Communications Corporation.
6  *
7  * Other contributors:
8  *   Robert O'Callahan <roc+@cs.cmu.edu>
9  *   David Baron <dbaron@fas.harvard.edu>
10  *   Christian Biesinger <cbiesinger@web.de>
11  *   Randall Jesup <rjesup@wgate.com>
12  *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
13  *   Josh Soref <timeless@mac.com>
14  *   Boris Zbarsky <bzbarsky@mit.edu>
15  *
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  *
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  *
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
29  *
30  * Alternatively, the contents of this file may be used under the terms
31  * of either the Mozilla Public License Version 1.1, found at
32  * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
33  * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
34  * (the "GPL"), in which case the provisions of the MPL or the GPL are
35  * applicable instead of those above.  If you wish to allow use of your
36  * version of this file only under the terms of one of those two
37  * licenses (the MPL or the GPL) and not to allow others to use your
38  * version of this file under the LGPL, indicate your decision by
39  * deletingthe provisions above and replace them with the notice and
40  * other provisions required by the MPL or the GPL, as the case may be.
41  * If you do not delete the provisions above, a recipient may use your
42  * version of this file under any of the LGPL, the MPL or the GPL.
43  */
44 
45 #include "third_party/blink/renderer/core/paint/paint_layer.h"
46 
47 #include <limits>
48 
49 #include "base/allocator/partition_allocator/partition_alloc.h"
50 #include "base/containers/adapters.h"
51 #include "third_party/blink/public/platform/task_type.h"
52 #include "third_party/blink/renderer/core/animation/scroll_timeline.h"
53 #include "third_party/blink/renderer/core/css/css_property_names.h"
54 #include "third_party/blink/renderer/core/css/pseudo_style_request.h"
55 #include "third_party/blink/renderer/core/dom/document.h"
56 #include "third_party/blink/renderer/core/dom/shadow_root.h"
57 #include "third_party/blink/renderer/core/frame/local_frame.h"
58 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
59 #include "third_party/blink/renderer/core/frame/settings.h"
60 #include "third_party/blink/renderer/core/html_names.h"
61 #include "third_party/blink/renderer/core/layout/fragmentainer_iterator.h"
62 #include "third_party/blink/renderer/core/layout/geometry/transform_state.h"
63 #include "third_party/blink/renderer/core/layout/hit_test_request.h"
64 #include "third_party/blink/renderer/core/layout/hit_test_result.h"
65 #include "third_party/blink/renderer/core/layout/hit_testing_transform_state.h"
66 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
67 #include "third_party/blink/renderer/core/layout/layout_flow_thread.h"
68 #include "third_party/blink/renderer/core/layout/layout_inline.h"
69 #include "third_party/blink/renderer/core/layout/layout_tree_as_text.h"
70 #include "third_party/blink/renderer/core/layout/layout_view.h"
71 #include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h"
72 #include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
73 #include "third_party/blink/renderer/core/page/page.h"
74 #include "third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h"
75 #include "third_party/blink/renderer/core/paint/box_reflection_utils.h"
76 #include "third_party/blink/renderer/core/paint/clip_path_clipper.h"
77 #include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
78 #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
79 #include "third_party/blink/renderer/core/paint/filter_effect_builder.h"
80 #include "third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h"
81 #include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
82 #include "third_party/blink/renderer/core/paint/paint_info.h"
83 #include "third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h"
84 #include "third_party/blink/renderer/core/paint/paint_layer_painter.h"
85 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
86 #include "third_party/blink/renderer/core/style/reference_clip_path_operation.h"
87 #include "third_party/blink/renderer/core/style/shape_clip_path_operation.h"
88 #include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
89 #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
90 #include "third_party/blink/renderer/platform/geometry/float_point_3d.h"
91 #include "third_party/blink/renderer/platform/geometry/float_rect.h"
92 #include "third_party/blink/renderer/platform/geometry/length_functions.h"
93 #include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
94 #include "third_party/blink/renderer/platform/graphics/filters/filter.h"
95 #include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
96 #include "third_party/blink/renderer/platform/heap/heap.h"
97 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
98 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
99 #include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
100 #include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
101 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
102 
103 namespace blink {
104 
105 namespace {
106 
107 static CompositingQueryMode g_compositing_query_mode =
108     kCompositingQueriesAreOnlyAllowedInCertainDocumentLifecyclePhases;
109 
110 #if defined(OS_LINUX) || defined(OS_BSD)
111 struct SameSizeAsPaintLayer : DisplayItemClient {
112   // The bit fields may fit into the machine word of DisplayItemClient which
113   // has only 8-bit data.
114   unsigned bit_fields1 : 24;
115   unsigned bit_fields2;
116   void* pointers[11];
117 #if DCHECK_IS_ON()
118   void* pointer;
119 #endif
120   LayoutUnit layout_units[4];
121   IntSize size;
122   Persistent<PaintLayerScrollableArea> scrollable_area;
123   CullRect previous_cull_rect;
124 };
125 
126 static_assert(sizeof(PaintLayer) == sizeof(SameSizeAsPaintLayer),
127               "PaintLayer should stay small");
128 #endif
129 
130 }  // namespace
131 
PaintLayerRareData()132 PaintLayerRareData::PaintLayerRareData()
133     : enclosing_pagination_layer(nullptr),
134       potential_compositing_reasons_from_style(CompositingReason::kNone),
135       potential_compositing_reasons_from_non_style(CompositingReason::kNone),
136       compositing_reasons(CompositingReason::kNone),
137       squashing_disallowed_reasons(SquashingDisallowedReason::kNone),
138       grouped_mapping(nullptr) {}
139 
140 PaintLayerRareData::~PaintLayerRareData() = default;
141 
PaintLayer(LayoutBoxModelObject & layout_object)142 PaintLayer::PaintLayer(LayoutBoxModelObject& layout_object)
143     : is_root_layer_(IsA<LayoutView>(layout_object)),
144       has_visible_content_(false),
145       needs_descendant_dependent_flags_update_(true),
146       needs_visual_overflow_recalc_(true),
147       has_visible_descendant_(false),
148 #if DCHECK_IS_ON()
149       // The root layer (LayoutView) does not need position update at start
150       // because its Location() is always 0.
151       needs_position_update_(!IsRootLayer()),
152 #endif
153       has3d_transformed_descendant_(false),
154       needs_ancestor_dependent_compositing_inputs_update_(
155           !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()),
156       child_needs_compositing_inputs_update_(
157           !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()),
158       has_compositing_descendant_(false),
159       should_isolate_composited_descendants_(false),
160       lost_grouped_mapping_(false),
161       self_needs_repaint_(false),
162       descendant_needs_repaint_(false),
163       previous_paint_result_(kFullyPainted),
164       needs_paint_phase_descendant_outlines_(false),
165       needs_paint_phase_float_(false),
166       has_descendant_with_clip_path_(false),
167       has_non_isolated_descendant_with_blend_mode_(false),
168       has_fixed_position_descendant_(false),
169       has_sticky_position_descendant_(false),
170       has_non_contained_absolute_position_descendant_(false),
171       has_stacked_descendant_in_current_stacking_context_(false),
172       self_painting_status_changed_(false),
173       filter_on_effect_node_dirty_(false),
174       backdrop_filter_on_effect_node_dirty_(false),
175       is_under_svg_hidden_container_(false),
176       descendant_has_direct_or_scrolling_compositing_reason_(false),
177       needs_compositing_reasons_update_(
178           !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()),
179       descendant_may_need_compositing_requirements_update_(false),
180       needs_compositing_layer_assignment_(false),
181       descendant_needs_compositing_layer_assignment_(false),
182       has_self_painting_layer_descendant_(false),
183       needs_reorder_overlay_overflow_controls_(false),
184 #if DCHECK_IS_ON()
185       layer_list_mutation_allowed_(true),
186 #endif
187       layout_object_(layout_object),
188       parent_(nullptr),
189       previous_(nullptr),
190       next_(nullptr),
191       first_(nullptr),
192       last_(nullptr),
193       static_inline_position_(0),
194       static_block_position_(0),
195       ancestor_overflow_layer_(nullptr)
196 #if DCHECK_IS_ON()
197       ,
198       stacking_parent_(nullptr)
199 #endif
200 {
201   is_self_painting_layer_ = ShouldBeSelfPaintingLayer();
202 
203   UpdateScrollableArea();
204 }
205 
~PaintLayer()206 PaintLayer::~PaintLayer() {
207   if (rare_data_ && rare_data_->resource_info) {
208     const ComputedStyle& style = GetLayoutObject().StyleRef();
209     if (style.HasFilter())
210       style.Filter().RemoveClient(*rare_data_->resource_info);
211     if (auto* reference_clip =
212             DynamicTo<ReferenceClipPathOperation>(style.ClipPath()))
213       reference_clip->RemoveClient(*rare_data_->resource_info);
214     rare_data_->resource_info->ClearLayer();
215   }
216 
217   if (GroupedMapping()) {
218     DisableCompositingQueryAsserts disabler;
219     SetGroupedMapping(nullptr, kInvalidateLayerAndRemoveFromMapping);
220   }
221 
222   // Child layers will be deleted by their corresponding layout objects, so
223   // we don't need to delete them ourselves.
224   {
225     DisableCompositingQueryAsserts disabler;
226     ClearCompositedLayerMapping(true);
227   }
228 
229   // Reset this flag before disposing scrollable_area_ to prevent
230   // PaintLayerScrollableArea::WillRemoveScrollbar() from dirtying the z-order
231   // list of the stacking context. If this layer is removed from the parent,
232   // the z-order list should have been invalidated in RemoveChild().
233   needs_reorder_overlay_overflow_controls_ = false;
234 
235   if (scrollable_area_)
236     scrollable_area_->Dispose();
237 
238 #if DCHECK_IS_ON()
239   // stacking_parent_ should be cleared because DirtyStackingContextZOrderLists
240   // should have been called.
241   if (!GetLayoutObject().DocumentBeingDestroyed())
242     DCHECK(!stacking_parent_);
243 #endif
244 }
245 
DebugName() const246 String PaintLayer::DebugName() const {
247   return GetLayoutObject().DebugName();
248 }
249 
OwnerNodeId() const250 DOMNodeId PaintLayer::OwnerNodeId() const {
251   return static_cast<const DisplayItemClient&>(GetLayoutObject()).OwnerNodeId();
252 }
253 
VisualRect() const254 IntRect PaintLayer::VisualRect() const {
255   return layout_object_.FragmentsVisualRectBoundingBox();
256 }
257 
Compositor() const258 PaintLayerCompositor* PaintLayer::Compositor() const {
259   if (!GetLayoutObject().View())
260     return nullptr;
261   return GetLayoutObject().View()->Compositor();
262 }
263 
ContentChanged(ContentChangeType change_type)264 void PaintLayer::ContentChanged(ContentChangeType change_type) {
265   // updateLayerCompositingState will query compositingReasons for accelerated
266   // overflow scrolling.  This is tripped by
267   // web_tests/compositing/content-changed-chicken-egg.html
268   DisableCompositingQueryAsserts disabler;
269 
270   if (Compositor()) {
271     if (change_type == kCanvasChanged)
272       SetNeedsCompositingInputsUpdate();
273 
274     if (change_type == kCanvasContextChanged) {
275       SetNeedsCompositingInputsUpdate();
276 
277       // Although we're missing test coverage, we need to call
278       // GraphicsLayer::SetContentsToCcLayer with the new cc::Layer for this
279       // canvas. See http://crbug.com/349195
280       if (HasCompositedLayerMapping()) {
281         GetCompositedLayerMapping()->SetNeedsGraphicsLayerUpdate(
282             kGraphicsLayerUpdateSubtree);
283       }
284     }
285   }
286 
287   if (CompositedLayerMapping* composited_layer_mapping =
288           GetCompositedLayerMapping())
289     composited_layer_mapping->ContentChanged(change_type);
290 }
291 
PaintsWithFilters() const292 bool PaintLayer::PaintsWithFilters() const {
293   if (!GetLayoutObject().HasFilterInducingProperty())
294     return false;
295 
296   if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
297     // https://code.google.com/p/chromium/issues/detail?id=343759
298     DisableCompositingQueryAsserts disabler;
299     return !GetCompositedLayerMapping() ||
300            GetCompositingState() != kPaintsIntoOwnBacking;
301   } else {
302     return true;
303   }
304 }
305 
SubpixelAccumulation() const306 PhysicalOffset PaintLayer::SubpixelAccumulation() const {
307   return rare_data_ ? rare_data_->subpixel_accumulation : PhysicalOffset();
308 }
309 
SetSubpixelAccumulation(const PhysicalOffset & accumulation)310 void PaintLayer::SetSubpixelAccumulation(const PhysicalOffset& accumulation) {
311   DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
312   if (rare_data_ || !accumulation.IsZero())
313     EnsureRareData().subpixel_accumulation = accumulation;
314 }
315 
UpdateLayerPositionsAfterLayout()316 void PaintLayer::UpdateLayerPositionsAfterLayout() {
317   TRACE_EVENT0("blink,benchmark",
318                "PaintLayer::updateLayerPositionsAfterLayout");
319   RUNTIME_CALL_TIMER_SCOPE(
320       V8PerIsolateData::MainThreadIsolate(),
321       RuntimeCallStats::CounterId::kUpdateLayerPositionsAfterLayout);
322 
323   ClearClipRects();
324   UpdateLayerPositionRecursive();
325 
326   UpdatePaginationRecursive(EnclosingPaginationLayer());
327 }
328 
UpdateLayerPositionRecursive()329 void PaintLayer::UpdateLayerPositionRecursive() {
330   auto old_location = location_without_position_offset_;
331   auto old_offset_for_in_flow_rel_position = OffsetForInFlowRelPosition();
332   UpdateLayerPosition();
333 
334   if (location_without_position_offset_ != old_location) {
335     SetNeedsCompositingInputsUpdate();
336   } else {
337     // TODO(chrishtr): compute this invalidation in layout instead of here.
338     auto offset_for_in_flow_rel_position =
339         rare_data_ ? rare_data_->offset_for_in_flow_rel_position
340                    : PhysicalOffset();
341     if (offset_for_in_flow_rel_position != old_offset_for_in_flow_rel_position)
342       SetNeedsCompositingInputsUpdate();
343   }
344 
345   // Display-locked elements always have a PaintLayer, meaning that the
346   // PaintLayer traversal won't skip locked elements. Thus, we don't have to do
347   // an ancestor check, and simply skip iterating children when this element is
348   // locked for child layout.
349   if (GetLayoutObject().LayoutBlockedByDisplayLock(
350           DisplayLockLifecycleTarget::kChildren)) {
351     return;
352   }
353 
354   for (PaintLayer* child = FirstChild(); child; child = child->NextSibling())
355     child->UpdateLayerPositionRecursive();
356 }
357 
SticksToScroller() const358 bool PaintLayer::SticksToScroller() const {
359   if (!GetLayoutObject().StyleRef().HasStickyConstrainedPosition())
360     return false;
361   return AncestorOverflowLayer()->GetScrollableArea();
362 }
363 
FixedToViewport() const364 bool PaintLayer::FixedToViewport() const {
365   if (GetLayoutObject().StyleRef().GetPosition() != EPosition::kFixed)
366     return false;
367   return GetLayoutObject().Container() == GetLayoutObject().View();
368 }
369 
ScrollsWithRespectTo(const PaintLayer * other) const370 bool PaintLayer::ScrollsWithRespectTo(const PaintLayer* other) const {
371   if (FixedToViewport() != other->FixedToViewport())
372     return true;
373   // If either element sticks we cannot trivially determine that the layers do
374   // not scroll with respect to each other.
375   if (SticksToScroller() || other->SticksToScroller())
376     return true;
377   return AncestorScrollingLayer() != other->AncestorScrollingLayer();
378 }
379 
IsAffectedByScrollOf(const PaintLayer * ancestor) const380 bool PaintLayer::IsAffectedByScrollOf(const PaintLayer* ancestor) const {
381   if (this == ancestor)
382     return false;
383 
384   const PaintLayer* current_layer = this;
385   while (current_layer && current_layer != ancestor) {
386     bool ancestor_escaped = false;
387     const PaintLayer* container =
388         current_layer->ContainingLayer(ancestor, &ancestor_escaped);
389     if (ancestor_escaped)
390       return false;
391     // Workaround the bug that LayoutView is mistakenly considered
392     // a fixed-pos container.
393     if (current_layer->GetLayoutObject().IsFixedPositioned() &&
394         container->IsRootLayer())
395       return false;
396     current_layer = container;
397   }
398   return current_layer == ancestor;
399 }
400 
UpdateTransformationMatrix()401 void PaintLayer::UpdateTransformationMatrix() {
402   if (TransformationMatrix* transform = Transform()) {
403     LayoutBox* box = GetLayoutBox();
404     DCHECK(box);
405     transform->MakeIdentity();
406     box->StyleRef().ApplyTransform(
407         *transform, box->Size(), ComputedStyle::kIncludeTransformOrigin,
408         ComputedStyle::kIncludeMotionPath,
409         ComputedStyle::kIncludeIndependentTransformProperties);
410     MakeMatrixRenderable(
411         *transform,
412         box->GetDocument().GetSettings()->GetAcceleratedCompositingEnabled());
413   }
414 }
415 
UpdateTransform(const ComputedStyle * old_style,const ComputedStyle & new_style)416 void PaintLayer::UpdateTransform(const ComputedStyle* old_style,
417                                  const ComputedStyle& new_style) {
418   // It's possible for the old and new style transform data to be equivalent
419   // while hasTransform() differs, as it checks a number of conditions aside
420   // from just the matrix, including but not limited to animation state.
421   if (old_style && old_style->HasTransform() == new_style.HasTransform() &&
422       new_style.TransformDataEquivalent(*old_style)) {
423     return;
424   }
425 
426   // LayoutObject::HasTransformRelatedProperty is also true when there is
427   // transform-style: preserve-3d or perspective set, so check style too.
428   bool has_transform = GetLayoutObject().HasTransformRelatedProperty() &&
429                        new_style.HasTransform();
430   bool had3d_transform = Has3DTransform();
431 
432   bool had_transform = Transform();
433   if (has_transform != had_transform) {
434     if (has_transform)
435       EnsureRareData().transform = std::make_unique<TransformationMatrix>();
436     else
437       rare_data_->transform.reset();
438 
439     // PaintLayers with transforms act as clip rects roots, so clear the cached
440     // clip rects here.
441     ClearClipRects();
442   } else if (has_transform) {
443     ClearClipRects(kAbsoluteClipRectsIgnoringViewportClip);
444   }
445 
446   UpdateTransformationMatrix();
447 
448   if (had3d_transform != Has3DTransform()) {
449     SetNeedsCompositingInputsUpdateInternal();
450     MarkAncestorChainForFlagsUpdate();
451   }
452 
453   if (LocalFrameView* frame_view = GetLayoutObject().GetDocument().View())
454     frame_view->SetNeedsUpdateGeometries();
455 }
456 
CurrentTransform() const457 TransformationMatrix PaintLayer::CurrentTransform() const {
458   if (TransformationMatrix* transform = Transform())
459     return *transform;
460   return TransformationMatrix();
461 }
462 
RenderableTransform(GlobalPaintFlags global_paint_flags) const463 TransformationMatrix PaintLayer::RenderableTransform(
464     GlobalPaintFlags global_paint_flags) const {
465   TransformationMatrix* transform = Transform();
466   if (!transform)
467     return TransformationMatrix();
468 
469   if (global_paint_flags & kGlobalPaintFlattenCompositingLayers) {
470     TransformationMatrix matrix = *transform;
471     MakeMatrixRenderable(matrix, false /* flatten 3d */);
472     return matrix;
473   }
474 
475   return *transform;
476 }
477 
ConvertFromFlowThreadToVisualBoundingBoxInAncestor(const PaintLayer * ancestor_layer,PhysicalRect & rect) const478 void PaintLayer::ConvertFromFlowThreadToVisualBoundingBoxInAncestor(
479     const PaintLayer* ancestor_layer,
480     PhysicalRect& rect) const {
481   PaintLayer* pagination_layer = EnclosingPaginationLayer();
482   DCHECK(pagination_layer);
483   LayoutFlowThread& flow_thread =
484       ToLayoutFlowThread(pagination_layer->GetLayoutObject());
485 
486   // First make the flow thread rectangle relative to the flow thread, not to
487   // |layer|.
488   PhysicalOffset offset_within_pagination_layer;
489   ConvertToLayerCoords(pagination_layer, offset_within_pagination_layer);
490   rect.Move(offset_within_pagination_layer);
491 
492   // Then make the rectangle visual, relative to the fragmentation context.
493   // Split our box up into the actual fragment boxes that layout in the
494   // columns/pages and unite those together to get our true bounding box.
495   rect = PhysicalRectToBeNoop(
496       flow_thread.FragmentsBoundingBox(rect.ToLayoutRect()));
497 
498   // Finally, make the visual rectangle relative to |ancestorLayer|.
499   if (ancestor_layer->EnclosingPaginationLayer() != pagination_layer) {
500     rect.Move(pagination_layer->VisualOffsetFromAncestor(ancestor_layer));
501     return;
502   }
503   // The ancestor layer is inside the same pagination layer as |layer|, so we
504   // need to subtract the visual distance from the ancestor layer to the
505   // pagination layer.
506   rect.Move(-ancestor_layer->VisualOffsetFromAncestor(pagination_layer));
507 }
508 
UpdatePaginationRecursive(bool needs_pagination_update)509 void PaintLayer::UpdatePaginationRecursive(bool needs_pagination_update) {
510   if (rare_data_)
511     rare_data_->enclosing_pagination_layer = nullptr;
512 
513   if (GetLayoutObject().IsLayoutFlowThread())
514     needs_pagination_update = true;
515 
516   if (needs_pagination_update) {
517     // Each paginated layer has to paint on its own. There is no recurring into
518     // child layers. Each layer has to be checked individually and genuinely
519     // know if it is going to have to split itself up when painting only its
520     // contents (and not any other descendant layers). We track an
521     // enclosingPaginationLayer instead of using a simple bit, since we want to
522     // be able to get back to that layer easily.
523     if (LayoutFlowThread* containing_flow_thread =
524             GetLayoutObject().FlowThreadContainingBlock())
525       EnsureRareData().enclosing_pagination_layer =
526           containing_flow_thread->Layer();
527   }
528 
529   // If this element prevents child painting, then we can skip updating
530   // pagination info, since it won't be used anyway.
531   if (GetLayoutObject().PaintBlockedByDisplayLock(
532           DisplayLockLifecycleTarget::kChildren)) {
533     return;
534   }
535 
536   for (PaintLayer* child = FirstChild(); child; child = child->NextSibling())
537     child->UpdatePaginationRecursive(needs_pagination_update);
538 }
539 
ClearPaginationRecursive()540 void PaintLayer::ClearPaginationRecursive() {
541   if (rare_data_)
542     rare_data_->enclosing_pagination_layer = nullptr;
543   for (PaintLayer* child = FirstChild(); child; child = child->NextSibling())
544     child->ClearPaginationRecursive();
545 }
546 
TransformAncestorOrRoot() const547 const PaintLayer& PaintLayer::TransformAncestorOrRoot() const {
548   return TransformAncestor() ? *TransformAncestor()
549                              : *GetLayoutObject().View()->Layer();
550 }
551 
MapPointInPaintInvalidationContainerToBacking(const LayoutBoxModelObject & paint_invalidation_container,PhysicalOffset & point)552 void PaintLayer::MapPointInPaintInvalidationContainerToBacking(
553     const LayoutBoxModelObject& paint_invalidation_container,
554     PhysicalOffset& point) {
555   PaintLayer* paint_invalidation_layer = paint_invalidation_container.Layer();
556   if (!paint_invalidation_layer->GroupedMapping())
557     return;
558 
559   GraphicsLayer* squashing_layer =
560       paint_invalidation_layer->GroupedMapping()->SquashingLayer();
561 
562   PropertyTreeState source_state =
563       paint_invalidation_container.FirstFragment().LocalBorderBoxProperties();
564   PropertyTreeState dest_state = squashing_layer->GetPropertyTreeState();
565 
566   // Move the point into the source_state transform space, map to dest_state
567   // transform space, then move into squashing layer state.
568   point += paint_invalidation_container.FirstFragment().PaintOffset();
569   point = PhysicalOffset::FromFloatPointRound(
570       GeometryMapper::SourceToDestinationProjection(source_state.Transform(),
571                                                     dest_state.Transform())
572           .MapPoint(FloatPoint(point)));
573   point -= PhysicalOffset(squashing_layer->GetOffsetFromTransformNode());
574 }
575 
MapQuadInPaintInvalidationContainerToBacking(const LayoutBoxModelObject & paint_invalidation_container,FloatQuad & quad)576 void PaintLayer::MapQuadInPaintInvalidationContainerToBacking(
577     const LayoutBoxModelObject& paint_invalidation_container,
578     FloatQuad& quad) {
579   PaintLayer* paint_invalidation_layer = paint_invalidation_container.Layer();
580   if (!paint_invalidation_layer->GroupedMapping())
581     return;
582 
583   GraphicsLayer* squashing_layer =
584       paint_invalidation_layer->GroupedMapping()->SquashingLayer();
585 
586   PropertyTreeState source_state =
587       paint_invalidation_container.FirstFragment().LocalBorderBoxProperties();
588   PropertyTreeState dest_state = squashing_layer->GetPropertyTreeState();
589 
590   // Move the rect into the source_state transform space, map to dest_state
591   // transform space, then move into squashing layer state.
592   quad.Move(
593       FloatSize(paint_invalidation_container.FirstFragment().PaintOffset()));
594   GeometryMapper::SourceToDestinationProjection(source_state.Transform(),
595                                                 dest_state.Transform())
596       .MapQuad(quad);
597   quad.Move(
598       -ToFloatSize(FloatPoint(squashing_layer->GetOffsetFromTransformNode())));
599 }
600 
DirtyVisibleContentStatus()601 void PaintLayer::DirtyVisibleContentStatus() {
602   MarkAncestorChainForFlagsUpdate();
603   // Non-self-painting layers paint into their ancestor layer, and count as part
604   // of the "visible contents" of the parent, so we need to dirty it.
605   if (!IsSelfPaintingLayer())
606     Parent()->DirtyVisibleContentStatus();
607 }
608 
MarkAncestorChainForFlagsUpdate(DescendantDependentFlagsUpdateFlag flag)609 void PaintLayer::MarkAncestorChainForFlagsUpdate(
610     DescendantDependentFlagsUpdateFlag flag) {
611 #if DCHECK_IS_ON()
612   DCHECK(flag == DoesNotNeedDescendantDependentUpdate ||
613          !layout_object_.GetDocument()
614               .View()
615               ->IsUpdatingDescendantDependentFlags());
616 #endif
617   for (PaintLayer* layer = this; layer; layer = layer->Parent()) {
618     if (layer->needs_descendant_dependent_flags_update_ &&
619         layer->GetLayoutObject().NeedsPaintPropertyUpdate())
620       break;
621     if (flag == NeedsDescendantDependentUpdate)
622       layer->needs_descendant_dependent_flags_update_ = true;
623     layer->GetLayoutObject().SetNeedsPaintPropertyUpdate();
624   }
625 }
626 
UpdateDescendantDependentFlags()627 void PaintLayer::UpdateDescendantDependentFlags() {
628   if (needs_descendant_dependent_flags_update_) {
629     bool old_has_non_isolated_descendant_with_blend_mode =
630         has_non_isolated_descendant_with_blend_mode_;
631     has_visible_descendant_ = false;
632     has_non_isolated_descendant_with_blend_mode_ = false;
633     has_descendant_with_clip_path_ = false;
634     has_fixed_position_descendant_ = false;
635     has_sticky_position_descendant_ = false;
636     has_non_contained_absolute_position_descendant_ = false;
637     has_stacked_descendant_in_current_stacking_context_ = false;
638     has_self_painting_layer_descendant_ = false;
639 
640     bool can_contain_abs =
641         GetLayoutObject().CanContainAbsolutePositionObjects();
642 
643     for (PaintLayer* child = FirstChild(); child;
644          child = child->NextSibling()) {
645       const ComputedStyle& child_style = child->GetLayoutObject().StyleRef();
646 
647       child->UpdateDescendantDependentFlags();
648 
649       if (child->has_visible_content_ || child->has_visible_descendant_)
650         has_visible_descendant_ = true;
651 
652       has_non_isolated_descendant_with_blend_mode_ |=
653           (!child_style.IsStackingContext() &&
654            child->HasNonIsolatedDescendantWithBlendMode()) ||
655           child_style.HasBlendMode();
656 
657       has_descendant_with_clip_path_ |= child->HasDescendantWithClipPath() ||
658                                         child->GetLayoutObject().HasClipPath();
659 
660       has_fixed_position_descendant_ |=
661           child->HasFixedPositionDescendant() ||
662           child_style.GetPosition() == EPosition::kFixed;
663       has_sticky_position_descendant_ |=
664           child->HasStickyPositionDescendant() ||
665           child_style.GetPosition() == EPosition::kSticky;
666 
667       if (!can_contain_abs) {
668         has_non_contained_absolute_position_descendant_ |=
669             (child->HasNonContainedAbsolutePositionDescendant() ||
670              child_style.GetPosition() == EPosition::kAbsolute);
671       }
672 
673       if (!has_stacked_descendant_in_current_stacking_context_) {
674         if (child_style.IsStacked()) {
675           has_stacked_descendant_in_current_stacking_context_ = true;
676         } else if (!child_style.IsStackingContext()) {
677           has_stacked_descendant_in_current_stacking_context_ =
678               child->has_stacked_descendant_in_current_stacking_context_;
679         }
680       }
681 
682       has_self_painting_layer_descendant_ =
683           has_self_painting_layer_descendant_ ||
684           child->HasSelfPaintingLayerDescendant() ||
685           child->IsSelfPaintingLayer();
686     }
687 
688     UpdateStackingNode();
689 
690     if (old_has_non_isolated_descendant_with_blend_mode !=
691         static_cast<bool>(has_non_isolated_descendant_with_blend_mode_)) {
692       // The LayoutView DisplayItemClient owns painting of the background
693       // of the HTML element. When blending isolation of the HTML element's
694       // descendants change, there will be an addition or removal of an
695       // isolation effect node for the HTML element to add (or remove)
696       // isolated blending, and that case we need to re-paint the LayoutView.
697       if (Parent() && Parent()->IsRootLayer())
698         GetLayoutObject().View()->SetBackgroundNeedsFullPaintInvalidation();
699       GetLayoutObject().SetNeedsPaintPropertyUpdate();
700     }
701     needs_descendant_dependent_flags_update_ = false;
702 
703     if (IsSelfPaintingLayer() && needs_visual_overflow_recalc_) {
704       auto old_visual_rect = GetLayoutObject().PhysicalVisualOverflowRect();
705       GetLayoutObject().RecalcVisualOverflow();
706       if (old_visual_rect != GetLayoutObject().PhysicalVisualOverflowRect()) {
707         SetNeedsCompositingInputsUpdateInternal();
708         MarkAncestorChainForFlagsUpdate(DoesNotNeedDescendantDependentUpdate);
709       }
710     }
711     needs_visual_overflow_recalc_ = false;
712   }
713 
714   bool previously_has_visible_content = has_visible_content_;
715   if (GetLayoutObject().StyleRef().Visibility() == EVisibility::kVisible) {
716     has_visible_content_ = true;
717   } else {
718     // layer may be hidden but still have some visible content, check for this
719     has_visible_content_ = false;
720     LayoutObject* r = GetLayoutObject().SlowFirstChild();
721     while (r) {
722       if (r->StyleRef().Visibility() == EVisibility::kVisible &&
723           (!r->HasLayer() || !r->EnclosingLayer()->IsSelfPaintingLayer())) {
724         has_visible_content_ = true;
725         break;
726       }
727       LayoutObject* layout_object_first_child = r->SlowFirstChild();
728       if (layout_object_first_child &&
729           (!r->HasLayer() || !r->EnclosingLayer()->IsSelfPaintingLayer())) {
730         r = layout_object_first_child;
731       } else if (r->NextSibling()) {
732         r = r->NextSibling();
733       } else {
734         do {
735           r = r->Parent();
736           if (r == &GetLayoutObject())
737             r = nullptr;
738         } while (r && !r->NextSibling());
739         if (r)
740           r = r->NextSibling();
741       }
742     }
743   }
744 
745   if (HasVisibleContent() != previously_has_visible_content) {
746     SetNeedsCompositingInputsUpdateInternal();
747     // We need to tell layout_object_ to recheck its rect because we
748     // pretend that invisible LayoutObjects have 0x0 rects. Changing
749     // visibility therefore changes our rect and we need to visit
750     // this LayoutObject during the PrePaintTreeWalk.
751     layout_object_.SetShouldCheckForPaintInvalidation();
752   }
753 
754   Update3DTransformedDescendantStatus();
755 }
756 
Update3DTransformedDescendantStatus()757 void PaintLayer::Update3DTransformedDescendantStatus() {
758   has3d_transformed_descendant_ = false;
759 
760   // Transformed or preserve-3d descendants can only be in the z-order lists,
761   // not in the normal flow list, so we only need to check those.
762   PaintLayerPaintOrderIterator iterator(*this, kStackedChildren);
763   while (PaintLayer* child_layer = iterator.Next()) {
764     bool child_has3d = false;
765     // If the child lives in a 3d hierarchy, then the layer at the root of
766     // that hierarchy needs the m_has3DTransformedDescendant set.
767     if (child_layer->Preserves3D() &&
768         (child_layer->Has3DTransform() ||
769          child_layer->Has3DTransformedDescendant()))
770       child_has3d = true;
771     else if (child_layer->Has3DTransform())
772       child_has3d = true;
773 
774     if (child_has3d) {
775       has3d_transformed_descendant_ = true;
776       break;
777     }
778   }
779 }
780 
UpdateLayerPosition()781 void PaintLayer::UpdateLayerPosition() {
782   // LayoutBoxes will call UpdateSizeAndScrollingAfterLayout() from
783   // LayoutBox::UpdateAfterLayout, but LayoutInlines will still need to update
784   // their size.
785   if (GetLayoutObject().IsLayoutInline())
786     UpdateSize();
787   PhysicalOffset local_point;
788   if (LayoutBox* box = GetLayoutBox()) {
789     local_point += box->PhysicalLocation();
790   }
791 
792   if (!GetLayoutObject().IsOutOfFlowPositioned() &&
793       !GetLayoutObject().IsColumnSpanAll()) {
794     // We must adjust our position by walking up the layout tree looking for the
795     // nearest enclosing object with a layer.
796     LayoutObject* curr = GetLayoutObject().Container();
797     while (curr && !curr->HasLayer()) {
798       if (curr->IsBox() && !curr->IsTableRow()) {
799         // Rows and cells share the same coordinate space (that of the section).
800         // Omit them when computing our xpos/ypos.
801         local_point += ToLayoutBox(curr)->PhysicalLocation();
802       }
803       curr = curr->Container();
804     }
805     if (curr && curr->IsTableRow()) {
806       // Put ourselves into the row coordinate space.
807       local_point -= ToLayoutBox(curr)->PhysicalLocation();
808     }
809   }
810 
811   if (PaintLayer* containing_layer = ContainingLayer()) {
812     auto& container = containing_layer->GetLayoutObject();
813     if (GetLayoutObject().IsOutOfFlowPositioned() &&
814         container.IsLayoutInline() &&
815         container.CanContainOutOfFlowPositionedElement(
816             GetLayoutObject().StyleRef().GetPosition())) {
817       // Adjust offset for absolute under in-flow positioned inline.
818       PhysicalOffset offset =
819           ToLayoutInline(container).OffsetForInFlowPositionedInline(
820               ToLayoutBox(GetLayoutObject()));
821       local_point += offset;
822     }
823   }
824 
825   if (GetLayoutObject().IsInFlowPositioned() &&
826       GetLayoutObject().IsRelPositioned()) {
827     auto new_offset = GetLayoutObject().OffsetForInFlowPosition();
828     if (rare_data_ || !new_offset.IsZero())
829       EnsureRareData().offset_for_in_flow_rel_position = new_offset;
830   } else if (rare_data_) {
831     rare_data_->offset_for_in_flow_rel_position = PhysicalOffset();
832   }
833   location_without_position_offset_ = local_point;
834 
835 #if DCHECK_IS_ON()
836   needs_position_update_ = false;
837 #endif
838 }
839 
UpdateSize()840 bool PaintLayer::UpdateSize() {
841   LayoutSize old_size = size_;
842   if (IsRootLayer()) {
843     size_ = LayoutSize(GetLayoutObject().GetDocument().View()->Size());
844   } else if (GetLayoutObject().IsInline() &&
845              GetLayoutObject().IsLayoutInline()) {
846     LayoutInline& inline_flow = ToLayoutInline(GetLayoutObject());
847     IntRect line_box = EnclosingIntRect(inline_flow.PhysicalLinesBoundingBox());
848     size_ = LayoutSize(line_box.Size());
849   } else if (LayoutBox* box = GetLayoutBox()) {
850     size_ = box->Size();
851   }
852   if (old_size != size_)
853     SetNeedsCompositingInputsUpdate();
854 
855   return old_size != size_;
856 }
857 
UpdateSizeAndScrollingAfterLayout()858 void PaintLayer::UpdateSizeAndScrollingAfterLayout() {
859   bool did_resize = UpdateSize();
860   if (RequiresScrollableArea()) {
861     DCHECK(scrollable_area_);
862     scrollable_area_->UpdateAfterLayout();
863     if (did_resize)
864       scrollable_area_->VisibleSizeChanged();
865   }
866 }
867 
PerspectiveOrigin() const868 FloatPoint PaintLayer::PerspectiveOrigin() const {
869   if (!GetLayoutObject().HasTransformRelatedProperty())
870     return FloatPoint();
871 
872   const LayoutRect border_box = ToLayoutBox(GetLayoutObject()).BorderBoxRect();
873   const ComputedStyle& style = GetLayoutObject().StyleRef();
874 
875   return FloatPointForLengthPoint(style.PerspectiveOrigin(),
876                                   FloatSize(border_box.Size()));
877 }
878 
ContainingLayer(const PaintLayer * ancestor,bool * skipped_ancestor) const879 PaintLayer* PaintLayer::ContainingLayer(const PaintLayer* ancestor,
880                                         bool* skipped_ancestor) const {
881   // If we have specified an ancestor, surely the caller needs to know whether
882   // we skipped it.
883   DCHECK(!ancestor || skipped_ancestor);
884   if (skipped_ancestor)
885     *skipped_ancestor = false;
886 
887   LayoutObject& layout_object = GetLayoutObject();
888   if (layout_object.IsOutOfFlowPositioned()) {
889     auto can_contain_this_layer =
890         layout_object.IsFixedPositioned()
891             ? &LayoutObject::CanContainFixedPositionObjects
892             : &LayoutObject::CanContainAbsolutePositionObjects;
893 
894     PaintLayer* curr = Parent();
895     while (curr && !((&curr->GetLayoutObject())->*can_contain_this_layer)()) {
896       if (skipped_ancestor && curr == ancestor)
897         *skipped_ancestor = true;
898       curr = curr->Parent();
899     }
900     return curr;
901   }
902 
903   // If the parent layer is not a block, there might be floating objects
904   // between this layer (included) and parent layer which need to escape the
905   // inline parent to find the actual containing layer through the containing
906   // block chain.
907   // Column span need to find the containing layer through its containing block.
908   if ((!Parent() || Parent()->GetLayoutObject().IsLayoutBlock()) &&
909       !layout_object.IsColumnSpanAll())
910     return Parent();
911 
912   // This is a universal approach to find containing layer, but is slower than
913   // the earlier code.
914   base::Optional<LayoutObject::AncestorSkipInfo> skip_info;
915   if (skipped_ancestor)
916     skip_info.emplace(&ancestor->GetLayoutObject());
917   auto* object = &layout_object;
918   while (auto* container =
919              object->Container(skipped_ancestor ? &*skip_info : nullptr)) {
920     if (skipped_ancestor && skip_info->AncestorSkipped())
921       *skipped_ancestor = true;
922     if (container->HasLayer())
923       return ToLayoutBoxModelObject(container)->Layer();
924     object = container;
925   }
926   return nullptr;
927 }
928 
ComputeOffsetFromAncestor(const PaintLayer & ancestor_layer) const929 PhysicalOffset PaintLayer::ComputeOffsetFromAncestor(
930     const PaintLayer& ancestor_layer) const {
931   const LayoutBoxModelObject& ancestor_object =
932       ancestor_layer.GetLayoutObject();
933   PhysicalOffset result = GetLayoutObject().LocalToAncestorPoint(
934       PhysicalOffset(), &ancestor_object, kIgnoreTransforms);
935   if (ancestor_object.UsesCompositedScrolling()) {
936     result += PhysicalOffset(
937         ToLayoutBox(ancestor_object).PixelSnappedScrolledContentOffset());
938   }
939   return result;
940 }
941 
CompositingContainer() const942 PaintLayer* PaintLayer::CompositingContainer() const {
943   if (IsReplacedNormalFlowStacking())
944     return Parent();
945   if (!GetLayoutObject().StyleRef().IsStacked()) {
946     if (IsSelfPaintingLayer() || GetLayoutObject().IsColumnSpanAll())
947       return Parent();
948     return ContainingLayer();
949   }
950   return AncestorStackingContext();
951 }
952 
AncestorStackingContext() const953 PaintLayer* PaintLayer::AncestorStackingContext() const {
954   for (PaintLayer* ancestor = Parent(); ancestor;
955        ancestor = ancestor->Parent()) {
956     if (ancestor->GetLayoutObject().StyleRef().IsStackingContext())
957       return ancestor;
958   }
959   return nullptr;
960 }
961 
IsPaintInvalidationContainer() const962 bool PaintLayer::IsPaintInvalidationContainer() const {
963   return GetCompositingState() == kPaintsIntoOwnBacking ||
964          GetCompositingState() == kPaintsIntoGroupedBacking;
965 }
966 
967 // Note: enclosingCompositingLayer does not include squashed layers. Compositing
968 // stacking children of squashed layers receive graphics layers that are
969 // parented to the compositing ancestor of the squashed layer.
EnclosingLayerWithCompositedLayerMapping(IncludeSelfOrNot include_self) const970 PaintLayer* PaintLayer::EnclosingLayerWithCompositedLayerMapping(
971     IncludeSelfOrNot include_self) const {
972   DCHECK(IsAllowedToQueryCompositingState());
973 
974   if ((include_self == kIncludeSelf) &&
975       GetCompositingState() != kNotComposited &&
976       GetCompositingState() != kPaintsIntoGroupedBacking)
977     return const_cast<PaintLayer*>(this);
978 
979   for (PaintLayer* curr = CompositingContainer(); curr;
980        curr = curr->CompositingContainer()) {
981     if (curr->GetCompositingState() != kNotComposited &&
982         curr->GetCompositingState() != kPaintsIntoGroupedBacking)
983       return curr;
984   }
985 
986   return nullptr;
987 }
988 
989 // Return the enclosingCompositedLayerForPaintInvalidation for the given Layer
990 // including crossing frame boundaries.
991 PaintLayer*
EnclosingLayerForPaintInvalidationCrossingFrameBoundaries() const992 PaintLayer::EnclosingLayerForPaintInvalidationCrossingFrameBoundaries() const {
993   const PaintLayer* layer = this;
994   PaintLayer* composited_layer = nullptr;
995   while (!composited_layer) {
996     composited_layer = layer->EnclosingLayerForPaintInvalidation();
997     if (!composited_layer) {
998       CHECK(layer->GetLayoutObject().GetFrame());
999       auto* owner = layer->GetLayoutObject().GetFrame()->OwnerLayoutObject();
1000       if (!owner)
1001         break;
1002       layer = owner->EnclosingLayer();
1003     }
1004   }
1005   return composited_layer;
1006 }
1007 
EnclosingLayerForPaintInvalidation() const1008 PaintLayer* PaintLayer::EnclosingLayerForPaintInvalidation() const {
1009   DCHECK(IsAllowedToQueryCompositingState());
1010 
1011   if (IsPaintInvalidationContainer())
1012     return const_cast<PaintLayer*>(this);
1013 
1014   for (PaintLayer* curr = CompositingContainer(); curr;
1015        curr = curr->CompositingContainer()) {
1016     if (curr->IsPaintInvalidationContainer())
1017       return curr;
1018   }
1019 
1020   return nullptr;
1021 }
1022 
SetNeedsCompositingInputsUpdate(bool mark_ancestor_flags)1023 void PaintLayer::SetNeedsCompositingInputsUpdate(bool mark_ancestor_flags) {
1024   SetNeedsCompositingInputsUpdateInternal();
1025 
1026   // TODO(chrishtr): These are a bit of a heavy hammer, because not all
1027   // things which require compositing inputs update require a descendant-
1028   // dependent flags update. Reduce call sites after CAP launch allows
1029   /// removal of CompositingInputsUpdater.
1030   if (mark_ancestor_flags)
1031     MarkAncestorChainForFlagsUpdate(NeedsDescendantDependentUpdate);
1032 }
1033 
SetNeedsVisualOverflowRecalc()1034 void PaintLayer::SetNeedsVisualOverflowRecalc() {
1035   DCHECK(IsSelfPaintingLayer());
1036   needs_visual_overflow_recalc_ = true;
1037   MarkAncestorChainForFlagsUpdate();
1038 }
1039 
SetChildNeedsCompositingInputsUpdateUpToAncestor(PaintLayer * ancestor)1040 void PaintLayer::SetChildNeedsCompositingInputsUpdateUpToAncestor(
1041     PaintLayer* ancestor) {
1042   DCHECK(ancestor);
1043 
1044   for (auto* layer = this; layer && layer != ancestor; layer = layer->Parent())
1045     layer->child_needs_compositing_inputs_update_ = true;
1046 
1047   ancestor->child_needs_compositing_inputs_update_ = true;
1048 }
1049 
SetNeedsCompositingInputsUpdateInternal()1050 void PaintLayer::SetNeedsCompositingInputsUpdateInternal() {
1051   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
1052     return;
1053 
1054   needs_ancestor_dependent_compositing_inputs_update_ = true;
1055 
1056   // We might call this function on a locked element. Now, locked elements might
1057   // have a persistent dirty child bit, meaning that the below loop won't mark
1058   // the breakcrumb bit further up the chain (since this element appears to
1059   // already have a breadcrumb). However, since the element itself needs an
1060   // ancestor dependent update, we need to force the propagation at least one
1061   // level to the parent. This ensures that the real dirty bit
1062   // (|needs_ancestor_dependent_compositing_inputs_update_|) can be discovered
1063   // by the compositing update walk.
1064   bool child_flag_may_persist_after_update =
1065       GetLayoutObject().PrePaintBlockedByDisplayLock(
1066           DisplayLockLifecycleTarget::kChildren);
1067 
1068   PaintLayer* initial_layer = child_needs_compositing_inputs_update_ &&
1069                                       child_flag_may_persist_after_update
1070                                   ? Parent()
1071                                   : this;
1072 
1073   PaintLayer* last_ancestor = nullptr;
1074   for (PaintLayer* current = initial_layer;
1075        current && !current->child_needs_compositing_inputs_update_;
1076        current = current->Parent()) {
1077     last_ancestor = current;
1078     current->child_needs_compositing_inputs_update_ = true;
1079     if (Compositor() &&
1080         (current != initial_layer ||
1081          !current->GetLayoutObject().IsStickyPositioned()) &&
1082         current->GetLayoutObject().ShouldApplyStrictContainment())
1083       break;
1084   }
1085 
1086   if (Compositor()) {
1087     Compositor()->SetNeedsCompositingUpdate(
1088         kCompositingUpdateAfterCompositingInputChange);
1089 
1090     if (last_ancestor)
1091       Compositor()->UpdateCompositingInputsRoot(last_ancestor);
1092   }
1093 }
1094 
UpdateAncestorDependentCompositingInputs(const AncestorDependentCompositingInputs & compositing_inputs)1095 void PaintLayer::UpdateAncestorDependentCompositingInputs(
1096     const AncestorDependentCompositingInputs& compositing_inputs) {
1097   DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
1098   EnsureAncestorDependentCompositingInputs() = compositing_inputs;
1099   needs_ancestor_dependent_compositing_inputs_update_ = false;
1100 }
1101 
ClearChildNeedsCompositingInputsUpdate()1102 void PaintLayer::ClearChildNeedsCompositingInputsUpdate() {
1103   DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
1104   DCHECK(!NeedsCompositingInputsUpdate());
1105   child_needs_compositing_inputs_update_ = false;
1106 }
1107 
HasNonIsolatedDescendantWithBlendMode() const1108 bool PaintLayer::HasNonIsolatedDescendantWithBlendMode() const {
1109   DCHECK(!needs_descendant_dependent_flags_update_);
1110   if (has_non_isolated_descendant_with_blend_mode_)
1111     return true;
1112   if (GetLayoutObject().IsSVGRoot())
1113     return ToLayoutSVGRoot(GetLayoutObject())
1114         .HasNonIsolatedBlendingDescendants();
1115   return false;
1116 }
1117 
SetCompositingReasons(CompositingReasons reasons,CompositingReasons mask)1118 void PaintLayer::SetCompositingReasons(CompositingReasons reasons,
1119                                        CompositingReasons mask) {
1120   CompositingReasons old_reasons =
1121       rare_data_ ? rare_data_->compositing_reasons : CompositingReason::kNone;
1122   if ((old_reasons & mask) == (reasons & mask))
1123     return;
1124   CompositingReasons new_reasons = (reasons & mask) | (old_reasons & ~mask);
1125   if (rare_data_ || new_reasons != CompositingReason::kNone)
1126     EnsureRareData().compositing_reasons = new_reasons;
1127 }
1128 
SetSquashingDisallowedReasons(SquashingDisallowedReasons reasons)1129 void PaintLayer::SetSquashingDisallowedReasons(
1130     SquashingDisallowedReasons reasons) {
1131   SquashingDisallowedReasons old_reasons =
1132       rare_data_ ? rare_data_->squashing_disallowed_reasons
1133                  : SquashingDisallowedReason::kNone;
1134   if (old_reasons == reasons)
1135     return;
1136   if (rare_data_ || reasons != SquashingDisallowedReason::kNone)
1137     EnsureRareData().squashing_disallowed_reasons = reasons;
1138 }
1139 
SetHasCompositingDescendant(bool has_compositing_descendant)1140 void PaintLayer::SetHasCompositingDescendant(bool has_compositing_descendant) {
1141   if (has_compositing_descendant_ ==
1142       static_cast<unsigned>(has_compositing_descendant))
1143     return;
1144 
1145   has_compositing_descendant_ = has_compositing_descendant;
1146 
1147   if (HasCompositedLayerMapping())
1148     GetCompositedLayerMapping()->SetNeedsGraphicsLayerUpdate(
1149         kGraphicsLayerUpdateLocal);
1150 }
1151 
SetShouldIsolateCompositedDescendants(bool should_isolate_composited_descendants)1152 void PaintLayer::SetShouldIsolateCompositedDescendants(
1153     bool should_isolate_composited_descendants) {
1154   if (should_isolate_composited_descendants_ ==
1155       static_cast<unsigned>(should_isolate_composited_descendants))
1156     return;
1157 
1158   should_isolate_composited_descendants_ =
1159       should_isolate_composited_descendants;
1160 
1161   if (HasCompositedLayerMapping())
1162     GetCompositedLayerMapping()->SetNeedsGraphicsLayerUpdate(
1163         kGraphicsLayerUpdateLocal);
1164 }
1165 
HasAncestorWithFilterThatMovesPixels() const1166 bool PaintLayer::HasAncestorWithFilterThatMovesPixels() const {
1167   for (const PaintLayer* curr = this; curr; curr = curr->Parent()) {
1168     if (curr->HasFilterThatMovesPixels())
1169       return true;
1170   }
1171   return false;
1172 }
1173 
operator new(size_t sz)1174 void* PaintLayer::operator new(size_t sz) {
1175   return WTF::Partitions::LayoutPartition()->Alloc(
1176       sz, WTF_HEAP_PROFILER_TYPE_NAME(PaintLayer));
1177 }
1178 
operator delete(void * ptr)1179 void PaintLayer::operator delete(void* ptr) {
1180   base::PartitionFree(ptr);
1181 }
1182 
AddChild(PaintLayer * child,PaintLayer * before_child)1183 void PaintLayer::AddChild(PaintLayer* child, PaintLayer* before_child) {
1184 #if DCHECK_IS_ON()
1185   DCHECK(layer_list_mutation_allowed_);
1186 #endif
1187 
1188   PaintLayer* prev_sibling =
1189       before_child ? before_child->PreviousSibling() : LastChild();
1190   if (prev_sibling) {
1191     child->SetPreviousSibling(prev_sibling);
1192     prev_sibling->SetNextSibling(child);
1193     DCHECK_NE(prev_sibling, child);
1194   } else {
1195     SetFirstChild(child);
1196   }
1197 
1198   if (before_child) {
1199     before_child->SetPreviousSibling(child);
1200     child->SetNextSibling(before_child);
1201     DCHECK_NE(before_child, child);
1202   } else {
1203     SetLastChild(child);
1204   }
1205 
1206   child->parent_ = this;
1207 
1208   // The ancestor overflow layer is calculated during compositing inputs update
1209   // and should not be set yet.
1210   CHECK(!child->AncestorOverflowLayer());
1211 
1212   SetNeedsCompositingInputsUpdate();
1213 
1214   const ComputedStyle& child_style = child->GetLayoutObject().StyleRef();
1215 
1216   if (Compositor()) {
1217     if (!child_style.IsStacked() && !GetLayoutObject().DocumentBeingDestroyed())
1218       Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
1219   }
1220 
1221   if (child_style.IsStacked() || child->FirstChild()) {
1222     // Dirty the z-order list in which we are contained. The
1223     // ancestorStackingContextNode() can be null in the case where we're
1224     // building up generated content layers. This is ok, since the lists will
1225     // start off dirty in that case anyway.
1226     child->DirtyStackingContextZOrderLists();
1227   }
1228 
1229   // Non-self-painting children paint into this layer, so the visible contents
1230   // status of this layer is affected.
1231   if (!child->IsSelfPaintingLayer())
1232     DirtyVisibleContentStatus();
1233 
1234   MarkAncestorChainForFlagsUpdate();
1235 
1236   // Need to force requirements update, due to change of stacking order.
1237   SetNeedsCompositingRequirementsUpdate();
1238 
1239   child->SetNeedsRepaint();
1240 }
1241 
RemoveChild(PaintLayer * old_child)1242 void PaintLayer::RemoveChild(PaintLayer* old_child) {
1243 #if DCHECK_IS_ON()
1244   DCHECK(layer_list_mutation_allowed_);
1245 #endif
1246 
1247   old_child->MarkCompositingContainerChainForNeedsRepaint();
1248 
1249   if (old_child->PreviousSibling())
1250     old_child->PreviousSibling()->SetNextSibling(old_child->NextSibling());
1251   if (old_child->NextSibling())
1252     old_child->NextSibling()->SetPreviousSibling(old_child->PreviousSibling());
1253 
1254   if (first_ == old_child)
1255     first_ = old_child->NextSibling();
1256   if (last_ == old_child)
1257     last_ = old_child->PreviousSibling();
1258 
1259   const ComputedStyle& old_child_style =
1260       old_child->GetLayoutObject().StyleRef();
1261 
1262   if (!GetLayoutObject().DocumentBeingDestroyed()) {
1263     if (Compositor()) {
1264       if (!old_child_style.IsStacked())
1265         Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
1266 
1267       if (Compositor()->GetCompositingInputsRoot() == old_child)
1268         Compositor()->ClearCompositingInputsRoot();
1269     }
1270     // Dirty the z-order list in which we are contained.
1271     old_child->DirtyStackingContextZOrderLists();
1272     SetNeedsCompositingInputsUpdate();
1273   }
1274 
1275   if (GetLayoutObject().StyleRef().Visibility() != EVisibility::kVisible)
1276     DirtyVisibleContentStatus();
1277 
1278   old_child->SetPreviousSibling(nullptr);
1279   old_child->SetNextSibling(nullptr);
1280   old_child->parent_ = nullptr;
1281 
1282   // Remove any ancestor overflow layers which descended into the removed child.
1283   if (old_child->AncestorOverflowLayer())
1284     old_child->RemoveAncestorOverflowLayer(old_child->AncestorOverflowLayer());
1285 
1286   if (old_child->has_visible_content_ || old_child->has_visible_descendant_)
1287     MarkAncestorChainForFlagsUpdate();
1288 
1289   if (old_child->EnclosingPaginationLayer())
1290     old_child->ClearPaginationRecursive();
1291 }
1292 
ClearClipRects(ClipRectsCacheSlot cache_slot)1293 void PaintLayer::ClearClipRects(ClipRectsCacheSlot cache_slot) {
1294   Clipper(GeometryMapperOption::kDoNotUseGeometryMapper)
1295       .ClearClipRectsIncludingDescendants(cache_slot);
1296 }
1297 
RemoveOnlyThisLayerAfterStyleChange(const ComputedStyle * old_style)1298 void PaintLayer::RemoveOnlyThisLayerAfterStyleChange(
1299     const ComputedStyle* old_style) {
1300   if (!parent_)
1301     return;
1302 
1303   if (old_style && old_style->IsStacked())
1304     DirtyStackingContextZOrderLists();
1305 
1306   bool did_set_paint_invalidation = false;
1307   if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
1308     // Destructing PaintLayer would cause CompositedLayerMapping and composited
1309     // layers to be destructed and detach from layer tree immediately. Layers
1310     // could have dangling scroll/clip parent if compositing update were
1311     // omitted.
1312     if (LocalFrameView* frame_view = layout_object_.GetDocument().View())
1313       frame_view->SetNeedsForcedCompositingUpdate();
1314 
1315     // We need the current compositing status.
1316     DisableCompositingQueryAsserts disabler;
1317     if (IsPaintInvalidationContainer()) {
1318       // Our children will be reparented and contained by a new paint
1319       // invalidation container, so need paint invalidation. CompositingUpdate
1320       // can't see this layer (which has been removed) so won't do this for us.
1321       ObjectPaintInvalidator(GetLayoutObject())
1322           .InvalidatePaintIncludingNonCompositingDescendants();
1323       GetLayoutObject().SetSubtreeShouldDoFullPaintInvalidation();
1324       did_set_paint_invalidation = true;
1325     }
1326   }
1327 
1328   if (!did_set_paint_invalidation && IsSelfPaintingLayer()) {
1329     if (PaintLayer* enclosing_self_painting_layer =
1330             parent_->EnclosingSelfPaintingLayer())
1331       enclosing_self_painting_layer->MergeNeedsPaintPhaseFlagsFrom(*this);
1332   }
1333 
1334   ClearClipRects();
1335 
1336   PaintLayer* next_sib = NextSibling();
1337 
1338   // Now walk our kids and reattach them to our parent.
1339   PaintLayer* current = first_;
1340   while (current) {
1341     PaintLayer* next = current->NextSibling();
1342     RemoveChild(current);
1343     parent_->AddChild(current, next_sib);
1344 
1345     // FIXME: We should call a specialized version of this function.
1346     current->UpdateLayerPositionsAfterLayout();
1347     current = next;
1348   }
1349 
1350   // Remove us from the parent.
1351   parent_->RemoveChild(this);
1352   layout_object_.DestroyLayer();
1353 }
1354 
InsertOnlyThisLayerAfterStyleChange()1355 void PaintLayer::InsertOnlyThisLayerAfterStyleChange() {
1356   if (!parent_ && GetLayoutObject().Parent()) {
1357     // We need to connect ourselves when our layoutObject() has a parent.
1358     // Find our enclosingLayer and add ourselves.
1359     PaintLayer* parent_layer = GetLayoutObject().Parent()->EnclosingLayer();
1360     DCHECK(parent_layer);
1361     PaintLayer* before_child = GetLayoutObject().Parent()->FindNextLayer(
1362         parent_layer, &GetLayoutObject());
1363     parent_layer->AddChild(this, before_child);
1364   }
1365 
1366   // Remove all descendant layers from the hierarchy and add them to the new
1367   // position.
1368   for (LayoutObject* curr = GetLayoutObject().SlowFirstChild(); curr;
1369        curr = curr->NextSibling())
1370     curr->MoveLayers(parent_, this);
1371 
1372   // If the previous paint invalidation container is not a stacking context and
1373   // this object is stacked content, creating this layer may cause this object
1374   // and its descendants to change paint invalidation container.
1375   bool did_set_paint_invalidation = false;
1376   if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
1377       !IsA<LayoutView>(GetLayoutObject()) && GetLayoutObject().IsRooted() &&
1378       GetLayoutObject().StyleRef().IsStacked()) {
1379     const LayoutBoxModelObject& previous_paint_invalidation_container =
1380         GetLayoutObject().Parent()->ContainerForPaintInvalidation();
1381     if (!previous_paint_invalidation_container.StyleRef().IsStackingContext()) {
1382       ObjectPaintInvalidator(GetLayoutObject())
1383           .InvalidatePaintIncludingNonSelfPaintingLayerDescendants();
1384       // Set needsRepaint along the original compositingContainer chain.
1385       GetLayoutObject().Parent()->EnclosingLayer()->SetNeedsRepaint();
1386       did_set_paint_invalidation = true;
1387     }
1388   }
1389 
1390   if (!did_set_paint_invalidation && IsSelfPaintingLayer() && parent_) {
1391     if (PaintLayer* enclosing_self_painting_layer =
1392             parent_->EnclosingSelfPaintingLayer())
1393       MergeNeedsPaintPhaseFlagsFrom(*enclosing_self_painting_layer);
1394   }
1395 
1396   // Clear out all the clip rects.
1397   ClearClipRects();
1398 }
1399 
1400 // Returns the layer reached on the walk up towards the ancestor.
AccumulateOffsetTowardsAncestor(const PaintLayer * layer,const PaintLayer * ancestor_layer,PhysicalOffset & location)1401 static inline const PaintLayer* AccumulateOffsetTowardsAncestor(
1402     const PaintLayer* layer,
1403     const PaintLayer* ancestor_layer,
1404     PhysicalOffset& location) {
1405   DCHECK(ancestor_layer != layer);
1406 
1407   const LayoutBoxModelObject& layout_object = layer->GetLayoutObject();
1408 
1409   if (layout_object.IsFixedPositioned() &&
1410       (!ancestor_layer || ancestor_layer == layout_object.View()->Layer())) {
1411     // If the fixed layer's container is the root, just add in the offset of the
1412     // view. We can obtain this by calling localToAbsolute() on the LayoutView.
1413     location +=
1414         layout_object.LocalToAbsolutePoint(PhysicalOffset(), kIgnoreTransforms);
1415     return ancestor_layer;
1416   }
1417 
1418   bool found_ancestor_first = false;
1419   PaintLayer* containing_layer =
1420       ancestor_layer
1421           ? layer->ContainingLayer(ancestor_layer, &found_ancestor_first)
1422           : layer->ContainingLayer(ancestor_layer, nullptr);
1423 
1424   if (found_ancestor_first) {
1425     // Found ancestorLayer before the containing layer, so compute offset of
1426     // both relative to the container and subtract.
1427     PhysicalOffset this_coords;
1428     layer->ConvertToLayerCoords(containing_layer, this_coords);
1429 
1430     PhysicalOffset ancestor_coords;
1431     ancestor_layer->ConvertToLayerCoords(containing_layer, ancestor_coords);
1432 
1433     location += (this_coords - ancestor_coords);
1434     return ancestor_layer;
1435   }
1436 
1437   if (!containing_layer)
1438     return nullptr;
1439 
1440   location += layer->LocationWithoutPositionOffset();
1441   if (layer->GetLayoutObject().IsRelPositioned()) {
1442     location += layer->OffsetForInFlowRelPosition();
1443   } else if (layer->GetLayoutObject().IsInFlowPositioned()) {
1444     location += layer->GetLayoutObject().OffsetForInFlowPosition();
1445   }
1446   location -=
1447       PhysicalOffset(containing_layer->PixelSnappedScrolledContentOffset());
1448 
1449   return containing_layer;
1450 }
1451 
ConvertToLayerCoords(const PaintLayer * ancestor_layer,PhysicalOffset & location) const1452 void PaintLayer::ConvertToLayerCoords(const PaintLayer* ancestor_layer,
1453                                       PhysicalOffset& location) const {
1454   if (ancestor_layer == this)
1455     return;
1456 
1457   const PaintLayer* curr_layer = this;
1458   while (curr_layer && curr_layer != ancestor_layer)
1459     curr_layer =
1460         AccumulateOffsetTowardsAncestor(curr_layer, ancestor_layer, location);
1461 }
1462 
ConvertToLayerCoords(const PaintLayer * ancestor_layer,PhysicalRect & rect) const1463 void PaintLayer::ConvertToLayerCoords(const PaintLayer* ancestor_layer,
1464                                       PhysicalRect& rect) const {
1465   PhysicalOffset delta;
1466   ConvertToLayerCoords(ancestor_layer, delta);
1467   rect.Move(delta);
1468 }
1469 
VisualOffsetFromAncestor(const PaintLayer * ancestor_layer,PhysicalOffset offset) const1470 PhysicalOffset PaintLayer::VisualOffsetFromAncestor(
1471     const PaintLayer* ancestor_layer,
1472     PhysicalOffset offset) const {
1473   if (ancestor_layer == this)
1474     return offset;
1475   PaintLayer* pagination_layer = EnclosingPaginationLayer();
1476   if (pagination_layer == this)
1477     pagination_layer = Parent()->EnclosingPaginationLayer();
1478   if (!pagination_layer) {
1479     ConvertToLayerCoords(ancestor_layer, offset);
1480     return offset;
1481   }
1482 
1483   LayoutFlowThread& flow_thread =
1484       ToLayoutFlowThread(pagination_layer->GetLayoutObject());
1485   ConvertToLayerCoords(pagination_layer, offset);
1486   offset = PhysicalOffsetToBeNoop(
1487       flow_thread.FlowThreadPointToVisualPoint(offset.ToLayoutPoint()));
1488   if (ancestor_layer == pagination_layer)
1489     return offset;
1490 
1491   if (ancestor_layer->EnclosingPaginationLayer() != pagination_layer) {
1492     offset += pagination_layer->VisualOffsetFromAncestor(ancestor_layer);
1493   } else {
1494     // The ancestor layer is also inside the pagination layer, so we need to
1495     // subtract the visual distance from the ancestor layer to the pagination
1496     // layer.
1497     offset -= ancestor_layer->VisualOffsetFromAncestor(pagination_layer);
1498   }
1499   return offset;
1500 }
1501 
DidUpdateScrollsOverflow()1502 void PaintLayer::DidUpdateScrollsOverflow() {
1503   UpdateSelfPaintingLayer();
1504 }
1505 
UpdateStackingNode()1506 void PaintLayer::UpdateStackingNode() {
1507 #if DCHECK_IS_ON()
1508   DCHECK(layer_list_mutation_allowed_);
1509 #endif
1510 
1511   bool needs_stacking_node =
1512       has_stacked_descendant_in_current_stacking_context_ &&
1513       GetLayoutObject().StyleRef().IsStackingContext();
1514 
1515   if (needs_stacking_node != !!stacking_node_) {
1516     if (needs_stacking_node)
1517       stacking_node_ = std::make_unique<PaintLayerStackingNode>(*this);
1518     else
1519       stacking_node_ = nullptr;
1520   }
1521 
1522   if (stacking_node_)
1523     stacking_node_->UpdateZOrderLists();
1524 }
1525 
RequiresScrollableArea() const1526 bool PaintLayer::RequiresScrollableArea() const {
1527   if (!GetLayoutBox())
1528     return false;
1529   if (GetLayoutObject().HasOverflowClip())
1530     return true;
1531   // Iframes with the resize property can be resized. This requires
1532   // scroll corner painting, which is implemented, in part, by
1533   // PaintLayerScrollableArea.
1534   if (GetLayoutBox()->CanResize())
1535     return true;
1536   return false;
1537 }
1538 
UpdateScrollableArea()1539 void PaintLayer::UpdateScrollableArea() {
1540   if (RequiresScrollableArea() && !scrollable_area_) {
1541     scrollable_area_ = MakeGarbageCollected<PaintLayerScrollableArea>(*this);
1542     if (Compositor()) {
1543       Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
1544     }
1545     GetLayoutObject().SetNeedsPaintPropertyUpdate();
1546   } else if (!RequiresScrollableArea() && scrollable_area_) {
1547     scrollable_area_->Dispose();
1548     scrollable_area_.Clear();
1549     if (Compositor()) {
1550       Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
1551     }
1552     GetLayoutObject().SetBackgroundPaintLocation(
1553         kBackgroundPaintInGraphicsLayer);
1554     GetLayoutObject().SetNeedsPaintPropertyUpdate();
1555   }
1556 }
1557 
HasOverflowControls() const1558 bool PaintLayer::HasOverflowControls() const {
1559   return scrollable_area_ && (scrollable_area_->HasScrollbar() ||
1560                               scrollable_area_->ScrollCorner() ||
1561                               GetLayoutObject().StyleRef().HasResize());
1562 }
1563 
AppendSingleFragmentIgnoringPagination(PaintLayerFragments & fragments,const PaintLayer * root_layer,const CullRect * cull_rect,OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior,ShouldRespectOverflowClipType respect_overflow_clip,const PhysicalOffset * offset_from_root,const PhysicalOffset & sub_pixel_accumulation) const1564 void PaintLayer::AppendSingleFragmentIgnoringPagination(
1565     PaintLayerFragments& fragments,
1566     const PaintLayer* root_layer,
1567     const CullRect* cull_rect,
1568     OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior,
1569     ShouldRespectOverflowClipType respect_overflow_clip,
1570     const PhysicalOffset* offset_from_root,
1571     const PhysicalOffset& sub_pixel_accumulation) const {
1572   PaintLayerFragment fragment;
1573   ClipRectsContext clip_rects_context(
1574       root_layer, &root_layer->GetLayoutObject().FirstFragment(),
1575       kUncachedClipRects, overlay_scrollbar_clip_behavior,
1576       respect_overflow_clip, sub_pixel_accumulation);
1577   Clipper(GeometryMapperOption::kUseGeometryMapper)
1578       .CalculateRects(clip_rects_context, &GetLayoutObject().FirstFragment(),
1579                       cull_rect, fragment.layer_bounds,
1580                       fragment.background_rect, fragment.foreground_rect,
1581                       offset_from_root);
1582   fragment.root_fragment_data = &root_layer->GetLayoutObject().FirstFragment();
1583   fragment.fragment_data = &GetLayoutObject().FirstFragment();
1584   fragments.push_back(fragment);
1585 }
1586 
ShouldFragmentCompositedBounds(const PaintLayer * compositing_layer) const1587 bool PaintLayer::ShouldFragmentCompositedBounds(
1588     const PaintLayer* compositing_layer) const {
1589   if (!EnclosingPaginationLayer())
1590     return false;
1591   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
1592     return true;
1593   if (PaintsWithTransform(kGlobalPaintNormalPhase))
1594     return true;
1595   if (!compositing_layer) {
1596     compositing_layer =
1597         EnclosingLayerForPaintInvalidationCrossingFrameBoundaries();
1598   }
1599   if (!compositing_layer)
1600     return true;
1601   // Composited layers may not be fragmented.
1602   return !compositing_layer->EnclosingPaginationLayer();
1603 }
1604 
CollectFragments(PaintLayerFragments & fragments,const PaintLayer * root_layer,const CullRect * cull_rect,OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior,ShouldRespectOverflowClipType respect_overflow_clip,const PhysicalOffset * offset_from_root,const PhysicalOffset & sub_pixel_accumulation) const1605 void PaintLayer::CollectFragments(
1606     PaintLayerFragments& fragments,
1607     const PaintLayer* root_layer,
1608     const CullRect* cull_rect,
1609     OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior,
1610     ShouldRespectOverflowClipType respect_overflow_clip,
1611     const PhysicalOffset* offset_from_root,
1612     const PhysicalOffset& sub_pixel_accumulation) const {
1613   PaintLayerFragment fragment;
1614   const auto& first_fragment_data = GetLayoutObject().FirstFragment();
1615   const auto& first_root_fragment_data =
1616       root_layer->GetLayoutObject().FirstFragment();
1617 
1618   // If both |this| and |root_layer| are fragmented and are inside the same
1619   // pagination container, then try to match fragments from |root_layer| to
1620   // |this|, so that any fragment clip for |root_layer|'s fragment matches
1621   // |this|'s. Note we check both ShouldFragmentCompositedBounds() and next
1622   // fragment here because the former may return false even if |this| is
1623   // fragmented, e.g. for fixed-position objects in paged media, and the next
1624   // fragment can be null even if the first fragment is actually in a fragmented
1625   // context when the current layer appears in only one of the multiple
1626   // fragments of the pagination container.
1627   bool is_fragmented =
1628       ShouldFragmentCompositedBounds() || first_fragment_data.NextFragment();
1629   bool should_match_fragments =
1630       is_fragmented &&
1631       root_layer->EnclosingPaginationLayer() == EnclosingPaginationLayer();
1632 
1633   // The inherited offset_from_root does not include any pagination offsets.
1634   // In the presence of fragmentation, we cannot use it.
1635   bool offset_from_root_can_be_used = offset_from_root && !is_fragmented;
1636   for (auto* fragment_data = &first_fragment_data; fragment_data;
1637        fragment_data = fragment_data->NextFragment()) {
1638     const FragmentData* root_fragment_data;
1639     if (root_layer == this) {
1640       root_fragment_data = fragment_data;
1641     } else if (should_match_fragments) {
1642       for (root_fragment_data = &first_root_fragment_data; root_fragment_data;
1643            root_fragment_data = root_fragment_data->NextFragment()) {
1644         if (root_fragment_data->LogicalTopInFlowThread() ==
1645             fragment_data->LogicalTopInFlowThread())
1646           break;
1647       }
1648     } else {
1649       root_fragment_data = &first_root_fragment_data;
1650     }
1651 
1652     bool cant_find_fragment = !root_fragment_data;
1653     if (cant_find_fragment) {
1654       DCHECK(should_match_fragments);
1655       // Fall back to the first fragment, in order to have
1656       // PaintLayerClipper at least compute |fragment.layer_bounds|.
1657       root_fragment_data = &first_root_fragment_data;
1658     }
1659 
1660     ClipRectsContext clip_rects_context(
1661         root_layer, root_fragment_data, kUncachedClipRects,
1662         overlay_scrollbar_clip_behavior, respect_overflow_clip,
1663         sub_pixel_accumulation);
1664 
1665     base::Optional<CullRect> fragment_cull_rect;
1666     if (cull_rect) {
1667       // |cull_rect| is in the coordinate space of |root_layer| (i.e. the
1668       // space of |root_layer|'s first fragment). Map the rect to the space of
1669       // the current root fragment.
1670       auto rect = cull_rect->Rect();
1671       first_root_fragment_data.MapRectToFragment(*root_fragment_data, rect);
1672       fragment_cull_rect.emplace(rect);
1673     }
1674 
1675     Clipper(GeometryMapperOption::kUseGeometryMapper)
1676         .CalculateRects(
1677             clip_rects_context, fragment_data,
1678             fragment_cull_rect ? &*fragment_cull_rect : nullptr,
1679             fragment.layer_bounds, fragment.background_rect,
1680             fragment.foreground_rect,
1681             offset_from_root_can_be_used ? offset_from_root : nullptr);
1682 
1683     if (cant_find_fragment) {
1684       // If we couldn't find a matching fragment when |should_match_fragments|
1685       // was true, then fall back to no clip.
1686       fragment.background_rect.Reset();
1687       fragment.foreground_rect.Reset();
1688     }
1689 
1690     fragment.root_fragment_data = root_fragment_data;
1691     fragment.fragment_data = fragment_data;
1692 
1693     if (GetLayoutObject().CanTraversePhysicalFragments()) {
1694       if (const auto* block = DynamicTo<LayoutBlock>(&GetLayoutObject())) {
1695         fragment.physical_fragment = block->CurrentFragment();
1696         DCHECK(fragment.physical_fragment);
1697 
1698         // TODO(mstensho): Implement support for multiple fragments per node.
1699         DCHECK(!fragment_data->NextFragment());
1700       }
1701     }
1702 
1703     fragments.push_back(fragment);
1704   }
1705 }
1706 
HitTestRecursionData(const PhysicalRect & rect_arg,const HitTestLocation & location_arg,const HitTestLocation & original_location_arg)1707 PaintLayer::HitTestRecursionData::HitTestRecursionData(
1708     const PhysicalRect& rect_arg,
1709     const HitTestLocation& location_arg,
1710     const HitTestLocation& original_location_arg)
1711     : rect(rect_arg),
1712       location(location_arg),
1713       original_location(original_location_arg),
1714       intersects_location(location_arg.Intersects(rect_arg)) {}
1715 
HitTest(const HitTestLocation & hit_test_location,HitTestResult & result,const PhysicalRect & hit_test_area)1716 bool PaintLayer::HitTest(const HitTestLocation& hit_test_location,
1717                          HitTestResult& result,
1718                          const PhysicalRect& hit_test_area) {
1719   DCHECK(IsSelfPaintingLayer() || HasSelfPaintingLayerDescendant());
1720 
1721   // LayoutView should make sure to update layout before entering hit testing
1722   DCHECK(!GetLayoutObject().GetFrame()->View()->LayoutPending());
1723   DCHECK(!GetLayoutObject().GetDocument().GetLayoutView()->NeedsLayout());
1724 
1725   const HitTestRequest& request = result.GetHitTestRequest();
1726 
1727   HitTestRecursionData recursion_data(hit_test_area, hit_test_location,
1728                                       hit_test_location);
1729   PaintLayer* inside_layer =
1730       HitTestLayer(this, nullptr, result, recursion_data, false);
1731   if (!inside_layer && IsRootLayer()) {
1732     bool fallback = false;
1733     // If we didn't hit any layers but are still inside the document
1734     // bounds, then we should fallback to hitting the document.
1735     // For rect-based hit test, we do the fallback only when the hit-rect
1736     // is totally within the document bounds.
1737     if (hit_test_area.Contains(hit_test_location.BoundingBox())) {
1738       fallback = true;
1739 
1740       // Mouse dragging outside the main document should also be
1741       // delivered to the document.
1742       // TODO(miletus): Capture behavior inconsistent with iframes
1743       // crbug.com/522109.
1744       // TODO(majidvp): This should apply more consistently across different
1745       // event types and we should not use RequestType for it. Perhaps best for
1746       // it to be done at a higher level. See http://crbug.com/505825
1747     } else if ((request.Active() || request.Release()) &&
1748                !request.IsChildFrameHitTest()) {
1749       fallback = true;
1750     }
1751     if (fallback) {
1752       GetLayoutObject().UpdateHitTestResult(result, hit_test_location.Point());
1753       inside_layer = this;
1754 
1755       // Don't cache this result since it really wasn't a true hit.
1756       result.SetCacheable(false);
1757     }
1758   }
1759 
1760   // Now determine if the result is inside an anchor - if the urlElement isn't
1761   // already set.
1762   Node* node = result.InnerNode();
1763   if (node && !result.URLElement())
1764     result.SetURLElement(node->EnclosingLinkEventParentOrSelf());
1765 
1766   // Now return whether we were inside this layer (this will always be true for
1767   // the root layer).
1768   return inside_layer;
1769 }
1770 
EnclosingNode() const1771 Node* PaintLayer::EnclosingNode() const {
1772   for (LayoutObject* r = &GetLayoutObject(); r; r = r->Parent()) {
1773     if (Node* e = r->GetNode())
1774       return e;
1775   }
1776   NOTREACHED();
1777   return nullptr;
1778 }
1779 
IsInTopLayer() const1780 bool PaintLayer::IsInTopLayer() const {
1781   auto* element = DynamicTo<Element>(GetLayoutObject().GetNode());
1782   return element && element->IsInTopLayer();
1783 }
1784 
1785 // Compute the z-offset of the point in the transformState.
1786 // This is effectively projecting a ray normal to the plane of ancestor, finding
1787 // where that ray intersects target, and computing the z delta between those two
1788 // points.
ComputeZOffset(const HitTestingTransformState & transform_state)1789 static double ComputeZOffset(const HitTestingTransformState& transform_state) {
1790   // We got an affine transform, so no z-offset
1791   if (transform_state.accumulated_transform_.IsAffine())
1792     return 0;
1793 
1794   // Flatten the point into the target plane
1795   FloatPoint target_point = transform_state.MappedPoint();
1796 
1797   // Now map the point back through the transform, which computes Z.
1798   FloatPoint3D backmapped_point =
1799       transform_state.accumulated_transform_.MapPoint(
1800           FloatPoint3D(target_point));
1801   return backmapped_point.Z();
1802 }
1803 
CreateLocalTransformState(PaintLayer * root_layer,PaintLayer * container_layer,const HitTestRecursionData & recursion_data,const HitTestingTransformState * container_transform_state,const PhysicalOffset & translation_offset) const1804 HitTestingTransformState PaintLayer::CreateLocalTransformState(
1805     PaintLayer* root_layer,
1806     PaintLayer* container_layer,
1807     const HitTestRecursionData& recursion_data,
1808     const HitTestingTransformState* container_transform_state,
1809     const PhysicalOffset& translation_offset) const {
1810   // If we're already computing transform state, then it's relative to the
1811   // container (which we know is non-null).
1812   // If this is the first time we need to make transform state, then base it
1813   // off of hitTestLocation, which is relative to rootLayer.
1814   HitTestingTransformState transform_state =
1815       container_transform_state
1816           ? *container_transform_state
1817           : HitTestingTransformState(recursion_data.location.TransformedPoint(),
1818                                      recursion_data.location.TransformedRect(),
1819                                      FloatQuad(FloatRect(recursion_data.rect)));
1820 
1821   PhysicalOffset offset;
1822   if (container_transform_state)
1823     ConvertToLayerCoords(container_layer, offset);
1824   else
1825     ConvertToLayerCoords(root_layer, offset);
1826 
1827   offset += translation_offset;
1828 
1829   LayoutObject* container_layout_object =
1830       container_layer ? &container_layer->GetLayoutObject() : nullptr;
1831   if (GetLayoutObject().ShouldUseTransformFromContainer(
1832           container_layout_object)) {
1833     TransformationMatrix container_transform;
1834     GetLayoutObject().GetTransformFromContainer(container_layout_object, offset,
1835                                                 container_transform);
1836     transform_state.ApplyTransform(
1837         container_transform, HitTestingTransformState::kAccumulateTransform);
1838   } else {
1839     transform_state.Translate(offset.left.ToInt(), offset.top.ToInt(),
1840                               HitTestingTransformState::kAccumulateTransform);
1841   }
1842 
1843   return transform_state;
1844 }
1845 
IsHitCandidateForDepthOrder(const PaintLayer * hit_layer,bool can_depth_sort,double * z_offset,const HitTestingTransformState * transform_state)1846 static bool IsHitCandidateForDepthOrder(
1847     const PaintLayer* hit_layer,
1848     bool can_depth_sort,
1849     double* z_offset,
1850     const HitTestingTransformState* transform_state) {
1851   if (!hit_layer)
1852     return false;
1853 
1854   // The hit layer is depth-sorting with other layers, so just say that it was
1855   // hit.
1856   if (can_depth_sort)
1857     return true;
1858 
1859   // We need to look at z-depth to decide if this layer was hit.
1860   if (z_offset) {
1861     DCHECK(transform_state);
1862     // This is actually computing our z, but that's OK because the hitLayer is
1863     // coplanar with us.
1864     double child_z_offset = ComputeZOffset(*transform_state);
1865     if (child_z_offset > *z_offset) {
1866       *z_offset = child_z_offset;
1867       return true;
1868     }
1869     return false;
1870   }
1871 
1872   return true;
1873 }
1874 
1875 // Calling IsDescendantOf is sad (slow), but it's the only way to tell
1876 // whether a hit test candidate is a descendant of the stop node.
IsHitCandidateForStopNode(const LayoutObject & candidate,const LayoutObject * stop_node)1877 static bool IsHitCandidateForStopNode(const LayoutObject& candidate,
1878                                       const LayoutObject* stop_node) {
1879   return !stop_node || (&candidate == stop_node) ||
1880          !candidate.IsDescendantOf(stop_node);
1881 }
1882 
1883 // hitTestLocation and hitTestRect are relative to rootLayer.
1884 // A 'flattening' layer is one preserves3D() == false.
1885 // transformState.m_accumulatedTransform holds the transform from the containing
1886 // flattening layer.
1887 // transformState.m_lastPlanarPoint is the hitTestLocation in the plane of the
1888 // containing flattening layer.
1889 // transformState.m_lastPlanarQuad is the hitTestRect as a quad in the plane of
1890 // the containing flattening layer.
1891 //
1892 // If zOffset is non-null (which indicates that the caller wants z offset
1893 // information), *zOffset on return is the z offset of the hit point relative to
1894 // the containing flattening layer.
HitTestLayer(PaintLayer * root_layer,PaintLayer * container_layer,HitTestResult & result,const HitTestRecursionData & recursion_data,bool applied_transform,HitTestingTransformState * transform_state,double * z_offset,bool check_resizer_only)1895 PaintLayer* PaintLayer::HitTestLayer(PaintLayer* root_layer,
1896                                      PaintLayer* container_layer,
1897                                      HitTestResult& result,
1898                                      const HitTestRecursionData& recursion_data,
1899                                      bool applied_transform,
1900                                      HitTestingTransformState* transform_state,
1901                                      double* z_offset,
1902                                      bool check_resizer_only) {
1903   const LayoutObject& layout_object = GetLayoutObject();
1904   DCHECK_GE(layout_object.GetDocument().Lifecycle().GetState(),
1905             DocumentLifecycle::kCompositingClean);
1906 
1907   if (!IsSelfPaintingLayer() && !HasSelfPaintingLayerDescendant())
1908     return nullptr;
1909 
1910   if ((result.GetHitTestRequest().GetType() &
1911        HitTestRequest::kIgnoreZeroOpacityObjects) &&
1912       !layout_object.HasNonZeroEffectiveOpacity()) {
1913     return nullptr;
1914   }
1915 
1916   ShouldRespectOverflowClipType clip_behavior = kRespectOverflowClip;
1917   if (result.GetHitTestRequest().IgnoreClipping())
1918     clip_behavior = kIgnoreOverflowClip;
1919 
1920   // We can only reach an SVG foreign object's PaintLayer from
1921   // LayoutSVGForeignObject::NodeAtFloatPoint (because
1922   // IsReplacedNormalFlowStacking() true for LayoutSVGForeignObject),
1923   // where the hit_test_rect has already been transformed to local coordinates.
1924   bool use_transform = Transform() && !layout_object.IsSVGForeignObject();
1925 
1926   // Apply a transform if we have one.
1927   if (use_transform && !applied_transform) {
1928     if (EnclosingPaginationLayer()) {
1929       return HitTestTransformedLayerInFragments(
1930           root_layer, container_layer, result, recursion_data, transform_state,
1931           z_offset, check_resizer_only, clip_behavior);
1932     }
1933 
1934     // Make sure the parent's clip rects have been calculated.
1935     if (Parent()) {
1936       ClipRect clip_rect;
1937       Clipper(GeometryMapperOption::kUseGeometryMapper)
1938           .CalculateBackgroundClipRect(
1939               ClipRectsContext(
1940                   root_layer, &root_layer->GetLayoutObject().FirstFragment(),
1941                   kUncachedClipRects, kExcludeOverlayScrollbarSizeForHitTesting,
1942                   clip_behavior),
1943               clip_rect);
1944       // Go ahead and test the enclosing clip now.
1945       if (!clip_rect.Intersects(recursion_data.location))
1946         return nullptr;
1947     }
1948 
1949     return HitTestLayerByApplyingTransform(root_layer, container_layer, result,
1950                                            recursion_data, transform_state,
1951                                            z_offset, check_resizer_only);
1952   }
1953 
1954   // Don't hit test the clip-path area when checking for occlusion. This is
1955   // necessary because SVG doesn't support rect-based hit testing, so
1956   // HitTestClippedOutByClipPath may erroneously return true for a rect-based
1957   // hit test).
1958   bool is_occlusion_test = result.GetHitTestRequest().GetType() &
1959                            HitTestRequest::kHitTestVisualOverflow;
1960   if (!is_occlusion_test && layout_object.HasClipPath() &&
1961       HitTestClippedOutByClipPath(root_layer, recursion_data.location)) {
1962     return nullptr;
1963   }
1964 
1965   // The natural thing would be to keep HitTestingTransformState on the stack,
1966   // but it's big, so we heap-allocate.
1967   HitTestingTransformState* local_transform_state = nullptr;
1968   STACK_UNINITIALIZED base::Optional<HitTestingTransformState> storage;
1969 
1970   if (applied_transform) {
1971     // We computed the correct state in the caller (above code), so just
1972     // reference it.
1973     DCHECK(transform_state);
1974     local_transform_state = transform_state;
1975   } else if (transform_state || has3d_transformed_descendant_ ||
1976              Preserves3D()) {
1977     // We need transform state for the first time, or to offset the container
1978     // state, so create it here.
1979     storage = CreateLocalTransformState(root_layer, container_layer,
1980                                         recursion_data, transform_state);
1981     local_transform_state = &*storage;
1982   }
1983 
1984   // Check for hit test on backface if backface-visibility is 'hidden'
1985   if (local_transform_state && layout_object.StyleRef().BackfaceVisibility() ==
1986                                    EBackfaceVisibility::kHidden) {
1987     STACK_UNINITIALIZED TransformationMatrix inverted_matrix =
1988         local_transform_state->accumulated_transform_.Inverse();
1989     // If the z-vector of the matrix is negative, the back is facing towards the
1990     // viewer.
1991     if (inverted_matrix.M33() < 0)
1992       return nullptr;
1993   }
1994 
1995   HitTestingTransformState* unflattened_transform_state = local_transform_state;
1996   STACK_UNINITIALIZED base::Optional<HitTestingTransformState>
1997       unflattened_storage;
1998   if (local_transform_state && !Preserves3D()) {
1999     // Keep a copy of the pre-flattening state, for computing z-offsets for the
2000     // container
2001     unflattened_storage.emplace(*local_transform_state);
2002     unflattened_transform_state = &*unflattened_storage;
2003     // This layer is flattening, so flatten the state passed to descendants.
2004     local_transform_state->Flatten();
2005   }
2006 
2007   // The following are used for keeping track of the z-depth of the hit point of
2008   // 3d-transformed descendants.
2009   double local_z_offset = -std::numeric_limits<double>::infinity();
2010   double* z_offset_for_descendants_ptr = nullptr;
2011   double* z_offset_for_contents_ptr = nullptr;
2012 
2013   bool depth_sort_descendants = false;
2014   if (Preserves3D()) {
2015     depth_sort_descendants = true;
2016     // Our layers can depth-test with our container, so share the z depth
2017     // pointer with the container, if it passed one down.
2018     z_offset_for_descendants_ptr = z_offset ? z_offset : &local_z_offset;
2019     z_offset_for_contents_ptr = z_offset ? z_offset : &local_z_offset;
2020   } else if (z_offset) {
2021     z_offset_for_descendants_ptr = nullptr;
2022     // Container needs us to give back a z offset for the hit layer.
2023     z_offset_for_contents_ptr = z_offset;
2024   }
2025 
2026   // Collect the fragments. This will compute the clip rectangles for each
2027   // layer fragment.
2028   STACK_UNINITIALIZED base::Optional<PaintLayerFragments> layer_fragments;
2029   if (recursion_data.intersects_location) {
2030     layer_fragments.emplace();
2031     if (applied_transform) {
2032       DCHECK(root_layer == this);
2033       PhysicalOffset ignored;
2034       AppendSingleFragmentIgnoringPagination(
2035           *layer_fragments, root_layer, nullptr,
2036           kExcludeOverlayScrollbarSizeForHitTesting, clip_behavior, &ignored);
2037     } else {
2038       CollectFragments(*layer_fragments, root_layer, nullptr,
2039                        kExcludeOverlayScrollbarSizeForHitTesting,
2040                        clip_behavior);
2041     }
2042 
2043     // See if the hit test pos is inside the resizer of current layer. This
2044     // should be done before walking child layers to avoid that the resizer
2045     // clickable area is obscured by the positive child layers.
2046     if (scrollable_area_ && scrollable_area_->HitTestResizerInFragments(
2047                                 *layer_fragments, recursion_data.location)) {
2048       if (Node* node_for_resizer = layout_object.NodeForHitTest())
2049         result.SetInnerNode(node_for_resizer);
2050       return this;
2051     }
2052   }
2053 
2054   if (check_resizer_only)
2055     return nullptr;
2056 
2057   // See if the hit test pos is inside the resizer of the child layers which
2058   // has reordered the painting of the overlay overflow controls.
2059   if (stacking_node_) {
2060     for (auto* layer : base::Reversed(
2061              stacking_node_->OverlayOverflowControlsReorderedList())) {
2062       if (layer->HitTestLayer(
2063               root_layer, nullptr, result, recursion_data,
2064               false /*applied_transform*/, local_transform_state,
2065               z_offset_for_descendants_ptr, true /*check_resizer_only*/)) {
2066         return layer;
2067       }
2068     }
2069   }
2070 
2071   // This variable tracks which layer the mouse ends up being inside.
2072   PaintLayer* candidate_layer = nullptr;
2073 
2074   // Begin by walking our list of positive layers from highest z-index down to
2075   // the lowest z-index.
2076   PaintLayer* hit_layer = HitTestChildren(
2077       kPositiveZOrderChildren, root_layer, result, recursion_data,
2078       local_transform_state, z_offset_for_descendants_ptr, z_offset,
2079       unflattened_transform_state, depth_sort_descendants);
2080   if (hit_layer) {
2081     if (!depth_sort_descendants)
2082       return hit_layer;
2083     candidate_layer = hit_layer;
2084   }
2085 
2086   // Now check our overflow objects.
2087   hit_layer = HitTestChildren(
2088       kNormalFlowChildren, root_layer, result, recursion_data,
2089       local_transform_state, z_offset_for_descendants_ptr, z_offset,
2090       unflattened_transform_state, depth_sort_descendants);
2091   if (hit_layer) {
2092     if (!depth_sort_descendants)
2093       return hit_layer;
2094     candidate_layer = hit_layer;
2095   }
2096 
2097   const LayoutObject* stop_node = result.GetHitTestRequest().GetStopNode();
2098   PhysicalOffset offset;
2099   if (recursion_data.intersects_location) {
2100     // Next we want to see if the mouse pos is inside the child LayoutObjects of
2101     // the layer. Check every fragment in reverse order.
2102     if (IsSelfPaintingLayer() && !layout_object.PaintBlockedByDisplayLock(
2103                                      DisplayLockLifecycleTarget::kChildren)) {
2104       // Hit test with a temporary HitTestResult, because we only want to commit
2105       // to 'result' if we know we're frontmost.
2106       STACK_UNINITIALIZED HitTestResult temp_result(
2107           result.GetHitTestRequest(), recursion_data.original_location);
2108       temp_result.SetInertNode(result.InertNode());
2109       bool inside_fragment_foreground_rect = false;
2110 
2111       if (HitTestContentsForFragments(
2112               *layer_fragments, offset, temp_result, recursion_data.location,
2113               kHitTestDescendants, inside_fragment_foreground_rect) &&
2114           IsHitCandidateForDepthOrder(this, false, z_offset_for_contents_ptr,
2115                                       unflattened_transform_state) &&
2116           IsHitCandidateForStopNode(GetLayoutObject(), stop_node)) {
2117         if (result.GetHitTestRequest().ListBased())
2118           result.Append(temp_result);
2119         else
2120           result = temp_result;
2121         if (!depth_sort_descendants)
2122           return this;
2123         // Foreground can depth-sort with descendant layers, so keep this as a
2124         // candidate.
2125         candidate_layer = this;
2126       } else if (inside_fragment_foreground_rect &&
2127                  result.GetHitTestRequest().ListBased() &&
2128                  IsHitCandidateForStopNode(GetLayoutObject(), stop_node)) {
2129         result.Append(temp_result);
2130       } else if (result.GetHitTestRequest().RetargetForInert() &&
2131                  IsHitCandidateForStopNode(GetLayoutObject(), stop_node)) {
2132         result.SetInertNode(temp_result.InertNode());
2133       }
2134     }
2135   }
2136 
2137   // Now check our negative z-index children.
2138   hit_layer = HitTestChildren(
2139       kNegativeZOrderChildren, root_layer, result, recursion_data,
2140       local_transform_state, z_offset_for_descendants_ptr, z_offset,
2141       unflattened_transform_state, depth_sort_descendants);
2142   if (hit_layer) {
2143     if (!depth_sort_descendants)
2144       return hit_layer;
2145     candidate_layer = hit_layer;
2146   }
2147 
2148   // If we found a layer, return. Child layers, and foreground always render
2149   // in front of background.
2150   if (candidate_layer)
2151     return candidate_layer;
2152 
2153   if (recursion_data.intersects_location && IsSelfPaintingLayer()) {
2154     STACK_UNINITIALIZED HitTestResult temp_result(
2155         result.GetHitTestRequest(), recursion_data.original_location);
2156     temp_result.SetInertNode(result.InertNode());
2157     bool inside_fragment_background_rect = false;
2158     if (HitTestContentsForFragments(*layer_fragments, offset, temp_result,
2159                                     recursion_data.location, kHitTestSelf,
2160                                     inside_fragment_background_rect) &&
2161         IsHitCandidateForDepthOrder(this, false, z_offset_for_contents_ptr,
2162                                     unflattened_transform_state) &&
2163         IsHitCandidateForStopNode(GetLayoutObject(), stop_node)) {
2164       if (result.GetHitTestRequest().ListBased())
2165         result.Append(temp_result);
2166       else
2167         result = temp_result;
2168       return this;
2169     } else if (result.GetHitTestRequest().RetargetForInert() &&
2170                IsHitCandidateForStopNode(GetLayoutObject(), stop_node)) {
2171       result.SetInertNode(temp_result.InertNode());
2172     }
2173     if (inside_fragment_background_rect &&
2174         result.GetHitTestRequest().ListBased() &&
2175         IsHitCandidateForStopNode(GetLayoutObject(), stop_node)) {
2176       result.Append(temp_result);
2177     }
2178   }
2179 
2180   return nullptr;
2181 }
2182 
HitTestContentsForFragments(const PaintLayerFragments & layer_fragments,const PhysicalOffset & offset,HitTestResult & result,const HitTestLocation & hit_test_location,HitTestFilter hit_test_filter,bool & inside_clip_rect) const2183 bool PaintLayer::HitTestContentsForFragments(
2184     const PaintLayerFragments& layer_fragments,
2185     const PhysicalOffset& offset,
2186     HitTestResult& result,
2187     const HitTestLocation& hit_test_location,
2188     HitTestFilter hit_test_filter,
2189     bool& inside_clip_rect) const {
2190   if (layer_fragments.IsEmpty())
2191     return false;
2192 
2193   for (int i = layer_fragments.size() - 1; i >= 0; --i) {
2194     const PaintLayerFragment& fragment = layer_fragments.at(i);
2195     if ((hit_test_filter == kHitTestSelf &&
2196          !fragment.background_rect.Intersects(hit_test_location)) ||
2197         (hit_test_filter == kHitTestDescendants &&
2198          !fragment.foreground_rect.Intersects(hit_test_location)))
2199       continue;
2200     inside_clip_rect = true;
2201     PhysicalOffset fragment_offset = offset;
2202     fragment_offset += fragment.layer_bounds.offset;
2203     if (HitTestContents(result, fragment.physical_fragment, fragment_offset,
2204                         hit_test_location, hit_test_filter))
2205       return true;
2206   }
2207 
2208   return false;
2209 }
2210 
HitTestTransformedLayerInFragments(PaintLayer * root_layer,PaintLayer * container_layer,HitTestResult & result,const HitTestRecursionData & recursion_data,HitTestingTransformState * transform_state,double * z_offset,bool check_resizer_only,ShouldRespectOverflowClipType clip_behavior)2211 PaintLayer* PaintLayer::HitTestTransformedLayerInFragments(
2212     PaintLayer* root_layer,
2213     PaintLayer* container_layer,
2214     HitTestResult& result,
2215     const HitTestRecursionData& recursion_data,
2216     HitTestingTransformState* transform_state,
2217     double* z_offset,
2218     bool check_resizer_only,
2219     ShouldRespectOverflowClipType clip_behavior) {
2220   PaintLayerFragments enclosing_pagination_fragments;
2221   // FIXME: We're missing a sub-pixel offset here crbug.com/348728
2222 
2223   EnclosingPaginationLayer()->CollectFragments(
2224       enclosing_pagination_fragments, root_layer, nullptr,
2225       kExcludeOverlayScrollbarSizeForHitTesting, clip_behavior, nullptr,
2226       PhysicalOffset());
2227 
2228   for (const auto& fragment : enclosing_pagination_fragments) {
2229     // Apply the page/column clip for this fragment, as well as any clips
2230     // established by layers in between us and the enclosing pagination layer.
2231     PhysicalRect clip_rect = fragment.background_rect.Rect();
2232     if (!recursion_data.location.Intersects(clip_rect))
2233       continue;
2234 
2235     PaintLayer* hit_layer = HitTestLayerByApplyingTransform(
2236         root_layer, container_layer, result, recursion_data, transform_state,
2237         z_offset, check_resizer_only,
2238         fragment.fragment_data->LegacyPaginationOffset());
2239     if (hit_layer)
2240       return hit_layer;
2241   }
2242 
2243   return nullptr;
2244 }
2245 
HitTestLayerByApplyingTransform(PaintLayer * root_layer,PaintLayer * container_layer,HitTestResult & result,const HitTestRecursionData & recursion_data,HitTestingTransformState * transform_state,double * z_offset,bool check_resizer_only,const PhysicalOffset & translation_offset)2246 PaintLayer* PaintLayer::HitTestLayerByApplyingTransform(
2247     PaintLayer* root_layer,
2248     PaintLayer* container_layer,
2249     HitTestResult& result,
2250     const HitTestRecursionData& recursion_data,
2251     HitTestingTransformState* transform_state,
2252     double* z_offset,
2253     bool check_resizer_only,
2254     const PhysicalOffset& translation_offset) {
2255   // Create a transform state to accumulate this transform.
2256   HitTestingTransformState new_transform_state =
2257       CreateLocalTransformState(root_layer, container_layer, recursion_data,
2258                                 transform_state, translation_offset);
2259 
2260   // If the transform can't be inverted, then don't hit test this layer at all.
2261   if (!new_transform_state.accumulated_transform_.IsInvertible())
2262     return nullptr;
2263 
2264   // Compute the point and the hit test rect in the coords of this layer by
2265   // using the values from the transformState, which store the point and quad in
2266   // the coords of the last flattened layer, and the accumulated transform which
2267   // lets up map through preserve-3d layers.
2268   //
2269   // We can't just map hitTestLocation and hitTestRect because they may have
2270   // been flattened (losing z) by our container.
2271   FloatPoint local_point = new_transform_state.MappedPoint();
2272   PhysicalRect bounds_of_mapped_area = new_transform_state.BoundsOfMappedArea();
2273   base::Optional<HitTestLocation> new_location;
2274   if (recursion_data.location.IsRectBasedTest())
2275     new_location.emplace(local_point, new_transform_state.MappedQuad());
2276   else
2277     new_location.emplace(local_point, new_transform_state.BoundsOfMappedQuad());
2278   HitTestRecursionData new_recursion_data(bounds_of_mapped_area, *new_location,
2279                                           recursion_data.original_location);
2280 
2281   // Now do a hit test with the root layer shifted to be us.
2282   return HitTestLayer(this, container_layer, result, new_recursion_data, true,
2283                       &new_transform_state, z_offset, check_resizer_only);
2284 }
2285 
HitTestContents(HitTestResult & result,const NGPhysicalBoxFragment * physical_fragment,const PhysicalOffset & fragment_offset,const HitTestLocation & hit_test_location,HitTestFilter hit_test_filter) const2286 bool PaintLayer::HitTestContents(HitTestResult& result,
2287                                  const NGPhysicalBoxFragment* physical_fragment,
2288                                  const PhysicalOffset& fragment_offset,
2289                                  const HitTestLocation& hit_test_location,
2290                                  HitTestFilter hit_test_filter) const {
2291   DCHECK(IsSelfPaintingLayer() || HasSelfPaintingLayerDescendant());
2292 
2293   bool did_hit;
2294   if (physical_fragment) {
2295     did_hit = NGBoxFragmentPainter(*physical_fragment)
2296                   .HitTestAllPhases(result, hit_test_location, fragment_offset,
2297                                     hit_test_filter);
2298   } else {
2299     did_hit = GetLayoutObject().HitTestAllPhases(
2300         result, hit_test_location, fragment_offset, hit_test_filter);
2301   }
2302 
2303   if (!did_hit) {
2304     // It's wrong to set innerNode, but then claim that you didn't hit anything,
2305     // unless it is a list-based test.
2306     DCHECK(!result.InnerNode() || (result.GetHitTestRequest().ListBased() &&
2307                                    result.ListBasedTestResult().size()));
2308     return false;
2309   }
2310 
2311   if (!result.InnerNode()) {
2312     // We hit something anonymous, and we didn't find a DOM node ancestor in
2313     // this layer.
2314 
2315     if (GetLayoutObject().IsLayoutFlowThread()) {
2316       // For a flow thread it's safe to just say that we didn't hit anything.
2317       // That means that we'll continue as normally, and eventually hit a column
2318       // set sibling instead. Column sets are also anonymous, but, unlike flow
2319       // threads, they don't establish layers, so we'll fall back and hit the
2320       // multicol container parent (which should have a DOM node).
2321       return false;
2322     }
2323 
2324     Node* e = EnclosingNode();
2325     // FIXME: should be a call to result.setNodeAndPosition. What we would
2326     // really want to do here is to return and look for the nearest
2327     // non-anonymous ancestor, and ignore aunts and uncles on our way. It's bad
2328     // to look for it manually like we do here, and give up on setting a local
2329     // point in the result, because that has bad implications for text selection
2330     // and caretRangeFromPoint(). See crbug.com/461791
2331     // This code path only ever hits in fullscreen tests.
2332     result.SetInnerNode(e);
2333   }
2334   return true;
2335 }
2336 
IsReplacedNormalFlowStacking() const2337 bool PaintLayer::IsReplacedNormalFlowStacking() const {
2338   return GetLayoutObject().IsSVGForeignObject();
2339 }
2340 
SetNeedsCompositingLayerAssignment()2341 void PaintLayer::SetNeedsCompositingLayerAssignment() {
2342   needs_compositing_layer_assignment_ = true;
2343 
2344   for (PaintLayer* curr = CompositingContainer();
2345        curr && !curr->StackingDescendantNeedsCompositingLayerAssignment();
2346        curr = curr->CompositingContainer()) {
2347     curr->descendant_needs_compositing_layer_assignment_ = true;
2348   }
2349 }
2350 
ClearNeedsCompositingLayerAssignment()2351 void PaintLayer::ClearNeedsCompositingLayerAssignment() {
2352   needs_compositing_layer_assignment_ = false;
2353   descendant_needs_compositing_layer_assignment_ = false;
2354 }
2355 
SetNeedsCompositingRequirementsUpdate()2356 void PaintLayer::SetNeedsCompositingRequirementsUpdate() {
2357   for (PaintLayer* curr = this;
2358        curr && !curr->DescendantMayNeedCompositingRequirementsUpdate();
2359        curr = curr->Parent()) {
2360     curr->descendant_may_need_compositing_requirements_update_ = true;
2361   }
2362 }
2363 
HitTestChildren(PaintLayerIteration children_to_visit,PaintLayer * root_layer,HitTestResult & result,const HitTestRecursionData & recursion_data,HitTestingTransformState * transform_state,double * z_offset_for_descendants,double * z_offset,HitTestingTransformState * unflattened_transform_state,bool depth_sort_descendants)2364 PaintLayer* PaintLayer::HitTestChildren(
2365     PaintLayerIteration children_to_visit,
2366     PaintLayer* root_layer,
2367     HitTestResult& result,
2368     const HitTestRecursionData& recursion_data,
2369     HitTestingTransformState* transform_state,
2370     double* z_offset_for_descendants,
2371     double* z_offset,
2372     HitTestingTransformState* unflattened_transform_state,
2373     bool depth_sort_descendants) {
2374   if (!HasSelfPaintingLayerDescendant())
2375     return nullptr;
2376 
2377   if (GetLayoutObject().PaintBlockedByDisplayLock(
2378           DisplayLockLifecycleTarget::kChildren))
2379     return nullptr;
2380 
2381   const LayoutObject* stop_node = result.GetHitTestRequest().GetStopNode();
2382   PaintLayer* stop_layer = stop_node ? stop_node->PaintingLayer() : nullptr;
2383 
2384   PaintLayer* result_layer = nullptr;
2385   PaintLayerPaintOrderReverseIterator iterator(*this, children_to_visit);
2386   while (PaintLayer* child_layer = iterator.Next()) {
2387     if (child_layer->IsReplacedNormalFlowStacking())
2388       continue;
2389 
2390     // Avoid the call to child_layer->HitTestLayer() if possible.
2391     if (stop_layer == this &&
2392         !IsHitCandidateForStopNode(child_layer->GetLayoutObject(), stop_node)) {
2393       continue;
2394     }
2395 
2396     PaintLayer* hit_layer = nullptr;
2397     STACK_UNINITIALIZED HitTestResult temp_result(
2398         result.GetHitTestRequest(), recursion_data.original_location);
2399     temp_result.SetInertNode(result.InertNode());
2400     hit_layer = child_layer->HitTestLayer(
2401         root_layer, this, temp_result, recursion_data, false, transform_state,
2402         z_offset_for_descendants);
2403 
2404     // If it is a list-based test, we can safely append the temporary result
2405     // since it might had hit nodes but not necesserily had hitLayer set.
2406     if (result.GetHitTestRequest().ListBased())
2407       result.Append(temp_result);
2408 
2409     if (IsHitCandidateForDepthOrder(hit_layer, depth_sort_descendants, z_offset,
2410                                     unflattened_transform_state)) {
2411       result_layer = hit_layer;
2412       if (!result.GetHitTestRequest().ListBased())
2413         result = temp_result;
2414       if (!depth_sort_descendants)
2415         break;
2416     } else if (result.GetHitTestRequest().RetargetForInert()) {
2417       result.SetInertNode(temp_result.InertNode());
2418     }
2419   }
2420 
2421   return result_layer;
2422 }
2423 
UpdateFilterReferenceBox()2424 void PaintLayer::UpdateFilterReferenceBox() {
2425   if (!HasFilterThatMovesPixels())
2426     return;
2427   FloatRect reference_box =
2428       FloatRect(PhysicalBoundingBoxIncludingStackingChildren(
2429           PhysicalOffset(),
2430           PaintLayer::kIncludeTransformsAndCompositedChildLayers));
2431   float zoom = GetLayoutObject().StyleRef().EffectiveZoom();
2432   if (zoom != 1)
2433     reference_box.Scale(1 / zoom);
2434   if (!ResourceInfo() || ResourceInfo()->FilterReferenceBox() != reference_box)
2435     GetLayoutObject().SetNeedsPaintPropertyUpdate();
2436   EnsureResourceInfo().SetFilterReferenceBox(reference_box);
2437 }
2438 
FilterReferenceBox() const2439 FloatRect PaintLayer::FilterReferenceBox() const {
2440   DCHECK(IsAllowedToQueryCompositingState());
2441   if (ResourceInfo())
2442     return ResourceInfo()->FilterReferenceBox();
2443   return FloatRect();
2444 }
2445 
BackdropFilterReferenceBox() const2446 FloatRect PaintLayer::BackdropFilterReferenceBox() const {
2447   FloatRect reference_box(GetLayoutObject().BorderBoundingBox());
2448   float zoom = GetLayoutObject().StyleRef().EffectiveZoom();
2449   if (zoom != 1)
2450     reference_box.Scale(1 / zoom);
2451   return reference_box;
2452 }
2453 
BackdropFilterBounds(const FloatRect & reference_box) const2454 gfx::RRectF PaintLayer::BackdropFilterBounds(
2455     const FloatRect& reference_box) const {
2456   auto& style = GetLayoutObject().StyleRef();
2457   FloatRect scaled_reference_box(reference_box);
2458   scaled_reference_box.Scale(style.EffectiveZoom());
2459   gfx::RRectF backdrop_filter_bounds =
2460       gfx::RRectF(style.GetRoundedBorderFor(LayoutRect(scaled_reference_box)));
2461   return backdrop_filter_bounds;
2462 }
HitTestClippedOutByClipPath(PaintLayer * root_layer,const HitTestLocation & hit_test_location) const2463 bool PaintLayer::HitTestClippedOutByClipPath(
2464     PaintLayer* root_layer,
2465     const HitTestLocation& hit_test_location) const {
2466   DCHECK(GetLayoutObject().HasClipPath());
2467   DCHECK(IsSelfPaintingLayer());
2468   DCHECK(root_layer);
2469 
2470   PhysicalRect origin;
2471   if (EnclosingPaginationLayer())
2472     ConvertFromFlowThreadToVisualBoundingBoxInAncestor(root_layer, origin);
2473   else
2474     ConvertToLayerCoords(root_layer, origin);
2475 
2476   FloatPoint point(hit_test_location.Point() - origin.offset);
2477   FloatRect reference_box(
2478       ClipPathClipper::LocalReferenceBox(GetLayoutObject()));
2479 
2480   ClipPathOperation* clip_path_operation =
2481       GetLayoutObject().StyleRef().ClipPath();
2482   DCHECK(clip_path_operation);
2483   if (clip_path_operation->GetType() == ClipPathOperation::SHAPE) {
2484     ShapeClipPathOperation* clip_path =
2485         To<ShapeClipPathOperation>(clip_path_operation);
2486     return !clip_path->GetPath(reference_box).Contains(point);
2487   }
2488   DCHECK_EQ(clip_path_operation->GetType(), ClipPathOperation::REFERENCE);
2489   LayoutSVGResourceClipper* clipper = GetSVGResourceAsType(clip_path_operation);
2490   if (!clipper)
2491     return false;
2492   // If the clipPath is using "userspace on use" units, then the origin of
2493   // the coordinate system is the top-left of the reference box, so adjust
2494   // the point accordingly.
2495   if (clipper->ClipPathUnits() == SVGUnitTypes::kSvgUnitTypeUserspaceonuse)
2496     point.MoveBy(-reference_box.Location());
2497   // Unzoom the point and the reference box, since the <clipPath> geometry is
2498   // not zoomed.
2499   float inverse_zoom = 1 / GetLayoutObject().StyleRef().EffectiveZoom();
2500   point.Scale(inverse_zoom, inverse_zoom);
2501   reference_box.Scale(inverse_zoom);
2502   HitTestLocation location(point);
2503   return !clipper->HitTestClipContent(reference_box, location);
2504 }
2505 
IntersectsDamageRect(const PhysicalRect & layer_bounds,const PhysicalRect & damage_rect,const PhysicalOffset & offset_from_root) const2506 bool PaintLayer::IntersectsDamageRect(
2507     const PhysicalRect& layer_bounds,
2508     const PhysicalRect& damage_rect,
2509     const PhysicalOffset& offset_from_root) const {
2510   // Always examine the canvas and the root.
2511   // FIXME: Could eliminate the isDocumentElement() check if we fix background
2512   // painting so that the LayoutView paints the root's background.
2513   if (IsRootLayer() || GetLayoutObject().IsDocumentElement())
2514     return true;
2515 
2516   // If we aren't an inline flow, and our layer bounds do intersect the damage
2517   // rect, then we can go ahead and return true.
2518   LayoutView* view = GetLayoutObject().View();
2519   DCHECK(view);
2520   if (view && !GetLayoutObject().IsLayoutInline()) {
2521     if (layer_bounds.Intersects(damage_rect))
2522       return true;
2523   }
2524 
2525   // Otherwise we need to compute the bounding box of this single layer and see
2526   // if it intersects the damage rect.
2527   return PhysicalBoundingBox(offset_from_root).Intersects(damage_rect);
2528 }
2529 
LocalBoundingBox() const2530 PhysicalRect PaintLayer::LocalBoundingBox() const {
2531   PhysicalRect rect = GetLayoutObject().PhysicalVisualOverflowRect();
2532   if (GetLayoutObject().IsEffectiveRootScroller() || IsRootLayer()) {
2533     rect.Unite(
2534         PhysicalRect(rect.offset, GetLayoutObject().View()->ViewRect().size));
2535   }
2536   return rect;
2537 }
2538 
PhysicalBoundingBox(const PaintLayer * ancestor_layer) const2539 PhysicalRect PaintLayer::PhysicalBoundingBox(
2540     const PaintLayer* ancestor_layer) const {
2541   PhysicalOffset offset_from_root;
2542   ConvertToLayerCoords(ancestor_layer, offset_from_root);
2543   return PhysicalBoundingBox(offset_from_root);
2544 }
2545 
PhysicalBoundingBox(const PhysicalOffset & offset_from_root) const2546 PhysicalRect PaintLayer::PhysicalBoundingBox(
2547     const PhysicalOffset& offset_from_root) const {
2548   PhysicalRect result = LocalBoundingBox();
2549   result.Move(offset_from_root);
2550   return result;
2551 }
2552 
FragmentsBoundingBox(const PaintLayer * ancestor_layer) const2553 PhysicalRect PaintLayer::FragmentsBoundingBox(
2554     const PaintLayer* ancestor_layer) const {
2555   if (!EnclosingPaginationLayer())
2556     return PhysicalBoundingBox(ancestor_layer);
2557 
2558   PhysicalRect result = LocalBoundingBox();
2559   ConvertFromFlowThreadToVisualBoundingBoxInAncestor(ancestor_layer, result);
2560   return result;
2561 }
2562 
BoundingBoxForCompositingOverlapTest() const2563 PhysicalRect PaintLayer::BoundingBoxForCompositingOverlapTest() const {
2564   // Apply NeverIncludeTransformForAncestorLayer, because the geometry map in
2565   // CompositingInputsUpdater will take care of applying the transform of |this|
2566   // (== the ancestorLayer argument to boundingBoxForCompositing).
2567   // TODO(trchen): Layer fragmentation is inhibited across compositing boundary.
2568   // Should we return the unfragmented bounds for overlap testing? Or perhaps
2569   // assume fragmented layers always overlap?
2570   PhysicalRect bounding_box =
2571       OverlapBoundsIncludeChildren()
2572           ? BoundingBoxForCompositingInternal(
2573                 *this, nullptr, kNeverIncludeTransformForAncestorLayer)
2574           : FragmentsBoundingBox(this);
2575   const ComputedStyle& style = GetLayoutObject().StyleRef();
2576   if (style.HasBackdropFilter() &&
2577       style.BackdropFilter().HasFilterThatMovesPixels()) {
2578     bounding_box = PhysicalRect::EnclosingRect(
2579         style.BackdropFilter().MapRect(FloatRect(bounding_box)));
2580   }
2581   return bounding_box;
2582 }
2583 
OverlapBoundsIncludeChildren() const2584 bool PaintLayer::OverlapBoundsIncludeChildren() const {
2585   return HasFilterThatMovesPixels();
2586 }
2587 
ExpandRectForStackingChildren(const PaintLayer & composited_layer,PhysicalRect & result,PaintLayer::CalculateBoundsOptions options) const2588 void PaintLayer::ExpandRectForStackingChildren(
2589     const PaintLayer& composited_layer,
2590     PhysicalRect& result,
2591     PaintLayer::CalculateBoundsOptions options) const {
2592   // If we're locked, th en the subtree does not contribute painted output.
2593   // Furthermore, we might not have up-to-date sizing and position information
2594   // in the subtree, so skip recursing into the subtree.
2595   if (GetLayoutObject().PaintBlockedByDisplayLock(
2596           DisplayLockLifecycleTarget::kChildren)) {
2597     return;
2598   }
2599 
2600   PaintLayerPaintOrderIterator iterator(*this, kAllChildren);
2601   while (PaintLayer* child_layer = iterator.Next()) {
2602     // Here we exclude both directly composited layers and squashing layers
2603     // because those Layers don't paint into the graphics layer
2604     // for this Layer. For example, the bounds of squashed Layers
2605     // will be included in the computation of the appropriate squashing
2606     // GraphicsLayer.
2607     if (options != PaintLayer::CalculateBoundsOptions::
2608                        kIncludeTransformsAndCompositedChildLayers &&
2609         child_layer->GetCompositingState() != kNotComposited)
2610       continue;
2611     result.Unite(child_layer->BoundingBoxForCompositingInternal(
2612         composited_layer, this, options));
2613   }
2614 }
2615 
PhysicalBoundingBoxIncludingStackingChildren(const PhysicalOffset & offset_from_root,CalculateBoundsOptions options) const2616 PhysicalRect PaintLayer::PhysicalBoundingBoxIncludingStackingChildren(
2617     const PhysicalOffset& offset_from_root,
2618     CalculateBoundsOptions options) const {
2619   PhysicalRect result = LocalBoundingBox();
2620   ExpandRectForStackingChildren(*this, result, options);
2621 
2622   result.Move(offset_from_root);
2623   return result;
2624 }
2625 
BoundingBoxForCompositing() const2626 PhysicalRect PaintLayer::BoundingBoxForCompositing() const {
2627   return BoundingBoxForCompositingInternal(
2628       *this, nullptr, kMaybeIncludeTransformForAncestorLayer);
2629 }
2630 
ShouldApplyTransformToBoundingBox(const PaintLayer & composited_layer,CalculateBoundsOptions options) const2631 bool PaintLayer::ShouldApplyTransformToBoundingBox(
2632     const PaintLayer& composited_layer,
2633     CalculateBoundsOptions options) const {
2634   if (!Transform())
2635     return false;
2636   if (options == kIncludeTransformsAndCompositedChildLayers)
2637     return true;
2638   if (PaintsWithTransform(kGlobalPaintNormalPhase)) {
2639     if (this != &composited_layer)
2640       return true;
2641     if (options == kMaybeIncludeTransformForAncestorLayer)
2642       return true;
2643   }
2644   return false;
2645 }
2646 
BoundingBoxForCompositingInternal(const PaintLayer & composited_layer,const PaintLayer * stacking_parent,CalculateBoundsOptions options) const2647 PhysicalRect PaintLayer::BoundingBoxForCompositingInternal(
2648     const PaintLayer& composited_layer,
2649     const PaintLayer* stacking_parent,
2650     CalculateBoundsOptions options) const {
2651   if (!IsSelfPaintingLayer())
2652     return PhysicalRect();
2653 
2654   // FIXME: This could be improved to do a check like
2655   // hasVisibleNonCompositingDescendantLayers() (bug 92580).
2656   if (this != &composited_layer && !HasVisibleContent() &&
2657       !HasVisibleDescendant())
2658     return PhysicalRect();
2659 
2660   if (GetLayoutObject().IsEffectiveRootScroller() || IsRootLayer()) {
2661     // In root layer scrolling mode, the main GraphicsLayer is the size of the
2662     // layout viewport. In non-RLS mode, it is the union of the layout viewport
2663     // and the document's layout overflow rect.
2664     IntRect result = IntRect();
2665     if (LocalFrameView* frame_view = GetLayoutObject().GetFrameView())
2666       result = IntRect(IntPoint(), frame_view->Size());
2667     return PhysicalRect(result);
2668   }
2669 
2670   // The layer created for the LayoutFlowThread is just a helper for painting
2671   // and hit-testing, and should not contribute to the bounding box. The
2672   // LayoutMultiColumnSets will contribute the correct size for the layout
2673   // content of the multicol container.
2674   if (GetLayoutObject().IsLayoutFlowThread())
2675     return PhysicalRect();
2676 
2677   // If there is a clip applied by an ancestor to this PaintLayer but below or
2678   // equal to |ancestorLayer|, apply that clip.
2679   PhysicalRect result = Clipper(GeometryMapperOption::kDoNotUseGeometryMapper)
2680                             .LocalClipRect(composited_layer);
2681 
2682   result.Intersect(LocalBoundingBox());
2683 
2684   ExpandRectForStackingChildren(composited_layer, result, options);
2685 
2686   // Only enlarge by the filter outsets if we know the filter is going to be
2687   // rendered in software.  Accelerated filters will handle their own outsets.
2688   if (PaintsWithFilters())
2689     result = MapRectForFilter(result);
2690 
2691   if (ShouldApplyTransformToBoundingBox(composited_layer, options)) {
2692     result =
2693         PhysicalRect::EnclosingRect(Transform()->MapRect(FloatRect(result)));
2694   }
2695 
2696   if (ShouldFragmentCompositedBounds(&composited_layer)) {
2697     ConvertFromFlowThreadToVisualBoundingBoxInAncestor(&composited_layer,
2698                                                        result);
2699     return result;
2700   }
2701 
2702   if (stacking_parent) {
2703     PhysicalOffset delta;
2704     ConvertToLayerCoords(stacking_parent, delta);
2705     result.Move(delta);
2706   }
2707   return result;
2708 }
2709 
GetCompositingState() const2710 CompositingState PaintLayer::GetCompositingState() const {
2711   DCHECK(IsAllowedToQueryCompositingState());
2712 
2713   // This is computed procedurally so there is no redundant state variable that
2714   // can get out of sync from the real actual compositing state.
2715 
2716   if (GroupedMapping()) {
2717     DCHECK(!GetCompositedLayerMapping());
2718     return kPaintsIntoGroupedBacking;
2719   }
2720 
2721   if (!GetCompositedLayerMapping())
2722     return kNotComposited;
2723 
2724   return kPaintsIntoOwnBacking;
2725 }
2726 
IsAllowedToQueryCompositingState() const2727 bool PaintLayer::IsAllowedToQueryCompositingState() const {
2728   if (g_compositing_query_mode == kCompositingQueriesAreAllowed ||
2729       RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
2730     return true;
2731   return GetLayoutObject().GetDocument().Lifecycle().GetState() >=
2732          DocumentLifecycle::kInCompositingUpdate;
2733 }
2734 
GetCompositedLayerMapping() const2735 CompositedLayerMapping* PaintLayer::GetCompositedLayerMapping() const {
2736   DCHECK(IsAllowedToQueryCompositingState());
2737   return rare_data_ ? rare_data_->composited_layer_mapping.get() : nullptr;
2738 }
2739 
GraphicsLayerBacking(const LayoutObject * obj) const2740 GraphicsLayer* PaintLayer::GraphicsLayerBacking(const LayoutObject* obj) const {
2741   switch (GetCompositingState()) {
2742     case kNotComposited:
2743       return nullptr;
2744     case kPaintsIntoGroupedBacking:
2745       return GroupedMapping()->SquashingLayer();
2746     default:
2747       return (obj != &GetLayoutObject() &&
2748               GetCompositedLayerMapping()->ScrollingContentsLayer())
2749                  ? GetCompositedLayerMapping()->ScrollingContentsLayer()
2750                  : GetCompositedLayerMapping()->MainGraphicsLayer();
2751   }
2752 }
2753 
EnsureCompositedLayerMapping()2754 void PaintLayer::EnsureCompositedLayerMapping() {
2755   if (HasCompositedLayerMapping())
2756     return;
2757 
2758   EnsureRareData().composited_layer_mapping =
2759       std::make_unique<CompositedLayerMapping>(*this);
2760   rare_data_->composited_layer_mapping->SetNeedsGraphicsLayerUpdate(
2761       kGraphicsLayerUpdateSubtree);
2762 }
2763 
ClearCompositedLayerMapping(bool layer_being_destroyed)2764 void PaintLayer::ClearCompositedLayerMapping(bool layer_being_destroyed) {
2765   if (!HasCompositedLayerMapping())
2766     return;
2767 
2768   if (layer_being_destroyed) {
2769     if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
2770       // The visual rects will be in a different coordinate space after losing
2771       // their compositing container. Clear them before prepaint to avoid
2772       // spurious layout shift reports from LayoutShiftTracker.
2773       // If the PaintLayer were not being destroyed, this would happen during
2774       // the compositing update (PaintLayerCompositor::UpdateIfNeeded).
2775       // TODO: LayoutShiftTracker's reliance on having visual rects cleared
2776       // before prepaint in the case of compositing changes is not ideal, and
2777       // will not work with CompositeAfterPaint. Some transform tree changes may
2778       // still produce incorrect behavior from LayoutShiftTracker (see
2779       // discussion on review thread of http://crrev.com/c/1636403).
2780       if (Compositor()) {
2781         Compositor()
2782             ->ForceRecomputeVisualRectsIncludingNonCompositingDescendants(
2783                 layout_object_);
2784       }
2785     }
2786   } else {
2787     // We need to make sure our decendants get a geometry update. In principle,
2788     // we could call setNeedsGraphicsLayerUpdate on our children, but that would
2789     // require walking the z-order lists to find them. Instead, we
2790     // over-invalidate by marking our parent as needing a geometry update.
2791     if (PaintLayer* compositing_parent =
2792             EnclosingLayerWithCompositedLayerMapping(kExcludeSelf))
2793       compositing_parent->GetCompositedLayerMapping()
2794           ->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree);
2795   }
2796   DCHECK(rare_data_);
2797   rare_data_->composited_layer_mapping.reset();
2798 }
2799 
SetGroupedMapping(CompositedLayerMapping * grouped_mapping,SetGroupMappingOptions options)2800 void PaintLayer::SetGroupedMapping(CompositedLayerMapping* grouped_mapping,
2801                                    SetGroupMappingOptions options) {
2802   CompositedLayerMapping* old_grouped_mapping = GroupedMapping();
2803   if (grouped_mapping == old_grouped_mapping)
2804     return;
2805 
2806   if (options == kInvalidateLayerAndRemoveFromMapping && old_grouped_mapping) {
2807     old_grouped_mapping->SetNeedsGraphicsLayerUpdate(
2808         kGraphicsLayerUpdateSubtree);
2809     old_grouped_mapping->RemoveLayerFromSquashingGraphicsLayer(this);
2810   }
2811   if (rare_data_ || grouped_mapping)
2812     EnsureRareData().grouped_mapping = grouped_mapping;
2813 #if DCHECK_IS_ON()
2814   DCHECK(!grouped_mapping ||
2815          grouped_mapping->VerifyLayerInSquashingVector(this));
2816 #endif
2817   if (options == kInvalidateLayerAndRemoveFromMapping && grouped_mapping)
2818     grouped_mapping->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree);
2819 }
2820 
NeedsCompositedScrolling() const2821 bool PaintLayer::NeedsCompositedScrolling() const {
2822   return scrollable_area_ && scrollable_area_->NeedsCompositedScrolling();
2823 }
2824 
PaintsWithTransform(GlobalPaintFlags global_paint_flags) const2825 bool PaintLayer::PaintsWithTransform(
2826     GlobalPaintFlags global_paint_flags) const {
2827   return Transform() && !PaintsIntoOwnBacking(global_paint_flags);
2828 }
2829 
PaintsIntoOwnBacking(GlobalPaintFlags global_paint_flags) const2830 bool PaintLayer::PaintsIntoOwnBacking(
2831     GlobalPaintFlags global_paint_flags) const {
2832   return !(global_paint_flags & kGlobalPaintFlattenCompositingLayers) &&
2833          GetCompositingState() == kPaintsIntoOwnBacking;
2834 }
2835 
PaintsIntoOwnOrGroupedBacking(GlobalPaintFlags global_paint_flags) const2836 bool PaintLayer::PaintsIntoOwnOrGroupedBacking(
2837     GlobalPaintFlags global_paint_flags) const {
2838   return !(global_paint_flags & kGlobalPaintFlattenCompositingLayers) &&
2839          GetCompositingState() != kNotComposited;
2840 }
2841 
SupportsSubsequenceCaching() const2842 bool PaintLayer::SupportsSubsequenceCaching() const {
2843   if (EnclosingPaginationLayer())
2844     return false;
2845 
2846   // SVG paints atomically.
2847   if (GetLayoutObject().IsSVGRoot())
2848     return true;
2849 
2850   // Don't create subsequence for the document element because the subsequence
2851   // for LayoutView serves the same purpose. This can avoid unnecessary paint
2852   // chunks that would otherwise be forced by the subsequence.
2853   if (GetLayoutObject().IsDocumentElement())
2854     return false;
2855 
2856   // Create subsequence for only stacking contexts whose painting are atomic.
2857   return GetLayoutObject().StyleRef().IsStackingContext();
2858 }
2859 
GetScrollingCoordinator()2860 ScrollingCoordinator* PaintLayer::GetScrollingCoordinator() {
2861   Page* page = GetLayoutObject().GetFrame()->GetPage();
2862   return (!page) ? nullptr : page->GetScrollingCoordinator();
2863 }
2864 
CompositesWithTransform() const2865 bool PaintLayer::CompositesWithTransform() const {
2866   return TransformAncestor() || Transform();
2867 }
2868 
CompositesWithOpacity() const2869 bool PaintLayer::CompositesWithOpacity() const {
2870   return OpacityAncestor() || GetLayoutObject().StyleRef().HasOpacity();
2871 }
2872 
BackgroundIsKnownToBeOpaqueInRect(const PhysicalRect & local_rect,bool should_check_children) const2873 bool PaintLayer::BackgroundIsKnownToBeOpaqueInRect(
2874     const PhysicalRect& local_rect,
2875     bool should_check_children) const {
2876   if (PaintsWithTransparency(kGlobalPaintNormalPhase))
2877     return false;
2878 
2879   // We can't use hasVisibleContent(), because that will be true if our
2880   // layoutObject is hidden, but some child is visible and that child doesn't
2881   // cover the entire rect.
2882   if (GetLayoutObject().StyleRef().Visibility() != EVisibility::kVisible)
2883     return false;
2884 
2885   if (GetLayoutObject().HasMask() || GetLayoutObject().HasClipPath())
2886     return false;
2887 
2888   if (PaintsWithFilters() &&
2889       GetLayoutObject().StyleRef().Filter().HasFilterThatAffectsOpacity())
2890     return false;
2891 
2892   // FIXME: Handle simple transforms.
2893   if (Transform() && GetCompositingState() != kPaintsIntoOwnBacking)
2894     return false;
2895 
2896   if (GetLayoutObject().StyleRef().GetPosition() == EPosition::kFixed &&
2897       GetCompositingState() != kPaintsIntoOwnBacking)
2898     return false;
2899 
2900   // FIXME: We currently only check the immediate layoutObject,
2901   // which will miss many cases where additional layout objects paint
2902   // into this layer.
2903   if (GetLayoutObject().BackgroundIsKnownToBeOpaqueInRect(local_rect))
2904     return true;
2905 
2906   if (!should_check_children)
2907     return false;
2908 
2909   // We can't consult child layers if we clip, since they might cover
2910   // parts of the rect that are clipped out.
2911   if (GetLayoutObject().HasClipRelatedProperty())
2912     return false;
2913 
2914   // TODO(schenney): This could be improved by unioning the opaque regions of
2915   // all the children.  That would require a refactoring because currently
2916   // children just check they at least cover the given rect, but a unioning
2917   // method would require children to compute and report their rects.
2918   return ChildBackgroundIsKnownToBeOpaqueInRect(local_rect);
2919 }
2920 
ChildBackgroundIsKnownToBeOpaqueInRect(const PhysicalRect & local_rect) const2921 bool PaintLayer::ChildBackgroundIsKnownToBeOpaqueInRect(
2922     const PhysicalRect& local_rect) const {
2923   PaintLayerPaintOrderReverseIterator reverse_iterator(*this, kAllChildren);
2924   while (PaintLayer* child_layer = reverse_iterator.Next()) {
2925     // Stop at composited paint boundaries and non-self-painting layers.
2926     if (child_layer->IsPaintInvalidationContainer())
2927       continue;
2928 
2929     if (!child_layer->CanUseConvertToLayerCoords())
2930       continue;
2931 
2932     PhysicalOffset child_offset;
2933     PhysicalRect child_local_rect(local_rect);
2934     child_layer->ConvertToLayerCoords(this, child_offset);
2935     child_local_rect.Move(-child_offset);
2936 
2937     if (child_layer->BackgroundIsKnownToBeOpaqueInRect(child_local_rect, true))
2938       return true;
2939   }
2940   return false;
2941 }
2942 
ShouldBeSelfPaintingLayer() const2943 bool PaintLayer::ShouldBeSelfPaintingLayer() const {
2944   return GetLayoutObject().LayerTypeRequired() == kNormalPaintLayer ||
2945          (scrollable_area_ && scrollable_area_->HasOverlayOverflowControls()) ||
2946          ScrollsOverflow();
2947 }
2948 
UpdateSelfPaintingLayer()2949 void PaintLayer::UpdateSelfPaintingLayer() {
2950   bool is_self_painting_layer = ShouldBeSelfPaintingLayer();
2951   if (IsSelfPaintingLayer() == is_self_painting_layer)
2952     return;
2953 
2954   // Invalidate the old subsequences which may no longer contain some
2955   // descendants of this layer because of the self painting status change.
2956   SetNeedsRepaint();
2957   is_self_painting_layer_ = is_self_painting_layer;
2958   self_painting_status_changed_ = true;
2959   // Self-painting change can change the compositing container chain;
2960   // invalidate the new chain in addition to the old one.
2961   MarkCompositingContainerChainForNeedsRepaint();
2962 
2963   if (is_self_painting_layer)
2964     SetNeedsVisualOverflowRecalc();
2965 
2966   if (PaintLayer* parent = Parent()) {
2967     parent->MarkAncestorChainForFlagsUpdate();
2968 
2969     if (PaintLayer* enclosing_self_painting_layer =
2970             parent->EnclosingSelfPaintingLayer()) {
2971       if (is_self_painting_layer)
2972         MergeNeedsPaintPhaseFlagsFrom(*enclosing_self_painting_layer);
2973       else
2974         enclosing_self_painting_layer->MergeNeedsPaintPhaseFlagsFrom(*this);
2975     }
2976   }
2977 }
2978 
EnclosingSelfPaintingLayer()2979 PaintLayer* PaintLayer::EnclosingSelfPaintingLayer() {
2980   PaintLayer* layer = this;
2981   while (layer && !layer->IsSelfPaintingLayer())
2982     layer = layer->Parent();
2983   return layer;
2984 }
2985 
HasNonEmptyChildLayoutObjects() const2986 bool PaintLayer::HasNonEmptyChildLayoutObjects() const {
2987   // Some HTML can cause whitespace text nodes to have layoutObjects, like:
2988   // <div>
2989   // <img src=...>
2990   // </div>
2991   // so test for 0x0 LayoutTexts here
2992   for (LayoutObject* child = GetLayoutObject().SlowFirstChild(); child;
2993        child = child->NextSibling()) {
2994     if (!child->HasLayer()) {
2995       if (child->IsLayoutInline() || !child->IsBox())
2996         return true;
2997 
2998       if (ToLayoutBox(child)->Size().Width() > 0 ||
2999           ToLayoutBox(child)->Size().Height() > 0)
3000         return true;
3001     }
3002   }
3003   return false;
3004 }
3005 
HasBoxDecorationsOrBackground() const3006 bool PaintLayer::HasBoxDecorationsOrBackground() const {
3007   return GetLayoutObject().StyleRef().HasBoxDecorations() ||
3008          GetLayoutObject().StyleRef().HasBackground();
3009 }
3010 
HasVisibleBoxDecorations() const3011 bool PaintLayer::HasVisibleBoxDecorations() const {
3012   if (!HasVisibleContent())
3013     return false;
3014 
3015   return HasBoxDecorationsOrBackground() || HasOverflowControls();
3016 }
3017 
UpdateFilters(const ComputedStyle * old_style,const ComputedStyle & new_style)3018 void PaintLayer::UpdateFilters(const ComputedStyle* old_style,
3019                                const ComputedStyle& new_style) {
3020   if (!filter_on_effect_node_dirty_) {
3021     filter_on_effect_node_dirty_ =
3022         old_style ? !old_style->FilterDataEquivalent(new_style) ||
3023                         !old_style->ReflectionDataEquivalent(new_style)
3024                   : new_style.HasFilterInducingProperty();
3025   }
3026 
3027   if (!new_style.HasFilterInducingProperty() &&
3028       (!old_style || !old_style->HasFilterInducingProperty()))
3029     return;
3030 
3031   const bool had_resource_info = ResourceInfo();
3032   if (new_style.HasFilterInducingProperty())
3033     new_style.Filter().AddClient(EnsureResourceInfo());
3034   if (had_resource_info && old_style)
3035     old_style->Filter().RemoveClient(*ResourceInfo());
3036 }
3037 
UpdateBackdropFilters(const ComputedStyle * old_style,const ComputedStyle & new_style)3038 void PaintLayer::UpdateBackdropFilters(const ComputedStyle* old_style,
3039                                        const ComputedStyle& new_style) {
3040   if (!backdrop_filter_on_effect_node_dirty_) {
3041     backdrop_filter_on_effect_node_dirty_ =
3042         old_style ? !old_style->BackdropFilterDataEquivalent(new_style)
3043                   : new_style.HasBackdropFilter();
3044   }
3045 }
3046 
UpdateClipPath(const ComputedStyle * old_style,const ComputedStyle & new_style)3047 void PaintLayer::UpdateClipPath(const ComputedStyle* old_style,
3048                                 const ComputedStyle& new_style) {
3049   ClipPathOperation* new_clip = new_style.ClipPath();
3050   ClipPathOperation* old_clip = old_style ? old_style->ClipPath() : nullptr;
3051   if (!new_clip && !old_clip)
3052     return;
3053   const bool had_resource_info = ResourceInfo();
3054   if (auto* reference_clip = DynamicTo<ReferenceClipPathOperation>(new_clip))
3055     reference_clip->AddClient(EnsureResourceInfo());
3056   if (had_resource_info) {
3057     if (auto* old_reference_clip =
3058             DynamicTo<ReferenceClipPathOperation>(old_clip))
3059       old_reference_clip->RemoveClient(*ResourceInfo());
3060   }
3061 }
3062 
AttemptDirectCompositingUpdate(const StyleDifference & diff,const ComputedStyle * old_style)3063 bool PaintLayer::AttemptDirectCompositingUpdate(
3064     const StyleDifference& diff,
3065     const ComputedStyle* old_style) {
3066   CompositingReasons old_potential_compositing_reasons_from_style =
3067       PotentialCompositingReasonsFromStyle();
3068   if (Compositor() &&
3069       (diff.HasDifference() || needs_compositing_reasons_update_))
3070     Compositor()->UpdatePotentialCompositingReasonsFromStyle(*this);
3071   needs_compositing_reasons_update_ = false;
3072 
3073   // This function implements an optimization for transforms and opacity.
3074   // A common pattern is for a touchmove handler to update the transform
3075   // and/or an opacity of an element every frame while the user moves their
3076   // finger across the screen. The conditions below recognize when the
3077   // compositing state is set up to receive a direct transform or opacity
3078   // update.
3079 
3080   if (!diff.HasAtMostPropertySpecificDifferences(
3081           StyleDifference::kTransformChanged |
3082           StyleDifference::kOpacityChanged))
3083     return false;
3084   // The potentialCompositingReasonsFromStyle could have changed without
3085   // a corresponding StyleDifference if an animation started or ended.
3086   if (PotentialCompositingReasonsFromStyle() !=
3087       old_potential_compositing_reasons_from_style)
3088     return false;
3089   if (!rare_data_ || !rare_data_->composited_layer_mapping)
3090     return false;
3091 
3092   // If a transform changed, we can't use the fast path.
3093   if (diff.TransformChanged())
3094     return false;
3095 
3096   // We composite transparent Layers differently from non-transparent
3097   // Layers even when the non-transparent Layers are already a
3098   // stacking context.
3099   if (diff.OpacityChanged() &&
3100       layout_object_.StyleRef().HasOpacity() != old_style->HasOpacity())
3101     return false;
3102 
3103   // Changes in pointer-events affect hit test visibility of the scrollable
3104   // area and its |m_scrollsOverflow| value which determines if the layer
3105   // requires composited scrolling or not.
3106   if (scrollable_area_ &&
3107       layout_object_.StyleRef().PointerEvents() != old_style->PointerEvents())
3108     return false;
3109 
3110   UpdateTransform(old_style, GetLayoutObject().StyleRef());
3111 
3112   // FIXME: Consider introducing a smaller graphics layer update scope
3113   // that just handles transforms and opacity. GraphicsLayerUpdateLocal
3114   // will also program bounds, clips, and many other properties that could
3115   // not possibly have changed.
3116   rare_data_->composited_layer_mapping->SetNeedsGraphicsLayerUpdate(
3117       kGraphicsLayerUpdateLocal);
3118   if (Compositor()) {
3119     Compositor()->SetNeedsCompositingUpdate(
3120         kCompositingUpdateAfterGeometryChange);
3121   }
3122 
3123   if (RequiresScrollableArea()) {
3124     DCHECK(scrollable_area_);
3125     scrollable_area_->UpdateAfterStyleChange(old_style);
3126   }
3127 
3128   return true;
3129 }
3130 
StyleDidChange(StyleDifference diff,const ComputedStyle * old_style)3131 void PaintLayer::StyleDidChange(StyleDifference diff,
3132                                 const ComputedStyle* old_style) {
3133   UpdateScrollableArea();
3134 
3135   if (AttemptDirectCompositingUpdate(diff, old_style)) {
3136     if (diff.HasDifference())
3137       GetLayoutObject().SetNeedsPaintPropertyUpdate();
3138     return;
3139   }
3140 
3141   if (PaintLayerStackingNode::StyleDidChange(*this, old_style))
3142     MarkAncestorChainForFlagsUpdate();
3143 
3144   if (RequiresScrollableArea()) {
3145     DCHECK(scrollable_area_);
3146     scrollable_area_->UpdateAfterStyleChange(old_style);
3147   }
3148 
3149   // Overlay scrollbars can make this layer self-painting so we need
3150   // to recompute the bit once scrollbars have been updated.
3151   UpdateSelfPaintingLayer();
3152 
3153   const ComputedStyle& new_style = GetLayoutObject().StyleRef();
3154 
3155   if (diff.CompositingReasonsChanged()) {
3156     SetNeedsCompositingInputsUpdate();
3157   } else {
3158     // For querying stale GetCompositingState().
3159     DisableCompositingQueryAsserts disable;
3160 
3161     // Compositing inputs update is required when the PaintLayer is currently
3162     // composited. This is because even style changes as simple as background
3163     // color change, or pointer-events state change, can update compositing
3164     // state.
3165     if (old_style && GetCompositingState() == kPaintsIntoOwnBacking)
3166       SetNeedsCompositingInputsUpdate();
3167   }
3168 
3169   // HasAlphaChanged can affect whether a composited layer is opaque.
3170   if (diff.NeedsLayout() || diff.HasAlphaChanged())
3171     SetNeedsCompositingInputsUpdate();
3172 
3173   // A scroller that changes background color might become opaque or not
3174   // opaque, which in turn affects whether it can be composited on low-DPI
3175   // screens.
3176   if (GetScrollableArea() && GetScrollableArea()->ScrollsOverflow() &&
3177       diff.HasDifference()) {
3178     SetNeedsCompositingInputsUpdate();
3179   }
3180 
3181   if (diff.TransformChanged() || diff.OpacityChanged() ||
3182       diff.ZIndexChanged() || diff.FilterChanged() ||
3183       diff.BackdropFilterChanged() || diff.CssClipChanged() ||
3184       diff.BlendModeChanged() || diff.MaskChanged()) {
3185     GetLayoutObject().SetNeedsPaintPropertyUpdate();
3186     SetNeedsCompositingInputsUpdate();
3187   }
3188 
3189   // HasNonContainedAbsolutePositionDescendant depends on position changes.
3190   if (!old_style || old_style->GetPosition() != new_style.GetPosition())
3191     MarkAncestorChainForFlagsUpdate();
3192 
3193   UpdateTransform(old_style, new_style);
3194   UpdateFilters(old_style, new_style);
3195   UpdateBackdropFilters(old_style, new_style);
3196   UpdateClipPath(old_style, new_style);
3197 
3198   if (!SelfNeedsRepaint()) {
3199     if (diff.ZIndexChanged()) {
3200       // We don't need to invalidate paint of objects when paint order
3201       // changes. However, we do need to repaint the containing stacking
3202       // context, in order to generate new paint chunks in the correct order.
3203       // Raster invalidation will be issued if needed during paint.
3204       SetNeedsRepaint();
3205     } else if (old_style &&
3206                !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
3207       // Change of PaintedOutputInvisible() will affect existence of paint
3208       // chunks, so needs repaint.
3209       if (PaintLayerPainter::PaintedOutputInvisible(*old_style) !=
3210           PaintLayerPainter::PaintedOutputInvisible(new_style))
3211         SetNeedsRepaint();
3212     }
3213   }
3214 }
3215 
PixelSnappedScrolledContentOffset() const3216 LayoutSize PaintLayer::PixelSnappedScrolledContentOffset() const {
3217   if (GetLayoutObject().HasOverflowClip())
3218     return GetLayoutBox()->PixelSnappedScrolledContentOffset();
3219   return LayoutSize();
3220 }
3221 
Clipper(GeometryMapperOption geometry_mapper_option) const3222 PaintLayerClipper PaintLayer::Clipper(
3223     GeometryMapperOption geometry_mapper_option) const {
3224   return PaintLayerClipper(*this, geometry_mapper_option ==
3225                                       GeometryMapperOption::kUseGeometryMapper);
3226 }
3227 
ScrollsOverflow() const3228 bool PaintLayer::ScrollsOverflow() const {
3229   if (PaintLayerScrollableArea* scrollable_area = GetScrollableArea())
3230     return scrollable_area->ScrollsOverflow();
3231 
3232   return false;
3233 }
3234 
FilterOperationsIncludingReflection() const3235 FilterOperations PaintLayer::FilterOperationsIncludingReflection() const {
3236   const auto& style = GetLayoutObject().StyleRef();
3237   FilterOperations filter_operations = style.Filter();
3238   if (GetLayoutObject().HasReflection() && GetLayoutObject().IsBox()) {
3239     BoxReflection reflection = BoxReflectionForPaintLayer(*this, style);
3240     filter_operations.Operations().push_back(
3241         MakeGarbageCollected<BoxReflectFilterOperation>(reflection));
3242   }
3243   return filter_operations;
3244 }
3245 
UpdateCompositorFilterOperationsForFilter(CompositorFilterOperations & operations) const3246 void PaintLayer::UpdateCompositorFilterOperationsForFilter(
3247     CompositorFilterOperations& operations) const {
3248   auto filter = FilterOperationsIncludingReflection();
3249   FloatRect reference_box = FilterReferenceBox();
3250   if (!operations.IsEmpty() && !filter_on_effect_node_dirty_ &&
3251       reference_box == operations.ReferenceBox())
3252     return;
3253   float zoom = GetLayoutObject().StyleRef().EffectiveZoom();
3254   operations =
3255       FilterEffectBuilder(reference_box, zoom).BuildFilterOperations(filter);
3256 }
3257 
UpdateCompositorFilterOperationsForBackdropFilter(CompositorFilterOperations & operations,base::Optional<gfx::RRectF> * backdrop_filter_bounds) const3258 void PaintLayer::UpdateCompositorFilterOperationsForBackdropFilter(
3259     CompositorFilterOperations& operations,
3260     base::Optional<gfx::RRectF>* backdrop_filter_bounds) const {
3261   DCHECK(backdrop_filter_bounds);
3262   const auto& style = GetLayoutObject().StyleRef();
3263   if (style.BackdropFilter().IsEmpty()) {
3264     operations.Clear();
3265     backdrop_filter_bounds->reset();
3266     return;
3267   }
3268   FloatRect reference_box = BackdropFilterReferenceBox();
3269   *backdrop_filter_bounds = BackdropFilterBounds(reference_box);
3270   if (operations.IsEmpty() || backdrop_filter_on_effect_node_dirty_ ||
3271       reference_box != operations.ReferenceBox()) {
3272     operations = CreateCompositorFilterOperationsForBackdropFilter();
3273   }
3274 }
3275 
3276 CompositorFilterOperations
CreateCompositorFilterOperationsForBackdropFilter() const3277 PaintLayer::CreateCompositorFilterOperationsForBackdropFilter() const {
3278   const auto& style = GetLayoutObject().StyleRef();
3279   CompositorFilterOperations return_value;
3280   if (style.BackdropFilter().IsEmpty()) {
3281     return return_value;
3282   }
3283   float zoom = style.EffectiveZoom();
3284   FloatRect reference_box = BackdropFilterReferenceBox();
3285   // Tack on regular filter values here - they need to be applied to the
3286   // backdrop image as well, in addition to being applied to the painted content
3287   // and children of the element. This is a bit of a hack - according to the
3288   // spec, filters should apply to the entire render pass as a whole, including
3289   // the backdrop-filtered content. However, because in the case that we have
3290   // both filters and backdrop-filters on a single element, we create two effect
3291   // nodes, and two render surfaces, and the backdrop-filter node comes first.
3292   // To get around that, we add the "regular" filters to the backdrop filters to
3293   // approximate.
3294   FilterOperations filter_operations = style.BackdropFilter();
3295   filter_operations.Operations().AppendVector(style.Filter().Operations());
3296   // Use kClamp tile mode to avoid pixel moving filters bringing in black
3297   // transparent pixels from the viewport edge.
3298   return_value = FilterEffectBuilder(reference_box, zoom, nullptr, nullptr,
3299                                      SkBlurImageFilter::kClamp_TileMode)
3300                      .BuildFilterOperations(filter_operations);
3301   // Note that return_value may be empty here, if the |filter_operations| list
3302   // contains only invalid filters (e.g. invalid reference filters). See
3303   // https://crbug.com/983157 for details.
3304   return return_value;
3305 }
3306 
EnsureResourceInfo()3307 PaintLayerResourceInfo& PaintLayer::EnsureResourceInfo() {
3308   PaintLayerRareData& rare_data = EnsureRareData();
3309   if (!rare_data.resource_info) {
3310     rare_data.resource_info =
3311         MakeGarbageCollected<PaintLayerResourceInfo>(this);
3312   }
3313   return *rare_data.resource_info;
3314 }
3315 
RemoveAncestorOverflowLayer(const PaintLayer * removed_layer)3316 void PaintLayer::RemoveAncestorOverflowLayer(const PaintLayer* removed_layer) {
3317   // If the current ancestor overflow layer does not match the removed layer
3318   // the ancestor overflow layer has changed so we can stop searching.
3319   if (AncestorOverflowLayer() && AncestorOverflowLayer() != removed_layer)
3320     return;
3321 
3322   if (AncestorOverflowLayer()) {
3323     // If the previous AncestorOverflowLayer is the root and this object is a
3324     // sticky viewport constrained object, it is no longer known to be
3325     // constrained by the root.
3326     if (AncestorOverflowLayer()->IsRootLayer() &&
3327         GetLayoutObject().StyleRef().HasStickyConstrainedPosition()) {
3328       if (LocalFrameView* frame_view = GetLayoutObject().GetFrameView())
3329         frame_view->RemoveViewportConstrainedObject(GetLayoutObject());
3330     }
3331 
3332     if (PaintLayerScrollableArea* ancestor_scrollable_area =
3333             AncestorOverflowLayer()->GetScrollableArea()) {
3334       // TODO(pdr): When CompositeAfterPaint is enabled, we will need to
3335       // invalidate the scroll paint property subtree for this so main thread
3336       // scroll reasons are recomputed.
3337       ancestor_scrollable_area->InvalidateStickyConstraintsFor(this);
3338     }
3339   }
3340   UpdateAncestorOverflowLayer(nullptr);
3341   PaintLayer* current = first_;
3342   while (current) {
3343     current->RemoveAncestorOverflowLayer(removed_layer);
3344     current = current->NextSibling();
3345   }
3346 }
3347 
MapRectForFilter(const FloatRect & rect) const3348 FloatRect PaintLayer::MapRectForFilter(const FloatRect& rect) const {
3349   if (!HasFilterThatMovesPixels())
3350     return rect;
3351   return FilterOperationsIncludingReflection().MapRect(rect);
3352 }
3353 
MapRectForFilter(const PhysicalRect & rect) const3354 PhysicalRect PaintLayer::MapRectForFilter(const PhysicalRect& rect) const {
3355   if (!HasFilterThatMovesPixels())
3356     return rect;
3357   return PhysicalRect::EnclosingRect(MapRectForFilter(FloatRect(rect)));
3358 }
3359 
HasFilterThatMovesPixels() const3360 bool PaintLayer::HasFilterThatMovesPixels() const {
3361   if (!HasFilterInducingProperty())
3362     return false;
3363   const ComputedStyle& style = GetLayoutObject().StyleRef();
3364   if (style.HasFilter() && style.Filter().HasFilterThatMovesPixels())
3365     return true;
3366   if (GetLayoutObject().HasReflection())
3367     return true;
3368   return false;
3369 }
3370 
SetNeedsRepaint()3371 void PaintLayer::SetNeedsRepaint() {
3372   SetSelfNeedsRepaint();
3373 
3374   // If you need repaint, then you might issue raster invalidations, and in
3375   // Composite after Paint mode, we do these in PAC::Update().
3376   LocalFrameView* frame_view = GetLayoutObject().GetDocument().View();
3377   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && frame_view) {
3378     frame_view->SetPaintArtifactCompositorNeedsUpdate();
3379   }
3380 
3381   // Do this unconditionally to ensure container chain is marked when
3382   // compositing status of the layer changes.
3383   MarkCompositingContainerChainForNeedsRepaint();
3384 }
3385 
SetSelfNeedsRepaint()3386 void PaintLayer::SetSelfNeedsRepaint() {
3387   self_needs_repaint_ = true;
3388   // Invalidate as a display item client.
3389   static_cast<DisplayItemClient*>(this)->Invalidate();
3390 }
3391 
MarkCompositingContainerChainForNeedsRepaint()3392 void PaintLayer::MarkCompositingContainerChainForNeedsRepaint() {
3393   // Need to access compositingState(). We've ensured correct flag setting when
3394   // compositingState() changes.
3395   DisableCompositingQueryAsserts disabler;
3396 
3397   PaintLayer* layer = this;
3398   while (true) {
3399     if (layer->GetCompositingState() == kPaintsIntoOwnBacking)
3400       return;
3401     if (CompositedLayerMapping* grouped_mapping = layer->GroupedMapping()) {
3402       // TODO(wkorman): As we clean up the CompositedLayerMapping needsRepaint
3403       // logic to delegate to scrollbars, we may be able to remove the line
3404       // below as well.
3405       grouped_mapping->OwningLayer().SetNeedsRepaint();
3406       return;
3407     }
3408 
3409     // For a non-self-painting layer having self-painting descendant, the
3410     // descendant will be painted through this layer's Parent() instead of
3411     // this layer's Container(), so in addition to the CompositingContainer()
3412     // chain, we also need to mark NeedsRepaint for Parent().
3413     // TODO(crbug.com/828103): clean up this.
3414     if (layer->Parent() && !layer->IsSelfPaintingLayer())
3415       layer->Parent()->SetNeedsRepaint();
3416 
3417     PaintLayer* container = layer->CompositingContainer();
3418     if (!container) {
3419       auto* owner = layer->GetLayoutObject().GetFrame()->OwnerLayoutObject();
3420       if (!owner)
3421         break;
3422       container = owner->EnclosingLayer();
3423     }
3424 
3425     if (container->descendant_needs_repaint_)
3426       break;
3427 
3428     container->descendant_needs_repaint_ = true;
3429     layer = container;
3430   }
3431 }
3432 
ClearNeedsRepaintRecursively()3433 void PaintLayer::ClearNeedsRepaintRecursively() {
3434   for (PaintLayer* child = FirstChild(); child; child = child->NextSibling())
3435     child->ClearNeedsRepaintRecursively();
3436   self_needs_repaint_ = false;
3437   descendant_needs_repaint_ = false;
3438 }
3439 
CommonAncestor(const PaintLayer * other) const3440 const PaintLayer* PaintLayer::CommonAncestor(const PaintLayer* other) const {
3441   DCHECK(other);
3442   if (this == other)
3443     return this;
3444 
3445   int this_depth = 0;
3446   for (auto* layer = this; layer; layer = layer->Parent()) {
3447     if (layer == other)
3448       return layer;
3449     this_depth++;
3450   }
3451   int other_depth = 0;
3452   for (auto* layer = other; layer; layer = layer->Parent()) {
3453     if (layer == this)
3454       return layer;
3455     other_depth++;
3456   }
3457 
3458   const PaintLayer* this_iterator = this;
3459   const PaintLayer* other_iterator = other;
3460   for (; this_depth > other_depth; this_depth--)
3461     this_iterator = this_iterator->Parent();
3462   for (; other_depth > this_depth; other_depth--)
3463     other_iterator = other_iterator->Parent();
3464 
3465   while (this_iterator) {
3466     if (this_iterator == other_iterator)
3467       return this_iterator;
3468     this_iterator = this_iterator->Parent();
3469     other_iterator = other_iterator->Parent();
3470   }
3471 
3472   DCHECK(!this_iterator);
3473   DCHECK(!other_iterator);
3474   return nullptr;
3475 }
3476 
DirtyStackingContextZOrderLists()3477 void PaintLayer::DirtyStackingContextZOrderLists() {
3478   auto* stacking_context = AncestorStackingContext();
3479   if (!stacking_context)
3480     return;
3481 
3482   // This invalidation code intentionally refers to stale state.
3483   DisableCompositingQueryAsserts disabler;
3484 
3485   // Changes of stacking may result in graphics layers changing size
3486   // due to new contents painting into them.
3487   if (auto* mapping = stacking_context->GetCompositedLayerMapping())
3488     mapping->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree);
3489 
3490   if (stacking_context->StackingNode())
3491     stacking_context->StackingNode()->DirtyZOrderLists();
3492 
3493   MarkAncestorChainForFlagsUpdate();
3494 }
3495 
DisableCompositingQueryAsserts()3496 DisableCompositingQueryAsserts::DisableCompositingQueryAsserts()
3497     : disabler_(&g_compositing_query_mode, kCompositingQueriesAreAllowed) {}
3498 
3499 }  // namespace blink
3500 
3501 #if DCHECK_IS_ON()
showLayerTree(const blink::PaintLayer * layer)3502 void showLayerTree(const blink::PaintLayer* layer) {
3503   blink::DisableCompositingQueryAsserts disabler;
3504   if (!layer) {
3505     LOG(ERROR) << "Cannot showLayerTree. Root is (nil)";
3506     return;
3507   }
3508 
3509   if (blink::LocalFrame* frame = layer->GetLayoutObject().GetFrame()) {
3510     WTF::String output =
3511         ExternalRepresentation(frame,
3512                                blink::kLayoutAsTextShowAllLayers |
3513                                    blink::kLayoutAsTextShowLayerNesting |
3514                                    blink::kLayoutAsTextShowCompositedLayers |
3515                                    blink::kLayoutAsTextShowAddresses |
3516                                    blink::kLayoutAsTextShowIDAndClass |
3517                                    blink::kLayoutAsTextDontUpdateLayout |
3518                                    blink::kLayoutAsTextShowLayoutState |
3519                                    blink::kLayoutAsTextShowPaintProperties,
3520                                layer);
3521     LOG(ERROR) << output.Utf8();
3522   }
3523 }
3524 
showLayerTree(const blink::LayoutObject * layoutObject)3525 void showLayerTree(const blink::LayoutObject* layoutObject) {
3526   if (!layoutObject) {
3527     LOG(ERROR) << "Cannot showLayerTree. Root is (nil)";
3528     return;
3529   }
3530   showLayerTree(layoutObject->EnclosingLayer());
3531 }
3532 #endif
3533