OLD | NEW |
(Empty) | |
| 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 if (layer->isRootLayer() || bounds.isEmpty()) |
| 119 return; |
| 120 |
| 121 // Layers do not contribute to overlap immediately--instead, they will |
| 122 // contribute to overlap as soon as they have been recursively processed |
| 123 // and popped off the stack. |
| 124 ASSERT(m_overlapStack.size() >= 2); |
| 125 m_overlapStack[m_overlapStack.size() - 2].add(bounds); |
| 126 } |
| 127 |
| 128 bool overlapsLayers(const IntRect& bounds) const |
| 129 { |
| 130 return m_overlapStack.last().overlapsLayers(bounds); |
| 131 } |
| 132 |
| 133 void beginNewOverlapTestingContext() |
| 134 { |
| 135 // This effectively creates a new "clean slate" for overlap state. |
| 136 // This is used when we know that a subtree or remaining set of |
| 137 // siblings does not need to check overlap with things behind it. |
| 138 m_overlapStack.append(OverlapMapContainer()); |
| 139 } |
| 140 |
| 141 void finishCurrentOverlapTestingContext() |
| 142 { |
| 143 // The overlap information on the top of the stack is still necessary |
| 144 // for checking overlap of any layers outside this context that may |
| 145 // overlap things from inside this context. Therefore, we must merge |
| 146 // the information from the top of the stack before popping the stack. |
| 147 // |
| 148 // FIXME: we may be able to avoid this deep copy by rearranging how |
| 149 // overlapMap state is managed. |
| 150 m_overlapStack[m_overlapStack.size() - 2].unite(m_overlapStack.last()); |
| 151 m_overlapStack.removeLast(); |
| 152 } |
| 153 |
| 154 private: |
| 155 Vector<OverlapMapContainer> m_overlapStack; |
| 156 }; |
| 157 |
| 158 class CompositingRequirementsUpdater::RecursionData { |
| 159 public: |
| 160 RecursionData(RenderLayer* compAncestor, RenderLayer* mostRecentCompositedLa
yer, bool testOverlap) |
| 161 : m_compositingAncestor(compAncestor) |
| 162 , m_mostRecentCompositedLayer(mostRecentCompositedLayer) |
| 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_mostRecentCompositedLayer(other.m_mostRecentCompositedLayer) |
| 175 , m_subtreeIsCompositing(other.m_subtreeIsCompositing) |
| 176 , m_hasUnisolatedCompositedBlendingDescendant(other.m_hasUnisolatedCompo
sitedBlendingDescendant) |
| 177 , m_testingOverlap(other.m_testingOverlap) |
| 178 #ifndef NDEBUG |
| 179 , m_depth(other.m_depth + 1) |
| 180 #endif |
| 181 { |
| 182 } |
| 183 |
| 184 RenderLayer* m_compositingAncestor; |
| 185 RenderLayer* m_mostRecentCompositedLayer; // in paint order regardless of hi
erarchy. |
| 186 bool m_subtreeIsCompositing; |
| 187 bool m_hasUnisolatedCompositedBlendingDescendant; |
| 188 bool m_testingOverlap; |
| 189 #ifndef NDEBUG |
| 190 int m_depth; |
| 191 #endif |
| 192 }; |
| 193 |
| 194 static bool requiresCompositingOrSquashing(CompositingReasons reasons) |
| 195 { |
| 196 #ifndef NDEBUG |
| 197 bool fastAnswer = reasons != CompositingReasonNone; |
| 198 bool slowAnswer = requiresCompositing(reasons) || requiresSquashing(reasons)
; |
| 199 ASSERT(fastAnswer == slowAnswer); |
| 200 #endif |
| 201 return reasons != CompositingReasonNone; |
| 202 } |
| 203 |
| 204 static CompositingReasons subtreeReasonsForCompositing(RenderObject* renderer, b
ool hasCompositedDescendants, bool has3DTransformedDescendants) |
| 205 { |
| 206 CompositingReasons subtreeReasons = CompositingReasonNone; |
| 207 |
| 208 // 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. |
| 209 RenderLayer* layer = toRenderBoxModelObject(renderer)->layer(); |
| 210 |
| 211 // When a layer has composited descendants, some effects, like 2d transforms
, filters, masks etc must be implemented |
| 212 // via compositing so that they also apply to those composited descdendants. |
| 213 if (hasCompositedDescendants) { |
| 214 if (layer->transform()) |
| 215 subtreeReasons |= CompositingReasonTransformWithCompositedDescendant
s; |
| 216 |
| 217 if (layer->shouldIsolateCompositedDescendants()) { |
| 218 ASSERT(layer->stackingNode()->isStackingContext()); |
| 219 subtreeReasons |= CompositingReasonIsolateCompositedDescendants; |
| 220 } |
| 221 |
| 222 // If the implementation of createsGroup changes, we need to be aware of
that in this part of code. |
| 223 ASSERT((renderer->isTransparent() || renderer->hasMask() || renderer->ha
sFilter() || renderer->hasBlendMode()) == renderer->createsGroup()); |
| 224 if (renderer->isTransparent()) |
| 225 subtreeReasons |= CompositingReasonOpacityWithCompositedDescendants; |
| 226 if (renderer->hasMask()) |
| 227 subtreeReasons |= CompositingReasonMaskWithCompositedDescendants; |
| 228 if (renderer->hasFilter()) |
| 229 subtreeReasons |= CompositingReasonFilterWithCompositedDescendants; |
| 230 if (renderer->hasBlendMode()) |
| 231 subtreeReasons |= CompositingReasonBlendingWithCompositedDescendants
; |
| 232 |
| 233 if (renderer->hasReflection()) |
| 234 subtreeReasons |= CompositingReasonReflectionWithCompositedDescendan
ts; |
| 235 |
| 236 if (renderer->hasClipOrOverflowClip()) |
| 237 subtreeReasons |= CompositingReasonClipsCompositingDescendants; |
| 238 } |
| 239 |
| 240 |
| 241 // A layer with preserve-3d or perspective only needs to be composited if th
ere are descendant layers that |
| 242 // will be affected by the preserve-3d or perspective. |
| 243 if (has3DTransformedDescendants) { |
| 244 if (renderer->style()->transformStyle3D() == TransformStyle3DPreserve3D) |
| 245 subtreeReasons |= CompositingReasonPreserve3DWith3DDescendants; |
| 246 |
| 247 if (renderer->style()->hasPerspective()) |
| 248 subtreeReasons |= CompositingReasonPerspectiveWith3DDescendants; |
| 249 } |
| 250 |
| 251 return subtreeReasons; |
| 252 } |
| 253 |
| 254 CompositingRequirementsUpdater::CompositingRequirementsUpdater(RenderView& rende
rView, CompositingReasonFinder& compositingReasonFinder, bool* needsToRecomputeC
ompositingRequirements) |
| 255 : m_renderView(renderView) |
| 256 , m_compositingReasonFinder(compositingReasonFinder) |
| 257 , m_needsToRecomputeCompositingRequirements(needsToRecomputeCompositingRequi
rements) |
| 258 { |
| 259 } |
| 260 |
| 261 CompositingRequirementsUpdater::~CompositingRequirementsUpdater() |
| 262 { |
| 263 } |
| 264 |
| 265 void CompositingRequirementsUpdater::update(RenderLayer* root) |
| 266 { |
| 267 TRACE_EVENT0("blink_rendering", "CompositingRequirementsUpdater::updateRecur
sive"); |
| 268 |
| 269 // Go through the layers in presentation order, so that we can compute which
RenderLayers need compositing layers. |
| 270 // FIXME: we could maybe do this and the hierarchy udpate in one pass, but t
he parenting logic would be more complex. |
| 271 RecursionData recursionData(root, 0, true); |
| 272 OverlapMap overlapTestRequestMap; |
| 273 bool saw3DTransform = false; |
| 274 |
| 275 // FIXME: Passing these unclippedDescendants down and keeping track |
| 276 // of them dynamically, we are requiring a full tree walk. This |
| 277 // should be removed as soon as proper overlap testing based on |
| 278 // scrolling and animation bounds is implemented (crbug.com/252472). |
| 279 Vector<RenderLayer*> unclippedDescendants; |
| 280 IntRect absoluteDecendantBoundingBox; |
| 281 updateRecursive(0, root, overlapTestRequestMap, recursionData, saw3DTransfor
m, unclippedDescendants, absoluteDecendantBoundingBox); |
| 282 } |
| 283 |
| 284 void CompositingRequirementsUpdater::updateRecursive(RenderLayer* ancestorLayer,
RenderLayer* layer, OverlapMap& overlapMap, RecursionData& currentRecursionData
, bool& descendantHas3DTransform, Vector<RenderLayer*>& unclippedDescendants, In
tRect& absoluteDecendantBoundingBox) |
| 285 { |
| 286 RenderLayerCompositor* compositor = m_renderView.compositor(); |
| 287 |
| 288 layer->stackingNode()->updateLayerListsIfNeeded(); |
| 289 |
| 290 // Clear the flag |
| 291 layer->setHasCompositingDescendant(false); |
| 292 |
| 293 // Start by assuming this layer will not need to composite. |
| 294 CompositingReasons reasonsToComposite = CompositingReasonNone; |
| 295 |
| 296 // First accumulate the straightforward compositing reasons. |
| 297 CompositingReasons directReasons = m_compositingReasonFinder.directReasons(l
ayer, m_needsToRecomputeCompositingRequirements); |
| 298 |
| 299 // Video is special. It's the only RenderLayer type that can both have |
| 300 // RenderLayer children and whose children can't use its backing to render |
| 301 // into. These children (the controls) always need to be promoted into their |
| 302 // own layers to draw on top of the accelerated video. |
| 303 if (currentRecursionData.m_compositingAncestor && currentRecursionData.m_com
positingAncestor->renderer()->isVideo()) |
| 304 directReasons |= CompositingReasonVideoOverlay; |
| 305 |
| 306 if (compositor->canBeComposited(layer)) |
| 307 reasonsToComposite |= directReasons; |
| 308 |
| 309 // Next, accumulate reasons related to overlap. |
| 310 // If overlap testing is used, this reason will be overridden. If overlap te
sting is not |
| 311 // used, we must assume we overlap if there is anything composited behind us
in paint-order. |
| 312 CompositingReasons overlapCompositingReason = currentRecursionData.m_subtree
IsCompositing ? CompositingReasonAssumedOverlap : CompositingReasonNone; |
| 313 |
| 314 if (m_renderView.compositorDrivenAcceleratedScrollingEnabled()) { |
| 315 Vector<size_t> unclippedDescendantsToRemove; |
| 316 for (size_t i = 0; i < unclippedDescendants.size(); i++) { |
| 317 RenderLayer* unclippedDescendant = unclippedDescendants.at(i); |
| 318 // If we've reached the containing block of one of the unclipped |
| 319 // descendants, that element is no longer relevant to whether or not
we |
| 320 // should opt in. Unfortunately we can't easily remove from the list |
| 321 // while we're iterating, so we have to store it for later removal. |
| 322 if (unclippedDescendant->renderer()->containingBlock() == layer->ren
derer()) { |
| 323 unclippedDescendantsToRemove.append(i); |
| 324 continue; |
| 325 } |
| 326 if (layer->scrollsWithRespectTo(unclippedDescendant)) |
| 327 reasonsToComposite |= CompositingReasonAssumedOverlap; |
| 328 } |
| 329 |
| 330 // Remove irrelevant unclipped descendants in reverse order so our store
d |
| 331 // indices remain valid. |
| 332 for (size_t i = 0; i < unclippedDescendantsToRemove.size(); i++) |
| 333 unclippedDescendants.remove(unclippedDescendantsToRemove.at(unclippe
dDescendantsToRemove.size() - i - 1)); |
| 334 |
| 335 if (reasonsToComposite & CompositingReasonOutOfFlowClipping) |
| 336 unclippedDescendants.append(layer); |
| 337 } |
| 338 |
| 339 const IntRect& absBounds = layer->ancestorDependentProperties().clippedAbsol
uteBoundingBox; |
| 340 absoluteDecendantBoundingBox = absBounds; |
| 341 |
| 342 if (currentRecursionData.m_testingOverlap && !requiresCompositingOrSquashing
(directReasons)) |
| 343 overlapCompositingReason = overlapMap.overlapsLayers(absBounds) ? Compos
itingReasonOverlap : CompositingReasonNone; |
| 344 |
| 345 reasonsToComposite |= overlapCompositingReason; |
| 346 |
| 347 // The children of this layer don't need to composite, unless there is |
| 348 // a compositing layer among them, so start by inheriting the compositing |
| 349 // ancestor with m_subtreeIsCompositing set to false. |
| 350 RecursionData childRecursionData(currentRecursionData); |
| 351 childRecursionData.m_subtreeIsCompositing = false; |
| 352 |
| 353 bool willBeCompositedOrSquashed = compositor->canBeComposited(layer) && requ
iresCompositingOrSquashing(reasonsToComposite); |
| 354 if (willBeCompositedOrSquashed) { |
| 355 // Tell the parent it has compositing descendants. |
| 356 currentRecursionData.m_subtreeIsCompositing = true; |
| 357 // This layer now acts as the ancestor for kids. |
| 358 childRecursionData.m_compositingAncestor = layer; |
| 359 |
| 360 // Here we know that all children and the layer's own contents can blind
ly paint into |
| 361 // this layer's backing, until a descendant is composited. So, we don't
need to check |
| 362 // for overlap with anything behind this layer. |
| 363 overlapMap.beginNewOverlapTestingContext(); |
| 364 // This layer is going to be composited, so children can safely ignore t
he fact that there's an |
| 365 // animation running behind this layer, meaning they can rely on the ove
rlap map testing again. |
| 366 childRecursionData.m_testingOverlap = true; |
| 367 } |
| 368 |
| 369 #if !ASSERT_DISABLED |
| 370 LayerListMutationDetector mutationChecker(layer->stackingNode()); |
| 371 #endif |
| 372 |
| 373 bool anyDescendantHas3DTransform = false; |
| 374 bool willHaveForegroundLayer = false; |
| 375 |
| 376 if (layer->stackingNode()->isStackingContainer()) { |
| 377 RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), Negativ
eZOrderChildren); |
| 378 while (RenderLayerStackingNode* curNode = iterator.next()) { |
| 379 IntRect absoluteChildDecendantBoundingBox; |
| 380 updateRecursive(layer, curNode->layer(), overlapMap, childRecursionD
ata, anyDescendantHas3DTransform, unclippedDescendants, absoluteChildDecendantBo
undingBox); |
| 381 absoluteDecendantBoundingBox.unite(absoluteChildDecendantBoundingBox
); |
| 382 |
| 383 // If we have to make a layer for this child, make one now so we can
have a contents layer |
| 384 // (since we need to ensure that the -ve z-order child renders under
neath our contents). |
| 385 if (childRecursionData.m_subtreeIsCompositing) { |
| 386 reasonsToComposite |= CompositingReasonNegativeZIndexChildren; |
| 387 |
| 388 if (!willBeCompositedOrSquashed) { |
| 389 // make layer compositing |
| 390 childRecursionData.m_compositingAncestor = layer; |
| 391 overlapMap.beginNewOverlapTestingContext(); |
| 392 willBeCompositedOrSquashed = true; |
| 393 willHaveForegroundLayer = true; |
| 394 |
| 395 // FIXME: temporary solution for the first negative z-index
composited child: |
| 396 // re-compute the absBounds for the child so that we
can add the |
| 397 // negative z-index child's bounds to the new overlap
context. |
| 398 overlapMap.beginNewOverlapTestingContext(); |
| 399 overlapMap.add(curNode->layer(), curNode->layer()->ancestorD
ependentProperties().clippedAbsoluteBoundingBox); |
| 400 overlapMap.finishCurrentOverlapTestingContext(); |
| 401 } |
| 402 } |
| 403 } |
| 404 } |
| 405 |
| 406 if (willHaveForegroundLayer) { |
| 407 ASSERT(willBeCompositedOrSquashed); |
| 408 // A foreground layer effectively is a new backing for all subsequent ch
ildren, so |
| 409 // we don't need to test for overlap with anything behind this. So, we c
an finish |
| 410 // the previous context that was accumulating rects for the negative z-i
ndex |
| 411 // children, and start with a fresh new empty context. |
| 412 overlapMap.finishCurrentOverlapTestingContext(); |
| 413 overlapMap.beginNewOverlapTestingContext(); |
| 414 // This layer is going to be composited, so children can safely ignore t
he fact that there's an |
| 415 // animation running behind this layer, meaning they can rely on the ove
rlap map testing again |
| 416 childRecursionData.m_testingOverlap = true; |
| 417 } |
| 418 |
| 419 if (requiresCompositing(reasonsToComposite)) { |
| 420 currentRecursionData.m_mostRecentCompositedLayer = layer; |
| 421 childRecursionData.m_mostRecentCompositedLayer = layer; |
| 422 } |
| 423 |
| 424 RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NormalFlowC
hildren | PositiveZOrderChildren); |
| 425 while (RenderLayerStackingNode* curNode = iterator.next()) { |
| 426 IntRect absoluteChildDecendantBoundingBox; |
| 427 updateRecursive(layer, curNode->layer(), overlapMap, childRecursionData,
anyDescendantHas3DTransform, unclippedDescendants, absoluteChildDecendantBoundi
ngBox); |
| 428 absoluteDecendantBoundingBox.unite(absoluteChildDecendantBoundingBox); |
| 429 } |
| 430 |
| 431 currentRecursionData.m_mostRecentCompositedLayer = childRecursionData.m_most
RecentCompositedLayer; |
| 432 |
| 433 // Now that the subtree has been traversed, we can check for compositing rea
sons that depended on the state of the subtree. |
| 434 |
| 435 // If we entered compositing mode during the recursion, the root will also n
eed to be composited (as long as accelerated compositing is enabled). |
| 436 if (layer->isRootLayer()) { |
| 437 // FIXME: How can we be in compositing mode but not have accelerated com
positing? |
| 438 if (compositor->inCompositingMode() && compositor->hasAcceleratedComposi
ting()) |
| 439 willBeCompositedOrSquashed = true; |
| 440 } |
| 441 |
| 442 // All layers (even ones that aren't being composited) need to get added to |
| 443 // the overlap map. Layers that are not separately composited will paint int
o their |
| 444 // compositing ancestor's backing, and so are still considered for overlap. |
| 445 if (childRecursionData.m_compositingAncestor && !childRecursionData.m_compos
itingAncestor->isRootLayer()) |
| 446 overlapMap.add(layer, absBounds); |
| 447 |
| 448 if (layer->stackingNode()->isStackingContext()) { |
| 449 layer->setShouldIsolateCompositedDescendants(childRecursionData.m_hasUni
solatedCompositedBlendingDescendant); |
| 450 } else { |
| 451 layer->setShouldIsolateCompositedDescendants(false); |
| 452 currentRecursionData.m_hasUnisolatedCompositedBlendingDescendant = child
RecursionData.m_hasUnisolatedCompositedBlendingDescendant; |
| 453 } |
| 454 |
| 455 // Now check for reasons to become composited that depend on the state of de
scendant layers. |
| 456 CompositingReasons subtreeCompositingReasons = subtreeReasonsForCompositing(
layer->renderer(), childRecursionData.m_subtreeIsCompositing, anyDescendantHas3D
Transform); |
| 457 reasonsToComposite |= subtreeCompositingReasons; |
| 458 if (!willBeCompositedOrSquashed && compositor->canBeComposited(layer) && req
uiresCompositingOrSquashing(subtreeCompositingReasons)) { |
| 459 childRecursionData.m_compositingAncestor = layer; |
| 460 // FIXME: this context push is effectively a no-op but needs to exist fo
r |
| 461 // now, because the code is designed to push overlap information to the |
| 462 // second-from-top context of the stack. |
| 463 overlapMap.beginNewOverlapTestingContext(); |
| 464 overlapMap.add(layer, absoluteDecendantBoundingBox); |
| 465 willBeCompositedOrSquashed = true; |
| 466 } |
| 467 |
| 468 // If the original layer is composited, the reflection needs to be, too. |
| 469 if (layer->reflectionInfo()) { |
| 470 // FIXME: Shouldn't we call computeCompositingRequirements to handle a r
eflection overlapping with another renderer? |
| 471 RenderLayer* reflectionLayer = layer->reflectionInfo()->reflectionLayer(
); |
| 472 CompositingReasons reflectionCompositingReason = willBeCompositedOrSquas
hed ? CompositingReasonReflectionOfCompositedParent : CompositingReasonNone; |
| 473 reflectionLayer->setCompositingReasons(reflectionLayer->compositingReaso
ns() | reflectionCompositingReason); |
| 474 } |
| 475 |
| 476 // Subsequent layers in the parent's stacking context may also need to compo
site. |
| 477 if (childRecursionData.m_subtreeIsCompositing) |
| 478 currentRecursionData.m_subtreeIsCompositing = true; |
| 479 |
| 480 if (willBeCompositedOrSquashed && layer->blendInfo().hasBlendMode()) |
| 481 currentRecursionData.m_hasUnisolatedCompositedBlendingDescendant = true; |
| 482 |
| 483 // Set the flag to say that this SC has compositing children. |
| 484 layer->setHasCompositingDescendant(childRecursionData.m_subtreeIsCompositing
); |
| 485 |
| 486 // Turn overlap testing off for later layers if it's already off, or if we h
ave an animating transform. |
| 487 // Note that if the layer clips its descendants, there's no reason to propag
ate the child animation to the parent layers. That's because |
| 488 // we know for sure the animation is contained inside the clipping rectangle
, which is already added to the overlap map. |
| 489 bool isCompositedClippingLayer = compositor->canBeComposited(layer) && (reas
onsToComposite & CompositingReasonClipsCompositingDescendants); |
| 490 if ((!childRecursionData.m_testingOverlap && !isCompositedClippingLayer) ||
isRunningAcceleratedTransformAnimation(layer->renderer())) |
| 491 currentRecursionData.m_testingOverlap = false; |
| 492 |
| 493 if (childRecursionData.m_compositingAncestor == layer && !layer->isRootLayer
()) |
| 494 overlapMap.finishCurrentOverlapTestingContext(); |
| 495 |
| 496 if (layer->isRootLayer()) { |
| 497 // The root layer needs to be composited if anything else in the tree is
composited. |
| 498 // Otherwise, we can disable compositing entirely. |
| 499 if (childRecursionData.m_subtreeIsCompositing || requiresCompositingOrSq
uashing(reasonsToComposite) || compositor->inForcedCompositingMode()) { |
| 500 willBeCompositedOrSquashed = true; |
| 501 reasonsToComposite |= CompositingReasonRoot; |
| 502 } else { |
| 503 compositor->enableCompositingMode(false); |
| 504 willBeCompositedOrSquashed = false; |
| 505 reasonsToComposite = CompositingReasonNone; |
| 506 } |
| 507 } |
| 508 |
| 509 if (requiresCompositing(reasonsToComposite)) |
| 510 currentRecursionData.m_mostRecentCompositedLayer = layer; |
| 511 |
| 512 // At this point we have finished collecting all reasons to composite this l
ayer. |
| 513 layer->setCompositingReasons(reasonsToComposite); |
| 514 |
| 515 descendantHas3DTransform |= anyDescendantHas3DTransform || layer->has3DTrans
form(); |
| 516 } |
| 517 |
| 518 bool CompositingRequirementsUpdater::isRunningAcceleratedTransformAnimation(Rend
erObject* renderer) const |
| 519 { |
| 520 if (!m_compositingReasonFinder.hasAnimationTrigger()) |
| 521 return false; |
| 522 return renderer->style()->hasCurrentTransformAnimation(); |
| 523 } |
| 524 |
| 525 } // namespace WebCore |
OLD | NEW |