| 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 "cc/layers/tiled_layer.h" | 5 #include "cc/layers/tiled_layer.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 return !tile->dirty_rect.Contains(tiler_->TileRect(tile)) && | 320 return !tile->dirty_rect.Contains(tiler_->TileRect(tile)) && |
| 321 tile->managed_resource()->have_backing_texture(); | 321 tile->managed_resource()->have_backing_texture(); |
| 322 } | 322 } |
| 323 | 323 |
| 324 bool TiledLayer::UpdateTiles(int left, | 324 bool TiledLayer::UpdateTiles(int left, |
| 325 int top, | 325 int top, |
| 326 int right, | 326 int right, |
| 327 int bottom, | 327 int bottom, |
| 328 ResourceUpdateQueue* queue, | 328 ResourceUpdateQueue* queue, |
| 329 const OcclusionTracker* occlusion, | 329 const OcclusionTracker* occlusion, |
| 330 bool* did_paint) { | 330 bool* updated) { |
| 331 CreateUpdaterIfNeeded(); | 331 CreateUpdaterIfNeeded(); |
| 332 | 332 |
| 333 bool ignore_occlusions = !occlusion; | 333 bool ignore_occlusions = !occlusion; |
| 334 if (!HaveTexturesForTiles(left, top, right, bottom, ignore_occlusions)) { | 334 if (!HaveTexturesForTiles(left, top, right, bottom, ignore_occlusions)) { |
| 335 failed_update_ = true; | 335 failed_update_ = true; |
| 336 return false; | 336 return false; |
| 337 } | 337 } |
| 338 | 338 |
| 339 gfx::Rect paint_rect = | 339 gfx::Rect paint_rect = |
| 340 MarkTilesForUpdate(left, top, right, bottom, ignore_occlusions); | 340 MarkTilesForUpdate(left, top, right, bottom, ignore_occlusions); |
| 341 | 341 |
| 342 if (occlusion) | 342 if (occlusion) |
| 343 occlusion->overdraw_metrics()->DidPaint(paint_rect); | 343 occlusion->overdraw_metrics()->DidPaint(paint_rect); |
| 344 | 344 |
| 345 if (paint_rect.IsEmpty()) | 345 if (paint_rect.IsEmpty()) |
| 346 return true; | 346 return true; |
| 347 | 347 |
| 348 *did_paint = true; | 348 *updated = true; |
| 349 UpdateTileTextures( | 349 UpdateTileTextures( |
| 350 paint_rect, left, top, right, bottom, queue, occlusion); | 350 paint_rect, left, top, right, bottom, queue, occlusion); |
| 351 return true; | 351 return true; |
| 352 } | 352 } |
| 353 | 353 |
| 354 void TiledLayer::MarkOcclusionsAndRequestTextures( | 354 void TiledLayer::MarkOcclusionsAndRequestTextures( |
| 355 int left, | 355 int left, |
| 356 int top, | 356 int top, |
| 357 int right, | 357 int right, |
| 358 int bottom, | 358 int bottom, |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 723 bound.Intersect(gfx::Rect(content_bounds())); | 723 bound.Intersect(gfx::Rect(content_bounds())); |
| 724 predicted_visible_rect_.Intersect(bound); | 724 predicted_visible_rect_.Intersect(bound); |
| 725 } | 725 } |
| 726 previous_content_bounds_ = content_bounds(); | 726 previous_content_bounds_ = content_bounds(); |
| 727 previous_visible_rect_ = visible_content_rect(); | 727 previous_visible_rect_ = visible_content_rect(); |
| 728 } | 728 } |
| 729 | 729 |
| 730 bool TiledLayer::Update(ResourceUpdateQueue* queue, | 730 bool TiledLayer::Update(ResourceUpdateQueue* queue, |
| 731 const OcclusionTracker* occlusion) { | 731 const OcclusionTracker* occlusion) { |
| 732 DCHECK(!skips_draw_ && !failed_update_); // Did ResetUpdateState get skipped? | 732 DCHECK(!skips_draw_ && !failed_update_); // Did ResetUpdateState get skipped? |
| 733 |
| 734 bool updated = false; |
| 735 |
| 733 { | 736 { |
| 734 base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_, | 737 base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_, |
| 735 true); | 738 true); |
| 736 | 739 |
| 737 ContentsScalingLayer::Update(queue, occlusion); | 740 updated |= ContentsScalingLayer::Update(queue, occlusion); |
| 738 UpdateBounds(); | 741 UpdateBounds(); |
| 739 } | 742 } |
| 740 | 743 |
| 741 if (tiler_->has_empty_bounds() || !DrawsContent()) | 744 if (tiler_->has_empty_bounds() || !DrawsContent()) |
| 742 return false; | 745 return false; |
| 743 | 746 |
| 744 bool did_paint = false; | |
| 745 | |
| 746 // Animation pre-paint. If the layer is small, try to paint it all | 747 // Animation pre-paint. If the layer is small, try to paint it all |
| 747 // immediately whether or not it is occluded, to avoid paint/upload | 748 // immediately whether or not it is occluded, to avoid paint/upload |
| 748 // hiccups while it is animating. | 749 // hiccups while it is animating. |
| 749 if (IsSmallAnimatedLayer()) { | 750 if (IsSmallAnimatedLayer()) { |
| 750 int left, top, right, bottom; | 751 int left, top, right, bottom; |
| 751 tiler_->ContentRectToTileIndices(gfx::Rect(content_bounds()), | 752 tiler_->ContentRectToTileIndices(gfx::Rect(content_bounds()), |
| 752 &left, | 753 &left, |
| 753 &top, | 754 &top, |
| 754 &right, | 755 &right, |
| 755 &bottom); | 756 &bottom); |
| 756 UpdateTiles(left, top, right, bottom, queue, NULL, &did_paint); | 757 UpdateTiles(left, top, right, bottom, queue, NULL, &updated); |
| 757 if (did_paint) | 758 if (updated) |
| 758 return did_paint; | 759 return updated; |
| 759 // This was an attempt to paint the entire layer so if we fail it's okay, | 760 // This was an attempt to paint the entire layer so if we fail it's okay, |
| 760 // just fallback on painting visible etc. below. | 761 // just fallback on painting visible etc. below. |
| 761 failed_update_ = false; | 762 failed_update_ = false; |
| 762 } | 763 } |
| 763 | 764 |
| 764 if (predicted_visible_rect_.IsEmpty()) | 765 if (predicted_visible_rect_.IsEmpty()) |
| 765 return did_paint; | 766 return updated; |
| 766 | 767 |
| 767 // Visible painting. First occlude visible tiles and paint the non-occluded | 768 // Visible painting. First occlude visible tiles and paint the non-occluded |
| 768 // tiles. | 769 // tiles. |
| 769 int left, top, right, bottom; | 770 int left, top, right, bottom; |
| 770 tiler_->ContentRectToTileIndices( | 771 tiler_->ContentRectToTileIndices( |
| 771 predicted_visible_rect_, &left, &top, &right, &bottom); | 772 predicted_visible_rect_, &left, &top, &right, &bottom); |
| 772 MarkOcclusionsAndRequestTextures(left, top, right, bottom, occlusion); | 773 MarkOcclusionsAndRequestTextures(left, top, right, bottom, occlusion); |
| 773 skips_draw_ = !UpdateTiles( | 774 skips_draw_ = !UpdateTiles( |
| 774 left, top, right, bottom, queue, occlusion, &did_paint); | 775 left, top, right, bottom, queue, occlusion, &updated); |
| 775 if (skips_draw_) | 776 if (skips_draw_) |
| 776 tiler_->reset(); | 777 tiler_->reset(); |
| 777 if (skips_draw_ || did_paint) | 778 if (skips_draw_ || updated) |
| 778 return true; | 779 return true; |
| 779 | 780 |
| 780 // If we have already painting everything visible. Do some pre-painting while | 781 // If we have already painting everything visible. Do some pre-painting while |
| 781 // idle. | 782 // idle. |
| 782 gfx::Rect idle_paint_content_rect = IdlePaintRect(); | 783 gfx::Rect idle_paint_content_rect = IdlePaintRect(); |
| 783 if (idle_paint_content_rect.IsEmpty()) | 784 if (idle_paint_content_rect.IsEmpty()) |
| 784 return did_paint; | 785 return updated; |
| 785 | 786 |
| 786 // Prepaint anything that was occluded but inside the layer's visible region. | 787 // Prepaint anything that was occluded but inside the layer's visible region. |
| 787 if (!UpdateTiles(left, top, right, bottom, queue, NULL, &did_paint) || | 788 if (!UpdateTiles(left, top, right, bottom, queue, NULL, &updated) || |
| 788 did_paint) | 789 updated) |
| 789 return did_paint; | 790 return updated; |
| 790 | 791 |
| 791 int prepaint_left, prepaint_top, prepaint_right, prepaint_bottom; | 792 int prepaint_left, prepaint_top, prepaint_right, prepaint_bottom; |
| 792 tiler_->ContentRectToTileIndices(idle_paint_content_rect, | 793 tiler_->ContentRectToTileIndices(idle_paint_content_rect, |
| 793 &prepaint_left, | 794 &prepaint_left, |
| 794 &prepaint_top, | 795 &prepaint_top, |
| 795 &prepaint_right, | 796 &prepaint_right, |
| 796 &prepaint_bottom); | 797 &prepaint_bottom); |
| 797 | 798 |
| 798 // Then expand outwards one row/column at a time until we find a dirty | 799 // Then expand outwards one row/column at a time until we find a dirty |
| 799 // row/column to update. Increment along the major and minor scroll directions | 800 // row/column to update. Increment along the major and minor scroll directions |
| 800 // first. | 801 // first. |
| 801 gfx::Vector2d delta = -predicted_scroll_; | 802 gfx::Vector2d delta = -predicted_scroll_; |
| 802 delta = gfx::Vector2d(delta.x() == 0 ? 1 : delta.x(), | 803 delta = gfx::Vector2d(delta.x() == 0 ? 1 : delta.x(), |
| 803 delta.y() == 0 ? 1 : delta.y()); | 804 delta.y() == 0 ? 1 : delta.y()); |
| 804 gfx::Vector2d major_delta = | 805 gfx::Vector2d major_delta = |
| 805 (std::abs(delta.x()) > std::abs(delta.y())) ? gfx::Vector2d(delta.x(), 0) | 806 (std::abs(delta.x()) > std::abs(delta.y())) ? gfx::Vector2d(delta.x(), 0) |
| 806 : gfx::Vector2d(0, delta.y()); | 807 : gfx::Vector2d(0, delta.y()); |
| 807 gfx::Vector2d minor_delta = | 808 gfx::Vector2d minor_delta = |
| 808 (std::abs(delta.x()) <= std::abs(delta.y())) ? gfx::Vector2d(delta.x(), 0) | 809 (std::abs(delta.x()) <= std::abs(delta.y())) ? gfx::Vector2d(delta.x(), 0) |
| 809 : gfx::Vector2d(0, delta.y()); | 810 : gfx::Vector2d(0, delta.y()); |
| 810 gfx::Vector2d deltas[4] = { major_delta, minor_delta, -major_delta, | 811 gfx::Vector2d deltas[4] = { major_delta, minor_delta, -major_delta, |
| 811 -minor_delta }; | 812 -minor_delta }; |
| 812 for (int i = 0; i < 4; i++) { | 813 for (int i = 0; i < 4; i++) { |
| 813 if (deltas[i].y() > 0) { | 814 if (deltas[i].y() > 0) { |
| 814 while (bottom < prepaint_bottom) { | 815 while (bottom < prepaint_bottom) { |
| 815 ++bottom; | 816 ++bottom; |
| 816 if (!UpdateTiles( | 817 if (!UpdateTiles( |
| 817 left, bottom, right, bottom, queue, NULL, &did_paint) || | 818 left, bottom, right, bottom, queue, NULL, &updated) || |
| 818 did_paint) | 819 updated) |
| 819 return did_paint; | 820 return updated; |
| 820 } | 821 } |
| 821 } | 822 } |
| 822 if (deltas[i].y() < 0) { | 823 if (deltas[i].y() < 0) { |
| 823 while (top > prepaint_top) { | 824 while (top > prepaint_top) { |
| 824 --top; | 825 --top; |
| 825 if (!UpdateTiles( | 826 if (!UpdateTiles( |
| 826 left, top, right, top, queue, NULL, &did_paint) || | 827 left, top, right, top, queue, NULL, &updated) || |
| 827 did_paint) | 828 updated) |
| 828 return did_paint; | 829 return updated; |
| 829 } | 830 } |
| 830 } | 831 } |
| 831 if (deltas[i].x() < 0) { | 832 if (deltas[i].x() < 0) { |
| 832 while (left > prepaint_left) { | 833 while (left > prepaint_left) { |
| 833 --left; | 834 --left; |
| 834 if (!UpdateTiles( | 835 if (!UpdateTiles( |
| 835 left, top, left, bottom, queue, NULL, &did_paint) || | 836 left, top, left, bottom, queue, NULL, &updated) || |
| 836 did_paint) | 837 updated) |
| 837 return did_paint; | 838 return updated; |
| 838 } | 839 } |
| 839 } | 840 } |
| 840 if (deltas[i].x() > 0) { | 841 if (deltas[i].x() > 0) { |
| 841 while (right < prepaint_right) { | 842 while (right < prepaint_right) { |
| 842 ++right; | 843 ++right; |
| 843 if (!UpdateTiles( | 844 if (!UpdateTiles( |
| 844 right, top, right, bottom, queue, NULL, &did_paint) || | 845 right, top, right, bottom, queue, NULL, &updated) || |
| 845 did_paint) | 846 updated) |
| 846 return did_paint; | 847 return updated; |
| 847 } | 848 } |
| 848 } | 849 } |
| 849 } | 850 } |
| 850 return did_paint; | 851 return updated; |
| 851 } | 852 } |
| 852 | 853 |
| 853 bool TiledLayer::NeedsIdlePaint() { | 854 bool TiledLayer::NeedsIdlePaint() { |
| 854 // Don't trigger more paints if we failed (as we'll just fail again). | 855 // Don't trigger more paints if we failed (as we'll just fail again). |
| 855 if (failed_update_ || visible_content_rect().IsEmpty() || | 856 if (failed_update_ || visible_content_rect().IsEmpty() || |
| 856 tiler_->has_empty_bounds() || !DrawsContent()) | 857 tiler_->has_empty_bounds() || !DrawsContent()) |
| 857 return false; | 858 return false; |
| 858 | 859 |
| 859 gfx::Rect idle_paint_content_rect = IdlePaintRect(); | 860 gfx::Rect idle_paint_content_rect = IdlePaintRect(); |
| 860 if (idle_paint_content_rect.IsEmpty()) | 861 if (idle_paint_content_rect.IsEmpty()) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 891 gfx::Rect prepaint_rect = visible_content_rect(); | 892 gfx::Rect prepaint_rect = visible_content_rect(); |
| 892 prepaint_rect.Inset(-tiler_->tile_size().width() * kPrepaintColumns, | 893 prepaint_rect.Inset(-tiler_->tile_size().width() * kPrepaintColumns, |
| 893 -tiler_->tile_size().height() * kPrepaintRows); | 894 -tiler_->tile_size().height() * kPrepaintRows); |
| 894 gfx::Rect content_rect(content_bounds()); | 895 gfx::Rect content_rect(content_bounds()); |
| 895 prepaint_rect.Intersect(content_rect); | 896 prepaint_rect.Intersect(content_rect); |
| 896 | 897 |
| 897 return prepaint_rect; | 898 return prepaint_rect; |
| 898 } | 899 } |
| 899 | 900 |
| 900 } // namespace cc | 901 } // namespace cc |
| OLD | NEW |