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