This source file includes following definitions.
- add
- overlapsLayers
- unite
- OverlapMap
- add
- overlapsLayers
- beginNewOverlapTestingContext
- finishCurrentOverlapTestingContext
- m_rootLayerAttachment
- enableCompositingMode
- cacheAcceleratedCompositingFlags
- layerSquashingEnabled
- canRender3DTransforms
- setCompositingLayersNeedRebuild
- updateCompositingRequirementsState
- findFullscreenVideoRenderer
- finishCompositingUpdateForFrameTree
- setNeedsCompositingUpdate
- clearAncestorDependentPropertyCacheRecursive
- updateCompositingLayers
- scheduleAnimationIfNeeded
- hasUnresolvedDirtyBits
- updateCompositingLayersInternal
- requiresCompositing
- requiresSquashing
- requiresCompositingOrSquashing
- addOutOfFlowPositionedLayer
- removeOutOfFlowPositionedLayer
- allocateOrClearCompositedLayerMapping
- computeOffsetFromAbsolute
- updateSquashingAssignment
- updateLayerIfViewportConstrained
- canSquashIntoCurrentSquashingOwner
- computeCompositedLayerUpdate
- applyUpdateLayerCompositingStateChickenEggHacks
- updateLayerCompositingState
- repaintOnCompositingChange
- repaintInCompositedAncestor
- calculateCompositedBounds
- layerWasAdded
- layerWillBeRemoved
- computeCompositingRequirements
- updateSquashingStateForNewMapping
- assignLayersToBackings
- assignLayersToBackingsForReflectionLayer
- assignLayersToBackingsInternal
- setCompositingParent
- removeCompositedChildren
- frameViewDidChangeLocation
- frameViewDidChangeSize
- frameViewDidScroll
- frameViewScrollbarsExistenceDidChange
- rootFixedBackgroundsChanged
- scrollingLayerDidChange
- layerTreeAsText
- frameContentsCompositor
- parentFrameContentLayers
- repaintCompositedLayers
- recursiveRepaintLayer
- rootRenderLayer
- rootGraphicsLayer
- scrollLayer
- containerLayer
- ensureRootTransformLayer
- setIsInWindow
- updateRootLayerPosition
- updateStyleDeterminedCompositingReasons
- updateDirectCompositingReasons
- needsOwnBacking
- canBeComposited
- clippedByAncestor
- clipsCompositingDescendants
- subtreeReasonsForCompositing
- isRunningAcceleratedTransformAnimation
- needsContentsCompositingLayer
- paintScrollbar
- paintContents
- supportsFixedRootBackgroundCompositing
- needsFixedRootBackgroundLayer
- fixedRootBackgroundLayer
- resetTrackedRepaintRectsRecursive
- resetTrackedRepaintRects
- setTracksRepaints
- isTrackingRepaints
- shouldCompositeOverflowControls
- requiresHorizontalScrollbarLayer
- requiresVerticalScrollbarLayer
- requiresScrollCornerLayer
- requiresOverhangLayers
- updateOverflowControlsLayers
- ensureRootLayer
- destroyRootLayer
- attachRootLayer
- detachRootLayer
- updateRootLayerAttachment
- isMainFrame
- notifyIFramesOfCompositingChange
- updateViewportConstraintStatus
- addViewportConstrainedLayer
- removeViewportConstrainedLayer
- scrollingCoordinator
- graphicsLayerFactory
- page
- lifecycle
- debugName
#include "config.h"
#include "core/rendering/compositing/RenderLayerCompositor.h"
#include "CSSPropertyNames.h"
#include "HTMLNames.h"
#include "RuntimeEnabledFeatures.h"
#include "core/animation/ActiveAnimations.h"
#include "core/animation/DocumentAnimations.h"
#include "core/dom/FullscreenElementStack.h"
#include "core/dom/NodeList.h"
#include "core/frame/DeprecatedScheduleStyleRecalcDuringCompositingUpdate.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/html/HTMLCanvasElement.h"
#include "core/html/HTMLIFrameElement.h"
#include "core/html/HTMLMediaElement.h"
#include "core/html/canvas/CanvasRenderingContext.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/page/Chrome.h"
#include "core/page/Page.h"
#include "core/page/scrolling/ScrollingConstraints.h"
#include "core/page/scrolling/ScrollingCoordinator.h"
#include "core/rendering/HitTestResult.h"
#include "core/rendering/RenderApplet.h"
#include "core/rendering/RenderEmbeddedObject.h"
#include "core/rendering/RenderFullScreen.h"
#include "core/rendering/RenderIFrame.h"
#include "core/rendering/RenderLayerStackingNode.h"
#include "core/rendering/RenderLayerStackingNodeIterator.h"
#include "core/rendering/RenderReplica.h"
#include "core/rendering/RenderVideo.h"
#include "core/rendering/RenderView.h"
#include "core/rendering/compositing/CompositedLayerMapping.h"
#include "core/rendering/compositing/GraphicsLayerUpdater.h"
#include "platform/OverscrollTheme.h"
#include "platform/TraceEvent.h"
#include "platform/geometry/TransformState.h"
#include "platform/graphics/GraphicsLayer.h"
#include "platform/scroll/ScrollbarTheme.h"
#include "public/platform/Platform.h"
#include "wtf/TemporaryChange.h"
#ifndef NDEBUG
#include "core/rendering/RenderTreeAsText.h"
#endif
namespace WebCore {
using namespace HTMLNames;
class OverlapMapContainer {
public:
void add(const IntRect& bounds)
{
m_layerRects.append(bounds);
m_boundingBox.unite(bounds);
}
bool overlapsLayers(const IntRect& bounds) const
{
if (!bounds.intersects(m_boundingBox))
return false;
for (unsigned i = 0; i < m_layerRects.size(); i++) {
if (m_layerRects[i].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<IntRect, 64> m_layerRects;
IntRect m_boundingBox;
};
class RenderLayerCompositor::OverlapMap {
WTF_MAKE_NONCOPYABLE(OverlapMap);
public:
OverlapMap()
{
beginNewOverlapTestingContext();
}
void add(RenderLayer* layer, const IntRect& bounds)
{
if (layer->isRootLayer() || bounds.isEmpty())
return;
ASSERT(m_overlapStack.size() >= 2);
m_overlapStack[m_overlapStack.size() - 2].add(bounds);
}
bool overlapsLayers(const IntRect& bounds) const
{
return m_overlapStack.last().overlapsLayers(bounds);
}
void beginNewOverlapTestingContext()
{
m_overlapStack.append(OverlapMapContainer());
}
void finishCurrentOverlapTestingContext()
{
m_overlapStack[m_overlapStack.size() - 2].unite(m_overlapStack.last());
m_overlapStack.removeLast();
}
private:
Vector<OverlapMapContainer> m_overlapStack;
};
struct CompositingRecursionData {
CompositingRecursionData(RenderLayer* compAncestor, RenderLayer* mostRecentCompositedLayer, bool testOverlap)
: m_compositingAncestor(compAncestor)
, m_mostRecentCompositedLayer(mostRecentCompositedLayer)
, m_subtreeIsCompositing(false)
, m_hasUnisolatedCompositedBlendingDescendant(false)
, m_testingOverlap(testOverlap)
#ifndef NDEBUG
, m_depth(0)
#endif
{
}
CompositingRecursionData(const CompositingRecursionData& other)
: m_compositingAncestor(other.m_compositingAncestor)
, m_mostRecentCompositedLayer(other.m_mostRecentCompositedLayer)
, m_subtreeIsCompositing(other.m_subtreeIsCompositing)
, m_hasUnisolatedCompositedBlendingDescendant(other.m_hasUnisolatedCompositedBlendingDescendant)
, m_testingOverlap(other.m_testingOverlap)
#ifndef NDEBUG
, m_depth(other.m_depth + 1)
#endif
{
}
RenderLayer* m_compositingAncestor;
RenderLayer* m_mostRecentCompositedLayer;
bool m_subtreeIsCompositing;
bool m_hasUnisolatedCompositedBlendingDescendant;
bool m_testingOverlap;
#ifndef NDEBUG
int m_depth;
#endif
};
RenderLayerCompositor::RenderLayerCompositor(RenderView& renderView)
: m_renderView(renderView)
, m_compositingReasonFinder(renderView)
, m_pendingUpdateType(CompositingUpdateNone)
, m_hasAcceleratedCompositing(true)
, m_showRepaintCounter(false)
, m_needsToRecomputeCompositingRequirements(false)
, m_compositing(false)
, m_compositingLayersNeedRebuild(false)
, m_forceCompositingMode(false)
, m_needsUpdateCompositingRequirementsState(false)
, m_isTrackingRepaints(false)
, m_rootLayerAttachment(RootLayerUnattached)
{
}
RenderLayerCompositor::~RenderLayerCompositor()
{
ASSERT(m_rootLayerAttachment == RootLayerUnattached);
}
void RenderLayerCompositor::enableCompositingMode(bool enable)
{
if (enable == m_compositing)
return;
m_compositing = enable;
if (m_compositing)
ensureRootLayer();
else
destroyRootLayer();
notifyIFramesOfCompositingChange();
}
void RenderLayerCompositor::cacheAcceleratedCompositingFlags()
{
bool hasAcceleratedCompositing = false;
bool showRepaintCounter = false;
bool forceCompositingMode = false;
if (Settings* settings = m_renderView.document().settings()) {
hasAcceleratedCompositing = settings->acceleratedCompositingEnabled();
if (hasAcceleratedCompositing) {
if (page()) {
m_compositingReasonFinder.updateTriggers();
hasAcceleratedCompositing = m_compositingReasonFinder.hasTriggers();
}
}
showRepaintCounter = settings->showRepaintCounter();
forceCompositingMode = settings->forceCompositingMode() && hasAcceleratedCompositing;
if (forceCompositingMode && !isMainFrame())
forceCompositingMode = m_compositingReasonFinder.requiresCompositingForScrollableFrame();
}
if (hasAcceleratedCompositing != m_hasAcceleratedCompositing || showRepaintCounter != m_showRepaintCounter || forceCompositingMode != m_forceCompositingMode)
setCompositingLayersNeedRebuild();
m_hasAcceleratedCompositing = hasAcceleratedCompositing;
m_showRepaintCounter = showRepaintCounter;
m_forceCompositingMode = forceCompositingMode;
}
bool RenderLayerCompositor::layerSquashingEnabled() const
{
if (RuntimeEnabledFeatures::bleedingEdgeFastPathsEnabled())
return true;
if (Settings* settings = m_renderView.document().settings())
return settings->layerSquashingEnabled();
return false;
}
bool RenderLayerCompositor::canRender3DTransforms() const
{
return hasAcceleratedCompositing() && m_compositingReasonFinder.has3DTransformTrigger();
}
void RenderLayerCompositor::setCompositingLayersNeedRebuild()
{
if (inCompositingMode())
m_compositingLayersNeedRebuild = true;
page()->animator().scheduleVisualUpdate();
}
void RenderLayerCompositor::updateCompositingRequirementsState()
{
if (!m_needsUpdateCompositingRequirementsState)
return;
TRACE_EVENT0("blink_rendering,comp-scroll", "RenderLayerCompositor::updateCompositingRequirementsState");
m_needsUpdateCompositingRequirementsState = false;
if (!rootRenderLayer() || !m_renderView.acceleratedCompositingForOverflowScrollEnabled())
return;
for (HashSet<RenderLayer*>::iterator it = m_outOfFlowPositionedLayers.begin(); it != m_outOfFlowPositionedLayers.end(); ++it)
(*it)->updateHasUnclippedDescendant();
const FrameView::ScrollableAreaSet* scrollableAreas = m_renderView.frameView()->scrollableAreas();
if (!scrollableAreas)
return;
for (FrameView::ScrollableAreaSet::iterator it = scrollableAreas->begin(); it != scrollableAreas->end(); ++it)
(*it)->updateNeedsCompositedScrolling();
}
static RenderVideo* findFullscreenVideoRenderer(Document& document)
{
Element* fullscreenElement = FullscreenElementStack::fullscreenElementFrom(document);
while (fullscreenElement && fullscreenElement->isFrameOwnerElement()) {
Document* contentDocument = toHTMLFrameOwnerElement(fullscreenElement)->contentDocument();
if (!contentDocument)
return 0;
fullscreenElement = FullscreenElementStack::fullscreenElementFrom(*contentDocument);
}
if (!isHTMLVideoElement(fullscreenElement))
return 0;
RenderObject* renderer = fullscreenElement->renderer();
if (!renderer)
return 0;
return toRenderVideo(renderer);
}
void RenderLayerCompositor::finishCompositingUpdateForFrameTree(LocalFrame* frame)
{
for (LocalFrame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling())
finishCompositingUpdateForFrameTree(child);
if (frame && frame->contentRenderer()) {
RenderLayerCompositor* frameCompositor = frame->contentRenderer()->compositor();
if (frameCompositor && !frameCompositor->isMainFrame())
frame->contentRenderer()->compositor()->updateCompositingLayers();
}
}
void RenderLayerCompositor::setNeedsCompositingUpdate(CompositingUpdateType updateType)
{
ASSERT(updateType != CompositingUpdateNone);
if (m_renderView.needsLayout())
return;
if (m_forceCompositingMode && !m_compositing)
enableCompositingMode(true);
if (!m_needsToRecomputeCompositingRequirements && !m_compositing)
return;
m_pendingUpdateType = std::max(m_pendingUpdateType, updateType);
switch (updateType) {
case CompositingUpdateNone:
ASSERT_NOT_REACHED();
break;
case CompositingUpdateAfterStyleChange:
m_needsToRecomputeCompositingRequirements = true;
break;
case CompositingUpdateAfterLayout:
m_needsToRecomputeCompositingRequirements = true;
break;
case CompositingUpdateOnScroll:
m_needsToRecomputeCompositingRequirements = true;
break;
case CompositingUpdateOnCompositedScroll:
case CompositingUpdateAfterCanvasContextChange:
break;
}
page()->animator().scheduleVisualUpdate();
}
static void clearAncestorDependentPropertyCacheRecursive(RenderLayer* layer)
{
layer->clearAncestorDependentPropertyCache();
RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), AllChildren);
for (RenderLayer* child = layer->firstChild(); child; child = child->nextSibling())
clearAncestorDependentPropertyCacheRecursive(child);
}
void RenderLayerCompositor::updateCompositingLayers()
{
TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::updateCompositingLayers");
if (m_renderView.needsLayout())
return;
lifecycle().advanceTo(DocumentLifecycle::InCompositingUpdate);
updateCompositingLayersInternal();
clearAncestorDependentPropertyCacheRecursive(rootRenderLayer());
lifecycle().advanceTo(DocumentLifecycle::CompositingClean);
DocumentAnimations::startPendingAnimations(m_renderView.document());
ASSERT(m_renderView.document().lifecycle().state() == DocumentLifecycle::CompositingClean);
}
void RenderLayerCompositor::scheduleAnimationIfNeeded()
{
LocalFrame* localFrame = &m_renderView.frameView()->frame();
for (LocalFrame* currentFrame = localFrame; currentFrame; currentFrame = currentFrame->tree().traverseNext(localFrame)) {
if (currentFrame->contentRenderer()) {
RenderLayerCompositor* childCompositor = currentFrame->contentRenderer()->compositor();
if (childCompositor && childCompositor->hasUnresolvedDirtyBits()) {
m_renderView.frameView()->scheduleAnimation();
return;
}
}
}
}
bool RenderLayerCompositor::hasUnresolvedDirtyBits()
{
return m_needsToRecomputeCompositingRequirements || m_compositingLayersNeedRebuild || m_needsUpdateCompositingRequirementsState || m_pendingUpdateType > CompositingUpdateNone;
}
void RenderLayerCompositor::updateCompositingLayersInternal()
{
if (isMainFrame() && m_renderView.frameView())
finishCompositingUpdateForFrameTree(&m_renderView.frameView()->frame());
if (m_forceCompositingMode && !m_compositing)
enableCompositingMode(true);
if (!m_needsToRecomputeCompositingRequirements && !m_compositing)
return;
CompositingUpdateType updateType = m_pendingUpdateType;
bool needCompositingRequirementsUpdate = m_needsToRecomputeCompositingRequirements;
bool needHierarchyAndGeometryUpdate = m_compositingLayersNeedRebuild;
bool needsToUpdateScrollingCoordinator = scrollingCoordinator() ? scrollingCoordinator()->needsToUpdateAfterCompositingChange() : false;
if (updateType == CompositingUpdateNone && !needCompositingRequirementsUpdate && !needHierarchyAndGeometryUpdate && !needsToUpdateScrollingCoordinator)
return;
m_pendingUpdateType = CompositingUpdateNone;
GraphicsLayerUpdater::UpdateType graphicsLayerUpdateType = GraphicsLayerUpdater::DoNotForceUpdate;
CompositingPropertyUpdater::UpdateType compositingPropertyUpdateType = CompositingPropertyUpdater::DoNotForceUpdate;
if (updateType >= CompositingUpdateAfterLayout) {
graphicsLayerUpdateType = GraphicsLayerUpdater::ForceUpdate;
compositingPropertyUpdateType = CompositingPropertyUpdater::ForceUpdate;
}
m_compositingLayersNeedRebuild = false;
m_needsToRecomputeCompositingRequirements = false;
RenderLayer* updateRoot = rootRenderLayer();
if (needCompositingRequirementsUpdate) {
CompositingRecursionData recursionData(updateRoot, 0, true);
bool layersChanged = false;
bool saw3DTransform = false;
{
TRACE_EVENT0("blink_rendering", "CompositingPropertyUpdater::updateAncestorDependentProperties");
CompositingPropertyUpdater(updateRoot).updateAncestorDependentProperties(updateRoot, compositingPropertyUpdateType, 0);
#if !ASSERT_DISABLED
CompositingPropertyUpdater::assertNeedsToUpdateAncestorDependantPropertiesBitsCleared(updateRoot);
#endif
}
{
TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::computeCompositingRequirements");
OverlapMap overlapTestRequestMap;
Vector<RenderLayer*> unclippedDescendants;
IntRect absoluteDecendantBoundingBox;
computeCompositingRequirements(0, updateRoot, overlapTestRequestMap, recursionData, saw3DTransform, unclippedDescendants, absoluteDecendantBoundingBox);
}
{
TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::assignLayersToBackings");
assignLayersToBackings(updateRoot, layersChanged);
}
{
TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::updateHasVisibleNonLayerContentLoop");
const FrameView::ScrollableAreaSet* scrollableAreas = m_renderView.frameView()->scrollableAreas();
if (scrollableAreas) {
for (FrameView::ScrollableAreaSet::iterator it = scrollableAreas->begin(); it != scrollableAreas->end(); ++it)
(*it)->updateHasVisibleNonLayerContent();
}
}
if (layersChanged)
needHierarchyAndGeometryUpdate = true;
}
if (updateType >= CompositingUpdateAfterStyleChange || needHierarchyAndGeometryUpdate) {
TRACE_EVENT0("blink_rendering", "GraphicsLayerUpdater::updateRecursive");
GraphicsLayerUpdater().update(*updateRoot, graphicsLayerUpdateType);
#if !ASSERT_DISABLED
GraphicsLayerUpdater::assertNeedsToUpdateGraphicsLayerBitsCleared(*updateRoot);
#endif
}
if (needHierarchyAndGeometryUpdate) {
GraphicsLayerVector childList;
{
TRACE_EVENT0("blink_rendering", "GraphicsLayerUpdater::rebuildTree");
GraphicsLayerUpdater().rebuildTree(*updateRoot, childList);
}
if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled() && isMainFrame()) {
RenderVideo* video = findFullscreenVideoRenderer(m_renderView.document());
if (video && video->hasCompositedLayerMapping()) {
childList.clear();
childList.append(video->compositedLayerMapping()->mainGraphicsLayer());
}
}
if (childList.isEmpty())
destroyRootLayer();
else
m_rootContentLayer->setChildren(childList);
}
ASSERT(updateRoot || !m_compositingLayersNeedRebuild);
if (!hasAcceleratedCompositing())
enableCompositingMode(false);
needsToUpdateScrollingCoordinator |= scrollingCoordinator() && scrollingCoordinator()->needsToUpdateAfterCompositingChange();
if (needsToUpdateScrollingCoordinator && isMainFrame() && scrollingCoordinator() && inCompositingMode())
scrollingCoordinator()->updateAfterCompositingChange();
if (isMainFrame())
InspectorInstrumentation::layerTreeDidChange(page());
}
static bool requiresCompositing(CompositingReasons reasons)
{
return reasons & ~CompositingReasonComboSquashableReasons;
}
static bool requiresSquashing(CompositingReasons reasons)
{
return !requiresCompositing(reasons) && (reasons & CompositingReasonComboSquashableReasons);
}
static bool requiresCompositingOrSquashing(CompositingReasons reasons)
{
#ifndef NDEBUG
bool fastAnswer = reasons != CompositingReasonNone;
bool slowAnswer = requiresCompositing(reasons) || requiresSquashing(reasons);
ASSERT(fastAnswer == slowAnswer);
#endif
return reasons != CompositingReasonNone;
}
void RenderLayerCompositor::addOutOfFlowPositionedLayer(RenderLayer* layer)
{
m_outOfFlowPositionedLayers.add(layer);
}
void RenderLayerCompositor::removeOutOfFlowPositionedLayer(RenderLayer* layer)
{
m_outOfFlowPositionedLayers.remove(layer);
}
bool RenderLayerCompositor::allocateOrClearCompositedLayerMapping(RenderLayer* layer, const CompositingStateTransitionType compositedLayerUpdate)
{
bool compositedLayerMappingChanged = false;
bool nonCompositedReasonChanged = updateLayerIfViewportConstrained(layer);
switch (compositedLayerUpdate) {
case AllocateOwnCompositedLayerMapping:
ASSERT(!layer->hasCompositedLayerMapping());
enableCompositingMode();
repaintOnCompositingChange(layer);
layer->ensureCompositedLayerMapping();
compositedLayerMappingChanged = true;
if (layer->isRootLayer() && isMainFrame()) {
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
scrollingCoordinator->frameViewRootLayerDidChange(m_renderView.frameView());
}
layer->setLostGroupedMapping(false);
layer->setGroupedMapping(0);
if (layer->parent())
layer->repainter().computeRepaintRectsIncludingDescendants();
break;
case RemoveOwnCompositedLayerMapping:
case PutInSquashingLayer:
if (layer->hasCompositedLayerMapping()) {
if (layer->isReflection()) {
RenderLayer* sourceLayer = toRenderLayerModelObject(layer->renderer()->parent())->layer();
if (sourceLayer->hasCompositedLayerMapping()) {
ASSERT(sourceLayer->compositedLayerMapping()->mainGraphicsLayer()->replicaLayer() == layer->compositedLayerMapping()->mainGraphicsLayer());
sourceLayer->compositedLayerMapping()->mainGraphicsLayer()->setReplicatedByLayer(0);
}
}
removeViewportConstrainedLayer(layer);
layer->clearCompositedLayerMapping();
compositedLayerMappingChanged = true;
layer->repainter().computeRepaintRectsIncludingDescendants();
repaintOnCompositingChange(layer);
}
break;
case RemoveFromSquashingLayer:
case NoCompositingStateChange:
break;
}
if (layer->hasCompositedLayerMapping() && layer->compositedLayerMapping()->updateRequiresOwnBackingStoreForIntrinsicReasons())
compositedLayerMappingChanged = true;
if (compositedLayerMappingChanged && layer->renderer()->isRenderPart()) {
RenderLayerCompositor* innerCompositor = frameContentsCompositor(toRenderPart(layer->renderer()));
if (innerCompositor && innerCompositor->inCompositingMode())
innerCompositor->updateRootLayerAttachment();
}
if (compositedLayerMappingChanged)
layer->clipper().clearClipRectsIncludingDescendants(PaintingClipRects);
if (compositedLayerMappingChanged || nonCompositedReasonChanged) {
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
scrollingCoordinator->frameViewFixedObjectsDidChange(m_renderView.frameView());
}
return compositedLayerMappingChanged || nonCompositedReasonChanged;
}
static LayoutPoint computeOffsetFromAbsolute(RenderLayer* layer)
{
TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint());
layer->renderer()->mapLocalToContainer(0, transformState, ApplyContainerFlip);
transformState.flatten();
return LayoutPoint(transformState.lastPlanarPoint());
}
bool RenderLayerCompositor::updateSquashingAssignment(RenderLayer* layer, SquashingState& squashingState, const CompositingStateTransitionType compositedLayerUpdate)
{
if (compositedLayerUpdate == PutInSquashingLayer) {
ASSERT(!layer->hasCompositedLayerMapping());
ASSERT(squashingState.hasMostRecentMapping);
LayoutPoint offsetFromAbsoluteForSquashedLayer = computeOffsetFromAbsolute(layer);
LayoutSize offsetFromSquashingCLM(offsetFromAbsoluteForSquashedLayer.x() - squashingState.offsetFromAbsoluteForSquashingCLM.x(),
offsetFromAbsoluteForSquashedLayer.y() - squashingState.offsetFromAbsoluteForSquashingCLM.y());
bool changedSquashingLayer =
squashingState.mostRecentMapping->updateSquashingLayerAssignment(layer, offsetFromSquashingCLM, squashingState.nextSquashedLayerIndex);
squashingState.nextSquashedLayerIndex++;
if (!changedSquashingLayer)
return true;
layer->clipper().clearClipRectsIncludingDescendants();
repaintOnCompositingChange(layer);
if (layer->parent())
layer->repainter().computeRepaintRectsIncludingDescendants();
return true;
} else if (compositedLayerUpdate == RemoveFromSquashingLayer) {
layer->setGroupedMapping(0);
layer->repainter().computeRepaintRectsIncludingDescendants();
repaintOnCompositingChange(layer);
layer->setLostGroupedMapping(false);
return true;
}
return false;
}
bool RenderLayerCompositor::updateLayerIfViewportConstrained(RenderLayer* layer)
{
RenderLayer::ViewportConstrainedNotCompositedReason viewportConstrainedNotCompositedReason = RenderLayer::NoNotCompositedReason;
m_compositingReasonFinder.requiresCompositingForPosition(layer->renderer(), layer, &viewportConstrainedNotCompositedReason, &m_needsToRecomputeCompositingRequirements);
if (layer->viewportConstrainedNotCompositedReason() != viewportConstrainedNotCompositedReason) {
ASSERT(layer->renderer()->style()->position() == FixedPosition);
layer->setViewportConstrainedNotCompositedReason(viewportConstrainedNotCompositedReason);
return true;
}
return false;
}
bool RenderLayerCompositor::canSquashIntoCurrentSquashingOwner(const RenderLayer* layer, const RenderLayerCompositor::SquashingState& squashingState)
{
if (layer->renderer()->clippingContainer() != squashingState.mostRecentMapping->owningLayer().renderer()->clippingContainer())
return false;
ASSERT(squashingState.hasMostRecentMapping);
if (layer->scrollsWithRespectTo(&squashingState.mostRecentMapping->owningLayer()))
return false;
return true;
}
RenderLayerCompositor::CompositingStateTransitionType RenderLayerCompositor::computeCompositedLayerUpdate(RenderLayer* layer)
{
CompositingStateTransitionType update = NoCompositingStateChange;
if (!layer->subtreeIsInvisible() && needsOwnBacking(layer)) {
if (!layer->hasCompositedLayerMapping()) {
update = AllocateOwnCompositedLayerMapping;
}
} else {
if (layer->hasCompositedLayerMapping())
update = RemoveOwnCompositedLayerMapping;
if (layerSquashingEnabled()) {
if (!layer->subtreeIsInvisible() && requiresSquashing(layer->compositingReasons())) {
update = PutInSquashingLayer;
} else if (layer->groupedMapping() || layer->lostGroupedMapping()) {
update = RemoveFromSquashingLayer;
}
}
}
return update;
}
void RenderLayerCompositor::applyUpdateLayerCompositingStateChickenEggHacks(RenderLayer* layer, CompositingStateTransitionType compositedLayerUpdate)
{
if (compositedLayerUpdate != NoCompositingStateChange)
allocateOrClearCompositedLayerMapping(layer, compositedLayerUpdate);
}
void RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, UpdateLayerCompositingStateOptions options)
{
updateDirectCompositingReasons(layer);
CompositingStateTransitionType compositedLayerUpdate = computeCompositedLayerUpdate(layer);
if (compositedLayerUpdate != NoCompositingStateChange) {
setCompositingLayersNeedRebuild();
setNeedsToRecomputeCompositingRequirements();
}
if (options == UseChickenEggHacks)
applyUpdateLayerCompositingStateChickenEggHacks(layer, compositedLayerUpdate);
}
void RenderLayerCompositor::repaintOnCompositingChange(RenderLayer* layer)
{
if (layer->renderer() != &m_renderView && !layer->renderer()->parent())
return;
RenderLayerModelObject* repaintContainer = layer->renderer()->containerForRepaint();
if (!repaintContainer)
repaintContainer = &m_renderView;
layer->repainter().repaintIncludingNonCompositingDescendants(repaintContainer);
}
void RenderLayerCompositor::repaintInCompositedAncestor(RenderLayer* layer, const LayoutRect& rect)
{
RenderLayer* compositedAncestor = layer->enclosingCompositingLayerForRepaint(ExcludeSelf);
if (compositedAncestor) {
LayoutPoint offset;
layer->convertToLayerCoords(compositedAncestor, offset);
LayoutRect repaintRect = rect;
repaintRect.moveBy(offset);
if (compositedAncestor->compositingState() == PaintsIntoOwnBacking) {
compositedAncestor->repainter().setBackingNeedsRepaintInRect(repaintRect);
} else if (compositedAncestor->compositingState() == PaintsIntoGroupedBacking) {
compositedAncestor->groupedMapping()->squashingLayer()->setNeedsDisplayInRect(repaintRect);
} else {
ASSERT_NOT_REACHED();
}
}
}
LayoutRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer) const
{
if (!canBeComposited(layer))
return LayoutRect();
RenderLayer::CalculateLayerBoundsFlags flags = RenderLayer::DefaultCalculateLayerBoundsFlags | RenderLayer::ExcludeHiddenDescendants;
return layer->calculateLayerBounds(ancestorLayer, 0, flags);
}
void RenderLayerCompositor::layerWasAdded(RenderLayer* , RenderLayer* )
{
setCompositingLayersNeedRebuild();
}
void RenderLayerCompositor::layerWillBeRemoved(RenderLayer* parent, RenderLayer* child)
{
if (!child->hasCompositedLayerMapping() || parent->renderer()->documentBeingDestroyed())
return;
removeViewportConstrainedLayer(child);
{
DisableCompositingQueryAsserts disabler;
repaintInCompositedAncestor(child, child->compositedLayerMapping()->compositedBounds());
}
setCompositingParent(child, 0);
setCompositingLayersNeedRebuild();
}
void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestorLayer, RenderLayer* layer, OverlapMap& overlapMap, CompositingRecursionData& currentRecursionData, bool& descendantHas3DTransform, Vector<RenderLayer*>& unclippedDescendants, IntRect& absoluteDecendantBoundingBox)
{
layer->stackingNode()->updateLayerListsIfNeeded();
layer->setHasCompositingDescendant(false);
layer->setHasNonCompositedChild(false);
CompositingReasons reasonsToComposite = CompositingReasonNone;
CompositingReasons directReasons = m_compositingReasonFinder.directReasons(layer, &m_needsToRecomputeCompositingRequirements);
if (currentRecursionData.m_compositingAncestor && currentRecursionData.m_compositingAncestor->renderer()->isVideo())
directReasons |= CompositingReasonVideoOverlay;
if (canBeComposited(layer))
reasonsToComposite |= directReasons;
CompositingReasons overlapCompositingReason = currentRecursionData.m_subtreeIsCompositing ? CompositingReasonAssumedOverlap : CompositingReasonNone;
if (m_renderView.compositorDrivenAcceleratedScrollingEnabled()) {
Vector<size_t> unclippedDescendantsToRemove;
for (size_t i = 0; i < unclippedDescendants.size(); i++) {
RenderLayer* unclippedDescendant = unclippedDescendants.at(i);
if (unclippedDescendant->renderer()->containingBlock() == layer->renderer()) {
unclippedDescendantsToRemove.append(i);
continue;
}
if (layer->scrollsWithRespectTo(unclippedDescendant))
reasonsToComposite |= CompositingReasonAssumedOverlap;
}
for (size_t i = 0; i < unclippedDescendantsToRemove.size(); i++)
unclippedDescendants.remove(unclippedDescendantsToRemove.at(unclippedDescendantsToRemove.size() - i - 1));
if (reasonsToComposite & CompositingReasonOutOfFlowClipping)
unclippedDescendants.append(layer);
}
const IntRect& absBounds = layer->ancestorDependentProperties().clippedAbsoluteBoundingBox;
absoluteDecendantBoundingBox = absBounds;
if (currentRecursionData.m_testingOverlap && !requiresCompositingOrSquashing(directReasons))
overlapCompositingReason = overlapMap.overlapsLayers(absBounds) ? CompositingReasonOverlap : CompositingReasonNone;
reasonsToComposite |= overlapCompositingReason;
CompositingRecursionData childRecursionData(currentRecursionData);
childRecursionData.m_subtreeIsCompositing = false;
bool willBeCompositedOrSquashed = canBeComposited(layer) && requiresCompositingOrSquashing(reasonsToComposite);
if (willBeCompositedOrSquashed) {
currentRecursionData.m_subtreeIsCompositing = true;
childRecursionData.m_compositingAncestor = layer;
overlapMap.beginNewOverlapTestingContext();
childRecursionData.m_testingOverlap = true;
}
#if !ASSERT_DISABLED
LayerListMutationDetector mutationChecker(layer->stackingNode());
#endif
bool anyDescendantHas3DTransform = false;
bool willHaveForegroundLayer = false;
if (layer->stackingNode()->isStackingContainer()) {
RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NegativeZOrderChildren);
while (RenderLayerStackingNode* curNode = iterator.next()) {
IntRect absoluteChildDecendantBoundingBox;
computeCompositingRequirements(layer, curNode->layer(), overlapMap, childRecursionData, anyDescendantHas3DTransform, unclippedDescendants, absoluteChildDecendantBoundingBox);
absoluteDecendantBoundingBox.unite(absoluteChildDecendantBoundingBox);
if (childRecursionData.m_subtreeIsCompositing) {
reasonsToComposite |= CompositingReasonNegativeZIndexChildren;
if (!willBeCompositedOrSquashed) {
childRecursionData.m_compositingAncestor = layer;
overlapMap.beginNewOverlapTestingContext();
willBeCompositedOrSquashed = true;
willHaveForegroundLayer = true;
overlapMap.beginNewOverlapTestingContext();
overlapMap.add(curNode->layer(), curNode->layer()->ancestorDependentProperties().clippedAbsoluteBoundingBox);
overlapMap.finishCurrentOverlapTestingContext();
}
}
}
}
if (willHaveForegroundLayer) {
ASSERT(willBeCompositedOrSquashed);
overlapMap.finishCurrentOverlapTestingContext();
overlapMap.beginNewOverlapTestingContext();
childRecursionData.m_testingOverlap = true;
}
if (requiresCompositing(reasonsToComposite)) {
currentRecursionData.m_mostRecentCompositedLayer = layer;
childRecursionData.m_mostRecentCompositedLayer = layer;
}
RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NormalFlowChildren | PositiveZOrderChildren);
while (RenderLayerStackingNode* curNode = iterator.next()) {
IntRect absoluteChildDecendantBoundingBox;
computeCompositingRequirements(layer, curNode->layer(), overlapMap, childRecursionData, anyDescendantHas3DTransform, unclippedDescendants, absoluteChildDecendantBoundingBox);
absoluteDecendantBoundingBox.unite(absoluteChildDecendantBoundingBox);
}
currentRecursionData.m_mostRecentCompositedLayer = childRecursionData.m_mostRecentCompositedLayer;
if (layer->isRootLayer()) {
if (inCompositingMode() && m_hasAcceleratedCompositing)
willBeCompositedOrSquashed = true;
}
if (childRecursionData.m_compositingAncestor && !childRecursionData.m_compositingAncestor->isRootLayer())
overlapMap.add(layer, absBounds);
if (layer->stackingNode()->isStackingContext()) {
layer->setShouldIsolateCompositedDescendants(childRecursionData.m_hasUnisolatedCompositedBlendingDescendant);
} else {
layer->setShouldIsolateCompositedDescendants(false);
currentRecursionData.m_hasUnisolatedCompositedBlendingDescendant = childRecursionData.m_hasUnisolatedCompositedBlendingDescendant;
}
CompositingReasons subtreeCompositingReasons = subtreeReasonsForCompositing(layer->renderer(), childRecursionData.m_subtreeIsCompositing, anyDescendantHas3DTransform);
reasonsToComposite |= subtreeCompositingReasons;
if (!willBeCompositedOrSquashed && canBeComposited(layer) && requiresCompositingOrSquashing(subtreeCompositingReasons)) {
childRecursionData.m_compositingAncestor = layer;
overlapMap.beginNewOverlapTestingContext();
overlapMap.add(layer, absoluteDecendantBoundingBox);
willBeCompositedOrSquashed = true;
}
if (layer->reflectionInfo()) {
RenderLayer* reflectionLayer = layer->reflectionInfo()->reflectionLayer();
CompositingReasons reflectionCompositingReason = willBeCompositedOrSquashed ? CompositingReasonReflectionOfCompositedParent : CompositingReasonNone;
reflectionLayer->setCompositingReasons(reflectionLayer->compositingReasons() | reflectionCompositingReason);
}
if (childRecursionData.m_subtreeIsCompositing)
currentRecursionData.m_subtreeIsCompositing = true;
if (willBeCompositedOrSquashed && layer->blendInfo().hasBlendMode())
currentRecursionData.m_hasUnisolatedCompositedBlendingDescendant = true;
layer->setHasCompositingDescendant(childRecursionData.m_subtreeIsCompositing);
bool isCompositedClippingLayer = canBeComposited(layer) && (reasonsToComposite & CompositingReasonClipsCompositingDescendants);
if ((!childRecursionData.m_testingOverlap && !isCompositedClippingLayer) || isRunningAcceleratedTransformAnimation(layer->renderer()))
currentRecursionData.m_testingOverlap = false;
if (childRecursionData.m_compositingAncestor == layer && !layer->isRootLayer())
overlapMap.finishCurrentOverlapTestingContext();
if (layer->isRootLayer()) {
if (childRecursionData.m_subtreeIsCompositing || requiresCompositingOrSquashing(reasonsToComposite) || m_forceCompositingMode) {
willBeCompositedOrSquashed = true;
reasonsToComposite |= CompositingReasonRoot;
} else {
enableCompositingMode(false);
willBeCompositedOrSquashed = false;
reasonsToComposite = CompositingReasonNone;
}
}
if (requiresCompositing(reasonsToComposite))
currentRecursionData.m_mostRecentCompositedLayer = layer;
layer->setCompositingReasons(reasonsToComposite);
if (!willBeCompositedOrSquashed && layer->parent())
layer->parent()->setHasNonCompositedChild(true);
descendantHas3DTransform |= anyDescendantHas3DTransform || layer->has3DTransform();
}
void RenderLayerCompositor::SquashingState::updateSquashingStateForNewMapping(CompositedLayerMappingPtr newCompositedLayerMapping, bool hasNewCompositedLayerMapping, LayoutPoint newOffsetFromAbsoluteForSquashingCLM)
{
if (hasMostRecentMapping)
mostRecentMapping->finishAccumulatingSquashingLayers(nextSquashedLayerIndex);
nextSquashedLayerIndex = 0;
mostRecentMapping = newCompositedLayerMapping;
hasMostRecentMapping = hasNewCompositedLayerMapping;
offsetFromAbsoluteForSquashingCLM = newOffsetFromAbsoluteForSquashingCLM;
}
void RenderLayerCompositor::assignLayersToBackings(RenderLayer* updateRoot, bool& layersChanged)
{
SquashingState squashingState;
assignLayersToBackingsInternal(updateRoot, squashingState, layersChanged);
if (squashingState.hasMostRecentMapping)
squashingState.mostRecentMapping->finishAccumulatingSquashingLayers(squashingState.nextSquashedLayerIndex);
}
void RenderLayerCompositor::assignLayersToBackingsForReflectionLayer(RenderLayer* reflectionLayer, bool& layersChanged)
{
CompositingStateTransitionType compositedLayerUpdate = computeCompositedLayerUpdate(reflectionLayer);
if (compositedLayerUpdate != NoCompositingStateChange) {
layersChanged = true;
allocateOrClearCompositedLayerMapping(reflectionLayer, compositedLayerUpdate);
}
updateDirectCompositingReasons(reflectionLayer);
if (reflectionLayer->hasCompositedLayerMapping())
reflectionLayer->compositedLayerMapping()->updateGraphicsLayerConfiguration(GraphicsLayerUpdater::ForceUpdate);
}
void RenderLayerCompositor::assignLayersToBackingsInternal(RenderLayer* layer, SquashingState& squashingState, bool& layersChanged)
{
if (layerSquashingEnabled() && requiresSquashing(layer->compositingReasons()) && !canSquashIntoCurrentSquashingOwner(layer, squashingState))
layer->setCompositingReasons(layer->compositingReasons() | CompositingReasonNoSquashingTargetFound);
CompositingStateTransitionType compositedLayerUpdate = computeCompositedLayerUpdate(layer);
if (allocateOrClearCompositedLayerMapping(layer, compositedLayerUpdate))
layersChanged = true;
if (layer->reflectionInfo())
assignLayersToBackingsForReflectionLayer(layer->reflectionInfo()->reflectionLayer(), layersChanged);
if (layerSquashingEnabled()) {
if (updateSquashingAssignment(layer, squashingState, compositedLayerUpdate))
layersChanged = true;
}
if (layer->stackingNode()->isStackingContainer()) {
RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NegativeZOrderChildren);
while (RenderLayerStackingNode* curNode = iterator.next())
assignLayersToBackingsInternal(curNode->layer(), squashingState, layersChanged);
}
if (layerSquashingEnabled()) {
if (layer->compositingState() == PaintsIntoOwnBacking || layer->compositingState() == HasOwnBackingButPaintsIntoAncestor) {
ASSERT(!requiresSquashing(layer->compositingReasons()));
LayoutPoint offsetFromAbsoluteForSquashingCLM = computeOffsetFromAbsolute(layer);
squashingState.updateSquashingStateForNewMapping(layer->compositedLayerMapping(), layer->hasCompositedLayerMapping(), offsetFromAbsoluteForSquashingCLM);
}
}
RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NormalFlowChildren | PositiveZOrderChildren);
while (RenderLayerStackingNode* curNode = iterator.next())
assignLayersToBackingsInternal(curNode->layer(), squashingState, layersChanged);
}
void RenderLayerCompositor::setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer)
{
ASSERT(!parentLayer || childLayer->ancestorCompositingLayer() == parentLayer);
ASSERT(childLayer->hasCompositedLayerMapping());
if (!parentLayer || !parentLayer->hasCompositedLayerMapping())
return;
if (parentLayer) {
GraphicsLayer* hostingLayer = parentLayer->compositedLayerMapping()->parentForSublayers();
GraphicsLayer* hostedLayer = childLayer->compositedLayerMapping()->childForSuperlayers();
hostingLayer->addChild(hostedLayer);
} else {
childLayer->compositedLayerMapping()->childForSuperlayers()->removeFromParent();
}
}
void RenderLayerCompositor::removeCompositedChildren(RenderLayer* layer)
{
ASSERT(layer->hasCompositedLayerMapping());
GraphicsLayer* hostingLayer = layer->compositedLayerMapping()->parentForSublayers();
hostingLayer->removeAllChildren();
}
void RenderLayerCompositor::frameViewDidChangeLocation(const IntPoint& contentsOffset)
{
if (m_overflowControlsHostLayer)
m_overflowControlsHostLayer->setPosition(contentsOffset);
}
void RenderLayerCompositor::frameViewDidChangeSize()
{
if (m_containerLayer) {
FrameView* frameView = m_renderView.frameView();
m_containerLayer->setSize(frameView->unscaledVisibleContentSize());
frameViewDidScroll();
updateOverflowControlsLayers();
}
}
enum AcceleratedFixedRootBackgroundHistogramBuckets {
ScrolledMainFrameBucket = 0,
ScrolledMainFrameWithAcceleratedFixedRootBackground = 1,
ScrolledMainFrameWithUnacceleratedFixedRootBackground = 2,
AcceleratedFixedRootBackgroundHistogramMax = 3
};
void RenderLayerCompositor::frameViewDidScroll()
{
FrameView* frameView = m_renderView.frameView();
IntPoint scrollPosition = frameView->scrollPosition();
if (!m_scrollLayer)
return;
bool scrollingCoordinatorHandlesOffset = false;
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
if (Settings* settings = m_renderView.document().settings()) {
if (isMainFrame() || settings->compositedScrollingForFramesEnabled())
scrollingCoordinatorHandlesOffset = scrollingCoordinator->scrollableAreaScrollLayerDidChange(frameView);
}
}
if (scrollingCoordinatorHandlesOffset)
m_scrollLayer->setPosition(-frameView->minimumScrollPosition());
else
m_scrollLayer->setPosition(-scrollPosition);
blink::Platform::current()->histogramEnumeration("Renderer.AcceleratedFixedRootBackground",
ScrolledMainFrameBucket,
AcceleratedFixedRootBackgroundHistogramMax);
}
void RenderLayerCompositor::frameViewScrollbarsExistenceDidChange()
{
if (m_containerLayer)
updateOverflowControlsLayers();
}
void RenderLayerCompositor::rootFixedBackgroundsChanged()
{
if (!supportsFixedRootBackgroundCompositing())
return;
DisableCompositingQueryAsserts disabler;
if (GraphicsLayer* backgroundLayer = fixedRootBackgroundLayer())
m_containerLayer->addChildBelow(backgroundLayer, m_scrollLayer.get());
}
bool RenderLayerCompositor::scrollingLayerDidChange(RenderLayer* layer)
{
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
return scrollingCoordinator->scrollableAreaScrollLayerDidChange(layer->scrollableArea());
return false;
}
String RenderLayerCompositor::layerTreeAsText(LayerTreeFlags flags)
{
ASSERT(m_renderView.document().lifecycle().state() >= DocumentLifecycle::CompositingClean);
if (!m_rootContentLayer)
return String();
GraphicsLayer* rootLayer = m_rootContentLayer.get();
if (flags & LayerTreeIncludesRootLayer)
rootLayer = rootGraphicsLayer();
String layerTreeText = rootLayer->layerTreeAsText(flags);
if (flags & LayerTreeIncludesRepaintRects)
return m_renderView.frameView()->trackedRepaintRectsAsText() + layerTreeText;
return layerTreeText;
}
RenderLayerCompositor* RenderLayerCompositor::frameContentsCompositor(RenderPart* renderer)
{
if (!renderer->node()->isFrameOwnerElement())
return 0;
HTMLFrameOwnerElement* element = toHTMLFrameOwnerElement(renderer->node());
if (Document* contentDocument = element->contentDocument()) {
if (RenderView* view = contentDocument->renderView())
return view->compositor();
}
return 0;
}
bool RenderLayerCompositor::parentFrameContentLayers(RenderPart* renderer)
{
RenderLayerCompositor* innerCompositor = frameContentsCompositor(renderer);
if (!innerCompositor || !innerCompositor->inCompositingMode() || innerCompositor->rootLayerAttachment() != RootLayerAttachedViaEnclosingFrame)
return false;
RenderLayer* layer = renderer->layer();
if (!layer->hasCompositedLayerMapping())
return false;
CompositedLayerMappingPtr compositedLayerMapping = layer->compositedLayerMapping();
GraphicsLayer* hostingLayer = compositedLayerMapping->parentForSublayers();
GraphicsLayer* rootLayer = innerCompositor->rootGraphicsLayer();
if (hostingLayer->children().size() != 1 || hostingLayer->children()[0] != rootLayer) {
hostingLayer->removeAllChildren();
hostingLayer->addChild(rootLayer);
}
return true;
}
void RenderLayerCompositor::repaintCompositedLayers()
{
recursiveRepaintLayer(rootRenderLayer());
}
void RenderLayerCompositor::recursiveRepaintLayer(RenderLayer* layer)
{
if (layer->compositingState() == PaintsIntoOwnBacking)
layer->repainter().setBackingNeedsRepaint();
#if !ASSERT_DISABLED
LayerListMutationDetector mutationChecker(layer->stackingNode());
#endif
unsigned childrenToVisit = NormalFlowChildren;
if (layer->hasCompositingDescendant())
childrenToVisit |= PositiveZOrderChildren | NegativeZOrderChildren;
RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), childrenToVisit);
while (RenderLayerStackingNode* curNode = iterator.next())
recursiveRepaintLayer(curNode->layer());
}
RenderLayer* RenderLayerCompositor::rootRenderLayer() const
{
return m_renderView.layer();
}
GraphicsLayer* RenderLayerCompositor::rootGraphicsLayer() const
{
if (m_overflowControlsHostLayer)
return m_overflowControlsHostLayer.get();
return m_rootContentLayer.get();
}
GraphicsLayer* RenderLayerCompositor::scrollLayer() const
{
return m_scrollLayer.get();
}
GraphicsLayer* RenderLayerCompositor::containerLayer() const
{
return m_containerLayer.get();
}
GraphicsLayer* RenderLayerCompositor::ensureRootTransformLayer()
{
ASSERT(rootGraphicsLayer());
if (!m_rootTransformLayer.get()) {
m_rootTransformLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
m_overflowControlsHostLayer->addChild(m_rootTransformLayer.get());
m_rootTransformLayer->addChild(m_containerLayer.get());
updateOverflowControlsLayers();
}
return m_rootTransformLayer.get();
}
void RenderLayerCompositor::setIsInWindow(bool isInWindow)
{
if (!inCompositingMode())
return;
if (isInWindow) {
if (m_rootLayerAttachment != RootLayerUnattached)
return;
RootLayerAttachment attachment = isMainFrame() ? RootLayerAttachedViaChromeClient : RootLayerAttachedViaEnclosingFrame;
attachRootLayer(attachment);
} else {
if (m_rootLayerAttachment == RootLayerUnattached)
return;
detachRootLayer();
}
}
void RenderLayerCompositor::updateRootLayerPosition()
{
if (m_rootContentLayer) {
const IntRect& documentRect = m_renderView.documentRect();
m_rootContentLayer->setSize(documentRect.size());
m_rootContentLayer->setPosition(documentRect.location());
#if USE(RUBBER_BANDING)
if (m_layerForOverhangShadow)
OverscrollTheme::theme()->updateOverhangShadowLayer(m_layerForOverhangShadow.get(), m_rootContentLayer.get());
#endif
}
if (m_containerLayer) {
FrameView* frameView = m_renderView.frameView();
m_containerLayer->setSize(frameView->unscaledVisibleContentSize());
}
}
void RenderLayerCompositor::updateStyleDeterminedCompositingReasons(RenderLayer* layer)
{
CompositingReasons reasons = m_compositingReasonFinder.styleDeterminedReasons(layer->renderer());
layer->setCompositingReasons(reasons, CompositingReasonComboAllStyleDeterminedReasons);
}
void RenderLayerCompositor::updateDirectCompositingReasons(RenderLayer* layer)
{
CompositingReasons reasons = m_compositingReasonFinder.directReasons(layer, &m_needsToRecomputeCompositingRequirements);
layer->setCompositingReasons(reasons, CompositingReasonComboAllDirectReasons);
}
bool RenderLayerCompositor::needsOwnBacking(const RenderLayer* layer) const
{
if (!canBeComposited(layer))
return false;
bool needsOwnBackingForDisabledSquashing = !layerSquashingEnabled() && requiresSquashing(layer->compositingReasons());
return requiresCompositing(layer->compositingReasons()) || needsOwnBackingForDisabledSquashing || (inCompositingMode() && layer->isRootLayer());
}
bool RenderLayerCompositor::canBeComposited(const RenderLayer* layer) const
{
return m_hasAcceleratedCompositing && layer->isSelfPaintingLayer() && layer->renderer()->flowThreadState() == RenderObject::NotInsideFlowThread;
}
bool RenderLayerCompositor::clippedByAncestor(const RenderLayer* layer) const
{
if (!layer->hasCompositedLayerMapping() || !layer->parent())
return false;
const RenderLayer* compositingAncestor = layer->ancestorCompositingLayer();
if (!compositingAncestor)
return false;
RenderObject* clippingContainer = layer->renderer()->clippingContainer();
if (!clippingContainer)
return false;
if (compositingAncestor->renderer()->isDescendantOf(clippingContainer))
return false;
return true;
}
bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer) const
{
return layer->hasCompositingDescendant() && layer->renderer()->hasClipOrOverflowClip();
}
CompositingReasons RenderLayerCompositor::subtreeReasonsForCompositing(RenderObject* renderer, bool hasCompositedDescendants, bool has3DTransformedDescendants) const
{
CompositingReasons subtreeReasons = CompositingReasonNone;
RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
if (hasCompositedDescendants) {
if (layer->transform())
subtreeReasons |= CompositingReasonTransformWithCompositedDescendants;
if (layer->shouldIsolateCompositedDescendants()) {
ASSERT(layer->stackingNode()->isStackingContext());
subtreeReasons |= CompositingReasonIsolateCompositedDescendants;
}
ASSERT((renderer->isTransparent() || renderer->hasMask() || renderer->hasFilter() || renderer->hasBlendMode()) == renderer->createsGroup());
if (renderer->isTransparent())
subtreeReasons |= CompositingReasonOpacityWithCompositedDescendants;
if (renderer->hasMask())
subtreeReasons |= CompositingReasonMaskWithCompositedDescendants;
if (renderer->hasFilter())
subtreeReasons |= CompositingReasonFilterWithCompositedDescendants;
if (renderer->hasBlendMode())
subtreeReasons |= CompositingReasonBlendingWithCompositedDescendants;
if (renderer->hasReflection())
subtreeReasons |= CompositingReasonReflectionWithCompositedDescendants;
if (renderer->hasClipOrOverflowClip())
subtreeReasons |= CompositingReasonClipsCompositingDescendants;
}
if (has3DTransformedDescendants) {
if (renderer->style()->transformStyle3D() == TransformStyle3DPreserve3D)
subtreeReasons |= CompositingReasonPreserve3DWith3DDescendants;
if (renderer->style()->hasPerspective())
subtreeReasons |= CompositingReasonPerspectiveWith3DDescendants;
}
return subtreeReasons;
}
bool RenderLayerCompositor::isRunningAcceleratedTransformAnimation(RenderObject* renderer) const
{
if (!m_compositingReasonFinder.hasAnimationTrigger())
return false;
return hasActiveAnimations(*renderer, CSSPropertyTransform);
}
bool RenderLayerCompositor::needsContentsCompositingLayer(const RenderLayer* layer) const
{
return layer->stackingNode()->hasNegativeZOrderList();
}
static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
{
if (!scrollbar)
return;
context.save();
const IntRect& scrollbarRect = scrollbar->frameRect();
context.translate(-scrollbarRect.x(), -scrollbarRect.y());
IntRect transformedClip = clip;
transformedClip.moveBy(scrollbarRect.location());
scrollbar->paint(&context, transformedClip);
context.restore();
}
void RenderLayerCompositor::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase, const IntRect& clip)
{
if (graphicsLayer == layerForHorizontalScrollbar())
paintScrollbar(m_renderView.frameView()->horizontalScrollbar(), context, clip);
else if (graphicsLayer == layerForVerticalScrollbar())
paintScrollbar(m_renderView.frameView()->verticalScrollbar(), context, clip);
else if (graphicsLayer == layerForScrollCorner()) {
const IntRect& scrollCorner = m_renderView.frameView()->scrollCornerRect();
context.save();
context.translate(-scrollCorner.x(), -scrollCorner.y());
IntRect transformedClip = clip;
transformedClip.moveBy(scrollCorner.location());
m_renderView.frameView()->paintScrollCorner(&context, transformedClip);
context.restore();
}
}
bool RenderLayerCompositor::supportsFixedRootBackgroundCompositing() const
{
if (Settings* settings = m_renderView.document().settings()) {
if (settings->acceleratedCompositingForFixedRootBackgroundEnabled())
return true;
}
return false;
}
bool RenderLayerCompositor::needsFixedRootBackgroundLayer(const RenderLayer* layer) const
{
if (layer != m_renderView.layer())
return false;
return supportsFixedRootBackgroundCompositing() && m_renderView.rootBackgroundIsEntirelyFixed();
}
GraphicsLayer* RenderLayerCompositor::fixedRootBackgroundLayer() const
{
RenderLayer* viewLayer = m_renderView.layer();
if (!viewLayer)
return 0;
if (viewLayer->compositingState() == PaintsIntoOwnBacking && viewLayer->compositedLayerMapping()->backgroundLayerPaintsFixedRootBackground())
return viewLayer->compositedLayerMapping()->backgroundLayer();
return 0;
}
static void resetTrackedRepaintRectsRecursive(GraphicsLayer* graphicsLayer)
{
if (!graphicsLayer)
return;
graphicsLayer->resetTrackedRepaints();
for (size_t i = 0; i < graphicsLayer->children().size(); ++i)
resetTrackedRepaintRectsRecursive(graphicsLayer->children()[i]);
if (GraphicsLayer* replicaLayer = graphicsLayer->replicaLayer())
resetTrackedRepaintRectsRecursive(replicaLayer);
if (GraphicsLayer* maskLayer = graphicsLayer->maskLayer())
resetTrackedRepaintRectsRecursive(maskLayer);
if (GraphicsLayer* clippingMaskLayer = graphicsLayer->contentsClippingMaskLayer())
resetTrackedRepaintRectsRecursive(clippingMaskLayer);
}
void RenderLayerCompositor::resetTrackedRepaintRects()
{
if (GraphicsLayer* rootLayer = rootGraphicsLayer())
resetTrackedRepaintRectsRecursive(rootLayer);
}
void RenderLayerCompositor::setTracksRepaints(bool tracksRepaints)
{
updateCompositingLayers();
m_isTrackingRepaints = tracksRepaints;
}
bool RenderLayerCompositor::isTrackingRepaints() const
{
return m_isTrackingRepaints;
}
static bool shouldCompositeOverflowControls(FrameView* view)
{
if (Page* page = view->frame().page()) {
if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
if (scrollingCoordinator->coordinatesScrollingForFrameView(view))
return true;
}
return true;
}
bool RenderLayerCompositor::requiresHorizontalScrollbarLayer() const
{
FrameView* view = m_renderView.frameView();
return shouldCompositeOverflowControls(view) && view->horizontalScrollbar();
}
bool RenderLayerCompositor::requiresVerticalScrollbarLayer() const
{
FrameView* view = m_renderView.frameView();
return shouldCompositeOverflowControls(view) && view->verticalScrollbar();
}
bool RenderLayerCompositor::requiresScrollCornerLayer() const
{
FrameView* view = m_renderView.frameView();
return shouldCompositeOverflowControls(view) && view->isScrollCornerVisible();
}
#if USE(RUBBER_BANDING)
bool RenderLayerCompositor::requiresOverhangLayers() const
{
if (!isMainFrame())
return false;
if (scrollingCoordinator() && m_renderView.frameView()->hasOpaqueBackground())
return true;
return true;
}
#endif
void RenderLayerCompositor::updateOverflowControlsLayers()
{
#if USE(RUBBER_BANDING)
if (requiresOverhangLayers()) {
if (!m_layerForOverhangShadow) {
m_layerForOverhangShadow = GraphicsLayer::create(graphicsLayerFactory(), this);
OverscrollTheme::theme()->setUpOverhangShadowLayer(m_layerForOverhangShadow.get());
OverscrollTheme::theme()->updateOverhangShadowLayer(m_layerForOverhangShadow.get(), m_rootContentLayer.get());
m_scrollLayer->addChild(m_layerForOverhangShadow.get());
}
} else {
if (m_layerForOverhangShadow) {
m_layerForOverhangShadow->removeFromParent();
m_layerForOverhangShadow = nullptr;
}
}
#endif
GraphicsLayer* controlsParent = m_rootTransformLayer.get() ? m_rootTransformLayer.get() : m_overflowControlsHostLayer.get();
if (requiresHorizontalScrollbarLayer()) {
if (!m_layerForHorizontalScrollbar) {
m_layerForHorizontalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), this);
controlsParent->addChild(m_layerForHorizontalScrollbar.get());
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
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);
}
if (requiresVerticalScrollbarLayer()) {
if (!m_layerForVerticalScrollbar) {
m_layerForVerticalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), this);
controlsParent->addChild(m_layerForVerticalScrollbar.get());
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
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);
}
if (requiresScrollCornerLayer()) {
if (!m_layerForScrollCorner) {
m_layerForScrollCorner = GraphicsLayer::create(graphicsLayerFactory(), this);
controlsParent->addChild(m_layerForScrollCorner.get());
}
} else if (m_layerForScrollCorner) {
m_layerForScrollCorner->removeFromParent();
m_layerForScrollCorner = nullptr;
}
m_renderView.frameView()->positionScrollbarLayers();
}
void RenderLayerCompositor::ensureRootLayer()
{
RootLayerAttachment expectedAttachment = isMainFrame() ? RootLayerAttachedViaChromeClient : RootLayerAttachedViaEnclosingFrame;
if (expectedAttachment == m_rootLayerAttachment)
return;
if (!m_rootContentLayer) {
m_rootContentLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
IntRect overflowRect = m_renderView.pixelSnappedLayoutOverflowRect();
m_rootContentLayer->setSize(FloatSize(overflowRect.maxX(), overflowRect.maxY()));
m_rootContentLayer->setPosition(FloatPoint());
m_rootContentLayer->setMasksToBounds(true);
}
if (!m_overflowControlsHostLayer) {
ASSERT(!m_scrollLayer);
ASSERT(!m_containerLayer);
m_overflowControlsHostLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
m_containerLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
bool containerMasksToBounds = !isMainFrame();
if (Settings* settings = m_renderView.document().settings()) {
if (settings->mainFrameClipsContent())
containerMasksToBounds = true;
}
m_containerLayer->setMasksToBounds(containerMasksToBounds);
m_scrollLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(m_scrollLayer.get(), true);
m_overflowControlsHostLayer->addChild(m_containerLayer.get());
m_containerLayer->addChild(m_scrollLayer.get());
m_scrollLayer->addChild(m_rootContentLayer.get());
frameViewDidChangeSize();
frameViewDidScroll();
}
if (m_rootLayerAttachment != RootLayerUnattached)
detachRootLayer();
attachRootLayer(expectedAttachment);
}
void RenderLayerCompositor::destroyRootLayer()
{
if (!m_rootContentLayer)
return;
detachRootLayer();
#if USE(RUBBER_BANDING)
if (m_layerForOverhangShadow) {
m_layerForOverhangShadow->removeFromParent();
m_layerForOverhangShadow = nullptr;
}
#endif
if (m_layerForHorizontalScrollbar) {
m_layerForHorizontalScrollbar->removeFromParent();
m_layerForHorizontalScrollbar = nullptr;
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
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()));
}
if (m_layerForVerticalScrollbar) {
m_layerForVerticalScrollbar->removeFromParent();
m_layerForVerticalScrollbar = nullptr;
if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
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()));
}
if (m_layerForScrollCorner) {
m_layerForScrollCorner = nullptr;
m_renderView.frameView()->invalidateScrollCorner(m_renderView.frameView()->scrollCornerRect());
}
if (m_overflowControlsHostLayer) {
m_overflowControlsHostLayer = nullptr;
m_containerLayer = nullptr;
m_scrollLayer = nullptr;
}
ASSERT(!m_scrollLayer);
m_rootContentLayer = nullptr;
m_rootTransformLayer = nullptr;
}
void RenderLayerCompositor::attachRootLayer(RootLayerAttachment attachment)
{
if (!m_rootContentLayer)
return;
switch (attachment) {
case RootLayerUnattached:
ASSERT_NOT_REACHED();
break;
case RootLayerAttachedViaChromeClient: {
LocalFrame& frame = m_renderView.frameView()->frame();
Page* page = frame.page();
if (!page)
return;
page->chrome().client().attachRootGraphicsLayer(rootGraphicsLayer());
break;
}
case RootLayerAttachedViaEnclosingFrame: {
HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement();
ASSERT(ownerElement);
DeprecatedScheduleStyleRecalcDuringCompositingUpdate marker(ownerElement->document().lifecycle());
ownerElement->scheduleLayerUpdate();
break;
}
}
m_rootLayerAttachment = attachment;
}
void RenderLayerCompositor::detachRootLayer()
{
if (!m_rootContentLayer || m_rootLayerAttachment == RootLayerUnattached)
return;
switch (m_rootLayerAttachment) {
case RootLayerAttachedViaEnclosingFrame: {
if (m_overflowControlsHostLayer)
m_overflowControlsHostLayer->removeFromParent();
else
m_rootContentLayer->removeFromParent();
if (HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement()) {
DeprecatedScheduleStyleRecalcDuringCompositingUpdate marker(ownerElement->document().lifecycle());
ownerElement->scheduleLayerUpdate();
}
break;
}
case RootLayerAttachedViaChromeClient: {
LocalFrame& frame = m_renderView.frameView()->frame();
Page* page = frame.page();
if (!page)
return;
page->chrome().client().attachRootGraphicsLayer(0);
}
break;
case RootLayerUnattached:
break;
}
m_rootLayerAttachment = RootLayerUnattached;
}
void RenderLayerCompositor::updateRootLayerAttachment()
{
ensureRootLayer();
}
bool RenderLayerCompositor::isMainFrame() const
{
return !m_renderView.document().ownerElement();
}
void RenderLayerCompositor::notifyIFramesOfCompositingChange()
{
if (!m_renderView.frameView())
return;
LocalFrame& frame = m_renderView.frameView()->frame();
for (LocalFrame* child = frame.tree().firstChild(); child; child = child->tree().traverseNext(&frame)) {
if (!child->document())
continue;
if (HTMLFrameOwnerElement* ownerElement = child->document()->ownerElement()) {
DeprecatedScheduleStyleRecalcDuringCompositingUpdate marker(ownerElement->document().lifecycle());
ownerElement->scheduleLayerUpdate();
}
}
if (HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement()) {
ownerElement->document().renderView()->compositor()->setNeedsToRecomputeCompositingRequirements();
DeprecatedScheduleStyleRecalcDuringCompositingUpdate marker(ownerElement->document().lifecycle());
ownerElement->scheduleLayerUpdate();
}
}
void RenderLayerCompositor::updateViewportConstraintStatus(RenderLayer* layer)
{
if (CompositingReasonFinder::isViewportConstrainedFixedOrStickyLayer(layer))
addViewportConstrainedLayer(layer);
else
removeViewportConstrainedLayer(layer);
}
void RenderLayerCompositor::addViewportConstrainedLayer(RenderLayer* layer)
{
m_viewportConstrainedLayers.add(layer);
}
void RenderLayerCompositor::removeViewportConstrainedLayer(RenderLayer* layer)
{
if (!m_viewportConstrainedLayers.contains(layer))
return;
m_viewportConstrainedLayers.remove(layer);
}
ScrollingCoordinator* RenderLayerCompositor::scrollingCoordinator() const
{
if (Page* page = this->page())
return page->scrollingCoordinator();
return 0;
}
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();
}
DocumentLifecycle& RenderLayerCompositor::lifecycle() const
{
return m_renderView.document().lifecycle();
}
String RenderLayerCompositor::debugName(const GraphicsLayer* graphicsLayer)
{
String name;
if (graphicsLayer == m_rootContentLayer.get()) {
name = "Content Root Layer";
} else if (graphicsLayer == m_rootTransformLayer.get()) {
name = "Root Transform Layer";
#if USE(RUBBER_BANDING)
} else if (graphicsLayer == m_layerForOverhangShadow.get()) {
name = "Overhang Areas Shadow";
#endif
} else if (graphicsLayer == m_overflowControlsHostLayer.get()) {
name = "Overflow Controls Host Layer";
} else if (graphicsLayer == m_layerForHorizontalScrollbar.get()) {
name = "Horizontal Scrollbar Layer";
} else if (graphicsLayer == m_layerForVerticalScrollbar.get()) {
name = "Vertical Scrollbar Layer";
} else if (graphicsLayer == m_layerForScrollCorner.get()) {
name = "Scroll Corner Layer";
} else if (graphicsLayer == m_containerLayer.get()) {
name = "LocalFrame Clipping Layer";
} else if (graphicsLayer == m_scrollLayer.get()) {
name = "LocalFrame Scrolling Layer";
} else {
ASSERT_NOT_REACHED();
}
return name;
}
}