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

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: Add constants. 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"
11 #include "Region.h" 11 #include "Region.h"
12 #include "base/basictypes.h" 12 #include "base/basictypes.h"
13 #include "cc/overdraw_metrics.h" 13 #include "cc/overdraw_metrics.h"
14 #include "cc/tiled_layer_impl.h" 14 #include "cc/tiled_layer_impl.h"
15 #include "third_party/khronos/GLES2/gl2.h" 15 #include "third_party/khronos/GLES2/gl2.h"
16 16
17 using namespace std; 17 using namespace std;
18 using WebKit::WebTransformationMatrix; 18 using WebKit::WebTransformationMatrix;
19 19
20 namespace cc { 20 namespace cc {
21 21
22 // Maximum predictive expansion of the visible area.
23 static const int maxPredictiveTilesCount = 2;
24
25 // Number of rows/columns of tiles to pre-paint.
26 // We should increase these further as all textures are
27 // prioritized and we insure performance doesn't suffer.
28 static const int prepaintRows = 4;
29 static const int prepaintColumns = 2;
30
31
22 class UpdatableTile : public LayerTilingData::Tile { 32 class UpdatableTile : public LayerTilingData::Tile {
23 public: 33 public:
24 static scoped_ptr<UpdatableTile> create(scoped_ptr<LayerTextureUpdater::Text ure> texture) 34 static scoped_ptr<UpdatableTile> create(scoped_ptr<LayerTextureUpdater::Text ure> texture)
25 { 35 {
26 return make_scoped_ptr(new UpdatableTile(texture.Pass())); 36 return make_scoped_ptr(new UpdatableTile(texture.Pass()));
27 } 37 }
28 38
29 LayerTextureUpdater::Texture* texture() { return m_texture.get(); } 39 LayerTextureUpdater::Texture* texture() { return m_texture.get(); }
30 PrioritizedTexture* managedTexture() { return m_texture->texture(); } 40 PrioritizedTexture* managedTexture() { return m_texture->texture(); }
31 41
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 priority = PriorityCalculator::maxPriority(priority, PriorityCalculator: :smallAnimatedLayerMinPriority()); 569 priority = PriorityCalculator::maxPriority(priority, PriorityCalculator: :smallAnimatedLayerMinPriority());
560 if (priority != PriorityCalculator::lowestPriority()) 570 if (priority != PriorityCalculator::lowestPriority())
561 texture->setRequestPriority(priority); 571 texture->setRequestPriority(priority);
562 } 572 }
563 } 573 }
564 574
565 void TiledLayer::setTexturePriorities(const PriorityCalculator& priorityCalc) 575 void TiledLayer::setTexturePriorities(const PriorityCalculator& priorityCalc)
566 { 576 {
567 updateBounds(); 577 updateBounds();
568 resetUpdateState(); 578 resetUpdateState();
579 updateScrollPrediction();
569 580
570 if (m_tiler->hasEmptyBounds()) 581 if (m_tiler->hasEmptyBounds())
571 return; 582 return;
572 583
573 bool drawsToRoot = !renderTarget()->parent(); 584 bool drawsToRoot = !renderTarget()->parent();
574 bool smallAnimatedLayer = isSmallAnimatedLayer(this); 585 bool smallAnimatedLayer = isSmallAnimatedLayer(this);
575 586
576 // Minimally create the tiles in the desired pre-paint rect. 587 // Minimally create the tiles in the desired pre-paint rect.
577 IntRect createTilesRect = idlePaintRect(); 588 IntRect createTilesRect = idlePaintRect();
578 if (!createTilesRect.isEmpty()) { 589 if (!createTilesRect.isEmpty()) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 } 639 }
629 } 640 }
630 641
631 // Now update priorities on all tiles we have in the layer, no matter where they are. 642 // Now update priorities on all tiles we have in the layer, no matter where they are.
632 for (LayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin( ); iter != m_tiler->tiles().end(); ++iter) { 643 for (LayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin( ); iter != m_tiler->tiles().end(); ++iter) {
633 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); 644 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
634 // FIXME: This should not ever be null. 645 // FIXME: This should not ever be null.
635 if (!tile) 646 if (!tile)
636 continue; 647 continue;
637 IntRect tileRect = m_tiler->tileRect(tile); 648 IntRect tileRect = m_tiler->tileRect(tile);
638 setPriorityForTexture(visibleContentRect(), tileRect, drawsToRoot, small AnimatedLayer, tile->managedTexture()); 649 setPriorityForTexture(m_predictedVisibleRect, tileRect, drawsToRoot, sma llAnimatedLayer, tile->managedTexture());
639 } 650 }
640 } 651 }
641 652
642 Region TiledLayer::visibleContentOpaqueRegion() const 653 Region TiledLayer::visibleContentOpaqueRegion() const
643 { 654 {
644 if (m_skipsDraw) 655 if (m_skipsDraw)
645 return Region(); 656 return Region();
646 if (contentsOpaque()) 657 if (contentsOpaque())
647 return visibleContentRect(); 658 return visibleContentRect();
648 return m_tiler->opaqueRegionInContentRect(visibleContentRect()); 659 return m_tiler->opaqueRegionInContentRect(visibleContentRect());
649 } 660 }
650 661
651 void TiledLayer::resetUpdateState() 662 void TiledLayer::resetUpdateState()
652 { 663 {
653 m_skipsDraw = false; 664 m_skipsDraw = false;
654 m_failedUpdate = false; 665 m_failedUpdate = false;
655 666
656 LayerTilingData::TileMap::const_iterator end = m_tiler->tiles().end(); 667 LayerTilingData::TileMap::const_iterator end = m_tiler->tiles().end();
657 for (LayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin( ); iter != end; ++iter) { 668 for (LayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin( ); iter != end; ++iter) {
658 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); 669 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
659 // FIXME: This should not ever be null. 670 // FIXME: This should not ever be null.
660 if (!tile) 671 if (!tile)
661 continue; 672 continue;
662 tile->resetUpdateState(); 673 tile->resetUpdateState();
663 } 674 }
664 } 675 }
665 676
677 namespace {
678 IntRect expandRectByDelta(IntRect rect, IntSize delta) {
679 int width = rect.width() + abs(delta.width());
680 int height = rect.height() + abs(delta.height());
681 int x = rect.x() + ((delta.width() < 0) ? delta.width() : 0);
682 int y = rect.y() + ((delta.height() < 0) ? delta.height() : 0);
683 return IntRect(x, y, width, height);
684 }
685 }
686
687 void TiledLayer::updateScrollPrediction()
688 {
689 // This scroll prediction is very primitive and should be replaced by a
690 // a recursive calculation on all layers which uses actual scroll/animation
691 // velocities. To insure this doesn't miss-predict, we only use it to predic t
692 // the visibleRect if:
693 // - contentBounds() hasn't changed.
694 // - visibleRect.size() hasn't changed.
695 // These two conditions prevent rotations, scales, pinch-zooms etc. where
696 // the prediction would be incorrect.
697 IntSize delta = visibleContentRect().center() - m_previousVisibleRect.center ();
698 m_predictedScroll = -delta;
699 m_predictedVisibleRect = visibleContentRect();
700 if (m_previousContentBounds == contentBounds() && m_previousVisibleRect.size () == visibleContentRect().size()) {
701 // Only expand the visible rect in the major scroll direction, to preven t
702 // massive paints due to diagonal scrolls.
703 IntSize majorScrollDelta = (abs(delta.width()) > abs(delta.height())) ? IntSize(delta.width(), 0) : IntSize(0, delta.height());
704 m_predictedVisibleRect = expandRectByDelta(visibleContentRect(), majorSc rollDelta);
705
706 // Bound the prediction to prevent unbounded paints, and clamp to conten t bounds.
707 IntRect bound = visibleContentRect();
708 bound.inflateX(m_tiler->tileSize().width() * maxPredictiveTilesCount);
709 bound.inflateY(m_tiler->tileSize().height() * maxPredictiveTilesCount);
710 bound.intersect(IntRect(IntPoint::zero(), contentBounds()));
711 m_predictedVisibleRect.intersect(bound);
712 }
713 m_previousContentBounds = contentBounds();
714 m_previousVisibleRect = visibleContentRect();
715 }
716
666 void TiledLayer::update(TextureUpdateQueue& queue, const OcclusionTracker* occlu sion, RenderingStats& stats) 717 void TiledLayer::update(TextureUpdateQueue& queue, const OcclusionTracker* occlu sion, RenderingStats& stats)
667 { 718 {
668 DCHECK(!m_skipsDraw && !m_failedUpdate); // Did resetUpdateState get skipped ? 719 DCHECK(!m_skipsDraw && !m_failedUpdate); // Did resetUpdateState get skipped ?
669 updateBounds(); 720 updateBounds();
670 if (m_tiler->hasEmptyBounds() || !drawsContent()) 721 if (m_tiler->hasEmptyBounds() || !drawsContent())
671 return; 722 return;
672 723
673 bool didPaint = false; 724 bool didPaint = false;
674 725
675 // Animation pre-paint. If the layer is small, try to paint it all 726 // Animation pre-paint. If the layer is small, try to paint it all
676 // immediately whether or not it is occluded, to avoid paint/upload 727 // immediately whether or not it is occluded, to avoid paint/upload
677 // hiccups while it is animating. 728 // hiccups while it is animating.
678 if (isSmallAnimatedLayer(this)) { 729 if (isSmallAnimatedLayer(this)) {
679 int left, top, right, bottom; 730 int left, top, right, bottom;
680 m_tiler->contentRectToTileIndices(IntRect(IntPoint::zero(), contentBound s()), left, top, right, bottom); 731 m_tiler->contentRectToTileIndices(IntRect(IntPoint::zero(), contentBound s()), left, top, right, bottom);
681 updateTiles(left, top, right, bottom, queue, 0, stats, didPaint); 732 updateTiles(left, top, right, bottom, queue, 0, stats, didPaint);
682 if (didPaint) 733 if (didPaint)
683 return; 734 return;
684 // This was an attempt to paint the entire layer so if we fail it's okay , 735 // This was an attempt to paint the entire layer so if we fail it's okay ,
685 // just fallback on painting visible etc. below. 736 // just fallback on painting visible etc. below.
686 m_failedUpdate = false; 737 m_failedUpdate = false;
687 } 738 }
688 739
689 if (visibleContentRect().isEmpty()) 740 if (m_predictedVisibleRect.isEmpty())
690 return; 741 return;
691 742
692 // Visible painting. First occlude visible tiles and paint the non-occluded tiles. 743 // Visible painting. First occlude visible tiles and paint the non-occluded tiles.
693 int left, top, right, bottom; 744 int left, top, right, bottom;
694 m_tiler->contentRectToTileIndices(visibleContentRect(), left, top, right, bo ttom); 745 m_tiler->contentRectToTileIndices(m_predictedVisibleRect, left, top, right, bottom);
695 markOcclusionsAndRequestTextures(left, top, right, bottom, occlusion); 746 markOcclusionsAndRequestTextures(left, top, right, bottom, occlusion);
696 m_skipsDraw = !updateTiles(left, top, right, bottom, queue, occlusion, stats , didPaint); 747 m_skipsDraw = !updateTiles(left, top, right, bottom, queue, occlusion, stats , didPaint);
697 if (m_skipsDraw) 748 if (m_skipsDraw)
698 m_tiler->reset(); 749 m_tiler->reset();
699 if (m_skipsDraw || didPaint) 750 if (m_skipsDraw || didPaint)
700 return; 751 return;
701 752
702 // If we have already painting everything visible. Do some pre-painting whil e idle. 753 // If we have already painting everything visible. Do some pre-painting whil e idle.
703 IntRect idlePaintContentRect = idlePaintRect(); 754 IntRect idlePaintContentRect = idlePaintRect();
704 if (idlePaintContentRect.isEmpty()) 755 if (idlePaintContentRect.isEmpty())
705 return; 756 return;
706 757
707 // Prepaint anything that was occluded but inside the layer's visible region . 758 // Prepaint anything that was occluded but inside the layer's visible region .
708 if (!updateTiles(left, top, right, bottom, queue, 0, stats, didPaint) || did Paint) 759 if (!updateTiles(left, top, right, bottom, queue, 0, stats, didPaint) || did Paint)
709 return; 760 return;
710 761
711 int prepaintLeft, prepaintTop, prepaintRight, prepaintBottom; 762 int prepaintLeft, prepaintTop, prepaintRight, prepaintBottom;
712 m_tiler->contentRectToTileIndices(idlePaintContentRect, prepaintLeft, prepai ntTop, prepaintRight, prepaintBottom); 763 m_tiler->contentRectToTileIndices(idlePaintContentRect, prepaintLeft, prepai ntTop, prepaintRight, prepaintBottom);
713 764
714 // Then expand outwards from the visible area until we find a dirty row or c olumn to update. 765 // Then expand outwards one row/column at a time until we find a dirty row/c olumn
715 while (left > prepaintLeft || top > prepaintTop || right < prepaintRight || bottom < prepaintBottom) { 766 // to update. Increment along the major and minor scroll directions first.
716 if (bottom < prepaintBottom) { 767 IntSize delta = -m_predictedScroll;
717 ++bottom; 768 delta = IntSize(delta.width() == 0 ? 1 : delta.width(),
718 if (!updateTiles(left, bottom, right, bottom, queue, 0, stats, didPa int) || didPaint) 769 delta.height() == 0 ? 1 : delta.height());
719 return; 770 IntSize majorDelta = (abs(delta.width()) > abs(delta.height())) ? IntSize(d elta.width(), 0) : IntSize(0, delta.height());
771 IntSize minorDelta = (abs(delta.width()) <= abs(delta.height())) ? IntSize(d elta.width(), 0) : IntSize(0, delta.height());
772 IntSize deltas[4] = {majorDelta, minorDelta, -majorDelta, -minorDelta};
773 for(int i = 0; i < 4; i++) {
774 if (deltas[i].height() > 0) {
775 while (bottom < prepaintBottom) {
776 ++bottom;
777 if (!updateTiles(left, bottom, right, bottom, queue, 0, stats, d idPaint) || didPaint)
778 return;
779 }
720 } 780 }
721 if (top > prepaintTop) { 781 if (deltas[i].height() < 0) {
722 --top; 782 while (top > prepaintTop) {
723 if (!updateTiles(left, top, right, top, queue, 0, stats, didPaint) | | didPaint) 783 --top;
724 return; 784 if (!updateTiles(left, top, right, top, queue, 0, stats, didPain t) || didPaint)
785 return;
786 }
725 } 787 }
726 if (left > prepaintLeft) { 788 if (deltas[i].width() < 0) {
727 --left; 789 while (left > prepaintLeft) {
728 if (!updateTiles(left, top, left, bottom, queue, 0, stats, didPaint) || didPaint) 790 --left;
729 return; 791 if (!updateTiles(left, top, left, bottom, queue, 0, stats, didPa int) || didPaint)
792 return;
793 }
730 } 794 }
731 if (right < prepaintRight) { 795 if (deltas[i].width() > 0) {
732 ++right; 796 while (right < prepaintRight) {
733 if (!updateTiles(right, top, right, bottom, queue, 0, stats, didPain t) || didPaint) 797 ++right;
734 return; 798 if (!updateTiles(right, top, right, bottom, queue, 0, stats, did Paint) || didPaint)
799 return;
800 }
735 } 801 }
736 } 802 }
737 } 803 }
738 804
739 bool TiledLayer::needsIdlePaint() 805 bool TiledLayer::needsIdlePaint()
740 { 806 {
741 // Don't trigger more paints if we failed (as we'll just fail again). 807 // Don't trigger more paints if we failed (as we'll just fail again).
742 if (m_failedUpdate || visibleContentRect().isEmpty() || m_tiler->hasEmptyBou nds() || !drawsContent()) 808 if (m_failedUpdate || visibleContentRect().isEmpty() || m_tiler->hasEmptyBou nds() || !drawsContent())
743 return false; 809 return false;
744 810
(...skipping 20 matching lines...) Expand all
765 } 831 }
766 return false; 832 return false;
767 } 833 }
768 834
769 IntRect TiledLayer::idlePaintRect() 835 IntRect TiledLayer::idlePaintRect()
770 { 836 {
771 // Don't inflate an empty rect. 837 // Don't inflate an empty rect.
772 if (visibleContentRect().isEmpty()) 838 if (visibleContentRect().isEmpty())
773 return IntRect(); 839 return IntRect();
774 840
775 // FIXME: This can be made a lot larger now! We should increase
776 // this slowly while insuring it doesn't cause any perf issues.
777 IntRect prepaintRect = visibleContentRect(); 841 IntRect prepaintRect = visibleContentRect();
778 prepaintRect.inflateX(m_tiler->tileSize().width()); 842 prepaintRect.inflateX(m_tiler->tileSize().width() * prepaintColumns);
779 prepaintRect.inflateY(m_tiler->tileSize().height() * 2); 843 prepaintRect.inflateY(m_tiler->tileSize().height() * prepaintRows);
780 IntRect contentRect(IntPoint::zero(), contentBounds()); 844 IntRect contentRect(IntPoint::zero(), contentBounds());
781 prepaintRect.intersect(contentRect); 845 prepaintRect.intersect(contentRect);
782 846
783 return prepaintRect; 847 return prepaintRect;
784 } 848 }
785 849
786 } 850 }
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