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

Side by Side Diff: cc/tiled_layer.cc

Issue 11193010: cc: Add predictive pre-painting. (Closed) Base URL: http://git.chromium.org/chromium/src.git@PTM_TiledLayerChromium_fixes
Patch Set: Rebase + fix test Created 8 years, 2 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
« no previous file with comments | « cc/tiled_layer.h ('k') | cc/tiled_layer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « cc/tiled_layer.h ('k') | cc/tiled_layer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698