/* * 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 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. */ #pragma once #include "FloatPoint.h" #include "FloatPoint3D.h" #include "GraphicsLayer.h" #include "GraphicsLayerClient.h" #include "RenderLayer.h" #include "RenderLayerCompositor.h" #include "ScrollingCoordinator.h" namespace WebCore { class EventRegionContext; class KeyframeList; class PaintedContentsInfo; class RenderLayerCompositor; class TiledBacking; class TransformationMatrix; #if CPU(ADDRESS64) && PLATFORM(COCOA) #define USE_OWNING_LAYER_BEAR_TRAP 1 #define BEAR_TRAP_VALUE 0xEEEEEEEEEEEEEEEE #else #define USE_OWNING_LAYER_BEAR_TRAP 0 #endif enum CompositingLayerType { NormalCompositingLayer, // non-tiled layer with backing store TiledCompositingLayer, // tiled layer (always has backing store) MediaCompositingLayer, // layer that contains an image, video, WebGL or plugin ContainerCompositingLayer // layer with no backing store }; // RenderLayerBacking controls the compositing behavior for a single RenderLayer. // It holds the various GraphicsLayers, and makes decisions about intra-layer rendering // optimizations. // // There is one RenderLayerBacking for each RenderLayer that is composited. class RenderLayerBacking final : public GraphicsLayerClient { WTF_MAKE_NONCOPYABLE(RenderLayerBacking); WTF_MAKE_FAST_ALLOCATED; public: explicit RenderLayerBacking(RenderLayer&); ~RenderLayerBacking(); #if PLATFORM(IOS_FAMILY) void layerWillBeDestroyed(); #endif // Do cleanup while layer->backing() is still valid. void willBeDestroyed(); RenderLayer& owningLayer() const { return m_owningLayer; } // Included layers are non-z-order descendant layers that are painted into this backing. const Vector>& backingSharingLayers() const { return m_backingSharingLayers; } void setBackingSharingLayers(Vector>&&); bool hasBackingSharingLayers() const { return !m_backingSharingLayers.isEmpty(); } void removeBackingSharingLayer(RenderLayer&); void clearBackingSharingLayers(); void updateConfigurationAfterStyleChange(); // Returns true if layer configuration changed. bool updateConfiguration(const RenderLayer* compositingAncestor); // Update graphics layer position and bounds. void updateGeometry(const RenderLayer* compositingAncestor); // Update state the requires that descendant layers have been updated. void updateAfterDescendants(); // Update contents and clipping structure. void updateDrawsContent(); void updateAfterLayout(bool needsClippingUpdate, bool needsFullRepaint); GraphicsLayer* graphicsLayer() const { return m_graphicsLayer.get(); } // Layer to clip children bool hasClippingLayer() const { return (m_childContainmentLayer && !m_isFrameLayerWithTiledBacking); } GraphicsLayer* clippingLayer() const { return !m_isFrameLayerWithTiledBacking ? m_childContainmentLayer.get() : nullptr; } bool hasAncestorClippingLayers() const { return !!m_ancestorClippingStack; } LayerAncestorClippingStack* ancestorClippingStack() const { return m_ancestorClippingStack.get(); } bool updateAncestorClippingStack(Vector&&); void ensureOverflowControlsHostLayerAncestorClippingStack(const RenderLayer* compositedAncestor); LayerAncestorClippingStack* overflowControlsHostLayerAncestorClippingStack() const { return m_overflowControlsHostLayerAncestorClippingStack.get(); } GraphicsLayer* contentsContainmentLayer() const { return m_contentsContainmentLayer.get(); } GraphicsLayer* foregroundLayer() const { return m_foregroundLayer.get(); } GraphicsLayer* backgroundLayer() const { return m_backgroundLayer.get(); } bool backgroundLayerPaintsFixedRootBackground() const { return m_backgroundLayerPaintsFixedRootBackground; } bool needsRepaintOnCompositedScroll() const; bool requiresBackgroundLayer() const { return m_requiresBackgroundLayer; } void setRequiresBackgroundLayer(bool); bool hasScrollingLayer() const { return m_scrollContainerLayer != nullptr; } GraphicsLayer* scrollContainerLayer() const { return m_scrollContainerLayer.get(); } GraphicsLayer* scrolledContentsLayer() const { return m_scrolledContentsLayer.get(); } void detachFromScrollingCoordinator(OptionSet); ScrollingNodeID scrollingNodeIDForRole(ScrollCoordinationRole role) const { switch (role) { case ScrollCoordinationRole::Scrolling: return m_scrollingNodeID; case ScrollCoordinationRole::ScrollingProxy: // These nodeIDs are stored in m_ancestorClippingStack. ASSERT_NOT_REACHED(); return 0; case ScrollCoordinationRole::FrameHosting: return m_frameHostingNodeID; case ScrollCoordinationRole::ViewportConstrained: return m_viewportConstrainedNodeID; case ScrollCoordinationRole::Positioning: return m_positioningNodeID; } return 0; } void setScrollingNodeIDForRole(ScrollingNodeID, ScrollCoordinationRole); ScrollingNodeID scrollingNodeIDForChildren() const; bool hasMaskLayer() const { return m_maskLayer; } bool hasChildClippingMaskLayer() const { return m_childClippingMaskLayer != nullptr; } GraphicsLayer* parentForSublayers() const; GraphicsLayer* childForSuperlayers() const; // RenderLayers with backing normally short-circuit paintLayer() because // their content is rendered via callbacks from GraphicsLayer. However, the document // layer is special, because it has a GraphicsLayer to act as a container for the GraphicsLayers // for descendants, but its contents usually render into the window (in which case this returns true). // This returns false for other layers, and when the document layer actually needs to paint into its backing store // for some reason. bool paintsIntoWindow() const; // Returns true for a composited layer that has no backing store of its own, so // paints into some ancestor layer. bool paintsIntoCompositedAncestor() const { return !m_requiresOwnBackingStore; } void setRequiresOwnBackingStore(bool); void setContentsNeedDisplay(GraphicsLayer::ShouldClipToLayer = GraphicsLayer::ClipToLayer); // r is in the coordinate space of the layer's render object void setContentsNeedDisplayInRect(const LayoutRect&, GraphicsLayer::ShouldClipToLayer = GraphicsLayer::ClipToLayer); // Notification from the renderer that its content changed. void contentChanged(ContentChangeType); // Interface to start, finish, suspend and resume animations bool startAnimation(double timeOffset, const Animation&, const KeyframeList&); void animationPaused(double timeOffset, const String& name); void animationFinished(const String& name); void transformRelatedPropertyDidChange(); void suspendAnimations(MonotonicTime = MonotonicTime()); void resumeAnimations(); LayoutRect compositedBounds() const; // Returns true if changed. bool setCompositedBounds(const LayoutRect&); // Returns true if changed. bool updateCompositedBounds(); void updateAllowsBackingStoreDetaching(const LayoutRect& absoluteBounds); #if ENABLE(ASYNC_SCROLLING) bool maintainsEventRegion() const; void updateEventRegion(); bool needsEventRegionUpdate() const { return m_needsEventRegionUpdate; } void setNeedsEventRegionUpdate(bool needsUpdate = true) { m_needsEventRegionUpdate = needsUpdate; } #endif void updateAfterWidgetResize(); void positionOverflowControlsLayers(); bool isFrameLayerWithTiledBacking() const { return m_isFrameLayerWithTiledBacking; } WEBCORE_EXPORT TiledBacking* tiledBacking() const; void adjustTiledBackingCoverage(); void setTiledBackingHasMargins(bool hasExtendedBackgroundOnLeftAndRight, bool hasExtendedBackgroundOnTopAndBottom); void updateDebugIndicators(bool showBorder, bool showRepaintCounter); bool paintsSubpixelAntialiasedText() const { return m_paintsSubpixelAntialiasedText; } // GraphicsLayerClient interface void tiledBackingUsageChanged(const GraphicsLayer*, bool /*usingTiledBacking*/) override; void notifyAnimationStarted(const GraphicsLayer*, const String& animationKey, MonotonicTime startTime) override; void notifyFlushRequired(const GraphicsLayer*) override; void notifyFlushBeforeDisplayRefresh(const GraphicsLayer*) override; void paintContents(const GraphicsLayer*, GraphicsContext&, const FloatRect& clip, GraphicsLayerPaintBehavior) override; float deviceScaleFactor() const override; float contentsScaleMultiplierForNewTiles(const GraphicsLayer*) const override; bool paintsOpaquelyAtNonIntegralScales(const GraphicsLayer*) const override; float pageScaleFactor() const override; float zoomedOutPageScaleFactor() const override; void didChangePlatformLayerForLayer(const GraphicsLayer*) override; bool getCurrentTransform(const GraphicsLayer*, TransformationMatrix&) const override; bool isTrackingRepaints() const override; bool shouldSkipLayerInDump(const GraphicsLayer*, OptionSet) const override; bool shouldDumpPropertyForLayer(const GraphicsLayer*, const char* propertyName, OptionSet) const override; bool shouldAggressivelyRetainTiles(const GraphicsLayer*) const override; bool shouldTemporarilyRetainTileCohorts(const GraphicsLayer*) const override; bool useGiantTiles() const override; void logFilledVisibleFreshTile(unsigned) override; bool needsPixelAligment() const override { return !m_isMainFrameRenderViewLayer; } LayoutSize subpixelOffsetFromRenderer() const { return m_subpixelOffsetFromRenderer; } TransformationMatrix transformMatrixForProperty(AnimatedPropertyID) const final; #if PLATFORM(IOS_FAMILY) bool needsIOSDumpRenderTreeMainFrameRenderViewLayerIsAlwaysOpaqueHack(const GraphicsLayer&) const override; #endif #ifndef NDEBUG void verifyNotPainting() override; #endif WEBCORE_EXPORT LayoutRect contentsBox() const; // For informative purposes only. WEBCORE_EXPORT CompositingLayerType compositingLayerType() const; GraphicsLayer* layerForHorizontalScrollbar() const { return m_layerForHorizontalScrollbar.get(); } GraphicsLayer* layerForVerticalScrollbar() const { return m_layerForVerticalScrollbar.get(); } GraphicsLayer* layerForScrollCorner() const { return m_layerForScrollCorner.get(); } GraphicsLayer* overflowControlsContainer() const { return m_overflowControlsContainer.get(); } void adjustOverflowControlsPositionRelativeToAncestor(const RenderLayer&); bool canCompositeFilters() const { return m_canCompositeFilters; } #if ENABLE(FILTERS_LEVEL_2) bool canCompositeBackdropFilters() const { return m_canCompositeBackdropFilters; } #endif // Return an estimate of the backing store area (in pixels) allocated by this object's GraphicsLayers. WEBCORE_EXPORT double backingStoreMemoryEstimate() const; // For testing only. WEBCORE_EXPORT void setUsesDisplayListDrawing(bool); WEBCORE_EXPORT String displayListAsText(DisplayList::AsTextFlags) const; WEBCORE_EXPORT void setIsTrackingDisplayListReplay(bool); WEBCORE_EXPORT String replayDisplayListAsText(DisplayList::AsTextFlags) const; private: friend class PaintedContentsInfo; FloatRect backgroundBoxForSimpleContainerPainting() const; void createPrimaryGraphicsLayer(); void destroyGraphicsLayers(); void willDestroyLayer(const GraphicsLayer*); LayoutRect compositedBoundsIncludingMargin() const; Ref createGraphicsLayer(const String&, GraphicsLayer::Type = GraphicsLayer::Type::Normal); RenderLayerModelObject& renderer() const { return m_owningLayer.renderer(); } RenderBox* renderBox() const { return m_owningLayer.renderBox(); } RenderLayerCompositor& compositor() const { return m_owningLayer.compositor(); } void updateInternalHierarchy(); bool updateAncestorClipping(bool needsAncestorClip, const RenderLayer* compositingAncestor); bool updateDescendantClippingLayer(bool needsDescendantClip); bool updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer); bool updateForegroundLayer(bool needsForegroundLayer); bool updateBackgroundLayer(bool needsBackgroundLayer); bool updateMaskingLayer(bool hasMask, bool hasClipPath); bool requiresLayerForScrollbar(Scrollbar*) const; bool requiresHorizontalScrollbarLayer() const; bool requiresVerticalScrollbarLayer() const; bool requiresScrollCornerLayer() const; bool updateScrollingLayers(bool scrollingLayers); void updateScrollOffset(ScrollOffset); void setLocationOfScrolledContents(ScrollOffset, ScrollingLayerPositionAction); void updateChildClippingStrategy(bool needsDescendantsClippingLayer); void updateMaskingLayerGeometry(); void updateRootLayerConfiguration(); void updatePaintingPhases(); void setBackgroundLayerPaintsFixedRootBackground(bool); LayoutSize contentOffsetInCompositingLayer() const; // Result is transform origin in device pixels. FloatPoint3D computeTransformOriginForPainting(const LayoutRect& borderBox) const; LayoutSize offsetRelativeToRendererOriginForDescendantLayers() const; void ensureClippingStackLayers(LayerAncestorClippingStack&); void removeClippingStackLayers(LayerAncestorClippingStack&); void updateClippingStackLayerGeometry(LayerAncestorClippingStack&, const RenderLayer* compositedAncestor, LayoutRect& parentGraphicsLayerRect); void connectClippingStackLayers(LayerAncestorClippingStack&); void updateOpacity(const RenderStyle&); void updateTransform(const RenderStyle&); void updateChildrenTransformAndAnchorPoint(const LayoutRect& primaryGraphicsLayerRect, LayoutSize offsetFromParentGraphicsLayer); void updateFilters(const RenderStyle&); #if ENABLE(FILTERS_LEVEL_2) void updateBackdropFilters(const RenderStyle&); void updateBackdropFiltersGeometry(); #endif #if ENABLE(CSS_COMPOSITING) void updateBlendMode(const RenderStyle&); #endif void updateCustomAppearance(const RenderStyle&); // Return the opacity value that this layer should use for compositing. float compositingOpacity(float rendererOpacity) const; Color rendererBackgroundColor() const; bool isMainFrameRenderViewLayer() const; bool paintsBoxDecorations() const; bool paintsContent(RenderLayer::PaintedContentRequest&) const; void updateDrawsContent(PaintedContentsInfo&); // Returns true if this compositing layer has no visible content. bool isSimpleContainerCompositingLayer(PaintedContentsInfo&) const; // Returns true if this layer has content that needs to be rendered by painting into the backing store. bool containsPaintedContent(PaintedContentsInfo&) const; // Returns true if the RenderLayer just contains an image that we can composite directly. bool isDirectlyCompositedImage() const; void updateImageContents(PaintedContentsInfo&); void updateDirectlyCompositedBoxDecorations(PaintedContentsInfo&, bool& didUpdateContentsRect); void updateDirectlyCompositedBackgroundColor(PaintedContentsInfo&, bool& didUpdateContentsRect); void updateDirectlyCompositedBackgroundImage(PaintedContentsInfo&, bool& didUpdateContentsRect); void resetContentsRect(); void updateContentsRects(); bool isPaintDestinationForDescendantLayers(RenderLayer::PaintedContentRequest&) const; bool hasVisibleNonCompositedDescendants() const; bool shouldClipCompositedBounds() const; bool hasTiledBackingFlatteningLayer() const { return (m_childContainmentLayer && m_isFrameLayerWithTiledBacking); } GraphicsLayer* tileCacheFlatteningLayer() const { return m_isFrameLayerWithTiledBacking ? m_childContainmentLayer.get() : nullptr; } void paintIntoLayer(const GraphicsLayer*, GraphicsContext&, const IntRect& paintDirtyRect, OptionSet, EventRegionContext* = nullptr); OptionSet paintFlagsForLayer(const GraphicsLayer&) const; void paintDebugOverlays(const GraphicsLayer*, GraphicsContext&); static CSSPropertyID graphicsLayerToCSSProperty(AnimatedPropertyID); static AnimatedPropertyID cssToGraphicsLayerProperty(CSSPropertyID); bool canIssueSetNeedsDisplay() const { return !paintsIntoWindow() && !paintsIntoCompositedAncestor(); } LayoutRect computeParentGraphicsLayerRect(const RenderLayer* compositedAncestor) const; LayoutRect computePrimaryGraphicsLayerRect(const RenderLayer* compositedAncestor, const LayoutRect& parentGraphicsLayerRect) const; #if USE(OWNING_LAYER_BEAR_TRAP) uintptr_t m_owningLayerBearTrap { BEAR_TRAP_VALUE }; // webkit.org/b.206915 #endif RenderLayer& m_owningLayer; // A list other layers that paint into this backing store, later than m_owningLayer in paint order. Vector> m_backingSharingLayers; std::unique_ptr m_ancestorClippingStack; // Only used if we are clipped by an ancestor which is not a stacking context. std::unique_ptr m_overflowControlsHostLayerAncestorClippingStack; // Used when we have an overflow controls host layer which was reparented, and needs clipping by ancestors. RefPtr m_contentsContainmentLayer; // Only used if we have a background layer; takes the transform. RefPtr m_graphicsLayer; RefPtr m_foregroundLayer; // Only used in cases where we need to draw the foreground separately. RefPtr m_backgroundLayer; // Only used in cases where we need to draw the background separately. RefPtr m_childContainmentLayer; // Only used if we have clipping on a stacking context with compositing children, or if the layer has a tile cache. RefPtr m_maskLayer; // Only used if we have a mask and/or clip-path. RefPtr m_childClippingMaskLayer; // Only used if we have to clip child layers or accelerated contents with border radius or clip-path. RefPtr m_layerForHorizontalScrollbar; RefPtr m_layerForVerticalScrollbar; RefPtr m_layerForScrollCorner; RefPtr m_overflowControlsContainer; RefPtr m_scrollContainerLayer; // Only used if the layer is using composited scrolling. RefPtr m_scrolledContentsLayer; // Only used if the layer is using composited scrolling. LayoutRect m_compositedBounds; LayoutSize m_subpixelOffsetFromRenderer; // This is the subpixel distance between the primary graphics layer and the associated renderer's bounds. LayoutSize m_compositedBoundsOffsetFromGraphicsLayer; // This is the subpixel distance between the primary graphics layer and the render layer bounds. ScrollingNodeID m_viewportConstrainedNodeID { 0 }; ScrollingNodeID m_scrollingNodeID { 0 }; ScrollingNodeID m_frameHostingNodeID { 0 }; ScrollingNodeID m_positioningNodeID { 0 }; bool m_artificiallyInflatedBounds { false }; // bounds had to be made non-zero to make transform-origin work bool m_isMainFrameRenderViewLayer { false }; bool m_isFrameLayerWithTiledBacking { false }; bool m_requiresOwnBackingStore { true }; bool m_canCompositeFilters { false }; #if ENABLE(FILTERS_LEVEL_2) bool m_canCompositeBackdropFilters { false }; #endif bool m_backgroundLayerPaintsFixedRootBackground { false }; bool m_requiresBackgroundLayer { false }; bool m_hasSubpixelRounding { false }; bool m_paintsSubpixelAntialiasedText { false }; // This is for logging only. #if ENABLE(ASYNC_SCROLLING) bool m_needsEventRegionUpdate { true }; #endif }; enum CanvasCompositingStrategy { UnacceleratedCanvas, CanvasPaintedToLayer, CanvasAsLayerContents }; CanvasCompositingStrategy canvasCompositingStrategy(const RenderObject&); WTF::TextStream& operator<<(WTF::TextStream&, const RenderLayerBacking&); } // namespace WebCore