1 /* 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. 3 * 4 * Portions are Copyright (C) 1998 Netscape Communications Corporation. 5 * 6 * Other contributors: 7 * Robert O'Callahan <roc+@cs.cmu.edu> 8 * David Baron <dbaron (at) fas.harvard.edu> 9 * Christian Biesinger <cbiesinger (at) web.de> 10 * Randall Jesup <rjesup (at) wgate.com> 11 * Roland Mainz <roland.mainz (at) informatik.med.uni-giessen.de> 12 * Josh Soref <timeless (at) mac.com> 13 * Boris Zbarsky <bzbarsky (at) mit.edu> 14 * 15 * This library is free software; you can redistribute it and/or 16 * modify it under the terms of the GNU Lesser General Public 17 * License as published by the Free Software Foundation; either 18 * version 2.1 of the License, or (at your option) any later version. 19 * 20 * This library is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 * Lesser General Public License for more details. 24 * 25 * You should have received a copy of the GNU Lesser General Public 26 * License along with this library; if not, write to the Free Software 27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 28 * 29 * Alternatively, the contents of this file may be used under the terms 30 * of either the Mozilla Public License Version 1.1, found at 31 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public 32 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html 33 * (the "GPL"), in which case the provisions of the MPL or the GPL are 34 * applicable instead of those above. If you wish to allow use of your 35 * version of this file only under the terms of one of those two 36 * licenses (the MPL or the GPL) and not to allow others to use your 37 * version of this file under the LGPL, indicate your decision by 38 * deletingthe provisions above and replace them with the notice and 39 * other provisions required by the MPL or the GPL, as the case may be. 40 * If you do not delete the provisions above, a recipient may use your 41 * version of this file under any of the LGPL, the MPL or the GPL. 42 */ 43 44 #include "config.h" 45 #include "core/rendering/RenderLayerStackingNode.h" 46 47 #include "core/rendering/RenderLayer.h" 48 #include "core/rendering/RenderLayerCompositor.h" 49 #include "core/rendering/RenderView.h" 50 #include "public/platform/Platform.h" 51 52 namespace WebCore { 53 54 // FIXME: This should not require RenderLayer. There is currently a cycle where 55 // in order to determine if we shoulBeNormalFlowOnly() and isStackingContainer() 56 // we have to ask the render layer about some of its state. 57 RenderLayerStackingNode::RenderLayerStackingNode(RenderLayer* layer) 58 : m_layer(layer) 59 , m_descendantsAreContiguousInStackingOrder(false) 60 , m_descendantsAreContiguousInStackingOrderDirty(true) 61 , m_normalFlowListDirty(true) 62 , m_needsToBeStackingContainer(false) 63 , m_needsToBeStackingContainerHasBeenRecorded(false) 64 #if !ASSERT_DISABLED 65 , m_layerListMutationAllowed(true) 66 , m_stackingParent(0) 67 #endif 68 { 69 m_isNormalFlowOnly = shouldBeNormalFlowOnly(); 70 71 // Non-stacking containers should have empty z-order lists. As this is already the case, 72 // there is no need to dirty / recompute these lists. 73 m_zOrderListsDirty = isStackingContainer(); 74 } 75 76 RenderLayerStackingNode::~RenderLayerStackingNode() 77 { 78 #if !ASSERT_DISABLED 79 if (!renderer()->documentBeingDestroyed()) { 80 ASSERT(!isInStackingParentZOrderLists()); 81 ASSERT(!isInStackingParentNormalFlowList()); 82 83 updateStackingParentForZOrderLists(0); 84 updateStackingParentForNormalFlowList(0); 85 } 86 #endif 87 } 88 89 bool RenderLayerStackingNode::isStackingContext(const RenderStyle* style) const 90 { 91 return !style->hasAutoZIndex() || layer()->isRootLayer(); 92 } 93 94 // Helper for the sorting of layers by z-index. 95 static inline bool compareZIndex(RenderLayerStackingNode* first, RenderLayerStackingNode* second) 96 { 97 return first->zIndex() < second->zIndex(); 98 } 99 100 RenderLayerCompositor* RenderLayerStackingNode::compositor() const 101 { 102 if (!renderer()->view()) 103 return 0; 104 return renderer()->view()->compositor(); 105 } 106 107 void RenderLayerStackingNode::dirtyNormalFlowListCanBePromotedToStackingContainer() 108 { 109 m_descendantsAreContiguousInStackingOrderDirty = true; 110 111 if (m_normalFlowListDirty || !normalFlowList()) 112 return; 113 114 for (size_t index = 0; index < normalFlowList()->size(); ++index) 115 normalFlowList()->at(index)->dirtyNormalFlowListCanBePromotedToStackingContainer(); 116 } 117 118 void RenderLayerStackingNode::dirtySiblingStackingNodeCanBePromotedToStackingContainer() 119 { 120 RenderLayerStackingNode* stackingNode = ancestorStackingNode(); 121 if (!stackingNode) 122 return; 123 124 if (!stackingNode->zOrderListsDirty() && stackingNode->posZOrderList()) { 125 for (size_t index = 0; index < stackingNode->posZOrderList()->size(); ++index) 126 stackingNode->posZOrderList()->at(index)->setDescendantsAreContiguousInStackingOrderDirty(true); 127 } 128 129 stackingNode->dirtyNormalFlowListCanBePromotedToStackingContainer(); 130 131 if (!stackingNode->zOrderListsDirty() && stackingNode->negZOrderList()) { 132 for (size_t index = 0; index < stackingNode->negZOrderList()->size(); ++index) 133 stackingNode->negZOrderList()->at(index)->setDescendantsAreContiguousInStackingOrderDirty(true); 134 } 135 } 136 137 void RenderLayerStackingNode::dirtyZOrderLists() 138 { 139 ASSERT(m_layerListMutationAllowed); 140 ASSERT(isStackingContainer()); 141 142 #if !ASSERT_DISABLED 143 updateStackingParentForZOrderLists(0); 144 #endif 145 146 if (m_posZOrderList) 147 m_posZOrderList->clear(); 148 if (m_negZOrderList) 149 m_negZOrderList->clear(); 150 m_zOrderListsDirty = true; 151 152 m_descendantsAreContiguousInStackingOrderDirty = true; 153 154 if (!renderer()->documentBeingDestroyed()) { 155 compositor()->setNeedsUpdateCompositingRequirementsState(); 156 compositor()->setCompositingLayersNeedRebuild(); 157 if (layer()->acceleratedCompositingForOverflowScrollEnabled()) 158 compositor()->setNeedsToRecomputeCompositingRequirements(); 159 } 160 } 161 162 void RenderLayerStackingNode::dirtyStackingContainerZOrderLists() 163 { 164 // Any siblings in the ancestor stacking context could also be affected. 165 // Changing z-index, for example, could cause us to stack in between a 166 // sibling's descendants, meaning that we have to recompute 167 // m_descendantsAreContiguousInStackingOrder for that sibling. 168 dirtySiblingStackingNodeCanBePromotedToStackingContainer(); 169 170 RenderLayerStackingNode* stackingContainerNode = ancestorStackingContainerNode(); 171 if (stackingContainerNode) 172 stackingContainerNode->dirtyZOrderLists(); 173 174 // Any change that could affect our stacking container's z-order list could 175 // cause other RenderLayers in our stacking context to either opt in or out 176 // of composited scrolling. It is important that we make our stacking 177 // context aware of these z-order changes so the appropriate updating can 178 // happen. 179 RenderLayerStackingNode* stackingNode = ancestorStackingNode(); 180 if (stackingNode && stackingNode != stackingContainerNode) 181 stackingNode->dirtyZOrderLists(); 182 } 183 184 void RenderLayerStackingNode::dirtyNormalFlowList() 185 { 186 ASSERT(m_layerListMutationAllowed); 187 188 #if !ASSERT_DISABLED 189 updateStackingParentForNormalFlowList(0); 190 #endif 191 192 if (m_normalFlowList) 193 m_normalFlowList->clear(); 194 m_normalFlowListDirty = true; 195 196 if (!renderer()->documentBeingDestroyed()) { 197 compositor()->setCompositingLayersNeedRebuild(); 198 if (layer()->acceleratedCompositingForOverflowScrollEnabled()) 199 compositor()->setNeedsToRecomputeCompositingRequirements(); 200 } 201 } 202 203 void RenderLayerStackingNode::rebuildZOrderLists() 204 { 205 ASSERT(m_layerListMutationAllowed); 206 ASSERT(isDirtyStackingContainer()); 207 rebuildZOrderLists(m_posZOrderList, m_negZOrderList); 208 209 #if !ASSERT_DISABLED 210 updateStackingParentForZOrderLists(this); 211 #endif 212 213 m_zOrderListsDirty = false; 214 } 215 216 void RenderLayerStackingNode::rebuildZOrderLists(OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, 217 OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList, const RenderLayerStackingNode* nodeToForceAsStackingContainer, 218 CollectLayersBehavior collectLayersBehavior) 219 { 220 for (RenderLayer* child = layer()->firstChild(); child; child = child->nextSibling()) { 221 if (!layer()->reflectionInfo() || layer()->reflectionInfo()->reflectionLayer() != child) 222 child->stackingNode()->collectLayers(posZOrderList, negZOrderList, nodeToForceAsStackingContainer, collectLayersBehavior); 223 } 224 225 // Sort the two lists. 226 if (posZOrderList) 227 std::stable_sort(posZOrderList->begin(), posZOrderList->end(), compareZIndex); 228 229 if (negZOrderList) 230 std::stable_sort(negZOrderList->begin(), negZOrderList->end(), compareZIndex); 231 232 // Append layers for top layer elements after normal layer collection, to ensure they are on top regardless of z-indexes. 233 // The renderers of top layer elements are children of the view, sorted in top layer stacking order. 234 if (layer()->isRootLayer()) { 235 RenderObject* view = renderer()->view(); 236 for (RenderObject* child = view->firstChild(); child; child = child->nextSibling()) { 237 Element* childElement = (child->node() && child->node()->isElementNode()) ? toElement(child->node()) : 0; 238 if (childElement && childElement->isInTopLayer()) { 239 RenderLayer* layer = toRenderLayerModelObject(child)->layer(); 240 // Create the buffer if it doesn't exist yet. 241 if (!posZOrderList) 242 posZOrderList = adoptPtr(new Vector<RenderLayerStackingNode*>); 243 posZOrderList->append(layer->stackingNode()); 244 } 245 } 246 } 247 } 248 249 void RenderLayerStackingNode::updateNormalFlowList() 250 { 251 if (!m_normalFlowListDirty) 252 return; 253 254 ASSERT(m_layerListMutationAllowed); 255 256 for (RenderLayer* child = layer()->firstChild(); child; child = child->nextSibling()) { 257 // Ignore non-overflow layers and reflections. 258 if (child->stackingNode()->isNormalFlowOnly() && (!layer()->reflectionInfo() || layer()->reflectionInfo()->reflectionLayer() != child)) { 259 if (!m_normalFlowList) 260 m_normalFlowList = adoptPtr(new Vector<RenderLayerStackingNode*>); 261 m_normalFlowList->append(child->stackingNode()); 262 } 263 } 264 265 #if !ASSERT_DISABLED 266 updateStackingParentForNormalFlowList(this); 267 #endif 268 269 m_normalFlowListDirty = false; 270 } 271 272 void RenderLayerStackingNode::collectLayers(OwnPtr<Vector<RenderLayerStackingNode*> >& posBuffer, OwnPtr<Vector<RenderLayerStackingNode*> >& negBuffer, 273 const RenderLayerStackingNode* nodeToForceAsStackingContainer, CollectLayersBehavior collectLayersBehavior) 274 { 275 if (layer()->isInTopLayer()) 276 return; 277 278 layer()->updateDescendantDependentFlags(); 279 280 bool isStacking = false; 281 bool isNormalFlow = false; 282 283 switch (collectLayersBehavior) { 284 case ForceLayerToStackingContainer: 285 ASSERT(nodeToForceAsStackingContainer); 286 if (this == nodeToForceAsStackingContainer) { 287 isStacking = true; 288 isNormalFlow = false; 289 } else { 290 isStacking = isStackingContext(); 291 isNormalFlow = shouldBeNormalFlowOnlyIgnoringCompositedScrolling(); 292 } 293 break; 294 case OverflowScrollCanBeStackingContainers: 295 ASSERT(!nodeToForceAsStackingContainer); 296 isStacking = isStackingContainer(); 297 isNormalFlow = isNormalFlowOnly(); 298 break; 299 case OnlyStackingContextsCanBeStackingContainers: 300 isStacking = isStackingContext(); 301 isNormalFlow = shouldBeNormalFlowOnlyIgnoringCompositedScrolling(); 302 break; 303 } 304 305 // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists. 306 if (!isNormalFlow && !layer()->isOutOfFlowRenderFlowThread()) { 307 // Determine which buffer the child should be in. 308 OwnPtr<Vector<RenderLayerStackingNode*> >& buffer = (zIndex() >= 0) ? posBuffer : negBuffer; 309 310 // Create the buffer if it doesn't exist yet. 311 if (!buffer) 312 buffer = adoptPtr(new Vector<RenderLayerStackingNode*>); 313 314 // Append ourselves at the end of the appropriate buffer. 315 buffer->append(this); 316 } 317 318 // Recur into our children to collect more layers, but only if we don't establish 319 // a stacking context/container. 320 if (!isStacking) { 321 for (RenderLayer* child = layer()->firstChild(); child; child = child->nextSibling()) { 322 // Ignore reflections. 323 if (!layer()->reflectionInfo() || layer()->reflectionInfo()->reflectionLayer() != child) 324 child->stackingNode()->collectLayers(posBuffer, negBuffer, nodeToForceAsStackingContainer, collectLayersBehavior); 325 } 326 } 327 } 328 329 #if !ASSERT_DISABLED 330 bool RenderLayerStackingNode::isInStackingParentZOrderLists() const 331 { 332 if (!m_stackingParent || m_stackingParent->zOrderListsDirty()) 333 return false; 334 335 if (m_stackingParent->posZOrderList() && m_stackingParent->posZOrderList()->find(this) != kNotFound) 336 return true; 337 338 if (m_stackingParent->negZOrderList() && m_stackingParent->negZOrderList()->find(this) != kNotFound) 339 return true; 340 341 return false; 342 } 343 344 bool RenderLayerStackingNode::isInStackingParentNormalFlowList() const 345 { 346 if (!m_stackingParent || m_stackingParent->normalFlowListDirty()) 347 return false; 348 349 return (m_stackingParent->normalFlowList() && m_stackingParent->normalFlowList()->find(this) != kNotFound); 350 } 351 352 void RenderLayerStackingNode::updateStackingParentForZOrderLists(RenderLayerStackingNode* stackingParent) 353 { 354 if (m_posZOrderList) { 355 for (size_t i = 0; i < m_posZOrderList->size(); ++i) 356 m_posZOrderList->at(i)->setStackingParent(stackingParent); 357 } 358 359 if (m_negZOrderList) { 360 for (size_t i = 0; i < m_negZOrderList->size(); ++i) 361 m_negZOrderList->at(i)->setStackingParent(stackingParent); 362 } 363 } 364 365 void RenderLayerStackingNode::updateStackingParentForNormalFlowList(RenderLayerStackingNode* stackingParent) 366 { 367 if (m_normalFlowList) { 368 for (size_t i = 0; i < m_normalFlowList->size(); ++i) 369 m_normalFlowList->at(i)->setStackingParent(stackingParent); 370 } 371 } 372 #endif 373 374 void RenderLayerStackingNode::updateLayerListsIfNeeded() 375 { 376 updateZOrderLists(); 377 updateNormalFlowList(); 378 379 if (!layer()->reflectionInfo()) 380 return; 381 382 RenderLayer* reflectionLayer = layer()->reflectionInfo()->reflectionLayer(); 383 reflectionLayer->stackingNode()->updateZOrderLists(); 384 reflectionLayer->stackingNode()->updateNormalFlowList(); 385 } 386 387 void RenderLayerStackingNode::updateStackingNodesAfterStyleChange(const RenderStyle* oldStyle) 388 { 389 bool wasStackingContext = oldStyle ? isStackingContext(oldStyle) : false; 390 EVisibility oldVisibility = oldStyle ? oldStyle->visibility() : VISIBLE; 391 int oldZIndex = oldStyle ? oldStyle->zIndex() : 0; 392 393 // FIXME: RenderLayer already handles visibility changes through our visiblity dirty bits. This logic could 394 // likely be folded along with the rest. 395 bool isStackingContext = this->isStackingContext(); 396 if (isStackingContext == wasStackingContext && oldVisibility == renderer()->style()->visibility() && oldZIndex == zIndex()) 397 return; 398 399 dirtyStackingContainerZOrderLists(); 400 401 if (isStackingContainer()) 402 dirtyZOrderLists(); 403 else 404 clearZOrderLists(); 405 406 compositor()->setNeedsUpdateCompositingRequirementsState(); 407 } 408 409 bool RenderLayerStackingNode::shouldBeNormalFlowOnly() const 410 { 411 return shouldBeNormalFlowOnlyIgnoringCompositedScrolling() && !layer()->needsCompositedScrolling(); 412 } 413 414 bool RenderLayerStackingNode::shouldBeNormalFlowOnlyIgnoringCompositedScrolling() const 415 { 416 const bool couldBeNormalFlow = renderer()->hasOverflowClip() 417 || renderer()->hasReflection() 418 || renderer()->hasMask() 419 || renderer()->isCanvas() 420 || renderer()->isVideo() 421 || renderer()->isEmbeddedObject() 422 || renderer()->isRenderIFrame() 423 || (renderer()->style()->specifiesColumns() && !layer()->isRootLayer()); 424 const bool preventsElementFromBeingNormalFlow = renderer()->isPositioned() 425 || renderer()->hasTransform() 426 || renderer()->hasClipPath() 427 || renderer()->hasFilter() 428 || renderer()->hasBlendMode() 429 || layer()->isTransparent() 430 || renderer()->style()->hasFlowFrom(); 431 432 return couldBeNormalFlow && !preventsElementFromBeingNormalFlow; 433 } 434 435 void RenderLayerStackingNode::updateIsNormalFlowOnly() 436 { 437 bool isNormalFlowOnly = shouldBeNormalFlowOnly(); 438 if (isNormalFlowOnly == this->isNormalFlowOnly()) 439 return; 440 441 m_isNormalFlowOnly = isNormalFlowOnly; 442 if (RenderLayer* p = layer()->parent()) 443 p->stackingNode()->dirtyNormalFlowList(); 444 dirtyStackingContainerZOrderLists(); 445 } 446 447 bool RenderLayerStackingNode::needsToBeStackingContainer() const 448 { 449 return layer()->scrollableArea() && layer()->scrollableArea()->adjustForForceCompositedScrollingMode(m_needsToBeStackingContainer); 450 } 451 452 // Determine whether the current layer can be promoted to a stacking container. 453 // We do this by computing what positive and negative z-order lists would look 454 // like before and after promotion, and ensuring that proper stacking order is 455 // preserved between the two sets of lists. 456 void RenderLayerStackingNode::updateDescendantsAreContiguousInStackingOrder() 457 { 458 TRACE_EVENT0("blink_rendering,comp-scroll", "RenderLayerStackingNode::updateDescendantsAreContiguousInStackingOrder"); 459 460 const RenderLayer* currentLayer = layer(); 461 if (isStackingContext() || !m_descendantsAreContiguousInStackingOrderDirty || !currentLayer->acceleratedCompositingForOverflowScrollEnabled()) 462 return; 463 464 if (!currentLayer->scrollsOverflow()) 465 return; 466 467 RenderLayerStackingNode* stackingNode = ancestorStackingNode(); 468 if (!stackingNode) 469 return; 470 471 OwnPtr<Vector<RenderLayerStackingNode*> > posZOrderListBeforePromote = adoptPtr(new Vector<RenderLayerStackingNode*>); 472 OwnPtr<Vector<RenderLayerStackingNode*> > negZOrderListBeforePromote = adoptPtr(new Vector<RenderLayerStackingNode*>); 473 OwnPtr<Vector<RenderLayerStackingNode*> > posZOrderListAfterPromote = adoptPtr(new Vector<RenderLayerStackingNode*>); 474 OwnPtr<Vector<RenderLayerStackingNode*> > negZOrderListAfterPromote = adoptPtr(new Vector<RenderLayerStackingNode*>); 475 476 collectBeforePromotionZOrderList(stackingNode, posZOrderListBeforePromote, negZOrderListBeforePromote); 477 collectAfterPromotionZOrderList(stackingNode, posZOrderListAfterPromote, negZOrderListAfterPromote); 478 479 size_t maxIndex = std::min(posZOrderListAfterPromote->size() + negZOrderListAfterPromote->size(), posZOrderListBeforePromote->size() + negZOrderListBeforePromote->size()); 480 481 m_descendantsAreContiguousInStackingOrderDirty = false; 482 m_descendantsAreContiguousInStackingOrder = false; 483 484 const RenderLayerStackingNode* nodeAfterPromote = 0; 485 for (size_t i = 0; i < maxIndex && nodeAfterPromote != this; ++i) { 486 const RenderLayerStackingNode* nodeBeforePromote = i < negZOrderListBeforePromote->size() 487 ? negZOrderListBeforePromote->at(i) 488 : posZOrderListBeforePromote->at(i - negZOrderListBeforePromote->size()); 489 nodeAfterPromote = i < negZOrderListAfterPromote->size() 490 ? negZOrderListAfterPromote->at(i) 491 : posZOrderListAfterPromote->at(i - negZOrderListAfterPromote->size()); 492 493 if (nodeBeforePromote != nodeAfterPromote && (nodeAfterPromote != this || renderer()->hasBackground())) 494 return; 495 } 496 497 nodeAfterPromote = 0; 498 for (size_t i = 0; i < maxIndex && nodeAfterPromote != this; ++i) { 499 const RenderLayerStackingNode* nodeBeforePromote = i < posZOrderListBeforePromote->size() 500 ? posZOrderListBeforePromote->at(posZOrderListBeforePromote->size() - i - 1) 501 : negZOrderListBeforePromote->at(negZOrderListBeforePromote->size() + posZOrderListBeforePromote->size() - i - 1); 502 nodeAfterPromote = i < posZOrderListAfterPromote->size() 503 ? posZOrderListAfterPromote->at(posZOrderListAfterPromote->size() - i - 1) 504 : negZOrderListAfterPromote->at(negZOrderListAfterPromote->size() + posZOrderListAfterPromote->size() - i - 1); 505 506 if (nodeBeforePromote != nodeAfterPromote && nodeAfterPromote != this) 507 return; 508 } 509 510 m_descendantsAreContiguousInStackingOrder = true; 511 } 512 513 void RenderLayerStackingNode::collectBeforePromotionZOrderList(RenderLayerStackingNode* ancestorStackingNode, 514 OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList) 515 { 516 ancestorStackingNode->rebuildZOrderLists(posZOrderList, negZOrderList, this, OnlyStackingContextsCanBeStackingContainers); 517 518 const RenderLayer* currentLayer = layer(); 519 const RenderLayer* positionedAncestor = currentLayer->parent(); 520 while (positionedAncestor && !positionedAncestor->isPositionedContainer() && !positionedAncestor->stackingNode()->isStackingContext()) 521 positionedAncestor = positionedAncestor->parent(); 522 if (positionedAncestor && (!positionedAncestor->isPositionedContainer() || positionedAncestor->stackingNode()->isStackingContext())) 523 positionedAncestor = 0; 524 525 if (!posZOrderList) 526 posZOrderList = adoptPtr(new Vector<RenderLayerStackingNode*>()); 527 else if (posZOrderList->find(this) != kNotFound) 528 return; 529 530 // The current node will appear in the z-order lists after promotion, so 531 // for a meaningful comparison, we must insert it in the z-order lists 532 // before promotion if it does not appear there already. 533 if (!positionedAncestor) { 534 posZOrderList->prepend(this); 535 return; 536 } 537 538 for (size_t index = 0; index < posZOrderList->size(); index++) { 539 if (posZOrderList->at(index)->layer() == positionedAncestor) { 540 posZOrderList->insert(index + 1, this); 541 return; 542 } 543 } 544 } 545 546 void RenderLayerStackingNode::collectAfterPromotionZOrderList(RenderLayerStackingNode* ancestorStackingNode, 547 OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList) 548 { 549 ancestorStackingNode->rebuildZOrderLists(posZOrderList, negZOrderList, this, ForceLayerToStackingContainer); 550 } 551 552 // Compute what positive and negative z-order lists would look like before and 553 // after promotion, so we can later ensure that proper stacking order is 554 // preserved between the two sets of lists. 555 // 556 // A few examples: 557 // c = currentLayer 558 // - = negative z-order child of currentLayer 559 // + = positive z-order child of currentLayer 560 // a = positioned ancestor of currentLayer 561 // x = any other RenderLayer in the list 562 // 563 // (a) xxxxx-----++a+++x 564 // (b) xxx-----c++++++xx 565 // 566 // Normally the current layer would be painted in the normal flow list if it 567 // doesn't already appear in the positive z-order list. However, in the case 568 // that the layer has a positioned ancestor, it will paint directly after the 569 // positioned ancestor. In example (a), the current layer would be painted in 570 // the middle of its own positive z-order children, so promoting would cause a 571 // change in paint order (since a promoted layer will paint all of its positive 572 // z-order children strictly after it paints itself). 573 // 574 // In example (b), it is ok to promote the current layer only if it does not 575 // have a background. If it has a background, the background gets painted before 576 // the layer's negative z-order children, so again, a promotion would cause a 577 // change in paint order (causing the background to get painted after the 578 // negative z-order children instead of before). 579 // 580 void RenderLayerStackingNode::computePaintOrderList(PaintOrderListType type, Vector<RefPtr<Node> >& list) 581 { 582 OwnPtr<Vector<RenderLayerStackingNode*> > posZOrderList; 583 OwnPtr<Vector<RenderLayerStackingNode*> > negZOrderList; 584 585 RenderLayerStackingNode* stackingNode = ancestorStackingNode(); 586 if (!stackingNode) 587 return; 588 589 switch (type) { 590 case BeforePromote: 591 collectBeforePromotionZOrderList(stackingNode, posZOrderList, negZOrderList); 592 break; 593 case AfterPromote: 594 collectAfterPromotionZOrderList(stackingNode, posZOrderList, negZOrderList); 595 break; 596 } 597 598 if (negZOrderList) { 599 for (size_t index = 0; index < negZOrderList->size(); ++index) 600 list.append(negZOrderList->at(index)->renderer()->node()); 601 } 602 603 if (posZOrderList) { 604 for (size_t index = 0; index < posZOrderList->size(); ++index) 605 list.append(posZOrderList->at(index)->renderer()->node()); 606 } 607 } 608 609 bool RenderLayerStackingNode::descendantsAreContiguousInStackingOrder() const 610 { 611 if (isStackingContext() || !ancestorStackingContainerNode()) 612 return true; 613 614 ASSERT(!m_descendantsAreContiguousInStackingOrderDirty); 615 return m_descendantsAreContiguousInStackingOrder; 616 } 617 618 bool RenderLayerStackingNode::setNeedsToBeStackingContainer(bool needsToBeStackingContainer) 619 { 620 if (this->needsToBeStackingContainer() == needsToBeStackingContainer) 621 return false; 622 623 // Count the total number of RenderLayers which need to be stacking 624 // containers some point. This should be recorded at most once per 625 // RenderLayer, so we check m_needsToBeStackingContainerHasBeenRecorded. 626 if (layer()->acceleratedCompositingForOverflowScrollEnabled() && !m_needsToBeStackingContainerHasBeenRecorded) { 627 blink::Platform::current()->histogramEnumeration("Renderer.CompositedScrolling", RenderLayer::NeedsToBeStackingContainerBucket, RenderLayer::CompositedScrollingHistogramMax); 628 m_needsToBeStackingContainerHasBeenRecorded = true; 629 } 630 631 m_needsToBeStackingContainer = needsToBeStackingContainer; 632 633 return true; 634 } 635 636 RenderLayerStackingNode* RenderLayerStackingNode::ancestorStackingContainerNode() const 637 { 638 RenderLayer* ancestor = layer()->parent(); 639 while (ancestor && !ancestor->stackingNode()->isStackingContainer()) 640 ancestor = ancestor->parent(); 641 if (ancestor) 642 return ancestor->stackingNode(); 643 return 0; 644 } 645 646 RenderLayerStackingNode* RenderLayerStackingNode::ancestorStackingNode() const 647 { 648 RenderLayer* ancestor = layer()->parent(); 649 while (ancestor && !ancestor->stackingNode()->isStackingContext()) 650 ancestor = ancestor->parent(); 651 if (ancestor) 652 return ancestor->stackingNode(); 653 return 0; 654 } 655 656 RenderLayerModelObject* RenderLayerStackingNode::renderer() const 657 { 658 return m_layer->renderer(); 659 } 660 661 } // namespace WebCore 662