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