summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/RenderLayerCompositor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering/RenderLayerCompositor.cpp')
-rw-r--r--Source/WebCore/rendering/RenderLayerCompositor.cpp2440
1 files changed, 1450 insertions, 990 deletions
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp
index 84a271d8c..e87ba96a8 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp
@@ -13,7 +13,7 @@
* 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
+ * 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
@@ -25,10 +25,9 @@
#include "config.h"
-#if USE(ACCELERATED_COMPOSITING)
#include "RenderLayerCompositor.h"
-#include "AnimationController.h"
+#include "CSSAnimationController.h"
#include "CanvasRenderingContext.h"
#include "CSSPropertyNames.h"
#include "Chrome.h"
@@ -43,9 +42,10 @@
#include "HitTestResult.h"
#include "InspectorInstrumentation.h"
#include "Logging.h"
+#include "MainFrame.h"
#include "NodeList.h"
#include "Page.h"
-#include "ProgressTracker.h"
+#include "PageOverlayController.h"
#include "RenderEmbeddedObject.h"
#include "RenderFlowThread.h"
#include "RenderFullScreen.h"
@@ -59,41 +59,37 @@
#include "ScrollingConstraints.h"
#include "ScrollingCoordinator.h"
#include "Settings.h"
+#include "TextStream.h"
#include "TiledBacking.h"
#include "TransformState.h"
#include <wtf/CurrentTime.h>
-#include <wtf/TemporaryChange.h>
+#include <wtf/SetForScope.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>
#if PLATFORM(IOS)
-#include "MainFrame.h"
-#include "Region.h"
+#include "LegacyTileCache.h"
#include "RenderScrollbar.h"
-#include "TileCache.h"
-#endif
-
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
-#include "HTMLAudioElement.h"
-#include "HTMLMediaElement.h"
#endif
-#ifndef NDEBUG
+#if ENABLE(TREE_DEBUGGING)
#include "RenderTreeAsText.h"
#endif
-#if ENABLE(3D_RENDERING)
+#if ENABLE(3D_TRANSFORMS)
// This symbol is used to determine from a script whether 3D rendering is enabled (via 'nm').
-bool WebCoreHas3DRendering = true;
+WEBCORE_EXPORT bool WebCoreHas3DRendering = true;
#endif
#if !PLATFORM(MAC) && !PLATFORM(IOS)
-#define WTF_USE_COMPOSITING_FOR_SMALL_CANVASES 1
+#define USE_COMPOSITING_FOR_SMALL_CANVASES 1
#endif
namespace WebCore {
+#if !USE(COMPOSITING_FOR_SMALL_CANVASES)
static const int canvasAreaThresholdRequiringCompositing = 50 * 100;
+#endif
// During page loading delay layer flushes up to this many seconds to allow them coalesce, reducing workload.
#if PLATFORM(IOS)
static const double throttledLayerFlushInitialDelay = .5;
@@ -105,6 +101,38 @@ static const double throttledLayerFlushDelay = .5;
using namespace HTMLNames;
+class OverlapMapContainer {
+public:
+ void add(const LayoutRect& bounds)
+ {
+ m_layerRects.append(bounds);
+ m_boundingBox.unite(bounds);
+ }
+
+ bool overlapsLayers(const LayoutRect& bounds) const
+ {
+ // Checking with the bounding box will quickly reject cases when
+ // layers are created for lists of items going in one direction and
+ // never overlap with each other.
+ if (!bounds.intersects(m_boundingBox))
+ return false;
+ for (const auto& layerRect : m_layerRects) {
+ if (layerRect.intersects(bounds))
+ return true;
+ }
+ return false;
+ }
+
+ void unite(const OverlapMapContainer& otherContainer)
+ {
+ m_layerRects.appendVector(otherContainer.m_layerRects);
+ m_boundingBox.unite(otherContainer.m_boundingBox);
+ }
+private:
+ Vector<LayoutRect> m_layerRects;
+ LayoutRect m_boundingBox;
+};
+
class RenderLayerCompositor::OverlapMap {
WTF_MAKE_NONCOPYABLE(OverlapMap);
public:
@@ -117,50 +145,46 @@ public:
pushCompositingContainer();
}
- void add(const RenderLayer* layer, const IntRect& bounds)
+ void add(const LayoutRect& bounds)
{
// Layers do not contribute to overlap immediately--instead, they will
// contribute to overlap as soon as their composited ancestor has been
// recursively processed and popped off the stack.
ASSERT(m_overlapStack.size() >= 2);
- m_overlapStack[m_overlapStack.size() - 2].append(bounds);
- m_layers.add(layer);
+ m_overlapStack[m_overlapStack.size() - 2].add(bounds);
+ m_isEmpty = false;
}
- bool contains(const RenderLayer* layer)
+ bool overlapsLayers(const LayoutRect& bounds) const
{
- return m_layers.contains(layer);
+ return m_overlapStack.last().overlapsLayers(bounds);
}
- bool overlapsLayers(const IntRect& bounds) const
+ bool isEmpty() const
{
- return m_overlapStack.last().intersects(bounds);
- }
-
- bool isEmpty()
- {
- return m_layers.isEmpty();
+ return m_isEmpty;
}
void pushCompositingContainer()
{
- m_overlapStack.append(RectList());
+ m_overlapStack.append(OverlapMapContainer());
}
void popCompositingContainer()
{
- m_overlapStack[m_overlapStack.size() - 2].append(m_overlapStack.last());
+ m_overlapStack[m_overlapStack.size() - 2].unite(m_overlapStack.last());
m_overlapStack.removeLast();
}
+ const RenderGeometryMap& geometryMap() const { return m_geometryMap; }
RenderGeometryMap& geometryMap() { return m_geometryMap; }
private:
struct RectList {
- Vector<IntRect> rects;
- IntRect boundingRect;
+ Vector<LayoutRect> rects;
+ LayoutRect boundingRect;
- void append(const IntRect& rect)
+ void append(const LayoutRect& rect)
{
rects.append(rect);
boundingRect.unite(rect);
@@ -172,56 +196,73 @@ private:
boundingRect.unite(rectList.boundingRect);
}
- bool intersects(const IntRect& rect) const
+ bool intersects(const LayoutRect& rect) const
{
if (!rects.size() || !boundingRect.intersects(rect))
return false;
- for (unsigned i = 0; i < rects.size(); i++) {
- if (rects[i].intersects(rect))
+ for (const auto& currentRect : rects) {
+ if (currentRect.intersects(rect))
return true;
}
return false;
}
};
- Vector<RectList> m_overlapStack;
- HashSet<const RenderLayer*> m_layers;
+ Vector<OverlapMapContainer> m_overlapStack;
RenderGeometryMap m_geometryMap;
+ bool m_isEmpty { true };
};
-struct CompositingState {
+struct RenderLayerCompositor::CompositingState {
CompositingState(RenderLayer* compAncestor, bool testOverlap = true)
- : m_compositingAncestor(compAncestor)
- , m_subtreeIsCompositing(false)
- , m_testingOverlap(testOverlap)
- , m_subtreeHasBlending(false)
-#ifndef NDEBUG
- , m_depth(0)
+ : compositingAncestor(compAncestor)
+ , subtreeIsCompositing(false)
+ , testingOverlap(testOverlap)
+ , ancestorHasTransformAnimation(false)
+#if ENABLE(CSS_COMPOSITING)
+ , hasNotIsolatedCompositedBlendingDescendants(false)
+#endif
+#if ENABLE(TREE_DEBUGGING)
+ , depth(0)
#endif
{
}
CompositingState(const CompositingState& other)
- : m_compositingAncestor(other.m_compositingAncestor)
- , m_subtreeIsCompositing(other.m_subtreeIsCompositing)
- , m_testingOverlap(other.m_testingOverlap)
- , m_subtreeHasBlending(other.m_subtreeHasBlending)
-#ifndef NDEBUG
- , m_depth(other.m_depth + 1)
+ : compositingAncestor(other.compositingAncestor)
+ , subtreeIsCompositing(other.subtreeIsCompositing)
+ , testingOverlap(other.testingOverlap)
+ , ancestorHasTransformAnimation(other.ancestorHasTransformAnimation)
+#if ENABLE(CSS_COMPOSITING)
+ , hasNotIsolatedCompositedBlendingDescendants(other.hasNotIsolatedCompositedBlendingDescendants)
+#endif
+#if ENABLE(TREE_DEBUGGING)
+ , depth(other.depth + 1)
#endif
{
}
- RenderLayer* m_compositingAncestor;
- bool m_subtreeIsCompositing;
- bool m_testingOverlap;
- bool m_subtreeHasBlending;
-#ifndef NDEBUG
- int m_depth;
+ RenderLayer* compositingAncestor;
+ bool subtreeIsCompositing;
+ bool testingOverlap;
+ bool ancestorHasTransformAnimation;
+#if ENABLE(CSS_COMPOSITING)
+ bool hasNotIsolatedCompositedBlendingDescendants;
+#endif
+#if ENABLE(TREE_DEBUGGING)
+ int depth;
#endif
};
+struct RenderLayerCompositor::OverlapExtent {
+ LayoutRect bounds;
+ bool extentComputed { false };
+ bool hasTransformAnimation { false };
+ bool animationCausesExtentUncertainty { false };
+
+ bool knownToBeHaveExtentUncertainty() const { return extentComputed && animationCausesExtentUncertainty; }
+};
#if !LOG_DISABLED
static inline bool compositingLogEnabled()
@@ -232,35 +273,8 @@ static inline bool compositingLogEnabled()
RenderLayerCompositor::RenderLayerCompositor(RenderView& renderView)
: m_renderView(renderView)
- , m_updateCompositingLayersTimer(this, &RenderLayerCompositor::updateCompositingLayersTimerFired)
- , m_hasAcceleratedCompositing(true)
- , m_compositingTriggers(static_cast<ChromeClient::CompositingTriggerFlags>(ChromeClient::AllTriggers))
- , m_compositedLayerCount(0)
- , m_showDebugBorders(false)
- , m_showRepaintCounter(false)
- , m_acceleratedDrawingEnabled(false)
- , m_reevaluateCompositingAfterLayout(false)
- , m_compositing(false)
- , m_compositingLayersNeedRebuild(false)
- , m_flushingLayers(false)
- , m_shouldFlushOnReattach(false)
- , m_forceCompositingMode(false)
- , m_inPostLayoutUpdate(false)
- , m_isTrackingRepaints(false)
- , m_layersWithTiledBackingCount(0)
- , m_rootLayerAttachment(RootLayerUnattached)
- , m_layerFlushTimer(this, &RenderLayerCompositor::layerFlushTimerFired)
- , m_layerFlushThrottlingEnabled(page() && page()->progress().isMainLoadProgressing())
- , m_layerFlushThrottlingTemporarilyDisabledForInteraction(false)
- , m_hasPendingLayerFlush(false)
- , m_paintRelatedMilestonesTimer(this, &RenderLayerCompositor::paintRelatedMilestonesTimerFired)
-#if !LOG_DISABLED
- , m_rootLayerUpdateCount(0)
- , m_obligateCompositedLayerCount(0)
- , m_secondaryCompositedLayerCount(0)
- , m_obligatoryBackingStoreBytes(0)
- , m_secondaryBackingStoreBytes(0)
-#endif
+ , m_updateCompositingLayersTimer(*this, &RenderLayerCompositor::updateCompositingLayersTimerFired)
+ , m_layerFlushTimer(*this, &RenderLayerCompositor::layerFlushTimerFired)
{
}
@@ -292,28 +306,28 @@ void RenderLayerCompositor::cacheAcceleratedCompositingFlags()
bool showRepaintCounter = false;
bool forceCompositingMode = false;
bool acceleratedDrawingEnabled = false;
+ bool displayListDrawingEnabled = false;
- const Settings& settings = m_renderView.frameView().frame().settings();
+ auto& settings = m_renderView.settings();
hasAcceleratedCompositing = settings.acceleratedCompositingEnabled();
// We allow the chrome to override the settings, in case the page is rendered
// on a chrome that doesn't allow accelerated compositing.
if (hasAcceleratedCompositing) {
- if (Page* page = this->page()) {
- m_compositingTriggers = page->chrome().client().allowedCompositingTriggers();
- hasAcceleratedCompositing = m_compositingTriggers;
- }
+ m_compositingTriggers = page().chrome().client().allowedCompositingTriggers();
+ hasAcceleratedCompositing = m_compositingTriggers;
}
showDebugBorders = settings.showDebugBorders();
showRepaintCounter = settings.showRepaintCounter();
forceCompositingMode = settings.forceCompositingMode() && hasAcceleratedCompositing;
- if (forceCompositingMode && m_renderView.document().ownerElement())
+ if (forceCompositingMode && !isMainFrameCompositor())
forceCompositingMode = requiresCompositingForScrollableFrame();
acceleratedDrawingEnabled = settings.acceleratedDrawingEnabled();
-
+ displayListDrawingEnabled = settings.displayListDrawingEnabled();
+
if (hasAcceleratedCompositing != m_hasAcceleratedCompositing || showDebugBorders != m_showDebugBorders || showRepaintCounter != m_showRepaintCounter || forceCompositingMode != m_forceCompositingMode)
setCompositingLayersNeedRebuild();
@@ -323,6 +337,7 @@ void RenderLayerCompositor::cacheAcceleratedCompositingFlags()
m_showRepaintCounter = showRepaintCounter;
m_forceCompositingMode = forceCompositingMode;
m_acceleratedDrawingEnabled = acceleratedDrawingEnabled;
+ m_displayListDrawingEnabled = displayListDrawingEnabled;
if (debugBordersChanged) {
if (m_layerForHorizontalScrollbar)
@@ -347,6 +362,20 @@ void RenderLayerCompositor::setCompositingLayersNeedRebuild(bool needRebuild)
m_compositingLayersNeedRebuild = needRebuild;
}
+void RenderLayerCompositor::willRecalcStyle()
+{
+ m_layerNeedsCompositingUpdate = false;
+}
+
+bool RenderLayerCompositor::didRecalcStyleWithNoPendingLayout()
+{
+ if (!m_layerNeedsCompositingUpdate)
+ return false;
+
+ cacheAcceleratedCompositingFlags();
+ return updateCompositingLayers(CompositingUpdateAfterStyleChange);
+}
+
void RenderLayerCompositor::customPositionForVisibleRectComputation(const GraphicsLayer* graphicsLayer, FloatPoint& position) const
{
if (graphicsLayer != m_scrollLayer.get())
@@ -368,8 +397,7 @@ void RenderLayerCompositor::notifyFlushRequired(const GraphicsLayer* layer)
void RenderLayerCompositor::scheduleLayerFlushNow()
{
m_hasPendingLayerFlush = false;
- if (Page* page = this->page())
- page->chrome().client().scheduleCompositingLayerFlush();
+ page().chrome().client().scheduleCompositingLayerFlush();
}
void RenderLayerCompositor::scheduleLayerFlush(bool canThrottle)
@@ -386,16 +414,6 @@ void RenderLayerCompositor::scheduleLayerFlush(bool canThrottle)
scheduleLayerFlushNow();
}
-#if PLATFORM(IOS)
-ChromeClient* RenderLayerCompositor::chromeClient() const
-{
- Page* page = m_renderView.frameView().frame().page();
- if (!page)
- return 0;
- return &page->chrome().client();
-}
-#endif
-
void RenderLayerCompositor::flushPendingLayerChanges(bool isFlushRoot)
{
// FrameView::flushCompositingStateIncludingSubframes() flushes each subframe,
@@ -421,54 +439,82 @@ void RenderLayerCompositor::flushPendingLayerChanges(bool isFlushRoot)
if (GraphicsLayer* rootLayer = rootGraphicsLayer()) {
#if PLATFORM(IOS)
- rootLayer->flushCompositingState(frameView.visibleExtentContentRect());
+ FloatRect exposedRect = frameView.exposedContentRect();
+ LOG_WITH_STREAM(Compositing, stream << "\nRenderLayerCompositor " << this << " flushPendingLayerChanges (root " << isFlushRoot << ") exposedRect " << exposedRect);
+ rootLayer->flushCompositingState(exposedRect);
#else
// Having a m_clipLayer indicates that we're doing scrolling via GraphicsLayers.
- IntRect visibleRect = m_clipLayer ? IntRect(IntPoint(), frameView.contentsSize()) : frameView.visibleContentRect();
+ FloatRect visibleRect = m_clipLayer ? FloatRect({ 0, 0 }, frameView.sizeForVisibleContent()) : frameView.visibleContentRect();
+
+ if (frameView.viewExposedRect())
+ visibleRect.intersect(frameView.viewExposedRect().value());
+
+ LOG_WITH_STREAM(Compositing, stream << "\nRenderLayerCompositor " << this << " flushPendingLayerChanges(" << isFlushRoot << ") " << visibleRect);
rootLayer->flushCompositingState(visibleRect);
+ LOG_WITH_STREAM(Compositing, stream << "RenderLayerCompositor " << this << " flush complete\n");
#endif
}
ASSERT(m_flushingLayers);
m_flushingLayers = false;
-#if PLATFORM(IOS)
- updateCustomLayersAfterFlush();
+ updateScrollCoordinatedLayersAfterFlushIncludingSubframes();
- ChromeClient* client = this->chromeClient();
- if (client && isFlushRoot)
- client->didFlushCompositingLayers();
-#else
- for (auto it = m_viewportConstrainedLayersNeedingUpdate.begin(), end = m_viewportConstrainedLayersNeedingUpdate.end(); it != end; ++it)
- registerOrUpdateViewportConstrainedLayer(**it);
- m_viewportConstrainedLayersNeedingUpdate.clear();
+#if PLATFORM(IOS)
+ if (isFlushRoot)
+ page().chrome().client().didFlushCompositingLayers();
#endif
+
+ ++m_layerFlushCount;
startLayerFlushTimerIfNeeded();
}
+void RenderLayerCompositor::updateScrollCoordinatedLayersAfterFlushIncludingSubframes()
+{
+ updateScrollCoordinatedLayersAfterFlush();
+
+ Frame& frame = m_renderView.frameView().frame();
+ for (Frame* subframe = frame.tree().firstChild(); subframe; subframe = subframe->tree().traverseNext(&frame)) {
+ RenderView* view = subframe->contentRenderer();
+ if (!view)
+ continue;
+
+ view->compositor().updateScrollCoordinatedLayersAfterFlush();
+ }
+}
+
+void RenderLayerCompositor::updateScrollCoordinatedLayersAfterFlush()
+{
+#if PLATFORM(IOS)
+ updateCustomLayersAfterFlush();
+#endif
+
+ for (auto* layer : m_scrollCoordinatedLayersNeedingUpdate)
+ updateScrollCoordinatedStatus(*layer);
+
+ m_scrollCoordinatedLayersNeedingUpdate.clear();
+}
+
#if PLATFORM(IOS)
static bool scrollbarHasDisplayNone(Scrollbar* scrollbar)
{
if (!scrollbar || !scrollbar->isCustomScrollbar())
return false;
- RefPtr<RenderStyle> scrollbarStyle = static_cast<RenderScrollbar*>(scrollbar)->getScrollbarPseudoStyle(ScrollbarBGPart, SCROLLBAR);
+ std::unique_ptr<RenderStyle> scrollbarStyle = static_cast<RenderScrollbar*>(scrollbar)->getScrollbarPseudoStyle(ScrollbarBGPart, SCROLLBAR);
return scrollbarStyle && scrollbarStyle->display() == NONE;
}
// FIXME: Can we make |layer| const RenderLayer&?
-static void updateScrollingLayerWithClient(RenderLayer& layer, ChromeClient* client)
+static void updateScrollingLayerWithClient(RenderLayer& layer, ChromeClient& client)
{
- if (!client)
- return;
-
RenderLayerBacking* backing = layer.backing();
ASSERT(backing);
bool allowHorizontalScrollbar = !scrollbarHasDisplayNone(layer.horizontalScrollbar());
bool allowVerticalScrollbar = !scrollbarHasDisplayNone(layer.verticalScrollbar());
- client->addOrUpdateScrollingLayer(layer.renderer().element(), backing->scrollingLayer()->platformLayer(), backing->scrollingContentsLayer()->platformLayer(),
- IntSize(layer.scrollWidth(), layer.scrollHeight()), allowHorizontalScrollbar, allowVerticalScrollbar);
+ client.addOrUpdateScrollingLayer(layer.renderer().element(), backing->scrollingLayer()->platformLayer(), backing->scrollingContentsLayer()->platformLayer(),
+ layer.scrollableContentsSize(), allowHorizontalScrollbar, allowVerticalScrollbar);
}
void RenderLayerCompositor::updateCustomLayersAfterFlush()
@@ -476,10 +522,8 @@ void RenderLayerCompositor::updateCustomLayersAfterFlush()
registerAllViewportConstrainedLayers();
if (!m_scrollingLayersNeedingUpdate.isEmpty()) {
- ChromeClient* chromeClient = this->chromeClient();
-
- for (auto it = m_scrollingLayersNeedingUpdate.begin(), end = m_scrollingLayersNeedingUpdate.end(); it != end; ++it)
- updateScrollingLayerWithClient(**it, chromeClient);
+ for (auto* layer : m_scrollingLayersNeedingUpdate)
+ updateScrollingLayerWithClient(*layer, page().chrome().client());
m_scrollingLayersNeedingUpdate.clear();
}
m_scrollingLayersNeedingUpdate.clear();
@@ -488,8 +532,8 @@ void RenderLayerCompositor::updateCustomLayersAfterFlush()
void RenderLayerCompositor::didFlushChangesForLayer(RenderLayer& layer, const GraphicsLayer* graphicsLayer)
{
- if (m_viewportConstrainedLayers.contains(&layer))
- m_viewportConstrainedLayersNeedingUpdate.add(&layer);
+ if (m_scrollCoordinatedLayers.contains(&layer))
+ m_scrollCoordinatedLayersNeedingUpdate.add(&layer);
#if PLATFORM(IOS)
if (m_scrollingLayers.contains(&layer))
@@ -505,8 +549,8 @@ void RenderLayerCompositor::didPaintBacking(RenderLayerBacking*)
{
FrameView& frameView = m_renderView.frameView();
frameView.setLastPaintTime(monotonicallyIncreasingTime());
- if (frameView.milestonesPendingPaint() && !m_paintRelatedMilestonesTimer.isActive())
- m_paintRelatedMilestonesTimer.startOneShot(0);
+ if (frameView.milestonesPendingPaint())
+ frameView.firePaintRelatedMilestonesIfNeeded();
}
void RenderLayerCompositor::didChangeVisibleRect()
@@ -518,7 +562,7 @@ void RenderLayerCompositor::didChangeVisibleRect()
const FrameView& frameView = m_renderView.frameView();
#if PLATFORM(IOS)
- IntRect visibleRect = frameView.visibleExtentContentRect();
+ IntRect visibleRect = enclosingIntRect(frameView.exposedContentRect());
#else
IntRect visibleRect = m_clipLayer ? IntRect(IntPoint(), frameView.contentsSize()) : frameView.visibleContentRect();
#endif
@@ -530,26 +574,24 @@ void RenderLayerCompositor::didChangeVisibleRect()
void RenderLayerCompositor::notifyFlushBeforeDisplayRefresh(const GraphicsLayer*)
{
if (!m_layerUpdater) {
- PlatformDisplayID displayID = 0;
- if (Page* page = this->page())
- displayID = page->chrome().displayID();
-
- m_layerUpdater = adoptPtr(new GraphicsLayerUpdater(this, displayID));
+ PlatformDisplayID displayID = page().chrome().displayID();
+ m_layerUpdater = std::make_unique<GraphicsLayerUpdater>(*this, displayID);
}
m_layerUpdater->scheduleUpdate();
}
-void RenderLayerCompositor::flushLayers(GraphicsLayerUpdater*)
+void RenderLayerCompositor::flushLayersSoon(GraphicsLayerUpdater&)
{
- flushPendingLayerChanges(true); // FIXME: deal with iframes
+ scheduleLayerFlush(true);
}
-void RenderLayerCompositor::layerTiledBackingUsageChanged(const GraphicsLayer*, bool usingTiledBacking)
+void RenderLayerCompositor::layerTiledBackingUsageChanged(const GraphicsLayer* graphicsLayer, bool usingTiledBacking)
{
- if (usingTiledBacking)
+ if (usingTiledBacking) {
++m_layersWithTiledBackingCount;
- else {
+ graphicsLayer->tiledBacking()->setIsInWindow(page().isInWindow());
+ } else {
ASSERT(m_layersWithTiledBackingCount > 0);
--m_layersWithTiledBackingCount;
}
@@ -558,12 +600,12 @@ void RenderLayerCompositor::layerTiledBackingUsageChanged(const GraphicsLayer*,
RenderLayerCompositor* RenderLayerCompositor::enclosingCompositorFlushingLayers() const
{
for (Frame* frame = &m_renderView.frameView().frame(); frame; frame = frame->tree().parent()) {
- RenderLayerCompositor* compositor = frame->contentRenderer() ? &frame->contentRenderer()->compositor() : 0;
+ RenderLayerCompositor* compositor = frame->contentRenderer() ? &frame->contentRenderer()->compositor() : nullptr;
if (compositor->isFlushingLayers())
return compositor;
}
- return 0;
+ return nullptr;
}
void RenderLayerCompositor::scheduleCompositingLayerUpdate()
@@ -572,37 +614,49 @@ void RenderLayerCompositor::scheduleCompositingLayerUpdate()
m_updateCompositingLayersTimer.startOneShot(0);
}
-void RenderLayerCompositor::updateCompositingLayersTimerFired(Timer<RenderLayerCompositor>&)
+void RenderLayerCompositor::updateCompositingLayersTimerFired()
{
updateCompositingLayers(CompositingUpdateAfterLayout);
}
bool RenderLayerCompositor::hasAnyAdditionalCompositedLayers(const RenderLayer& rootLayer) const
{
- return m_compositedLayerCount > (rootLayer.isComposited() ? 1 : 0);
+ int layerCount = m_compositedLayerCount + m_renderView.frame().mainFrame().pageOverlayController().overlayCount();
+ return layerCount > (rootLayer.isComposited() ? 1 : 0);
}
-void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType updateType, RenderLayer* updateRoot)
+void RenderLayerCompositor::cancelCompositingLayerUpdate()
{
m_updateCompositingLayersTimer.stop();
+}
+
+bool RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType updateType, RenderLayer* updateRoot)
+{
+ LOG(Compositing, "RenderLayerCompositor %p updateCompositingLayers %d %p", this, updateType, updateRoot);
+
+ m_updateCompositingLayersTimer.stop();
+
+ ASSERT(m_renderView.document().pageCacheState() == Document::NotInPageCache);
- // Compositing layers will be updated in Document::implicitClose() if suppressed here.
+ // Compositing layers will be updated in Document::setVisualUpdatesAllowed(bool) if suppressed here.
if (!m_renderView.document().visualUpdatesAllowed())
- return;
+ return false;
// Avoid updating the layers with old values. Compositing layers will be updated after the layout is finished.
if (m_renderView.needsLayout())
- return;
+ return false;
- if (m_forceCompositingMode && !m_compositing)
+ if (!m_compositing && (m_forceCompositingMode || (isMainFrameCompositor() && m_renderView.frame().mainFrame().pageOverlayController().overlayCount())))
enableCompositingMode(true);
if (!m_reevaluateCompositingAfterLayout && !m_compositing)
- return;
+ return false;
+
+ ++m_compositingUpdateCount;
AnimationUpdateBlock animationUpdateBlock(&m_renderView.frameView().frame().animation());
- TemporaryChange<bool> postLayoutChange(m_inPostLayoutUpdate, true);
+ SetForScope<bool> postLayoutChange(m_inPostLayoutUpdate, true);
bool checkForHierarchyUpdate = m_reevaluateCompositingAfterLayout;
bool needGeometryUpdate = false;
@@ -624,7 +678,7 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
}
if (!checkForHierarchyUpdate && !needGeometryUpdate)
- return;
+ return false;
bool needHierarchyUpdate = m_compositingLayersNeedRebuild;
bool isFullUpdate = !updateRoot;
@@ -636,6 +690,8 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
if (isFullUpdate && updateType == CompositingUpdateAfterLayout)
m_reevaluateCompositingAfterLayout = false;
+ LOG(Compositing, " checkForHierarchyUpdate %d, needGeometryUpdate %d", checkForHierarchyUpdate, needHierarchyUpdate);
+
#if !LOG_DISABLED
double startTime = 0;
if (compositingLogEnabled()) {
@@ -645,15 +701,15 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
#endif
if (checkForHierarchyUpdate) {
- if (isFullUpdate)
- updateRenderFlowThreadLayersIfNeeded();
+ if (m_renderView.hasRenderNamedFlowThreads() && isFullUpdate)
+ m_renderView.flowThreadController().updateFlowThreadsLayerToRegionMappingsIfNeeded();
// Go through the layers in presentation order, so that we can compute which RenderLayers need compositing layers.
// FIXME: we could maybe do this and the hierarchy udpate in one pass, but the parenting logic would be more complex.
CompositingState compState(updateRoot);
bool layersChanged = false;
bool saw3DTransform = false;
OverlapMap overlapTestRequestMap;
- computeCompositingRequirements(nullptr, *updateRoot, &overlapTestRequestMap, compState, layersChanged, saw3DTransform);
+ computeCompositingRequirements(nullptr, *updateRoot, overlapTestRequestMap, compState, layersChanged, saw3DTransform);
needHierarchyUpdate |= layersChanged;
}
@@ -665,7 +721,7 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
m_secondaryBackingStoreBytes = 0;
Frame& frame = m_renderView.frameView().frame();
- bool isMainFrame = !m_renderView.document().ownerElement();
+ bool isMainFrame = isMainFrameCompositor();
LOG(Compositing, "\nUpdate %d of %s.\n", m_rootLayerUpdateCount, isMainFrame ? "main frame" : frame.tree().uniqueName().string().utf8().data());
}
#endif
@@ -677,17 +733,21 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
// Host the document layer in the RenderView's root layer.
if (isFullUpdate) {
+ appendDocumentOverlayLayers(childList);
// Even when childList is empty, don't drop out of compositing mode if there are
// composited layers that we didn't hit in our traversal (e.g. because of visibility:hidden).
if (childList.isEmpty() && !hasAnyAdditionalCompositedLayers(*updateRoot))
destroyRootLayer();
- else
+ else if (m_rootContentLayer)
m_rootContentLayer->setChildren(childList);
}
+
+ reattachSubframeScrollLayers();
} else if (needGeometryUpdate) {
// We just need to do a geometry update. This is only used for position:fixed scrolling;
// most of the time, geometry is updated via RenderLayer::styleChanged().
updateLayerTreeGeometry(*updateRoot, 0);
+ ASSERT(!isFullUpdate || !m_subframeScrollLayersNeedReattach);
}
#if !LOG_DISABLED
@@ -706,19 +766,24 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
enableCompositingMode(false);
// Inform the inspector that the layer tree has changed.
- InspectorInstrumentation::layerTreeDidChange(page());
+ InspectorInstrumentation::layerTreeDidChange(&page());
+
+ return true;
}
-void RenderLayerCompositor::updateRenderFlowThreadLayersIfNeeded()
+void RenderLayerCompositor::appendDocumentOverlayLayers(Vector<GraphicsLayer*>& childList)
{
- if (m_renderView.hasRenderNamedFlowThreads())
- m_renderView.flowThreadController().updateRenderFlowThreadLayersIfNeeded();
+ if (!isMainFrameCompositor() || !m_compositing)
+ return;
+
+ Frame& frame = m_renderView.frameView().frame();
+ childList.append(&frame.mainFrame().pageOverlayController().layerWithDocumentOverlays());
}
void RenderLayerCompositor::layerBecameNonComposited(const RenderLayer& layer)
{
// Inform the inspector that the given RenderLayer was destroyed.
- InspectorInstrumentation::renderLayerDestroyed(page(), &layer);
+ InspectorInstrumentation::renderLayerDestroyed(&page(), layer);
ASSERT(m_compositedLayerCount > 0);
--m_compositedLayerCount;
@@ -739,22 +804,45 @@ void RenderLayerCompositor::logLayerInfo(const RenderLayer& layer, int depth)
m_secondaryBackingStoreBytes += backing->backingStoreMemoryEstimate();
}
+ LayoutRect absoluteBounds = backing->compositedBounds();
+ absoluteBounds.move(layer.offsetFromAncestor(m_renderView.layer()));
+
StringBuilder logString;
- logString.append(String::format("%*p %dx%d %.2fKB", 12 + depth * 2, &layer,
- backing->compositedBounds().width().round(), backing->compositedBounds().height().round(),
+ logString.append(String::format("%*p (%.3f,%.3f-%.3f,%.3f) %.2fKB", 12 + depth * 2, &layer,
+ absoluteBounds.x().toFloat(), absoluteBounds.y().toFloat(), absoluteBounds.maxX().toFloat(), absoluteBounds.maxY().toFloat(),
backing->backingStoreMemoryEstimate() / 1024));
- logString.append(" (");
+ logString.appendLiteral(" (");
logString.append(logReasonsForCompositing(layer));
- logString.append(") ");
+ logString.appendLiteral(") ");
- if (backing->graphicsLayer()->contentsOpaque() || backing->paintsIntoCompositedAncestor()) {
+ if (backing->graphicsLayer()->contentsOpaque() || backing->paintsIntoCompositedAncestor() || backing->foregroundLayer() || backing->backgroundLayer()) {
logString.append('[');
- if (backing->graphicsLayer()->contentsOpaque())
- logString.append("opaque");
- if (backing->paintsIntoCompositedAncestor())
- logString.append("paints into ancestor");
- logString.append("] ");
+ bool prependSpace = false;
+ if (backing->graphicsLayer()->contentsOpaque()) {
+ logString.appendLiteral("opaque");
+ prependSpace = true;
+ }
+
+ if (backing->paintsIntoCompositedAncestor()) {
+ if (prependSpace)
+ logString.appendLiteral(", ");
+ logString.appendLiteral("paints into ancestor");
+ prependSpace = true;
+ }
+
+ if (backing->foregroundLayer() || backing->backgroundLayer()) {
+ if (prependSpace)
+ logString.appendLiteral(", ");
+ if (backing->foregroundLayer() && backing->backgroundLayer())
+ logString.appendLiteral("foreground+background");
+ else if (backing->foregroundLayer())
+ logString.appendLiteral("foreground");
+ else
+ logString.appendLiteral("background");
+ }
+
+ logString.appendLiteral("] ");
}
logString.append(layer.name());
@@ -763,12 +851,136 @@ void RenderLayerCompositor::logLayerInfo(const RenderLayer& layer, int depth)
}
#endif
-bool RenderLayerCompositor::updateBacking(RenderLayer& layer, CompositingChangeRepaint shouldRepaint)
+static bool checkIfDescendantClippingContextNeedsUpdate(const RenderLayer& layer, bool isClipping)
+{
+ for (RenderLayer* child = layer.firstChild(); child; child = child->nextSibling()) {
+ RenderLayerBacking* backing = child->backing();
+ if (backing && (isClipping || backing->hasAncestorClippingLayer()))
+ return true;
+
+ if (checkIfDescendantClippingContextNeedsUpdate(*child, isClipping))
+ return true;
+ }
+ return false;
+}
+
+#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
+static bool isScrollableOverflow(EOverflow overflow)
+{
+ return overflow == OSCROLL || overflow == OAUTO || overflow == OOVERLAY;
+}
+
+static bool styleHasTouchScrolling(const RenderStyle& style)
+{
+ return style.useTouchOverflowScrolling() && (isScrollableOverflow(style.overflowX()) || isScrollableOverflow(style.overflowY()));
+}
+#endif
+
+static bool styleChangeRequiresLayerRebuild(const RenderLayer& layer, const RenderStyle& oldStyle, const RenderStyle& newStyle)
+{
+ // Clip can affect ancestor compositing bounds, so we need recompute overlap when it changes on a non-composited layer.
+ // FIXME: we should avoid doing this for all clip changes.
+ if (oldStyle.clip() != newStyle.clip() || oldStyle.hasClip() != newStyle.hasClip())
+ return true;
+
+ // FIXME: need to check everything that we consult to avoid backing store here: webkit.org/b/138383
+ if (!oldStyle.opacity() != !newStyle.opacity()) {
+ RenderLayerModelObject* repaintContainer = layer.renderer().containerForRepaint();
+ if (RenderLayerBacking* ancestorBacking = repaintContainer ? repaintContainer->layer()->backing() : nullptr) {
+ if (static_cast<bool>(newStyle.opacity()) != ancestorBacking->graphicsLayer()->drawsContent())
+ return true;
+ }
+ }
+
+ // When overflow changes, composited layers may need to update their ancestorClipping layers.
+ if (!layer.isComposited() && (oldStyle.overflowX() != newStyle.overflowX() || oldStyle.overflowY() != newStyle.overflowY()) && layer.stackingContainer()->hasCompositingDescendant())
+ return true;
+
+#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
+ if (styleHasTouchScrolling(oldStyle) != styleHasTouchScrolling(newStyle))
+ return true;
+#endif
+
+ // Compositing layers keep track of whether they are clipped by any of the ancestors.
+ // When the current layer's clipping behaviour changes, we need to propagate it to the descendants.
+ bool wasClipping = oldStyle.hasClip() || oldStyle.overflowX() != OVISIBLE || oldStyle.overflowY() != OVISIBLE;
+ bool isClipping = newStyle.hasClip() || newStyle.overflowX() != OVISIBLE || newStyle.overflowY() != OVISIBLE;
+ if (isClipping != wasClipping) {
+ if (checkIfDescendantClippingContextNeedsUpdate(layer, isClipping))
+ return true;
+ }
+
+ return false;
+}
+
+void RenderLayerCompositor::layerStyleChanged(StyleDifference diff, RenderLayer& layer, const RenderStyle* oldStyle)
+{
+ if (diff == StyleDifferenceEqual)
+ return;
+
+ const RenderStyle& newStyle = layer.renderer().style();
+ if (updateLayerCompositingState(layer) || (oldStyle && styleChangeRequiresLayerRebuild(layer, *oldStyle, newStyle))) {
+ setCompositingLayersNeedRebuild();
+ m_layerNeedsCompositingUpdate = true;
+ return;
+ }
+
+ if (layer.isComposited()) {
+ // FIXME: updating geometry here is potentially harmful, because layout is not up-to-date.
+ layer.backing()->updateGeometry();
+ layer.backing()->updateAfterDescendants();
+ m_layerNeedsCompositingUpdate = true;
+ return;
+ }
+
+ // We don't have any direct reasons for this style change to affect layer composition. Test if it might affect things indirectly.
+ if (oldStyle && styleChangeMayAffectIndirectCompositingReasons(layer.renderer(), *oldStyle)) {
+ m_layerNeedsCompositingUpdate = true;
+ return;
+ }
+
+ if (layer.isRootLayer()) {
+ // Needed for scroll bars.
+ m_layerNeedsCompositingUpdate = true;
+ }
+}
+
+bool RenderLayerCompositor::canCompositeClipPath(const RenderLayer& layer)
+{
+ ASSERT(layer.isComposited());
+ ASSERT(layer.renderer().style().clipPath());
+
+ if (layer.renderer().hasMask())
+ return false;
+
+ ClipPathOperation& clipPath = *layer.renderer().style().clipPath();
+ return (clipPath.type() != ClipPathOperation::Shape || clipPath.type() == ClipPathOperation::Shape) && GraphicsLayer::supportsLayerType(GraphicsLayer::Type::Shape);
+}
+
+static RenderLayerModelObject& rendererForCompositingTests(const RenderLayer& layer)
+{
+ RenderLayerModelObject* renderer = &layer.renderer();
+
+ // The compositing state of a reflection should match that of its reflected layer.
+ if (layer.isReflection())
+ renderer = downcast<RenderLayerModelObject>(renderer->parent()); // The RenderReplica's parent is the object being reflected.
+
+ return *renderer;
+}
+
+bool RenderLayerCompositor::updateBacking(RenderLayer& layer, CompositingChangeRepaint shouldRepaint, BackingRequired backingRequired)
{
bool layerChanged = false;
RenderLayer::ViewportConstrainedNotCompositedReason viewportConstrainedNotCompositedReason = RenderLayer::NoNotCompositedReason;
- if (needsToBeComposited(layer, &viewportConstrainedNotCompositedReason)) {
+ if (backingRequired == BackingRequired::Unknown)
+ backingRequired = needsToBeComposited(layer, &viewportConstrainedNotCompositedReason) ? BackingRequired::Yes : BackingRequired::No;
+ else {
+ // Need to fetch viewportConstrainedNotCompositedReason, but without doing all the work that needsToBeComposited does.
+ requiresCompositingForPosition(rendererForCompositingTests(layer), layer, &viewportConstrainedNotCompositedReason);
+ }
+
+ if (backingRequired == BackingRequired::Yes) {
enableCompositingMode();
if (!layer.backing()) {
@@ -779,18 +991,19 @@ bool RenderLayerCompositor::updateBacking(RenderLayer& layer, CompositingChangeR
layer.ensureBacking();
// At this time, the ScrollingCoordinator only supports the top-level frame.
- if (layer.isRootLayer() && !m_renderView.document().ownerElement()) {
- layer.backing()->attachToScrollingCoordinatorWithParent(0);
+ if (layer.isRootLayer() && isMainFrameCompositor()) {
+ updateScrollCoordinatedStatus(layer);
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->frameViewRootLayerDidChange(&m_renderView.frameView());
+ scrollingCoordinator->frameViewRootLayerDidChange(m_renderView.frameView());
#if ENABLE(RUBBER_BANDING)
- if (Page* page = this->page()) {
- updateLayerForHeader(page->headerHeight());
- updateLayerForFooter(page->footerHeight());
- }
+ updateLayerForHeader(page().headerHeight());
+ updateLayerForFooter(page().footerHeight());
#endif
- if (mainFrameBackingIsTiledWithMargin())
+ if (m_renderView.settings().backgroundShouldExtendBeyondPage())
m_rootContentLayer->setMasksToBounds(false);
+
+ if (TiledBacking* tiledBacking = layer.backing()->tiledBacking())
+ tiledBacking->setTopContentInset(m_renderView.frameView().topContentInset());
}
// This layer and all of its descendants have cached repaints rects that are relative to
@@ -806,15 +1019,15 @@ bool RenderLayerCompositor::updateBacking(RenderLayer& layer, CompositingChangeR
// its replica GraphicsLayer. In practice this should never happen because reflectee and reflection
// are both either composited, or not composited.
if (layer.isReflection()) {
- RenderLayer* sourceLayer = toRenderLayerModelObject(layer.renderer().parent())->layer();
+ RenderLayer* sourceLayer = downcast<RenderLayerModelObject>(*layer.renderer().parent()).layer();
if (RenderLayerBacking* backing = sourceLayer->backing()) {
ASSERT(backing->graphicsLayer()->replicaLayer() == layer.backing()->graphicsLayer());
- backing->graphicsLayer()->setReplicatedByLayer(0);
+ backing->graphicsLayer()->setReplicatedByLayer(nullptr);
}
}
- removeViewportConstrainedLayer(layer);
-
+ removeFromScrollCoordinatedLayers(layer);
+
layer.clearBacking();
layerChanged = true;
@@ -829,14 +1042,14 @@ bool RenderLayerCompositor::updateBacking(RenderLayer& layer, CompositingChangeR
}
#if ENABLE(VIDEO)
- if (layerChanged && layer.renderer().isVideo()) {
+ if (layerChanged && is<RenderVideo>(layer.renderer())) {
// If it's a video, give the media player a chance to hook up to the layer.
- toRenderVideo(layer.renderer()).acceleratedRenderingStateChanged();
+ downcast<RenderVideo>(layer.renderer()).acceleratedRenderingStateChanged();
}
#endif
- if (layerChanged && layer.renderer().isWidget()) {
- RenderLayerCompositor* innerCompositor = frameContentsCompositor(toRenderWidget(&layer.renderer()));
+ if (layerChanged && is<RenderWidget>(layer.renderer())) {
+ RenderLayerCompositor* innerCompositor = frameContentsCompositor(&downcast<RenderWidget>(layer.renderer()));
if (innerCompositor && innerCompositor->inCompositingMode())
innerCompositor->updateRootLayerAttachment();
}
@@ -853,7 +1066,7 @@ bool RenderLayerCompositor::updateBacking(RenderLayer& layer, CompositingChangeR
}
if (layerChanged) {
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->frameViewFixedObjectsDidChange(&m_renderView.frameView());
+ scrollingCoordinator->frameViewFixedObjectsDidChange(m_renderView.frameView());
}
} else
layer.setViewportConstrainedNotCompositedReason(RenderLayer::NoNotCompositedReason);
@@ -870,7 +1083,7 @@ bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer& layer, Comp
// See if we need content or clipping layers. Methods called here should assume
// that the compositing state of descendant layers has not been updated yet.
- if (layer.backing() && layer.backing()->updateGraphicsLayerConfiguration())
+ if (layer.backing() && layer.backing()->updateConfiguration())
layerChanged = true;
return layerChanged;
@@ -901,13 +1114,8 @@ void RenderLayerCompositor::repaintInCompositedAncestor(RenderLayer& layer, cons
RenderLayer* compositedAncestor = layer.enclosingCompositingLayerForRepaint(ExcludeSelf);
if (compositedAncestor) {
ASSERT(compositedAncestor->backing());
-
- LayoutPoint offset;
- layer.convertToLayerCoords(compositedAncestor, offset);
-
LayoutRect repaintRect = rect;
- repaintRect.moveBy(offset);
-
+ repaintRect.move(layer.offsetFromAncestor(compositedAncestor));
compositedAncestor->setBackingNeedsRepaintInRect(repaintRect);
}
@@ -917,15 +1125,6 @@ void RenderLayerCompositor::repaintInCompositedAncestor(RenderLayer& layer, cons
m_renderView.frameView().setNeedsOneShotDrawingSynchronization();
}
-// The bounds of the GraphicsLayer created for a compositing layer is the union of the bounds of all the descendant
-// RenderLayers that are rendered by the composited RenderLayer.
-LayoutRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer& layer, const RenderLayer& ancestorLayer) const
-{
- if (!canBeComposited(layer))
- return LayoutRect();
- return layer.calculateLayerBounds(&ancestorLayer, nullptr, RenderLayer::DefaultCalculateLayerBoundsFlags | RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask);
-}
-
void RenderLayerCompositor::layerWasAdded(RenderLayer&, RenderLayer&)
{
setCompositingLayersNeedRebuild();
@@ -933,10 +1132,10 @@ void RenderLayerCompositor::layerWasAdded(RenderLayer&, RenderLayer&)
void RenderLayerCompositor::layerWillBeRemoved(RenderLayer& parent, RenderLayer& child)
{
- if (!child.isComposited() || parent.renderer().documentBeingDestroyed())
+ if (!child.isComposited() || parent.renderer().renderTreeBeingDestroyed())
return;
- removeViewportConstrainedLayer(child);
+ removeFromScrollCoordinatedLayers(child);
repaintInCompositedAncestor(child, child.backing()->compositedBounds());
setCompositingParent(child, nullptr);
@@ -954,67 +1153,85 @@ RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const Rend
return nullptr;
}
-void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, RenderLayer& layer, IntRect& layerBounds, bool& boundsComputed)
+void RenderLayerCompositor::computeExtent(const OverlapMap& overlapMap, const RenderLayer& layer, OverlapExtent& extent) const
{
- if (layer.isRootLayer())
+ if (extent.extentComputed)
return;
- if (!boundsComputed) {
- // FIXME: If this layer's overlap bounds include its children, we don't need to add its
- // children's bounds to the overlap map.
- layerBounds = enclosingIntRect(overlapMap.geometryMap().absoluteRect(layer.overlapBounds()));
- // Empty rects never intersect, but we need them to for the purposes of overlap testing.
- if (layerBounds.isEmpty())
- layerBounds.setSize(IntSize(1, 1));
- boundsComputed = true;
+ LayoutRect layerBounds;
+ if (extent.hasTransformAnimation)
+ extent.animationCausesExtentUncertainty = !layer.getOverlapBoundsIncludingChildrenAccountingForTransformAnimations(layerBounds);
+ else
+ layerBounds = layer.overlapBounds();
+
+ // In the animating transform case, we avoid double-accounting for the transform because
+ // we told pushMappingsToAncestor() to ignore transforms earlier.
+ extent.bounds = enclosingLayoutRect(overlapMap.geometryMap().absoluteRect(layerBounds));
+
+ // Empty rects never intersect, but we need them to for the purposes of overlap testing.
+ if (extent.bounds.isEmpty())
+ extent.bounds.setSize(LayoutSize(1, 1));
+
+
+ RenderLayerModelObject& renderer = layer.renderer();
+ if (renderer.isOutOfFlowPositioned() && renderer.style().position() == FixedPosition && renderer.container() == &m_renderView) {
+ // Because fixed elements get moved around without re-computing overlap, we have to compute an overlap
+ // rect that covers all the locations that the fixed element could move to.
+ // FIXME: need to handle sticky too.
+ extent.bounds = m_renderView.frameView().fixedScrollableAreaBoundsInflatedForScrolling(extent.bounds);
}
- IntRect clipRect = pixelSnappedIntRect(layer.backgroundClipRect(RenderLayer::ClipRectsContext(&rootRenderLayer(), 0, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions.
+ extent.extentComputed = true;
+}
+
+void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, const RenderLayer& layer, OverlapExtent& extent)
+{
+ if (layer.isRootLayer())
+ return;
+
+ computeExtent(overlapMap, layer, extent);
+
+ LayoutRect clipRect = layer.backgroundClipRect(RenderLayer::ClipRectsContext(&rootRenderLayer(), AbsoluteClipRects)).rect(); // FIXME: Incorrect for CSS regions.
// On iOS, pageScaleFactor() is not applied by RenderView, so we should not scale here.
- // FIXME: Set Settings::delegatesPageScaling to true for iOS.
-#if !PLATFORM(IOS)
- const Settings& settings = m_renderView.frameView().frame().settings();
- if (!settings.delegatesPageScaling())
+ if (!m_renderView.settings().delegatesPageScaling())
clipRect.scale(pageScaleFactor());
-#endif
- clipRect.intersect(layerBounds);
- overlapMap.add(&layer, clipRect);
+ clipRect.intersect(extent.bounds);
+ overlapMap.add(clipRect);
}
-void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, RenderLayer& layer, RenderLayer* ancestorLayer)
+void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, const RenderLayer& layer, const RenderLayer* ancestorLayer)
{
- if (!canBeComposited(layer) || overlapMap.contains(&layer))
+ if (!canBeComposited(layer))
return;
// A null ancestorLayer is an indication that 'layer' has already been pushed.
if (ancestorLayer)
overlapMap.geometryMap().pushMappingsToAncestor(&layer, ancestorLayer);
- IntRect bounds;
- bool haveComputedBounds = false;
- addToOverlapMap(overlapMap, layer, bounds, haveComputedBounds);
+ OverlapExtent layerExtent;
+ addToOverlapMap(overlapMap, layer, layerExtent);
#if !ASSERT_DISABLED
- LayerListMutationDetector mutationChecker(&layer);
+ LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(&layer));
#endif
if (layer.isStackingContainer()) {
if (Vector<RenderLayer*>* negZOrderList = layer.negZOrderList()) {
- for (size_t i = 0, size = negZOrderList->size(); i < size; ++i)
- addToOverlapMapRecursive(overlapMap, *negZOrderList->at(i), &layer);
+ for (auto* renderLayer : *negZOrderList)
+ addToOverlapMapRecursive(overlapMap, *renderLayer, &layer);
}
}
if (Vector<RenderLayer*>* normalFlowList = layer.normalFlowList()) {
- for (size_t i = 0, size = normalFlowList->size(); i < size; ++i)
- addToOverlapMapRecursive(overlapMap, *normalFlowList->at(i), &layer);
+ for (auto* renderLayer : *normalFlowList)
+ addToOverlapMapRecursive(overlapMap, *renderLayer, &layer);
}
if (layer.isStackingContainer()) {
if (Vector<RenderLayer*>* posZOrderList = layer.posZOrderList()) {
- for (size_t i = 0, size = posZOrderList->size(); i < size; ++i)
- addToOverlapMapRecursive(overlapMap, *posZOrderList->at(i), &layer);
+ for (auto* renderLayer : *posZOrderList)
+ addToOverlapMapRecursive(overlapMap, *renderLayer, &layer);
}
}
@@ -1022,7 +1239,7 @@ void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, Ren
overlapMap.geometryMap().popMappingsToAncestor(ancestorLayer);
}
-void RenderLayerCompositor::computeCompositingRequirementsForNamedFlowFixed(RenderLayer& layer, OverlapMap* overlapMap, CompositingState& childState, bool& layersChanged, bool& anyDescendantHas3DTransform)
+void RenderLayerCompositor::computeCompositingRequirementsForNamedFlowFixed(RenderLayer& layer, OverlapMap& overlapMap, CompositingState& childState, bool& layersChanged, bool& anyDescendantHas3DTransform)
{
if (!layer.isRootLayer())
return;
@@ -1033,10 +1250,8 @@ void RenderLayerCompositor::computeCompositingRequirementsForNamedFlowFixed(Rend
Vector<RenderLayer*> fixedLayers;
layer.renderer().view().flowThreadController().collectFixedPositionedLayers(fixedLayers);
- for (size_t i = 0; i < fixedLayers.size(); ++i) {
- RenderLayer* fixedLayer = fixedLayers.at(i);
+ for (auto* fixedLayer : fixedLayers)
computeCompositingRequirements(&layer, *fixedLayer, overlapMap, childState, layersChanged, anyDescendantHas3DTransform);
- }
}
// Recurse through the layers in z-index and overflow order (which is equivalent to painting order)
@@ -1048,42 +1263,45 @@ void RenderLayerCompositor::computeCompositingRequirementsForNamedFlowFixed(Rend
// must be compositing so that its contents render over that child.
// This implies that its positive z-index children must also be compositing.
//
-void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestorLayer, RenderLayer& layer, OverlapMap* overlapMap, CompositingState& compositingState, bool& layersChanged, bool& descendantHas3DTransform)
+void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestorLayer, RenderLayer& layer, OverlapMap& overlapMap, CompositingState& compositingState, bool& layersChanged, bool& descendantHas3DTransform)
{
layer.updateDescendantDependentFlags();
layer.updateLayerListsIfNeeded();
if (layer.isFlowThreadCollectingGraphicsLayersUnderRegions()) {
- RenderFlowThread& flowThread = toRenderFlowThread(layer.renderer());
+ auto& flowThread = downcast<RenderFlowThread>(layer.renderer());
layer.setHasCompositingDescendant(flowThread.hasCompositingRegionDescendant());
// Before returning, we need to update the lists of all child layers. This is required because,
// if this flow thread will not be painted (for instance because of having no regions, or only invalid regions),
// the child layers will never have their lists updated (which would normally happen during painting).
layer.updateDescendantsLayerListsIfNeeded(true);
-
return;
}
- if (overlapMap)
- overlapMap->geometryMap().pushMappingsToAncestor(&layer, ancestorLayer);
-
// Clear the flag
layer.setHasCompositingDescendant(false);
+ layer.setIndirectCompositingReason(RenderLayer::IndirectCompositingReason::None);
+
+ // Check if the layer needs to be composited for direct reasons (e.g. 3D transform).
+ bool willBeComposited = needsToBeComposited(layer);
- RenderLayer::IndirectCompositingReason compositingReason = compositingState.m_subtreeIsCompositing ? RenderLayer::IndirectCompositingForStacking : RenderLayer::NoIndirectCompositingReason;
+ OverlapExtent layerExtent;
+ // Use the fact that we're composited as a hint to check for an animating transform.
+ // FIXME: Maybe needsToBeComposited() should return a bitmask of reasons, to avoid the need to recompute things.
+ if (willBeComposited && !layer.isRootLayer())
+ layerExtent.hasTransformAnimation = isRunningTransformAnimation(layer.renderer());
- bool haveComputedBounds = false;
- IntRect absBounds;
- if (overlapMap && !overlapMap->isEmpty() && compositingState.m_testingOverlap) {
- // If we're testing for overlap, we only need to composite if we overlap something that is already composited.
- absBounds = enclosingIntRect(overlapMap->geometryMap().absoluteRect(layer.overlapBounds()));
+ bool respectTransforms = !layerExtent.hasTransformAnimation;
+ overlapMap.geometryMap().pushMappingsToAncestor(&layer, ancestorLayer, respectTransforms);
+
+ RenderLayer::IndirectCompositingReason compositingReason = compositingState.subtreeIsCompositing ? RenderLayer::IndirectCompositingReason::Stacking : RenderLayer::IndirectCompositingReason::None;
- // Empty rects never intersect, but we need them to for the purposes of overlap testing.
- if (absBounds.isEmpty())
- absBounds.setSize(IntSize(1, 1));
- haveComputedBounds = true;
- compositingReason = overlapMap->overlapsLayers(absBounds) ? RenderLayer::IndirectCompositingForOverlap : RenderLayer::NoIndirectCompositingReason;
+ // If we know for sure the layer is going to be composited, don't bother looking it up in the overlap map
+ if (!willBeComposited && !overlapMap.isEmpty() && compositingState.testingOverlap) {
+ computeExtent(overlapMap, layer, layerExtent);
+ // If we're testing for overlap, we only need to composite if we overlap something that is already composited.
+ compositingReason = overlapMap.overlapsLayers(layerExtent.bounds) ? RenderLayer::IndirectCompositingReason::Overlap : RenderLayer::IndirectCompositingReason::None;
}
#if ENABLE(VIDEO)
@@ -1091,30 +1309,41 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor
// RenderLayer children and whose children can't use its backing to render
// into. These children (the controls) always need to be promoted into their
// own layers to draw on top of the accelerated video.
- if (compositingState.m_compositingAncestor && compositingState.m_compositingAncestor->renderer().isVideo())
- compositingReason = RenderLayer::IndirectCompositingForOverlap;
+ if (compositingState.compositingAncestor && compositingState.compositingAncestor->renderer().isVideo())
+ compositingReason = RenderLayer::IndirectCompositingReason::Overlap;
#endif
layer.setIndirectCompositingReason(compositingReason);
+ // Check if the computed indirect reason will force the layer to become composited.
+ if (!willBeComposited && layer.mustCompositeForIndirectReasons() && canBeComposited(layer))
+ willBeComposited = true;
+ ASSERT(willBeComposited == needsToBeComposited(layer));
+
// The children of this layer don't need to composite, unless there is
// a compositing layer among them, so start by inheriting the compositing
- // ancestor with m_subtreeIsCompositing set to false.
+ // ancestor with subtreeIsCompositing set to false.
CompositingState childState(compositingState);
- childState.m_subtreeIsCompositing = false;
+ childState.subtreeIsCompositing = false;
+#if ENABLE(CSS_COMPOSITING)
+ childState.hasNotIsolatedCompositedBlendingDescendants = false;
+#endif
- bool willBeComposited = needsToBeComposited(layer);
if (willBeComposited) {
// Tell the parent it has compositing descendants.
- compositingState.m_subtreeIsCompositing = true;
+ compositingState.subtreeIsCompositing = true;
// This layer now acts as the ancestor for kids.
- childState.m_compositingAncestor = &layer;
+ childState.compositingAncestor = &layer;
- if (overlapMap)
- overlapMap->pushCompositingContainer();
+ overlapMap.pushCompositingContainer();
// This layer is going to be composited, so children can safely ignore the fact that there's an
// animation running behind this layer, meaning they can rely on the overlap map testing again.
- childState.m_testingOverlap = true;
+ childState.testingOverlap = true;
+
+ computeExtent(overlapMap, layer, layerExtent);
+ childState.ancestorHasTransformAnimation |= layerExtent.hasTransformAnimation;
+ // Too hard to compute animated bounds if both us and some ancestor is animating transform.
+ layerExtent.animationCausesExtentUncertainty |= layerExtent.hasTransformAnimation && compositingState.ancestorHasTransformAnimation;
}
#if !ASSERT_DISABLED
@@ -1125,20 +1354,19 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor
if (layer.isStackingContainer()) {
if (Vector<RenderLayer*>* negZOrderList = layer.negZOrderList()) {
- for (size_t i = 0, size = negZOrderList->size(); i < size; ++i) {
- computeCompositingRequirements(&layer, *negZOrderList->at(i), overlapMap, childState, layersChanged, anyDescendantHas3DTransform);
+ for (auto* renderLayer : *negZOrderList) {
+ computeCompositingRequirements(&layer, *renderLayer, overlapMap, childState, layersChanged, anyDescendantHas3DTransform);
// If we have to make a layer for this child, make one now so we can have a contents layer
// (since we need to ensure that the -ve z-order child renders underneath our contents).
- if (!willBeComposited && childState.m_subtreeIsCompositing) {
+ if (!willBeComposited && childState.subtreeIsCompositing) {
// make layer compositing
- layer.setIndirectCompositingReason(RenderLayer::IndirectCompositingForBackgroundLayer);
- childState.m_compositingAncestor = &layer;
- if (overlapMap)
- overlapMap->pushCompositingContainer();
+ layer.setIndirectCompositingReason(RenderLayer::IndirectCompositingReason::BackgroundLayer);
+ childState.compositingAncestor = &layer;
+ overlapMap.pushCompositingContainer();
// This layer is going to be composited, so children can safely ignore the fact that there's an
// animation running behind this layer, meaning they can rely on the overlap map testing again
- childState.m_testingOverlap = true;
+ childState.testingOverlap = true;
willBeComposited = true;
}
}
@@ -1150,19 +1378,19 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor
// anonymous RenderRegion, but first we need to make sure that the parent itself of the region is going to
// have a composited layer. We only want to make regions composited when there's an actual layer that we
// need to move to that region.
- computeRegionCompositingRequirements(toRenderBlockFlow(layer.renderer()).renderNamedFlowFragment(), overlapMap, childState, layersChanged, anyDescendantHas3DTransform);
+ computeRegionCompositingRequirements(downcast<RenderBlockFlow>(layer.renderer()).renderNamedFlowFragment(), overlapMap, childState, layersChanged, anyDescendantHas3DTransform);
}
if (Vector<RenderLayer*>* normalFlowList = layer.normalFlowList()) {
- for (size_t i = 0, size = normalFlowList->size(); i < size; ++i)
- computeCompositingRequirements(&layer, *normalFlowList->at(i), overlapMap, childState, layersChanged, anyDescendantHas3DTransform);
+ for (auto* renderLayer : *normalFlowList)
+ computeCompositingRequirements(&layer, *renderLayer, overlapMap, childState, layersChanged, anyDescendantHas3DTransform);
}
if (layer.isStackingContainer()) {
if (Vector<RenderLayer*>* posZOrderList = layer.posZOrderList()) {
- for (size_t i = 0, size = posZOrderList->size(); i < size; ++i)
- computeCompositingRequirements(&layer, *posZOrderList->at(i), overlapMap, childState, layersChanged, anyDescendantHas3DTransform);
+ for (auto* renderLayer : *posZOrderList)
+ computeCompositingRequirements(&layer, *renderLayer, overlapMap, childState, layersChanged, anyDescendantHas3DTransform);
}
}
@@ -1175,75 +1403,75 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor
willBeComposited = true;
}
- // If the layer composited for other reasons than blending, it is no longer needed to keep track of whether a child was blended.
- if (compositingState.m_subtreeHasBlending && !layer.hasBlendMode())
- compositingState.m_subtreeHasBlending = false;
-
ASSERT(willBeComposited == needsToBeComposited(layer));
// All layers (even ones that aren't being composited) need to get added to
// the overlap map. Layers that do not composite will draw into their
// compositing ancestor's backing, and so are still considered for overlap.
- if (overlapMap && childState.m_compositingAncestor && !childState.m_compositingAncestor->isRootLayer())
- addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds);
-
- if (childState.m_subtreeHasBlending || layer.hasBlendMode())
- compositingState.m_subtreeHasBlending = true;
+ // FIXME: When layerExtent has taken animation bounds into account, we also know that the bounds
+ // include descendants, so we don't need to add them all to the overlap map.
+ if (childState.compositingAncestor && !childState.compositingAncestor->isRootLayer())
+ addToOverlapMap(overlapMap, layer, layerExtent);
+#if ENABLE(CSS_COMPOSITING)
+ layer.setHasNotIsolatedCompositedBlendingDescendants(childState.hasNotIsolatedCompositedBlendingDescendants);
+ ASSERT(!layer.hasNotIsolatedCompositedBlendingDescendants() || layer.hasNotIsolatedBlendingDescendants());
+#endif
// Now check for reasons to become composited that depend on the state of descendant layers.
RenderLayer::IndirectCompositingReason indirectCompositingReason;
if (!willBeComposited && canBeComposited(layer)
- && requiresCompositingForIndirectReason(layer.renderer(), childState.m_subtreeIsCompositing, compositingState.m_subtreeHasBlending, anyDescendantHas3DTransform, indirectCompositingReason)) {
+ && requiresCompositingForIndirectReason(layer.renderer(), childState.subtreeIsCompositing, anyDescendantHas3DTransform, indirectCompositingReason)) {
layer.setIndirectCompositingReason(indirectCompositingReason);
- childState.m_compositingAncestor = &layer;
- if (overlapMap) {
- overlapMap->pushCompositingContainer();
- addToOverlapMapRecursive(*overlapMap, layer);
- }
+ childState.compositingAncestor = &layer;
+ overlapMap.pushCompositingContainer();
+ addToOverlapMapRecursive(overlapMap, layer);
willBeComposited = true;
}
ASSERT(willBeComposited == needsToBeComposited(layer));
if (layer.reflectionLayer()) {
// FIXME: Shouldn't we call computeCompositingRequirements to handle a reflection overlapping with another renderer?
- layer.reflectionLayer()->setIndirectCompositingReason(willBeComposited ? RenderLayer::IndirectCompositingForStacking : RenderLayer::NoIndirectCompositingReason);
+ layer.reflectionLayer()->setIndirectCompositingReason(willBeComposited ? RenderLayer::IndirectCompositingReason::Stacking : RenderLayer::IndirectCompositingReason::None);
}
// Subsequent layers in the parent stacking context also need to composite.
- if (childState.m_subtreeIsCompositing)
- compositingState.m_subtreeIsCompositing = true;
+ if (childState.subtreeIsCompositing)
+ compositingState.subtreeIsCompositing = true;
- // Set the flag to say that this SC has compositing children.
- layer.setHasCompositingDescendant(childState.m_subtreeIsCompositing);
+ // Set the flag to say that this layer has compositing children.
+ layer.setHasCompositingDescendant(childState.subtreeIsCompositing);
- // setHasCompositingDescendant() may have changed the answer to needsToBeComposited() when clipping,
- // so test that again.
+ // setHasCompositingDescendant() may have changed the answer to needsToBeComposited() when clipping, so test that again.
bool isCompositedClippingLayer = canBeComposited(layer) && clipsCompositingDescendants(layer);
// Turn overlap testing off for later layers if it's already off, or if we have an animating transform.
// Note that if the layer clips its descendants, there's no reason to propagate the child animation to the parent layers. That's because
// we know for sure the animation is contained inside the clipping rectangle, which is already added to the overlap map.
- if ((!childState.m_testingOverlap && !isCompositedClippingLayer) || isRunningAcceleratedTransformAnimation(layer.renderer()))
- compositingState.m_testingOverlap = false;
+ if ((!childState.testingOverlap && !isCompositedClippingLayer) || layerExtent.knownToBeHaveExtentUncertainty())
+ compositingState.testingOverlap = false;
if (isCompositedClippingLayer) {
if (!willBeComposited) {
- childState.m_compositingAncestor = &layer;
- if (overlapMap) {
- overlapMap->pushCompositingContainer();
- addToOverlapMapRecursive(*overlapMap, layer);
- }
+ childState.compositingAncestor = &layer;
+ overlapMap.pushCompositingContainer();
+ addToOverlapMapRecursive(overlapMap, layer);
willBeComposited = true;
}
}
- if (overlapMap && childState.m_compositingAncestor == &layer && !layer.isRootLayer())
- overlapMap->popCompositingContainer();
+#if ENABLE(CSS_COMPOSITING)
+ if ((willBeComposited && layer.hasBlendMode())
+ || (layer.hasNotIsolatedCompositedBlendingDescendants() && !layer.isolatesCompositedBlending()))
+ compositingState.hasNotIsolatedCompositedBlendingDescendants = true;
+#endif
+
+ if (childState.compositingAncestor == &layer && !layer.isRootLayer())
+ overlapMap.popCompositingContainer();
// If we're back at the root, and no other layers need to be composited, and the root layer itself doesn't need
// to be composited, then we can drop out of compositing mode altogether. However, don't drop out of compositing mode
// if there are composited layers that we didn't hit in our traversal (e.g. because of visibility:hidden).
- if (layer.isRootLayer() && !childState.m_subtreeIsCompositing && !requiresCompositingLayer(layer) && !m_forceCompositingMode && !hasAnyAdditionalCompositedLayers(layer)) {
+ if (layer.isRootLayer() && !childState.subtreeIsCompositing && !requiresCompositingLayer(layer) && !m_forceCompositingMode && !hasAnyAdditionalCompositedLayers(layer)) {
// Don't drop out of compositing on iOS, because we may flash. See <rdar://problem/8348337>.
#if !PLATFORM(IOS)
enableCompositingMode(false);
@@ -1251,13 +1479,10 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor
#endif
}
- // If the layer is going into compositing mode, repaint its old location.
ASSERT(willBeComposited == needsToBeComposited(layer));
- if (!layer.isComposited() && willBeComposited)
- repaintOnCompositingChange(layer);
// Update backing now, so that we can use isComposited() reliably during tree traversal in rebuildCompositingLayerTree().
- if (updateBacking(layer, CompositingChangeRepaintNow))
+ if (updateBacking(layer, CompositingChangeRepaintNow, willBeComposited ? BackingRequired::Yes : BackingRequired::No))
layersChanged = true;
if (layer.reflectionLayer() && updateLayerCompositingState(*layer.reflectionLayer(), CompositingChangeRepaintNow))
@@ -1265,30 +1490,26 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor
descendantHas3DTransform |= anyDescendantHas3DTransform || layer.has3DTransform();
- if (overlapMap)
- overlapMap->geometryMap().popMappingsToAncestor(ancestorLayer);
+ overlapMap.geometryMap().popMappingsToAncestor(ancestorLayer);
}
-void RenderLayerCompositor::computeRegionCompositingRequirements(RenderNamedFlowFragment* region, OverlapMap* overlapMap, CompositingState& childState, bool& layersChanged, bool& anyDescendantHas3DTransform)
+void RenderLayerCompositor::computeRegionCompositingRequirements(RenderNamedFlowFragment* region, OverlapMap& overlapMap, CompositingState& childState, bool& layersChanged, bool& anyDescendantHas3DTransform)
{
if (!region->isValid())
return;
RenderFlowThread* flowThread = region->flowThread();
- if (overlapMap)
- overlapMap->geometryMap().pushRenderFlowThread(flowThread);
+ overlapMap.geometryMap().pushRenderFlowThread(flowThread);
if (const RenderLayerList* layerList = flowThread->getLayerListForRegion(region)) {
- for (size_t i = 0, listSize = layerList->size(); i < listSize; ++i) {
- RenderLayer& curLayer = *layerList->at(i);
- ASSERT(flowThread->regionForCompositedLayer(curLayer) == region);
- computeCompositingRequirements(flowThread->layer(), curLayer, overlapMap, childState, layersChanged, anyDescendantHas3DTransform);
+ for (auto* renderLayer : *layerList) {
+ ASSERT(flowThread->regionForCompositedLayer(*renderLayer) == region);
+ computeCompositingRequirements(flowThread->layer(), *renderLayer, overlapMap, childState, layersChanged, anyDescendantHas3DTransform);
}
}
- if (overlapMap)
- overlapMap->geometryMap().popMappingsToAncestor(&region->layerOwner());
+ overlapMap.geometryMap().popMappingsToAncestor(&region->layerOwner());
}
void RenderLayerCompositor::setCompositingParent(RenderLayer& childLayer, RenderLayer* parentLayer)
@@ -1339,10 +1560,8 @@ void RenderLayerCompositor::rebuildCompositingLayerTreeForNamedFlowFixed(RenderL
Vector<RenderLayer*> fixedLayers;
layer.renderer().view().flowThreadController().collectFixedPositionedLayers(fixedLayers);
- for (size_t i = 0; i < fixedLayers.size(); ++i) {
- RenderLayer* fixedLayer = fixedLayers.at(i);
+ for (auto* fixedLayer : fixedLayers)
rebuildCompositingLayerTree(*fixedLayer, childGraphicsLayersOfEnclosingLayer, depth);
- }
}
void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer& layer, Vector<GraphicsLayer*>& childLayersOfEnclosingLayer, int depth)
@@ -1366,10 +1585,10 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer& layer, Vect
reflection->backing()->updateCompositedBounds();
}
- if (layerBacking->updateGraphicsLayerConfiguration())
+ if (layerBacking->updateConfiguration())
layerBacking->updateDebugIndicators(m_showDebugBorders, m_showRepaintCounter);
- layerBacking->updateGraphicsLayerGeometry();
+ layerBacking->updateGeometry();
if (!layer.parent())
updateRootLayerPosition();
@@ -1394,8 +1613,8 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer& layer, Vect
if (layer.isStackingContainer()) {
if (Vector<RenderLayer*>* negZOrderList = layer.negZOrderList()) {
- for (size_t i = 0, size = negZOrderList->size(); i < size; ++i)
- rebuildCompositingLayerTree(*negZOrderList->at(i), childList, depth + 1);
+ for (auto* renderLayer : *negZOrderList)
+ rebuildCompositingLayerTree(*renderLayer, childList, depth + 1);
}
// If a negative z-order child is compositing, we get a foreground layer which needs to get parented.
@@ -1404,17 +1623,17 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer& layer, Vect
}
if (layer.renderer().isRenderNamedFlowFragmentContainer())
- rebuildRegionCompositingLayerTree(toRenderBlockFlow(layer.renderer()).renderNamedFlowFragment(), layerChildren, depth + 1);
+ rebuildRegionCompositingLayerTree(downcast<RenderBlockFlow>(layer.renderer()).renderNamedFlowFragment(), layerChildren, depth + 1);
if (Vector<RenderLayer*>* normalFlowList = layer.normalFlowList()) {
- for (size_t i = 0, size = normalFlowList->size(); i < size; ++i)
- rebuildCompositingLayerTree(*normalFlowList->at(i), childList, depth + 1);
+ for (auto* renderLayer : *normalFlowList)
+ rebuildCompositingLayerTree(*renderLayer, childList, depth + 1);
}
if (layer.isStackingContainer()) {
if (Vector<RenderLayer*>* posZOrderList = layer.posZOrderList()) {
- for (size_t i = 0, size = posZOrderList->size(); i < size; ++i)
- rebuildCompositingLayerTree(*posZOrderList->at(i), childList, depth + 1);
+ for (auto* renderLayer : *posZOrderList)
+ rebuildCompositingLayerTree(*renderLayer, childList, depth + 1);
}
}
@@ -1423,8 +1642,8 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer& layer, Vect
if (layerBacking) {
bool parented = false;
- if (layer.renderer().isWidget())
- parented = parentFrameContentLayers(toRenderWidget(&layer.renderer()));
+ if (is<RenderWidget>(layer.renderer()))
+ parented = parentFrameContentLayers(&downcast<RenderWidget>(layer.renderer()));
if (!parented)
layerBacking->parentForSublayers()->setChildren(layerChildren);
@@ -1450,6 +1669,9 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer& layer, Vect
childLayersOfEnclosingLayer.append(layerBacking->childForSuperlayers());
}
+
+ if (RenderLayerBacking* layerBacking = layer.backing())
+ layerBacking->updateAfterDescendants();
}
void RenderLayerCompositor::rebuildRegionCompositingLayerTree(RenderNamedFlowFragment* region, Vector<GraphicsLayer*>& childList, int depth)
@@ -1460,10 +1682,9 @@ void RenderLayerCompositor::rebuildRegionCompositingLayerTree(RenderNamedFlowFra
RenderFlowThread* flowThread = region->flowThread();
ASSERT(flowThread->collectsGraphicsLayersUnderRegions());
if (const RenderLayerList* layerList = flowThread->getLayerListForRegion(region)) {
- for (size_t i = 0, listSize = layerList->size(); i < listSize; ++i) {
- RenderLayer& curLayer = *layerList->at(i);
- ASSERT(flowThread->regionForCompositedLayer(curLayer) == region);
- rebuildCompositingLayerTree(curLayer, childList, depth + 1);
+ for (auto* renderLayer : *layerList) {
+ ASSERT(flowThread->regionForCompositedLayer(*renderLayer) == region);
+ rebuildCompositingLayerTree(*renderLayer, childList, depth + 1);
}
}
}
@@ -1478,14 +1699,17 @@ void RenderLayerCompositor::frameViewDidChangeSize()
{
if (m_clipLayer) {
const FrameView& frameView = m_renderView.frameView();
- m_clipLayer->setSize(frameView.unscaledVisibleContentSize());
+ m_clipLayer->setSize(frameView.sizeForVisibleContent());
+ m_clipLayer->setPosition(positionForClipLayer());
frameViewDidScroll();
updateOverflowControlsLayers();
#if ENABLE(RUBBER_BANDING)
- if (m_layerForOverhangAreas)
+ if (m_layerForOverhangAreas) {
m_layerForOverhangAreas->setSize(frameView.frameRect().size());
+ m_layerForOverhangAreas->setPosition(FloatPoint(0, m_renderView.frameView().topContentInset()));
+ }
#endif
}
}
@@ -1493,7 +1717,7 @@ void RenderLayerCompositor::frameViewDidChangeSize()
bool RenderLayerCompositor::hasCoordinatedScrolling() const
{
ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
- return scrollingCoordinator && scrollingCoordinator->coordinatesScrollingForFrameView(&m_renderView.frameView());
+ return scrollingCoordinator && scrollingCoordinator->coordinatesScrollingForFrameView(m_renderView.frameView());
}
void RenderLayerCompositor::updateScrollLayerPosition()
@@ -1503,16 +1727,19 @@ void RenderLayerCompositor::updateScrollLayerPosition()
FrameView& frameView = m_renderView.frameView();
IntPoint scrollPosition = frameView.scrollPosition();
- const Settings& settings = m_renderView.frameView().frame().settings();
- if (settings.compositedScrollingForFramesEnabled()) {
- if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->scrollableAreaScrollLayerDidChange(&frameView);
- }
-
m_scrollLayer->setPosition(FloatPoint(-scrollPosition.x(), -scrollPosition.y()));
if (GraphicsLayer* fixedBackgroundLayer = fixedRootBackgroundLayer())
- fixedBackgroundLayer->setPosition(IntPoint(frameView.scrollOffsetForFixedPosition()));
+ fixedBackgroundLayer->setPosition(frameView.scrollPositionForFixedPosition());
+}
+
+FloatPoint RenderLayerCompositor::positionForClipLayer() const
+{
+ FrameView& frameView = m_renderView.frameView();
+
+ return FloatPoint(
+ frameView.shouldPlaceBlockDirectionScrollbarOnLeft() ? frameView.horizontalScrollbarIntrusion() : 0,
+ FrameView::yPositionForInsetClipLayer(frameView.scrollPosition(), frameView.topContentInset()));
}
void RenderLayerCompositor::frameViewDidScroll()
@@ -1546,28 +1773,23 @@ void RenderLayerCompositor::frameViewDidLayout()
void RenderLayerCompositor::rootFixedBackgroundsChanged()
{
RenderLayerBacking* renderViewBacking = m_renderView.layer()->backing();
- if (renderViewBacking && renderViewBacking->usingTiledBacking())
+ if (renderViewBacking && renderViewBacking->isMainFrameLayerWithTiledBacking())
setCompositingLayersNeedRebuild();
}
void RenderLayerCompositor::scrollingLayerDidChange(RenderLayer& layer)
{
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->scrollableAreaScrollLayerDidChange(&layer);
+ scrollingCoordinator->scrollableAreaScrollLayerDidChange(layer);
}
void RenderLayerCompositor::fixedRootBackgroundLayerChanged()
{
- if (m_renderView.documentBeingDestroyed())
+ if (m_renderView.renderTreeBeingDestroyed())
return;
- if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
- RenderLayerBacking* renderViewBacking = m_renderView.layer()->backing();
- if (!renderViewBacking)
- return;
-
- scrollingCoordinator->updateScrollingNode(renderViewBacking->scrollLayerID(), scrollLayer(), fixedRootBackgroundLayer());
- }
+ if (m_renderView.layer()->isComposited())
+ updateScrollCoordinatedStatus(*m_renderView.layer());
}
String RenderLayerCompositor::layerTreeAsText(LayerTreeFlags flags)
@@ -1592,6 +1814,8 @@ String RenderLayerCompositor::layerTreeAsText(LayerTreeFlags flags)
layerTreeBehavior |= LayerTreeAsTextIncludePaintingPhases;
if (flags & LayerTreeFlagsIncludeContentLayers)
layerTreeBehavior |= LayerTreeAsTextIncludeContentLayers;
+ if (flags & LayerTreeFlagsIncludeAcceleratesDrawing)
+ layerTreeBehavior |= LayerTreeAsTextIncludeAcceleratesDrawing;
// We skip dumping the scroll and clip layers to keep layerTreeAsText output
// similar between platforms.
@@ -1599,16 +1823,13 @@ String RenderLayerCompositor::layerTreeAsText(LayerTreeFlags flags)
// Dump an empty layer tree only if the only composited layer is the main frame's tiled backing,
// so that tests expecting us to drop out of accelerated compositing when there are no layers succeed.
- if (!hasAnyAdditionalCompositedLayers(rootRenderLayer()) && mainFrameBackingIsTiled() && !(layerTreeBehavior & LayerTreeAsTextIncludeTileCaches))
- layerTreeText = "";
+ if (!hasAnyAdditionalCompositedLayers(rootRenderLayer()) && documentUsesTiledBacking() && !(layerTreeBehavior & LayerTreeAsTextIncludeTileCaches))
+ layerTreeText = emptyString();
// The true root layer is not included in the dump, so if we want to report
// its repaint rects, they must be included here.
- if (flags & LayerTreeFlagsIncludeRepaintRects) {
- String layerTreeTextWithRootRepaintRects = m_renderView.frameView().trackedRepaintRectsAsText();
- layerTreeTextWithRootRepaintRects.append(layerTreeText);
- return layerTreeTextWithRootRepaintRects;
- }
+ if (flags & LayerTreeFlagsIncludeRepaintRects)
+ return m_renderView.frameView().trackedRepaintRectsAsText() + layerTreeText;
return layerTreeText;
}
@@ -1619,7 +1840,7 @@ RenderLayerCompositor* RenderLayerCompositor::frameContentsCompositor(RenderWidg
if (RenderView* view = contentDocument->renderView())
return &view->compositor();
}
- return 0;
+ return nullptr;
}
bool RenderLayerCompositor::parentFrameContentLayers(RenderWidget* renderer)
@@ -1655,8 +1876,8 @@ void RenderLayerCompositor::updateLayerTreeGeometry(RenderLayer& layer, int dept
reflection->backing()->updateCompositedBounds();
}
- layerBacking->updateGraphicsLayerConfiguration();
- layerBacking->updateGraphicsLayerGeometry();
+ layerBacking->updateConfiguration();
+ layerBacking->updateGeometry();
if (!layer.parent())
updateRootLayerPosition();
@@ -1674,22 +1895,25 @@ void RenderLayerCompositor::updateLayerTreeGeometry(RenderLayer& layer, int dept
if (layer.isStackingContainer()) {
if (Vector<RenderLayer*>* negZOrderList = layer.negZOrderList()) {
- for (size_t i = 0, size = negZOrderList->size(); i < size; ++i)
- updateLayerTreeGeometry(*negZOrderList->at(i), depth + 1);
+ for (auto* renderLayer : *negZOrderList)
+ updateLayerTreeGeometry(*renderLayer, depth + 1);
}
}
if (Vector<RenderLayer*>* normalFlowList = layer.normalFlowList()) {
- for (size_t i = 0, size = normalFlowList->size(); i < size; ++i)
- updateLayerTreeGeometry(*normalFlowList->at(i), depth + 1);
+ for (auto* renderLayer : *normalFlowList)
+ updateLayerTreeGeometry(*renderLayer, depth + 1);
}
if (layer.isStackingContainer()) {
if (Vector<RenderLayer*>* posZOrderList = layer.posZOrderList()) {
- for (size_t i = 0, size = posZOrderList->size(); i < size; ++i)
- updateLayerTreeGeometry(*posZOrderList->at(i), depth + 1);
+ for (auto* renderLayer : *posZOrderList)
+ updateLayerTreeGeometry(*renderLayer, depth + 1);
}
}
+
+ if (RenderLayerBacking* layerBacking = layer.backing())
+ layerBacking->updateAfterDescendants();
}
// Recurs down the RenderLayer tree until its finds the compositing descendants of compositingAncestor and updates their geometry.
@@ -1704,9 +1928,11 @@ void RenderLayerCompositor::updateCompositingDescendantGeometry(RenderLayer& com
reflection->backing()->updateCompositedBounds();
}
- layerBacking->updateGraphicsLayerGeometry();
- if (compositedChildrenOnly)
+ layerBacking->updateGeometry();
+ if (compositedChildrenOnly) {
+ layerBacking->updateAfterDescendants();
return;
+ }
}
}
@@ -1722,42 +1948,39 @@ void RenderLayerCompositor::updateCompositingDescendantGeometry(RenderLayer& com
if (layer.isStackingContainer()) {
if (Vector<RenderLayer*>* negZOrderList = layer.negZOrderList()) {
- size_t listSize = negZOrderList->size();
- for (size_t i = 0; i < listSize; ++i)
- updateCompositingDescendantGeometry(compositingAncestor, *negZOrderList->at(i), compositedChildrenOnly);
+ for (auto* renderLayer : *negZOrderList)
+ updateCompositingDescendantGeometry(compositingAncestor, *renderLayer, compositedChildrenOnly);
}
}
if (Vector<RenderLayer*>* normalFlowList = layer.normalFlowList()) {
- size_t listSize = normalFlowList->size();
- for (size_t i = 0; i < listSize; ++i)
- updateCompositingDescendantGeometry(compositingAncestor, *normalFlowList->at(i), compositedChildrenOnly);
+ for (auto* renderLayer : *normalFlowList)
+ updateCompositingDescendantGeometry(compositingAncestor, *renderLayer, compositedChildrenOnly);
}
if (layer.isStackingContainer()) {
if (Vector<RenderLayer*>* posZOrderList = layer.posZOrderList()) {
- size_t listSize = posZOrderList->size();
- for (size_t i = 0; i < listSize; ++i)
- updateCompositingDescendantGeometry(compositingAncestor, *posZOrderList->at(i), compositedChildrenOnly);
+ for (auto* renderLayer : *posZOrderList)
+ updateCompositingDescendantGeometry(compositingAncestor, *renderLayer, compositedChildrenOnly);
}
}
+
+ if (&layer != &compositingAncestor) {
+ if (RenderLayerBacking* layerBacking = layer.backing())
+ layerBacking->updateAfterDescendants();
+ }
}
-
-void RenderLayerCompositor::repaintCompositedLayers(const IntRect* absRect)
+void RenderLayerCompositor::repaintCompositedLayers()
{
- recursiveRepaintLayer(rootRenderLayer(), absRect);
+ recursiveRepaintLayer(rootRenderLayer());
}
-void RenderLayerCompositor::recursiveRepaintLayer(RenderLayer& layer, const IntRect* rect)
+void RenderLayerCompositor::recursiveRepaintLayer(RenderLayer& layer)
{
// FIXME: This method does not work correctly with transforms.
- if (layer.isComposited() && !layer.backing()->paintsIntoCompositedAncestor()) {
- if (rect)
- layer.setBackingNeedsRepaintInRect(*rect);
- else
- layer.setBackingNeedsRepaint();
- }
+ if (layer.isComposited() && !layer.backing()->paintsIntoCompositedAncestor())
+ layer.setBackingNeedsRepaint();
#if !ASSERT_DISABLED
LayerListMutationDetector mutationChecker(&layer);
@@ -1765,39 +1988,18 @@ void RenderLayerCompositor::recursiveRepaintLayer(RenderLayer& layer, const IntR
if (layer.hasCompositingDescendant()) {
if (Vector<RenderLayer*>* negZOrderList = layer.negZOrderList()) {
- for (size_t i = 0, size = negZOrderList->size(); i < size; ++i) {
- RenderLayer& childLayer = *negZOrderList->at(i);
- if (rect) {
- IntRect childRect(*rect);
- childLayer.convertToPixelSnappedLayerCoords(&layer, childRect);
- recursiveRepaintLayer(childLayer, &childRect);
- } else
- recursiveRepaintLayer(childLayer);
- }
+ for (auto* renderLayer : *negZOrderList)
+ recursiveRepaintLayer(*renderLayer);
}
if (Vector<RenderLayer*>* posZOrderList = layer.posZOrderList()) {
- for (size_t i = 0, size = posZOrderList->size(); i < size; ++i) {
- RenderLayer& childLayer = *posZOrderList->at(i);
- if (rect) {
- IntRect childRect(*rect);
- childLayer.convertToPixelSnappedLayerCoords(&layer, childRect);
- recursiveRepaintLayer(childLayer, &childRect);
- } else
- recursiveRepaintLayer(childLayer);
- }
+ for (auto* renderLayer : *posZOrderList)
+ recursiveRepaintLayer(*renderLayer);
}
}
if (Vector<RenderLayer*>* normalFlowList = layer.normalFlowList()) {
- for (size_t i = 0, size = normalFlowList->size(); i < size; ++i) {
- RenderLayer& childLayer = *normalFlowList->at(i);
- if (rect) {
- IntRect childRect(*rect);
- childLayer.convertToPixelSnappedLayerCoords(&layer, childRect);
- recursiveRepaintLayer(childLayer, &childRect);
- } else
- recursiveRepaintLayer(childLayer);
- }
+ for (auto* renderLayer : *normalFlowList)
+ recursiveRepaintLayer(*renderLayer);
}
}
@@ -1818,6 +2020,16 @@ GraphicsLayer* RenderLayerCompositor::scrollLayer() const
return m_scrollLayer.get();
}
+GraphicsLayer* RenderLayerCompositor::clipLayer() const
+{
+ return m_clipLayer.get();
+}
+
+GraphicsLayer* RenderLayerCompositor::rootContentLayer() const
+{
+ return m_rootContentLayer.get();
+}
+
#if ENABLE(RUBBER_BANDING)
GraphicsLayer* RenderLayerCompositor::headerLayer() const
{
@@ -1830,25 +2042,24 @@ GraphicsLayer* RenderLayerCompositor::footerLayer() const
}
#endif
-TiledBacking* RenderLayerCompositor::pageTiledBacking() const
-{
- RenderLayerBacking* renderViewBacking = m_renderView.layer()->backing();
- return renderViewBacking ? renderViewBacking->tiledBacking() : nullptr;
-}
-
void RenderLayerCompositor::setIsInWindow(bool isInWindow)
{
- if (TiledBacking* tiledBacking = pageTiledBacking())
- tiledBacking->setIsInWindow(isInWindow);
+ LOG(Compositing, "RenderLayerCompositor %p setIsInWindow %d", this, isInWindow);
if (!inCompositingMode())
return;
+ if (GraphicsLayer* rootLayer = rootGraphicsLayer()) {
+ GraphicsLayer::traverse(*rootLayer, [isInWindow](GraphicsLayer& layer) {
+ layer.setIsInWindow(isInWindow);
+ });
+ }
+
if (isInWindow) {
if (m_rootLayerAttachment != RootLayerUnattached)
return;
- RootLayerAttachment attachment = shouldPropagateCompositingToEnclosingFrame() ? RootLayerAttachedViaEnclosingFrame : RootLayerAttachedViaChromeClient;
+ RootLayerAttachment attachment = isMainFrameCompositor() ? RootLayerAttachedViaChromeClient : RootLayerAttachedViaEnclosingFrame;
attachRootLayer(attachment);
#if PLATFORM(IOS)
registerAllViewportConstrainedLayers();
@@ -1869,7 +2080,7 @@ void RenderLayerCompositor::setIsInWindow(bool isInWindow)
void RenderLayerCompositor::clearBackingForLayerIncludingDescendants(RenderLayer& layer)
{
if (layer.isComposited()) {
- removeViewportConstrainedLayer(layer);
+ removeFromScrollCoordinatedLayers(layer);
layer.clearBacking();
}
@@ -1885,12 +2096,14 @@ void RenderLayerCompositor::clearBackingForAllLayers()
void RenderLayerCompositor::updateRootLayerPosition()
{
if (m_rootContentLayer) {
- const IntRect& documentRect = m_renderView.documentRect();
- m_rootContentLayer->setSize(documentRect.size());
- m_rootContentLayer->setPosition(FloatPoint(documentRect.x(), documentRect.y() + m_renderView.frameView().headerHeight()));
+ m_rootContentLayer->setSize(m_renderView.frameView().contentsSize());
+ m_rootContentLayer->setPosition(m_renderView.frameView().positionForRootContentLayer());
+ m_rootContentLayer->setAnchorPoint(FloatPoint3D());
+ }
+ if (m_clipLayer) {
+ m_clipLayer->setSize(m_renderView.frameView().sizeForVisibleContent());
+ m_clipLayer->setPosition(positionForClipLayer());
}
- if (m_clipLayer)
- m_clipLayer->setSize(m_renderView.frameView().unscaledVisibleContentSize());
#if ENABLE(RUBBER_BANDING)
if (m_contentShadowLayer) {
@@ -1910,52 +2123,6 @@ bool RenderLayerCompositor::has3DContent() const
return layerHas3DContent(rootRenderLayer());
}
-bool RenderLayerCompositor::allowsIndependentlyCompositedFrames(const FrameView* view)
-{
-#if PLATFORM(MAC) && !PLATFORM(IOS)
- // frames are only independently composited in Mac pre-WebKit2.
- return view->platformWidget();
-#else
- UNUSED_PARAM(view);
-#endif
- return false;
-}
-
-bool RenderLayerCompositor::shouldPropagateCompositingToEnclosingFrame() const
-{
- // Parent document content needs to be able to render on top of a composited frame, so correct behavior
- // is to have the parent document become composited too. However, this can cause problems on platforms that
- // use native views for frames (like Mac), so disable that behavior on those platforms for now.
- HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement();
- RenderElement* renderer = ownerElement ? ownerElement->renderer() : 0;
-
- // If we are the top-level frame, don't propagate.
- if (!ownerElement)
- return false;
-
- if (!allowsIndependentlyCompositedFrames(&m_renderView.frameView()))
- return true;
-
- if (!renderer || !renderer->isWidget())
- return false;
-
- // On Mac, only propagate compositing if the frame is overlapped in the parent
- // document, or the parent is already compositing, or the main frame is scaled.
- Page* page = this->page();
- if (page && page->pageScaleFactor() != 1)
- return true;
-
- RenderWidget* frameRenderer = toRenderWidget(renderer);
- if (frameRenderer->widget()) {
- ASSERT(frameRenderer->widget()->isFrameView());
- FrameView* view = toFrameView(frameRenderer->widget());
- if (view->isOverlappedIncludingAncestors() || view->hasCompositingAncestor())
- return true;
- }
-
- return false;
-}
-
bool RenderLayerCompositor::needsToBeComposited(const RenderLayer& layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason) const
{
if (!canBeComposited(layer))
@@ -1969,28 +2136,24 @@ bool RenderLayerCompositor::needsToBeComposited(const RenderLayer& layer, Render
// static
bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer& layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason) const
{
- auto renderer = &layer.renderer();
-
- // The compositing state of a reflection should match that of its reflected layer.
- if (layer.isReflection())
- renderer = toRenderLayerModelObject(renderer->parent()); // The RenderReplica's parent is the object being reflected.
+ auto& renderer = rendererForCompositingTests(layer);
// The root layer always has a compositing layer, but it may not have backing.
- return requiresCompositingForTransform(*renderer)
- || requiresCompositingForVideo(*renderer)
- || requiresCompositingForCanvas(*renderer)
- || requiresCompositingForPlugin(*renderer)
- || requiresCompositingForFrame(*renderer)
- || (canRender3DTransforms() && renderer->style().backfaceVisibility() == BackfaceVisibilityHidden)
- || clipsCompositingDescendants(*renderer->layer())
- || requiresCompositingForAnimation(*renderer)
- || requiresCompositingForFilters(*renderer)
- || requiresCompositingForPosition(*renderer, *renderer->layer(), viewportConstrainedNotCompositedReason)
+ return requiresCompositingForTransform(renderer)
+ || requiresCompositingForVideo(renderer)
+ || requiresCompositingForCanvas(renderer)
+ || requiresCompositingForPlugin(renderer)
+ || requiresCompositingForFrame(renderer)
+ || requiresCompositingForBackfaceVisibility(renderer)
+ || clipsCompositingDescendants(*renderer.layer())
+ || requiresCompositingForAnimation(renderer)
+ || requiresCompositingForFilters(renderer)
+ || requiresCompositingForWillChange(renderer)
+ || requiresCompositingForPosition(renderer, *renderer.layer(), viewportConstrainedNotCompositedReason)
#if PLATFORM(IOS)
- || requiresCompositingForScrolling(*renderer)
+ || requiresCompositingForScrolling(*renderer.layer())
#endif
- || requiresCompositingForOverflowScrolling(*renderer->layer())
- || requiresCompositingForBlending(*renderer);
+ || requiresCompositingForOverflowScrolling(*renderer.layer());
}
bool RenderLayerCompositor::canBeComposited(const RenderLayer& layer) const
@@ -2004,13 +2167,12 @@ bool RenderLayerCompositor::canBeComposited(const RenderLayer& layer) const
if (layer.isRenderFlowThread())
return false;
- // A faster way of saying layer.enclosingFlowThreadLayer()->isFlowThreadCollectingGraphicsLayersUnderRegions()
- return layer.isInsideOutOfFlowThread();
+ return true;
}
return false;
}
-bool RenderLayerCompositor::requiresOwnBackingStore(const RenderLayer& layer, const RenderLayer* compositingAncestorLayer, const IntRect& layerCompositedBoundsInAncestor, const IntRect& ancestorCompositedBounds) const
+bool RenderLayerCompositor::requiresOwnBackingStore(const RenderLayer& layer, const RenderLayer* compositingAncestorLayer, const LayoutRect& layerCompositedBoundsInAncestor, const LayoutRect& ancestorCompositedBounds) const
{
auto& renderer = layer.renderer();
@@ -2026,30 +2188,30 @@ bool RenderLayerCompositor::requiresOwnBackingStore(const RenderLayer& layer, co
|| requiresCompositingForCanvas(renderer)
|| requiresCompositingForPlugin(renderer)
|| requiresCompositingForFrame(renderer)
- || (canRender3DTransforms() && renderer.style().backfaceVisibility() == BackfaceVisibilityHidden)
+ || requiresCompositingForBackfaceVisibility(renderer)
|| requiresCompositingForAnimation(renderer)
|| requiresCompositingForFilters(renderer)
- || requiresCompositingForBlending(renderer)
+ || requiresCompositingForWillChange(renderer)
|| requiresCompositingForPosition(renderer, layer)
|| requiresCompositingForOverflowScrolling(layer)
|| renderer.isTransparent()
|| renderer.hasMask()
|| renderer.hasReflection()
|| renderer.hasFilter()
+ || renderer.hasBackdropFilter()
#if PLATFORM(IOS)
- || requiresCompositingForScrolling(renderer)
+ || requiresCompositingForScrolling(layer)
#endif
)
return true;
-
-
+
if (layer.mustCompositeForIndirectReasons()) {
RenderLayer::IndirectCompositingReason reason = layer.indirectCompositingReason();
- return reason == RenderLayer::IndirectCompositingForOverlap
- || reason == RenderLayer::IndirectCompositingForStacking
- || reason == RenderLayer::IndirectCompositingForBackgroundLayer
- || reason == RenderLayer::IndirectCompositingForGraphicalEffect
- || reason == RenderLayer::IndirectCompositingForPreserve3D; // preserve-3d has to create backing store to ensure that 3d-transformed elements intersect.
+ return reason == RenderLayer::IndirectCompositingReason::Overlap
+ || reason == RenderLayer::IndirectCompositingReason::Stacking
+ || reason == RenderLayer::IndirectCompositingReason::BackgroundLayer
+ || reason == RenderLayer::IndirectCompositingReason::GraphicalEffect
+ || reason == RenderLayer::IndirectCompositingReason::Preserve3D; // preserve-3d has to create backing store to ensure that 3d-transformed elements intersect.
}
if (!ancestorCompositedBounds.contains(layerCompositedBoundsInAncestor))
@@ -2065,78 +2227,91 @@ CompositingReasons RenderLayerCompositor::reasonsForCompositing(const RenderLaye
if (!layer.isComposited())
return reasons;
- auto renderer = &layer.renderer();
- if (layer.isReflection())
- renderer = toRenderLayerModelObject(renderer->parent());
+ auto& renderer = rendererForCompositingTests(layer);
- if (requiresCompositingForTransform(*renderer))
+ if (requiresCompositingForTransform(renderer))
reasons |= CompositingReason3DTransform;
- if (requiresCompositingForVideo(*renderer))
+ if (requiresCompositingForVideo(renderer))
reasons |= CompositingReasonVideo;
- else if (requiresCompositingForCanvas(*renderer))
+ else if (requiresCompositingForCanvas(renderer))
reasons |= CompositingReasonCanvas;
- else if (requiresCompositingForPlugin(*renderer))
+ else if (requiresCompositingForPlugin(renderer))
reasons |= CompositingReasonPlugin;
- else if (requiresCompositingForFrame(*renderer))
+ else if (requiresCompositingForFrame(renderer))
reasons |= CompositingReasonIFrame;
- if ((canRender3DTransforms() && renderer->style().backfaceVisibility() == BackfaceVisibilityHidden))
+ if ((canRender3DTransforms() && renderer.style().backfaceVisibility() == BackfaceVisibilityHidden))
reasons |= CompositingReasonBackfaceVisibilityHidden;
- if (clipsCompositingDescendants(*renderer->layer()))
+ if (clipsCompositingDescendants(*renderer.layer()))
reasons |= CompositingReasonClipsCompositingDescendants;
- if (requiresCompositingForAnimation(*renderer))
+ if (requiresCompositingForAnimation(renderer))
reasons |= CompositingReasonAnimation;
- if (requiresCompositingForFilters(*renderer))
+ if (requiresCompositingForFilters(renderer))
reasons |= CompositingReasonFilters;
- if (requiresCompositingForBlending(*renderer))
- reasons |= CompositingReasonBlending;
+ if (requiresCompositingForWillChange(renderer))
+ reasons |= CompositingReasonWillChange;
- if (requiresCompositingForPosition(*renderer, *renderer->layer()))
- reasons |= renderer->style().position() == FixedPosition ? CompositingReasonPositionFixed : CompositingReasonPositionSticky;
+ if (requiresCompositingForPosition(renderer, *renderer.layer()))
+ reasons |= renderer.style().position() == FixedPosition ? CompositingReasonPositionFixed : CompositingReasonPositionSticky;
#if PLATFORM(IOS)
- if (requiresCompositingForScrolling(*renderer))
+ if (requiresCompositingForScrolling(*renderer.layer()))
reasons |= CompositingReasonOverflowScrollingTouch;
#endif
- if (requiresCompositingForOverflowScrolling(*renderer->layer()))
+ if (requiresCompositingForOverflowScrolling(*renderer.layer()))
reasons |= CompositingReasonOverflowScrollingTouch;
- if (renderer->layer()->indirectCompositingReason() == RenderLayer::IndirectCompositingForStacking)
+ switch (renderer.layer()->indirectCompositingReason()) {
+ case RenderLayer::IndirectCompositingReason::None:
+ break;
+ case RenderLayer::IndirectCompositingReason::Stacking:
reasons |= CompositingReasonStacking;
- else if (renderer->layer()->indirectCompositingReason() == RenderLayer::IndirectCompositingForOverlap)
+ break;
+ case RenderLayer::IndirectCompositingReason::Overlap:
reasons |= CompositingReasonOverlap;
- else if (renderer->layer()->indirectCompositingReason() == RenderLayer::IndirectCompositingForBackgroundLayer)
+ break;
+ case RenderLayer::IndirectCompositingReason::BackgroundLayer:
reasons |= CompositingReasonNegativeZIndexChildren;
- else if (renderer->layer()->indirectCompositingReason() == RenderLayer::IndirectCompositingForGraphicalEffect) {
- if (renderer->layer()->transform())
+ break;
+ case RenderLayer::IndirectCompositingReason::GraphicalEffect:
+ if (renderer.hasTransform())
reasons |= CompositingReasonTransformWithCompositedDescendants;
- if (renderer->isTransparent())
+ if (renderer.isTransparent())
reasons |= CompositingReasonOpacityWithCompositedDescendants;
- if (renderer->hasMask())
+ if (renderer.hasMask())
reasons |= CompositingReasonMaskWithCompositedDescendants;
- if (renderer->hasReflection())
+ if (renderer.hasReflection())
reasons |= CompositingReasonReflectionWithCompositedDescendants;
- if (renderer->hasFilter())
+ if (renderer.hasFilter() || renderer.hasBackdropFilter())
reasons |= CompositingReasonFilterWithCompositedDescendants;
-
- if (renderer->hasBlendMode())
+
+#if ENABLE(CSS_COMPOSITING)
+ if (layer.isolatesCompositedBlending())
+ reasons |= CompositingReasonIsolatesCompositedBlendingDescendants;
+
+ if (layer.hasBlendMode())
reasons |= CompositingReasonBlendingWithCompositedDescendants;
- } else if (renderer->layer()->indirectCompositingReason() == RenderLayer::IndirectCompositingForPerspective)
+#endif
+ break;
+ case RenderLayer::IndirectCompositingReason::Perspective:
reasons |= CompositingReasonPerspective;
- else if (renderer->layer()->indirectCompositingReason() == RenderLayer::IndirectCompositingForPreserve3D)
+ break;
+ case RenderLayer::IndirectCompositingReason::Preserve3D:
reasons |= CompositingReasonPreserve3D;
+ break;
+ }
- if (inCompositingMode() && renderer->layer()->isRootLayer())
+ if (inCompositingMode() && renderer.layer()->isRootLayer())
reasons |= CompositingReasonRoot;
return reasons;
@@ -2171,9 +2346,6 @@ const char* RenderLayerCompositor::logReasonsForCompositing(const RenderLayer& l
if (reasons & CompositingReasonFilters)
return "filters";
- if (reasons & CompositingReasonBlending)
- return "blending";
-
if (reasons & CompositingReasonPositionFixed)
return "position: fixed";
@@ -2206,10 +2378,15 @@ const char* RenderLayerCompositor::logReasonsForCompositing(const RenderLayer& l
if (reasons & CompositingReasonFilterWithCompositedDescendants)
return "filter with composited descendants";
-
+
+#if ENABLE(CSS_COMPOSITING)
if (reasons & CompositingReasonBlendingWithCompositedDescendants)
return "blending with composited descendants";
+ if (reasons & CompositingReasonIsolatesCompositedBlendingDescendants)
+ return "isolates composited blending descendants";
+#endif
+
if (reasons & CompositingReasonPerspective)
return "perspective";
@@ -2239,22 +2416,27 @@ bool RenderLayerCompositor::clippedByAncestor(RenderLayer& layer) const
// If the compositingAncestor clips, that will be taken care of by clipsCompositingDescendants(),
// so we only care about clipping between its first child that is our ancestor (the computeClipRoot),
- // and layer.
- RenderLayer* computeClipRoot = nullptr;
- RenderLayer* parent = &layer;
- while (parent) {
- RenderLayer* next = parent->parent();
- if (next == compositingAncestor) {
- computeClipRoot = parent;
- break;
+ // and layer. The exception is when the compositingAncestor isolates composited blending children,
+ // in this case it is not allowed to clipsCompositingDescendants() and each of its children
+ // will be clippedByAncestor()s, including the compositingAncestor.
+ RenderLayer* computeClipRoot = compositingAncestor;
+ if (!compositingAncestor->isolatesCompositedBlending()) {
+ computeClipRoot = nullptr;
+ RenderLayer* parent = &layer;
+ while (parent) {
+ RenderLayer* next = parent->parent();
+ if (next == compositingAncestor) {
+ computeClipRoot = parent;
+ break;
+ }
+ parent = next;
}
- parent = next;
+
+ if (!computeClipRoot || computeClipRoot == &layer)
+ return false;
}
-
- if (!computeClipRoot || computeClipRoot == &layer)
- return false;
- return layer.backgroundClipRect(RenderLayer::ClipRectsContext(computeClipRoot, 0, TemporaryClipRects)).rect() != LayoutRect::infiniteRect(); // FIXME: Incorrect for CSS regions.
+ return !layer.backgroundClipRect(RenderLayer::ClipRectsContext(computeClipRoot, TemporaryClipRects)).isInfinite(); // FIXME: Incorrect for CSS regions.
}
// Return true if the given layer is a stacking context and has compositing child
@@ -2262,20 +2444,19 @@ bool RenderLayerCompositor::clippedByAncestor(RenderLayer& layer) const
// into the hierarchy between this layer and its children in the z-order hierarchy.
bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer& layer) const
{
- return layer.hasCompositingDescendant() && layer.renderer().hasClipOrOverflowClip();
+ return layer.hasCompositingDescendant() && layer.renderer().hasClipOrOverflowClip() && !layer.isolatesCompositedBlending();
}
bool RenderLayerCompositor::requiresCompositingForScrollableFrame() const
{
- // Need this done first to determine overflow.
- ASSERT(!m_renderView.needsLayout());
- HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement();
- if (!ownerElement)
+ if (isMainFrameCompositor())
return false;
if (!(m_compositingTriggers & ChromeClient::ScrollableInnerFrameTrigger))
return false;
+ // Need this done first to determine overflow.
+ ASSERT(!m_renderView.needsLayout());
return m_renderView.frameView().isScrollable();
}
@@ -2289,28 +2470,34 @@ bool RenderLayerCompositor::requiresCompositingForTransform(RenderLayerModelObje
return renderer.hasTransform() && renderer.style().transform().has3DOperation();
}
+bool RenderLayerCompositor::requiresCompositingForBackfaceVisibility(RenderLayerModelObject& renderer) const
+{
+ if (!(m_compositingTriggers & ChromeClient::ThreeDTransformTrigger))
+ return false;
+
+ if (renderer.style().backfaceVisibility() != BackfaceVisibilityHidden)
+ return false;
+
+ if (renderer.layer()->has3DTransformedAncestor())
+ return true;
+
+ // FIXME: workaround for webkit.org/b/132801
+ RenderLayer* stackingContext = renderer.layer()->stackingContainer();
+ if (stackingContext && stackingContext->renderer().style().transformStyle3D() == TransformStyle3DPreserve3D)
+ return true;
+
+ return false;
+}
+
bool RenderLayerCompositor::requiresCompositingForVideo(RenderLayerModelObject& renderer) const
{
if (!(m_compositingTriggers & ChromeClient::VideoTrigger))
return false;
#if ENABLE(VIDEO)
- if (renderer.isVideo()) {
- RenderVideo& video = toRenderVideo(renderer);
+ if (is<RenderVideo>(renderer)) {
+ auto& video = downcast<RenderVideo>(renderer);
return (video.requiresImmediateCompositing() || video.shouldDisplayVideo()) && canAccelerateVideoRendering(video);
}
-#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
- if (renderer.isWidget()) {
- if (!m_hasAcceleratedCompositing)
- return false;
-
- Element* element = renderer.element();
- if (!element || (!isHTMLVideoElement(element) && !isHTMLAudioElement(element)))
- return false;
-
- HTMLMediaElement* mediaElement = toHTMLMediaElement(element);
- return mediaElement->player() ? mediaElement->player()->supportsAcceleratedRendering() : false;
- }
-#endif // ENABLE(PLUGIN_PROXY_FOR_VIDEO)
#else
UNUSED_PARAM(renderer);
#endif
@@ -2326,8 +2513,9 @@ bool RenderLayerCompositor::requiresCompositingForCanvas(RenderLayerModelObject&
#if USE(COMPOSITING_FOR_SMALL_CANVASES)
bool isCanvasLargeEnoughToForceCompositing = true;
#else
- HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer.element());
- bool isCanvasLargeEnoughToForceCompositing = canvas->size().area() >= canvasAreaThresholdRequiringCompositing;
+ HTMLCanvasElement* canvas = downcast<HTMLCanvasElement>(renderer.element());
+ auto canvasArea = canvas->size().area<RecordOverflow>();
+ bool isCanvasLargeEnoughToForceCompositing = !canvasArea.hasOverflowed() && canvasArea.unsafeGet() >= canvasAreaThresholdRequiringCompositing;
#endif
CanvasCompositingStrategy compositingStrategy = canvasCompositingStrategy(renderer);
return compositingStrategy == CanvasAsLayerContents || (compositingStrategy == CanvasPaintedToLayer && isCanvasLargeEnoughToForceCompositing);
@@ -2341,44 +2529,45 @@ bool RenderLayerCompositor::requiresCompositingForPlugin(RenderLayerModelObject&
if (!(m_compositingTriggers & ChromeClient::PluginTrigger))
return false;
- bool composite = renderer.isEmbeddedObject() && toRenderEmbeddedObject(&renderer)->allowsAcceleratedCompositing();
+ bool composite = is<RenderEmbeddedObject>(renderer) && downcast<RenderEmbeddedObject>(renderer).allowsAcceleratedCompositing();
if (!composite)
return false;
m_reevaluateCompositingAfterLayout = true;
- RenderWidget& pluginRenderer = *toRenderWidget(&renderer);
+ RenderWidget& pluginRenderer = downcast<RenderWidget>(renderer);
+ if (pluginRenderer.style().visibility() != VISIBLE)
+ return false;
+
// If we can't reliably know the size of the plugin yet, don't change compositing state.
if (pluginRenderer.needsLayout())
- return pluginRenderer.hasLayer() && pluginRenderer.layer()->isComposited();
+ return pluginRenderer.isComposited();
// Don't go into compositing mode if height or width are zero, or size is 1x1.
- IntRect contentBox = pixelSnappedIntRect(pluginRenderer.contentBoxRect());
+ IntRect contentBox = snappedIntRect(pluginRenderer.contentBoxRect());
return contentBox.height() * contentBox.width() > 1;
}
bool RenderLayerCompositor::requiresCompositingForFrame(RenderLayerModelObject& renderer) const
{
- if (!renderer.isWidget())
+ if (!is<RenderWidget>(renderer))
return false;
- RenderWidget& frameRenderer = *toRenderWidget(&renderer);
+ auto& frameRenderer = downcast<RenderWidget>(renderer);
+ if (frameRenderer.style().visibility() != VISIBLE)
+ return false;
if (!frameRenderer.requiresAcceleratedCompositing())
return false;
m_reevaluateCompositingAfterLayout = true;
- RenderLayerCompositor* innerCompositor = frameContentsCompositor(&frameRenderer);
- if (!innerCompositor || !innerCompositor->shouldPropagateCompositingToEnclosingFrame())
- return false;
-
// If we can't reliably know the size of the iframe yet, don't change compositing state.
if (!frameRenderer.parent() || frameRenderer.needsLayout())
- return frameRenderer.hasLayer() && frameRenderer.layer()->isComposited();
+ return frameRenderer.isComposited();
// Don't go into compositing mode if height or width are zero.
- return !pixelSnappedIntRect(frameRenderer.contentBoxRect()).isEmpty();
+ return !snappedIntRect(frameRenderer.contentBoxRect()).isEmpty();
}
bool RenderLayerCompositor::requiresCompositingForAnimation(RenderLayerModelObject& renderer) const
@@ -2386,26 +2575,25 @@ bool RenderLayerCompositor::requiresCompositingForAnimation(RenderLayerModelObje
if (!(m_compositingTriggers & ChromeClient::AnimationTrigger))
return false;
- AnimationController& animController = renderer.animation();
- return (animController.isRunningAnimationOnRenderer(&renderer, CSSPropertyOpacity)
+ const AnimationBase::RunningState activeAnimationState = AnimationBase::Running | AnimationBase::Paused;
+ CSSAnimationController& animController = renderer.animation();
+ return (animController.isRunningAnimationOnRenderer(renderer, CSSPropertyOpacity, activeAnimationState)
&& (inCompositingMode() || (m_compositingTriggers & ChromeClient::AnimatedOpacityTrigger)))
-#if ENABLE(CSS_FILTERS)
-#if PLATFORM(IOS) || !PLATFORM(MAC) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
- // <rdar://problem/10907251> - WebKit2 doesn't support CA animations of CI filters on Lion and below
- || animController.isRunningAnimationOnRenderer(&renderer, CSSPropertyWebkitFilter)
-#endif // PLATFORM(IOS) || !PLATFORM(MAC) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
-#endif // CSS_FILTERS
- || animController.isRunningAnimationOnRenderer(&renderer, CSSPropertyWebkitTransform);
+ || animController.isRunningAnimationOnRenderer(renderer, CSSPropertyFilter, activeAnimationState)
+#if ENABLE(FILTERS_LEVEL_2)
+ || animController.isRunningAnimationOnRenderer(renderer, CSSPropertyWebkitBackdropFilter, activeAnimationState)
+#endif
+ || animController.isRunningAnimationOnRenderer(renderer, CSSPropertyTransform, activeAnimationState);
}
-bool RenderLayerCompositor::requiresCompositingForIndirectReason(RenderLayerModelObject& renderer, bool hasCompositedDescendants, bool hasBlendedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason& reason) const
+bool RenderLayerCompositor::requiresCompositingForIndirectReason(RenderLayerModelObject& renderer, bool hasCompositedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason& reason) const
{
- RenderLayer& layer = *toRenderBoxModelObject(renderer).layer();
+ RenderLayer& layer = *downcast<RenderBoxModelObject>(renderer).layer();
// When a layer has composited descendants, some effects, like 2d transforms, filters, masks etc must be implemented
// via compositing so that they also apply to those composited descendants.
- if (hasCompositedDescendants && (hasBlendedDescendants || layer.transform() || renderer.createsGroup() || renderer.hasReflection() || renderer.isRenderNamedFlowFragmentContainer())) {
- reason = RenderLayer::IndirectCompositingForGraphicalEffect;
+ if (hasCompositedDescendants && (layer.isolatesCompositedBlending() || layer.transform() || renderer.createsGroup() || renderer.hasReflection() || renderer.isRenderNamedFlowFragmentContainer())) {
+ reason = RenderLayer::IndirectCompositingReason::GraphicalEffect;
return true;
}
@@ -2413,79 +2601,106 @@ bool RenderLayerCompositor::requiresCompositingForIndirectReason(RenderLayerMode
// will be affected by the preserve-3d or perspective.
if (has3DTransformedDescendants) {
if (renderer.style().transformStyle3D() == TransformStyle3DPreserve3D) {
- reason = RenderLayer::IndirectCompositingForPreserve3D;
+ reason = RenderLayer::IndirectCompositingReason::Preserve3D;
return true;
}
if (renderer.style().hasPerspective()) {
- reason = RenderLayer::IndirectCompositingForPerspective;
+ reason = RenderLayer::IndirectCompositingReason::Perspective;
return true;
}
}
- reason = RenderLayer::NoIndirectCompositingReason;
+ reason = RenderLayer::IndirectCompositingReason::None;
return false;
}
-#if PLATFORM(IOS)
-bool RenderLayerCompositor::requiresCompositingForScrolling(RenderLayerModelObject& renderer) const
+bool RenderLayerCompositor::styleChangeMayAffectIndirectCompositingReasons(const RenderLayerModelObject& renderer, const RenderStyle& oldStyle)
{
- return renderer.hasLayer() && toRenderBoxModelObject(renderer).layer()->hasAcceleratedTouchScrolling();
+ if (renderer.isRenderNamedFlowFragmentContainer())
+ return true;
+
+ auto& style = renderer.style();
+ if (RenderElement::createsGroupForStyle(style) != RenderElement::createsGroupForStyle(oldStyle))
+ return true;
+ if (style.isolation() != oldStyle.isolation())
+ return true;
+ if (style.hasTransform() != oldStyle.hasTransform())
+ return true;
+ if (style.boxReflect() != oldStyle.boxReflect())
+ return true;
+ if (style.transformStyle3D() != oldStyle.transformStyle3D())
+ return true;
+ if (style.hasPerspective() != oldStyle.hasPerspective())
+ return true;
+
+ return false;
}
-#endif
bool RenderLayerCompositor::requiresCompositingForFilters(RenderLayerModelObject& renderer) const
{
-#if ENABLE(CSS_FILTERS)
+#if ENABLE(FILTERS_LEVEL_2)
+ if (renderer.hasBackdropFilter())
+ return true;
+#endif
+
if (!(m_compositingTriggers & ChromeClient::FilterTrigger))
return false;
return renderer.hasFilter();
-#else
- UNUSED_PARAM(renderer);
- return false;
-#endif
}
-bool RenderLayerCompositor::requiresCompositingForBlending(RenderLayerModelObject& renderer) const
+bool RenderLayerCompositor::requiresCompositingForWillChange(RenderLayerModelObject& renderer) const
{
-#if ENABLE(CSS_COMPOSITING)
- return renderer.hasBlendMode();
-#else
- UNUSED_PARAM(renderer);
- return false;
-#endif
+ if (!renderer.style().willChange() || !renderer.style().willChange()->canTriggerCompositing())
+ return false;
+
+ if (is<RenderBox>(renderer))
+ return true;
+
+ return renderer.style().willChange()->canTriggerCompositingOnInline();
}
-#if PLATFORM(IOS)
-static bool isStickyInAcceleratedScrollingLayerOrViewport(const RenderLayer& layer, const RenderLayer** enclosingAcceleratedOverflowLayer = 0)
+bool RenderLayerCompositor::isAsyncScrollableStickyLayer(const RenderLayer& layer, const RenderLayer** enclosingAcceleratedOverflowLayer) const
{
ASSERT(layer.renderer().isStickyPositioned());
RenderLayer* enclosingOverflowLayer = layer.enclosingOverflowClipLayer(ExcludeSelf);
- if (enclosingOverflowLayer && enclosingOverflowLayer->hasAcceleratedTouchScrolling()) {
+
+#if PLATFORM(IOS)
+ if (enclosingOverflowLayer && enclosingOverflowLayer->hasTouchScrollableOverflow()) {
if (enclosingAcceleratedOverflowLayer)
*enclosingAcceleratedOverflowLayer = enclosingOverflowLayer;
return true;
}
-
- return !enclosingOverflowLayer;
-}
+#else
+ UNUSED_PARAM(enclosingAcceleratedOverflowLayer);
#endif
+ // If the layer is inside normal overflow, it's not async-scrollable.
+ if (enclosingOverflowLayer)
+ return false;
+
+ // No overflow ancestor, so see if the frame supports async scrolling.
+ if (hasCoordinatedScrolling())
+ return true;
-static bool isViewportConstrainedFixedOrStickyLayer(const RenderLayer& layer)
-{
#if PLATFORM(IOS)
- if (layer.renderer().isStickyPositioned())
- return isStickyInAcceleratedScrollingLayerOrViewport(layer);
+ // iOS WK1 has fixed/sticky support in the main frame via WebFixedPositionContent.
+ return isMainFrameCompositor();
#else
- if (layer.renderer().isStickyPositioned())
- return !layer.enclosingOverflowClipLayer(ExcludeSelf);
+ return false;
#endif
+}
+
+bool RenderLayerCompositor::isViewportConstrainedFixedOrStickyLayer(const RenderLayer& layer) const
+{
+ if (layer.renderer().isStickyPositioned())
+ return isAsyncScrollableStickyLayer(layer);
if (layer.renderer().style().position() != FixedPosition)
return false;
+ // FIXME: Handle fixed inside of a transform, which should not behave as fixed.
for (RenderLayer* stackingContainer = layer.stackingContainer(); stackingContainer; stackingContainer = stackingContainer->stackingContainer()) {
if (stackingContainer->isComposited() && stackingContainer->renderer().style().position() == FixedPosition)
return false;
@@ -2494,23 +2709,20 @@ static bool isViewportConstrainedFixedOrStickyLayer(const RenderLayer& layer)
return true;
}
-bool RenderLayerCompositor::requiresCompositingForPosition(RenderLayerModelObject& renderer, const RenderLayer& layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason) const
+static bool useCoordinatedScrollingForLayer(RenderView& view, const RenderLayer& layer)
{
-#if PLATFORM(IOS)
- if (renderer.isStickyPositioned())
+ if (layer.isRootLayer() && view.frameView().frame().isMainFrame())
return true;
- // position:fixed elements that create their own stacking context (e.g. have an explicit z-index,
- // opacity, transform) can get their own composited layer. A stacking context is required otherwise
- // z-index and clipping will be broken.
- if (!(renderer.isOutOfFlowPositioned() && renderer.style().position() == FixedPosition))
- return false;
-
- if (!m_renderView.hasCustomFixedPosition(renderer, RenderView::CheckContainingBlock)) {
- m_reevaluateCompositingAfterLayout = true;
- return false;
- }
+#if PLATFORM(IOS)
+ return layer.hasTouchScrollableOverflow();
#else
+ return layer.needsCompositedScrolling();
+#endif
+}
+
+bool RenderLayerCompositor::requiresCompositingForPosition(RenderLayerModelObject& renderer, const RenderLayer& layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason) const
+{
// position:fixed elements that create their own stacking context (e.g. have an explicit z-index,
// opacity, transform) can get their own composited layer. A stacking context is required otherwise
// z-index and clipping will be broken.
@@ -2527,13 +2739,11 @@ bool RenderLayerCompositor::requiresCompositingForPosition(RenderLayerModelObjec
return false;
// FIXME: acceleratedCompositingForFixedPositionEnabled should probably be renamed acceleratedCompositingForViewportConstrainedPositionEnabled().
- const Settings& settings = m_renderView.frameView().frame().settings();
- if (!settings.acceleratedCompositingForFixedPositionEnabled())
+ if (!m_renderView.settings().acceleratedCompositingForFixedPositionEnabled())
return false;
if (isSticky)
- return hasCoordinatedScrolling() && isViewportConstrainedFixedOrStickyLayer(layer);
-#endif
+ return isAsyncScrollableStickyLayer(layer);
auto container = renderer.container();
// If the renderer is not hooked up yet then we have to wait until it is.
@@ -2564,14 +2774,21 @@ bool RenderLayerCompositor::requiresCompositingForPosition(RenderLayerModelObjec
}
// Fixed position elements that are invisible in the current view don't get their own layer.
- LayoutRect viewBounds = m_renderView.frameView().viewportConstrainedVisibleContentRect();
- LayoutRect layerBounds = layer.calculateLayerBounds(&layer, 0, RenderLayer::UseLocalClipRectIfPossible | RenderLayer::IncludeLayerFilterOutsets | RenderLayer::UseFragmentBoxes
+ // FIXME: We shouldn't have to check useFixedLayout() here; one of the viewport rects needs to give the correct answer.
+ LayoutRect viewBounds;
+ if (m_renderView.frameView().useFixedLayout())
+ viewBounds = m_renderView.unscaledDocumentRect();
+ else
+ viewBounds = m_renderView.frameView().rectForFixedPositionLayout();
+
+ LayoutRect layerBounds = layer.calculateLayerBounds(&layer, LayoutSize(), RenderLayer::UseLocalClipRectIfPossible | RenderLayer::IncludeLayerFilterOutsets | RenderLayer::UseFragmentBoxesExcludingCompositing
| RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask | RenderLayer::IncludeCompositedDescendants);
// Map to m_renderView to ignore page scale.
FloatRect absoluteBounds = layer.renderer().localToContainerQuad(FloatRect(layerBounds), &m_renderView).boundingBox();
if (!viewBounds.intersects(enclosingIntRect(absoluteBounds))) {
if (viewportConstrainedNotCompositedReason)
*viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForBoundsOutOfView;
+ LOG_WITH_STREAM(Compositing, stream << "Layer " << &layer << " bounds " << layerBounds << " outside visible rect " << viewBounds);
return false;
}
@@ -2583,12 +2800,27 @@ bool RenderLayerCompositor::requiresCompositingForOverflowScrolling(const Render
return layer.needsCompositedScrolling();
}
-bool RenderLayerCompositor::isRunningAcceleratedTransformAnimation(RenderLayerModelObject& renderer) const
+#if PLATFORM(IOS)
+bool RenderLayerCompositor::requiresCompositingForScrolling(const RenderLayer& layer) const
+{
+ if (!layer.hasAcceleratedTouchScrolling())
+ return false;
+
+ if (!m_inPostLayoutUpdate) {
+ m_reevaluateCompositingAfterLayout = true;
+ return layer.isComposited();
+ }
+
+ return layer.hasTouchScrollableOverflow();
+}
+#endif
+
+bool RenderLayerCompositor::isRunningTransformAnimation(RenderLayerModelObject& renderer) const
{
if (!(m_compositingTriggers & ChromeClient::AnimationTrigger))
return false;
- return renderer.animation().isRunningAnimationOnRenderer(&renderer, CSSPropertyWebkitTransform);
+ return renderer.animation().isRunningAnimationOnRenderer(renderer, CSSPropertyTransform, AnimationBase::Running | AnimationBase::Paused);
}
// If an element has negative z-index children, those children render in front of the
@@ -2601,8 +2833,10 @@ bool RenderLayerCompositor::needsContentsCompositingLayer(const RenderLayer& lay
bool RenderLayerCompositor::requiresScrollLayer(RootLayerAttachment attachment) const
{
+ FrameView& frameView = m_renderView.frameView();
+
// This applies when the application UI handles scrolling, in which case RenderLayerCompositor doesn't need to manage it.
- if (m_renderView.frameView().delegatesScrolling())
+ if (frameView.delegatesScrolling() && isMainFrameCompositor())
return false;
// We need to handle our own scrolling if we're:
@@ -2610,7 +2844,7 @@ bool RenderLayerCompositor::requiresScrollLayer(RootLayerAttachment attachment)
|| attachment == RootLayerAttachedViaEnclosingFrame; // a composited frame on Mac
}
-static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
+void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
{
if (!scrollbar)
return;
@@ -2620,23 +2854,24 @@ static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const
context.translate(-scrollbarRect.x(), -scrollbarRect.y());
IntRect transformedClip = clip;
transformedClip.moveBy(scrollbarRect.location());
- scrollbar->paint(&context, transformedClip);
+ scrollbar->paint(context, transformedClip);
context.restore();
}
-void RenderLayerCompositor::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase, const IntRect& clip)
+void RenderLayerCompositor::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase, const FloatRect& clip)
{
+ IntRect pixelSnappedRectForIntegralPositionedItems = snappedIntRect(LayoutRect(clip));
if (graphicsLayer == layerForHorizontalScrollbar())
- paintScrollbar(m_renderView.frameView().horizontalScrollbar(), context, clip);
+ paintScrollbar(m_renderView.frameView().horizontalScrollbar(), context, pixelSnappedRectForIntegralPositionedItems);
else if (graphicsLayer == layerForVerticalScrollbar())
- paintScrollbar(m_renderView.frameView().verticalScrollbar(), context, clip);
+ paintScrollbar(m_renderView.frameView().verticalScrollbar(), context, pixelSnappedRectForIntegralPositionedItems);
else if (graphicsLayer == layerForScrollCorner()) {
const IntRect& scrollCorner = m_renderView.frameView().scrollCornerRect();
context.save();
context.translate(-scrollCorner.x(), -scrollCorner.y());
- IntRect transformedClip = clip;
+ IntRect transformedClip = pixelSnappedRectForIntegralPositionedItems;
transformedClip.moveBy(scrollCorner.location());
- m_renderView.frameView().paintScrollCorner(&context, transformedClip);
+ m_renderView.frameView().paintScrollCorner(context, transformedClip);
context.restore();
}
}
@@ -2644,7 +2879,7 @@ void RenderLayerCompositor::paintContents(const GraphicsLayer* graphicsLayer, Gr
bool RenderLayerCompositor::supportsFixedRootBackgroundCompositing() const
{
RenderLayerBacking* renderViewBacking = m_renderView.layer()->backing();
- return renderViewBacking && renderViewBacking->usingTiledBacking();
+ return renderViewBacking && renderViewBacking->isMainFrameLayerWithTiledBacking();
}
bool RenderLayerCompositor::needsFixedRootBackgroundLayer(const RenderLayer& layer) const
@@ -2652,6 +2887,11 @@ bool RenderLayerCompositor::needsFixedRootBackgroundLayer(const RenderLayer& lay
if (&layer != m_renderView.layer())
return false;
+ if (m_renderView.settings().fixedBackgroundsPaintRelativeToDocument())
+ return false;
+
+ LOG(Compositing, "RenderLayerCompositor %p needsFixedRootBackgroundLayer returning %d", this, supportsFixedRootBackgroundCompositing() && m_renderView.rootBackgroundIsEntirelyFixed());
+
return supportsFixedRootBackgroundCompositing() && m_renderView.rootBackgroundIsEntirelyFixed();
}
@@ -2668,24 +2908,13 @@ GraphicsLayer* RenderLayerCompositor::fixedRootBackgroundLayer() const
return nullptr;
}
-static void resetTrackedRepaintRectsRecursive(GraphicsLayer& graphicsLayer)
-{
- graphicsLayer.resetTrackedRepaints();
-
- for (size_t i = 0, size = graphicsLayer.children().size(); i < size; ++i)
- resetTrackedRepaintRectsRecursive(*graphicsLayer.children()[i]);
-
- if (GraphicsLayer* replicaLayer = graphicsLayer.replicaLayer())
- resetTrackedRepaintRectsRecursive(*replicaLayer);
-
- if (GraphicsLayer* maskLayer = graphicsLayer.maskLayer())
- resetTrackedRepaintRectsRecursive(*maskLayer);
-}
-
void RenderLayerCompositor::resetTrackedRepaintRects()
{
- if (GraphicsLayer* rootLayer = rootGraphicsLayer())
- resetTrackedRepaintRectsRecursive(*rootLayer);
+ if (GraphicsLayer* rootLayer = rootGraphicsLayer()) {
+ GraphicsLayer::traverse(*rootLayer, [](GraphicsLayer& layer) {
+ layer.resetTrackedRepaints();
+ });
+ }
}
void RenderLayerCompositor::setTracksRepaints(bool tracksRepaints)
@@ -2700,29 +2929,30 @@ bool RenderLayerCompositor::isTrackingRepaints() const
float RenderLayerCompositor::deviceScaleFactor() const
{
- Page* page = this->page();
- return page ? page->deviceScaleFactor() : 1;
+ return m_renderView.document().deviceScaleFactor();
}
float RenderLayerCompositor::pageScaleFactor() const
{
- Page* page = this->page();
- return page ? page->pageScaleFactor() : 1;
+ return page().pageScaleFactor();
+}
+
+float RenderLayerCompositor::zoomedOutPageScaleFactor() const
+{
+ return page().zoomedOutPageScaleFactor();
}
float RenderLayerCompositor::contentsScaleMultiplierForNewTiles(const GraphicsLayer*) const
{
#if PLATFORM(IOS)
- TileCache* tileCache = nullptr;
- if (Page* page = this->page()) {
- if (FrameView* frameView = page->mainFrame().view())
- tileCache = frameView->tileCache();
- }
+ LegacyTileCache* tileCache = nullptr;
+ if (FrameView* frameView = page().mainFrame().view())
+ tileCache = frameView->legacyTileCache();
if (!tileCache)
return 1;
- return tileCache->tilingMode() == TileCache::Zooming ? 0.125 : 1;
+ return tileCache->tileControllerShouldUseLowScaleTiles() ? 0.125 : 1;
#else
return 1;
#endif
@@ -2733,13 +2963,7 @@ void RenderLayerCompositor::didCommitChangesForLayer(const GraphicsLayer*) const
// Nothing to do here yet.
}
-bool RenderLayerCompositor::keepLayersPixelAligned() const
-{
- // When scaling, attempt to align compositing layers to pixel boundaries.
- return true;
-}
-
-bool RenderLayerCompositor::mainFrameBackingIsTiled() const
+bool RenderLayerCompositor::documentUsesTiledBacking() const
{
RenderLayer* layer = m_renderView.layer();
if (!layer)
@@ -2749,20 +2973,12 @@ bool RenderLayerCompositor::mainFrameBackingIsTiled() const
if (!backing)
return false;
- return backing->usingTiledBacking();
+ return backing->isMainFrameLayerWithTiledBacking();
}
-bool RenderLayerCompositor::mainFrameBackingIsTiledWithMargin() const
+bool RenderLayerCompositor::isMainFrameCompositor() const
{
- RenderLayer* layer = m_renderView.layer();
- if (!layer)
- return false;
-
- RenderLayerBacking* backing = layer->backing();
- if (!backing)
- return false;
-
- return backing->tiledBackingHasMargin();
+ return m_renderView.frameView().frame().isMainFrame();
}
bool RenderLayerCompositor::shouldCompositeOverflowControls() const
@@ -2775,11 +2991,13 @@ bool RenderLayerCompositor::shouldCompositeOverflowControls() const
if (frameView.delegatesScrolling())
return false;
- if (mainFrameBackingIsTiled())
+ if (documentUsesTiledBacking())
return true;
+#if !USE(COORDINATED_GRAPHICS_THREADED)
if (!frameView.hasOverlayScrollbars())
return false;
+#endif
return true;
}
@@ -2802,12 +3020,11 @@ bool RenderLayerCompositor::requiresScrollCornerLayer() const
#if ENABLE(RUBBER_BANDING)
bool RenderLayerCompositor::requiresOverhangAreasLayer() const
{
- // We don't want a layer if this is a subframe.
- if (m_renderView.document().ownerElement())
+ if (!isMainFrameCompositor())
return false;
// We do want a layer if we're using tiled drawing and can scroll.
- if (mainFrameBackingIsTiled() && m_renderView.frameView().hasOpaqueBackground() && !m_renderView.frameView().prohibitsScrolling())
+ if (documentUsesTiledBacking() && m_renderView.frameView().hasOpaqueBackground() && !m_renderView.frameView().prohibitsScrolling())
return true;
return false;
@@ -2815,16 +3032,19 @@ bool RenderLayerCompositor::requiresOverhangAreasLayer() const
bool RenderLayerCompositor::requiresContentShadowLayer() const
{
- // We don't want a layer if this is a subframe.
- if (m_renderView.document().ownerElement())
+ if (!isMainFrameCompositor())
return false;
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
if (viewHasTransparentBackground())
return false;
+ // If the background is going to extend, then it doesn't make sense to have a shadow layer.
+ if (m_renderView.settings().backgroundShouldExtendBeyondPage())
+ return false;
+
// On Mac, we want a content shadow layer if we're using tiled drawing and can scroll.
- if (mainFrameBackingIsTiled() && !m_renderView.frameView().prohibitsScrolling())
+ if (documentUsesTiledBacking() && !m_renderView.frameView().prohibitsScrolling())
return true;
#endif
@@ -2833,22 +3053,20 @@ bool RenderLayerCompositor::requiresContentShadowLayer() const
GraphicsLayer* RenderLayerCompositor::updateLayerForTopOverhangArea(bool wantsLayer)
{
- if (m_renderView.document().ownerElement())
- return 0;
+ if (!isMainFrameCompositor())
+ return nullptr;
if (!wantsLayer) {
if (m_layerForTopOverhangArea) {
m_layerForTopOverhangArea->removeFromParent();
m_layerForTopOverhangArea = nullptr;
}
- return 0;
+ return nullptr;
}
if (!m_layerForTopOverhangArea) {
- m_layerForTopOverhangArea = GraphicsLayer::create(graphicsLayerFactory(), this);
-#ifndef NDEBUG
- m_layerForTopOverhangArea->setName("top overhang area");
-#endif
+ m_layerForTopOverhangArea = GraphicsLayer::create(graphicsLayerFactory(), *this);
+ m_layerForTopOverhangArea->setName("top overhang");
m_scrollLayer->addChildBelow(m_layerForTopOverhangArea.get(), m_rootContentLayer.get());
}
@@ -2857,33 +3075,32 @@ GraphicsLayer* RenderLayerCompositor::updateLayerForTopOverhangArea(bool wantsLa
GraphicsLayer* RenderLayerCompositor::updateLayerForBottomOverhangArea(bool wantsLayer)
{
- if (m_renderView.document().ownerElement())
- return 0;
+ if (!isMainFrameCompositor())
+ return nullptr;
if (!wantsLayer) {
if (m_layerForBottomOverhangArea) {
m_layerForBottomOverhangArea->removeFromParent();
m_layerForBottomOverhangArea = nullptr;
}
- return 0;
+ return nullptr;
}
if (!m_layerForBottomOverhangArea) {
- m_layerForBottomOverhangArea = GraphicsLayer::create(graphicsLayerFactory(), this);
-#ifndef NDEBUG
- m_layerForBottomOverhangArea->setName("bottom overhang area");
-#endif
+ m_layerForBottomOverhangArea = GraphicsLayer::create(graphicsLayerFactory(), *this);
+ m_layerForBottomOverhangArea->setName("bottom overhang");
m_scrollLayer->addChildBelow(m_layerForBottomOverhangArea.get(), m_rootContentLayer.get());
}
- m_layerForBottomOverhangArea->setPosition(FloatPoint(0, m_rootContentLayer->size().height() + m_renderView.frameView().headerHeight() + m_renderView.frameView().footerHeight()));
+ m_layerForBottomOverhangArea->setPosition(FloatPoint(0, m_rootContentLayer->size().height() + m_renderView.frameView().headerHeight()
+ + m_renderView.frameView().footerHeight() + m_renderView.frameView().topContentInset()));
return m_layerForBottomOverhangArea.get();
}
GraphicsLayer* RenderLayerCompositor::updateLayerForHeader(bool wantsLayer)
{
- if (m_renderView.document().ownerElement())
- return 0;
+ if (!isMainFrameCompositor())
+ return nullptr;
if (!wantsLayer) {
if (m_layerForHeader) {
@@ -2893,37 +3110,35 @@ GraphicsLayer* RenderLayerCompositor::updateLayerForHeader(bool wantsLayer)
// The ScrollingTree knows about the header layer, and the position of the root layer is affected
// by the header layer, so if we remove the header, we need to tell the scrolling tree.
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->frameViewRootLayerDidChange(&m_renderView.frameView());
+ scrollingCoordinator->frameViewRootLayerDidChange(m_renderView.frameView());
}
- return 0;
+ return nullptr;
}
if (!m_layerForHeader) {
- m_layerForHeader = GraphicsLayer::create(graphicsLayerFactory(), this);
-#ifndef NDEBUG
+ m_layerForHeader = GraphicsLayer::create(graphicsLayerFactory(), *this);
m_layerForHeader->setName("header");
-#endif
- m_scrollLayer->addChildBelow(m_layerForHeader.get(), m_rootContentLayer.get());
+ m_scrollLayer->addChildAbove(m_layerForHeader.get(), m_rootContentLayer.get());
m_renderView.frameView().addPaintPendingMilestones(DidFirstFlushForHeaderLayer);
}
- m_layerForHeader->setPosition(FloatPoint());
+ m_layerForHeader->setPosition(FloatPoint(0,
+ FrameView::yPositionForHeaderLayer(m_renderView.frameView().scrollPosition(), m_renderView.frameView().topContentInset())));
m_layerForHeader->setAnchorPoint(FloatPoint3D());
m_layerForHeader->setSize(FloatSize(m_renderView.frameView().visibleWidth(), m_renderView.frameView().headerHeight()));
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->frameViewRootLayerDidChange(&m_renderView.frameView());
+ scrollingCoordinator->frameViewRootLayerDidChange(m_renderView.frameView());
- if (Page* page = this->page())
- page->chrome().client().didAddHeaderLayer(m_layerForHeader.get());
+ page().chrome().client().didAddHeaderLayer(*m_layerForHeader);
return m_layerForHeader.get();
}
GraphicsLayer* RenderLayerCompositor::updateLayerForFooter(bool wantsLayer)
{
- if (m_renderView.document().ownerElement())
- return 0;
+ if (!isMainFrameCompositor())
+ return nullptr;
if (!wantsLayer) {
if (m_layerForFooter) {
@@ -2933,28 +3148,27 @@ GraphicsLayer* RenderLayerCompositor::updateLayerForFooter(bool wantsLayer)
// The ScrollingTree knows about the footer layer, and the total scrollable size is affected
// by the footer layer, so if we remove the footer, we need to tell the scrolling tree.
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->frameViewRootLayerDidChange(&m_renderView.frameView());
+ scrollingCoordinator->frameViewRootLayerDidChange(m_renderView.frameView());
}
- return 0;
+ return nullptr;
}
if (!m_layerForFooter) {
- m_layerForFooter = GraphicsLayer::create(graphicsLayerFactory(), this);
-#ifndef NDEBUG
+ m_layerForFooter = GraphicsLayer::create(graphicsLayerFactory(), *this);
m_layerForFooter->setName("footer");
-#endif
- m_scrollLayer->addChildBelow(m_layerForFooter.get(), m_rootContentLayer.get());
+ m_scrollLayer->addChildAbove(m_layerForFooter.get(), m_rootContentLayer.get());
}
- m_layerForFooter->setPosition(FloatPoint(0, m_rootContentLayer->size().height() + m_renderView.frameView().headerHeight()));
+ float totalContentHeight = m_rootContentLayer->size().height() + m_renderView.frameView().headerHeight() + m_renderView.frameView().footerHeight();
+ m_layerForFooter->setPosition(FloatPoint(0, FrameView::yPositionForFooterLayer(m_renderView.frameView().scrollPosition(),
+ m_renderView.frameView().topContentInset(), totalContentHeight, m_renderView.frameView().footerHeight())));
m_layerForFooter->setAnchorPoint(FloatPoint3D());
m_layerForFooter->setSize(FloatSize(m_renderView.frameView().visibleWidth(), m_renderView.frameView().footerHeight()));
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->frameViewRootLayerDidChange(&m_renderView.frameView());
+ scrollingCoordinator->frameViewRootLayerDidChange(m_renderView.frameView());
- if (Page* page = this->page())
- page->chrome().client().didAddFooterLayer(m_layerForFooter.get());
+ page().chrome().client().didAddFooterLayer(*m_layerForFooter);
return m_layerForFooter.get();
}
@@ -2976,7 +3190,66 @@ bool RenderLayerCompositor::viewHasTransparentBackground(Color* backgroundColor)
if (backgroundColor)
*backgroundColor = documentBackgroundColor;
- return documentBackgroundColor.hasAlpha();
+ return !documentBackgroundColor.isOpaque();
+}
+
+// We can't rely on getting layerStyleChanged() for a style change that affects the root background, because the style change may
+// be on the body which has no RenderLayer.
+void RenderLayerCompositor::rootOrBodyStyleChanged(RenderElement& renderer, const RenderStyle* oldStyle)
+{
+ if (!inCompositingMode())
+ return;
+
+ Color oldBackgroundColor;
+ if (oldStyle)
+ oldBackgroundColor = oldStyle->visitedDependentColor(CSSPropertyBackgroundColor);
+
+ if (oldBackgroundColor != renderer.style().visitedDependentColor(CSSPropertyBackgroundColor))
+ rootBackgroundTransparencyChanged();
+
+ bool hadFixedBackground = oldStyle && oldStyle->hasEntirelyFixedBackground();
+ if (hadFixedBackground != renderer.style().hasEntirelyFixedBackground()) {
+ setCompositingLayersNeedRebuild();
+ scheduleCompositingLayerUpdate();
+ }
+}
+
+void RenderLayerCompositor::rootBackgroundTransparencyChanged()
+{
+ if (!inCompositingMode())
+ return;
+
+ bool isTransparent = viewHasTransparentBackground();
+
+ LOG(Compositing, "RenderLayerCompositor %p rootBackgroundTransparencyChanged. isTransparent=%d, changed=%d", this, isTransparent, m_viewBackgroundIsTransparent == isTransparent);
+ if (m_viewBackgroundIsTransparent == isTransparent)
+ return;
+
+ m_viewBackgroundIsTransparent = isTransparent;
+
+ // FIXME: We should do something less expensive than a full layer rebuild.
+ setCompositingLayersNeedRebuild();
+ scheduleCompositingLayerUpdate();
+}
+
+void RenderLayerCompositor::setRootExtendedBackgroundColor(const Color& color)
+{
+ if (color == m_rootExtendedBackgroundColor)
+ return;
+
+ m_rootExtendedBackgroundColor = color;
+
+ page().chrome().client().pageExtendedBackgroundColorDidChange(color);
+
+#if ENABLE(RUBBER_BANDING)
+ if (!m_layerForOverhangAreas)
+ return;
+
+ m_layerForOverhangAreas->setBackgroundColor(m_rootExtendedBackgroundColor);
+
+ if (!m_rootExtendedBackgroundColor.isValid())
+ m_layerForOverhangAreas->setCustomAppearance(GraphicsLayer::ScrollingOverhang);
+#endif
}
void RenderLayerCompositor::updateOverflowControlsLayers()
@@ -2984,13 +3257,21 @@ void RenderLayerCompositor::updateOverflowControlsLayers()
#if ENABLE(RUBBER_BANDING)
if (requiresOverhangAreasLayer()) {
if (!m_layerForOverhangAreas) {
- m_layerForOverhangAreas = GraphicsLayer::create(graphicsLayerFactory(), this);
-#ifndef NDEBUG
+ m_layerForOverhangAreas = GraphicsLayer::create(graphicsLayerFactory(), *this);
m_layerForOverhangAreas->setName("overhang areas");
-#endif
m_layerForOverhangAreas->setDrawsContent(false);
- m_layerForOverhangAreas->setSize(m_renderView.frameView().frameRect().size());
- m_layerForOverhangAreas->setCustomAppearance(GraphicsLayer::ScrollingOverhang);
+
+ float topContentInset = m_renderView.frameView().topContentInset();
+ IntSize overhangAreaSize = m_renderView.frameView().frameRect().size();
+ overhangAreaSize.setHeight(overhangAreaSize.height() - topContentInset);
+ m_layerForOverhangAreas->setSize(overhangAreaSize);
+ m_layerForOverhangAreas->setPosition(FloatPoint(0, topContentInset));
+ m_layerForOverhangAreas->setAnchorPoint(FloatPoint3D());
+
+ if (m_renderView.settings().backgroundShouldExtendBeyondPage())
+ m_layerForOverhangAreas->setBackgroundColor(m_renderView.frameView().documentBackgroundColor());
+ else
+ m_layerForOverhangAreas->setCustomAppearance(GraphicsLayer::ScrollingOverhang);
// We want the overhang areas layer to be positioned below the frame contents,
// so insert it below the clip layer.
@@ -3003,12 +3284,11 @@ void RenderLayerCompositor::updateOverflowControlsLayers()
if (requiresContentShadowLayer()) {
if (!m_contentShadowLayer) {
- m_contentShadowLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
-#ifndef NDEBUG
+ m_contentShadowLayer = GraphicsLayer::create(graphicsLayerFactory(), *this);
m_contentShadowLayer->setName("content shadow");
-#endif
m_contentShadowLayer->setSize(m_rootContentLayer->size());
m_contentShadowLayer->setPosition(m_rootContentLayer->position());
+ m_contentShadowLayer->setAnchorPoint(FloatPoint3D());
m_contentShadowLayer->setCustomAppearance(GraphicsLayer::ScrollingShadow);
m_scrollLayer->addChildBelow(m_contentShadowLayer.get(), m_rootContentLayer.get());
@@ -3021,59 +3301,52 @@ void RenderLayerCompositor::updateOverflowControlsLayers()
if (requiresHorizontalScrollbarLayer()) {
if (!m_layerForHorizontalScrollbar) {
- m_layerForHorizontalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), this);
+ m_layerForHorizontalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), *this);
m_layerForHorizontalScrollbar->setShowDebugBorder(m_showDebugBorders);
-#ifndef NDEBUG
m_layerForHorizontalScrollbar->setName("horizontal scrollbar container");
-
-#endif
-#if PLATFORM(MAC) && USE(CA)
+#if PLATFORM(COCOA) && USE(CA)
m_layerForHorizontalScrollbar->setAcceleratesDrawing(acceleratedDrawingEnabled());
#endif
m_overflowControlsHostLayer->addChild(m_layerForHorizontalScrollbar.get());
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_renderView.frameView(), HorizontalScrollbar);
+ scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), HorizontalScrollbar);
}
} else if (m_layerForHorizontalScrollbar) {
m_layerForHorizontalScrollbar->removeFromParent();
m_layerForHorizontalScrollbar = nullptr;
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_renderView.frameView(), HorizontalScrollbar);
+ scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), HorizontalScrollbar);
}
if (requiresVerticalScrollbarLayer()) {
if (!m_layerForVerticalScrollbar) {
- m_layerForVerticalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), this);
+ m_layerForVerticalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), *this);
m_layerForVerticalScrollbar->setShowDebugBorder(m_showDebugBorders);
-#ifndef NDEBUG
m_layerForVerticalScrollbar->setName("vertical scrollbar container");
-#endif
-#if PLATFORM(MAC) && USE(CA)
+#if PLATFORM(COCOA) && USE(CA)
m_layerForVerticalScrollbar->setAcceleratesDrawing(acceleratedDrawingEnabled());
#endif
m_overflowControlsHostLayer->addChild(m_layerForVerticalScrollbar.get());
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_renderView.frameView(), VerticalScrollbar);
+ scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), VerticalScrollbar);
}
} else if (m_layerForVerticalScrollbar) {
m_layerForVerticalScrollbar->removeFromParent();
m_layerForVerticalScrollbar = nullptr;
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_renderView.frameView(), VerticalScrollbar);
+ scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), VerticalScrollbar);
}
if (requiresScrollCornerLayer()) {
if (!m_layerForScrollCorner) {
- m_layerForScrollCorner = GraphicsLayer::create(graphicsLayerFactory(), this);
+ m_layerForScrollCorner = GraphicsLayer::create(graphicsLayerFactory(), *this);
m_layerForScrollCorner->setShowDebugBorder(m_showDebugBorders);
-#ifndef NDEBUG
m_layerForScrollCorner->setName("scroll corner");
-#endif
-#if PLATFORM(MAC) && USE(CA)
+#if PLATFORM(COCOA) && USE(CA)
m_layerForScrollCorner->setAcceleratesDrawing(acceleratedDrawingEnabled());
#endif
m_overflowControlsHostLayer->addChild(m_layerForScrollCorner.get());
@@ -3088,16 +3361,14 @@ void RenderLayerCompositor::updateOverflowControlsLayers()
void RenderLayerCompositor::ensureRootLayer()
{
- RootLayerAttachment expectedAttachment = shouldPropagateCompositingToEnclosingFrame() ? RootLayerAttachedViaEnclosingFrame : RootLayerAttachedViaChromeClient;
+ RootLayerAttachment expectedAttachment = isMainFrameCompositor() ? RootLayerAttachedViaChromeClient : RootLayerAttachedViaEnclosingFrame;
if (expectedAttachment == m_rootLayerAttachment)
return;
if (!m_rootContentLayer) {
- m_rootContentLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
-#ifndef NDEBUG
+ m_rootContentLayer = GraphicsLayer::create(graphicsLayerFactory(), *this);
m_rootContentLayer->setName("content root");
-#endif
- IntRect overflowRect = m_renderView.pixelSnappedLayoutOverflowRect();
+ IntRect overflowRect = snappedIntRect(m_renderView.layoutOverflowRect());
m_rootContentLayer->setSize(FloatSize(overflowRect.maxX(), overflowRect.maxY()));
m_rootContentLayer->setPosition(FloatPoint());
@@ -3118,31 +3389,25 @@ void RenderLayerCompositor::ensureRootLayer()
ASSERT(!m_clipLayer);
// Create a layer to host the clipping layer and the overflow controls layers.
- m_overflowControlsHostLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
-#ifndef NDEBUG
+ m_overflowControlsHostLayer = GraphicsLayer::create(graphicsLayerFactory(), *this);
m_overflowControlsHostLayer->setName("overflow controls host");
-#endif
// Create a clipping layer if this is an iframe
- m_clipLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
-#ifndef NDEBUG
+ m_clipLayer = GraphicsLayer::create(graphicsLayerFactory(), *this);
m_clipLayer->setName("frame clipping");
-#endif
m_clipLayer->setMasksToBounds(true);
- m_scrollLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
-#ifndef NDEBUG
+ m_scrollLayer = GraphicsLayer::create(graphicsLayerFactory(), *this);
m_scrollLayer->setName("frame scrolling");
-#endif
- if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(m_scrollLayer.get(), true);
// Hook them up
m_overflowControlsHostLayer->addChild(m_clipLayer.get());
m_clipLayer->addChild(m_scrollLayer.get());
m_scrollLayer->addChild(m_rootContentLayer.get());
- m_clipLayer->setSize(m_renderView.frameView().unscaledVisibleContentSize());
+ m_clipLayer->setSize(m_renderView.frameView().sizeForVisibleContent());
+ m_clipLayer->setPosition(positionForClipLayer());
+ m_clipLayer->setAnchorPoint(FloatPoint3D());
updateOverflowControlsLayers();
@@ -3184,18 +3449,18 @@ void RenderLayerCompositor::destroyRootLayer()
m_layerForHorizontalScrollbar->removeFromParent();
m_layerForHorizontalScrollbar = nullptr;
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_renderView.frameView(), HorizontalScrollbar);
+ scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), HorizontalScrollbar);
if (Scrollbar* horizontalScrollbar = m_renderView.frameView().verticalScrollbar())
- m_renderView.frameView().invalidateScrollbar(horizontalScrollbar, IntRect(IntPoint(0, 0), horizontalScrollbar->frameRect().size()));
+ m_renderView.frameView().invalidateScrollbar(*horizontalScrollbar, IntRect(IntPoint(0, 0), horizontalScrollbar->frameRect().size()));
}
if (m_layerForVerticalScrollbar) {
m_layerForVerticalScrollbar->removeFromParent();
m_layerForVerticalScrollbar = nullptr;
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_renderView.frameView(), VerticalScrollbar);
+ scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), VerticalScrollbar);
if (Scrollbar* verticalScrollbar = m_renderView.frameView().verticalScrollbar())
- m_renderView.frameView().invalidateScrollbar(verticalScrollbar, IntRect(IntPoint(0, 0), verticalScrollbar->frameRect().size()));
+ m_renderView.frameView().invalidateScrollbar(*verticalScrollbar, IntRect(IntPoint(0, 0), verticalScrollbar->frameRect().size()));
}
if (m_layerForScrollCorner) {
@@ -3219,23 +3484,24 @@ void RenderLayerCompositor::attachRootLayer(RootLayerAttachment attachment)
if (!m_rootContentLayer)
return;
+ LOG(Compositing, "RenderLayerCompositor %p attachRootLayer %d", this, attachment);
+
switch (attachment) {
case RootLayerUnattached:
ASSERT_NOT_REACHED();
break;
case RootLayerAttachedViaChromeClient: {
Frame& frame = m_renderView.frameView().frame();
- Page* page = frame.page();
- if (!page)
- return;
-
- page->chrome().client().attachRootGraphicsLayer(&frame, rootGraphicsLayer());
+ page().chrome().client().attachRootGraphicsLayer(frame, rootGraphicsLayer());
+ if (frame.isMainFrame())
+ page().chrome().client().attachViewOverlayGraphicsLayer(frame, &frame.mainFrame().pageOverlayController().layerWithViewOverlays());
break;
}
case RootLayerAttachedViaEnclosingFrame: {
- // The layer will get hooked up via RenderLayerBacking::updateGraphicsLayerConfiguration()
+ // The layer will get hooked up via RenderLayerBacking::updateConfiguration()
// for the frame's renderer in the parent document.
- m_renderView.document().ownerElement()->scheduleSetNeedsStyleRecalc(SyntheticStyleChange);
+ if (auto* ownerElement = m_renderView.document().ownerElement())
+ ownerElement->scheduleinvalidateStyleAndLayerComposition();
break;
}
}
@@ -3264,16 +3530,16 @@ void RenderLayerCompositor::detachRootLayer()
m_rootContentLayer->removeFromParent();
if (HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement())
- ownerElement->scheduleSetNeedsStyleRecalc(SyntheticStyleChange);
+ ownerElement->scheduleinvalidateStyleAndLayerComposition();
break;
}
case RootLayerAttachedViaChromeClient: {
Frame& frame = m_renderView.frameView().frame();
- Page* page = frame.page();
- if (!page)
- return;
-
- page->chrome().client().attachRootGraphicsLayer(&frame, 0);
+ page().chrome().client().attachRootGraphicsLayer(frame, nullptr);
+ if (frame.isMainFrame()) {
+ page().chrome().client().attachViewOverlayGraphicsLayer(frame, nullptr);
+ frame.mainFrame().pageOverlayController().willDetachRootLayer();
+ }
}
break;
case RootLayerUnattached:
@@ -3291,29 +3557,32 @@ void RenderLayerCompositor::updateRootLayerAttachment()
void RenderLayerCompositor::rootLayerAttachmentChanged()
{
+ // The document-relative page overlay layer (which is pinned to the main frame's layer tree)
+ // is moved between different RenderLayerCompositors' layer trees, and needs to be
+ // reattached whenever we swap in a new RenderLayerCompositor.
+ if (m_rootLayerAttachment == RootLayerUnattached)
+ return;
+
+ Frame& frame = m_renderView.frameView().frame();
+
// The attachment can affect whether the RenderView layer's paintsIntoWindow() behavior,
- // so call updateGraphicsLayerGeometry() to udpate that.
+ // so call updateDrawsContent() to update that.
RenderLayer* layer = m_renderView.layer();
- if (RenderLayerBacking* backing = layer ? layer->backing() : 0)
+ if (RenderLayerBacking* backing = layer ? layer->backing() : nullptr)
backing->updateDrawsContent();
+
+ if (!frame.isMainFrame())
+ return;
+
+ m_rootContentLayer->addChild(&frame.mainFrame().pageOverlayController().layerWithDocumentOverlays());
}
-// IFrames are special, because we hook compositing layers together across iframe boundaries
-// when both parent and iframe content are composited. So when this frame becomes composited, we have
-// to use a synthetic style change to get the iframes into RenderLayers in order to allow them to composite.
void RenderLayerCompositor::notifyIFramesOfCompositingChange()
{
- Frame& frame = m_renderView.frameView().frame();
-
- for (Frame* child = frame.tree().firstChild(); child; child = child->tree().traverseNext(&frame)) {
- if (child->document() && child->document()->ownerElement())
- child->document()->ownerElement()->scheduleSetNeedsStyleRecalc(SyntheticStyleChange);
- }
-
- // Compositing also affects the answer to RenderIFrame::requiresAcceleratedCompositing(), so
+ // Compositing affects the answer to RenderIFrame::requiresAcceleratedCompositing(), so
// we need to schedule a style recalc in our parent document.
if (HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement())
- ownerElement->scheduleSetNeedsStyleRecalc(SyntheticStyleChange);
+ ownerElement->scheduleinvalidateStyleAndLayerComposition();
}
bool RenderLayerCompositor::layerHas3DContent(const RenderLayer& layer) const
@@ -3331,23 +3600,23 @@ bool RenderLayerCompositor::layerHas3DContent(const RenderLayer& layer) const
if (layer.isStackingContainer()) {
if (Vector<RenderLayer*>* negZOrderList = layer.negZOrderList()) {
- for (size_t i = 0, size = negZOrderList->size(); i < size; ++i) {
- if (layerHas3DContent(*negZOrderList->at(i)))
+ for (auto* renderLayer : *negZOrderList) {
+ if (layerHas3DContent(*renderLayer))
return true;
}
}
if (Vector<RenderLayer*>* posZOrderList = layer.posZOrderList()) {
- for (size_t i = 0, size = posZOrderList->size(); i < size; ++i) {
- if (layerHas3DContent(*posZOrderList->at(i)))
+ for (auto* renderLayer : *posZOrderList) {
+ if (layerHas3DContent(*renderLayer))
return true;
}
}
}
if (Vector<RenderLayer*>* normalFlowList = layer.normalFlowList()) {
- for (size_t i = 0, size = normalFlowList->size(); i < size; ++i) {
- if (layerHas3DContent(*normalFlowList->at(i)))
+ for (auto* renderLayer : *normalFlowList) {
+ if (layerHas3DContent(*renderLayer))
return true;
}
}
@@ -3357,37 +3626,42 @@ bool RenderLayerCompositor::layerHas3DContent(const RenderLayer& layer) const
void RenderLayerCompositor::deviceOrPageScaleFactorChanged()
{
- // Start at the RenderView's layer, since that's where the scale is applied.
- RenderLayer* viewLayer = m_renderView.layer();
- if (!viewLayer->isComposited())
- return;
-
- if (GraphicsLayer* rootLayer = viewLayer->backing()->childForSuperlayers())
+ // Page scale will only be applied at to the RenderView and sublayers, but the device scale factor
+ // needs to be applied at the level of rootGraphicsLayer().
+ GraphicsLayer* rootLayer = rootGraphicsLayer();
+ if (rootLayer)
rootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants();
}
-void RenderLayerCompositor::updateViewportConstraintStatus(RenderLayer& layer)
+void RenderLayerCompositor::updateScrollCoordinatedStatus(RenderLayer& layer)
{
+ LayerScrollCoordinationRoles coordinationRoles = 0;
if (isViewportConstrainedFixedOrStickyLayer(layer))
- addViewportConstrainedLayer(layer);
- else
- removeViewportConstrainedLayer(layer);
-}
+ coordinationRoles |= ViewportConstrained;
-void RenderLayerCompositor::addViewportConstrainedLayer(RenderLayer& layer)
-{
- m_viewportConstrainedLayers.add(&layer);
- registerOrUpdateViewportConstrainedLayer(layer);
+ if (useCoordinatedScrollingForLayer(m_renderView, layer))
+ coordinationRoles |= Scrolling;
+
+ if (coordinationRoles) {
+ if (m_scrollCoordinatedLayers.add(&layer).isNewEntry)
+ m_subframeScrollLayersNeedReattach = true;
+
+ updateScrollCoordinatedLayer(layer, coordinationRoles);
+ } else
+ removeFromScrollCoordinatedLayers(layer);
}
-void RenderLayerCompositor::removeViewportConstrainedLayer(RenderLayer& layer)
+void RenderLayerCompositor::removeFromScrollCoordinatedLayers(RenderLayer& layer)
{
- if (!m_viewportConstrainedLayers.contains(&layer))
+ if (!m_scrollCoordinatedLayers.contains(&layer))
return;
- unregisterViewportConstrainedLayer(layer);
- m_viewportConstrainedLayers.remove(&layer);
- m_viewportConstrainedLayersNeedingUpdate.remove(&layer);
+ m_subframeScrollLayersNeedReattach = true;
+
+ m_scrollCoordinatedLayers.remove(&layer);
+ m_scrollCoordinatedLayersNeedingUpdate.remove(&layer);
+
+ detachScrollCoordinatedLayer(layer, Scrolling | ViewportConstrained);
}
FixedPositionViewportConstraints RenderLayerCompositor::computeFixedViewportConstraints(RenderLayer& layer) const
@@ -3395,11 +3669,12 @@ FixedPositionViewportConstraints RenderLayerCompositor::computeFixedViewportCons
ASSERT(layer.isComposited());
GraphicsLayer* graphicsLayer = layer.backing()->graphicsLayer();
- LayoutRect viewportRect = m_renderView.frameView().viewportConstrainedVisibleContentRect();
+ LayoutRect viewportRect = m_renderView.frameView().rectForFixedPositionLayout();
FixedPositionViewportConstraints constraints;
constraints.setLayerPositionAtLastLayout(graphicsLayer->position());
constraints.setViewportRectAtLastLayout(viewportRect);
+ constraints.setAlignmentOffset(graphicsLayer->pixelAlignmentOffset());
const RenderStyle& style = layer.renderer().style();
if (!style.left().isAuto())
@@ -3434,98 +3709,258 @@ StickyPositionViewportConstraints RenderLayerCompositor::computeStickyViewportCo
ASSERT(!layer.enclosingOverflowClipLayer(ExcludeSelf));
#endif
- LayoutRect viewportRect = m_renderView.frameView().viewportConstrainedVisibleContentRect();
- RenderBoxModelObject& renderer = toRenderBoxModelObject(layer.renderer());
+ RenderBoxModelObject& renderer = downcast<RenderBoxModelObject>(layer.renderer());
StickyPositionViewportConstraints constraints;
- renderer.computeStickyPositionConstraints(constraints, viewportRect);
+ renderer.computeStickyPositionConstraints(constraints, renderer.constrainingRectForStickyPosition());
GraphicsLayer* graphicsLayer = layer.backing()->graphicsLayer();
constraints.setLayerPositionAtLastLayout(graphicsLayer->position());
constraints.setStickyOffsetAtLastLayout(renderer.stickyPositionOffset());
+ constraints.setAlignmentOffset(graphicsLayer->pixelAlignmentOffset());
return constraints;
}
-#if !PLATFORM(IOS)
-static RenderLayerBacking* nearestScrollingCoordinatorAncestor(RenderLayer& layer)
+static ScrollingNodeID enclosingScrollingNodeID(RenderLayer& layer, IncludeSelfOrNot includeSelf)
{
- RenderLayer* ancestor = layer.parent();
- while (ancestor) {
- if (RenderLayerBacking* backing = ancestor->backing()) {
- if (backing->scrollLayerID() && !ancestor->scrollsOverflow())
- return backing;
+ RenderLayer* currLayer = includeSelf == IncludeSelf ? &layer : layer.parent();
+ while (currLayer) {
+ if (RenderLayerBacking* backing = currLayer->backing()) {
+ if (ScrollingNodeID nodeID = backing->scrollingNodeIDForChildren())
+ return nodeID;
}
- ancestor = ancestor->parent();
+ currLayer = currLayer->parent();
}
- return nullptr;
+ return 0;
}
-#endif
-void RenderLayerCompositor::registerOrUpdateViewportConstrainedLayer(RenderLayer& layer)
+static ScrollingNodeID scrollCoordinatedAncestorInParentOfFrame(Frame& frame)
{
-#if PLATFORM(IOS)
- UNUSED_PARAM(layer);
- // On iOS, we batch-update viewport-constrained layers in updateCustomLayersAfterFlush().
-#else
- // FIXME: We should support sticky position here! And we should eventuall support fixed/sticky elements
- // that are inside non-main frames once we get non-main frames scrolling with the ScrollingCoordinator.
- if (m_renderView.document().ownerElement())
+ if (!frame.document() || !frame.view())
+ return 0;
+
+ // Find the frame's enclosing layer in our render tree.
+ HTMLFrameOwnerElement* ownerElement = frame.document()->ownerElement();
+ RenderElement* frameRenderer = ownerElement ? ownerElement->renderer() : nullptr;
+ if (!frameRenderer)
+ return 0;
+
+ RenderLayer* layerInParentDocument = frameRenderer->enclosingLayer();
+ if (!layerInParentDocument)
+ return 0;
+
+ return enclosingScrollingNodeID(*layerInParentDocument, IncludeSelf);
+}
+
+void RenderLayerCompositor::reattachSubframeScrollLayers()
+{
+ if (!m_subframeScrollLayersNeedReattach)
+ return;
+
+ m_subframeScrollLayersNeedReattach = false;
+
+ ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
+
+ for (Frame* child = m_renderView.frameView().frame().tree().firstChild(); child; child = child->tree().nextSibling()) {
+ if (!child->document() || !child->view())
+ continue;
+
+ // Ignore frames that are not scroll-coordinated.
+ FrameView* childFrameView = child->view();
+ ScrollingNodeID frameScrollingNodeID = childFrameView->scrollLayerID();
+ if (!frameScrollingNodeID)
+ continue;
+
+ ScrollingNodeID parentNodeID = scrollCoordinatedAncestorInParentOfFrame(*child);
+ if (!parentNodeID)
+ continue;
+
+ scrollingCoordinator->attachToStateTree(FrameScrollingNode, frameScrollingNodeID, parentNodeID);
+ }
+}
+
+static inline LayerScrollCoordinationRole scrollCoordinationRoleForNodeType(ScrollingNodeType nodeType)
+{
+ switch (nodeType) {
+ case FrameScrollingNode:
+ case OverflowScrollingNode:
+ return Scrolling;
+ case FixedNode:
+ case StickyNode:
+ return ViewportConstrained;
+ }
+ ASSERT_NOT_REACHED();
+ return Scrolling;
+}
+
+ScrollingNodeID RenderLayerCompositor::attachScrollingNode(RenderLayer& layer, ScrollingNodeType nodeType, ScrollingNodeID parentNodeID)
+{
+ ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
+ RenderLayerBacking* backing = layer.backing();
+ // Crash logs suggest that backing can be null here, but we don't know how: rdar://problem/18545452.
+ ASSERT(backing);
+ if (!backing)
+ return 0;
+
+ LayerScrollCoordinationRole role = scrollCoordinationRoleForNodeType(nodeType);
+ ScrollingNodeID nodeID = backing->scrollingNodeIDForRole(role);
+ if (!nodeID)
+ nodeID = scrollingCoordinator->uniqueScrollLayerID();
+
+ nodeID = scrollingCoordinator->attachToStateTree(nodeType, nodeID, parentNodeID);
+ if (!nodeID)
+ return 0;
+
+ backing->setScrollingNodeIDForRole(nodeID, role);
+ m_scrollingNodeToLayerMap.add(nodeID, &layer);
+
+ return nodeID;
+}
+
+void RenderLayerCompositor::detachScrollCoordinatedLayer(RenderLayer& layer, LayerScrollCoordinationRoles roles)
+{
+ RenderLayerBacking* backing = layer.backing();
+ if (!backing)
return;
+ if (roles & Scrolling) {
+ if (ScrollingNodeID nodeID = backing->scrollingNodeIDForRole(Scrolling))
+ m_scrollingNodeToLayerMap.remove(nodeID);
+ }
+
+ if (roles & ViewportConstrained) {
+ if (ScrollingNodeID nodeID = backing->scrollingNodeIDForRole(ViewportConstrained))
+ m_scrollingNodeToLayerMap.remove(nodeID);
+ }
+
+ backing->detachFromScrollingCoordinator(roles);
+}
+
+void RenderLayerCompositor::updateScrollCoordinationForThisFrame(ScrollingNodeID parentNodeID)
+{
+ ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
+ ASSERT(scrollingCoordinator->coordinatesScrollingForFrameView(m_renderView.frameView()));
+
+ ScrollingNodeID nodeID = attachScrollingNode(*m_renderView.layer(), FrameScrollingNode, parentNodeID);
+ scrollingCoordinator->updateFrameScrollingNode(nodeID, m_scrollLayer.get(), m_rootContentLayer.get(), fixedRootBackgroundLayer(), clipLayer());
+}
+
+void RenderLayerCompositor::updateScrollCoordinatedLayer(RenderLayer& layer, LayerScrollCoordinationRoles reasons)
+{
ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
- if (!scrollingCoordinator)
+ if (!scrollingCoordinator || !scrollingCoordinator->coordinatesScrollingForFrameView(m_renderView.frameView()))
return;
- // FIXME: rename to supportsViewportConstrainedPositionLayers()?
- if (!scrollingCoordinator->supportsFixedPositionLayers() || !layer.parent())
+ bool isRootLayer = &layer == m_renderView.layer();
+
+ // FIXME: Remove supportsFixedPositionLayers() since all platforms support them now.
+ if (!scrollingCoordinator->supportsFixedPositionLayers() || (!layer.parent() && !isRootLayer))
return;
- ASSERT(m_viewportConstrainedLayers.contains(&layer));
+ ASSERT(m_scrollCoordinatedLayers.contains(&layer));
ASSERT(layer.isComposited());
RenderLayerBacking* backing = layer.backing();
if (!backing)
return;
- ScrollingNodeID nodeID = backing->scrollLayerID();
- RenderLayerBacking* parent = nearestScrollingCoordinatorAncestor(layer);
- if (!parent)
- return;
+ if (!m_renderView.frame().isMainFrame()) {
+ ScrollingNodeID parentDocumentHostingNodeID = scrollCoordinatedAncestorInParentOfFrame(m_renderView.frame());
+ if (!parentDocumentHostingNodeID)
+ return;
+
+ updateScrollCoordinationForThisFrame(parentDocumentHostingNodeID);
+ if (!(reasons & ViewportConstrained) && isRootLayer)
+ return;
+ }
+ ScrollingNodeID parentNodeID = enclosingScrollingNodeID(layer, ExcludeSelf);
+ if (!parentNodeID && !isRootLayer)
+ return;
+
// Always call this even if the backing is already attached because the parent may have changed.
- backing->attachToScrollingCoordinatorWithParent(parent);
- nodeID = backing->scrollLayerID();
+ // If a node plays both roles, fixed/sticky is always the ancestor node of scrolling.
+ if (reasons & ViewportConstrained) {
+ ScrollingNodeType nodeType = FrameScrollingNode;
+ if (layer.renderer().style().position() == FixedPosition)
+ nodeType = FixedNode;
+ else if (layer.renderer().style().position() == StickyPosition)
+ nodeType = StickyNode;
+ else
+ ASSERT_NOT_REACHED();
- if (layer.renderer().isStickyPositioned())
- scrollingCoordinator->updateViewportConstrainedNode(nodeID, computeStickyViewportConstraints(layer), backing->graphicsLayer());
- else
- scrollingCoordinator->updateViewportConstrainedNode(nodeID, computeFixedViewportConstraints(layer), backing->graphicsLayer());
+ ScrollingNodeID nodeID = attachScrollingNode(layer, nodeType, parentNodeID);
+ if (!nodeID)
+ return;
+
+ switch (nodeType) {
+ case FixedNode:
+ scrollingCoordinator->updateViewportConstrainedNode(nodeID, computeFixedViewportConstraints(layer), backing->graphicsLayer());
+ break;
+ case StickyNode:
+ scrollingCoordinator->updateViewportConstrainedNode(nodeID, computeStickyViewportConstraints(layer), backing->graphicsLayer());
+ break;
+ case FrameScrollingNode:
+ case OverflowScrollingNode:
+ break;
+ }
+
+ parentNodeID = nodeID;
+ } else
+ detachScrollCoordinatedLayer(layer, ViewportConstrained);
+
+ if (reasons & Scrolling) {
+ if (isRootLayer)
+ updateScrollCoordinationForThisFrame(parentNodeID);
+ else {
+ ScrollingNodeType nodeType = OverflowScrollingNode;
+ ScrollingNodeID nodeID = attachScrollingNode(layer, nodeType, parentNodeID);
+ if (!nodeID)
+ return;
+
+ ScrollingCoordinator::ScrollingGeometry scrollingGeometry;
+ scrollingGeometry.scrollOrigin = layer.scrollOrigin();
+ scrollingGeometry.scrollPosition = layer.scrollPosition();
+ scrollingGeometry.scrollableAreaSize = layer.visibleSize();
+ scrollingGeometry.contentSize = layer.contentsSize();
+ scrollingGeometry.reachableContentSize = layer.scrollableContentsSize();
+#if ENABLE(CSS_SCROLL_SNAP)
+ if (const Vector<LayoutUnit>* offsets = layer.horizontalSnapOffsets())
+ scrollingGeometry.horizontalSnapOffsets = *offsets;
+ if (const Vector<LayoutUnit>* offsets = layer.verticalSnapOffsets())
+ scrollingGeometry.verticalSnapOffsets = *offsets;
+ if (const Vector<ScrollOffsetRange<LayoutUnit>>* ranges = layer.horizontalSnapOffsetRanges())
+ scrollingGeometry.horizontalSnapOffsetRanges = *ranges;
+ if (const Vector<ScrollOffsetRange<LayoutUnit>>* ranges = layer.verticalSnapOffsetRanges())
+ scrollingGeometry.verticalSnapOffsetRanges = *ranges;
+ scrollingGeometry.currentHorizontalSnapPointIndex = layer.currentHorizontalSnapPointIndex();
+ scrollingGeometry.currentVerticalSnapPointIndex = layer.currentVerticalSnapPointIndex();
#endif
+ scrollingCoordinator->updateOverflowScrollingNode(nodeID, backing->scrollingLayer(), backing->scrollingContentsLayer(), &scrollingGeometry);
+ }
+ } else
+ detachScrollCoordinatedLayer(layer, Scrolling);
}
-void RenderLayerCompositor::unregisterViewportConstrainedLayer(RenderLayer& layer)
+ScrollableArea* RenderLayerCompositor::scrollableAreaForScrollLayerID(ScrollingNodeID nodeID) const
{
- ASSERT(m_viewportConstrainedLayers.contains(&layer));
-#if PLATFORM(IOS)
- UNUSED_PARAM(layer);
- // On iOS, we batch-update viewport-constrained layers in updateCustomLayersAfterFlush().
-#else
- if (RenderLayerBacking* backing = layer.backing())
- backing->detachFromScrollingCoordinator();
-#endif
+ if (!nodeID)
+ return nullptr;
+
+ return m_scrollingNodeToLayerMap.get(nodeID);
}
#if PLATFORM(IOS)
-typedef HashMap<PlatformLayer*, OwnPtr<ViewportConstraints>> LayerMap;
+typedef HashMap<PlatformLayer*, std::unique_ptr<ViewportConstraints>> LayerMap;
typedef HashMap<PlatformLayer*, PlatformLayer*> StickyContainerMap;
void RenderLayerCompositor::registerAllViewportConstrainedLayers()
{
// Only the main frame should register fixed/sticky layers.
- if (m_renderView.document().ownerElement())
+ if (!isMainFrameCompositor())
return;
if (scrollingCoordinator())
@@ -3534,87 +3969,96 @@ void RenderLayerCompositor::registerAllViewportConstrainedLayers()
LayerMap layerMap;
StickyContainerMap stickyContainerMap;
- for (auto it = m_viewportConstrainedLayers.begin(), end = m_viewportConstrainedLayers.end(); it != end; ++it) {
- RenderLayer& layer = **it;
- ASSERT(layer.isComposited());
+ for (auto* layer : m_scrollCoordinatedLayers) {
+ ASSERT(layer->isComposited());
std::unique_ptr<ViewportConstraints> constraints;
- if (layer.renderer().isStickyPositioned()) {
- constraints = std::make_unique<StickyPositionViewportConstraints>(computeStickyViewportConstraints(layer));
+ if (layer->renderer().isStickyPositioned()) {
+ constraints = std::make_unique<StickyPositionViewportConstraints>(computeStickyViewportConstraints(*layer));
const RenderLayer* enclosingTouchScrollableLayer = nullptr;
- if (isStickyInAcceleratedScrollingLayerOrViewport(layer, &enclosingTouchScrollableLayer) && enclosingTouchScrollableLayer) {
+ if (isAsyncScrollableStickyLayer(*layer, &enclosingTouchScrollableLayer) && enclosingTouchScrollableLayer) {
ASSERT(enclosingTouchScrollableLayer->isComposited());
- stickyContainerMap.add(layer.backing()->graphicsLayer()->platformLayer(), enclosingTouchScrollableLayer->backing()->scrollingLayer()->platformLayer());
+ stickyContainerMap.add(layer->backing()->graphicsLayer()->platformLayer(), enclosingTouchScrollableLayer->backing()->scrollingLayer()->platformLayer());
}
- } else
- constraints = std::make_unique<FixedPositionViewportConstraints>(computeFixedViewportConstraints(layer));
+ } else if (layer->renderer().style().position() == FixedPosition)
+ constraints = std::make_unique<FixedPositionViewportConstraints>(computeFixedViewportConstraints(*layer));
+ else
+ continue;
- layerMap.add(layer.backing()->graphicsLayer()->platformLayer(), adoptPtr(constraints.release()));
+ layerMap.add(layer->backing()->graphicsLayer()->platformLayer(), WTFMove(constraints));
}
- if (ChromeClient* client = this->chromeClient())
- client->updateViewportConstrainedLayers(layerMap, stickyContainerMap);
+ page().chrome().client().updateViewportConstrainedLayers(layerMap, stickyContainerMap);
}
void RenderLayerCompositor::unregisterAllViewportConstrainedLayers()
{
// Only the main frame should register fixed/sticky layers.
- if (m_renderView.document().ownerElement())
+ if (!isMainFrameCompositor())
return;
if (scrollingCoordinator())
return;
- if (ChromeClient* client = this->chromeClient()) {
- LayerMap layerMap;
- StickyContainerMap stickyContainerMap;
- client->updateViewportConstrainedLayers(layerMap, stickyContainerMap);
- }
+ LayerMap layerMap;
+ StickyContainerMap stickyContainerMap;
+ page().chrome().client().updateViewportConstrainedLayers(layerMap, stickyContainerMap);
}
void RenderLayerCompositor::registerAllScrollingLayers()
{
- ChromeClient* client = this->chromeClient();
- if (!client)
- return;
-
- for (auto it = m_scrollingLayers.begin(), end = m_scrollingLayers.end(); it != end; ++it)
- updateScrollingLayerWithClient(**it, client);
+ for (auto* layer : m_scrollingLayers)
+ updateScrollingLayerWithClient(*layer, page().chrome().client());
}
void RenderLayerCompositor::unregisterAllScrollingLayers()
{
- ChromeClient* client = this->chromeClient();
- if (!client)
- return;
-
- for (auto it = m_scrollingLayers.begin(), end = m_scrollingLayers.end(); it != end; ++it) {
- RenderLayer& layer = **it;
- RenderLayerBacking* backing = layer.backing();
+ for (auto* layer : m_scrollingLayers) {
+ RenderLayerBacking* backing = layer->backing();
ASSERT(backing);
- client->removeScrollingLayer(layer.renderer().element(), backing->scrollingLayer()->platformLayer(), backing->scrollingContentsLayer()->platformLayer());
+ page().chrome().client().removeScrollingLayer(layer->renderer().element(), backing->scrollingLayer()->platformLayer(), backing->scrollingContentsLayer()->platformLayer());
}
}
+#endif
-// Called when the size of the contentsLayer changes, and when the contentsLayer is replaced by another layer.
-void RenderLayerCompositor::scrollingLayerAddedOrUpdated(RenderLayer* layer)
+void RenderLayerCompositor::willRemoveScrollingLayerWithBacking(RenderLayer& layer, RenderLayerBacking& backing)
{
- ASSERT(!m_renderView.document().inPageCache());
- m_scrollingLayers.add(layer);
+ if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
+ backing.detachFromScrollingCoordinator(Scrolling);
+
+ // For Coordinated Graphics.
+ scrollingCoordinator->scrollableAreaScrollLayerDidChange(layer);
+ return;
+ }
+
+#if PLATFORM(IOS)
+ m_scrollingLayersNeedingUpdate.remove(&layer);
+ m_scrollingLayers.remove(&layer);
+
+ if (m_renderView.document().pageCacheState() != Document::NotInPageCache)
+ return;
+
+ PlatformLayer* scrollingLayer = backing.scrollingLayer()->platformLayer();
+ PlatformLayer* contentsLayer = backing.scrollingContentsLayer()->platformLayer();
+ page().chrome().client().removeScrollingLayer(layer.renderer().element(), scrollingLayer, contentsLayer);
+#endif
}
-void RenderLayerCompositor::scrollingLayerRemoved(RenderLayer* layer, PlatformLayer* scrollingLayer, PlatformLayer* contentsLayer)
+void RenderLayerCompositor::didAddScrollingLayer(RenderLayer& layer)
{
- m_scrollingLayersNeedingUpdate.remove(layer);
- m_scrollingLayers.remove(layer);
+ updateScrollCoordinatedStatus(layer);
- if (m_renderView.document().inPageCache())
+ if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
+ // For Coordinated Graphics.
+ scrollingCoordinator->scrollableAreaScrollLayerDidChange(layer);
return;
+ }
- if (ChromeClient* client = this->chromeClient())
- client->removeScrollingLayer(layer->renderer().element(), scrollingLayer, contentsLayer);
-}
+#if PLATFORM(IOS)
+ ASSERT(m_renderView.document().pageCacheState() == Document::NotInPageCache);
+ m_scrollingLayers.add(&layer);
#endif
+}
void RenderLayerCompositor::windowScreenDidChange(PlatformDisplayID displayID)
{
@@ -3624,23 +4068,12 @@ void RenderLayerCompositor::windowScreenDidChange(PlatformDisplayID displayID)
ScrollingCoordinator* RenderLayerCompositor::scrollingCoordinator() const
{
- if (Page* page = this->page())
- return page->scrollingCoordinator();
-
- return 0;
+ return page().scrollingCoordinator();
}
GraphicsLayerFactory* RenderLayerCompositor::graphicsLayerFactory() const
{
- if (Page* page = this->page())
- return page->chrome().client().graphicsLayerFactory();
-
- return 0;
-}
-
-Page* RenderLayerCompositor::page() const
-{
- return m_renderView.frameView().frame().page();
+ return page().chrome().client().graphicsLayerFactory();
}
void RenderLayerCompositor::setLayerFlushThrottlingEnabled(bool enabled)
@@ -3690,27 +4123,54 @@ void RenderLayerCompositor::startInitialLayerFlushTimerIfNeeded()
m_layerFlushTimer.startOneShot(throttledLayerFlushInitialDelay);
}
-void RenderLayerCompositor::layerFlushTimerFired(Timer<RenderLayerCompositor>&)
+void RenderLayerCompositor::layerFlushTimerFired()
{
if (!m_hasPendingLayerFlush)
return;
scheduleLayerFlushNow();
}
-void RenderLayerCompositor::paintRelatedMilestonesTimerFired(Timer<RenderLayerCompositor>&)
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+RefPtr<DisplayRefreshMonitor> RenderLayerCompositor::createDisplayRefreshMonitor(PlatformDisplayID displayID) const
{
- Frame& frame = m_renderView.frameView().frame();
- Page* page = frame.page();
- if (!page)
- return;
+ if (auto monitor = page().chrome().client().createDisplayRefreshMonitor(displayID))
+ return monitor;
- // If the layer tree is frozen, we'll paint when it's unfrozen and schedule the timer again.
- if (page->chrome().client().layerTreeStateIsFrozen())
- return;
+ return DisplayRefreshMonitor::createDefaultDisplayRefreshMonitor(displayID);
+}
+#endif
- m_renderView.frameView().firePaintRelatedMilestones();
+void RenderLayerCompositor::startTrackingLayerFlushes()
+{
+ m_layerFlushCount = 0;
}
-} // namespace WebCore
+unsigned RenderLayerCompositor::layerFlushCount() const
+{
+ return m_layerFlushCount;
+}
+
+void RenderLayerCompositor::startTrackingCompositingUpdates()
+{
+ m_compositingUpdateCount = 0;
+}
-#endif // USE(ACCELERATED_COMPOSITING)
+unsigned RenderLayerCompositor::compositingUpdateCount() const
+{
+ return m_compositingUpdateCount;
+}
+
+#if ENABLE(CSS_SCROLL_SNAP)
+void RenderLayerCompositor::updateScrollSnapPropertiesWithFrameView(const FrameView& frameView)
+{
+ if (ScrollingCoordinator* coordinator = scrollingCoordinator())
+ coordinator->updateScrollSnapPropertiesWithFrameView(frameView);
+}
+#endif
+
+Page& RenderLayerCompositor::page() const
+{
+ return m_renderView.page();
+}
+
+} // namespace WebCore