| 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 |