OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights
reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights
reserved. |
3 * | 3 * |
4 * Portions are Copyright (C) 1998 Netscape Communications Corporation. | 4 * Portions are Copyright (C) 1998 Netscape Communications Corporation. |
5 * | 5 * |
6 * Other contributors: | 6 * Other contributors: |
7 * Robert O'Callahan <roc+@cs.cmu.edu> | 7 * Robert O'Callahan <roc+@cs.cmu.edu> |
8 * David Baron <dbaron@fas.harvard.edu> | 8 * David Baron <dbaron@fas.harvard.edu> |
9 * Christian Biesinger <cbiesinger@web.de> | 9 * Christian Biesinger <cbiesinger@web.de> |
10 * Randall Jesup <rjesup@wgate.com> | 10 * Randall Jesup <rjesup@wgate.com> |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 RenderLayer::RenderLayer(RenderLayerModelObject* renderer) | 127 RenderLayer::RenderLayer(RenderLayerModelObject* renderer) |
128 : m_inResizeMode(false) | 128 : m_inResizeMode(false) |
129 , m_scrollDimensionsDirty(true) | 129 , m_scrollDimensionsDirty(true) |
130 , m_normalFlowListDirty(true) | 130 , m_normalFlowListDirty(true) |
131 , m_hasSelfPaintingLayerDescendant(false) | 131 , m_hasSelfPaintingLayerDescendant(false) |
132 , m_hasSelfPaintingLayerDescendantDirty(false) | 132 , m_hasSelfPaintingLayerDescendantDirty(false) |
133 , m_hasOutOfFlowPositionedDescendant(false) | 133 , m_hasOutOfFlowPositionedDescendant(false) |
134 , m_hasOutOfFlowPositionedDescendantDirty(true) | 134 , m_hasOutOfFlowPositionedDescendantDirty(true) |
135 , m_hasUnclippedDescendant(false) | 135 , m_hasUnclippedDescendant(false) |
136 , m_needsCompositedScrolling(false) | 136 , m_needsCompositedScrolling(false) |
137 , m_descendantsAreContiguousInStackingOrder(false) | 137 , m_canBePromotedToStackingContainer(false) |
138 , m_descendantsAreContiguousInStackingOrderDirty(true) | 138 , m_canBePromotedToStackingContainerDirty(true) |
139 , m_isRootLayer(renderer->isRenderView()) | 139 , m_isRootLayer(renderer->isRenderView()) |
140 , m_usedTransparency(false) | 140 , m_usedTransparency(false) |
141 , m_paintingInsideReflection(false) | 141 , m_paintingInsideReflection(false) |
142 , m_inOverflowRelayout(false) | 142 , m_inOverflowRelayout(false) |
143 , m_repaintStatus(NeedsNormalRepaint) | 143 , m_repaintStatus(NeedsNormalRepaint) |
144 , m_visibleContentStatusDirty(true) | 144 , m_visibleContentStatusDirty(true) |
145 , m_hasVisibleContent(false) | 145 , m_hasVisibleContent(false) |
146 , m_visibleDescendantStatusDirty(false) | 146 , m_visibleDescendantStatusDirty(false) |
147 , m_hasVisibleDescendant(false) | 147 , m_hasVisibleDescendant(false) |
148 , m_isPaginated(false) | 148 , m_isPaginated(false) |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 } | 498 } |
499 } | 499 } |
500 } | 500 } |
501 | 501 |
502 bool RenderLayer::acceleratedCompositingForOverflowScrollEnabled() const | 502 bool RenderLayer::acceleratedCompositingForOverflowScrollEnabled() const |
503 { | 503 { |
504 const Settings* settings = renderer()->document()->settings(); | 504 const Settings* settings = renderer()->document()->settings(); |
505 return settings && settings->acceleratedCompositingForOverflowScrollEnabled(
); | 505 return settings && settings->acceleratedCompositingForOverflowScrollEnabled(
); |
506 } | 506 } |
507 | 507 |
508 // If we are a stacking container, then this function will determine if our | 508 // Determine whether the current layer can be promoted to a stacking container. |
509 // descendants for a contiguous block in stacking order. This is required in | 509 // We do this by computing what positive and negative z-order lists would look |
510 // order for an element to be safely promoted to a stacking container. It is saf
e | 510 // like before and after promotion, and ensuring that proper stacking order is |
511 // to become a stacking container if this change would not alter the stacking | 511 // preserved between the two sets of lists. |
512 // order of layers on the page. That can only happen if a non-descendant appear | 512 void RenderLayer::updateCanBeStackingContainer() |
513 // between us and our descendants in stacking order. Here's an example: | |
514 // | |
515 // this | |
516 // / | \. | |
517 // A B C | |
518 // /\ | /\. | |
519 // 0 -8 D 2 7 | |
520 // | | |
521 // 5 | |
522 // | |
523 // I've labeled our normal flow descendants A, B, C, and D, our stacking | |
524 // container descendants with their z indices, and us with 'this' (we're a | |
525 // stacking container and our zIndex doesn't matter here). These nodes appear in | |
526 // three lists: posZOrder, negZOrder, and normal flow (keep in mind that normal | |
527 // flow layers don't overlap). So if we arrange these lists in order we get our | |
528 // stacking order: | |
529 // | |
530 // [-8], [A-D], [0, 2, 5, 7]--> pos z-order. | |
531 // | | | |
532 // Neg z-order. <-+ +--> Normal flow descendants. | |
533 // | |
534 // We can then assign new, 'stacking' order indices to these elements as follows
: | |
535 // | |
536 // [-8], [A-D], [0, 2, 5, 7] | |
537 // 'Stacking' indices: -1 0 1 2 3 4 | |
538 // | |
539 // Note that the normal flow descendants can share an index because they don't | |
540 // stack/overlap. Now our problem becomes very simple: a layer can safely become | |
541 // a stacking container if the stacking-order indices of it and its descendants | |
542 // appear in a contiguous block in the list of stacking indices. This problem | |
543 // can be solved very efficiently by calculating the min/max stacking indices in | |
544 // the subtree, and the number stacking container descendants. Once we have this | |
545 // information, we know that the subtree's indices form a contiguous block if: | |
546 // | |
547 // maxStackIndex - minStackIndex == numSCDescendants | |
548 // | |
549 // So for node A in the example above we would have: | |
550 // maxStackIndex = 1 | |
551 // minStackIndex = -1 | |
552 // numSCDecendants = 2 | |
553 // | |
554 // and so, | |
555 // maxStackIndex - minStackIndex == numSCDescendants | |
556 // ===> 1 - (-1) == 2 | |
557 // ===> 2 == 2 | |
558 // | |
559 // Since this is true, A can safely become a stacking container. | |
560 // Now, for node C we have: | |
561 // | |
562 // maxStackIndex = 4 | |
563 // minStackIndex = 0 <-- because C has stacking index 0. | |
564 // numSCDecendants = 2 | |
565 // | |
566 // and so, | |
567 // maxStackIndex - minStackIndex == numSCDescendants | |
568 // ===> 4 - 0 == 2 | |
569 // ===> 4 == 2 | |
570 // | |
571 // Since this is false, C cannot be safely promoted to a stacking container. Thi
s | |
572 // happened because of the elements with z-index 5 and 0. Now if 5 had been a | |
573 // child of C rather than D, and A had no child with Z index 0, we would have ha
d: | |
574 // | |
575 // maxStackIndex = 3 | |
576 // minStackIndex = 0 <-- because C has stacking index 0. | |
577 // numSCDecendants = 3 | |
578 // | |
579 // and so, | |
580 // maxStackIndex - minStackIndex == numSCDescendants | |
581 // ===> 3 - 0 == 3 | |
582 // ===> 3 == 3 | |
583 // | |
584 // And we would conclude that C could be promoted. | |
585 void RenderLayer::updateDescendantsAreContiguousInStackingOrder() | |
586 { | 513 { |
587 if (!m_descendantsAreContiguousInStackingOrderDirty || !isStackingContext()
|| !acceleratedCompositingForOverflowScrollEnabled()) | 514 TRACE_EVENT0("blink_rendering", "RenderLayer::updateCanBeStackingContainer")
; |
| 515 |
| 516 if (isStackingContext() || !m_canBePromotedToStackingContainerDirty || !acce
leratedCompositingForOverflowScrollEnabled()) |
588 return; | 517 return; |
589 | 518 |
590 OwnPtr<Vector<RenderLayer*> > posZOrderList; | 519 FrameView* frameView = renderer()->view()->frameView(); |
591 OwnPtr<Vector<RenderLayer*> > negZOrderList; | 520 if (!frameView || !frameView->containsScrollableArea(this)) |
592 rebuildZOrderLists(StopAtStackingContexts, posZOrderList, negZOrderList); | 521 return; |
593 | 522 |
594 // Create a reverse lookup. | 523 RenderLayer* ancestorStackingContext = this->ancestorStackingContext(); |
595 HashMap<const RenderLayer*, int> lookup; | 524 if (!ancestorStackingContext) |
| 525 return; |
596 | 526 |
597 if (negZOrderList) { | 527 OwnPtr<Vector<RenderLayer*> > posZOrderListBeforePromote = adoptPtr(new Vect
or<RenderLayer*>); |
598 int stackingOrderIndex = -1; | 528 OwnPtr<Vector<RenderLayer*> > negZOrderListBeforePromote = adoptPtr(new Vect
or<RenderLayer*>); |
599 size_t listSize = negZOrderList->size(); | 529 OwnPtr<Vector<RenderLayer*> > posZOrderListAfterPromote = adoptPtr(new Vecto
r<RenderLayer*>); |
600 for (size_t i = 0; i < listSize; ++i) { | 530 OwnPtr<Vector<RenderLayer*> > negZOrderListAfterPromote = adoptPtr(new Vecto
r<RenderLayer*>); |
601 RenderLayer* currentLayer = negZOrderList->at(listSize - i - 1); | 531 |
602 if (!currentLayer->isStackingContext()) | 532 collectBeforePromotionZOrderList(ancestorStackingContext, posZOrderListBefor
ePromote, negZOrderListBeforePromote); |
603 continue; | 533 collectAfterPromotionZOrderList(ancestorStackingContext, posZOrderListAfterP
romote, negZOrderListAfterPromote); |
604 lookup.set(currentLayer, stackingOrderIndex--); | 534 |
605 } | 535 size_t maxIndex = std::min(posZOrderListAfterPromote->size() + negZOrderList
AfterPromote->size(), posZOrderListBeforePromote->size() + negZOrderListBeforePr
omote->size()); |
| 536 |
| 537 m_canBePromotedToStackingContainerDirty = false; |
| 538 m_canBePromotedToStackingContainer = false; |
| 539 |
| 540 const RenderLayer* layerAfterPromote = 0; |
| 541 for (size_t i = 0; i < maxIndex && layerAfterPromote != this; ++i) { |
| 542 const RenderLayer* layerBeforePromote = i < negZOrderListBeforePromote->
size() |
| 543 ? negZOrderListBeforePromote->at(i) |
| 544 : posZOrderListBeforePromote->at(i - negZOrderListBeforePromote->siz
e()); |
| 545 layerAfterPromote = i < negZOrderListAfterPromote->size() |
| 546 ? negZOrderListAfterPromote->at(i) |
| 547 : posZOrderListAfterPromote->at(i - negZOrderListAfterPromote->size(
)); |
| 548 |
| 549 if (layerBeforePromote != layerAfterPromote && (layerAfterPromote != thi
s || renderer()->hasBackground())) |
| 550 return; |
606 } | 551 } |
607 | 552 |
608 if (posZOrderList) { | 553 layerAfterPromote = 0; |
609 size_t listSize = posZOrderList->size(); | 554 for (size_t i = 0; i < maxIndex && layerAfterPromote != this; ++i) { |
610 int stackingOrderIndex = 1; | 555 const RenderLayer* layerBeforePromote = i < posZOrderListBeforePromote->
size() |
611 for (size_t i = 0; i < listSize; ++i) { | 556 ? posZOrderListBeforePromote->at(posZOrderListBeforePromote->size()
- i - 1) |
612 RenderLayer* currentLayer = posZOrderList->at(i); | 557 : negZOrderListBeforePromote->at(negZOrderListBeforePromote->size()
+ posZOrderListBeforePromote->size() - i - 1); |
613 if (!currentLayer->isStackingContext()) | 558 layerAfterPromote = i < posZOrderListAfterPromote->size() |
614 continue; | 559 ? posZOrderListAfterPromote->at(posZOrderListAfterPromote->size() -
i - 1) |
615 lookup.set(currentLayer, stackingOrderIndex++); | 560 : negZOrderListAfterPromote->at(negZOrderListAfterPromote->size() +
posZOrderListAfterPromote->size() - i - 1); |
616 } | 561 |
| 562 if (layerBeforePromote != layerAfterPromote && layerAfterPromote != this
) |
| 563 return; |
617 } | 564 } |
618 | 565 |
619 int minIndex = 0; | 566 m_canBePromotedToStackingContainer = true; |
620 int maxIndex = 0; | |
621 int count = 0; | |
622 bool firstIteration = true; | |
623 updateDescendantsAreContiguousInStackingOrderRecursive(lookup, minIndex, max
Index, count, firstIteration); | |
624 | |
625 m_descendantsAreContiguousInStackingOrderDirty = false; | |
626 } | |
627 | |
628 void RenderLayer::updateDescendantsAreContiguousInStackingOrderRecursive(const H
ashMap<const RenderLayer*, int>& lookup, int& minIndex, int& maxIndex, int& coun
t, bool firstIteration) | |
629 { | |
630 if (isStackingContext() && !firstIteration) { | |
631 if (lookup.contains(this)) { | |
632 minIndex = std::min(minIndex, lookup.get(this)); | |
633 maxIndex = std::max(maxIndex, lookup.get(this)); | |
634 count++; | |
635 } | |
636 return; | |
637 } | |
638 | |
639 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
{ | |
640 int childMinIndex = 0; | |
641 int childMaxIndex = 0; | |
642 int childCount = 0; | |
643 child->updateDescendantsAreContiguousInStackingOrderRecursive(lookup, ch
ildMinIndex, childMaxIndex, childCount, false); | |
644 if (childCount) { | |
645 count += childCount; | |
646 minIndex = std::min(minIndex, childMinIndex); | |
647 maxIndex = std::max(maxIndex, childMaxIndex); | |
648 } | |
649 } | |
650 | |
651 if (!isStackingContext()) { | |
652 m_descendantsAreContiguousInStackingOrder = (maxIndex - minIndex) == cou
nt; | |
653 m_descendantsAreContiguousInStackingOrderDirty = false; | |
654 } | |
655 } | 567 } |
656 | 568 |
657 static inline bool isPositionedContainer(const RenderLayer* layer) | 569 static inline bool isPositionedContainer(const RenderLayer* layer) |
658 { | 570 { |
659 // FIXME: This is not in sync with containingBlock. | 571 // FIXME: This is not in sync with containingBlock. |
660 // RenderObject::canContainFixedPositionedObject() should probably be used | 572 // RenderObject::canContainFixedPositionedObject() should probably be used |
661 // instead. | 573 // instead. |
662 RenderLayerModelObject* layerRenderer = layer->renderer(); | 574 RenderLayerModelObject* layerRenderer = layer->renderer(); |
663 return layer->isRootLayer() || layerRenderer->isPositioned() || layer->hasTr
ansform(); | 575 return layer->isRootLayer() || layerRenderer->isPositioned() || layer->hasTr
ansform(); |
664 } | 576 } |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1078 if (curr == ancestorStackingContainer) | 990 if (curr == ancestorStackingContainer) |
1079 return; | 991 return; |
1080 } | 992 } |
1081 } | 993 } |
1082 | 994 |
1083 bool RenderLayer::canBeStackingContainer() const | 995 bool RenderLayer::canBeStackingContainer() const |
1084 { | 996 { |
1085 if (isStackingContext() || !ancestorStackingContainer()) | 997 if (isStackingContext() || !ancestorStackingContainer()) |
1086 return true; | 998 return true; |
1087 | 999 |
1088 ASSERT(!m_descendantsAreContiguousInStackingOrderDirty); | 1000 ASSERT(!m_canBePromotedToStackingContainerDirty); |
1089 return m_descendantsAreContiguousInStackingOrder; | 1001 return m_canBePromotedToStackingContainer; |
1090 } | 1002 } |
1091 | 1003 |
1092 void RenderLayer::setHasVisibleContent() | 1004 void RenderLayer::setHasVisibleContent() |
1093 { | 1005 { |
1094 if (m_hasVisibleContent && !m_visibleContentStatusDirty) { | 1006 if (m_hasVisibleContent && !m_visibleContentStatusDirty) { |
1095 ASSERT(!parent() || parent()->hasVisibleDescendant()); | 1007 ASSERT(!parent() || parent()->hasVisibleDescendant()); |
1096 return; | 1008 return; |
1097 } | 1009 } |
1098 | 1010 |
1099 m_visibleContentStatusDirty = false; | 1011 m_visibleContentStatusDirty = false; |
(...skipping 960 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2060 case CompositedScrollingAlwaysOff: | 1972 case CompositedScrollingAlwaysOff: |
2061 return false; | 1973 return false; |
2062 } | 1974 } |
2063 | 1975 |
2064 ASSERT_NOT_REACHED(); | 1976 ASSERT_NOT_REACHED(); |
2065 return m_needsCompositedScrolling; | 1977 return m_needsCompositedScrolling; |
2066 } | 1978 } |
2067 | 1979 |
2068 void RenderLayer::updateNeedsCompositedScrolling() | 1980 void RenderLayer::updateNeedsCompositedScrolling() |
2069 { | 1981 { |
2070 if (RenderLayer* ancestor = ancestorStackingContext()) | 1982 updateCanBeStackingContainer(); |
2071 ancestor->updateDescendantsAreContiguousInStackingOrder(); | |
2072 | 1983 |
2073 bool needsCompositedScrolling = false; | 1984 bool needsCompositedScrolling = false; |
| 1985 updateDescendantDependentFlags(); |
2074 | 1986 |
2075 FrameView* frameView = renderer()->view()->frameView(); | 1987 ASSERT(renderer()->view()->frameView() && renderer()->view()->frameView()->c
ontainsScrollableArea(this)); |
2076 if (frameView && frameView->containsScrollableArea(this)) { | 1988 bool forceUseCompositedScrolling = acceleratedCompositingForOverflowScrollEn
abled() |
2077 updateDescendantDependentFlags(); | 1989 && canBeStackingContainer() |
2078 | 1990 && !hasUnclippedDescendant(); |
2079 bool forceUseCompositedScrolling = acceleratedCompositingForOverflowScro
llEnabled() | |
2080 && canBeStackingContainer() | |
2081 && !hasUnclippedDescendant(); | |
2082 | 1991 |
2083 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING) | 1992 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING) |
2084 needsCompositedScrolling = forceUseCompositedScrolling || renderer()->st
yle()->useTouchOverflowScrolling(); | 1993 needsCompositedScrolling = forceUseCompositedScrolling || renderer()->style(
)->useTouchOverflowScrolling(); |
2085 #else | 1994 #else |
2086 needsCompositedScrolling = forceUseCompositedScrolling; | 1995 needsCompositedScrolling = forceUseCompositedScrolling; |
2087 #endif | 1996 #endif |
2088 // We gather a boolean value for use with Google UMA histograms to | 1997 // We gather a boolean value for use with Google UMA histograms to |
2089 // quantify the actual effects of a set of patches attempting to | 1998 // quantify the actual effects of a set of patches attempting to |
2090 // relax composited scrolling requirements, thereby increasing the | 1999 // relax composited scrolling requirements, thereby increasing the |
2091 // number of composited overflow divs. | 2000 // number of composited overflow divs. |
2092 if (acceleratedCompositingForOverflowScrollEnabled()) | 2001 if (acceleratedCompositingForOverflowScrollEnabled()) |
2093 HistogramSupport::histogramEnumeration("Renderer.NeedsCompositedScro
lling", needsCompositedScrolling, 2); | 2002 HistogramSupport::histogramEnumeration("Renderer.NeedsCompositedScrollin
g", needsCompositedScrolling, 2); |
2094 } | |
2095 | 2003 |
2096 setNeedsCompositedScrolling(needsCompositedScrolling); | 2004 setNeedsCompositedScrolling(needsCompositedScrolling); |
2097 } | 2005 } |
2098 | 2006 |
2099 void RenderLayer::setNeedsCompositedScrolling(bool needsCompositedScrolling) | 2007 void RenderLayer::setNeedsCompositedScrolling(bool needsCompositedScrolling) |
2100 { | 2008 { |
2101 if (m_needsCompositedScrolling == needsCompositedScrolling) | 2009 if (m_needsCompositedScrolling == needsCompositedScrolling) |
2102 return; | 2010 return; |
2103 | 2011 |
2104 m_needsCompositedScrolling = needsCompositedScrolling; | 2012 m_needsCompositedScrolling = needsCompositedScrolling; |
(...skipping 3514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5619 { | 5527 { |
5620 ASSERT(m_layerListMutationAllowed); | 5528 ASSERT(m_layerListMutationAllowed); |
5621 ASSERT(isStackingContainer()); | 5529 ASSERT(isStackingContainer()); |
5622 | 5530 |
5623 if (m_posZOrderList) | 5531 if (m_posZOrderList) |
5624 m_posZOrderList->clear(); | 5532 m_posZOrderList->clear(); |
5625 if (m_negZOrderList) | 5533 if (m_negZOrderList) |
5626 m_negZOrderList->clear(); | 5534 m_negZOrderList->clear(); |
5627 m_zOrderListsDirty = true; | 5535 m_zOrderListsDirty = true; |
5628 | 5536 |
5629 m_descendantsAreContiguousInStackingOrderDirty = true; | 5537 m_canBePromotedToStackingContainerDirty = true; |
5630 | 5538 |
5631 if (!renderer()->documentBeingDestroyed()) { | 5539 if (!renderer()->documentBeingDestroyed()) { |
5632 compositor()->setNeedsUpdateCompositingRequirementsState(); | 5540 compositor()->setNeedsUpdateCompositingRequirementsState(); |
5633 compositor()->setCompositingLayersNeedRebuild(); | 5541 compositor()->setCompositingLayersNeedRebuild(); |
5634 if (acceleratedCompositingForOverflowScrollEnabled()) | 5542 if (acceleratedCompositingForOverflowScrollEnabled()) |
5635 compositor()->setShouldReevaluateCompositingAfterLayout(); | 5543 compositor()->setShouldReevaluateCompositingAfterLayout(); |
5636 } | 5544 } |
5637 } | 5545 } |
5638 | 5546 |
5639 void RenderLayer::dirtyStackingContainerZOrderLists() | 5547 void RenderLayer::dirtyStackingContainerZOrderLists() |
(...skipping 812 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6452 } | 6360 } |
6453 } | 6361 } |
6454 | 6362 |
6455 void showLayerTree(const WebCore::RenderObject* renderer) | 6363 void showLayerTree(const WebCore::RenderObject* renderer) |
6456 { | 6364 { |
6457 if (!renderer) | 6365 if (!renderer) |
6458 return; | 6366 return; |
6459 showLayerTree(renderer->enclosingLayer()); | 6367 showLayerTree(renderer->enclosingLayer()); |
6460 } | 6368 } |
6461 #endif | 6369 #endif |
OLD | NEW |