• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "config.h"
6 #include "core/rendering/compositing/CompositingReasonFinder.h"
7 
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"
15 
16 namespace blink {
17 
CompositingReasonFinder(RenderView & renderView)18 CompositingReasonFinder::CompositingReasonFinder(RenderView& renderView)
19     : m_renderView(renderView)
20     , m_compositingTriggers(static_cast<CompositingTriggerFlags>(AllCompositingTriggers))
21 {
22     updateTriggers();
23 }
24 
updateTriggers()25 void CompositingReasonFinder::updateTriggers()
26 {
27     m_compositingTriggers = 0;
28 
29     Settings& settings = m_renderView.document().page()->settings();
30     if (settings.preferCompositingToLCDTextEnabled()) {
31         m_compositingTriggers |= ScrollableInnerFrameTrigger;
32         m_compositingTriggers |= OverflowScrollTrigger;
33         m_compositingTriggers |= ViewportConstrainedPositionedTrigger;
34     }
35 }
36 
hasOverflowScrollTrigger() const37 bool CompositingReasonFinder::hasOverflowScrollTrigger() const
38 {
39     return m_compositingTriggers & OverflowScrollTrigger;
40 }
41 
isMainFrame() const42 bool CompositingReasonFinder::isMainFrame() const
43 {
44     // FIXME: LocalFrame::isMainFrame() is probably better.
45     return !m_renderView.document().ownerElement();
46 }
47 
directReasons(const RenderLayer * layer) const48 CompositingReasons CompositingReasonFinder::directReasons(const RenderLayer* layer) const
49 {
50     ASSERT(potentialCompositingReasonsFromStyle(layer->renderer()) == layer->potentialCompositingReasonsFromStyle());
51     CompositingReasons styleDeterminedDirectCompositingReasons = layer->potentialCompositingReasonsFromStyle() & CompositingReasonComboAllDirectStyleDeterminedReasons;
52     return styleDeterminedDirectCompositingReasons | nonStyleDeterminedDirectReasons(layer);
53 }
54 
55 // This information doesn't appear to be incorporated into CompositingReasons.
requiresCompositingForScrollableFrame() const56 bool CompositingReasonFinder::requiresCompositingForScrollableFrame() const
57 {
58     // Need this done first to determine overflow.
59     ASSERT(!m_renderView.needsLayout());
60     if (isMainFrame())
61         return false;
62 
63     if (!(m_compositingTriggers & ScrollableInnerFrameTrigger))
64         return false;
65 
66     return m_renderView.frameView()->isScrollable();
67 }
68 
potentialCompositingReasonsFromStyle(RenderObject * renderer) const69 CompositingReasons CompositingReasonFinder::potentialCompositingReasonsFromStyle(RenderObject* renderer) const
70 {
71     CompositingReasons reasons = CompositingReasonNone;
72 
73     RenderStyle* style = renderer->style();
74 
75     if (requiresCompositingForTransform(renderer))
76         reasons |= CompositingReason3DTransform;
77 
78     if (style->backfaceVisibility() == BackfaceVisibilityHidden)
79         reasons |= CompositingReasonBackfaceVisibilityHidden;
80 
81     if (requiresCompositingForAnimation(style))
82         reasons |= CompositingReasonActiveAnimation;
83 
84     if (style->hasWillChangeCompositingHint() && !style->subtreeWillChangeContents())
85         reasons |= CompositingReasonWillChangeCompositingHint;
86 
87     if (style->hasInlineTransform())
88         reasons |= CompositingReasonInlineTransform;
89 
90     if (style->transformStyle3D() == TransformStyle3DPreserve3D)
91         reasons |= CompositingReasonPreserve3DWith3DDescendants;
92 
93     if (style->hasPerspective())
94         reasons |= CompositingReasonPerspectiveWith3DDescendants;
95 
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());
98 
99     if (style->hasMask())
100         reasons |= CompositingReasonMaskWithCompositedDescendants;
101 
102     if (style->hasFilter())
103         reasons |= CompositingReasonFilterWithCompositedDescendants;
104 
105     // See RenderLayer::updateTransform for an explanation of why we check both.
106     if (renderer->hasTransform() && style->hasTransform())
107         reasons |= CompositingReasonTransformWithCompositedDescendants;
108 
109     if (renderer->isTransparent())
110         reasons |= CompositingReasonOpacityWithCompositedDescendants;
111 
112     if (renderer->hasBlendMode())
113         reasons |= CompositingReasonBlendingWithCompositedDescendants;
114 
115     if (renderer->hasReflection())
116         reasons |= CompositingReasonReflectionWithCompositedDescendants;
117 
118     ASSERT(!(reasons & ~CompositingReasonComboAllStyleDeterminedReasons));
119     return reasons;
120 }
121 
requiresCompositingForTransform(RenderObject * renderer) const122 bool CompositingReasonFinder::requiresCompositingForTransform(RenderObject* renderer) const
123 {
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();
127 }
128 
nonStyleDeterminedDirectReasons(const RenderLayer * layer) const129 CompositingReasons CompositingReasonFinder::nonStyleDeterminedDirectReasons(const RenderLayer* layer) const
130 {
131     CompositingReasons directReasons = CompositingReasonNone;
132     RenderObject* renderer = layer->renderer();
133 
134     if (hasOverflowScrollTrigger()) {
135         if (layer->clipParent())
136             directReasons |= CompositingReasonOutOfFlowClipping;
137 
138         if (const RenderLayer* scrollingAncestor = layer->ancestorScrollingLayer()) {
139             if (scrollingAncestor->needsCompositedScrolling() && layer->scrollParent())
140                 directReasons |= CompositingReasonOverflowScrollingParent;
141         }
142 
143         if (layer->needsCompositedScrolling())
144             directReasons |= CompositingReasonOverflowScrollingTouch;
145     }
146 
147     if (requiresCompositingForPositionFixed(layer))
148         directReasons |= CompositingReasonPositionFixed;
149 
150     directReasons |= renderer->additionalCompositingReasons();
151 
152     ASSERT(!(directReasons & CompositingReasonComboAllStyleDeterminedReasons));
153     return directReasons;
154 }
155 
requiresCompositingForAnimation(RenderStyle * style) const156 bool CompositingReasonFinder::requiresCompositingForAnimation(RenderStyle* style) const
157 {
158     if (style->subtreeWillChangeContents())
159         return style->isRunningAnimationOnCompositor();
160 
161     return style->shouldCompositeForCurrentAnimations();
162 }
163 
requiresCompositingForPositionFixed(const RenderLayer * layer) const164 bool CompositingReasonFinder::requiresCompositingForPositionFixed(const RenderLayer* layer) const
165 {
166     if (!(m_compositingTriggers & ViewportConstrainedPositionedTrigger))
167         return false;
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();
171 }
172 
173 }
174