| /* |
| * Copyright (C) 2009, 2010, 2011 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_COMPOSITING_COMPOSITED_LAYER_MAPPING_H_ |
| #define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_COMPOSITING_COMPOSITED_LAYER_MAPPING_H_ |
| |
| #include <memory> |
| #include "third_party/blink/renderer/core/paint/compositing/graphics_layer_updater.h" |
| #include "third_party/blink/renderer/core/paint/paint_layer.h" |
| #include "third_party/blink/renderer/core/paint/paint_layer_painting_info.h" |
| #include "third_party/blink/renderer/platform/geometry/float_point.h" |
| #include "third_party/blink/renderer/platform/geometry/float_point_3d.h" |
| #include "third_party/blink/renderer/platform/graphics/graphics_layer.h" |
| #include "third_party/blink/renderer/platform/graphics/graphics_layer_client.h" |
| #include "third_party/blink/renderer/platform/graphics/graphics_types.h" |
| #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" |
| |
| namespace blink { |
| |
| class PaintLayerCompositor; |
| |
| // A GraphicsLayerPaintInfo contains all the info needed to paint a partial |
| // subtree of Layers into a GraphicsLayer. |
| struct GraphicsLayerPaintInfo { |
| DISALLOW_NEW(); |
| PaintLayer* paint_layer; |
| |
| PhysicalRect composited_bounds; |
| |
| // The clip rect to apply, in the local coordinate space of the squashed |
| // layer, when painting it. |
| ClipRect local_clip_rect_for_squashed_layer; |
| PaintLayer* local_clip_rect_root; |
| PhysicalOffset offset_from_clip_rect_root; |
| |
| // Offset describing where this squashed Layer paints into the shared |
| // GraphicsLayer backing. |
| IntSize offset_from_layout_object; |
| bool offset_from_layout_object_set; |
| |
| GraphicsLayerPaintInfo() |
| : paint_layer(nullptr), offset_from_layout_object_set(false) {} |
| }; |
| |
| enum GraphicsLayerUpdateScope { |
| kGraphicsLayerUpdateNone, |
| kGraphicsLayerUpdateLocal, |
| kGraphicsLayerUpdateSubtree, |
| }; |
| |
| // CompositedLayerMapping keeps track of how PaintLayers correspond to |
| // GraphicsLayers of the composited layer tree. Each instance of |
| // CompositedLayerMapping manages a small cluster of GraphicsLayers and the |
| // references to which Layers and paint phases contribute to each GraphicsLayer. |
| // |
| // - If a PaintLayer is composited, |
| // - if it paints into its own backings (GraphicsLayers), it owns a |
| // CompositedLayerMapping (PaintLayer::compositedLayerMapping()) to keep |
| // track the backings; |
| // - if it paints into grouped backing (i.e. it's squashed), it has a pointer |
| // (PaintLayer::groupedMapping()) to the CompositedLayerMapping into which |
| // the PaintLayer is squashed; |
| // - Otherwise the PaintLayer doesn't own or directly reference any |
| // CompositedLayerMapping. |
| class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient { |
| USING_FAST_MALLOC(CompositedLayerMapping); |
| |
| public: |
| explicit CompositedLayerMapping(PaintLayer&); |
| CompositedLayerMapping(const CompositedLayerMapping&) = delete; |
| CompositedLayerMapping& operator=(const CompositedLayerMapping&) = delete; |
| ~CompositedLayerMapping() override; |
| |
| PaintLayer& OwningLayer() const { return owning_layer_; } |
| |
| bool UpdateGraphicsLayerConfiguration( |
| const PaintLayer* compositing_container); |
| void UpdateGraphicsLayerGeometry( |
| const PaintLayer* compositing_container, |
| Vector<PaintLayer*>& layers_needing_paint_invalidation); |
| |
| // Update whether layer needs blending. |
| void UpdateContentsOpaque(); |
| |
| GraphicsLayer* MainGraphicsLayer() const { return graphics_layer_.get(); } |
| |
| GraphicsLayer* ForegroundLayer() const { return foreground_layer_.get(); } |
| |
| GraphicsLayer* DecorationOutlineLayer() const { |
| return decoration_outline_layer_.get(); |
| } |
| |
| GraphicsLayer* ScrollingContentsLayer() const { |
| return scrolling_contents_layer_.get(); |
| } |
| |
| GraphicsLayer* MaskLayer() const { return mask_layer_.get(); } |
| |
| GraphicsLayer* ParentForSublayers() const; |
| void SetSublayers(GraphicsLayerVector); |
| |
| // Returns the GraphicsLayer that |layer| is squashed into, which may be |
| // NonScrollingSquashingLayer or ScrollingContentsLayer. |
| GraphicsLayer* SquashingLayer(const PaintLayer& squashed_layer) const; |
| |
| GraphicsLayer* NonScrollingSquashingLayer() const { |
| return non_scrolling_squashing_layer_.get(); |
| } |
| const IntSize& NonScrollingSquashingLayerOffsetFromLayoutObject() const { |
| return non_scrolling_squashing_layer_offset_from_layout_object_; |
| } |
| |
| // Let all DrawsContent GraphicsLayers check raster invalidations after |
| // a no-change paint. |
| void SetNeedsCheckRasterInvalidation(); |
| |
| // Notification from the layoutObject that its content changed. |
| void ContentChanged(ContentChangeType); |
| |
| PhysicalRect CompositedBounds() const { return composited_bounds_; } |
| |
| void PositionOverflowControlsLayers(); |
| |
| bool MayBeSquashedIntoScrollingContents(const PaintLayer& layer) const { |
| return layer.AncestorScrollingLayer() == &owning_layer_; |
| } |
| |
| // Returns true if the assignment actually changed the assigned squashing |
| // layer. |
| bool UpdateSquashingLayerAssignment( |
| PaintLayer& squashed_layer, |
| wtf_size_t next_non_scrolling_squashed_layer_index, |
| wtf_size_t next_squashed_layer_in_scrolling_contents_index); |
| void RemoveLayerFromSquashingGraphicsLayer(const PaintLayer&); |
| #if DCHECK_IS_ON() |
| void AssertInSquashedLayersVector(const PaintLayer&) const; |
| #endif |
| |
| void FinishAccumulatingSquashingLayers( |
| wtf_size_t new_non_scrolling_squashed_layer_count, |
| wtf_size_t new_squashed_layer_in_scrolling_contents_count, |
| Vector<PaintLayer*>& layers_needing_paint_invalidation); |
| |
| void UpdateElementId(); |
| |
| // GraphicsLayerClient interface |
| IntRect ComputeInterestRect( |
| const GraphicsLayer*, |
| const IntRect& previous_interest_rect) const override; |
| IntRect PaintableRegion(const GraphicsLayer*) const override; |
| LayoutSize SubpixelAccumulation() const final; |
| bool NeedsRepaint(const GraphicsLayer&) const override; |
| void PaintContents(const GraphicsLayer*, |
| GraphicsContext&, |
| GraphicsLayerPaintingPhase, |
| const IntRect& interest_rect) const override; |
| bool ShouldSkipPaintingSubtree() const override; |
| bool IsTrackingRasterInvalidations() const override; |
| void GraphicsLayersDidChange() override; |
| |
| #if DCHECK_IS_ON() |
| void VerifyNotPainting() override; |
| #endif |
| |
| PhysicalRect ContentsBox() const; |
| |
| GraphicsLayer* LayerForHorizontalScrollbar() const { |
| return layer_for_horizontal_scrollbar_.get(); |
| } |
| GraphicsLayer* LayerForVerticalScrollbar() const { |
| return layer_for_vertical_scrollbar_.get(); |
| } |
| GraphicsLayer* LayerForScrollCorner() const { |
| return layer_for_scroll_corner_.get(); |
| } |
| |
| // Returns true if the overflow controls cannot be positioned within this |
| // CLM's internal hierarchy without incorrectly stacking under some |
| // scrolling content. If this returns true, these controls must be |
| // repositioned in the graphics layer tree to ensure that they stack above |
| // scrolling content. |
| bool NeedsToReparentOverflowControls() const; |
| |
| // Move overflow control layers from its parent into the vector. |
| // Returns the number of layers moved. |
| wtf_size_t MoveOverflowControlLayersInto(GraphicsLayerVector&, |
| wtf_size_t position); |
| |
| void SetBlendMode(BlendMode); |
| |
| bool NeedsGraphicsLayerUpdate() { |
| return pending_update_scope_ > kGraphicsLayerUpdateNone; |
| } |
| void SetNeedsGraphicsLayerUpdate(GraphicsLayerUpdateScope scope) { |
| pending_update_scope_ = std::max( |
| static_cast<GraphicsLayerUpdateScope>(pending_update_scope_), scope); |
| } |
| void ClearNeedsGraphicsLayerUpdate() { |
| pending_update_scope_ = kGraphicsLayerUpdateNone; |
| } |
| |
| GraphicsLayerUpdater::UpdateType UpdateTypeForChildren( |
| GraphicsLayerUpdater::UpdateType) const; |
| |
| #if DCHECK_IS_ON() |
| void AssertNeedsToUpdateGraphicsLayerBitsCleared() { |
| DCHECK_EQ(pending_update_scope_, |
| static_cast<unsigned>(kGraphicsLayerUpdateNone)); |
| } |
| #endif |
| |
| String DebugName(const GraphicsLayer*) const override; |
| |
| const ScrollableArea* GetScrollableAreaForTesting( |
| const GraphicsLayer*) const override; |
| |
| PhysicalOffset ContentOffsetInCompositingLayer() const; |
| |
| // If there is a squashed layer painting into this CLM that is an ancestor of |
| // the given LayoutObject, return it. Otherwise return nullptr. |
| const GraphicsLayerPaintInfo* ContainingSquashedLayerInSquashingLayer( |
| const LayoutObject*, |
| unsigned max_squashed_layer_index) const; |
| |
| // Returns whether an adjustment happend. |
| bool AdjustForCompositedScrolling(const GraphicsLayer*, |
| IntSize& offset) const; |
| |
| private: |
| // Returns true for layers with scrollable overflow which have a background |
| // that can be painted into the composited scrolling contents layer (i.e. |
| // the background can scroll with the content). When the background is also |
| // opaque this allows us to composite the scroller even on low DPI as we can |
| // draw with subpixel anti-aliasing. |
| bool BackgroundPaintsOntoScrollingContentsLayer() const { |
| return GetLayoutObject().GetBackgroundPaintLocation() & |
| kBackgroundPaintInScrollingContents; |
| } |
| |
| // Returns true if the background paints onto the main graphics layer. |
| // In some situations, we may paint background on both the main graphics layer |
| // and the scrolling contents layer. |
| bool BackgroundPaintsOntoGraphicsLayer() const { |
| return GetLayoutObject().GetBackgroundPaintLocation() & |
| kBackgroundPaintInGraphicsLayer; |
| } |
| |
| IntRect RecomputeInterestRect(const GraphicsLayer*) const; |
| static bool InterestRectChangedEnoughToRepaint( |
| const IntRect& previous_interest_rect, |
| const IntRect& new_interest_rect, |
| const IntSize& layer_size); |
| |
| static const GraphicsLayerPaintInfo* ContainingSquashedLayer( |
| const LayoutObject*, |
| const Vector<GraphicsLayerPaintInfo>& layers, |
| unsigned max_squashed_layer_index); |
| |
| // Paints the scrollbar part associated with the given graphics layer into the |
| // given context. |
| void PaintScrollableArea(const GraphicsLayer*, |
| GraphicsContext&, |
| const IntRect& interest_rect) const; |
| // Returns whether the given layer is part of the scrollable area, if any, |
| // associated with this mapping. |
| bool IsScrollableAreaLayer(const GraphicsLayer*) const; |
| |
| // Returns whether the given layer is a repaint needed part of the scrollable |
| // area, if any, associated with this mapping. |
| bool IsScrollableAreaLayerWhichNeedsRepaint(const GraphicsLayer*) const; |
| |
| // Helper methods to updateGraphicsLayerGeometry: |
| void ComputeGraphicsLayerParentLocation( |
| const PaintLayer* compositing_container, |
| IntPoint& graphics_layer_parent_location); |
| void UpdateSquashingLayerGeometry( |
| const PaintLayer* compositing_container, |
| const IntPoint& snapped_offset_from_composited_ancestor, |
| Vector<GraphicsLayerPaintInfo>& layers, |
| Vector<PaintLayer*>& layers_needing_paint_invalidation); |
| void UpdateMainGraphicsLayerGeometry(const IntRect& local_compositing_bounds); |
| void UpdateMaskLayerGeometry(); |
| void UpdateForegroundLayerGeometry(); |
| void UpdateDecorationOutlineLayerGeometry( |
| const IntSize& relative_compositing_bounds_size); |
| void UpdateScrollingContentsLayerGeometry( |
| Vector<PaintLayer*>& layers_needing_paint_invalidation); |
| |
| void CreatePrimaryGraphicsLayer(); |
| |
| std::unique_ptr<GraphicsLayer> CreateGraphicsLayer( |
| CompositingReasons, |
| SquashingDisallowedReasons = SquashingDisallowedReason::kNone); |
| bool ToggleScrollbarLayerIfNeeded(std::unique_ptr<GraphicsLayer>&, |
| bool needs_layer, |
| CompositingReasons); |
| |
| LayoutBoxModelObject& GetLayoutObject() const { |
| return owning_layer_.GetLayoutObject(); |
| } |
| PaintLayerCompositor* Compositor() const { |
| return owning_layer_.Compositor(); |
| } |
| |
| void UpdateInternalHierarchy(); |
| void UpdatePaintingPhases(); |
| bool UpdateOverflowControlsLayers(bool needs_horizontal_scrollbar_layer, |
| bool needs_vertical_scrollbar_layer, |
| bool needs_scroll_corner_layer); |
| bool UpdateForegroundLayer(bool needs_foreground_layer); |
| bool UpdateDecorationOutlineLayer(bool needs_decoration_outline_layer); |
| bool UpdateMaskLayer(bool needs_mask_layer); |
| bool RequiresHorizontalScrollbarLayer() const; |
| bool RequiresVerticalScrollbarLayer() const; |
| bool RequiresScrollCornerLayer() const; |
| bool UpdateScrollingContentsLayer(bool needs_scrolling_contents_layer); |
| bool UpdateSquashingLayers(bool needs_squashing_layers); |
| void UpdateDrawsContentAndPaintsHitTest(); |
| void UpdateCompositedBounds(); |
| void UpdateGraphicsLayerContentsOpaque(bool should_check_children); |
| |
| // Also sets subpixelAccumulation on the layer. |
| void ComputeBoundsOfOwningLayer( |
| const PaintLayer* composited_ancestor, |
| IntRect& local_compositing_bounds, |
| IntPoint& snapped_offset_from_composited_ancestor); |
| |
| GraphicsLayerPaintingPhase PaintingPhaseForPrimaryLayer() const; |
| |
| bool PaintsChildren() const; |
| |
| // Returns true if this layer has content that needs to be displayed by |
| // painting into the backing store. |
| bool ContainsPaintedContent() const; |
| |
| void UpdateContentsRect(); |
| void UpdateCompositingReasons(); |
| |
| static bool HasVisibleNonCompositingDescendant(PaintLayer* parent); |
| |
| void DoPaintTask(const GraphicsLayerPaintInfo&, |
| const GraphicsLayer&, |
| PaintLayerFlags, |
| GraphicsContext&, |
| const IntRect& clip) const; |
| |
| // Computes the background clip rect for the given squashed layer, up to any |
| // containing layer that is squashed into the same squashing layer and |
| // contains this squashed layer's clipping ancestor. The clip rect is |
| // returned in the coordinate space of the given squashed layer. If there is |
| // no such containing layer, returns the infinite rect. |
| static void UpdateLocalClipRectForSquashedLayer( |
| const PaintLayer& reference_layer, |
| const Vector<GraphicsLayerPaintInfo>& layers, |
| GraphicsLayerPaintInfo&); |
| |
| bool UpdateSquashingLayerAssignmentInternal( |
| Vector<GraphicsLayerPaintInfo>& squashed_layers, |
| PaintLayer& squashed_layer, |
| wtf_size_t next_squashed_layer_index); |
| void RemoveSquashedLayers(Vector<GraphicsLayerPaintInfo>& squashed_layers); |
| |
| PaintLayer& owning_layer_; |
| |
| // The hierarchy of layers that is maintained by the CompositedLayerMapping |
| // looks like this: |
| // |
| // + graphics_layer_ |
| // + layer_for_vertical_scrollbar_ [OPTIONAL][*] |
| // + layer_for_horizontal_scrollbar_ [OPTIONAL][*] |
| // + layer_for_scroll_corner_ [OPTIONAL][*] |
| // + contents layers (or contents layers under scrolling_contents_layer_) |
| // + decoration_outline_layer_ [OPTIONAL] |
| // + mask_layer_ [ OPTIONAL ] |
| // + non_scrolling_squashing_layer_ [ OPTIONAL ] |
| // |
| // [*] Overlay overflow controls may be placed above |
| // scrolling_contents_layer_, or repositioned in the graphics layer tree |
| // to ensure that they stack above scrolling content. |
| // |
| // Contents layers are directly under |graphics_layer_|, or under |
| // |scrolling_contents_layer_| when the layer is using composited scrolling. |
| // If owning_layer_ is a stacking context, contents layers include: |
| // - negative z-index children |
| // - foreground_layer_ |
| // - normal flow and positive z-index children |
| // If owning_layer_ is not a stacking context, contents layers are normal |
| // flow children. |
| |
| std::unique_ptr<GraphicsLayer> graphics_layer_; |
| |
| // Only used if the layer is using composited scrolling. |
| std::unique_ptr<GraphicsLayer> scrolling_contents_layer_; |
| IntSize previous_scroll_container_size_; |
| |
| // Only used if we have a mask. |
| std::unique_ptr<GraphicsLayer> mask_layer_; |
| |
| // There is one other (optional) layer whose painting is managed by the |
| // CompositedLayerMapping, but whose position in the hierarchy is maintained |
| // by the PaintLayerCompositor. This is the foreground layer. The foreground |
| // layer exists if we have composited descendants with negative z-order. We |
| // need the extra layer in this case because the layer needs to draw both |
| // below (for the background, say) and above (for the normal flow content, |
| // say) the negative z-order descendants and this is impossible with a single |
| // layer. The RLC handles inserting foreground_layer_ in the correct position |
| // in our descendant list for us (right after the neg z-order dsecendants). |
| // Only used in cases where we need to draw the foreground separately. |
| std::unique_ptr<GraphicsLayer> foreground_layer_; |
| |
| std::unique_ptr<GraphicsLayer> layer_for_horizontal_scrollbar_; |
| std::unique_ptr<GraphicsLayer> layer_for_vertical_scrollbar_; |
| std::unique_ptr<GraphicsLayer> layer_for_scroll_corner_; |
| |
| // DecorationLayer which paints outline. |
| std::unique_ptr<GraphicsLayer> decoration_outline_layer_; |
| |
| // Only used when |non_scrolling_squashed_layers_| is not empty. This is |
| // the backing that |non_scrolling_squashed_layers_| paint into. |
| std::unique_ptr<GraphicsLayer> non_scrolling_squashing_layer_; |
| IntSize non_scrolling_squashing_layer_offset_from_layout_object_; |
| |
| // Layers that are squashed into |non_scrolling_squashing_layer_|. |
| Vector<GraphicsLayerPaintInfo> non_scrolling_squashed_layers_; |
| |
| // Layers that are squashed into |scrolling_contents_layer_|. This is used |
| // when |owning_layer_| is scrollable but is not a stacking context, and |
| // there are scrolling stacked children that can be squashed into the |
| // scrolling contents without breaking stacking order. We don't need a special |
| // layer like |non_scrolling_squashing_layer_| because these squashed layers |
| // are always contained by |scrolling_contents_layer_|. |
| Vector<GraphicsLayerPaintInfo> squashed_layers_in_scrolling_contents_; |
| |
| PhysicalRect composited_bounds_; |
| |
| unsigned pending_update_scope_ : 2; |
| |
| friend class CompositedLayerMappingTest; |
| }; |
| |
| } // namespace blink |
| |
| #endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_COMPOSITING_COMPOSITED_LAYER_MAPPING_H_ |