Chromium Code Reviews| 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 |