Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(177)

Side by Side Diff: Source/core/rendering/RenderLayer.cpp

Issue 13427009: Replace the current contiguity check for composited scrolling (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Addressing review comments Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 RenderLayer::RenderLayer(RenderLayerModelObject* renderer) 142 RenderLayer::RenderLayer(RenderLayerModelObject* renderer)
143 : m_inResizeMode(false) 143 : m_inResizeMode(false)
144 , m_scrollDimensionsDirty(true) 144 , m_scrollDimensionsDirty(true)
145 , m_normalFlowListDirty(true) 145 , m_normalFlowListDirty(true)
146 , m_hasSelfPaintingLayerDescendant(false) 146 , m_hasSelfPaintingLayerDescendant(false)
147 , m_hasSelfPaintingLayerDescendantDirty(false) 147 , m_hasSelfPaintingLayerDescendantDirty(false)
148 , m_hasOutOfFlowPositionedDescendant(false) 148 , m_hasOutOfFlowPositionedDescendant(false)
149 , m_hasOutOfFlowPositionedDescendantDirty(true) 149 , m_hasOutOfFlowPositionedDescendantDirty(true)
150 , m_hasUnclippedDescendant(false) 150 , m_hasUnclippedDescendant(false)
151 , m_needsCompositedScrolling(false) 151 , m_needsCompositedScrolling(false)
152 , m_descendantsAreContiguousInStackingOrder(false) 152 , m_canBePromotedToStackingContainer(false)
153 , m_descendantsAreContiguousInStackingOrderDirty(true) 153 , m_canBePromotedToStackingContainerDirty(true)
154 , m_isRootLayer(renderer->isRenderView()) 154 , m_isRootLayer(renderer->isRenderView())
155 , m_usedTransparency(false) 155 , m_usedTransparency(false)
156 , m_paintingInsideReflection(false) 156 , m_paintingInsideReflection(false)
157 , m_inOverflowRelayout(false) 157 , m_inOverflowRelayout(false)
158 , m_repaintStatus(NeedsNormalRepaint) 158 , m_repaintStatus(NeedsNormalRepaint)
159 , m_visibleContentStatusDirty(true) 159 , m_visibleContentStatusDirty(true)
160 , m_hasVisibleContent(false) 160 , m_hasVisibleContent(false)
161 , m_visibleDescendantStatusDirty(false) 161 , m_visibleDescendantStatusDirty(false)
162 , m_hasVisibleDescendant(false) 162 , m_hasVisibleDescendant(false)
163 , m_isPaginated(false) 163 , m_isPaginated(false)
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 } 513 }
514 } 514 }
515 515
516 bool RenderLayer::acceleratedCompositingForOverflowScrollEnabled() const 516 bool RenderLayer::acceleratedCompositingForOverflowScrollEnabled() const
517 { 517 {
518 return renderer()->frame() 518 return renderer()->frame()
519 && renderer()->frame()->page()->settings() 519 && renderer()->frame()->page()->settings()
520 && (renderer()->frame()->page()->settings()->acceleratedCompositingForOv erflowScrollEnabled() != AcceleratedCompositingForOverflowScrollDisabled); 520 && (renderer()->frame()->page()->settings()->acceleratedCompositingForOv erflowScrollEnabled() != AcceleratedCompositingForOverflowScrollDisabled);
521 } 521 }
522 522
523 // If we are a stacking container, then this function will determine if our 523 // Determine whether the current layer can be promoted to a stacking container.
524 // descendants for a contiguous block in stacking order. This is required in 524 // We do this by computing what positive and negative z-order lists would look
525 // order for an element to be safely promoted to a stacking container. It is saf e 525 // like before and after promotion, and ensuring that proper stacking order is
526 // to become a stacking container if this change would not alter the stacking 526 // preserved between the two sets of lists.
527 // order of layers on the page. That can only happen if a non-descendant appear 527 void RenderLayer::updateCanBeStackingContainer()
528 // between us and our descendants in stacking order. Here's an example:
529 //
530 // this
531 // / | \.
532 // A B C
533 // /\ | /\.
534 // 0 -8 D 2 7
535 // |
536 // 5
537 //
538 // I've labeled our normal flow descendants A, B, C, and D, our stacking
539 // container descendants with their z indices, and us with 'this' (we're a
540 // stacking container and our zIndex doesn't matter here). These nodes appear in
541 // three lists: posZOrder, negZOrder, and normal flow (keep in mind that normal
542 // flow layers don't overlap). So if we arrange these lists in order we get our
543 // stacking order:
544 //
545 // [-8], [A-D], [0, 2, 5, 7]--> pos z-order.
546 // | |
547 // Neg z-order. <-+ +--> Normal flow descendants.
548 //
549 // We can then assign new, 'stacking' order indices to these elements as follows :
550 //
551 // [-8], [A-D], [0, 2, 5, 7]
552 // 'Stacking' indices: -1 0 1 2 3 4
553 //
554 // Note that the normal flow descendants can share an index because they don't
555 // stack/overlap. Now our problem becomes very simple: a layer can safely become
556 // a stacking container if the stacking-order indices of it and its descendants
557 // appear in a contiguous block in the list of stacking indices. This problem
558 // can be solved very efficiently by calculating the min/max stacking indices in
559 // the subtree, and the number stacking container descendants. Once we have this
560 // information, we know that the subtree's indices form a contiguous block if:
561 //
562 // maxStackIndex - minStackIndex == numSCDescendants
563 //
564 // So for node A in the example above we would have:
565 // maxStackIndex = 1
566 // minStackIndex = -1
567 // numSCDecendants = 2
568 //
569 // and so,
570 // maxStackIndex - minStackIndex == numSCDescendants
571 // ===> 1 - (-1) == 2
572 // ===> 2 == 2
573 //
574 // Since this is true, A can safely become a stacking container.
575 // Now, for node C we have:
576 //
577 // maxStackIndex = 4
578 // minStackIndex = 0 <-- because C has stacking index 0.
579 // numSCDecendants = 2
580 //
581 // and so,
582 // maxStackIndex - minStackIndex == numSCDescendants
583 // ===> 4 - 0 == 2
584 // ===> 4 == 2
585 //
586 // Since this is false, C cannot be safely promoted to a stacking container. Thi s
587 // happened because of the elements with z-index 5 and 0. Now if 5 had been a
588 // child of C rather than D, and A had no child with Z index 0, we would have ha d:
589 //
590 // maxStackIndex = 3
591 // minStackIndex = 0 <-- because C has stacking index 0.
592 // numSCDecendants = 3
593 //
594 // and so,
595 // maxStackIndex - minStackIndex == numSCDescendants
596 // ===> 3 - 0 == 3
597 // ===> 3 == 3
598 //
599 // And we would conclude that C could be promoted.
600 void RenderLayer::updateDescendantsAreContiguousInStackingOrder()
601 { 528 {
602 if (!m_descendantsAreContiguousInStackingOrderDirty || !isStackingContext() || acceleratedCompositingForOverflowScrollEnabled() == AcceleratedCompositingFor OverflowScrollDisabled) 529 TRACE_EVENT0("blink_rendering", "RenderLayer::updateCanBeStackingContainer") ;
530
531 if (isStackingContext() || !m_canBePromotedToStackingContainerDirty || !acce leratedCompositingForOverflowScrollEnabled())
603 return; 532 return;
604 533
605 OwnPtr<Vector<RenderLayer*> > posZOrderList; 534 FrameView* frameView = renderer()->view()->frameView();
606 OwnPtr<Vector<RenderLayer*> > negZOrderList; 535 if (!frameView || !frameView->containsScrollableArea(this))
607 rebuildZOrderLists(StopAtStackingContexts, posZOrderList, negZOrderList); 536 return;
608 537
609 // Create a reverse lookup. 538 RenderLayer* ancestorStackingContext = this->ancestorStackingContext();
610 HashMap<const RenderLayer*, int> lookup; 539 if (!ancestorStackingContext)
540 return;
611 541
612 if (negZOrderList) { 542 OwnPtr<Vector<RenderLayer*> > posZOrderListBeforePromote = adoptPtr(new Vect or<RenderLayer*>);
613 int stackingOrderIndex = -1; 543 OwnPtr<Vector<RenderLayer*> > negZOrderListBeforePromote = adoptPtr(new Vect or<RenderLayer*>);
614 size_t listSize = negZOrderList->size(); 544 OwnPtr<Vector<RenderLayer*> > posZOrderListAfterPromote = adoptPtr(new Vecto r<RenderLayer*>);
615 for (size_t i = 0; i < listSize; ++i) { 545 OwnPtr<Vector<RenderLayer*> > negZOrderListAfterPromote = adoptPtr(new Vecto r<RenderLayer*>);
616 RenderLayer* currentLayer = negZOrderList->at(listSize - i - 1); 546
617 if (!currentLayer->isStackingContext()) 547 collectBeforePromotionZOrderList(ancestorStackingContext, posZOrderListBefor ePromote, negZOrderListBeforePromote);
618 continue; 548 collectAfterPromotionZOrderList(ancestorStackingContext, posZOrderListAfterP romote, negZOrderListAfterPromote);
619 lookup.set(currentLayer, stackingOrderIndex--); 549
620 } 550 size_t maxIndex = std::min(posZOrderListAfterPromote->size() + negZOrderList AfterPromote->size(), posZOrderListBeforePromote->size() + negZOrderListBeforePr omote->size());
551
552 m_canBePromotedToStackingContainerDirty = false;
553 m_canBePromotedToStackingContainer = false;
554
555 for (size_t i = 0; i < maxIndex; ++i) {
556 const RenderLayer* layerBeforePromote = i < negZOrderListBeforePromote-> size()
557 ? negZOrderListBeforePromote->at(i)
558 : posZOrderListBeforePromote->at(i - negZOrderListBeforePromote->siz e());
559 const RenderLayer* layerAfterPromote = i < negZOrderListAfterPromote->si ze()
560 ? negZOrderListAfterPromote->at(i)
561 : posZOrderListAfterPromote->at(i - negZOrderListAfterPromote->size( ));
562
563 if (layerBeforePromote != layerAfterPromote && (layerAfterPromote != thi s || renderer()->hasBackground()))
564 return;
565
566 if (layerAfterPromote == this)
567 break;
esprehn 2013/05/15 06:50:18 This should be in the loop condition like i < maxI
hartmanng 2013/05/15 15:18:59 Done.
621 } 568 }
622 569
623 if (posZOrderList) { 570 for (size_t i = 0; i < maxIndex; ++i) {
624 size_t listSize = posZOrderList->size(); 571 const RenderLayer* layerBeforePromote = i < posZOrderListBeforePromote-> size()
625 int stackingOrderIndex = 1; 572 ? posZOrderListBeforePromote->at(posZOrderListBeforePromote->size() - i - 1)
esprehn 2013/05/15 06:50:18 This kind of math is really scary. I guess we do b
hartmanng 2013/05/15 15:18:59 Yeah I know what you mean - can you think of a way
626 for (size_t i = 0; i < listSize; ++i) { 573 : negZOrderListBeforePromote->at(negZOrderListBeforePromote->size() + posZOrderListBeforePromote->size() - i - 1);
627 RenderLayer* currentLayer = posZOrderList->at(i); 574 const RenderLayer* layerAfterPromote = i < posZOrderListAfterPromote->si ze()
628 if (!currentLayer->isStackingContext()) 575 ? posZOrderListAfterPromote->at(posZOrderListAfterPromote->size() - i - 1)
629 continue; 576 : negZOrderListAfterPromote->at(negZOrderListAfterPromote->size() + posZOrderListAfterPromote->size() - i - 1);
630 lookup.set(currentLayer, stackingOrderIndex++); 577
631 } 578 if (layerBeforePromote != layerAfterPromote && layerAfterPromote != this )
579 return;
580
581 if (layerAfterPromote == this)
582 break;
esprehn 2013/05/15 06:50:18 Same deal
hartmanng 2013/05/15 15:18:59 Done.
632 } 583 }
633 584
634 int minIndex = 0; 585 m_canBePromotedToStackingContainer = true;
635 int maxIndex = 0;
636 int count = 0;
637 bool firstIteration = true;
638 updateDescendantsAreContiguousInStackingOrderRecursive(lookup, minIndex, max Index, count, firstIteration);
639
640 m_descendantsAreContiguousInStackingOrderDirty = false;
641 }
642
643 void RenderLayer::updateDescendantsAreContiguousInStackingOrderRecursive(const H ashMap<const RenderLayer*, int>& lookup, int& minIndex, int& maxIndex, int& coun t, bool firstIteration)
644 {
645 if (isStackingContext() && !firstIteration) {
646 if (lookup.contains(this)) {
647 minIndex = std::min(minIndex, lookup.get(this));
648 maxIndex = std::max(maxIndex, lookup.get(this));
649 count++;
650 }
651 return;
652 }
653
654 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
655 int childMinIndex = 0;
656 int childMaxIndex = 0;
657 int childCount = 0;
658 child->updateDescendantsAreContiguousInStackingOrderRecursive(lookup, ch ildMinIndex, childMaxIndex, childCount, false);
659 if (childCount) {
660 count += childCount;
661 minIndex = std::min(minIndex, childMinIndex);
662 maxIndex = std::max(maxIndex, childMaxIndex);
663 }
664 }
665
666 if (!isStackingContext()) {
667 m_descendantsAreContiguousInStackingOrder = (maxIndex - minIndex) == cou nt;
668 m_descendantsAreContiguousInStackingOrderDirty = false;
669 }
670 } 586 }
671 587
672 static inline bool isPositionedContainer(const RenderLayer* layer) 588 static inline bool isPositionedContainer(const RenderLayer* layer)
673 { 589 {
674 // FIXME: This is not in sync with containingBlock. 590 // FIXME: This is not in sync with containingBlock.
675 // RenderObject::canContainFixedPositionedObject() should probably be used 591 // RenderObject::canContainFixedPositionedObject() should probably be used
676 // instead. 592 // instead.
677 RenderLayerModelObject* layerRenderer = layer->renderer(); 593 RenderLayerModelObject* layerRenderer = layer->renderer();
678 return layer->isRootLayer() || layerRenderer->isPositioned() || layer->hasTr ansform(); 594 return layer->isRootLayer() || layerRenderer->isPositioned() || layer->hasTr ansform();
679 } 595 }
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after
1093 if (curr == ancestorStackingContainer) 1009 if (curr == ancestorStackingContainer)
1094 return; 1010 return;
1095 } 1011 }
1096 } 1012 }
1097 1013
1098 bool RenderLayer::canBeStackingContainer() const 1014 bool RenderLayer::canBeStackingContainer() const
1099 { 1015 {
1100 if (isStackingContext() || !ancestorStackingContainer()) 1016 if (isStackingContext() || !ancestorStackingContainer())
1101 return true; 1017 return true;
1102 1018
1103 ASSERT(!m_descendantsAreContiguousInStackingOrderDirty); 1019 ASSERT(!m_canBePromotedToStackingContainerDirty);
1104 return m_descendantsAreContiguousInStackingOrder; 1020 return m_canBePromotedToStackingContainer;
1105 } 1021 }
1106 1022
1107 void RenderLayer::setHasVisibleContent() 1023 void RenderLayer::setHasVisibleContent()
1108 { 1024 {
1109 if (m_hasVisibleContent && !m_visibleContentStatusDirty) { 1025 if (m_hasVisibleContent && !m_visibleContentStatusDirty) {
1110 ASSERT(!parent() || parent()->hasVisibleDescendant()); 1026 ASSERT(!parent() || parent()->hasVisibleDescendant());
1111 return; 1027 return;
1112 } 1028 }
1113 1029
1114 m_visibleContentStatusDirty = false; 1030 m_visibleContentStatusDirty = false;
(...skipping 975 matching lines...) Expand 10 before | Expand all | Expand 10 after
2090 case AcceleratedCompositingForOverflowScrollAlwaysOn: 2006 case AcceleratedCompositingForOverflowScrollAlwaysOn:
2091 return true; 2007 return true;
2092 } 2008 }
2093 2009
2094 ASSERT_NOT_REACHED(); 2010 ASSERT_NOT_REACHED();
2095 return m_needsCompositedScrolling; 2011 return m_needsCompositedScrolling;
2096 } 2012 }
2097 2013
2098 void RenderLayer::updateNeedsCompositedScrolling() 2014 void RenderLayer::updateNeedsCompositedScrolling()
2099 { 2015 {
2100 if (RenderLayer* ancestor = ancestorStackingContext()) 2016 updateCanBeStackingContainer();
2101 ancestor->updateDescendantsAreContiguousInStackingOrder();
2102 2017
2103 bool needsCompositedScrolling = false; 2018 bool needsCompositedScrolling = false;
2019 updateDescendantDependentFlags();
2104 2020
2105 FrameView* frameView = renderer()->view()->frameView(); 2021 ASSERT(renderer()->view()->frameView() && renderer()->view()->frameView()->c ontainsScrollableArea(this));
2106 if (frameView && frameView->containsScrollableArea(this)) { 2022 bool forceUseCompositedScrolling = acceleratedCompositingForOverflowScrollEn abled()
2107 updateDescendantDependentFlags(); 2023 && canBeStackingContainer()
2108 2024 && !hasUnclippedDescendant();
2109 bool forceUseCompositedScrolling = acceleratedCompositingForOverflowScro llEnabled()
2110 && canBeStackingContainer()
2111 && !hasUnclippedDescendant();
2112 2025
2113 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING) 2026 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
2114 needsCompositedScrolling = forceUseCompositedScrolling || renderer()->st yle()->useTouchOverflowScrolling(); 2027 needsCompositedScrolling = forceUseCompositedScrolling || renderer()->style( )->useTouchOverflowScrolling();
2115 #else 2028 #else
2116 needsCompositedScrolling = forceUseCompositedScrolling; 2029 needsCompositedScrolling = forceUseCompositedScrolling;
2117 #endif 2030 #endif
2118 // We gather a boolean value for use with Google UMA histograms to 2031 // We gather a boolean value for use with Google UMA histograms to
2119 // quantify the actual effects of a set of patches attempting to 2032 // quantify the actual effects of a set of patches attempting to
2120 // relax composited scrolling requirements, thereby increasing the 2033 // relax composited scrolling requirements, thereby increasing the
2121 // number of composited overflow divs. 2034 // number of composited overflow divs.
2122 if (acceleratedCompositingForOverflowScrollEnabled()) 2035 if (acceleratedCompositingForOverflowScrollEnabled())
2123 HistogramSupport::histogramEnumeration("Renderer.NeedsCompositedScro lling", needsCompositedScrolling, 2); 2036 HistogramSupport::histogramEnumeration("Renderer.NeedsCompositedScrollin g", needsCompositedScrolling, 2);
2124 }
2125 2037
2126 setNeedsCompositedScrolling(needsCompositedScrolling); 2038 setNeedsCompositedScrolling(needsCompositedScrolling);
2127 } 2039 }
2128 2040
2129 void RenderLayer::setNeedsCompositedScrolling(bool needsCompositedScrolling) 2041 void RenderLayer::setNeedsCompositedScrolling(bool needsCompositedScrolling)
2130 { 2042 {
2131 if (m_needsCompositedScrolling == needsCompositedScrolling) 2043 if (m_needsCompositedScrolling == needsCompositedScrolling)
2132 return; 2044 return;
2133 2045
2134 m_needsCompositedScrolling = needsCompositedScrolling; 2046 m_needsCompositedScrolling = needsCompositedScrolling;
(...skipping 3519 matching lines...) Expand 10 before | Expand all | Expand 10 after
5654 { 5566 {
5655 ASSERT(m_layerListMutationAllowed); 5567 ASSERT(m_layerListMutationAllowed);
5656 ASSERT(isStackingContainer()); 5568 ASSERT(isStackingContainer());
5657 5569
5658 if (m_posZOrderList) 5570 if (m_posZOrderList)
5659 m_posZOrderList->clear(); 5571 m_posZOrderList->clear();
5660 if (m_negZOrderList) 5572 if (m_negZOrderList)
5661 m_negZOrderList->clear(); 5573 m_negZOrderList->clear();
5662 m_zOrderListsDirty = true; 5574 m_zOrderListsDirty = true;
5663 5575
5664 m_descendantsAreContiguousInStackingOrderDirty = true; 5576 m_canBePromotedToStackingContainerDirty = true;
5665 5577
5666 if (!renderer()->documentBeingDestroyed()) { 5578 if (!renderer()->documentBeingDestroyed()) {
5667 compositor()->setNeedsUpdateCompositedScrolling(); 5579 compositor()->setNeedsUpdateCompositedScrolling();
5668 compositor()->setCompositingLayersNeedRebuild(); 5580 compositor()->setCompositingLayersNeedRebuild();
5669 if (acceleratedCompositingForOverflowScrollEnabled()) 5581 if (acceleratedCompositingForOverflowScrollEnabled())
5670 compositor()->setShouldReevaluateCompositingAfterLayout(); 5582 compositor()->setShouldReevaluateCompositingAfterLayout();
5671 } 5583 }
5672 } 5584 }
5673 5585
5674 void RenderLayer::dirtyStackingContainerZOrderLists() 5586 void RenderLayer::dirtyStackingContainerZOrderLists()
(...skipping 822 matching lines...) Expand 10 before | Expand all | Expand 10 after
6497 } 6409 }
6498 } 6410 }
6499 6411
6500 void showLayerTree(const WebCore::RenderObject* renderer) 6412 void showLayerTree(const WebCore::RenderObject* renderer)
6501 { 6413 {
6502 if (!renderer) 6414 if (!renderer)
6503 return; 6415 return;
6504 showLayerTree(renderer->enclosingLayer()); 6416 showLayerTree(renderer->enclosingLayer());
6505 } 6417 }
6506 #endif 6418 #endif
OLDNEW
« LayoutTests/TestExpectations ('K') | « Source/core/rendering/RenderLayer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698