OLD | NEW |
---|---|
1 // Copyright 2011 The Chromium Authors. All rights reserved. | 1 // Copyright 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 | 6 |
7 #include "cc/tiled_layer.h" | 7 #include "cc/tiled_layer.h" |
8 | 8 |
9 #include "CCLayerImpl.h" | 9 #include "CCLayerImpl.h" |
10 #include "CCLayerTreeHost.h" | 10 #include "CCLayerTreeHost.h" |
(...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
561 priority = CCPriorityCalculator::maxPriority(priority, CCPriorityCalcula tor::smallAnimatedLayerMinPriority()); | 561 priority = CCPriorityCalculator::maxPriority(priority, CCPriorityCalcula tor::smallAnimatedLayerMinPriority()); |
562 if (priority != CCPriorityCalculator::lowestPriority()) | 562 if (priority != CCPriorityCalculator::lowestPriority()) |
563 texture->setRequestPriority(priority); | 563 texture->setRequestPriority(priority); |
564 } | 564 } |
565 } | 565 } |
566 | 566 |
567 void TiledLayerChromium::setTexturePriorities(const CCPriorityCalculator& priori tyCalc) | 567 void TiledLayerChromium::setTexturePriorities(const CCPriorityCalculator& priori tyCalc) |
568 { | 568 { |
569 updateBounds(); | 569 updateBounds(); |
570 resetUpdateState(); | 570 resetUpdateState(); |
571 updateScrollPrediction(); | |
571 | 572 |
572 if (m_tiler->hasEmptyBounds()) | 573 if (m_tiler->hasEmptyBounds()) |
573 return; | 574 return; |
574 | 575 |
575 bool drawsToRoot = !renderTarget()->parent(); | 576 bool drawsToRoot = !renderTarget()->parent(); |
576 bool smallAnimatedLayer = isSmallAnimatedLayer(this); | 577 bool smallAnimatedLayer = isSmallAnimatedLayer(this); |
577 | 578 |
578 // Minimally create the tiles in the desired pre-paint rect. | 579 // Minimally create the tiles in the desired pre-paint rect. |
579 IntRect createTilesRect = idlePaintRect(); | 580 IntRect createTilesRect = idlePaintRect(); |
580 if (!createTilesRect.isEmpty()) { | 581 if (!createTilesRect.isEmpty()) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
630 } | 631 } |
631 } | 632 } |
632 | 633 |
633 // Now update priorities on all tiles we have in the layer, no matter where they are. | 634 // Now update priorities on all tiles we have in the layer, no matter where they are. |
634 for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begi n(); iter != m_tiler->tiles().end(); ++iter) { | 635 for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begi n(); iter != m_tiler->tiles().end(); ++iter) { |
635 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); | 636 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); |
636 // FIXME: This should not ever be null. | 637 // FIXME: This should not ever be null. |
637 if (!tile) | 638 if (!tile) |
638 continue; | 639 continue; |
639 IntRect tileRect = m_tiler->tileRect(tile); | 640 IntRect tileRect = m_tiler->tileRect(tile); |
640 setPriorityForTexture(visibleContentRect(), tileRect, drawsToRoot, small AnimatedLayer, tile->managedTexture()); | 641 setPriorityForTexture(m_predictedVisibleRect, tileRect, drawsToRoot, sma llAnimatedLayer, tile->managedTexture()); |
641 } | 642 } |
642 } | 643 } |
643 | 644 |
644 Region TiledLayerChromium::visibleContentOpaqueRegion() const | 645 Region TiledLayerChromium::visibleContentOpaqueRegion() const |
645 { | 646 { |
646 if (m_skipsDraw) | 647 if (m_skipsDraw) |
647 return Region(); | 648 return Region(); |
648 if (contentsOpaque()) | 649 if (contentsOpaque()) |
649 return visibleContentRect(); | 650 return visibleContentRect(); |
650 return m_tiler->opaqueRegionInContentRect(visibleContentRect()); | 651 return m_tiler->opaqueRegionInContentRect(visibleContentRect()); |
651 } | 652 } |
652 | 653 |
653 void TiledLayerChromium::resetUpdateState() | 654 void TiledLayerChromium::resetUpdateState() |
654 { | 655 { |
655 m_skipsDraw = false; | 656 m_skipsDraw = false; |
656 m_failedUpdate = false; | 657 m_failedUpdate = false; |
657 | 658 |
658 CCLayerTilingData::TileMap::const_iterator end = m_tiler->tiles().end(); | 659 CCLayerTilingData::TileMap::const_iterator end = m_tiler->tiles().end(); |
659 for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begi n(); iter != end; ++iter) { | 660 for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begi n(); iter != end; ++iter) { |
660 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); | 661 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); |
661 // FIXME: This should not ever be null. | 662 // FIXME: This should not ever be null. |
662 if (!tile) | 663 if (!tile) |
663 continue; | 664 continue; |
664 tile->resetUpdateState(); | 665 tile->resetUpdateState(); |
665 } | 666 } |
666 } | 667 } |
667 | 668 |
669 namespace { | |
670 IntRect expandRectByDelta(IntRect rect, IntSize delta) { | |
671 int width = rect.width() + abs(delta.width()); | |
672 int height = rect.height() + abs(delta.height()); | |
673 int x = rect.x() + ((delta.width() < 0) ? delta.width() : 0); | |
enne (OOO)
2012/10/18 19:13:08
Why do you need this clamping on the negative end,
epennerAtGoogle
2012/10/18 19:58:55
When expanding a rect in the direction of an arbit
enne (OOO)
2012/10/19 18:40:56
Ah, gotcha, thanks.
| |
674 int y = rect.y() + ((delta.height() < 0) ? delta.height() : 0); | |
675 return IntRect(x, y, width, height); | |
676 } | |
677 } | |
678 | |
679 void TiledLayerChromium::updateScrollPrediction() | |
680 { | |
681 // This scroll prediction is very primitive and should be replaced by a | |
682 // a recursive calculation on all layers which uses actual scroll/animation | |
683 // velocities. To insure this doesn't miss-predict, we only use it to predic t | |
684 // the visibleRect if: | |
685 // - contentBounds() hasn't changed. | |
686 // - visibleRect.size() hasn't changed. | |
687 // These two conditions prevent rotations, scales, pinch-zooms etc. where | |
688 // the prediction would be incorrect. | |
689 IntSize delta = visibleContentRect().center() - m_previousVisibleRect.center (); | |
690 m_predictedScroll = -delta; | |
691 m_predictedVisibleRect = visibleContentRect(); | |
692 if (m_previousContentBounds == contentBounds() && m_previousVisibleRect.size () == visibleContentRect().size()) { | |
693 // Only expand the visible rect in the major scroll direction, to preven t | |
694 // massive paints due to diagonal scrolls. | |
695 IntSize majorScrollAxis = (abs(delta.width()) > abs(delta.height())) ? I ntSize(delta.width(), 0) : IntSize(0, delta.height()); | |
696 m_predictedVisibleRect = expandRectByDelta(visibleContentRect(), majorSc rollAxis); | |
697 | |
698 // Bound the prediction to at most 2 tiles, and clamp to content bounds. | |
enne (OOO)
2012/10/18 19:13:08
The 2 tiles ahead guess seems a little magical. H
epennerAtGoogle
2012/10/18 19:58:55
There needs to be some kind of clamp to prevent ar
| |
699 IntRect bound = visibleContentRect(); | |
700 bound.inflateX(m_tiler->tileSize().width() * 2); | |
701 bound.inflateY(m_tiler->tileSize().height() * 2); | |
702 bound.intersect(IntRect(IntPoint::zero(), contentBounds())); | |
703 m_predictedVisibleRect.intersect(bound); | |
704 } | |
705 m_previousContentBounds = contentBounds(); | |
706 m_previousVisibleRect = visibleContentRect(); | |
707 } | |
708 | |
668 void TiledLayerChromium::update(CCTextureUpdateQueue& queue, const CCOcclusionTr acker* occlusion, CCRenderingStats& stats) | 709 void TiledLayerChromium::update(CCTextureUpdateQueue& queue, const CCOcclusionTr acker* occlusion, CCRenderingStats& stats) |
669 { | 710 { |
670 ASSERT(!m_skipsDraw && !m_failedUpdate); // Did resetUpdateState get skipped ? | 711 ASSERT(!m_skipsDraw && !m_failedUpdate); // Did resetUpdateState get skipped ? |
671 updateBounds(); | 712 updateBounds(); |
672 if (m_tiler->hasEmptyBounds() || !drawsContent()) | 713 if (m_tiler->hasEmptyBounds() || !drawsContent()) |
673 return; | 714 return; |
674 | 715 |
675 bool didPaint = false; | 716 bool didPaint = false; |
676 | 717 |
677 // Animation pre-paint. If the layer is small, try to paint it all | 718 // Animation pre-paint. If the layer is small, try to paint it all |
678 // immediately whether or not it is occluded, to avoid paint/upload | 719 // immediately whether or not it is occluded, to avoid paint/upload |
679 // hiccups while it is animating. | 720 // hiccups while it is animating. |
680 if (isSmallAnimatedLayer(this)) { | 721 if (isSmallAnimatedLayer(this)) { |
681 int left, top, right, bottom; | 722 int left, top, right, bottom; |
682 m_tiler->contentRectToTileIndices(IntRect(IntPoint::zero(), contentBound s()), left, top, right, bottom); | 723 m_tiler->contentRectToTileIndices(IntRect(IntPoint::zero(), contentBound s()), left, top, right, bottom); |
683 updateTiles(left, top, right, bottom, queue, 0, stats, didPaint); | 724 updateTiles(left, top, right, bottom, queue, 0, stats, didPaint); |
684 if (didPaint) | 725 if (didPaint) |
685 return; | 726 return; |
686 // This was an attempt to paint the entire layer so if we fail it's okay , | 727 // This was an attempt to paint the entire layer so if we fail it's okay , |
687 // just fallback on painting visible etc. below. | 728 // just fallback on painting visible etc. below. |
688 m_failedUpdate = false; | 729 m_failedUpdate = false; |
689 } | 730 } |
690 | 731 |
691 if (visibleContentRect().isEmpty()) | 732 if (m_predictedVisibleRect.isEmpty()) |
692 return; | 733 return; |
693 | 734 |
694 // Visible painting. First occlude visible tiles and paint the non-occluded tiles. | 735 // Visible painting. First occlude visible tiles and paint the non-occluded tiles. |
695 int left, top, right, bottom; | 736 int left, top, right, bottom; |
696 m_tiler->contentRectToTileIndices(visibleContentRect(), left, top, right, bo ttom); | 737 m_tiler->contentRectToTileIndices(m_predictedVisibleRect, left, top, right, bottom); |
697 markOcclusionsAndRequestTextures(left, top, right, bottom, occlusion); | 738 markOcclusionsAndRequestTextures(left, top, right, bottom, occlusion); |
698 m_skipsDraw = !updateTiles(left, top, right, bottom, queue, occlusion, stats , didPaint); | 739 m_skipsDraw = !updateTiles(left, top, right, bottom, queue, occlusion, stats , didPaint); |
699 if (m_skipsDraw) | 740 if (m_skipsDraw) |
700 m_tiler->reset(); | 741 m_tiler->reset(); |
701 if (m_skipsDraw || didPaint) | 742 if (m_skipsDraw || didPaint) |
702 return; | 743 return; |
703 | 744 |
704 // If we have already painting everything visible. Do some pre-painting whil e idle. | 745 // If we have already painting everything visible. Do some pre-painting whil e idle. |
705 IntRect idlePaintContentRect = idlePaintRect(); | 746 IntRect idlePaintContentRect = idlePaintRect(); |
706 if (idlePaintContentRect.isEmpty()) | 747 if (idlePaintContentRect.isEmpty()) |
707 return; | 748 return; |
708 | 749 |
709 // Prepaint anything that was occluded but inside the layer's visible region . | 750 // Prepaint anything that was occluded but inside the layer's visible region . |
710 if (!updateTiles(left, top, right, bottom, queue, 0, stats, didPaint) || did Paint) | 751 if (!updateTiles(left, top, right, bottom, queue, 0, stats, didPaint) || did Paint) |
711 return; | 752 return; |
712 | 753 |
713 int prepaintLeft, prepaintTop, prepaintRight, prepaintBottom; | 754 int prepaintLeft, prepaintTop, prepaintRight, prepaintBottom; |
714 m_tiler->contentRectToTileIndices(idlePaintContentRect, prepaintLeft, prepai ntTop, prepaintRight, prepaintBottom); | 755 m_tiler->contentRectToTileIndices(idlePaintContentRect, prepaintLeft, prepai ntTop, prepaintRight, prepaintBottom); |
715 | 756 |
716 // Then expand outwards from the visible area until we find a dirty row or c olumn to update. | 757 // Then expand outwards one row/column at a time until we find a dirty row/c olumn |
717 while (left > prepaintLeft || top > prepaintTop || right < prepaintRight || bottom < prepaintBottom) { | 758 // to update. Increment along the major and minor scroll directions first. |
718 if (bottom < prepaintBottom) { | 759 IntSize delta = -m_predictedScroll; |
719 ++bottom; | 760 delta = IntSize(delta.width() == 0 ? 1 : delta.width(), |
720 if (!updateTiles(left, bottom, right, bottom, queue, 0, stats, didPa int) || didPaint) | 761 delta.height() == 0 ? 1 : delta.height()); |
721 return; | 762 IntSize majorDelta = (abs(delta.width()) > abs(delta.height())) ? IntSize(d elta.width(), 0) : IntSize(0, delta.height()); |
763 IntSize minorDelta = (abs(delta.width()) <= abs(delta.height())) ? IntSize(d elta.width(), 0) : IntSize(0, delta.height()); | |
764 IntSize deltas[4] = {majorDelta, minorDelta, -majorDelta, -minorDelta}; | |
765 for(int i = 0; i < 4; i++) { | |
766 if (deltas[i].height() > 0) { | |
767 while (bottom < prepaintBottom) { | |
768 ++bottom; | |
769 if (!updateTiles(left, bottom, right, bottom, queue, 0, stats, d idPaint) || didPaint) | |
770 return; | |
771 } | |
722 } | 772 } |
723 if (top > prepaintTop) { | 773 if (deltas[i].height() < 0) { |
724 --top; | 774 while (top > prepaintTop) { |
725 if (!updateTiles(left, top, right, top, queue, 0, stats, didPaint) | | didPaint) | 775 --top; |
726 return; | 776 if (!updateTiles(left, top, right, top, queue, 0, stats, didPain t) || didPaint) |
777 return; | |
778 } | |
727 } | 779 } |
728 if (left > prepaintLeft) { | 780 if (deltas[i].width() < 0) { |
729 --left; | 781 while (left > prepaintLeft) { |
730 if (!updateTiles(left, top, left, bottom, queue, 0, stats, didPaint) || didPaint) | 782 --left; |
731 return; | 783 if (!updateTiles(left, top, left, bottom, queue, 0, stats, didPa int) || didPaint) |
784 return; | |
785 } | |
732 } | 786 } |
733 if (right < prepaintRight) { | 787 if (deltas[i].width() > 0) { |
734 ++right; | 788 while (right < prepaintRight) { |
735 if (!updateTiles(right, top, right, bottom, queue, 0, stats, didPain t) || didPaint) | 789 ++right; |
736 return; | 790 if (!updateTiles(right, top, right, bottom, queue, 0, stats, did Paint) || didPaint) |
791 return; | |
792 } | |
737 } | 793 } |
738 } | 794 } |
739 } | 795 } |
740 | 796 |
741 bool TiledLayerChromium::needsIdlePaint() | 797 bool TiledLayerChromium::needsIdlePaint() |
742 { | 798 { |
743 // Don't trigger more paints if we failed (as we'll just fail again). | 799 // Don't trigger more paints if we failed (as we'll just fail again). |
744 if (m_failedUpdate || visibleContentRect().isEmpty() || m_tiler->hasEmptyBou nds() || !drawsContent()) | 800 if (m_failedUpdate || visibleContentRect().isEmpty() || m_tiler->hasEmptyBou nds() || !drawsContent()) |
745 return false; | 801 return false; |
746 | 802 |
(...skipping 23 matching lines...) Expand all Loading... | |
770 | 826 |
771 IntRect TiledLayerChromium::idlePaintRect() | 827 IntRect TiledLayerChromium::idlePaintRect() |
772 { | 828 { |
773 // Don't inflate an empty rect. | 829 // Don't inflate an empty rect. |
774 if (visibleContentRect().isEmpty()) | 830 if (visibleContentRect().isEmpty()) |
775 return IntRect(); | 831 return IntRect(); |
776 | 832 |
777 // FIXME: This can be made a lot larger now! We should increase | 833 // FIXME: This can be made a lot larger now! We should increase |
778 // this slowly while insuring it doesn't cause any perf issues. | 834 // this slowly while insuring it doesn't cause any perf issues. |
779 IntRect prepaintRect = visibleContentRect(); | 835 IntRect prepaintRect = visibleContentRect(); |
780 prepaintRect.inflateX(m_tiler->tileSize().width()); | 836 prepaintRect.inflateX(m_tiler->tileSize().width() * 2); |
781 prepaintRect.inflateY(m_tiler->tileSize().height() * 2); | 837 prepaintRect.inflateY(m_tiler->tileSize().height() * 4); |
782 IntRect contentRect(IntPoint::zero(), contentBounds()); | 838 IntRect contentRect(IntPoint::zero(), contentBounds()); |
783 prepaintRect.intersect(contentRect); | 839 prepaintRect.intersect(contentRect); |
784 | 840 |
785 return prepaintRect; | 841 return prepaintRect; |
786 } | 842 } |
787 | 843 |
788 } | 844 } |
OLD | NEW |