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 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 return !tile->dirty_rect.Contains(tiler_->TileRect(tile)) && | 310 return !tile->dirty_rect.Contains(tiler_->TileRect(tile)) && |
311 tile->managed_resource()->have_backing_texture(); | 311 tile->managed_resource()->have_backing_texture(); |
312 } | 312 } |
313 | 313 |
314 bool TiledLayer::UpdateTiles(int left, | 314 bool TiledLayer::UpdateTiles(int left, |
315 int top, | 315 int top, |
316 int right, | 316 int right, |
317 int bottom, | 317 int bottom, |
318 ResourceUpdateQueue* queue, | 318 ResourceUpdateQueue* queue, |
319 const OcclusionTracker* occlusion, | 319 const OcclusionTracker* occlusion, |
320 RenderingStats* stats, | |
321 bool* did_paint) { | 320 bool* did_paint) { |
322 *did_paint = false; | 321 *did_paint = false; |
323 CreateUpdaterIfNeeded(); | 322 CreateUpdaterIfNeeded(); |
324 | 323 |
325 bool ignore_occlusions = !occlusion; | 324 bool ignore_occlusions = !occlusion; |
326 if (!HaveTexturesForTiles(left, top, right, bottom, ignore_occlusions)) { | 325 if (!HaveTexturesForTiles(left, top, right, bottom, ignore_occlusions)) { |
327 failed_update_ = true; | 326 failed_update_ = true; |
328 return false; | 327 return false; |
329 } | 328 } |
330 | 329 |
331 gfx::Rect paint_rect = | 330 gfx::Rect paint_rect = |
332 MarkTilesForUpdate(left, top, right, bottom, ignore_occlusions); | 331 MarkTilesForUpdate(left, top, right, bottom, ignore_occlusions); |
333 | 332 |
334 if (occlusion) | 333 if (occlusion) |
335 occlusion->overdraw_metrics()->DidPaint(paint_rect); | 334 occlusion->overdraw_metrics()->DidPaint(paint_rect); |
336 | 335 |
337 if (paint_rect.IsEmpty()) | 336 if (paint_rect.IsEmpty()) |
338 return true; | 337 return true; |
339 | 338 |
340 *did_paint = true; | 339 *did_paint = true; |
341 UpdateTileTextures( | 340 UpdateTileTextures( |
342 paint_rect, left, top, right, bottom, queue, occlusion, stats); | 341 paint_rect, left, top, right, bottom, queue, occlusion); |
343 return true; | 342 return true; |
344 } | 343 } |
345 | 344 |
346 void TiledLayer::MarkOcclusionsAndRequestTextures( | 345 void TiledLayer::MarkOcclusionsAndRequestTextures( |
347 int left, | 346 int left, |
348 int top, | 347 int top, |
349 int right, | 348 int right, |
350 int bottom, | 349 int bottom, |
351 const OcclusionTracker* occlusion) { | 350 const OcclusionTracker* occlusion) { |
352 // There is some difficult dependancies between occlusions, recording | 351 // There is some difficult dependancies between occlusions, recording |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 } | 457 } |
459 return paint_rect; | 458 return paint_rect; |
460 } | 459 } |
461 | 460 |
462 void TiledLayer::UpdateTileTextures(gfx::Rect paint_rect, | 461 void TiledLayer::UpdateTileTextures(gfx::Rect paint_rect, |
463 int left, | 462 int left, |
464 int top, | 463 int top, |
465 int right, | 464 int right, |
466 int bottom, | 465 int bottom, |
467 ResourceUpdateQueue* queue, | 466 ResourceUpdateQueue* queue, |
468 const OcclusionTracker* occlusion, | 467 const OcclusionTracker* occlusion) { |
469 RenderingStats* stats) { | |
470 // The update_rect should be in layer space. So we have to convert the | 468 // The update_rect should be in layer space. So we have to convert the |
471 // paint_rect from content space to layer space. | 469 // paint_rect from content space to layer space. |
472 float width_scale = | 470 float width_scale = |
473 bounds().width() / static_cast<float>(content_bounds().width()); | 471 bounds().width() / static_cast<float>(content_bounds().width()); |
474 float height_scale = | 472 float height_scale = |
475 bounds().height() / static_cast<float>(content_bounds().height()); | 473 bounds().height() / static_cast<float>(content_bounds().height()); |
476 update_rect_ = gfx::ScaleRect(paint_rect, width_scale, height_scale); | 474 update_rect_ = gfx::ScaleRect(paint_rect, width_scale, height_scale); |
477 | 475 |
478 // Calling PrepareToUpdate() calls into WebKit to paint, which may have the | 476 // Calling PrepareToUpdate() calls into WebKit to paint, which may have the |
479 // side effect of disabling compositing, which causes our reference to the | 477 // side effect of disabling compositing, which causes our reference to the |
480 // texture updater to be deleted. However, we can't free the memory backing | 478 // texture updater to be deleted. However, we can't free the memory backing |
481 // the SkCanvas until the paint finishes, so we grab a local reference here to | 479 // the SkCanvas until the paint finishes, so we grab a local reference here to |
482 // hold the updater alive until the paint completes. | 480 // hold the updater alive until the paint completes. |
483 scoped_refptr<LayerUpdater> protector(Updater()); | 481 scoped_refptr<LayerUpdater> protector(Updater()); |
484 gfx::Rect painted_opaque_rect; | 482 gfx::Rect painted_opaque_rect; |
485 Updater()->PrepareToUpdate(paint_rect, | 483 Updater()->PrepareToUpdate(paint_rect, |
486 tiler_->tile_size(), | 484 tiler_->tile_size(), |
487 1.f / width_scale, | 485 1.f / width_scale, |
488 1.f / height_scale, | 486 1.f / height_scale, |
489 &painted_opaque_rect, | 487 &painted_opaque_rect); |
490 stats); | |
491 | 488 |
492 for (int j = top; j <= bottom; ++j) { | 489 for (int j = top; j <= bottom; ++j) { |
493 for (int i = left; i <= right; ++i) { | 490 for (int i = left; i <= right; ++i) { |
494 UpdatableTile* tile = TileAt(i, j); | 491 UpdatableTile* tile = TileAt(i, j); |
495 DCHECK(tile); // Did SetTexturePriorites get skipped? | 492 DCHECK(tile); // Did SetTexturePriorites get skipped? |
496 // FIXME: This should not ever be null. | 493 // FIXME: This should not ever be null. |
497 if (!tile) | 494 if (!tile) |
498 continue; | 495 continue; |
499 | 496 |
500 gfx::Rect tile_rect = tiler_->tile_bounds(i, j); | 497 gfx::Rect tile_rect = tiler_->tile_bounds(i, j); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 CHECK_GE(dest_offset.y(), 0); | 542 CHECK_GE(dest_offset.y(), 0); |
546 | 543 |
547 // Offset from paint rectangle to this tile's dirty rectangle. | 544 // Offset from paint rectangle to this tile's dirty rectangle. |
548 gfx::Vector2d paint_offset = source_rect.origin() - paint_rect.origin(); | 545 gfx::Vector2d paint_offset = source_rect.origin() - paint_rect.origin(); |
549 CHECK_GE(paint_offset.x(), 0); | 546 CHECK_GE(paint_offset.x(), 0); |
550 CHECK_GE(paint_offset.y(), 0); | 547 CHECK_GE(paint_offset.y(), 0); |
551 CHECK_LE(paint_offset.x() + source_rect.width(), paint_rect.width()); | 548 CHECK_LE(paint_offset.x() + source_rect.width(), paint_rect.width()); |
552 CHECK_LE(paint_offset.y() + source_rect.height(), paint_rect.height()); | 549 CHECK_LE(paint_offset.y() + source_rect.height(), paint_rect.height()); |
553 | 550 |
554 tile->updater_resource()->Update( | 551 tile->updater_resource()->Update( |
555 queue, source_rect, dest_offset, tile->partial_update, stats); | 552 queue, source_rect, dest_offset, tile->partial_update); |
556 if (occlusion) { | 553 if (occlusion) { |
557 occlusion->overdraw_metrics()-> | 554 occlusion->overdraw_metrics()-> |
558 DidUpload(gfx::Transform(), source_rect, tile->opaque_rect()); | 555 DidUpload(gfx::Transform(), source_rect, tile->opaque_rect()); |
559 } | 556 } |
560 } | 557 } |
561 } | 558 } |
562 } | 559 } |
563 | 560 |
564 // This picks a small animated layer to be anything less than one viewport. This | 561 // This picks a small animated layer to be anything less than one viewport. This |
565 // is specifically for page transitions which are viewport-sized layers. The | 562 // is specifically for page transitions which are viewport-sized layers. The |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
712 bound.Inset(-tiler_->tile_size().width() * kMaxPredictiveTilesCount, | 709 bound.Inset(-tiler_->tile_size().width() * kMaxPredictiveTilesCount, |
713 -tiler_->tile_size().height() * kMaxPredictiveTilesCount); | 710 -tiler_->tile_size().height() * kMaxPredictiveTilesCount); |
714 bound.Intersect(gfx::Rect(content_bounds())); | 711 bound.Intersect(gfx::Rect(content_bounds())); |
715 predicted_visible_rect_.Intersect(bound); | 712 predicted_visible_rect_.Intersect(bound); |
716 } | 713 } |
717 previous_content_bounds_ = content_bounds(); | 714 previous_content_bounds_ = content_bounds(); |
718 previous_visible_rect_ = visible_content_rect(); | 715 previous_visible_rect_ = visible_content_rect(); |
719 } | 716 } |
720 | 717 |
721 void TiledLayer::Update(ResourceUpdateQueue* queue, | 718 void TiledLayer::Update(ResourceUpdateQueue* queue, |
722 const OcclusionTracker* occlusion, | 719 const OcclusionTracker* occlusion) { |
723 RenderingStats* stats) { | |
724 DCHECK(!skips_draw_ && !failed_update_); // Did ResetUpdateState get skipped? | 720 DCHECK(!skips_draw_ && !failed_update_); // Did ResetUpdateState get skipped? |
725 { | 721 { |
726 base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_, | 722 base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_, |
727 true); | 723 true); |
728 | 724 |
729 ContentsScalingLayer::Update(queue, occlusion, stats); | 725 ContentsScalingLayer::Update(queue, occlusion); |
730 UpdateBounds(); | 726 UpdateBounds(); |
731 } | 727 } |
732 | 728 |
733 if (tiler_->has_empty_bounds() || !DrawsContent()) | 729 if (tiler_->has_empty_bounds() || !DrawsContent()) |
734 return; | 730 return; |
735 | 731 |
736 bool did_paint = false; | 732 bool did_paint = false; |
737 | 733 |
738 // Animation pre-paint. If the layer is small, try to paint it all | 734 // Animation pre-paint. If the layer is small, try to paint it all |
739 // immediately whether or not it is occluded, to avoid paint/upload | 735 // immediately whether or not it is occluded, to avoid paint/upload |
740 // hiccups while it is animating. | 736 // hiccups while it is animating. |
741 if (IsSmallAnimatedLayer()) { | 737 if (IsSmallAnimatedLayer()) { |
742 int left, top, right, bottom; | 738 int left, top, right, bottom; |
743 tiler_->ContentRectToTileIndices(gfx::Rect(content_bounds()), | 739 tiler_->ContentRectToTileIndices(gfx::Rect(content_bounds()), |
744 &left, | 740 &left, |
745 &top, | 741 &top, |
746 &right, | 742 &right, |
747 &bottom); | 743 &bottom); |
748 UpdateTiles(left, top, right, bottom, queue, NULL, stats, &did_paint); | 744 UpdateTiles(left, top, right, bottom, queue, NULL, &did_paint); |
749 if (did_paint) | 745 if (did_paint) |
750 return; | 746 return; |
751 // This was an attempt to paint the entire layer so if we fail it's okay, | 747 // This was an attempt to paint the entire layer so if we fail it's okay, |
752 // just fallback on painting visible etc. below. | 748 // just fallback on painting visible etc. below. |
753 failed_update_ = false; | 749 failed_update_ = false; |
754 } | 750 } |
755 | 751 |
756 if (predicted_visible_rect_.IsEmpty()) | 752 if (predicted_visible_rect_.IsEmpty()) |
757 return; | 753 return; |
758 | 754 |
759 // Visible painting. First occlude visible tiles and paint the non-occluded | 755 // Visible painting. First occlude visible tiles and paint the non-occluded |
760 // tiles. | 756 // tiles. |
761 int left, top, right, bottom; | 757 int left, top, right, bottom; |
762 tiler_->ContentRectToTileIndices( | 758 tiler_->ContentRectToTileIndices( |
763 predicted_visible_rect_, &left, &top, &right, &bottom); | 759 predicted_visible_rect_, &left, &top, &right, &bottom); |
764 MarkOcclusionsAndRequestTextures(left, top, right, bottom, occlusion); | 760 MarkOcclusionsAndRequestTextures(left, top, right, bottom, occlusion); |
765 skips_draw_ = !UpdateTiles( | 761 skips_draw_ = !UpdateTiles( |
766 left, top, right, bottom, queue, occlusion, stats, &did_paint); | 762 left, top, right, bottom, queue, occlusion, &did_paint); |
767 if (skips_draw_) | 763 if (skips_draw_) |
768 tiler_->reset(); | 764 tiler_->reset(); |
769 if (skips_draw_ || did_paint) | 765 if (skips_draw_ || did_paint) |
770 return; | 766 return; |
771 | 767 |
772 // If we have already painting everything visible. Do some pre-painting while | 768 // If we have already painting everything visible. Do some pre-painting while |
773 // idle. | 769 // idle. |
774 gfx::Rect idle_paint_content_rect = IdlePaintRect(); | 770 gfx::Rect idle_paint_content_rect = IdlePaintRect(); |
775 if (idle_paint_content_rect.IsEmpty()) | 771 if (idle_paint_content_rect.IsEmpty()) |
776 return; | 772 return; |
777 | 773 |
778 // Prepaint anything that was occluded but inside the layer's visible region. | 774 // Prepaint anything that was occluded but inside the layer's visible region. |
779 if (!UpdateTiles(left, top, right, bottom, queue, NULL, stats, &did_paint) || | 775 if (!UpdateTiles(left, top, right, bottom, queue, NULL, &did_paint) || |
780 did_paint) | 776 did_paint) |
781 return; | 777 return; |
782 | 778 |
783 int prepaint_left, prepaint_top, prepaint_right, prepaint_bottom; | 779 int prepaint_left, prepaint_top, prepaint_right, prepaint_bottom; |
784 tiler_->ContentRectToTileIndices(idle_paint_content_rect, | 780 tiler_->ContentRectToTileIndices(idle_paint_content_rect, |
785 &prepaint_left, | 781 &prepaint_left, |
786 &prepaint_top, | 782 &prepaint_top, |
787 &prepaint_right, | 783 &prepaint_right, |
788 &prepaint_bottom); | 784 &prepaint_bottom); |
789 | 785 |
790 // Then expand outwards one row/column at a time until we find a dirty | 786 // Then expand outwards one row/column at a time until we find a dirty |
791 // row/column to update. Increment along the major and minor scroll directions | 787 // row/column to update. Increment along the major and minor scroll directions |
792 // first. | 788 // first. |
793 gfx::Vector2d delta = -predicted_scroll_; | 789 gfx::Vector2d delta = -predicted_scroll_; |
794 delta = gfx::Vector2d(delta.x() == 0 ? 1 : delta.x(), | 790 delta = gfx::Vector2d(delta.x() == 0 ? 1 : delta.x(), |
795 delta.y() == 0 ? 1 : delta.y()); | 791 delta.y() == 0 ? 1 : delta.y()); |
796 gfx::Vector2d major_delta = | 792 gfx::Vector2d major_delta = |
797 (abs(delta.x()) > abs(delta.y())) ? gfx::Vector2d(delta.x(), 0) | 793 (abs(delta.x()) > abs(delta.y())) ? gfx::Vector2d(delta.x(), 0) |
798 : gfx::Vector2d(0, delta.y()); | 794 : gfx::Vector2d(0, delta.y()); |
799 gfx::Vector2d minor_delta = | 795 gfx::Vector2d minor_delta = |
800 (abs(delta.x()) <= abs(delta.y())) ? gfx::Vector2d(delta.x(), 0) | 796 (abs(delta.x()) <= abs(delta.y())) ? gfx::Vector2d(delta.x(), 0) |
801 : gfx::Vector2d(0, delta.y()); | 797 : gfx::Vector2d(0, delta.y()); |
802 gfx::Vector2d deltas[4] = { major_delta, minor_delta, -major_delta, | 798 gfx::Vector2d deltas[4] = { major_delta, minor_delta, -major_delta, |
803 -minor_delta }; | 799 -minor_delta }; |
804 for (int i = 0; i < 4; i++) { | 800 for (int i = 0; i < 4; i++) { |
805 if (deltas[i].y() > 0) { | 801 if (deltas[i].y() > 0) { |
806 while (bottom < prepaint_bottom) { | 802 while (bottom < prepaint_bottom) { |
807 ++bottom; | 803 ++bottom; |
808 if (!UpdateTiles( | 804 if (!UpdateTiles( |
809 left, bottom, right, bottom, queue, NULL, stats, &did_paint) || | 805 left, bottom, right, bottom, queue, NULL, &did_paint) || |
810 did_paint) | 806 did_paint) |
811 return; | 807 return; |
812 } | 808 } |
813 } | 809 } |
814 if (deltas[i].y() < 0) { | 810 if (deltas[i].y() < 0) { |
815 while (top > prepaint_top) { | 811 while (top > prepaint_top) { |
816 --top; | 812 --top; |
817 if (!UpdateTiles( | 813 if (!UpdateTiles( |
818 left, top, right, top, queue, NULL, stats, &did_paint) || | 814 left, top, right, top, queue, NULL, &did_paint) || |
819 did_paint) | 815 did_paint) |
820 return; | 816 return; |
821 } | 817 } |
822 } | 818 } |
823 if (deltas[i].x() < 0) { | 819 if (deltas[i].x() < 0) { |
824 while (left > prepaint_left) { | 820 while (left > prepaint_left) { |
825 --left; | 821 --left; |
826 if (!UpdateTiles( | 822 if (!UpdateTiles( |
827 left, top, left, bottom, queue, NULL, stats, &did_paint) || | 823 left, top, left, bottom, queue, NULL, &did_paint) || |
828 did_paint) | 824 did_paint) |
829 return; | 825 return; |
830 } | 826 } |
831 } | 827 } |
832 if (deltas[i].x() > 0) { | 828 if (deltas[i].x() > 0) { |
833 while (right < prepaint_right) { | 829 while (right < prepaint_right) { |
834 ++right; | 830 ++right; |
835 if (!UpdateTiles( | 831 if (!UpdateTiles( |
836 right, top, right, bottom, queue, NULL, stats, &did_paint) || | 832 right, top, right, bottom, queue, NULL, &did_paint) || |
837 did_paint) | 833 did_paint) |
838 return; | 834 return; |
839 } | 835 } |
840 } | 836 } |
841 } | 837 } |
842 } | 838 } |
843 | 839 |
844 bool TiledLayer::NeedsIdlePaint() { | 840 bool TiledLayer::NeedsIdlePaint() { |
845 // Don't trigger more paints if we failed (as we'll just fail again). | 841 // Don't trigger more paints if we failed (as we'll just fail again). |
846 if (failed_update_ || visible_content_rect().IsEmpty() || | 842 if (failed_update_ || visible_content_rect().IsEmpty() || |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
882 gfx::Rect prepaint_rect = visible_content_rect(); | 878 gfx::Rect prepaint_rect = visible_content_rect(); |
883 prepaint_rect.Inset(-tiler_->tile_size().width() * kPrepaintColumns, | 879 prepaint_rect.Inset(-tiler_->tile_size().width() * kPrepaintColumns, |
884 -tiler_->tile_size().height() * kPrepaintRows); | 880 -tiler_->tile_size().height() * kPrepaintRows); |
885 gfx::Rect content_rect(content_bounds()); | 881 gfx::Rect content_rect(content_bounds()); |
886 prepaint_rect.Intersect(content_rect); | 882 prepaint_rect.Intersect(content_rect); |
887 | 883 |
888 return prepaint_rect; | 884 return prepaint_rect; |
889 } | 885 } |
890 | 886 |
891 } // namespace cc | 887 } // namespace cc |
OLD | NEW |