RenderLayerCompositor.h [plain text]
#pragma once
#include "ChromeClient.h"
#include "GraphicsLayerClient.h"
#include "GraphicsLayerUpdater.h"
#include "RenderLayer.h"
#include <wtf/HashMap.h>
#include <wtf/OptionSet.h>
namespace WebCore {
class FixedPositionViewportConstraints;
class GraphicsLayer;
class GraphicsLayerUpdater;
class RenderEmbeddedObject;
class RenderVideo;
class RenderWidget;
class ScrollingCoordinator;
class StickyPositionViewportConstraints;
class TiledBacking;
typedef unsigned LayerTreeFlags;
enum class CompositingUpdateType {
AfterStyleChange,
AfterLayout,
OnScroll,
OnCompositedScroll
};
enum class CompositingReason {
Transform3D = 1 << 0,
Video = 1 << 1,
Canvas = 1 << 2,
Plugin = 1 << 3,
IFrame = 1 << 4,
BackfaceVisibilityHidden = 1 << 5,
ClipsCompositingDescendants = 1 << 6,
Animation = 1 << 7,
Filters = 1 << 8,
PositionFixed = 1 << 9,
PositionSticky = 1 << 10,
OverflowScrollingTouch = 1 << 11,
Stacking = 1 << 12,
Overlap = 1 << 13,
NegativeZIndexChildren = 1 << 14,
TransformWithCompositedDescendants = 1 << 15,
OpacityWithCompositedDescendants = 1 << 16,
MaskWithCompositedDescendants = 1 << 17,
ReflectionWithCompositedDescendants = 1 << 18,
FilterWithCompositedDescendants = 1 << 19,
BlendingWithCompositedDescendants = 1 << 20,
Perspective = 1 << 21,
Preserve3D = 1 << 22,
WillChange = 1 << 23,
Root = 1 << 24,
IsolatesCompositedBlendingDescendants = 1 << 25,
EmbeddedView = 1 << 26,
};
enum class ScrollCoordinationRole {
ViewportConstrained = 1 << 0,
Scrolling = 1 << 1
};
#if PLATFORM(IOS_FAMILY)
class LegacyWebKitScrollingLayerCoordinator {
public:
LegacyWebKitScrollingLayerCoordinator(ChromeClient& chromeClient, bool coordinateViewportConstainedLayers)
: m_chromeClient(chromeClient)
, m_coordinateViewportConstainedLayers(coordinateViewportConstainedLayers)
{
}
void registerAllViewportConstrainedLayers(RenderLayerCompositor&, const HashSet<RenderLayer*>&);
void unregisterAllViewportConstrainedLayers();
void registerAllScrollingLayers();
void registerScrollingLayersNeedingUpdate();
void unregisterAllScrollingLayers();
void addScrollingLayer(RenderLayer&);
void removeScrollingLayer(RenderLayer&, RenderLayerBacking&);
void didFlushChangesForLayer(RenderLayer&);
private:
void updateScrollingLayer(RenderLayer&);
ChromeClient& m_chromeClient;
HashSet<RenderLayer*> m_scrollingLayers;
HashSet<RenderLayer*> m_scrollingLayersNeedingUpdate;
const bool m_coordinateViewportConstainedLayers;
};
#endif
class RenderLayerCompositor final : public GraphicsLayerClient, public GraphicsLayerUpdaterClient {
WTF_MAKE_FAST_ALLOCATED;
friend class LegacyWebKitScrollingLayerCoordinator;
public:
explicit RenderLayerCompositor(RenderView&);
virtual ~RenderLayerCompositor();
bool usesCompositing() const { return m_compositing; }
void enableCompositingMode(bool enable = true);
bool inForcedCompositingMode() const { return m_forceCompositingMode; }
bool hasContentCompositingLayers() const { return m_contentLayersCount; }
bool hasAcceleratedCompositing() const { return m_hasAcceleratedCompositing; }
bool canRender3DTransforms() const;
void willRecalcStyle();
bool didRecalcStyleWithNoPendingLayout();
void scheduleLayerFlush(bool canThrottle);
void flushPendingLayerChanges(bool isFlushRoot = true);
void didFlushChangesForLayer(RenderLayer&, const GraphicsLayer*);
void didChangeVisibleRect();
bool updateCompositingLayers(CompositingUpdateType, RenderLayer* updateRoot = nullptr);
void scheduleCompositingLayerUpdate();
void cancelCompositingLayerUpdate();
enum CompositingChangeRepaint { CompositingChangeRepaintNow, CompositingChangeWillRepaintLater };
enum class LayoutUpToDate {
Yes, No
};
struct RequiresCompositingData {
LayoutUpToDate layoutUpToDate { LayoutUpToDate::Yes };
RenderLayer::ViewportConstrainedNotCompositedReason nonCompositedForPositionReason { RenderLayer::NoNotCompositedReason };
bool reevaluateAfterLayout { false };
};
bool updateLayerCompositingState(RenderLayer&, RequiresCompositingData&, CompositingChangeRepaint = CompositingChangeRepaintNow);
bool clippedByAncestor(RenderLayer&) const;
bool clipsCompositingDescendants(const RenderLayer&) const;
bool needsContentsCompositingLayer(const RenderLayer&) const;
bool fixedLayerIntersectsViewport(const RenderLayer&) const;
bool supportsFixedRootBackgroundCompositing() const;
bool needsFixedRootBackgroundLayer(const RenderLayer&) const;
GraphicsLayer* fixedRootBackgroundLayer() const;
void rootOrBodyStyleChanged(RenderElement&, const RenderStyle* oldStyle);
void rootBackgroundColorOrTransparencyChanged();
void repaintOnCompositingChange(RenderLayer&);
void repaintInCompositedAncestor(RenderLayer&, const LayoutRect&);
void layerWasAdded(RenderLayer& parent, RenderLayer& child);
void layerWillBeRemoved(RenderLayer& parent, RenderLayer& child);
void layerStyleChanged(StyleDifference, RenderLayer&, const RenderStyle* oldStyle);
static bool canCompositeClipPath(const RenderLayer&);
RenderLayer* enclosingNonStackingClippingLayer(const RenderLayer&) const;
void repaintCompositedLayers();
bool requiresOwnBackingStore(const RenderLayer&, const RenderLayer* compositingAncestorLayer, const LayoutRect& layerCompositedBoundsInAncestor, const LayoutRect& ancestorCompositedBounds) const;
WEBCORE_EXPORT RenderLayer& rootRenderLayer() const;
GraphicsLayer* rootGraphicsLayer() const;
GraphicsLayer* scrollLayer() const { return m_scrollLayer.get(); }
GraphicsLayer* clipLayer() const { return m_clipLayer.get(); }
GraphicsLayer* rootContentLayer() const { return m_rootContentLayer.get(); }
#if ENABLE(RUBBER_BANDING)
GraphicsLayer* headerLayer() const { return m_layerForHeader.get(); }
GraphicsLayer* footerLayer() const { return m_layerForFooter.get(); }
#endif
enum RootLayerAttachment {
RootLayerUnattached,
RootLayerAttachedViaChromeClient,
RootLayerAttachedViaEnclosingFrame
};
RootLayerAttachment rootLayerAttachment() const { return m_rootLayerAttachment; }
void updateRootLayerAttachment();
void updateRootLayerPosition();
void setIsInWindow(bool);
void clearBackingForAllLayers();
void layerBecameComposited(const RenderLayer&);
void layerBecameNonComposited(const RenderLayer&);
#if ENABLE(VIDEO)
bool canAccelerateVideoRendering(RenderVideo&) const;
#endif
bool has3DContent() const;
static RenderLayerCompositor* frameContentsCompositor(RenderWidget*);
static bool parentFrameContentLayers(RenderWidget*);
void frameViewDidChangeLocation(const IntPoint& contentsOffset);
void frameViewDidChangeSize();
void frameViewDidScroll();
void frameViewDidAddOrRemoveScrollbars();
void frameViewDidLayout();
void rootLayerConfigurationChanged();
void scrollingLayerDidChange(RenderLayer&);
void fixedRootBackgroundLayerChanged();
String layerTreeAsText(LayerTreeFlags);
float deviceScaleFactor() const override;
float contentsScaleMultiplierForNewTiles(const GraphicsLayer*) const override;
float pageScaleFactor() const override;
float zoomedOutPageScaleFactor() const override;
void didCommitChangesForLayer(const GraphicsLayer*) const override;
void notifyFlushBeforeDisplayRefresh(const GraphicsLayer*) override;
void layerTiledBackingUsageChanged(const GraphicsLayer*, bool );
bool acceleratedDrawingEnabled() const { return m_acceleratedDrawingEnabled; }
bool displayListDrawingEnabled() const { return m_displayListDrawingEnabled; }
void deviceOrPageScaleFactorChanged();
void windowScreenDidChange(PlatformDisplayID);
GraphicsLayer* layerForHorizontalScrollbar() const { return m_layerForHorizontalScrollbar.get(); }
GraphicsLayer* layerForVerticalScrollbar() const { return m_layerForVerticalScrollbar.get(); }
GraphicsLayer* layerForScrollCorner() const { return m_layerForScrollCorner.get(); }
#if ENABLE(RUBBER_BANDING)
GraphicsLayer* layerForOverhangAreas() const { return m_layerForOverhangAreas.get(); }
GraphicsLayer* layerForContentShadow() const { return m_contentShadowLayer.get(); }
GraphicsLayer* updateLayerForTopOverhangArea(bool wantsLayer);
GraphicsLayer* updateLayerForBottomOverhangArea(bool wantsLayer);
GraphicsLayer* updateLayerForHeader(bool wantsLayer);
GraphicsLayer* updateLayerForFooter(bool wantsLayer);
#endif
ScrollableArea* scrollableAreaForScrollLayerID(ScrollingNodeID) const;
enum class ScrollingNodeChangeFlags {
Layer = 1 << 0,
LayerGeometry = 1 << 1,
};
void updateScrollCoordinatedStatus(RenderLayer&, OptionSet<ScrollingNodeChangeFlags>);
void removeFromScrollCoordinatedLayers(RenderLayer&);
void willRemoveScrollingLayerWithBacking(RenderLayer&, RenderLayerBacking&);
void didAddScrollingLayer(RenderLayer&);
void resetTrackedRepaintRects();
void setTracksRepaints(bool tracksRepaints) { m_isTrackingRepaints = tracksRepaints; }
bool viewHasTransparentBackground(Color* backgroundColor = nullptr) const;
bool hasNonMainLayersWithTiledBacking() const { return m_layersWithTiledBackingCount; }
OptionSet<CompositingReason> reasonsForCompositing(const RenderLayer&) const;
void setLayerFlushThrottlingEnabled(bool);
void disableLayerFlushThrottlingTemporarilyForInteraction();
void didPaintBacking(RenderLayerBacking*);
const Color& rootExtendedBackgroundColor() const { return m_rootExtendedBackgroundColor; }
void updateRootContentLayerClipping();
#if ENABLE(CSS_SCROLL_SNAP)
void updateScrollSnapPropertiesWithFrameView(const FrameView&);
#endif
void startTrackingLayerFlushes() { m_layerFlushCount = 0; }
unsigned layerFlushCount() const { return m_layerFlushCount; }
void startTrackingCompositingUpdates() { m_compositingUpdateCount = 0; }
unsigned compositingUpdateCount() const { return m_compositingUpdateCount; }
private:
class OverlapMap;
struct CompositingState;
struct OverlapExtent;
bool updateCompositingPolicy();
void notifyFlushRequired(const GraphicsLayer*) override;
void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const FloatRect&, GraphicsLayerPaintBehavior) override;
void customPositionForVisibleRectComputation(const GraphicsLayer*, FloatPoint&) const override;
bool isTrackingRepaints() const override { return m_isTrackingRepaints; }
void flushLayersSoon(GraphicsLayerUpdater&) override;
void cacheAcceleratedCompositingFlags();
void cacheAcceleratedCompositingFlagsAfterLayout();
bool needsToBeComposited(const RenderLayer&, RequiresCompositingData&) const;
bool requiresCompositingLayer(const RenderLayer&, RequiresCompositingData&) const;
bool canBeComposited(const RenderLayer&) const;
bool needsCompositingUpdateForStyleChangeOnNonCompositedLayer(RenderLayer&, const RenderStyle* oldStyle) const;
enum class BackingRequired { No, Yes, Unknown };
bool updateBacking(RenderLayer&, RequiresCompositingData&, CompositingChangeRepaint shouldRepaint, BackingRequired = BackingRequired::Unknown);
void clearBackingForLayerIncludingDescendants(RenderLayer&);
void recursiveRepaintLayer(RenderLayer&);
void computeExtent(const OverlapMap&, const RenderLayer&, OverlapExtent&) const;
void addToOverlapMap(OverlapMap&, const RenderLayer&, OverlapExtent&);
void addToOverlapMapRecursive(OverlapMap&, const RenderLayer&, const RenderLayer* ancestorLayer = nullptr);
void updateCompositingLayersTimerFired();
void computeCompositingRequirements(RenderLayer* ancestorLayer, RenderLayer&, OverlapMap&, CompositingState&, bool& descendantHas3DTransform);
void traverseUnchangedSubtree(RenderLayer* ancestorLayer, RenderLayer&, OverlapMap&, CompositingState&, bool& descendantHas3DTransform);
enum class UpdateLevel {
AllDescendants = 1 << 0,
CompositedChildren = 1 << 1,
};
void updateBackingAndHierarchy(RenderLayer&, Vector<Ref<GraphicsLayer>>& childGraphicsLayersOfEnclosingLayer, OptionSet<UpdateLevel> = { }, int depth = 0);
void setCompositingParent(RenderLayer& childLayer, RenderLayer* parentLayer);
void removeCompositedChildren(RenderLayer&);
bool layerHas3DContent(const RenderLayer&) const;
bool isRunningTransformAnimation(RenderLayerModelObject&) const;
void appendDocumentOverlayLayers(Vector<Ref<GraphicsLayer>>&);
bool needsCompositingForContentOrOverlays() const;
void ensureRootLayer();
void destroyRootLayer();
void attachRootLayer(RootLayerAttachment);
void detachRootLayer();
void rootLayerAttachmentChanged();
void updateOverflowControlsLayers();
void updateScrollLayerPosition();
FloatPoint positionForClipLayer() const;
void notifyIFramesOfCompositingChange();
void updateScrollCoordinatedLayersAfterFlushIncludingSubframes();
void updateScrollCoordinatedLayersAfterFlush();
FloatRect visibleRectForLayerFlushing() const;
Page& page() const;
GraphicsLayerFactory* graphicsLayerFactory() const;
ScrollingCoordinator* scrollingCoordinator() const;
#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
RefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const override;
#endif
bool requiresCompositingForAnimation(RenderLayerModelObject&) const;
bool requiresCompositingForTransform(RenderLayerModelObject&) const;
bool requiresCompositingForBackfaceVisibility(RenderLayerModelObject&) const;
bool requiresCompositingForVideo(RenderLayerModelObject&) const;
bool requiresCompositingForCanvas(RenderLayerModelObject&) const;
bool requiresCompositingForFilters(RenderLayerModelObject&) const;
bool requiresCompositingForWillChange(RenderLayerModelObject&) const;
bool requiresCompositingForPlugin(RenderLayerModelObject&, RequiresCompositingData&) const;
bool requiresCompositingForFrame(RenderLayerModelObject&, RequiresCompositingData&) const;
bool requiresCompositingForScrollableFrame(RequiresCompositingData&) const;
bool requiresCompositingForPosition(RenderLayerModelObject&, const RenderLayer&, RequiresCompositingData&) const;
bool requiresCompositingForOverflowScrolling(const RenderLayer&, RequiresCompositingData&) const;
bool requiresCompositingForEditableImage(RenderLayerModelObject&) const;
bool requiresCompositingForIndirectReason(RenderLayerModelObject&, bool hasCompositedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason&) const;
static bool styleChangeMayAffectIndirectCompositingReasons(const RenderStyle& oldStyle, const RenderStyle& newStyle);
void updateCustomLayersAfterFlush();
void updateScrollCoordinationForThisFrame(ScrollingNodeID);
ScrollingNodeID attachScrollingNode(RenderLayer&, ScrollingNodeType, ScrollingNodeID parentNodeID);
void updateScrollCoordinatedLayer(RenderLayer&, OptionSet<ScrollCoordinationRole>, OptionSet<ScrollingNodeChangeFlags>);
void detachScrollCoordinatedLayer(RenderLayer&, OptionSet<ScrollCoordinationRole>);
void reattachSubframeScrollLayers();
FixedPositionViewportConstraints computeFixedViewportConstraints(RenderLayer&) const;
StickyPositionViewportConstraints computeStickyViewportConstraints(RenderLayer&) const;
bool requiresScrollLayer(RootLayerAttachment) const;
bool requiresHorizontalScrollbarLayer() const;
bool requiresVerticalScrollbarLayer() const;
bool requiresScrollCornerLayer() const;
#if ENABLE(RUBBER_BANDING)
bool requiresOverhangAreasLayer() const;
bool requiresContentShadowLayer() const;
#endif
bool hasCoordinatedScrolling() const;
bool useCoordinatedScrollingForLayer(const RenderLayer&) const;
bool isAsyncScrollableStickyLayer(const RenderLayer&, const RenderLayer** enclosingAcceleratedOverflowLayer = nullptr) const;
bool isViewportConstrainedFixedOrStickyLayer(const RenderLayer&) const;
bool shouldCompositeOverflowControls() const;
void scheduleLayerFlushNow();
bool isThrottlingLayerFlushes() const;
void startInitialLayerFlushTimerIfNeeded();
void startLayerFlushTimerIfNeeded();
void layerFlushTimerFired();
#if !LOG_DISABLED
const char* logReasonsForCompositing(const RenderLayer&);
void logLayerInfo(const RenderLayer&, const char*, int depth);
#endif
bool documentUsesTiledBacking() const;
bool isMainFrameCompositor() const;
private:
RenderView& m_renderView;
RefPtr<GraphicsLayer> m_rootContentLayer;
Timer m_updateCompositingLayersTimer;
ChromeClient::CompositingTriggerFlags m_compositingTriggers { static_cast<ChromeClient::CompositingTriggerFlags>(ChromeClient::AllTriggers) };
bool m_hasAcceleratedCompositing { true };
CompositingPolicy m_compositingPolicy { CompositingPolicy::Normal };
bool m_showDebugBorders { false };
bool m_showRepaintCounter { false };
bool m_acceleratedDrawingEnabled { false };
bool m_displayListDrawingEnabled { false };
bool m_compositing { false };
bool m_flushingLayers { false };
bool m_shouldFlushOnReattach { false };
bool m_forceCompositingMode { false };
bool m_inPostLayoutUpdate { false }; bool m_subframeScrollLayersNeedReattach { false };
bool m_isTrackingRepaints { false };
unsigned m_contentLayersCount { 0 };
unsigned m_layersWithTiledBackingCount { 0 };
unsigned m_layerFlushCount { 0 };
unsigned m_compositingUpdateCount { 0 };
RootLayerAttachment m_rootLayerAttachment { RootLayerUnattached };
RefPtr<GraphicsLayer> m_clipLayer;
RefPtr<GraphicsLayer> m_scrollLayer;
HashSet<RenderLayer*> m_scrollCoordinatedLayers;
HashSet<RenderLayer*> m_scrollCoordinatedLayersNeedingUpdate;
RefPtr<GraphicsLayer> m_overflowControlsHostLayer;
RefPtr<GraphicsLayer> m_layerForHorizontalScrollbar;
RefPtr<GraphicsLayer> m_layerForVerticalScrollbar;
RefPtr<GraphicsLayer> m_layerForScrollCorner;
#if ENABLE(RUBBER_BANDING)
RefPtr<GraphicsLayer> m_layerForOverhangAreas;
RefPtr<GraphicsLayer> m_contentShadowLayer;
RefPtr<GraphicsLayer> m_layerForTopOverhangArea;
RefPtr<GraphicsLayer> m_layerForBottomOverhangArea;
RefPtr<GraphicsLayer> m_layerForHeader;
RefPtr<GraphicsLayer> m_layerForFooter;
#endif
std::unique_ptr<GraphicsLayerUpdater> m_layerUpdater;
Timer m_layerFlushTimer;
bool m_layerFlushThrottlingEnabled { false };
bool m_layerFlushThrottlingTemporarilyDisabledForInteraction { false };
bool m_hasPendingLayerFlush { false };
bool m_viewBackgroundIsTransparent { false };
#if !LOG_DISABLED
int m_rootLayerUpdateCount { 0 };
int m_obligateCompositedLayerCount { 0 }; int m_secondaryCompositedLayerCount { 0 }; double m_obligatoryBackingStoreBytes { 0 };
double m_secondaryBackingStoreBytes { 0 };
#endif
Color m_viewBackgroundColor;
Color m_rootExtendedBackgroundColor;
HashMap<ScrollingNodeID, RenderLayer*> m_scrollingNodeToLayerMap;
#if PLATFORM(IOS_FAMILY)
std::unique_ptr<LegacyWebKitScrollingLayerCoordinator> m_legacyScrollingLayerCoordinator;
#endif
};
void paintScrollbar(Scrollbar*, GraphicsContext&, const IntRect& clip);
WTF::TextStream& operator<<(WTF::TextStream&, CompositingUpdateType);
WTF::TextStream& operator<<(WTF::TextStream&, CompositingPolicy);
}
#if ENABLE(TREE_DEBUGGING)
void showGraphicsLayerTreeForCompositor(WebCore::RenderLayerCompositor&);
#endif