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 |