Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / rendering / compositing / CompositingRequirementsUpdater.cpp
1 /*
2  * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2014 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "core/rendering/compositing/CompositingRequirementsUpdater.h"
29
30 #include "CSSPropertyNames.h"
31 #include "HTMLNames.h"
32 #include "RuntimeEnabledFeatures.h"
33 #include "core/animation/ActiveAnimations.h"
34 #include "core/animation/DocumentAnimations.h"
35 #include "core/dom/FullscreenElementStack.h"
36 #include "core/dom/NodeList.h"
37 #include "core/frame/DeprecatedScheduleStyleRecalcDuringCompositingUpdate.h"
38 #include "core/frame/FrameView.h"
39 #include "core/frame/LocalFrame.h"
40 #include "core/frame/Settings.h"
41 #include "core/html/HTMLCanvasElement.h"
42 #include "core/html/HTMLIFrameElement.h"
43 #include "core/html/HTMLMediaElement.h"
44 #include "core/html/canvas/CanvasRenderingContext.h"
45 #include "core/inspector/InspectorInstrumentation.h"
46 #include "core/page/Chrome.h"
47 #include "core/page/Page.h"
48 #include "core/page/scrolling/ScrollingConstraints.h"
49 #include "core/page/scrolling/ScrollingCoordinator.h"
50 #include "core/rendering/HitTestResult.h"
51 #include "core/rendering/RenderApplet.h"
52 #include "core/rendering/RenderEmbeddedObject.h"
53 #include "core/rendering/RenderFullScreen.h"
54 #include "core/rendering/RenderIFrame.h"
55 #include "core/rendering/RenderLayerStackingNode.h"
56 #include "core/rendering/RenderLayerStackingNodeIterator.h"
57 #include "core/rendering/RenderReplica.h"
58 #include "core/rendering/RenderVideo.h"
59 #include "core/rendering/RenderView.h"
60 #include "core/rendering/compositing/CompositedLayerMapping.h"
61 #include "core/rendering/compositing/GraphicsLayerUpdater.h"
62 #include "core/rendering/compositing/RenderLayerCompositor.h"
63 #include "platform/OverscrollTheme.h"
64 #include "platform/TraceEvent.h"
65 #include "platform/geometry/TransformState.h"
66 #include "platform/graphics/GraphicsLayer.h"
67 #include "platform/scroll/ScrollbarTheme.h"
68 #include "public/platform/Platform.h"
69 #include "wtf/TemporaryChange.h"
70
71 namespace WebCore {
72
73 class OverlapMapContainer {
74 public:
75     void add(const IntRect& bounds)
76     {
77         m_layerRects.append(bounds);
78         m_boundingBox.unite(bounds);
79     }
80
81     bool overlapsLayers(const IntRect& bounds) const
82     {
83         // Checking with the bounding box will quickly reject cases when
84         // layers are created for lists of items going in one direction and
85         // never overlap with each other.
86         if (!bounds.intersects(m_boundingBox))
87             return false;
88         for (unsigned i = 0; i < m_layerRects.size(); i++) {
89             if (m_layerRects[i].intersects(bounds))
90                 return true;
91         }
92         return false;
93     }
94
95     void unite(const OverlapMapContainer& otherContainer)
96     {
97         m_layerRects.appendVector(otherContainer.m_layerRects);
98         m_boundingBox.unite(otherContainer.m_boundingBox);
99     }
100 private:
101     Vector<IntRect, 64> m_layerRects;
102     IntRect m_boundingBox;
103 };
104
105 class CompositingRequirementsUpdater::OverlapMap {
106     WTF_MAKE_NONCOPYABLE(OverlapMap);
107 public:
108     OverlapMap()
109     {
110         // Begin by assuming the root layer will be composited so that there
111         // is something on the stack. The root layer should also never get a
112         // finishCurrentOverlapTestingContext() call.
113         beginNewOverlapTestingContext();
114     }
115
116     void add(RenderLayer* layer, const IntRect& bounds)
117     {
118         ASSERT(!layer->isRootLayer());
119         if (bounds.isEmpty())
120             return;
121
122         // Layers do not contribute to overlap immediately--instead, they will
123         // contribute to overlap as soon as they have been recursively processed
124         // and popped off the stack.
125         ASSERT(m_overlapStack.size() >= 2);
126         m_overlapStack[m_overlapStack.size() - 2].add(bounds);
127     }
128
129     bool overlapsLayers(const IntRect& bounds) const
130     {
131         return m_overlapStack.last().overlapsLayers(bounds);
132     }
133
134     void beginNewOverlapTestingContext()
135     {
136         // This effectively creates a new "clean slate" for overlap state.
137         // This is used when we know that a subtree or remaining set of
138         // siblings does not need to check overlap with things behind it.
139         m_overlapStack.append(OverlapMapContainer());
140     }
141
142     void finishCurrentOverlapTestingContext()
143     {
144         // The overlap information on the top of the stack is still necessary
145         // for checking overlap of any layers outside this context that may
146         // overlap things from inside this context. Therefore, we must merge
147         // the information from the top of the stack before popping the stack.
148         //
149         // FIXME: we may be able to avoid this deep copy by rearranging how
150         //        overlapMap state is managed.
151         m_overlapStack[m_overlapStack.size() - 2].unite(m_overlapStack.last());
152         m_overlapStack.removeLast();
153     }
154
155 private:
156     Vector<OverlapMapContainer> m_overlapStack;
157 };
158
159 class CompositingRequirementsUpdater::RecursionData {
160 public:
161     RecursionData(RenderLayer* compAncestor, bool testOverlap)
162         : m_compositingAncestor(compAncestor)
163         , m_subtreeIsCompositing(false)
164         , m_hasUnisolatedCompositedBlendingDescendant(false)
165         , m_testingOverlap(testOverlap)
166 #ifndef NDEBUG
167         , m_depth(0)
168 #endif
169     {
170     }
171
172     RecursionData(const RecursionData& other)
173         : m_compositingAncestor(other.m_compositingAncestor)
174         , m_subtreeIsCompositing(other.m_subtreeIsCompositing)
175         , m_hasUnisolatedCompositedBlendingDescendant(other.m_hasUnisolatedCompositedBlendingDescendant)
176         , m_testingOverlap(other.m_testingOverlap)
177 #ifndef NDEBUG
178         , m_depth(other.m_depth + 1)
179 #endif
180     {
181     }
182
183     RenderLayer* m_compositingAncestor;
184     bool m_subtreeIsCompositing;
185     bool m_hasUnisolatedCompositedBlendingDescendant;
186     bool m_testingOverlap;
187 #ifndef NDEBUG
188     int m_depth;
189 #endif
190 };
191
192 static bool requiresCompositingOrSquashing(CompositingReasons reasons)
193 {
194 #ifndef NDEBUG
195     bool fastAnswer = reasons != CompositingReasonNone;
196     bool slowAnswer = requiresCompositing(reasons) || requiresSquashing(reasons);
197     ASSERT(fastAnswer == slowAnswer);
198 #endif
199     return reasons != CompositingReasonNone;
200 }
201
202 static CompositingReasons subtreeReasonsForCompositing(RenderObject* renderer, bool hasCompositedDescendants, bool has3DTransformedDescendants)
203 {
204     CompositingReasons subtreeReasons = CompositingReasonNone;
205
206     // FIXME: this seems to be a potentially different layer than the layer for which this was called. May not be an error, but is very confusing.
207     RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
208
209     // When a layer has composited descendants, some effects, like 2d transforms, filters, masks etc must be implemented
210     // via compositing so that they also apply to those composited descdendants.
211     if (hasCompositedDescendants) {
212         if (layer->transform())
213             subtreeReasons |= CompositingReasonTransformWithCompositedDescendants;
214
215         if (layer->shouldIsolateCompositedDescendants()) {
216             ASSERT(layer->stackingNode()->isStackingContext());
217             subtreeReasons |= CompositingReasonIsolateCompositedDescendants;
218         }
219
220         // If the implementation of createsGroup changes, we need to be aware of that in this part of code.
221         ASSERT((renderer->isTransparent() || renderer->hasMask() || renderer->hasFilter() || renderer->hasBlendMode()) == renderer->createsGroup());
222         if (renderer->isTransparent())
223             subtreeReasons |= CompositingReasonOpacityWithCompositedDescendants;
224         if (renderer->hasMask())
225             subtreeReasons |= CompositingReasonMaskWithCompositedDescendants;
226         if (renderer->hasFilter())
227             subtreeReasons |= CompositingReasonFilterWithCompositedDescendants;
228         if (renderer->hasBlendMode())
229             subtreeReasons |= CompositingReasonBlendingWithCompositedDescendants;
230
231         if (renderer->hasReflection())
232             subtreeReasons |= CompositingReasonReflectionWithCompositedDescendants;
233
234         if (renderer->hasClipOrOverflowClip())
235             subtreeReasons |= CompositingReasonClipsCompositingDescendants;
236     }
237
238     // A layer with preserve-3d or perspective only needs to be composited if there are descendant layers that
239     // will be affected by the preserve-3d or perspective.
240     if (has3DTransformedDescendants) {
241         if (renderer->style()->transformStyle3D() == TransformStyle3DPreserve3D)
242             subtreeReasons |= CompositingReasonPreserve3DWith3DDescendants;
243
244         if (renderer->style()->hasPerspective())
245             subtreeReasons |= CompositingReasonPerspectiveWith3DDescendants;
246     }
247
248     return subtreeReasons;
249 }
250
251 CompositingRequirementsUpdater::CompositingRequirementsUpdater(RenderView& renderView, CompositingReasonFinder& compositingReasonFinder)
252     : m_renderView(renderView)
253     , m_compositingReasonFinder(compositingReasonFinder)
254 {
255 }
256
257 CompositingRequirementsUpdater::~CompositingRequirementsUpdater()
258 {
259 }
260
261 void CompositingRequirementsUpdater::update(RenderLayer* root)
262 {
263     TRACE_EVENT0("blink_rendering", "CompositingRequirementsUpdater::updateRecursive");
264
265     // Go through the layers in presentation order, so that we can compute which RenderLayers need compositing layers.
266     // FIXME: we could maybe do this and the hierarchy udpate in one pass, but the parenting logic would be more complex.
267     RecursionData recursionData(root, true);
268     OverlapMap overlapTestRequestMap;
269     bool saw3DTransform = false;
270
271     // FIXME: Passing these unclippedDescendants down and keeping track
272     // of them dynamically, we are requiring a full tree walk. This
273     // should be removed as soon as proper overlap testing based on
274     // scrolling and animation bounds is implemented (crbug.com/252472).
275     Vector<RenderLayer*> unclippedDescendants;
276     IntRect absoluteDecendantBoundingBox;
277     updateRecursive(0, root, overlapTestRequestMap, recursionData, saw3DTransform, unclippedDescendants, absoluteDecendantBoundingBox);
278 }
279
280 void CompositingRequirementsUpdater::updateRecursive(RenderLayer* ancestorLayer, RenderLayer* layer, OverlapMap& overlapMap, RecursionData& currentRecursionData, bool& descendantHas3DTransform, Vector<RenderLayer*>& unclippedDescendants, IntRect& absoluteDecendantBoundingBox)
281 {
282     RenderLayerCompositor* compositor = m_renderView.compositor();
283
284     layer->stackingNode()->updateLayerListsIfNeeded();
285
286     // Clear the flag
287     layer->setHasCompositingDescendant(false);
288
289     // Start by assuming this layer will not need to composite.
290     CompositingReasons reasonsToComposite = CompositingReasonNone;
291
292     // First accumulate the straightforward compositing reasons.
293     CompositingReasons directReasons = m_compositingReasonFinder.directReasons(layer);
294
295     // Video is special. It's the only RenderLayer type that can both have
296     // RenderLayer children and whose children can't use its backing to render
297     // into. These children (the controls) always need to be promoted into their
298     // own layers to draw on top of the accelerated video.
299     if (currentRecursionData.m_compositingAncestor && currentRecursionData.m_compositingAncestor->renderer()->isVideo())
300         directReasons |= CompositingReasonVideoOverlay;
301
302     if (compositor->canBeComposited(layer))
303         reasonsToComposite |= directReasons;
304
305     // Next, accumulate reasons related to overlap.
306     // If overlap testing is used, this reason will be overridden. If overlap testing is not
307     // used, we must assume we overlap if there is anything composited behind us in paint-order.
308     CompositingReasons overlapCompositingReason = currentRecursionData.m_subtreeIsCompositing ? CompositingReasonAssumedOverlap : CompositingReasonNone;
309
310     if (m_renderView.compositor()->acceleratedCompositingForOverflowScrollEnabled()) {
311         Vector<size_t> unclippedDescendantsToRemove;
312         for (size_t i = 0; i < unclippedDescendants.size(); i++) {
313             RenderLayer* unclippedDescendant = unclippedDescendants.at(i);
314             // If we've reached the containing block of one of the unclipped
315             // descendants, that element is no longer relevant to whether or not we
316             // should opt in. Unfortunately we can't easily remove from the list
317             // while we're iterating, so we have to store it for later removal.
318             if (unclippedDescendant->renderer()->containingBlock() == layer->renderer()) {
319                 unclippedDescendantsToRemove.append(i);
320                 continue;
321             }
322             if (layer->scrollsWithRespectTo(unclippedDescendant))
323                 reasonsToComposite |= CompositingReasonAssumedOverlap;
324         }
325
326         // Remove irrelevant unclipped descendants in reverse order so our stored
327         // indices remain valid.
328         for (size_t i = 0; i < unclippedDescendantsToRemove.size(); i++)
329             unclippedDescendants.remove(unclippedDescendantsToRemove.at(unclippedDescendantsToRemove.size() - i - 1));
330
331         if (reasonsToComposite & CompositingReasonOutOfFlowClipping)
332             unclippedDescendants.append(layer);
333     }
334
335     const IntRect& absBounds = layer->ancestorDependentProperties().clippedAbsoluteBoundingBox;
336     absoluteDecendantBoundingBox = absBounds;
337
338     if (currentRecursionData.m_testingOverlap && !requiresCompositingOrSquashing(directReasons))
339         overlapCompositingReason = overlapMap.overlapsLayers(absBounds) ? CompositingReasonOverlap : CompositingReasonNone;
340
341     reasonsToComposite |= overlapCompositingReason;
342
343     // The children of this layer don't need to composite, unless there is
344     // a compositing layer among them, so start by inheriting the compositing
345     // ancestor with m_subtreeIsCompositing set to false.
346     RecursionData childRecursionData(currentRecursionData);
347     childRecursionData.m_subtreeIsCompositing = false;
348
349     bool willBeCompositedOrSquashed = compositor->canBeComposited(layer) && requiresCompositingOrSquashing(reasonsToComposite);
350     if (willBeCompositedOrSquashed) {
351         // Tell the parent it has compositing descendants.
352         currentRecursionData.m_subtreeIsCompositing = true;
353         // This layer now acts as the ancestor for kids.
354         childRecursionData.m_compositingAncestor = layer;
355
356         // Here we know that all children and the layer's own contents can blindly paint into
357         // this layer's backing, until a descendant is composited. So, we don't need to check
358         // for overlap with anything behind this layer.
359         overlapMap.beginNewOverlapTestingContext();
360         // This layer is going to be composited, so children can safely ignore the fact that there's an
361         // animation running behind this layer, meaning they can rely on the overlap map testing again.
362         childRecursionData.m_testingOverlap = true;
363     }
364
365 #if !ASSERT_DISABLED
366     LayerListMutationDetector mutationChecker(layer->stackingNode());
367 #endif
368
369     bool anyDescendantHas3DTransform = false;
370     bool willHaveForegroundLayer = false;
371
372     if (layer->stackingNode()->isStackingContainer()) {
373         RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NegativeZOrderChildren);
374         while (RenderLayerStackingNode* curNode = iterator.next()) {
375             IntRect absoluteChildDecendantBoundingBox;
376             updateRecursive(layer, curNode->layer(), overlapMap, childRecursionData, anyDescendantHas3DTransform, unclippedDescendants, absoluteChildDecendantBoundingBox);
377             absoluteDecendantBoundingBox.unite(absoluteChildDecendantBoundingBox);
378
379             // If we have to make a layer for this child, make one now so we can have a contents layer
380             // (since we need to ensure that the -ve z-order child renders underneath our contents).
381             if (childRecursionData.m_subtreeIsCompositing) {
382                 reasonsToComposite |= CompositingReasonNegativeZIndexChildren;
383
384                 if (!willBeCompositedOrSquashed) {
385                     // make layer compositing
386                     childRecursionData.m_compositingAncestor = layer;
387                     overlapMap.beginNewOverlapTestingContext();
388                     willBeCompositedOrSquashed = true;
389                     willHaveForegroundLayer = true;
390
391                     // FIXME: temporary solution for the first negative z-index composited child:
392                     //        re-compute the absBounds for the child so that we can add the
393                     //        negative z-index child's bounds to the new overlap context.
394                     overlapMap.beginNewOverlapTestingContext();
395                     overlapMap.add(curNode->layer(), curNode->layer()->ancestorDependentProperties().clippedAbsoluteBoundingBox);
396                     overlapMap.finishCurrentOverlapTestingContext();
397                 }
398             }
399         }
400     }
401
402     if (willHaveForegroundLayer) {
403         ASSERT(willBeCompositedOrSquashed);
404         // A foreground layer effectively is a new backing for all subsequent children, so
405         // we don't need to test for overlap with anything behind this. So, we can finish
406         // the previous context that was accumulating rects for the negative z-index
407         // children, and start with a fresh new empty context.
408         overlapMap.finishCurrentOverlapTestingContext();
409         overlapMap.beginNewOverlapTestingContext();
410         // This layer is going to be composited, so children can safely ignore the fact that there's an
411         // animation running behind this layer, meaning they can rely on the overlap map testing again
412         childRecursionData.m_testingOverlap = true;
413     }
414
415     RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NormalFlowChildren | PositiveZOrderChildren);
416     while (RenderLayerStackingNode* curNode = iterator.next()) {
417         IntRect absoluteChildDecendantBoundingBox;
418         updateRecursive(layer, curNode->layer(), overlapMap, childRecursionData, anyDescendantHas3DTransform, unclippedDescendants, absoluteChildDecendantBoundingBox);
419         absoluteDecendantBoundingBox.unite(absoluteChildDecendantBoundingBox);
420     }
421
422     // Now that the subtree has been traversed, we can check for compositing reasons that depended on the state of the subtree.
423
424     if (layer->stackingNode()->isStackingContext()) {
425         layer->setShouldIsolateCompositedDescendants(childRecursionData.m_hasUnisolatedCompositedBlendingDescendant);
426     } else {
427         layer->setShouldIsolateCompositedDescendants(false);
428         currentRecursionData.m_hasUnisolatedCompositedBlendingDescendant = childRecursionData.m_hasUnisolatedCompositedBlendingDescendant;
429     }
430
431     // Subsequent layers in the parent's stacking context may also need to composite.
432     if (childRecursionData.m_subtreeIsCompositing)
433         currentRecursionData.m_subtreeIsCompositing = true;
434
435     // Set the flag to say that this SC has compositing children.
436     layer->setHasCompositingDescendant(childRecursionData.m_subtreeIsCompositing);
437
438     if (layer->isRootLayer()) {
439         // The root layer needs to be composited if anything else in the tree is composited.
440         // Otherwise, we can disable compositing entirely.
441         if (childRecursionData.m_subtreeIsCompositing || requiresCompositingOrSquashing(reasonsToComposite) || compositor->rootShouldAlwaysComposite()) {
442             reasonsToComposite |= CompositingReasonRoot;
443         } else {
444             compositor->setCompositingModeEnabled(false);
445             reasonsToComposite = CompositingReasonNone;
446         }
447     } else {
448         // All layers (even ones that aren't being composited) need to get added to
449         // the overlap map. Layers that are not separately composited will paint into their
450         // compositing ancestor's backing, and so are still considered for overlap.
451         if (childRecursionData.m_compositingAncestor && !childRecursionData.m_compositingAncestor->isRootLayer())
452             overlapMap.add(layer, absBounds);
453
454         // Now check for reasons to become composited that depend on the state of descendant layers.
455         CompositingReasons subtreeCompositingReasons = subtreeReasonsForCompositing(layer->renderer(), childRecursionData.m_subtreeIsCompositing, anyDescendantHas3DTransform);
456         reasonsToComposite |= subtreeCompositingReasons;
457         if (!willBeCompositedOrSquashed && compositor->canBeComposited(layer) && requiresCompositingOrSquashing(subtreeCompositingReasons)) {
458             childRecursionData.m_compositingAncestor = layer;
459             // FIXME: this context push is effectively a no-op but needs to exist for
460             // now, because the code is designed to push overlap information to the
461             // second-from-top context of the stack.
462             overlapMap.beginNewOverlapTestingContext();
463             overlapMap.add(layer, absoluteDecendantBoundingBox);
464             willBeCompositedOrSquashed = true;
465         }
466
467         // If the original layer is composited, the reflection needs to be, too.
468         if (layer->reflectionInfo()) {
469             // FIXME: Shouldn't we call computeCompositingRequirements to handle a reflection overlapping with another renderer?
470             RenderLayer* reflectionLayer = layer->reflectionInfo()->reflectionLayer();
471             CompositingReasons reflectionCompositingReason = willBeCompositedOrSquashed ? CompositingReasonReflectionOfCompositedParent : CompositingReasonNone;
472             reflectionLayer->setCompositingReasons(reflectionLayer->compositingReasons() | reflectionCompositingReason);
473         }
474
475         if (willBeCompositedOrSquashed && layer->blendInfo().hasBlendMode())
476             currentRecursionData.m_hasUnisolatedCompositedBlendingDescendant = true;
477
478         // Turn overlap testing off for later layers if it's already off, or if we have an animating transform.
479         // Note that if the layer clips its descendants, there's no reason to propagate the child animation to the parent layers. That's because
480         // we know for sure the animation is contained inside the clipping rectangle, which is already added to the overlap map.
481         bool isCompositedClippingLayer = compositor->canBeComposited(layer) && (reasonsToComposite & CompositingReasonClipsCompositingDescendants);
482         if ((!childRecursionData.m_testingOverlap && !isCompositedClippingLayer) || isRunningAcceleratedTransformAnimation(layer->renderer()))
483             currentRecursionData.m_testingOverlap = false;
484
485         if (childRecursionData.m_compositingAncestor == layer)
486             overlapMap.finishCurrentOverlapTestingContext();
487
488         descendantHas3DTransform |= anyDescendantHas3DTransform || layer->has3DTransform();
489     }
490
491     // At this point we have finished collecting all reasons to composite this layer.
492     layer->setCompositingReasons(reasonsToComposite);
493
494 }
495
496 bool CompositingRequirementsUpdater::isRunningAcceleratedTransformAnimation(RenderObject* renderer) const
497 {
498     return renderer->style()->hasCurrentTransformAnimation();
499 }
500
501 } // namespace WebCore