1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include "core/rendering/compositing/CompositingReasonFinder.h"
8 #include "core/CSSPropertyNames.h"
9 #include "core/dom/Document.h"
10 #include "core/frame/FrameView.h"
11 #include "core/frame/Settings.h"
12 #include "core/page/Page.h"
13 #include "core/rendering/RenderView.h"
14 #include "core/rendering/compositing/RenderLayerCompositor.h"
18 CompositingReasonFinder::CompositingReasonFinder(RenderView& renderView)
19 : m_renderView(renderView)
20 , m_compositingTriggers(static_cast<CompositingTriggerFlags>(AllCompositingTriggers))
25 void CompositingReasonFinder::updateTriggers()
27 m_compositingTriggers = 0;
29 Settings& settings = m_renderView.document().page()->settings();
30 if (settings.preferCompositingToLCDTextEnabled()) {
31 m_compositingTriggers |= ScrollableInnerFrameTrigger;
32 m_compositingTriggers |= OverflowScrollTrigger;
33 m_compositingTriggers |= ViewportConstrainedPositionedTrigger;
37 bool CompositingReasonFinder::hasOverflowScrollTrigger() const
39 return m_compositingTriggers & OverflowScrollTrigger;
42 bool CompositingReasonFinder::isMainFrame() const
44 // FIXME: LocalFrame::isMainFrame() is probably better.
45 return !m_renderView.document().ownerElement();
48 CompositingReasons CompositingReasonFinder::directReasons(const RenderLayer* layer) const
50 ASSERT(potentialCompositingReasonsFromStyle(layer->renderer()) == layer->potentialCompositingReasonsFromStyle());
51 CompositingReasons styleDeterminedDirectCompositingReasons = layer->potentialCompositingReasonsFromStyle() & CompositingReasonComboAllDirectStyleDeterminedReasons;
52 return styleDeterminedDirectCompositingReasons | nonStyleDeterminedDirectReasons(layer);
55 // This information doesn't appear to be incorporated into CompositingReasons.
56 bool CompositingReasonFinder::requiresCompositingForScrollableFrame() const
58 // Need this done first to determine overflow.
59 ASSERT(!m_renderView.needsLayout());
63 if (!(m_compositingTriggers & ScrollableInnerFrameTrigger))
66 return m_renderView.frameView()->isScrollable();
69 CompositingReasons CompositingReasonFinder::potentialCompositingReasonsFromStyle(RenderObject* renderer) const
71 CompositingReasons reasons = CompositingReasonNone;
73 RenderStyle* style = renderer->style();
75 if (requiresCompositingForTransform(renderer))
76 reasons |= CompositingReason3DTransform;
78 if (style->backfaceVisibility() == BackfaceVisibilityHidden)
79 reasons |= CompositingReasonBackfaceVisibilityHidden;
81 if (requiresCompositingForAnimation(style))
82 reasons |= CompositingReasonActiveAnimation;
84 if (style->hasWillChangeCompositingHint() && !style->subtreeWillChangeContents())
85 reasons |= CompositingReasonWillChangeCompositingHint;
87 if (style->hasInlineTransform())
88 reasons |= CompositingReasonInlineTransform;
90 if (style->transformStyle3D() == TransformStyle3DPreserve3D)
91 reasons |= CompositingReasonPreserve3DWith3DDescendants;
93 if (style->hasPerspective())
94 reasons |= CompositingReasonPerspectiveWith3DDescendants;
96 // If the implementation of createsGroup changes, we need to be aware of that in this part of code.
97 ASSERT((renderer->isTransparent() || renderer->hasMask() || renderer->hasFilter() || renderer->hasBlendMode()) == renderer->createsGroup());
100 reasons |= CompositingReasonMaskWithCompositedDescendants;
102 if (style->hasFilter())
103 reasons |= CompositingReasonFilterWithCompositedDescendants;
105 // See RenderLayer::updateTransform for an explanation of why we check both.
106 if (renderer->hasTransform() && style->hasTransform())
107 reasons |= CompositingReasonTransformWithCompositedDescendants;
109 if (renderer->isTransparent())
110 reasons |= CompositingReasonOpacityWithCompositedDescendants;
112 if (renderer->hasBlendMode())
113 reasons |= CompositingReasonBlendingWithCompositedDescendants;
115 if (renderer->hasReflection())
116 reasons |= CompositingReasonReflectionWithCompositedDescendants;
118 ASSERT(!(reasons & ~CompositingReasonComboAllStyleDeterminedReasons));
122 bool CompositingReasonFinder::requiresCompositingForTransform(RenderObject* renderer) const
124 // Note that we ask the renderer if it has a transform, because the style may have transforms,
125 // but the renderer may be an inline that doesn't suppport them.
126 return renderer->hasTransform() && renderer->style()->transform().has3DOperation();
129 CompositingReasons CompositingReasonFinder::nonStyleDeterminedDirectReasons(const RenderLayer* layer) const
131 CompositingReasons directReasons = CompositingReasonNone;
132 RenderObject* renderer = layer->renderer();
134 if (hasOverflowScrollTrigger()) {
135 if (layer->clipParent())
136 directReasons |= CompositingReasonOutOfFlowClipping;
138 if (const RenderLayer* scrollingAncestor = layer->ancestorScrollingLayer()) {
139 if (scrollingAncestor->needsCompositedScrolling() && layer->scrollParent())
140 directReasons |= CompositingReasonOverflowScrollingParent;
143 if (layer->needsCompositedScrolling())
144 directReasons |= CompositingReasonOverflowScrollingTouch;
147 if (requiresCompositingForPositionFixed(layer))
148 directReasons |= CompositingReasonPositionFixed;
150 directReasons |= renderer->additionalCompositingReasons();
152 ASSERT(!(directReasons & CompositingReasonComboAllStyleDeterminedReasons));
153 return directReasons;
156 bool CompositingReasonFinder::requiresCompositingForAnimation(RenderStyle* style) const
158 if (style->subtreeWillChangeContents())
159 return style->isRunningAnimationOnCompositor();
161 return style->shouldCompositeForCurrentAnimations();
164 bool CompositingReasonFinder::requiresCompositingForPositionFixed(const RenderLayer* layer) const
166 if (!(m_compositingTriggers & ViewportConstrainedPositionedTrigger))
168 // Don't promote fixed position elements that are descendants of a non-view container, e.g. transformed elements.
169 // They will stay fixed wrt the container rather than the enclosing frame.
170 return layer->scrollsWithViewport() && m_renderView.frameView()->isScrollable();