1 /*
2  * Copyright (C) 2009, 2010, 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
27 
28 #include <memory>
29 
30 #include "cc/layers/picture_layer.h"
31 #include "third_party/blink/renderer/core/accessibility/apply_dark_mode.h"
32 #include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
33 #include "third_party/blink/renderer/core/dom/dom_node_ids.h"
34 #include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
35 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
36 #include "third_party/blink/renderer/core/frame/remote_frame.h"
37 #include "third_party/blink/renderer/core/frame/settings.h"
38 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
39 #include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
40 #include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
41 #include "third_party/blink/renderer/core/html/html_iframe_element.h"
42 #include "third_party/blink/renderer/core/html/html_image_element.h"
43 #include "third_party/blink/renderer/core/html/media/html_media_element.h"
44 #include "third_party/blink/renderer/core/html/media/html_video_element.h"
45 #include "third_party/blink/renderer/core/html_names.h"
46 #include "third_party/blink/renderer/core/layout/geometry/transform_state.h"
47 #include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
48 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
49 #include "third_party/blink/renderer/core/layout/layout_embedded_object.h"
50 #include "third_party/blink/renderer/core/layout/layout_html_canvas.h"
51 #include "third_party/blink/renderer/core/layout/layout_image.h"
52 #include "third_party/blink/renderer/core/layout/layout_inline.h"
53 #include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
54 #include "third_party/blink/renderer/core/layout/layout_video.h"
55 #include "third_party/blink/renderer/core/layout/layout_view.h"
56 #include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
57 #include "third_party/blink/renderer/core/page/chrome_client.h"
58 #include "third_party/blink/renderer/core/page/page.h"
59 #include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
60 #include "third_party/blink/renderer/core/page/scrolling/snap_coordinator.h"
61 #include "third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h"
62 #include "third_party/blink/renderer/core/paint/clip_path_clipper.h"
63 #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
64 #include "third_party/blink/renderer/core/paint/css_mask_painter.h"
65 #include "third_party/blink/renderer/core/paint/frame_paint_timing.h"
66 #include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
67 #include "third_party/blink/renderer/core/paint/paint_info.h"
68 #include "third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h"
69 #include "third_party/blink/renderer/core/paint/paint_layer_painter.h"
70 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
71 #include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
72 #include "third_party/blink/renderer/core/probe/core_probes.h"
73 #include "third_party/blink/renderer/platform/fonts/font_cache.h"
74 #include "third_party/blink/renderer/platform/geometry/length_functions.h"
75 #include "third_party/blink/renderer/platform/graphics/bitmap_image.h"
76 #include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
77 #include "third_party/blink/renderer/platform/graphics/graphics_context.h"
78 #include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
79 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
80 #include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
81 #include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
82 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
83 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
84 
85 namespace blink {
86 
ContentsRect(const LayoutObject & layout_object)87 static PhysicalRect ContentsRect(const LayoutObject& layout_object) {
88   if (!layout_object.IsBox())
89     return PhysicalRect();
90   if (layout_object.IsLayoutReplaced())
91     return ToLayoutReplaced(layout_object).ReplacedContentRect();
92   return ToLayoutBox(layout_object).PhysicalContentBoxRect();
93 }
94 
BackgroundRect(const LayoutObject & layout_object)95 static PhysicalRect BackgroundRect(const LayoutObject& layout_object) {
96   if (!layout_object.IsBox())
97     return PhysicalRect();
98 
99   const LayoutBox& box = ToLayoutBox(layout_object);
100   return box.PhysicalBackgroundRect(kBackgroundClipRect);
101 }
102 
IsTextureLayerCanvas(const LayoutObject & layout_object)103 static inline bool IsTextureLayerCanvas(const LayoutObject& layout_object) {
104   if (layout_object.IsCanvas()) {
105     auto* canvas = To<HTMLCanvasElement>(layout_object.GetNode());
106     if (canvas->SurfaceLayerBridge())
107       return false;
108     if (CanvasRenderingContext* context = canvas->RenderingContext())
109       return context->IsComposited();
110   }
111   return false;
112 }
113 
IsSurfaceLayerCanvas(const LayoutObject & layout_object)114 static inline bool IsSurfaceLayerCanvas(const LayoutObject& layout_object) {
115   if (layout_object.IsCanvas()) {
116     auto* canvas = To<HTMLCanvasElement>(layout_object.GetNode());
117     return canvas->SurfaceLayerBridge();
118   }
119   return false;
120 }
121 
HasBoxDecorationsOrBackgroundImage(const ComputedStyle & style)122 static bool HasBoxDecorationsOrBackgroundImage(const ComputedStyle& style) {
123   return style.HasBoxDecorations() || style.HasBackgroundImage();
124 }
125 
ContentLayerSupportsDirectBackgroundComposition(const LayoutObject & layout_object)126 static bool ContentLayerSupportsDirectBackgroundComposition(
127     const LayoutObject& layout_object) {
128   // No support for decorations - border, border-radius or outline.
129   // Only simple background - solid color or transparent.
130   if (HasBoxDecorationsOrBackgroundImage(layout_object.StyleRef()))
131     return false;
132 
133   // If there is no background, there is nothing to support.
134   if (!layout_object.StyleRef().HasBackground())
135     return true;
136 
137   // Simple background that is contained within the contents rect.
138   return ContentsRect(layout_object).Contains(BackgroundRect(layout_object));
139 }
140 
GetPluginContainer(LayoutObject & layout_object)141 static WebPluginContainerImpl* GetPluginContainer(LayoutObject& layout_object) {
142   if (!layout_object.IsEmbeddedObject())
143     return nullptr;
144   return ToLayoutEmbeddedObject(layout_object).Plugin();
145 }
146 
147 // Returns true if the compositor will be responsible for applying the sticky
148 // position offset for this composited layer.
UsesCompositedStickyPosition(PaintLayer & layer)149 static bool UsesCompositedStickyPosition(PaintLayer& layer) {
150   return layer.GetLayoutObject().StyleRef().HasStickyConstrainedPosition() &&
151          layer.AncestorOverflowLayer()->NeedsCompositedScrolling();
152 }
153 
154 // Returns the sticky position offset that should be removed from a given layer
155 // for use in CompositedLayerMapping.
156 //
157 // If the layer is not using composited sticky position, this will return
158 // FloatPoint().
StickyPositionOffsetForLayer(PaintLayer & layer)159 static FloatPoint StickyPositionOffsetForLayer(PaintLayer& layer) {
160   if (!UsesCompositedStickyPosition(layer))
161     return FloatPoint();
162 
163   const StickyConstraintsMap& constraints_map = layer.AncestorOverflowLayer()
164                                                     ->GetScrollableArea()
165                                                     ->GetStickyConstraintsMap();
166   const StickyPositionScrollingConstraints& constraints =
167       constraints_map.at(&layer);
168 
169   return FloatPoint(constraints.GetOffsetForStickyPosition(constraints_map));
170 }
171 
NeedsDecorationOutlineLayer(const PaintLayer & paint_layer,const LayoutObject & layout_object)172 static bool NeedsDecorationOutlineLayer(const PaintLayer& paint_layer,
173                                         const LayoutObject& layout_object) {
174   int min_border_width = std::min(
175       layout_object.StyleRef().BorderTopWidth(),
176       std::min(layout_object.StyleRef().BorderLeftWidth(),
177                std::min(layout_object.StyleRef().BorderRightWidth(),
178                         layout_object.StyleRef().BorderBottomWidth())));
179 
180   bool could_obscure_decorations =
181       (paint_layer.GetScrollableArea() &&
182        paint_layer.GetScrollableArea()->UsesCompositedScrolling()) ||
183       layout_object.IsCanvas() || IsA<LayoutVideo>(layout_object);
184 
185   return could_obscure_decorations && layout_object.StyleRef().HasOutline() &&
186          layout_object.StyleRef().OutlineOffset() < -min_border_width;
187 }
188 
CompositedLayerMapping(PaintLayer & layer)189 CompositedLayerMapping::CompositedLayerMapping(PaintLayer& layer)
190     : owning_layer_(layer),
191       pending_update_scope_(kGraphicsLayerUpdateNone),
192       scrolling_contents_are_empty_(false),
193       draws_background_onto_content_layer_(false) {
194   CreatePrimaryGraphicsLayer();
195 }
196 
~CompositedLayerMapping()197 CompositedLayerMapping::~CompositedLayerMapping() {
198   // Do not leave the destroyed pointer dangling on any Layers that painted to
199   // this mapping's squashing layer.
200   for (wtf_size_t i = 0; i < squashed_layers_.size(); ++i) {
201     PaintLayer* old_squashed_layer = squashed_layers_[i].paint_layer;
202     // Assert on incorrect mappings between layers and groups
203     DCHECK_EQ(old_squashed_layer->GroupedMapping(), this);
204     if (old_squashed_layer->GroupedMapping() == this) {
205       old_squashed_layer->SetGroupedMapping(
206           nullptr, PaintLayer::kDoNotInvalidateLayerAndRemoveFromMapping);
207       old_squashed_layer->SetLostGroupedMapping(true);
208     }
209   }
210 
211   UpdateOverflowControlsLayers(false, false, false);
212   UpdateForegroundLayer(false);
213   UpdateMaskLayer(false);
214   UpdateScrollingLayers(false);
215   UpdateSquashingLayers(false);
216 }
217 
CreateGraphicsLayer(CompositingReasons reasons,SquashingDisallowedReasons squashing_disallowed_reasons)218 std::unique_ptr<GraphicsLayer> CompositedLayerMapping::CreateGraphicsLayer(
219     CompositingReasons reasons,
220     SquashingDisallowedReasons squashing_disallowed_reasons) {
221   auto graphics_layer = std::make_unique<GraphicsLayer>(*this);
222 
223   graphics_layer->SetCompositingReasons(reasons);
224   graphics_layer->SetSquashingDisallowedReasons(squashing_disallowed_reasons);
225   if (Node* owning_node = owning_layer_.GetLayoutObject().GetNode()) {
226     graphics_layer->SetOwnerNodeId(
227         static_cast<int>(DOMNodeIds::IdForNode(owning_node)));
228   }
229 
230   // Attempt to associate each layer with the frame owner's element ID.
231   Document* owner = nullptr;
232   if (GetLayoutObject().IsLayoutEmbeddedContent()) {
233     auto& embedded = ToLayoutEmbeddedContent(GetLayoutObject());
234     if (auto* frame_view =
235             DynamicTo<LocalFrameView>(embedded.GetEmbeddedContentView())) {
236       owner = frame_view->GetFrame().GetDocument();
237     } else {
238       // Ignore remote and plugin frames.
239     }
240   } else {
241     owner = &GetLayoutObject().GetDocument();
242   }
243   if (owner) {
244     graphics_layer->CcLayer()->SetFrameElementId(
245         CompositorElementIdFromUniqueObjectId(
246             DOMNodeIds::IdForNode(owner),
247             CompositorElementIdNamespace::kDOMNodeId));
248   }
249 
250   return graphics_layer;
251 }
252 
CreatePrimaryGraphicsLayer()253 void CompositedLayerMapping::CreatePrimaryGraphicsLayer() {
254   graphics_layer_ =
255       CreateGraphicsLayer(owning_layer_.GetCompositingReasons(),
256                           owning_layer_.GetSquashingDisallowedReasons());
257 
258   graphics_layer_->SetHitTestable(true);
259 }
260 
UpdateContentsOpaque()261 void CompositedLayerMapping::UpdateContentsOpaque() {
262   // If there is a foreground layer, children paint into that layer and
263   // not graphics_layer_, and so don't contribute to the opaqueness of the
264   // latter.
265   bool should_check_children = !foreground_layer_.get();
266   if (IsTextureLayerCanvas(GetLayoutObject())) {
267     CanvasRenderingContext* context =
268         To<HTMLCanvasElement>(GetLayoutObject().GetNode())->RenderingContext();
269     cc::Layer* layer = context ? context->CcLayer() : nullptr;
270     // Determine whether the external texture layer covers the whole graphics
271     // layer. This may not be the case if there are box decorations or
272     // shadows.
273     if (layer && layer->bounds() == graphics_layer_->CcLayer()->bounds()) {
274       // Determine whether the rendering context's external texture layer is
275       // opaque.
276       if (!context->CreationAttributes().alpha) {
277         graphics_layer_->SetContentsOpaque(true);
278       } else {
279         graphics_layer_->SetContentsOpaque(
280             !Color(layer->background_color()).HasAlpha());
281       }
282     } else {
283       graphics_layer_->SetContentsOpaque(false);
284     }
285   } else if (IsSurfaceLayerCanvas(GetLayoutObject())) {
286     // TODO(crbug.com/705019): Contents could be opaque, but that cannot be
287     // determined from the main thread. Or can it?
288     graphics_layer_->SetContentsOpaque(false);
289   } else if (BackgroundPaintsOntoScrollingContentsLayer()) {
290     DCHECK(HasScrollingLayer());
291     // Backgrounds painted onto the foreground are clipped by the padding box
292     // rect.
293     // TODO(flackr): This should actually check the entire overflow rect
294     // within the scrolling contents layer but since we currently only trigger
295     // this for solid color backgrounds the answer will be the same.
296     scrolling_contents_layer_->SetContentsOpaque(
297         owning_layer_.BackgroundIsKnownToBeOpaqueInRect(
298             ToLayoutBox(GetLayoutObject()).PhysicalPaddingBoxRect(),
299             should_check_children));
300 
301     if (BackgroundPaintsOntoGraphicsLayer()) {
302       graphics_layer_->SetContentsOpaque(
303           owning_layer_.BackgroundIsKnownToBeOpaqueInRect(
304               CompositedBounds(), should_check_children));
305     } else {
306       // If we only paint the background onto the scrolling contents layer we
307       // are going to leave a hole in the m_graphicsLayer where the background
308       // is so it is not opaque.
309       graphics_layer_->SetContentsOpaque(false);
310     }
311   } else {
312     DCHECK(BackgroundPaintsOntoGraphicsLayer());
313     if (HasScrollingLayer())
314       scrolling_contents_layer_->SetContentsOpaque(false);
315     graphics_layer_->SetContentsOpaque(
316         owning_layer_.BackgroundIsKnownToBeOpaqueInRect(CompositedBounds(),
317                                                         should_check_children));
318   }
319 }
320 
UpdateRasterizationPolicy()321 void CompositedLayerMapping::UpdateRasterizationPolicy() {
322   bool transformed_rasterization_allowed =
323       !(owning_layer_.GetCompositingReasons() &
324         CompositingReason::kComboAllDirectReasons);
325   graphics_layer_->CcLayer()->SetTransformedRasterizationAllowed(
326       transformed_rasterization_allowed);
327   if (squashing_layer_)
328     squashing_layer_->CcLayer()->SetTransformedRasterizationAllowed(true);
329 }
330 
UpdateCompositedBounds()331 void CompositedLayerMapping::UpdateCompositedBounds() {
332   DCHECK_EQ(owning_layer_.Compositor()->Lifecycle().GetState(),
333             DocumentLifecycle::kInCompositingUpdate);
334   // FIXME: if this is really needed for performance, it would be better to
335   // store it on Layer.
336   composited_bounds_ = owning_layer_.BoundingBoxForCompositing();
337 }
338 
UpdateCompositingReasons()339 void CompositedLayerMapping::UpdateCompositingReasons() {
340   // All other layers owned by this mapping will have the same compositing
341   // reason for their lifetime, so they are initialized only when created.
342   graphics_layer_->SetCompositingReasons(owning_layer_.GetCompositingReasons());
343   graphics_layer_->SetSquashingDisallowedReasons(
344       owning_layer_.GetSquashingDisallowedReasons());
345 }
346 
UpdateGraphicsLayerConfiguration(const PaintLayer * compositing_container)347 bool CompositedLayerMapping::UpdateGraphicsLayerConfiguration(
348     const PaintLayer* compositing_container) {
349   DCHECK_EQ(owning_layer_.Compositor()->Lifecycle().GetState(),
350             DocumentLifecycle::kInCompositingUpdate);
351 
352   // Note carefully: here we assume that the compositing state of all
353   // descendants have been updated already, so it is legitimate to compute and
354   // cache the composited bounds for this layer.
355   UpdateCompositedBounds();
356 
357   PaintLayerCompositor* compositor = Compositor();
358   LayoutObject& layout_object = GetLayoutObject();
359   const ComputedStyle& style = layout_object.StyleRef();
360 
361   bool layer_config_changed = false;
362 
363   if (UpdateForegroundLayer(
364           compositor->NeedsContentsCompositingLayer(&owning_layer_)))
365     layer_config_changed = true;
366 
367   if (UpdateScrollingLayers(owning_layer_.NeedsCompositedScrolling()))
368     layer_config_changed = true;
369 
370   // If the outline needs to draw over the composited scrolling contents layer
371   // or scrollbar layers (or video or webgl) it needs to be drawn into a
372   // separate layer.
373   bool needs_decoration_outline_layer =
374       NeedsDecorationOutlineLayer(owning_layer_, layout_object);
375 
376   if (UpdateDecorationOutlineLayer(needs_decoration_outline_layer))
377     layer_config_changed = true;
378 
379   if (UpdateOverflowControlsLayers(RequiresHorizontalScrollbarLayer(),
380                                    RequiresVerticalScrollbarLayer(),
381                                    RequiresScrollCornerLayer()))
382     layer_config_changed = true;
383 
384   if (UpdateSquashingLayers(!squashed_layers_.IsEmpty()))
385     layer_config_changed = true;
386 
387   if (layer_config_changed)
388     UpdateInternalHierarchy();
389 
390   // A mask layer is not part of the hierarchy proper, it's an auxiliary layer
391   // that's plugged into another GraphicsLayer that is part of the hierarchy.
392   // It has no parent or child GraphicsLayer. For that reason, we process it
393   // here, after the hierarchy has been updated.
394   bool has_mask =
395       CSSMaskPainter::MaskBoundingBox(GetLayoutObject(), PhysicalOffset())
396           .has_value();
397   bool has_clip_path =
398       ClipPathClipper::LocalClipPathBoundingBox(GetLayoutObject()).has_value();
399   if (UpdateMaskLayer(has_mask || has_clip_path)) {
400     graphics_layer_->SetMaskLayer(mask_layer_.get());
401     layer_config_changed = true;
402   }
403 
404   UpdateBackgroundColor();
405 
406   if (layout_object.IsImage()) {
407     if (IsDirectlyCompositedImage()) {
408       UpdateImageContents();
409     } else if (graphics_layer_->HasContentsLayer()) {
410       graphics_layer_->SetContentsToImage(nullptr, Image::kUnspecifiedDecode);
411     }
412   }
413 
414   if (layout_object.IsLayoutEmbeddedContent()) {
415     if (WebPluginContainerImpl* plugin = GetPluginContainer(layout_object)) {
416       graphics_layer_->SetContentsToCcLayer(
417           plugin->CcLayer(), plugin->PreventContentsOpaqueChangesToCcLayer());
418     } else if (auto* frame_owner =
419                    DynamicTo<HTMLFrameOwnerElement>(layout_object.GetNode())) {
420       if (auto* remote = DynamicTo<RemoteFrame>(frame_owner->ContentFrame())) {
421         graphics_layer_->SetContentsToCcLayer(
422             remote->GetCcLayer(), remote->WebLayerHasFixedContentsOpaque());
423       }
424     }
425     if (PaintLayerCompositor::AttachFrameContentLayersToIframeLayer(
426             ToLayoutEmbeddedContent(layout_object)))
427       layer_config_changed = true;
428   } else if (IsA<LayoutVideo>(layout_object)) {
429     auto* media_element = To<HTMLMediaElement>(layout_object.GetNode());
430     graphics_layer_->SetContentsToCcLayer(
431         media_element->CcLayer(),
432         /*prevent_contents_opaque_changes=*/true);
433   } else if (layout_object.IsCanvas()) {
434     graphics_layer_->SetContentsToCcLayer(
435         To<HTMLCanvasElement>(layout_object.GetNode())->ContentsCcLayer(),
436         /*prevent_contents_opaque_changes=*/false);
437     layer_config_changed = true;
438   }
439 
440   if (layer_config_changed) {
441     // Changes to either the internal hierarchy or the mask layer have an impact
442     // on painting phases, so we need to update when either are updated.
443     UpdatePaintingPhases();
444     // Need to update paint LayerState of the changed GraphicsLayers.
445     // The pre-paint tree walk does this.
446     layout_object.SetNeedsPaintPropertyUpdate();
447   }
448 
449   UpdateElementId();
450 
451   graphics_layer_->SetHasWillChangeTransformHint(
452       style.HasWillChangeTransformHint());
453 
454   if (style.Preserves3D() && style.HasOpacity() &&
455       owning_layer_.Has3DTransformedDescendant()) {
456     UseCounter::Count(layout_object.GetDocument(),
457                       WebFeature::kOpacityWithPreserve3DQuirk);
458   }
459 
460   return layer_config_changed;
461 }
462 
ComputeOffsetFromCompositedAncestor(const PaintLayer * layer,const PaintLayer * composited_ancestor,const PhysicalOffset & local_representative_point_for_fragmentation,const FloatPoint & offset_for_sticky_position)463 static PhysicalOffset ComputeOffsetFromCompositedAncestor(
464     const PaintLayer* layer,
465     const PaintLayer* composited_ancestor,
466     const PhysicalOffset& local_representative_point_for_fragmentation,
467     const FloatPoint& offset_for_sticky_position) {
468   // Add in the offset of the composited bounds from the coordinate space of
469   // the PaintLayer, since visualOffsetFromAncestor() requires the pre-offset
470   // input to be in the space of the PaintLayer. We also need to add in this
471   // offset before computation of visualOffsetFromAncestor(), because it affects
472   // fragmentation offset if compositedAncestor crosses a pagination boundary.
473   //
474   // Currently, visual fragmentation for composited layers is not implemented.
475   // For fragmented contents, we paint in the logical coordinates of the flow
476   // thread, then split the result by fragment boundary and paste each part
477   // into each fragment's physical position.
478   // Since composited layers don't support visual fragmentation, we have to
479   // choose a "representative" fragment to position the painted contents. This
480   // is where localRepresentativePointForFragmentation comes into play.
481   // The fragment that the representative point resides in will be chosen as
482   // the representative fragment for layer position purpose.
483   // For layers that are not fragmented, the point doesn't affect behavior as
484   // there is one and only one fragment.
485   PhysicalOffset offset = layer->VisualOffsetFromAncestor(
486       composited_ancestor, local_representative_point_for_fragmentation);
487   if (composited_ancestor)
488     offset += composited_ancestor->SubpixelAccumulation();
489   offset -= local_representative_point_for_fragmentation;
490   offset -= PhysicalOffset::FromFloatPointRound(offset_for_sticky_position);
491   return offset;
492 }
493 
ComputeBoundsOfOwningLayer(const PaintLayer * composited_ancestor,IntRect & local_bounds,IntPoint & snapped_offset_from_composited_ancestor)494 void CompositedLayerMapping::ComputeBoundsOfOwningLayer(
495     const PaintLayer* composited_ancestor,
496     IntRect& local_bounds,
497     IntPoint& snapped_offset_from_composited_ancestor) {
498   // HACK(chrishtr): adjust for position of inlines.
499   PhysicalOffset local_representative_point_for_fragmentation;
500   if (owning_layer_.GetLayoutObject().IsLayoutInline()) {
501     local_representative_point_for_fragmentation =
502         ToLayoutInline(owning_layer_.GetLayoutObject()).FirstLineBoxTopLeft();
503   }
504   // Blink will already have applied any necessary offset for sticky positioned
505   // elements. If the compositor is handling sticky offsets for this layer, we
506   // need to remove the Blink-side offset to avoid double-counting.
507   FloatPoint offset_for_sticky_position =
508       StickyPositionOffsetForLayer(owning_layer_);
509   PhysicalOffset offset_from_composited_ancestor =
510       ComputeOffsetFromCompositedAncestor(
511           &owning_layer_, composited_ancestor,
512           local_representative_point_for_fragmentation,
513           offset_for_sticky_position);
514   snapped_offset_from_composited_ancestor =
515       RoundedIntPoint(offset_from_composited_ancestor);
516 
517   PhysicalOffset subpixel_accumulation;
518   if (!owning_layer_.Transform() ||
519       owning_layer_.Transform()->IsIdentityOrTranslation()) {
520     subpixel_accumulation =
521         offset_from_composited_ancestor -
522         PhysicalOffset(snapped_offset_from_composited_ancestor);
523   }
524 
525   // Invalidate the whole layer when subpixel accumulation changes, since
526   // the previous subpixel accumulation is baked into the dispay list.
527   // However, don't do so for directly composited layers, to avoid impacting
528   // performance.
529   if (subpixel_accumulation != owning_layer_.SubpixelAccumulation()) {
530     // Always invalidate if under-invalidation checking is on, to avoid
531     // false positives.
532     if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled())
533       SetContentsNeedDisplay();
534     else if (!(owning_layer_.GetCompositingReasons() &
535                CompositingReason::kComboAllDirectReasons))
536       SetContentsNeedDisplay();
537   }
538 
539   // Otherwise discard the sub-pixel remainder because paint offset can't be
540   // transformed by a non-translation transform.
541   owning_layer_.SetSubpixelAccumulation(subpixel_accumulation);
542 
543   base::Optional<IntRect> mask_bounding_box =
544       CSSMaskPainter::MaskBoundingBox(GetLayoutObject(), subpixel_accumulation);
545   base::Optional<FloatRect> clip_path_bounding_box =
546       ClipPathClipper::LocalClipPathBoundingBox(GetLayoutObject());
547   if (clip_path_bounding_box)
548     clip_path_bounding_box->MoveBy(FloatPoint(subpixel_accumulation));
549 
550   // Override graphics layer size to the bound of mask layer, this is because
551   // the compositor implementation requires mask layer bound to match its
552   // host layer.
553   if (mask_bounding_box) {
554     local_bounds = *mask_bounding_box;
555     if (clip_path_bounding_box)
556       local_bounds.Intersect(EnclosingIntRect(*clip_path_bounding_box));
557   } else if (clip_path_bounding_box) {
558     local_bounds = EnclosingIntRect(*clip_path_bounding_box);
559   } else {
560     // Move the bounds by the subpixel accumulation so that it pixel-snaps
561     // relative to absolute pixels instead of local coordinates.
562     PhysicalRect local_raw_compositing_bounds = CompositedBounds();
563     local_raw_compositing_bounds.Move(subpixel_accumulation);
564     local_bounds = PixelSnappedIntRect(local_raw_compositing_bounds);
565   }
566 }
567 
UpdateSquashingLayerGeometry(const PaintLayer * compositing_container,const IntPoint & snapped_offset_from_composited_ancestor,Vector<GraphicsLayerPaintInfo> & layers,Vector<PaintLayer * > & layers_needing_paint_invalidation)568 void CompositedLayerMapping::UpdateSquashingLayerGeometry(
569     const PaintLayer* compositing_container,
570     const IntPoint& snapped_offset_from_composited_ancestor,
571     Vector<GraphicsLayerPaintInfo>& layers,
572     Vector<PaintLayer*>& layers_needing_paint_invalidation) {
573   if (!squashing_layer_)
574     return;
575 
576   IntPoint graphics_layer_parent_location;
577   ComputeGraphicsLayerParentLocation(compositing_container,
578                                      graphics_layer_parent_location);
579 
580   PhysicalOffset compositing_container_offset_from_parent_graphics_layer(
581       -graphics_layer_parent_location);
582   if (compositing_container) {
583     compositing_container_offset_from_parent_graphics_layer +=
584         compositing_container->SubpixelAccumulation();
585   }
586 
587   const PaintLayer* common_transform_ancestor = nullptr;
588   if (compositing_container && compositing_container->Transform()) {
589     common_transform_ancestor = compositing_container;
590   } else if (compositing_container) {
591     common_transform_ancestor =
592         &compositing_container->TransformAncestorOrRoot();
593   } else {
594     common_transform_ancestor = owning_layer_.Root();
595   }
596 
597   // FIXME: Cache these offsets.
598   PhysicalOffset compositing_container_offset_from_transformed_ancestor;
599   if (compositing_container) {
600     compositing_container_offset_from_transformed_ancestor =
601         compositing_container->ComputeOffsetFromAncestor(
602             *common_transform_ancestor);
603   }
604 
605   PhysicalRect total_squash_bounds;
606   for (wtf_size_t i = 0; i < layers.size(); ++i) {
607     PhysicalRect squashed_bounds =
608         layers[i].paint_layer->BoundingBoxForCompositing();
609 
610     // Store the local bounds of the Layer subtree before applying the offset.
611     layers[i].composited_bounds = squashed_bounds;
612 
613     PhysicalOffset squashed_layer_offset_from_transformed_ancestor =
614         layers[i].paint_layer->ComputeOffsetFromAncestor(
615             *common_transform_ancestor);
616     PhysicalOffset squashed_layer_offset_from_compositing_container =
617         squashed_layer_offset_from_transformed_ancestor -
618         compositing_container_offset_from_transformed_ancestor;
619 
620     squashed_bounds.Move(squashed_layer_offset_from_compositing_container);
621     total_squash_bounds.Unite(squashed_bounds);
622   }
623 
624   // The totalSquashBounds is positioned with respect to compositingContainer.
625   // But the squashingLayer needs to be positioned with respect to the
626   // graphicsLayerParent.  The conversion between compositingContainer and the
627   // graphicsLayerParent is already computed as
628   // compositingContainerOffsetFromParentGraphicsLayer.
629   total_squash_bounds.Move(
630       compositing_container_offset_from_parent_graphics_layer);
631   const IntRect squash_layer_bounds = EnclosingIntRect(total_squash_bounds);
632   const IntPoint squash_layer_origin = squash_layer_bounds.Location();
633   const PhysicalOffset squash_layer_origin_in_compositing_container_space =
634       PhysicalOffset(squash_layer_origin) -
635       compositing_container_offset_from_parent_graphics_layer;
636 
637   // Now that the squashing bounds are known, we can convert the PaintLayer
638   // painting offsets from compositingContainer space to the squashing layer
639   // space.
640   //
641   // The painting offset we want to compute for each squashed PaintLayer is
642   // essentially the position of the squashed PaintLayer described w.r.t.
643   // compositingContainer's origin.  So we just need to convert that point from
644   // compositingContainer space to the squashing layer's space. This is done by
645   // subtracting squashLayerOriginInCompositingContainerSpace, but then the
646   // offset overall needs to be negated because that's the direction that the
647   // painting code expects the offset to be.
648   for (wtf_size_t i = 0; i < layers.size(); ++i) {
649     const PhysicalOffset squashed_layer_offset_from_transformed_ancestor =
650         layers[i].paint_layer->ComputeOffsetFromAncestor(
651             *common_transform_ancestor);
652     const PhysicalOffset offset_from_squash_layer_origin =
653         (squashed_layer_offset_from_transformed_ancestor -
654          compositing_container_offset_from_transformed_ancestor) -
655         squash_layer_origin_in_compositing_container_space;
656 
657     IntSize new_offset_from_layout_object =
658         -ToIntSize(RoundedIntPoint(offset_from_squash_layer_origin));
659     PhysicalOffset subpixel_accumulation =
660         offset_from_squash_layer_origin +
661         PhysicalOffset(new_offset_from_layout_object);
662     if (layers[i].offset_from_layout_object_set &&
663         layers[i].offset_from_layout_object != new_offset_from_layout_object) {
664       ObjectPaintInvalidator(layers[i].paint_layer->GetLayoutObject())
665           .InvalidatePaintIncludingNonCompositingDescendants();
666       layers_needing_paint_invalidation.push_back(layers[i].paint_layer);
667     }
668     layers[i].offset_from_layout_object = new_offset_from_layout_object;
669     layers[i].offset_from_layout_object_set = true;
670 
671     layers[i].paint_layer->SetSubpixelAccumulation(subpixel_accumulation);
672   }
673 
674   squashing_layer_->SetSize(gfx::Size(squash_layer_bounds.Size()));
675   // We can't squashing_layer_->SetOffsetFromLayoutObject().
676   // Squashing layer has special paint and invalidation logic that already
677   // compensated for compositing bounds, setting it here would end up
678   // double adjustment.
679   auto new_offset = squash_layer_bounds.Location() -
680                     snapped_offset_from_composited_ancestor +
681                     ToIntSize(graphics_layer_parent_location);
682   if (new_offset != squashing_layer_offset_from_layout_object_) {
683     squashing_layer_offset_from_layout_object_ = new_offset;
684     // Need to update squashing LayerState according to the new offset.
685     // The pre-paint tree walk does this.
686     GetLayoutObject().SetNeedsPaintPropertyUpdate();
687   }
688 
689   for (wtf_size_t i = 0; i < layers.size(); ++i) {
690     LocalClipRectForSquashedLayer(owning_layer_, layers, layers[i]);
691   }
692 }
693 
UpdateGraphicsLayerGeometry(const PaintLayer * compositing_container,Vector<PaintLayer * > & layers_needing_paint_invalidation)694 void CompositedLayerMapping::UpdateGraphicsLayerGeometry(
695     const PaintLayer* compositing_container,
696     Vector<PaintLayer*>& layers_needing_paint_invalidation) {
697   DCHECK_EQ(owning_layer_.Compositor()->Lifecycle().GetState(),
698             DocumentLifecycle::kInCompositingUpdate);
699 
700   IntRect local_compositing_bounds;
701   IntPoint snapped_offset_from_composited_ancestor;
702   ComputeBoundsOfOwningLayer(compositing_container, local_compositing_bounds,
703                              snapped_offset_from_composited_ancestor);
704 
705   UpdateMainGraphicsLayerGeometry(local_compositing_bounds);
706   UpdateOverflowControlsHostLayerGeometry(compositing_container);
707   UpdateSquashingLayerGeometry(
708       compositing_container, snapped_offset_from_composited_ancestor,
709       squashed_layers_, layers_needing_paint_invalidation);
710 
711   UpdateMaskLayerGeometry();
712   // TODO(yigu): Currently the decoration layer uses the same contentSize
713   // as the foreground layer. There are scenarios where the sizes could be
714   // different so the decoration layer size should be calculated separately.
715   UpdateDecorationOutlineLayerGeometry(local_compositing_bounds.Size());
716   UpdateScrollingLayerGeometry();
717   UpdateForegroundLayerGeometry();
718 
719   if (owning_layer_.GetScrollableArea() &&
720       owning_layer_.GetScrollableArea()->ScrollsOverflow())
721     owning_layer_.GetScrollableArea()->PositionOverflowControls();
722 
723   UpdateContentsRect();
724   UpdateBackgroundColor();
725   UpdateDrawsContentAndPaintsHitTest();
726   UpdateElementId();
727   UpdateContentsOpaque();
728   UpdateRasterizationPolicy();
729   UpdateCompositingReasons();
730 }
731 
UpdateMainGraphicsLayerGeometry(const IntRect & local_compositing_bounds)732 void CompositedLayerMapping::UpdateMainGraphicsLayerGeometry(
733     const IntRect& local_compositing_bounds) {
734   graphics_layer_->SetOffsetFromLayoutObject(
735       ToIntSize(local_compositing_bounds.Location()));
736   graphics_layer_->SetSize(gfx::Size(local_compositing_bounds.Size()));
737 
738   // m_graphicsLayer is the corresponding GraphicsLayer for this PaintLayer and
739   // its non-compositing descendants. So, the visibility flag for
740   // m_graphicsLayer should be true if there are any non-compositing visible
741   // layers.
742   bool contents_visible = owning_layer_.HasVisibleContent() ||
743                           HasVisibleNonCompositingDescendant(&owning_layer_);
744   // TODO(sunxd): Investigate and possibly implement computing hit test regions
745   // in PaintTouchActionRects code path, so that cc has correct pointer-events
746   // information.
747   // For now, there is no need to set graphics_layer_'s hit testable bit here,
748   // because it is always hit testable from cc's perspective.
749   graphics_layer_->SetContentsVisible(contents_visible);
750 }
751 
ComputeGraphicsLayerParentLocation(const PaintLayer * compositing_container,IntPoint & graphics_layer_parent_location)752 void CompositedLayerMapping::ComputeGraphicsLayerParentLocation(
753     const PaintLayer* compositing_container,
754     IntPoint& graphics_layer_parent_location) {
755   if (compositing_container) {
756     graphics_layer_parent_location =
757         IntPoint(compositing_container->GetCompositedLayerMapping()
758                      ->ParentForSublayers()
759                      ->OffsetFromLayoutObject());
760   } else if (!GetLayoutObject().GetFrame()->IsLocalRoot()) {  // TODO(oopif)
761     DCHECK(!compositing_container);
762     graphics_layer_parent_location = IntPoint();
763   }
764 
765   if (compositing_container &&
766       compositing_container->NeedsCompositedScrolling()) {
767     LayoutBox& layout_box =
768         ToLayoutBox(compositing_container->GetLayoutObject());
769     IntSize scroll_offset =
770         FlooredIntSize(layout_box.PixelSnappedScrolledContentOffset());
771     IntPoint scroll_origin =
772         compositing_container->GetScrollableArea()->ScrollOrigin();
773     scroll_origin.Move(-layout_box.OriginAdjustmentForScrollbars());
774     scroll_origin.Move(-layout_box.BorderLeft().ToInt(),
775                        -layout_box.BorderTop().ToInt());
776     graphics_layer_parent_location = -(scroll_origin + scroll_offset);
777   }
778 }
779 
UpdateOverflowControlsHostLayerGeometry(const PaintLayer * compositing_container)780 void CompositedLayerMapping::UpdateOverflowControlsHostLayerGeometry(
781     const PaintLayer* compositing_container) {
782   if (!overflow_controls_host_layer_)
783     return;
784 
785   // To clip the scrollbars correctly, overflow_controls_host_layer_ should
786   // match our border box size.
787   const IntSize border_box_size =
788       owning_layer_.GetLayoutBox()->PixelSnappedBorderBoxSize(
789           PhysicalOffset(owning_layer_.SubpixelAccumulation() +
790                          owning_layer_.GetLayoutBox()->PhysicalLocation()));
791   overflow_controls_host_layer_->SetSize(gfx::Size(border_box_size));
792 }
793 
UpdateMaskLayerGeometry()794 void CompositedLayerMapping::UpdateMaskLayerGeometry() {
795   if (!mask_layer_)
796     return;
797 
798   if (mask_layer_->Size() != graphics_layer_->Size()) {
799     mask_layer_->SetSize(graphics_layer_->Size());
800     mask_layer_->SetNeedsDisplay();
801   }
802   mask_layer_->SetOffsetFromLayoutObject(
803       graphics_layer_->OffsetFromLayoutObject());
804 }
805 
UpdateScrollingLayerGeometry()806 void CompositedLayerMapping::UpdateScrollingLayerGeometry() {
807   if (!scrolling_layer_)
808     return;
809 
810   DCHECK(scrolling_contents_layer_);
811   LayoutBox& layout_box = ToLayoutBox(GetLayoutObject());
812   IntRect overflow_clip_rect = PixelSnappedIntRect(
813       layout_box.OverflowClipRect(owning_layer_.SubpixelAccumulation()));
814 
815   auto old_scroll_container_size = scrolling_layer_->Size();
816   scrolling_layer_->SetSize(gfx::Size(overflow_clip_rect.Size()));
817   bool scroll_container_size_changed =
818       old_scroll_container_size != scrolling_layer_->Size();
819 
820   scrolling_layer_->SetOffsetFromLayoutObject(
821       ToIntSize(overflow_clip_rect.Location()));
822 
823   PaintLayerScrollableArea* scrollable_area = owning_layer_.GetScrollableArea();
824   IntSize scroll_size = scrollable_area->PixelSnappedContentsSize(
825       owning_layer_.SubpixelAccumulation());
826 
827   // Ensure scrolling contents are at least as large as the scroll clip
828   scroll_size = scroll_size.ExpandedTo(overflow_clip_rect.Size());
829 
830   auto* scrolling_coordinator = owning_layer_.GetScrollingCoordinator();
831   scrolling_coordinator->UpdateCompositorScrollOffset(*layout_box.GetFrame(),
832                                                       *scrollable_area);
833 
834   if (gfx::Size(scroll_size) != scrolling_contents_layer_->Size() ||
835       scroll_container_size_changed) {
836     scrolling_coordinator->ScrollableAreaScrollLayerDidChange(scrollable_area);
837   }
838 
839   scrolling_contents_layer_->SetSize(gfx::Size(scroll_size));
840 
841   scrolling_contents_layer_->SetOffsetFromLayoutObject(
842       overflow_clip_rect.Location() - scrollable_area->ScrollOrigin());
843 }
844 
RequiresHorizontalScrollbarLayer() const845 bool CompositedLayerMapping::RequiresHorizontalScrollbarLayer() const {
846   return owning_layer_.GetScrollableArea() &&
847          owning_layer_.GetScrollableArea()->HorizontalScrollbar();
848 }
849 
RequiresVerticalScrollbarLayer() const850 bool CompositedLayerMapping::RequiresVerticalScrollbarLayer() const {
851   return owning_layer_.GetScrollableArea() &&
852          owning_layer_.GetScrollableArea()->VerticalScrollbar();
853 }
854 
RequiresScrollCornerLayer() const855 bool CompositedLayerMapping::RequiresScrollCornerLayer() const {
856   return owning_layer_.GetScrollableArea() &&
857          !owning_layer_.GetScrollableArea()
858               ->ScrollCornerAndResizerRect()
859               .IsEmpty();
860 }
861 
UpdateForegroundLayerGeometry()862 void CompositedLayerMapping::UpdateForegroundLayerGeometry() {
863   if (!foreground_layer_)
864     return;
865 
866   // Should be equivalent to local_compositing_bounds.
867   IntRect compositing_bounds(
868       IntPoint(graphics_layer_->OffsetFromLayoutObject()),
869       IntSize(graphics_layer_->Size()));
870   if (scrolling_layer_) {
871     // Override compositing bounds to include full overflow if composited
872     // scrolling is used.
873     compositing_bounds =
874         IntRect(IntPoint(scrolling_contents_layer_->OffsetFromLayoutObject()),
875                 IntSize(scrolling_contents_layer_->Size()));
876   }
877 
878   IntRect old_compositing_bounds(
879       IntPoint(foreground_layer_->OffsetFromLayoutObject()),
880       IntSize(foreground_layer_->Size()));
881   if (compositing_bounds != old_compositing_bounds) {
882     foreground_layer_->SetOffsetFromLayoutObject(
883         ToIntSize(compositing_bounds.Location()));
884     foreground_layer_->SetSize(gfx::Size(compositing_bounds.Size()));
885     foreground_layer_->SetNeedsDisplay();
886   }
887 }
888 
UpdateDecorationOutlineLayerGeometry(const IntSize & relative_compositing_bounds_size)889 void CompositedLayerMapping::UpdateDecorationOutlineLayerGeometry(
890     const IntSize& relative_compositing_bounds_size) {
891   if (!decoration_outline_layer_)
892     return;
893   const auto& decoration_size = relative_compositing_bounds_size;
894   if (gfx::Size(decoration_size) != decoration_outline_layer_->Size()) {
895     decoration_outline_layer_->SetSize(gfx::Size(decoration_size));
896     decoration_outline_layer_->SetNeedsDisplay();
897   }
898   decoration_outline_layer_->SetOffsetFromLayoutObject(
899       graphics_layer_->OffsetFromLayoutObject());
900 }
901 
UpdateInternalHierarchy()902 void CompositedLayerMapping::UpdateInternalHierarchy() {
903   // m_foregroundLayer has to be inserted in the correct order with child
904   // layers, so it's not inserted here.
905   graphics_layer_->RemoveFromParent();
906 
907   // Layer to which children should be attached as we build the hierarchy.
908   GraphicsLayer* bottom_layer = graphics_layer_.get();
909   auto update_bottom_layer = [&bottom_layer](GraphicsLayer* layer) {
910     if (layer) {
911       bottom_layer->AddChild(layer);
912       bottom_layer = layer;
913     }
914   };
915 
916   update_bottom_layer(scrolling_layer_.get());
917 
918   // Now constructing the subtree for the overflow controls.
919   bottom_layer = graphics_layer_.get();
920   update_bottom_layer(overflow_controls_host_layer_.get());
921   if (layer_for_horizontal_scrollbar_) {
922     overflow_controls_host_layer_->AddChild(
923         layer_for_horizontal_scrollbar_.get());
924   }
925   if (layer_for_vertical_scrollbar_) {
926     overflow_controls_host_layer_->AddChild(
927         layer_for_vertical_scrollbar_.get());
928   }
929   if (layer_for_scroll_corner_)
930     overflow_controls_host_layer_->AddChild(layer_for_scroll_corner_.get());
931 
932   // Now add the DecorationOutlineLayer as a subtree to GraphicsLayer
933   if (decoration_outline_layer_.get())
934     graphics_layer_->AddChild(decoration_outline_layer_.get());
935 
936   // The squashing containment layer, if it exists, becomes a no-op parent.
937   if (squashing_layer_) {
938     if (squashing_containment_layer_) {
939       squashing_containment_layer_->RemoveAllChildren();
940       squashing_containment_layer_->AddChild(graphics_layer_.get());
941       squashing_containment_layer_->AddChild(squashing_layer_.get());
942     }
943   }
944 }
945 
UpdatePaintingPhases()946 void CompositedLayerMapping::UpdatePaintingPhases() {
947   graphics_layer_->SetPaintingPhase(PaintingPhaseForPrimaryLayer());
948   if (scrolling_contents_layer_) {
949     GraphicsLayerPaintingPhase paint_phase =
950         kGraphicsLayerPaintOverflowContents |
951         kGraphicsLayerPaintCompositedScroll;
952     if (!foreground_layer_)
953       paint_phase |= kGraphicsLayerPaintForeground;
954     scrolling_contents_layer_->SetPaintingPhase(paint_phase);
955   }
956   if (foreground_layer_) {
957     GraphicsLayerPaintingPhase paint_phase = kGraphicsLayerPaintForeground;
958     if (scrolling_contents_layer_)
959       paint_phase |= kGraphicsLayerPaintOverflowContents;
960     foreground_layer_->SetPaintingPhase(paint_phase);
961   }
962 }
963 
UpdateContentsRect()964 void CompositedLayerMapping::UpdateContentsRect() {
965   graphics_layer_->SetContentsRect(PixelSnappedIntRect(ContentsBox()));
966 }
967 
UpdateDrawsContentAndPaintsHitTest()968 void CompositedLayerMapping::UpdateDrawsContentAndPaintsHitTest() {
969   bool in_overlay_fullscreen_video = false;
970   if (IsA<LayoutVideo>(GetLayoutObject())) {
971     auto* video_element = To<HTMLVideoElement>(GetLayoutObject().GetNode());
972     if (video_element->IsFullscreen() &&
973         video_element->UsesOverlayFullscreenVideo())
974       in_overlay_fullscreen_video = true;
975   }
976   bool has_painted_content =
977       in_overlay_fullscreen_video ? false : ContainsPaintedContent();
978   graphics_layer_->SetDrawsContent(has_painted_content);
979 
980   // |has_painted_content| is conservative (e.g., will be true if any descendant
981   // paints content, regardless of whether the descendant content is a hit test)
982   // but an exhaustive check of descendants that paint hit tests would be too
983   // expensive.
984   bool paints_hit_test =
985       has_painted_content || GetLayoutObject().HasEffectiveAllowedTouchAction();
986   bool paints_scroll_hit_test =
987       ((owning_layer_.GetScrollableArea() &&
988         owning_layer_.GetScrollableArea()->ScrollsOverflow()) ||
989        (GetPluginContainer(GetLayoutObject()) &&
990         GetPluginContainer(GetLayoutObject())->WantsWheelEvents()));
991   graphics_layer_->SetPaintsHitTest(paints_hit_test || paints_scroll_hit_test);
992 
993   if (scrolling_layer_) {
994     // m_scrollingLayer never has backing store.
995     // m_scrollingContentsLayer only needs backing store if the scrolled
996     // contents need to paint.
997     scrolling_contents_are_empty_ =
998         !owning_layer_.HasVisibleContent() ||
999         !(GetLayoutObject().StyleRef().HasBackground() ||
1000           GetLayoutObject().HasBackdropFilter() || PaintsChildren());
1001     scrolling_contents_layer_->SetDrawsContent(!scrolling_contents_are_empty_);
1002     scrolling_contents_layer_->SetPaintsHitTest(paints_hit_test);
1003   }
1004 
1005   draws_background_onto_content_layer_ = false;
1006 
1007   if (has_painted_content && IsTextureLayerCanvas(GetLayoutObject())) {
1008     CanvasRenderingContext* context =
1009         To<HTMLCanvasElement>(GetLayoutObject().GetNode())->RenderingContext();
1010     // Content layer may be null if context is lost.
1011     if (cc::Layer* content_layer = context->CcLayer()) {
1012       Color bg_color(Color::kTransparent);
1013       if (ContentLayerSupportsDirectBackgroundComposition(GetLayoutObject())) {
1014         bg_color = LayoutObjectBackgroundColor();
1015         has_painted_content = false;
1016         draws_background_onto_content_layer_ = true;
1017       }
1018       content_layer->SetBackgroundColor(bg_color.Rgb());
1019     }
1020   }
1021 
1022   // FIXME: we could refine this to only allocate backings for one of these
1023   // layers if possible.
1024   if (foreground_layer_) {
1025     foreground_layer_->SetDrawsContent(has_painted_content);
1026     foreground_layer_->SetPaintsHitTest(paints_hit_test);
1027   }
1028 
1029   if (decoration_outline_layer_)
1030     decoration_outline_layer_->SetDrawsContent(true);
1031 
1032   if (mask_layer_)
1033     mask_layer_->SetDrawsContent(true);
1034 }
1035 
ToggleScrollbarLayerIfNeeded(std::unique_ptr<GraphicsLayer> & layer,bool needs_layer,CompositingReasons reason)1036 bool CompositedLayerMapping::ToggleScrollbarLayerIfNeeded(
1037     std::unique_ptr<GraphicsLayer>& layer,
1038     bool needs_layer,
1039     CompositingReasons reason) {
1040   if (needs_layer == !!layer)
1041     return false;
1042   layer = needs_layer ? CreateGraphicsLayer(reason) : nullptr;
1043 
1044   if (PaintLayerScrollableArea* scrollable_area =
1045           owning_layer_.GetScrollableArea()) {
1046     if (ScrollingCoordinator* scrolling_coordinator =
1047             owning_layer_.GetScrollingCoordinator()) {
1048       if (reason == CompositingReason::kLayerForHorizontalScrollbar) {
1049         scrolling_coordinator->ScrollableAreaScrollbarLayerDidChange(
1050             scrollable_area, kHorizontalScrollbar);
1051       } else if (reason == CompositingReason::kLayerForVerticalScrollbar) {
1052         scrolling_coordinator->ScrollableAreaScrollbarLayerDidChange(
1053             scrollable_area, kVerticalScrollbar);
1054       }
1055     }
1056   }
1057   return true;
1058 }
1059 
UpdateOverflowControlsLayers(bool needs_horizontal_scrollbar_layer,bool needs_vertical_scrollbar_layer,bool needs_scroll_corner_layer)1060 bool CompositedLayerMapping::UpdateOverflowControlsLayers(
1061     bool needs_horizontal_scrollbar_layer,
1062     bool needs_vertical_scrollbar_layer,
1063     bool needs_scroll_corner_layer) {
1064   if (PaintLayerScrollableArea* scrollable_area =
1065           owning_layer_.GetScrollableArea()) {
1066     // If the scrollable area is marked as needing a new scrollbar layer,
1067     // destroy the layer now so that it will be created again below.
1068     if (layer_for_horizontal_scrollbar_ && needs_horizontal_scrollbar_layer &&
1069         scrollable_area->ShouldRebuildHorizontalScrollbarLayer()) {
1070       ToggleScrollbarLayerIfNeeded(
1071           layer_for_horizontal_scrollbar_, false,
1072           CompositingReason::kLayerForHorizontalScrollbar);
1073     }
1074     if (layer_for_vertical_scrollbar_ && needs_vertical_scrollbar_layer &&
1075         scrollable_area->ShouldRebuildVerticalScrollbarLayer()) {
1076       ToggleScrollbarLayerIfNeeded(
1077           layer_for_vertical_scrollbar_, false,
1078           CompositingReason::kLayerForVerticalScrollbar);
1079     }
1080     scrollable_area->ResetRebuildScrollbarLayerFlags();
1081 
1082     if (scrolling_contents_layer_ &&
1083         scrollable_area->NeedsShowScrollbarLayers()) {
1084       scrolling_contents_layer_->CcLayer()->ShowScrollbars();
1085       scrollable_area->DidShowScrollbarLayers();
1086     }
1087   }
1088 
1089   // If the subtree is invisible, we don't actually need scrollbar layers.
1090   // Only do this check if at least one of the bits is currently true.
1091   // This is important because this method is called during the destructor
1092   // of CompositedLayerMapping, which may happen during style recalc,
1093   // and therefore visible content status may be invalid.
1094   if (needs_horizontal_scrollbar_layer || needs_vertical_scrollbar_layer ||
1095       needs_scroll_corner_layer) {
1096     bool invisible = owning_layer_.SubtreeIsInvisible();
1097     needs_horizontal_scrollbar_layer &= !invisible;
1098     needs_vertical_scrollbar_layer &= !invisible;
1099     needs_scroll_corner_layer &= !invisible;
1100   }
1101 
1102   bool horizontal_scrollbar_layer_changed = ToggleScrollbarLayerIfNeeded(
1103       layer_for_horizontal_scrollbar_, needs_horizontal_scrollbar_layer,
1104       CompositingReason::kLayerForHorizontalScrollbar);
1105   bool vertical_scrollbar_layer_changed = ToggleScrollbarLayerIfNeeded(
1106       layer_for_vertical_scrollbar_, needs_vertical_scrollbar_layer,
1107       CompositingReason::kLayerForVerticalScrollbar);
1108   bool scroll_corner_layer_changed = ToggleScrollbarLayerIfNeeded(
1109       layer_for_scroll_corner_, needs_scroll_corner_layer,
1110       CompositingReason::kLayerForScrollCorner);
1111 
1112   bool needs_overflow_controls_host_layer = needs_horizontal_scrollbar_layer ||
1113                                             needs_vertical_scrollbar_layer ||
1114                                             needs_scroll_corner_layer;
1115   ToggleScrollbarLayerIfNeeded(
1116       overflow_controls_host_layer_, needs_overflow_controls_host_layer,
1117       CompositingReason::kLayerForOverflowControlsHost);
1118 
1119   return horizontal_scrollbar_layer_changed ||
1120          vertical_scrollbar_layer_changed || scroll_corner_layer_changed;
1121 }
1122 
PositionOverflowControlsLayers()1123 void CompositedLayerMapping::PositionOverflowControlsLayers() {
1124   if (GraphicsLayer* layer = LayerForHorizontalScrollbar()) {
1125     Scrollbar* h_bar = owning_layer_.GetScrollableArea()->HorizontalScrollbar();
1126     if (h_bar) {
1127       IntRect frame_rect = h_bar->FrameRect();
1128       layer->SetOffsetFromLayoutObject(ToIntSize(frame_rect.Location()));
1129       layer->SetSize(gfx::Size(frame_rect.Size()));
1130       if (layer->HasContentsLayer())
1131         layer->SetContentsRect(IntRect(IntPoint(), frame_rect.Size()));
1132     }
1133     bool h_bar_visible = h_bar && !layer->HasContentsLayer();
1134     layer->SetDrawsContent(h_bar_visible);
1135     layer->SetHitTestable(h_bar_visible);
1136   }
1137 
1138   if (GraphicsLayer* layer = LayerForVerticalScrollbar()) {
1139     Scrollbar* v_bar = owning_layer_.GetScrollableArea()->VerticalScrollbar();
1140     if (v_bar) {
1141       IntRect frame_rect = v_bar->FrameRect();
1142       layer->SetOffsetFromLayoutObject(ToIntSize(frame_rect.Location()));
1143       layer->SetSize(gfx::Size(frame_rect.Size()));
1144       if (layer->HasContentsLayer())
1145         layer->SetContentsRect(IntRect(IntPoint(), frame_rect.Size()));
1146     }
1147     bool v_bar_visible = v_bar && !layer->HasContentsLayer();
1148     layer->SetDrawsContent(v_bar_visible);
1149     layer->SetHitTestable(v_bar_visible);
1150   }
1151 
1152   if (GraphicsLayer* layer = LayerForScrollCorner()) {
1153     const IntRect& scroll_corner_and_resizer =
1154         owning_layer_.GetScrollableArea()->ScrollCornerAndResizerRect();
1155     layer->SetOffsetFromLayoutObject(
1156         ToIntSize(scroll_corner_and_resizer.Location()));
1157     layer->SetSize(gfx::Size(scroll_corner_and_resizer.Size()));
1158     layer->SetDrawsContent(!scroll_corner_and_resizer.IsEmpty());
1159     layer->SetHitTestable(!scroll_corner_and_resizer.IsEmpty());
1160   }
1161 }
1162 
1163 enum ApplyToGraphicsLayersModeFlags {
1164   kApplyToLayersAffectedByPreserve3D = (1 << 0),
1165   kApplyToSquashingLayer = (1 << 1),
1166   kApplyToScrollbarLayers = (1 << 2),
1167   kApplyToMaskLayers = (1 << 3),
1168   kApplyToContentLayers = (1 << 4),
1169   kApplyToChildContainingLayers =
1170       (1 << 5),  // layers between m_graphicsLayer and children
1171   kApplyToNonScrollingContentLayers = (1 << 6),
1172   kApplyToScrollingContentLayers = (1 << 7),
1173   kApplyToDecorationOutlineLayer = (1 << 8),
1174   kApplyToAllGraphicsLayers =
1175       (kApplyToSquashingLayer | kApplyToScrollbarLayers | kApplyToMaskLayers |
1176        kApplyToLayersAffectedByPreserve3D | kApplyToContentLayers |
1177        kApplyToScrollingContentLayers | kApplyToDecorationOutlineLayer)
1178 };
1179 typedef unsigned ApplyToGraphicsLayersMode;
1180 
1181 // Flags to layers mapping matrix:
1182 //                  bit 0 1 2 3 4 5 6 7 8
1183 // ChildTransform       *         *
1184 // Main                 *       *   *
1185 // Clipping             *         *
1186 // Scrolling            *         *
1187 // ScrollingContents    *       * *   *
1188 // Foreground           *       *     *
1189 // Squashing              *
1190 // Mask                       * *   *
1191 // HorizontalScrollbar      *
1192 // VerticalScrollbar        *
1193 // ScrollCorner             *
1194 // DecorationOutline                *   *
1195 template <typename Func>
ApplyToGraphicsLayers(const CompositedLayerMapping * mapping,const Func & f,ApplyToGraphicsLayersMode mode)1196 static void ApplyToGraphicsLayers(const CompositedLayerMapping* mapping,
1197                                   const Func& f,
1198                                   ApplyToGraphicsLayersMode mode) {
1199   DCHECK(mode);
1200 
1201   if (((mode & kApplyToLayersAffectedByPreserve3D) ||
1202        (mode & kApplyToContentLayers) ||
1203        (mode & kApplyToNonScrollingContentLayers)) &&
1204       mapping->MainGraphicsLayer())
1205     f(mapping->MainGraphicsLayer());
1206   if (((mode & kApplyToLayersAffectedByPreserve3D) ||
1207        (mode & kApplyToChildContainingLayers)) &&
1208       mapping->ScrollingLayer())
1209     f(mapping->ScrollingLayer());
1210   if (((mode & kApplyToLayersAffectedByPreserve3D) ||
1211        (mode & kApplyToContentLayers) ||
1212        (mode & kApplyToChildContainingLayers) ||
1213        (mode & kApplyToScrollingContentLayers)) &&
1214       mapping->ScrollingContentsLayer())
1215     f(mapping->ScrollingContentsLayer());
1216   if (((mode & kApplyToLayersAffectedByPreserve3D) ||
1217        (mode & kApplyToContentLayers) ||
1218        (mode & kApplyToScrollingContentLayers)) &&
1219       mapping->ForegroundLayer())
1220     f(mapping->ForegroundLayer());
1221 
1222   if ((mode & kApplyToSquashingLayer) && mapping->SquashingLayer())
1223     f(mapping->SquashingLayer());
1224 
1225   if (((mode & kApplyToMaskLayers) || (mode & kApplyToContentLayers) ||
1226        (mode & kApplyToNonScrollingContentLayers)) &&
1227       mapping->MaskLayer())
1228     f(mapping->MaskLayer());
1229 
1230   if ((mode & kApplyToScrollbarLayers) &&
1231       mapping->LayerForHorizontalScrollbar())
1232     f(mapping->LayerForHorizontalScrollbar());
1233   if ((mode & kApplyToScrollbarLayers) && mapping->LayerForVerticalScrollbar())
1234     f(mapping->LayerForVerticalScrollbar());
1235   if ((mode & kApplyToScrollbarLayers) && mapping->LayerForScrollCorner())
1236     f(mapping->LayerForScrollCorner());
1237 
1238   if (((mode & kApplyToDecorationOutlineLayer) ||
1239        (mode & kApplyToNonScrollingContentLayers)) &&
1240       mapping->DecorationOutlineLayer())
1241     f(mapping->DecorationOutlineLayer());
1242 }
1243 
1244 // You receive an element id if you have an animation, or you're a scroller (and
1245 // might impl animate).
1246 //
1247 // The element id for the scroll layers is assigned when they're constructed,
1248 // since this is unconditional. However, the element id for the primary layer
1249 // may change according to the rules above so we update those values here.
UpdateElementId()1250 void CompositedLayerMapping::UpdateElementId() {
1251   CompositorElementId element_id = CompositorElementIdFromUniqueObjectId(
1252       owning_layer_.GetLayoutObject().UniqueId(),
1253       CompositorElementIdNamespace::kPrimary);
1254 
1255   graphics_layer_->SetElementId(element_id);
1256 }
1257 
UpdateForegroundLayer(bool needs_foreground_layer)1258 bool CompositedLayerMapping::UpdateForegroundLayer(
1259     bool needs_foreground_layer) {
1260   bool layer_changed = false;
1261   if (needs_foreground_layer) {
1262     if (!foreground_layer_) {
1263       foreground_layer_ =
1264           CreateGraphicsLayer(CompositingReason::kLayerForForeground);
1265       foreground_layer_->SetHitTestable(true);
1266       layer_changed = true;
1267     }
1268   } else if (foreground_layer_) {
1269     foreground_layer_->RemoveFromParent();
1270     foreground_layer_ = nullptr;
1271     layer_changed = true;
1272   }
1273 
1274   return layer_changed;
1275 }
1276 
UpdateDecorationOutlineLayer(bool needs_decoration_outline_layer)1277 bool CompositedLayerMapping::UpdateDecorationOutlineLayer(
1278     bool needs_decoration_outline_layer) {
1279   bool layer_changed = false;
1280   if (needs_decoration_outline_layer) {
1281     if (!decoration_outline_layer_) {
1282       decoration_outline_layer_ =
1283           CreateGraphicsLayer(CompositingReason::kLayerForDecoration);
1284       decoration_outline_layer_->SetPaintingPhase(
1285           kGraphicsLayerPaintDecoration);
1286       layer_changed = true;
1287     }
1288   } else if (decoration_outline_layer_) {
1289     decoration_outline_layer_ = nullptr;
1290     layer_changed = true;
1291   }
1292 
1293   return layer_changed;
1294 }
1295 
UpdateMaskLayer(bool needs_mask_layer)1296 bool CompositedLayerMapping::UpdateMaskLayer(bool needs_mask_layer) {
1297   bool layer_changed = false;
1298   if (needs_mask_layer) {
1299     if (!mask_layer_) {
1300       mask_layer_ = CreateGraphicsLayer(CompositingReason::kLayerForMask);
1301       mask_layer_->SetPaintingPhase(kGraphicsLayerPaintMask);
1302       CompositorElementId element_id = CompositorElementIdFromUniqueObjectId(
1303           GetLayoutObject().UniqueId(),
1304           CompositorElementIdNamespace::kEffectMask);
1305       mask_layer_->SetElementId(element_id);
1306       if (GetLayoutObject().HasBackdropFilter())
1307         mask_layer_->CcLayer()->SetIsBackdropFilterMask(true);
1308       layer_changed = true;
1309     }
1310   } else if (mask_layer_) {
1311     mask_layer_ = nullptr;
1312     layer_changed = true;
1313   }
1314 
1315   return layer_changed;
1316 }
1317 
UpdateScrollingLayers(bool needs_scrolling_layers)1318 bool CompositedLayerMapping::UpdateScrollingLayers(
1319     bool needs_scrolling_layers) {
1320   ScrollingCoordinator* scrolling_coordinator =
1321       owning_layer_.GetScrollingCoordinator();
1322 
1323   auto* scrollable_area = owning_layer_.GetScrollableArea();
1324   if (scrollable_area)
1325     scrollable_area->SetUsesCompositedScrolling(needs_scrolling_layers);
1326 
1327   bool layer_changed = false;
1328   if (needs_scrolling_layers) {
1329     if (!scrolling_layer_) {
1330       // Outer layer which corresponds with the scroll view.
1331       scrolling_layer_ =
1332           CreateGraphicsLayer(CompositingReason::kLayerForScrollingContainer);
1333       scrolling_layer_->SetDrawsContent(false);
1334       scrolling_layer_->SetHitTestable(false);
1335 
1336       // Inner layer which renders the content that scrolls.
1337       scrolling_contents_layer_ =
1338           CreateGraphicsLayer(CompositingReason::kLayerForScrollingContents);
1339       scrolling_contents_layer_->SetHitTestable(true);
1340 
1341       auto element_id = scrollable_area->GetScrollElementId();
1342       scrolling_contents_layer_->SetElementId(element_id);
1343 
1344       scrolling_layer_->AddChild(scrolling_contents_layer_.get());
1345 
1346       layer_changed = true;
1347       if (scrolling_coordinator && scrollable_area) {
1348         scrolling_coordinator->ScrollableAreaScrollLayerDidChange(
1349             scrollable_area);
1350         const auto& object = GetLayoutObject();
1351         if (auto* layout_view = DynamicTo<LayoutView>(object))
1352           layout_view->GetFrameView()->ScrollableAreasDidChange();
1353       }
1354     }
1355   } else if (scrolling_layer_) {
1356     scrolling_layer_ = nullptr;
1357     scrolling_contents_layer_ = nullptr;
1358     layer_changed = true;
1359     if (scrolling_coordinator && scrollable_area) {
1360       scrolling_coordinator->ScrollableAreaScrollLayerDidChange(
1361           scrollable_area);
1362       const auto& object = GetLayoutObject();
1363       if (auto* layout_view = DynamicTo<LayoutView>(object))
1364         layout_view->GetFrameView()->ScrollableAreasDidChange();
1365     }
1366   }
1367 
1368   return layer_changed;
1369 }
1370 
UpdateSquashingLayers(bool needs_squashing_layers)1371 bool CompositedLayerMapping::UpdateSquashingLayers(
1372     bool needs_squashing_layers) {
1373   bool layers_changed = false;
1374 
1375   if (needs_squashing_layers) {
1376     if (!squashing_layer_) {
1377       squashing_layer_ =
1378           CreateGraphicsLayer(CompositingReason::kLayerForSquashingContents);
1379       squashing_layer_->SetDrawsContent(true);
1380       squashing_layer_->SetHitTestable(true);
1381       layers_changed = true;
1382     }
1383     if (!squashing_containment_layer_) {
1384       squashing_containment_layer_ =
1385           CreateGraphicsLayer(CompositingReason::kLayerForSquashingContainer);
1386       layers_changed = true;
1387     }
1388     DCHECK(squashing_layer_);
1389   } else {
1390     if (squashing_layer_) {
1391       squashing_layer_->RemoveFromParent();
1392       squashing_layer_ = nullptr;
1393       layers_changed = true;
1394     }
1395     if (squashing_containment_layer_) {
1396       squashing_containment_layer_->RemoveFromParent();
1397       squashing_containment_layer_ = nullptr;
1398       layers_changed = true;
1399     }
1400     DCHECK(!squashing_layer_);
1401     DCHECK(!squashing_containment_layer_);
1402   }
1403 
1404   return layers_changed;
1405 }
1406 
1407 GraphicsLayerPaintingPhase
PaintingPhaseForPrimaryLayer() const1408 CompositedLayerMapping::PaintingPhaseForPrimaryLayer() const {
1409   unsigned phase = kGraphicsLayerPaintBackground;
1410   if (!foreground_layer_)
1411     phase |= kGraphicsLayerPaintForeground;
1412   if (!mask_layer_)
1413     phase |= kGraphicsLayerPaintMask;
1414   if (!decoration_outline_layer_)
1415     phase |= kGraphicsLayerPaintDecoration;
1416 
1417   if (scrolling_contents_layer_) {
1418     phase &= ~kGraphicsLayerPaintForeground;
1419     phase |= kGraphicsLayerPaintCompositedScroll;
1420   }
1421 
1422   return static_cast<GraphicsLayerPaintingPhase>(phase);
1423 }
1424 
LayoutObjectBackgroundColor() const1425 Color CompositedLayerMapping::LayoutObjectBackgroundColor() const {
1426   const auto& object = GetLayoutObject();
1427   auto background_color = object.ResolveColor(GetCSSPropertyBackgroundColor());
1428   auto* layout_view = DynamicTo<LayoutView>(object);
1429   if (layout_view && object.GetDocument().IsInMainFrame()) {
1430     return layout_view->GetFrameView()->BaseBackgroundColor().Blend(
1431         background_color);
1432   }
1433   return background_color;
1434 }
1435 
UpdateBackgroundColor()1436 void CompositedLayerMapping::UpdateBackgroundColor() {
1437   auto color = LayoutObjectBackgroundColor().Rgb();
1438   graphics_layer_->SetBackgroundColor(color);
1439   if (scrolling_contents_layer_)
1440     scrolling_contents_layer_->SetBackgroundColor(color);
1441 }
1442 
PaintsChildren() const1443 bool CompositedLayerMapping::PaintsChildren() const {
1444   if (owning_layer_.HasVisibleContent() &&
1445       owning_layer_.HasNonEmptyChildLayoutObjects())
1446     return true;
1447 
1448   if (HasVisibleNonCompositingDescendant(&owning_layer_))
1449     return true;
1450 
1451   return false;
1452 }
1453 
IsCompositedPlugin(LayoutObject & layout_object)1454 static bool IsCompositedPlugin(LayoutObject& layout_object) {
1455   return layout_object.IsEmbeddedObject() &&
1456          ToLayoutEmbeddedObject(layout_object).RequiresAcceleratedCompositing();
1457 }
1458 
HasVisibleNonCompositingDescendant(PaintLayer * parent)1459 bool CompositedLayerMapping::HasVisibleNonCompositingDescendant(
1460     PaintLayer* parent) {
1461   if (!parent->HasVisibleDescendant())
1462     return false;
1463 
1464   PaintLayerPaintOrderIterator iterator(*parent, kAllChildren);
1465   while (PaintLayer* child_layer = iterator.Next()) {
1466     if (child_layer->HasCompositedLayerMapping())
1467       continue;
1468     if (child_layer->HasVisibleContent() ||
1469         HasVisibleNonCompositingDescendant(child_layer))
1470       return true;
1471   }
1472 
1473   return false;
1474 }
1475 
ContainsPaintedContent() const1476 bool CompositedLayerMapping::ContainsPaintedContent() const {
1477   if (CompositedBounds().IsEmpty())
1478     return false;
1479 
1480   if (GetLayoutObject().IsImage() && IsDirectlyCompositedImage())
1481     return false;
1482 
1483   LayoutObject& layout_object = GetLayoutObject();
1484   // FIXME: we could optimize cases where the image, video or canvas is known to
1485   // fill the border box entirely, and set background color on the layer in that
1486   // case, instead of allocating backing store and painting.
1487   auto* layout_video = DynamicTo<LayoutVideo>(layout_object);
1488   if (layout_video && layout_video->ShouldDisplayVideo())
1489     return owning_layer_.HasBoxDecorationsOrBackground();
1490 
1491   if (layout_object.GetNode() && layout_object.GetNode()->IsDocumentNode()) {
1492     if (owning_layer_.NeedsCompositedScrolling())
1493       return BackgroundPaintsOntoGraphicsLayer();
1494 
1495     // Look to see if the root object has a non-simple background
1496     LayoutObject* root_object =
1497         layout_object.GetDocument().documentElement()
1498             ? layout_object.GetDocument().documentElement()->GetLayoutObject()
1499             : nullptr;
1500     // Reject anything that has a border, a border-radius or outline,
1501     // or is not a simple background (no background, or solid color).
1502     if (root_object &&
1503         HasBoxDecorationsOrBackgroundImage(root_object->StyleRef()))
1504       return true;
1505 
1506     // Now look at the body's layoutObject.
1507     HTMLElement* body = layout_object.GetDocument().body();
1508     LayoutObject* body_object =
1509         IsA<HTMLBodyElement>(body) ? body->GetLayoutObject() : nullptr;
1510     if (body_object &&
1511         HasBoxDecorationsOrBackgroundImage(body_object->StyleRef()))
1512       return true;
1513   }
1514 
1515   if (owning_layer_.HasVisibleBoxDecorations())
1516     return true;
1517 
1518   if (layout_object.HasMask())  // masks require special treatment
1519     return true;
1520 
1521   if (layout_object.IsAtomicInlineLevel() && !IsCompositedPlugin(layout_object))
1522     return true;
1523 
1524   if (layout_object.IsLayoutMultiColumnSet())
1525     return true;
1526 
1527   // FIXME: it's O(n^2). A better solution is needed.
1528   return PaintsChildren();
1529 }
1530 
1531 // An image can be directly composited if it's the sole content of the layer,
1532 // and has no box decorations or clipping that require painting. Direct
1533 // compositing saves a backing store.
IsDirectlyCompositedImage() const1534 bool CompositedLayerMapping::IsDirectlyCompositedImage() const {
1535   DCHECK(GetLayoutObject().IsImage());
1536 
1537   LayoutImage& image_layout_object = ToLayoutImage(GetLayoutObject());
1538 
1539   if (owning_layer_.HasBoxDecorationsOrBackground() ||
1540       image_layout_object.HasClip() || image_layout_object.HasClipPath() ||
1541       image_layout_object.HasObjectFit())
1542     return false;
1543 
1544   if (ImageResourceContent* cached_image = image_layout_object.CachedImage()) {
1545     if (!cached_image->HasImage())
1546       return false;
1547 
1548     if (!IsA<BitmapImage>(cached_image->GetImage()))
1549       return false;
1550 
1551     UseCounter::Count(GetLayoutObject().GetDocument(),
1552                       WebFeature::kDirectlyCompositedImage);
1553     return true;
1554   }
1555 
1556   return false;
1557 }
1558 
ContentChanged(ContentChangeType change_type)1559 void CompositedLayerMapping::ContentChanged(ContentChangeType change_type) {
1560   if ((change_type == kImageChanged) && GetLayoutObject().IsImage() &&
1561       IsDirectlyCompositedImage()) {
1562     SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateLocal);
1563     Compositor()->SetNeedsCompositingUpdate(
1564         kCompositingUpdateAfterGeometryChange);
1565     return;
1566   }
1567 
1568   if (change_type == kCanvasChanged &&
1569       IsTextureLayerCanvas(GetLayoutObject())) {
1570     graphics_layer_->SetContentsNeedsDisplay();
1571     return;
1572   }
1573 }
1574 
UpdateImageContents()1575 void CompositedLayerMapping::UpdateImageContents() {
1576   DCHECK_EQ(owning_layer_.Compositor()->Lifecycle().GetState(),
1577             DocumentLifecycle::kInCompositingUpdate);
1578 
1579   DCHECK(GetLayoutObject().IsImage());
1580   LayoutImage& image_layout_object = ToLayoutImage(GetLayoutObject());
1581 
1582   ImageResourceContent* cached_image = image_layout_object.CachedImage();
1583   if (!cached_image)
1584     return;
1585 
1586   Image* image = cached_image->GetImage();
1587   if (!image)
1588     return;
1589 
1590   auto* html_image_element =
1591       DynamicTo<HTMLImageElement>(image_layout_object.GetNode());
1592   Image::ImageDecodingMode decode_mode =
1593       html_image_element ? html_image_element->GetDecodingModeForPainting(
1594                                image->paint_image_id())
1595                          : Image::kUnspecifiedDecode;
1596 
1597   // This is a no-op if the layer doesn't have an inner layer for the image.
1598   graphics_layer_->SetContentsToImage(
1599       image, decode_mode,
1600       LayoutObject::ShouldRespectImageOrientation(&image_layout_object));
1601 
1602   graphics_layer_->SetFilterQuality(
1603       GetLayoutObject().StyleRef().ImageRendering() ==
1604               EImageRendering::kPixelated
1605           ? kNone_SkFilterQuality
1606           : kLow_SkFilterQuality);
1607 
1608   // Prevent double-drawing: https://bugs.webkit.org/show_bug.cgi?id=58632
1609   UpdateDrawsContentAndPaintsHitTest();
1610 
1611   // Image animation is "lazy", in that it automatically stops unless someone is
1612   // drawing the image. So we have to kick the animation each time; this has the
1613   // downside that the image will keep animating, even if its layer is not
1614   // visible.
1615   image->StartAnimation();
1616 }
1617 
ComputeTransformOrigin(const IntRect & border_box) const1618 FloatPoint3D CompositedLayerMapping::ComputeTransformOrigin(
1619     const IntRect& border_box) const {
1620   const ComputedStyle& style = GetLayoutObject().StyleRef();
1621 
1622   FloatPoint3D origin;
1623   origin.SetX(
1624       FloatValueForLength(style.TransformOriginX(), border_box.Width()));
1625   origin.SetY(
1626       FloatValueForLength(style.TransformOriginY(), border_box.Height()));
1627   origin.SetZ(style.TransformOriginZ());
1628 
1629   return origin;
1630 }
1631 
1632 // Return the offset from the top-left of this compositing layer at which the
1633 // LayoutObject's contents are painted.
ContentOffsetInCompositingLayer() const1634 PhysicalOffset CompositedLayerMapping::ContentOffsetInCompositingLayer() const {
1635   return owning_layer_.SubpixelAccumulation() -
1636          PhysicalOffset(graphics_layer_->OffsetFromLayoutObject());
1637 }
1638 
ContentsBox() const1639 PhysicalRect CompositedLayerMapping::ContentsBox() const {
1640   PhysicalRect contents_box = ContentsRect(GetLayoutObject());
1641   contents_box.Move(ContentOffsetInCompositingLayer());
1642   return contents_box;
1643 }
1644 
NeedsToReparentOverflowControls() const1645 bool CompositedLayerMapping::NeedsToReparentOverflowControls() const {
1646   return owning_layer_.NeedsReorderOverlayOverflowControls();
1647 }
1648 
DetachLayerForOverflowControls()1649 GraphicsLayer* CompositedLayerMapping::DetachLayerForOverflowControls() {
1650   if (overflow_controls_host_layer_)
1651     overflow_controls_host_layer_->RemoveFromParent();
1652   return overflow_controls_host_layer_.get();
1653 }
1654 
DetachLayerForDecorationOutline()1655 GraphicsLayer* CompositedLayerMapping::DetachLayerForDecorationOutline() {
1656   if (!decoration_outline_layer_.get())
1657     return nullptr;
1658   decoration_outline_layer_->RemoveFromParent();
1659   return decoration_outline_layer_.get();
1660 }
1661 
ParentForSublayers() const1662 GraphicsLayer* CompositedLayerMapping::ParentForSublayers() const {
1663   if (scrolling_contents_layer_)
1664     return scrolling_contents_layer_.get();
1665 
1666   return graphics_layer_.get();
1667 }
1668 
SetSublayers(const GraphicsLayerVector & sublayers)1669 void CompositedLayerMapping::SetSublayers(
1670     const GraphicsLayerVector& sublayers) {
1671   GraphicsLayer* overflow_controls_container =
1672       overflow_controls_host_layer_.get();
1673   GraphicsLayer* parent = ParentForSublayers();
1674   bool needs_overflow_controls_reattached =
1675       overflow_controls_container &&
1676       overflow_controls_container->Parent() == parent;
1677 
1678   parent->SetChildren(sublayers);
1679 
1680   // If we have scrollbars, but are not using composited scrolling, then
1681   // parentForSublayers may return m_graphicsLayer.  In that case, the above
1682   // call to setChildren has clobbered the overflow controls host layer, so we
1683   // need to reattach it.
1684   if (needs_overflow_controls_reattached)
1685     parent->AddChild(overflow_controls_container);
1686 }
1687 
ChildForSuperlayers() const1688 GraphicsLayer* CompositedLayerMapping::ChildForSuperlayers() const {
1689   if (squashing_containment_layer_)
1690     return squashing_containment_layer_.get();
1691 
1692   return graphics_layer_.get();
1693 }
1694 
UpdateTypeForChildren(GraphicsLayerUpdater::UpdateType update_type) const1695 GraphicsLayerUpdater::UpdateType CompositedLayerMapping::UpdateTypeForChildren(
1696     GraphicsLayerUpdater::UpdateType update_type) const {
1697   if (pending_update_scope_ >= kGraphicsLayerUpdateSubtree)
1698     return GraphicsLayerUpdater::kForceUpdate;
1699   return update_type;
1700 }
1701 
1702 struct SetContentsNeedsDisplayFunctor {
operator ()blink::SetContentsNeedsDisplayFunctor1703   void operator()(GraphicsLayer* layer) const {
1704     if (layer->PaintsContentOrHitTest())
1705       layer->SetNeedsDisplay();
1706   }
1707 };
1708 
SetSquashingContentsNeedDisplay()1709 void CompositedLayerMapping::SetSquashingContentsNeedDisplay() {
1710   ApplyToGraphicsLayers(this, SetContentsNeedsDisplayFunctor(),
1711                         kApplyToSquashingLayer);
1712 }
1713 
SetContentsNeedDisplay()1714 void CompositedLayerMapping::SetContentsNeedDisplay() {
1715   // FIXME: need to split out paint invalidations for the background.
1716   ApplyToGraphicsLayers(this, SetContentsNeedsDisplayFunctor(),
1717                         kApplyToContentLayers);
1718 }
1719 
SetNeedsCheckRasterInvalidation()1720 void CompositedLayerMapping::SetNeedsCheckRasterInvalidation() {
1721   ApplyToGraphicsLayers(
1722       this,
1723       [](GraphicsLayer* graphics_layer) {
1724         if (graphics_layer->DrawsContent())
1725           graphics_layer->SetNeedsCheckRasterInvalidation();
1726       },
1727       kApplyToAllGraphicsLayers);
1728 }
1729 
ContainingSquashedLayer(const LayoutObject * layout_object,const Vector<GraphicsLayerPaintInfo> & layers,unsigned max_squashed_layer_index)1730 const GraphicsLayerPaintInfo* CompositedLayerMapping::ContainingSquashedLayer(
1731     const LayoutObject* layout_object,
1732     const Vector<GraphicsLayerPaintInfo>& layers,
1733     unsigned max_squashed_layer_index) {
1734   if (!layout_object)
1735     return nullptr;
1736   for (wtf_size_t i = 0; i < layers.size() && i < max_squashed_layer_index;
1737        ++i) {
1738     if (layout_object->IsDescendantOf(
1739             &layers[i].paint_layer->GetLayoutObject()))
1740       return &layers[i];
1741   }
1742   return nullptr;
1743 }
1744 
ContainingSquashedLayer(const LayoutObject * layout_object,unsigned max_squashed_layer_index)1745 const GraphicsLayerPaintInfo* CompositedLayerMapping::ContainingSquashedLayer(
1746     const LayoutObject* layout_object,
1747     unsigned max_squashed_layer_index) {
1748   return CompositedLayerMapping::ContainingSquashedLayer(
1749       layout_object, squashed_layers_, max_squashed_layer_index);
1750 }
1751 
LocalClipRectForSquashedLayer(const PaintLayer & reference_layer,const Vector<GraphicsLayerPaintInfo> & layers,GraphicsLayerPaintInfo & paint_info)1752 void CompositedLayerMapping::LocalClipRectForSquashedLayer(
1753     const PaintLayer& reference_layer,
1754     const Vector<GraphicsLayerPaintInfo>& layers,
1755     GraphicsLayerPaintInfo& paint_info) {
1756   const LayoutObject* clipping_container =
1757       paint_info.paint_layer->ClippingContainer();
1758   if (clipping_container == reference_layer.ClippingContainer()) {
1759     paint_info.local_clip_rect_for_squashed_layer =
1760         ClipRect(PhysicalRect(LayoutRect::InfiniteIntRect()));
1761     paint_info.offset_from_clip_rect_root = PhysicalOffset();
1762     paint_info.local_clip_rect_root = paint_info.paint_layer;
1763     return;
1764   }
1765 
1766   DCHECK(clipping_container);
1767 
1768   const GraphicsLayerPaintInfo* ancestor_paint_info =
1769       ContainingSquashedLayer(clipping_container, layers, layers.size());
1770   // Must be there, otherwise
1771   // CompositingLayerAssigner::canSquashIntoCurrentSquashingOwner would have
1772   // disallowed squashing.
1773   DCHECK(ancestor_paint_info);
1774 
1775   // FIXME: this is a potential performance issue. We should consider caching
1776   // these clip rects or otherwise optimizing.
1777   ClipRectsContext clip_rects_context(
1778       ancestor_paint_info->paint_layer,
1779       &ancestor_paint_info->paint_layer->GetLayoutObject().FirstFragment(),
1780       kUncachedClipRects);
1781   ClipRect parent_clip_rect;
1782   paint_info.paint_layer
1783       ->Clipper(PaintLayer::GeometryMapperOption::kDoNotUseGeometryMapper)
1784       .CalculateBackgroundClipRect(clip_rects_context, parent_clip_rect);
1785 
1786   // Convert from ancestor to local coordinates.
1787   IntSize ancestor_to_local_offset =
1788       paint_info.offset_from_layout_object -
1789       ancestor_paint_info->offset_from_layout_object;
1790   parent_clip_rect.Move(PhysicalOffset(ancestor_to_local_offset));
1791   paint_info.local_clip_rect_for_squashed_layer = parent_clip_rect;
1792   paint_info.offset_from_clip_rect_root =
1793       PhysicalOffset(ancestor_to_local_offset);
1794   paint_info.local_clip_rect_root = ancestor_paint_info->paint_layer;
1795 }
1796 
DoPaintTask(const GraphicsLayerPaintInfo & paint_info,const GraphicsLayer & graphics_layer,PaintLayerFlags paint_layer_flags,GraphicsContext & context,const IntRect & clip) const1797 void CompositedLayerMapping::DoPaintTask(
1798     const GraphicsLayerPaintInfo& paint_info,
1799     const GraphicsLayer& graphics_layer,
1800     PaintLayerFlags paint_layer_flags,
1801     GraphicsContext& context,
1802     const IntRect& clip /* In the coords of rootLayer */) const {
1803   FontCachePurgePreventer font_cache_purge_preventer;
1804 
1805   IntSize offset = paint_info.offset_from_layout_object;
1806   // The dirtyRect is in the coords of the painting root.
1807   IntRect dirty_rect(clip);
1808   dirty_rect.Move(offset);
1809 
1810   if (paint_layer_flags & (kPaintLayerPaintingOverflowContents)) {
1811     dirty_rect.MoveBy(
1812         RoundedIntPoint(paint_info.paint_layer->SubpixelAccumulation()));
1813   } else {
1814     PhysicalRect bounds = paint_info.composited_bounds;
1815     bounds.Move(paint_info.paint_layer->SubpixelAccumulation());
1816     dirty_rect.Intersect(PixelSnappedIntRect(bounds));
1817   }
1818 
1819 #if DCHECK_IS_ON()
1820   if (!GetLayoutObject().View()->GetFrame() ||
1821       !GetLayoutObject().View()->GetFrame()->ShouldThrottleRendering())
1822     paint_info.paint_layer->GetLayoutObject().AssertSubtreeIsLaidOut();
1823 #endif
1824 
1825   float device_scale_factor = blink::DeviceScaleFactorDeprecated(
1826       paint_info.paint_layer->GetLayoutObject().GetFrame());
1827   context.SetDeviceScaleFactor(device_scale_factor);
1828 
1829   Settings* settings = GetLayoutObject().GetFrame()->GetSettings();
1830   context.SetDarkMode(
1831       BuildDarkModeSettings(*settings, *GetLayoutObject().View()));
1832 
1833   if (paint_info.paint_layer->GetCompositingState() !=
1834       kPaintsIntoGroupedBacking) {
1835     // FIXME: GraphicsLayers need a way to split for multicol.
1836     PaintLayerPaintingInfo painting_info(
1837         paint_info.paint_layer, CullRect(dirty_rect), kGlobalPaintNormalPhase,
1838         paint_info.paint_layer->SubpixelAccumulation());
1839     PaintLayerPainter(*paint_info.paint_layer)
1840         .PaintLayerContents(context, painting_info, paint_layer_flags);
1841   } else {
1842     PaintLayerPaintingInfo painting_info(
1843         paint_info.paint_layer, CullRect(dirty_rect), kGlobalPaintNormalPhase,
1844         paint_info.paint_layer->SubpixelAccumulation());
1845     PaintLayerPainter(*paint_info.paint_layer)
1846         .Paint(context, painting_info, paint_layer_flags);
1847   }
1848 }
1849 
1850 // TODO(eseckler): Make recording distance configurable, e.g. for use in
1851 // headless, where we would like to record an exact area.
1852 // Note however that the minimum value for this constant is the size of a
1853 // raster tile. This is because the raster system is not able to raster a
1854 // tile that is not completely covered by a display list. If the constant
1855 // were less than the size of a tile, then a tile which partially overlaps
1856 // the screen may not be rastered.
1857 static const int kPixelDistanceToRecord = 4000;
1858 
RecomputeInterestRect(const GraphicsLayer * graphics_layer) const1859 IntRect CompositedLayerMapping::RecomputeInterestRect(
1860     const GraphicsLayer* graphics_layer) const {
1861   IntRect graphics_layer_bounds(IntPoint(), IntSize(graphics_layer->Size()));
1862 
1863   FloatClipRect mapping_rect((FloatRect(graphics_layer_bounds)));
1864 
1865   PropertyTreeState source_state = graphics_layer->GetPropertyTreeState();
1866 
1867   LayoutView* root_view = owning_layer_.GetLayoutObject().View();
1868   while (root_view->GetFrame()->OwnerLayoutObject())
1869     root_view = root_view->GetFrame()->OwnerLayoutObject()->View();
1870 
1871   PropertyTreeState root_view_contents_state =
1872       root_view->FirstFragment().ContentsProperties();
1873   PropertyTreeState root_view_border_box_state =
1874       root_view->FirstFragment().LocalBorderBoxProperties();
1875 
1876   // 1. Move into local transform space.
1877   mapping_rect.MoveBy(FloatPoint(graphics_layer->GetOffsetFromTransformNode()));
1878   // 2. Map into contents space of the root LayoutView.
1879   GeometryMapper::LocalToAncestorVisualRect(
1880       source_state, root_view_contents_state, mapping_rect);
1881 
1882   FloatRect visible_content_rect(EnclosingIntRect(mapping_rect.Rect()));
1883 
1884   // 3. Move into local border box transform space of the root LayoutView.
1885   // Note that the overflow clip has *not* been applied.
1886   GeometryMapper::SourceToDestinationRect(
1887       root_view_contents_state.Transform(),
1888       root_view_border_box_state.Transform(), visible_content_rect);
1889 
1890   // 4. Apply overflow clip, or adjusted version if necessary.
1891   root_view->GetFrameView()->ClipPaintRect(&visible_content_rect);
1892 
1893   FloatRect local_interest_rect;
1894   // If the visible content rect is empty, then it makes no sense to map it back
1895   // since there is nothing to map.
1896   if (!visible_content_rect.IsEmpty()) {
1897     local_interest_rect = visible_content_rect;
1898     // 5. Map the visible content rect from root view space to local graphics
1899     // layer space.
1900     GeometryMapper::SourceToDestinationRect(
1901         root_view_border_box_state.Transform(), source_state.Transform(),
1902         local_interest_rect);
1903     local_interest_rect.MoveBy(
1904         -FloatPoint(graphics_layer->GetOffsetFromTransformNode()));
1905 
1906     // TODO(chrishtr): the code below is a heuristic. Instead we should detect
1907     // and return whether the mapping failed.  In some cases,
1908     // absoluteToLocalQuad can fail to map back to the local space, due to
1909     // passing through non-invertible transforms or floating-point accuracy
1910     // issues. Examples include rotation near 90 degrees or perspective. In such
1911     // cases, fall back to painting the first kPixelDistanceToRecord pixels in
1912     // each direction.
1913 
1914     // Note that since the interest rect mapping above can produce extremely
1915     // large numbers in cases of perspective, try our best to "normalize" the
1916     // result by ensuring that none of the rect dimensions exceed some large,
1917     // but reasonable, limit.
1918     const float reasonable_pixel_limit = std::numeric_limits<int>::max() / 2.f;
1919     auto unpadded_intersection = local_interest_rect;
1920 
1921     // Note that by clamping X and Y, we are effectively moving the rect right /
1922     // down. However, this will at most make us paint more content, which is
1923     // better than erroneously deciding that the rect produced here is far
1924     // offscreen.
1925     if (unpadded_intersection.X() < -reasonable_pixel_limit)
1926       unpadded_intersection.SetX(-reasonable_pixel_limit);
1927     if (unpadded_intersection.Y() < -reasonable_pixel_limit)
1928       unpadded_intersection.SetY(-reasonable_pixel_limit);
1929     if (unpadded_intersection.MaxX() > reasonable_pixel_limit) {
1930       unpadded_intersection.SetWidth(reasonable_pixel_limit -
1931                                      unpadded_intersection.X());
1932     }
1933     if (unpadded_intersection.MaxY() > reasonable_pixel_limit) {
1934       unpadded_intersection.SetHeight(reasonable_pixel_limit -
1935                                       unpadded_intersection.Y());
1936     }
1937 
1938     unpadded_intersection.Intersect(FloatRect(graphics_layer_bounds));
1939     // If our unpadded intersection is not empty, then use that before padding,
1940     // since it can produce more stable results, and it would not produce any
1941     // smaller area than if we used the original local interest rect.
1942     if (!unpadded_intersection.IsEmpty())
1943       local_interest_rect = unpadded_intersection;
1944 
1945     // Expand by interest rect padding amount, scaled by the approximate scale
1946     // of the GraphicsLayer relative to screen pixels. If width or height
1947     // are zero or nearly zero, fall back to kPixelDistanceToRecord.
1948     // This is the same as the else clause below.
1949     float x_scale =
1950         visible_content_rect.Width() > std::numeric_limits<float>::epsilon()
1951             ? local_interest_rect.Width() / visible_content_rect.Width()
1952             : 1.0f;
1953     float y_scale =
1954         visible_content_rect.Height() > std::numeric_limits<float>::epsilon()
1955             ? local_interest_rect.Height() / visible_content_rect.Height()
1956             : 1.0f;
1957     // Take the max, to account for situations like rotation transforms, which
1958     // swap x and y.
1959     // Since at this point we can also have an extremely large scale due to
1960     // perspective (see the comments above), cap it to something reasonable.
1961     float scale = std::min(std::max(x_scale, y_scale),
1962                            reasonable_pixel_limit / kPixelDistanceToRecord);
1963     local_interest_rect.Inflate(kPixelDistanceToRecord * scale);
1964   } else {
1965     // Expand by interest rect padding amount.
1966     local_interest_rect.Inflate(kPixelDistanceToRecord);
1967   }
1968   return Intersection(EnclosingIntRect(local_interest_rect),
1969                       graphics_layer_bounds);
1970 }
1971 
1972 static const int kMinimumDistanceBeforeRepaint = 512;
1973 
InterestRectChangedEnoughToRepaint(const IntRect & previous_interest_rect,const IntRect & new_interest_rect,const IntSize & layer_size)1974 bool CompositedLayerMapping::InterestRectChangedEnoughToRepaint(
1975     const IntRect& previous_interest_rect,
1976     const IntRect& new_interest_rect,
1977     const IntSize& layer_size) {
1978   if (previous_interest_rect.IsEmpty() && new_interest_rect.IsEmpty())
1979     return false;
1980 
1981   // Repaint when going from empty to not-empty, to cover cases where the layer
1982   // is painted for the first time, or otherwise becomes visible.
1983   if (previous_interest_rect.IsEmpty())
1984     return true;
1985 
1986   // Repaint if the new interest rect includes area outside of a skirt around
1987   // the existing interest rect.
1988   IntRect expanded_previous_interest_rect(previous_interest_rect);
1989   expanded_previous_interest_rect.Inflate(kMinimumDistanceBeforeRepaint);
1990   if (!expanded_previous_interest_rect.Contains(new_interest_rect))
1991     return true;
1992 
1993   // Even if the new interest rect doesn't include enough new area to satisfy
1994   // the condition above, repaint anyway if it touches a layer edge not touched
1995   // by the existing interest rect.  Because it's impossible to expose more area
1996   // in the direction, repainting cannot be deferred until the exposed new area
1997   // satisfies the condition above.
1998   if (new_interest_rect.X() == 0 && previous_interest_rect.X() != 0)
1999     return true;
2000   if (new_interest_rect.Y() == 0 && previous_interest_rect.Y() != 0)
2001     return true;
2002   if (new_interest_rect.MaxX() == layer_size.Width() &&
2003       previous_interest_rect.MaxX() != layer_size.Width())
2004     return true;
2005   if (new_interest_rect.MaxY() == layer_size.Height() &&
2006       previous_interest_rect.MaxY() != layer_size.Height())
2007     return true;
2008 
2009   return false;
2010 }
2011 
ComputeInterestRect(const GraphicsLayer * graphics_layer,const IntRect & previous_interest_rect) const2012 IntRect CompositedLayerMapping::ComputeInterestRect(
2013     const GraphicsLayer* graphics_layer,
2014     const IntRect& previous_interest_rect) const {
2015   // Use the previous interest rect if it covers the whole layer.
2016   IntRect whole_layer_rect =
2017       IntRect(IntPoint(), IntSize(graphics_layer->Size()));
2018   if (!NeedsRepaint(*graphics_layer) &&
2019       previous_interest_rect == whole_layer_rect)
2020     return previous_interest_rect;
2021 
2022   if (graphics_layer != graphics_layer_.get() &&
2023       graphics_layer != squashing_layer_.get() &&
2024       graphics_layer != scrolling_contents_layer_.get())
2025     return whole_layer_rect;
2026 
2027   IntRect new_interest_rect = RecomputeInterestRect(graphics_layer);
2028   if (NeedsRepaint(*graphics_layer) ||
2029       InterestRectChangedEnoughToRepaint(previous_interest_rect,
2030                                          new_interest_rect,
2031                                          IntSize(graphics_layer->Size())))
2032     return new_interest_rect;
2033   return previous_interest_rect;
2034 }
2035 
SubpixelAccumulation() const2036 LayoutSize CompositedLayerMapping::SubpixelAccumulation() const {
2037   return owning_layer_.SubpixelAccumulation().ToLayoutSize();
2038 }
2039 
NeedsRepaint(const GraphicsLayer & graphics_layer) const2040 bool CompositedLayerMapping::NeedsRepaint(
2041     const GraphicsLayer& graphics_layer) const {
2042   return IsScrollableAreaLayerWhichNeedsRepaint(&graphics_layer) ||
2043          owning_layer_.SelfOrDescendantNeedsRepaint();
2044 }
2045 
AdjustForCompositedScrolling(const GraphicsLayer * graphics_layer,IntSize & offset) const2046 bool CompositedLayerMapping::AdjustForCompositedScrolling(
2047     const GraphicsLayer* graphics_layer,
2048     IntSize& offset) const {
2049   if (graphics_layer == scrolling_contents_layer_.get() ||
2050       graphics_layer == foreground_layer_.get()) {
2051     if (PaintLayerScrollableArea* scrollable_area =
2052             owning_layer_.GetScrollableArea()) {
2053       if (scrollable_area->UsesCompositedScrolling()) {
2054         // Note: this is the offset from the beginning of flow of the block, not
2055         // the offset from the top/left of the overflow rect.
2056         // offsetFromLayoutObject adds the origin offset from top/left to the
2057         // beginning of flow.
2058         ScrollOffset scroll_offset = scrollable_area->GetScrollOffset();
2059         offset.Expand(-scroll_offset.Width(), -scroll_offset.Height());
2060         return true;
2061       }
2062     }
2063   }
2064   return false;
2065 }
2066 
PaintContents(const GraphicsLayer * graphics_layer,GraphicsContext & context,GraphicsLayerPaintingPhase graphics_layer_painting_phase,const IntRect & interest_rect) const2067 void CompositedLayerMapping::PaintContents(
2068     const GraphicsLayer* graphics_layer,
2069     GraphicsContext& context,
2070     GraphicsLayerPaintingPhase graphics_layer_painting_phase,
2071     const IntRect& interest_rect) const {
2072   FramePaintTiming frame_paint_timing(context, GetLayoutObject().GetFrame());
2073 
2074   // https://code.google.com/p/chromium/issues/detail?id=343772
2075   DisableCompositingQueryAsserts disabler;
2076   // Allow throttling to make sure no painting paths (e.g.,
2077   // GraphicsLayer::PaintContents) try to paint throttled content.
2078   DocumentLifecycle::AllowThrottlingScope allow_throttling(
2079       owning_layer_.GetLayoutObject().GetDocument().Lifecycle());
2080 #if DCHECK_IS_ON()
2081   // FIXME: once the state machine is ready, this can be removed and we can
2082   // refer to that instead.
2083   if (Page* page = GetLayoutObject().GetFrame()->GetPage())
2084     page->SetIsPainting(true);
2085 #endif
2086 
2087   TRACE_EVENT1(
2088       "devtools.timeline,rail", "Paint", "data",
2089       inspector_paint_event::Data(&owning_layer_.GetLayoutObject(),
2090                                   PhysicalRect(interest_rect), graphics_layer));
2091 
2092   PaintLayerFlags paint_layer_flags = 0;
2093   if (graphics_layer_painting_phase & kGraphicsLayerPaintBackground)
2094     paint_layer_flags |= kPaintLayerPaintingCompositingBackgroundPhase;
2095   else
2096     paint_layer_flags |= kPaintLayerPaintingSkipRootBackground;
2097   if (graphics_layer_painting_phase & kGraphicsLayerPaintForeground)
2098     paint_layer_flags |= kPaintLayerPaintingCompositingForegroundPhase;
2099   if (graphics_layer_painting_phase & kGraphicsLayerPaintMask)
2100     paint_layer_flags |= kPaintLayerPaintingCompositingMaskPhase;
2101   if (graphics_layer_painting_phase & kGraphicsLayerPaintOverflowContents)
2102     paint_layer_flags |= kPaintLayerPaintingOverflowContents;
2103   if (graphics_layer_painting_phase & kGraphicsLayerPaintCompositedScroll)
2104     paint_layer_flags |= kPaintLayerPaintingCompositingScrollingPhase;
2105   if (graphics_layer_painting_phase & kGraphicsLayerPaintDecoration)
2106     paint_layer_flags |= kPaintLayerPaintingCompositingDecorationPhase;
2107 
2108   if (graphics_layer == graphics_layer_.get() ||
2109       graphics_layer == foreground_layer_.get() ||
2110       graphics_layer == mask_layer_.get() ||
2111       graphics_layer == scrolling_contents_layer_.get() ||
2112       graphics_layer == decoration_outline_layer_.get()) {
2113     if (BackgroundPaintsOntoScrollingContentsLayer()) {
2114       if (graphics_layer == scrolling_contents_layer_.get())
2115         paint_layer_flags &= ~kPaintLayerPaintingSkipRootBackground;
2116       else if (!BackgroundPaintsOntoGraphicsLayer())
2117         paint_layer_flags |= kPaintLayerPaintingSkipRootBackground;
2118     }
2119 
2120     GraphicsLayerPaintInfo paint_info;
2121     paint_info.paint_layer = &owning_layer_;
2122     paint_info.composited_bounds = CompositedBounds();
2123     paint_info.offset_from_layout_object =
2124         graphics_layer->OffsetFromLayoutObject();
2125     AdjustForCompositedScrolling(graphics_layer,
2126                                  paint_info.offset_from_layout_object);
2127 
2128     // We have to use the same root as for hit testing, because both methods can
2129     // compute and cache clipRects.
2130     DoPaintTask(paint_info, *graphics_layer, paint_layer_flags, context,
2131                 interest_rect);
2132   } else if (graphics_layer == squashing_layer_.get()) {
2133     for (wtf_size_t i = 0; i < squashed_layers_.size(); ++i) {
2134       DoPaintTask(squashed_layers_[i], *graphics_layer, paint_layer_flags,
2135                   context, interest_rect);
2136     }
2137   } else if (IsScrollableAreaLayer(graphics_layer)) {
2138     PaintScrollableArea(graphics_layer, context, interest_rect);
2139   }
2140 
2141 #if DCHECK_IS_ON()
2142   if (Page* page = GetLayoutObject().GetFrame()->GetPage())
2143     page->SetIsPainting(false);
2144 #endif
2145 }
2146 
PaintScrollableArea(const GraphicsLayer * graphics_layer,GraphicsContext & context,const IntRect & interest_rect) const2147 void CompositedLayerMapping::PaintScrollableArea(
2148     const GraphicsLayer* graphics_layer,
2149     GraphicsContext& context,
2150     const IntRect& interest_rect) const {
2151   // cull_rect is in the space of the containing scrollable area in which
2152   // Scrollbar::Paint() will paint the scrollbar.
2153   CullRect cull_rect(interest_rect);
2154   cull_rect.Move(graphics_layer->OffsetFromLayoutObject());
2155   PaintLayerScrollableArea* scrollable_area = owning_layer_.GetScrollableArea();
2156   if (graphics_layer == LayerForHorizontalScrollbar()) {
2157     if (const Scrollbar* scrollbar = scrollable_area->HorizontalScrollbar()) {
2158       if (cull_rect.Intersects(scrollbar->FrameRect()))
2159         scrollbar->Paint(context, IntPoint());
2160     }
2161   } else if (graphics_layer == LayerForVerticalScrollbar()) {
2162     if (const Scrollbar* scrollbar = scrollable_area->VerticalScrollbar()) {
2163       if (cull_rect.Intersects(scrollbar->FrameRect()))
2164         scrollbar->Paint(context, IntPoint());
2165     }
2166   } else if (graphics_layer == LayerForScrollCorner()) {
2167     ScrollableAreaPainter painter(*scrollable_area);
2168     painter.PaintScrollCorner(context, IntPoint(), cull_rect);
2169     painter.PaintResizer(context, IntPoint(), cull_rect);
2170   }
2171 }
2172 
IsScrollableAreaLayer(const GraphicsLayer * graphics_layer) const2173 bool CompositedLayerMapping::IsScrollableAreaLayer(
2174     const GraphicsLayer* graphics_layer) const {
2175   return graphics_layer == LayerForHorizontalScrollbar() ||
2176          graphics_layer == LayerForVerticalScrollbar() ||
2177          graphics_layer == LayerForScrollCorner();
2178 }
2179 
IsScrollableAreaLayerWhichNeedsRepaint(const GraphicsLayer * graphics_layer) const2180 bool CompositedLayerMapping::IsScrollableAreaLayerWhichNeedsRepaint(
2181     const GraphicsLayer* graphics_layer) const {
2182   if (PaintLayerScrollableArea* scrollable_area =
2183           owning_layer_.GetScrollableArea()) {
2184     if (graphics_layer == LayerForHorizontalScrollbar())
2185       return scrollable_area->HorizontalScrollbarNeedsPaintInvalidation();
2186 
2187     if (graphics_layer == LayerForVerticalScrollbar())
2188       return scrollable_area->VerticalScrollbarNeedsPaintInvalidation();
2189 
2190     if (graphics_layer == LayerForScrollCorner())
2191       return scrollable_area->ScrollCornerNeedsPaintInvalidation();
2192   }
2193 
2194   return false;
2195 }
2196 
ShouldThrottleRendering() const2197 bool CompositedLayerMapping::ShouldThrottleRendering() const {
2198   return GetLayoutObject().GetFrame()->ShouldThrottleRendering();
2199 }
2200 
IsUnderSVGHiddenContainer() const2201 bool CompositedLayerMapping::IsUnderSVGHiddenContainer() const {
2202   return owning_layer_.IsUnderSVGHiddenContainer();
2203 }
2204 
IsTrackingRasterInvalidations() const2205 bool CompositedLayerMapping::IsTrackingRasterInvalidations() const {
2206   return GetLayoutObject().GetFrameView()->IsTrackingRasterInvalidations();
2207 }
2208 
GraphicsLayersDidChange()2209 void CompositedLayerMapping::GraphicsLayersDidChange() {
2210   LocalFrameView* frame_view = GetLayoutObject().GetFrameView();
2211   DCHECK(frame_view);
2212   frame_view->SetForeignLayerListNeedsUpdate();
2213 }
2214 
PaintBlockedByDisplayLockIncludingAncestors(DisplayLockContextLifecycleTarget target) const2215 bool CompositedLayerMapping::PaintBlockedByDisplayLockIncludingAncestors(
2216     DisplayLockContextLifecycleTarget target) const {
2217   auto* node = GetLayoutObject().GetNode();
2218   if (node) {
2219     auto* element = DynamicTo<Element>(node);
2220     if (target == DisplayLockContextLifecycleTarget::kSelf && element) {
2221       if (auto* context = element->GetDisplayLockContext()) {
2222         if (!context->ShouldPaint(DisplayLockLifecycleTarget::kSelf))
2223           return true;
2224       }
2225     }
2226   }
2227   return DisplayLockUtilities::NearestLockedExclusiveAncestor(
2228       GetLayoutObject());
2229 }
2230 
NotifyDisplayLockNeedsGraphicsLayerCollection()2231 void CompositedLayerMapping::NotifyDisplayLockNeedsGraphicsLayerCollection() {
2232   if (auto* locked_element =
2233           DisplayLockUtilities::NearestLockedInclusiveAncestor(
2234               GetLayoutObject())) {
2235     locked_element->GetDisplayLockContext()
2236         ->NotifyNeedsGraphicsLayerCollection();
2237   }
2238 }
2239 
2240 #if DCHECK_IS_ON()
VerifyNotPainting()2241 void CompositedLayerMapping::VerifyNotPainting() {
2242   DCHECK(!GetLayoutObject().GetFrame()->GetPage() ||
2243          !GetLayoutObject().GetFrame()->GetPage()->IsPainting());
2244 }
2245 #endif
2246 
InvalidateLayerIfNoPrecedingEntry(wtf_size_t index_to_clear)2247 bool CompositedLayerMapping::InvalidateLayerIfNoPrecedingEntry(
2248     wtf_size_t index_to_clear) {
2249   PaintLayer* layer_to_remove = squashed_layers_[index_to_clear].paint_layer;
2250   wtf_size_t previous_index = 0;
2251   for (; previous_index < index_to_clear; ++previous_index) {
2252     if (squashed_layers_[previous_index].paint_layer == layer_to_remove)
2253       break;
2254   }
2255   if (previous_index == index_to_clear &&
2256       layer_to_remove->GroupedMapping() == this) {
2257     Compositor()->PaintInvalidationOnCompositingChange(layer_to_remove);
2258     return true;
2259   }
2260   return false;
2261 }
2262 
UpdateSquashingLayerAssignment(PaintLayer * squashed_layer,wtf_size_t next_squashed_layer_index)2263 bool CompositedLayerMapping::UpdateSquashingLayerAssignment(
2264     PaintLayer* squashed_layer,
2265     wtf_size_t next_squashed_layer_index) {
2266   GraphicsLayerPaintInfo paint_info;
2267   paint_info.paint_layer = squashed_layer;
2268   // NOTE: composited bounds are updated elsewhere
2269   // NOTE: offsetFromLayoutObject is updated elsewhere
2270 
2271   // Change tracking on squashing layers: at the first sign of something
2272   // changed, just invalidate the layer.
2273   // FIXME: Perhaps we can find a tighter more clever mechanism later.
2274   if (next_squashed_layer_index < squashed_layers_.size()) {
2275     if (paint_info.paint_layer ==
2276         squashed_layers_[next_squashed_layer_index].paint_layer)
2277       return false;
2278 
2279     // Must invalidate before adding the squashed layer to the mapping.
2280     Compositor()->PaintInvalidationOnCompositingChange(squashed_layer);
2281 
2282     // If the layer which was previously at |nextSquashedLayerIndex| is not
2283     // earlier in the grouped mapping, invalidate its current backing now, since
2284     // it will move later or be removed from the squashing layer.
2285     InvalidateLayerIfNoPrecedingEntry(next_squashed_layer_index);
2286 
2287     squashed_layers_.insert(next_squashed_layer_index, paint_info);
2288   } else {
2289     // Must invalidate before adding the squashed layer to the mapping.
2290     Compositor()->PaintInvalidationOnCompositingChange(squashed_layer);
2291     squashed_layers_.push_back(paint_info);
2292   }
2293   squashed_layer->SetGroupedMapping(
2294       this, PaintLayer::kInvalidateLayerAndRemoveFromMapping);
2295 
2296   return true;
2297 }
2298 
RemoveLayerFromSquashingGraphicsLayer(const PaintLayer * layer)2299 void CompositedLayerMapping::RemoveLayerFromSquashingGraphicsLayer(
2300     const PaintLayer* layer) {
2301   wtf_size_t layer_index = 0;
2302   for (; layer_index < squashed_layers_.size(); ++layer_index) {
2303     if (squashed_layers_[layer_index].paint_layer == layer)
2304       break;
2305   }
2306 
2307   // Assert on incorrect mappings between layers and groups
2308   DCHECK_LT(layer_index, squashed_layers_.size());
2309   if (layer_index == squashed_layers_.size())
2310     return;
2311 
2312   squashed_layers_.EraseAt(layer_index);
2313 }
2314 
2315 #if DCHECK_IS_ON()
VerifyLayerInSquashingVector(const PaintLayer * layer)2316 bool CompositedLayerMapping::VerifyLayerInSquashingVector(
2317     const PaintLayer* layer) {
2318   for (wtf_size_t layer_index = 0; layer_index < squashed_layers_.size();
2319        ++layer_index) {
2320     if (squashed_layers_[layer_index].paint_layer == layer)
2321       return true;
2322   }
2323 
2324   return false;
2325 }
2326 #endif
2327 
FinishAccumulatingSquashingLayers(wtf_size_t next_squashed_layer_index,Vector<PaintLayer * > & layers_needing_paint_invalidation)2328 void CompositedLayerMapping::FinishAccumulatingSquashingLayers(
2329     wtf_size_t next_squashed_layer_index,
2330     Vector<PaintLayer*>& layers_needing_paint_invalidation) {
2331   if (next_squashed_layer_index < squashed_layers_.size()) {
2332     // Any additional squashed Layers in the array no longer belong here, but
2333     // they might have been added already at an earlier index. Clear pointers on
2334     // those that do not appear in the valid set before removing all the extra
2335     // entries.
2336     for (wtf_size_t i = next_squashed_layer_index; i < squashed_layers_.size();
2337          ++i) {
2338       if (InvalidateLayerIfNoPrecedingEntry(i)) {
2339         squashed_layers_[i].paint_layer->SetGroupedMapping(
2340             nullptr, PaintLayer::kDoNotInvalidateLayerAndRemoveFromMapping);
2341         squashed_layers_[i].paint_layer->SetLostGroupedMapping(true);
2342       }
2343       layers_needing_paint_invalidation.push_back(
2344           squashed_layers_[i].paint_layer);
2345     }
2346 
2347     squashed_layers_.EraseAt(
2348         next_squashed_layer_index,
2349         squashed_layers_.size() - next_squashed_layer_index);
2350   }
2351 }
2352 
DebugName(const GraphicsLayer * graphics_layer) const2353 String CompositedLayerMapping::DebugName(
2354     const GraphicsLayer* graphics_layer) const {
2355   String name;
2356   if (graphics_layer == graphics_layer_.get()) {
2357     name = owning_layer_.DebugName();
2358   } else if (graphics_layer == squashing_containment_layer_.get()) {
2359     name = "Squashing Containment Layer";
2360   } else if (graphics_layer == squashing_layer_.get()) {
2361     name = "Squashing Layer (first squashed layer: " +
2362            (squashed_layers_.size() > 0
2363                 ? squashed_layers_[0].paint_layer->DebugName()
2364                 : "") +
2365            ")";
2366   } else if (graphics_layer == foreground_layer_.get()) {
2367     name = owning_layer_.DebugName() + " (foreground) Layer";
2368   } else if (graphics_layer == mask_layer_.get()) {
2369     name = "Mask Layer";
2370   } else if (graphics_layer == layer_for_horizontal_scrollbar_.get()) {
2371     name = "Horizontal Scrollbar Layer";
2372   } else if (graphics_layer == layer_for_vertical_scrollbar_.get()) {
2373     name = "Vertical Scrollbar Layer";
2374   } else if (graphics_layer == layer_for_scroll_corner_.get()) {
2375     name = "Scroll Corner Layer";
2376   } else if (graphics_layer == overflow_controls_host_layer_.get()) {
2377     name = "Overflow Controls Host Layer";
2378   } else if (graphics_layer == scrolling_layer_.get()) {
2379     name = "Scrolling Layer";
2380   } else if (graphics_layer == scrolling_contents_layer_.get()) {
2381     name = "Scrolling Contents Layer";
2382   } else if (graphics_layer == decoration_outline_layer_.get()) {
2383     name = "Decoration Layer";
2384   } else {
2385     NOTREACHED();
2386   }
2387 
2388   return name;
2389 }
2390 
GetScrollableAreaForTesting(const GraphicsLayer * layer) const2391 const ScrollableArea* CompositedLayerMapping::GetScrollableAreaForTesting(
2392     const GraphicsLayer* layer) const {
2393   if (layer == scrolling_contents_layer_.get())
2394     return owning_layer_.GetScrollableArea();
2395   return nullptr;
2396 }
2397 
2398 }  // namespace blink
2399