| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "platform/graphics/paint/PaintController.h" | 5 #include "platform/graphics/paint/PaintController.h" |
| 6 | 6 |
| 7 #include "platform/graphics/GraphicsLayer.h" | 7 #include "platform/graphics/GraphicsLayer.h" |
| 8 #include "platform/graphics/paint/DrawingDisplayItem.h" | 8 #include "platform/graphics/paint/DrawingDisplayItem.h" |
| 9 #include "platform/instrumentation/tracing/TraceEvent.h" | 9 #include "platform/instrumentation/tracing/TraceEvent.h" |
| 10 #include "platform/wtf/AutoReset.h" | 10 #include "platform/wtf/AutoReset.h" |
| 11 #include "platform/wtf/text/StringBuilder.h" | 11 #include "platform/wtf/text/StringBuilder.h" |
| 12 #include "third_party/skia/include/core/SkPictureAnalyzer.h" | 12 #include "third_party/skia/include/core/SkPictureAnalyzer.h" |
| 13 | 13 |
| 14 #ifndef NDEBUG | 14 #ifndef NDEBUG |
| 15 #include "platform/graphics/LoggingCanvas.h" | 15 #include "platform/graphics/LoggingCanvas.h" |
| 16 #include <stdio.h> | 16 #include <stdio.h> |
| 17 #endif | 17 #endif |
| 18 | 18 |
| 19 static constexpr int kMaxNumberOfSlowPathsBeforeVeto = 5; | 19 static constexpr int kMaxNumberOfSlowPathsBeforeVeto = 5; |
| 20 | 20 |
| 21 namespace blink { | 21 namespace blink { |
| 22 | 22 |
| 23 void PaintController::SetTracksRasterInvalidations(bool value) { | 23 void PaintController::SetTracksRasterInvalidations(bool value) { |
| 24 if (value) { | 24 if (value || |
| 25 paint_chunks_raster_invalidation_tracking_map_ = | 25 RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { |
| 26 raster_invalidation_tracking_map_ = |
| 26 WTF::WrapUnique(new RasterInvalidationTrackingMap<const PaintChunk>); | 27 WTF::WrapUnique(new RasterInvalidationTrackingMap<const PaintChunk>); |
| 27 } else { | 28 return; |
| 28 paint_chunks_raster_invalidation_tracking_map_ = nullptr; | |
| 29 } | 29 } |
| 30 raster_invalidation_tracking_map_ = nullptr; |
| 30 } | 31 } |
| 31 | 32 |
| 32 const PaintArtifact& PaintController::GetPaintArtifact() const { | 33 const PaintArtifact& PaintController::GetPaintArtifact() const { |
| 33 DCHECK(new_display_item_list_.IsEmpty()); | 34 DCHECK(new_display_item_list_.IsEmpty()); |
| 34 DCHECK(new_paint_chunks_.IsInInitialState()); | 35 DCHECK(new_paint_chunks_.IsInInitialState()); |
| 35 return current_paint_artifact_; | 36 return current_paint_artifact_; |
| 36 } | 37 } |
| 37 | 38 |
| 38 bool PaintController::UseCachedDrawingIfPossible( | 39 bool PaintController::UseCachedDrawingIfPossible( |
| 39 const DisplayItemClient& client, | 40 const DisplayItemClient& client, |
| (...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 break; | 591 break; |
| 591 } | 592 } |
| 592 } | 593 } |
| 593 } | 594 } |
| 594 | 595 |
| 595 for (auto* client : skipped_cache_clients) | 596 for (auto* client : skipped_cache_clients) |
| 596 client->SetDisplayItemsUncached(); | 597 client->SetDisplayItemsUncached(); |
| 597 | 598 |
| 598 // The new list will not be appended to again so we can release unused memory. | 599 // The new list will not be appended to again so we can release unused memory. |
| 599 new_display_item_list_.ShrinkToFit(); | 600 new_display_item_list_.ShrinkToFit(); |
| 601 |
| 602 if (raster_invalidation_tracking_map_) { |
| 603 for (const auto& chunk : current_paint_artifact_.PaintChunks()) |
| 604 raster_invalidation_tracking_map_->Remove(&chunk); |
| 605 } |
| 600 current_paint_artifact_ = PaintArtifact( | 606 current_paint_artifact_ = PaintArtifact( |
| 601 std::move(new_display_item_list_), new_paint_chunks_.ReleasePaintChunks(), | 607 std::move(new_display_item_list_), new_paint_chunks_.ReleasePaintChunks(), |
| 602 num_slow_paths <= kMaxNumberOfSlowPathsBeforeVeto); | 608 num_slow_paths <= kMaxNumberOfSlowPathsBeforeVeto); |
| 609 |
| 603 ResetCurrentListIndices(); | 610 ResetCurrentListIndices(); |
| 604 out_of_order_item_indices_.clear(); | 611 out_of_order_item_indices_.clear(); |
| 605 out_of_order_chunk_indices_.clear(); | 612 out_of_order_chunk_indices_.clear(); |
| 606 items_moved_into_new_list_.clear(); | 613 items_moved_into_new_list_.clear(); |
| 607 | 614 |
| 608 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 615 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| 609 for (const auto& chunk : current_paint_artifact_.PaintChunks()) { | 616 for (const auto& chunk : current_paint_artifact_.PaintChunks()) { |
| 610 if (chunk.id && chunk.id->client.IsJustCreated()) | 617 if (chunk.id && chunk.id->client.IsJustCreated()) |
| 611 chunk.id->client.ClearIsJustCreated(); | 618 chunk.id->client.ClearIsJustCreated(); |
| 612 } | 619 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 669 | 676 |
| 670 void PaintController::GenerateChunkRasterInvalidationRects( | 677 void PaintController::GenerateChunkRasterInvalidationRects( |
| 671 PaintChunk& new_chunk) { | 678 PaintChunk& new_chunk) { |
| 672 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | 679 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
| 673 if (new_chunk.begin_index >= | 680 if (new_chunk.begin_index >= |
| 674 current_cached_subsequence_begin_index_in_new_list_) | 681 current_cached_subsequence_begin_index_in_new_list_) |
| 675 return; | 682 return; |
| 676 | 683 |
| 677 static FloatRect infinite_float_rect(LayoutRect::InfiniteIntRect()); | 684 static FloatRect infinite_float_rect(LayoutRect::InfiniteIntRect()); |
| 678 if (!new_chunk.id) { | 685 if (!new_chunk.id) { |
| 679 AddRasterInvalidationInfo(nullptr, new_chunk, infinite_float_rect); | 686 AddRasterInvalidation(nullptr, new_chunk, infinite_float_rect); |
| 680 return; | 687 return; |
| 681 } | 688 } |
| 682 | 689 |
| 683 // Try to match old chunk sequentially first. | 690 // Try to match old chunk sequentially first. |
| 684 const auto& old_chunks = current_paint_artifact_.PaintChunks(); | 691 const auto& old_chunks = current_paint_artifact_.PaintChunks(); |
| 685 while (next_chunk_to_match_ < old_chunks.size()) { | 692 while (next_chunk_to_match_ < old_chunks.size()) { |
| 686 const PaintChunk& old_chunk = old_chunks[next_chunk_to_match_]; | 693 const PaintChunk& old_chunk = old_chunks[next_chunk_to_match_]; |
| 687 if (new_chunk.Matches(old_chunk)) { | 694 if (new_chunk.Matches(old_chunk)) { |
| 688 GenerateChunkRasterInvalidationRectsComparingOldChunk(new_chunk, | 695 GenerateChunkRasterInvalidationRectsComparingOldChunk(new_chunk, |
| 689 old_chunk); | 696 old_chunk); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 711 for (size_t i : it->value) { | 718 for (size_t i : it->value) { |
| 712 if (new_chunk.Matches(old_chunks[i])) { | 719 if (new_chunk.Matches(old_chunks[i])) { |
| 713 GenerateChunkRasterInvalidationRectsComparingOldChunk(new_chunk, | 720 GenerateChunkRasterInvalidationRectsComparingOldChunk(new_chunk, |
| 714 old_chunks[i]); | 721 old_chunks[i]); |
| 715 return; | 722 return; |
| 716 } | 723 } |
| 717 } | 724 } |
| 718 } | 725 } |
| 719 | 726 |
| 720 // We reach here because the chunk is new. | 727 // We reach here because the chunk is new. |
| 721 AddRasterInvalidationInfo(nullptr, new_chunk, infinite_float_rect); | 728 AddRasterInvalidation(nullptr, new_chunk, infinite_float_rect); |
| 722 } | 729 } |
| 723 | 730 |
| 724 void PaintController::AddRasterInvalidationInfo(const DisplayItemClient* client, | 731 void PaintController::AddRasterInvalidation(const DisplayItemClient* client, |
| 725 PaintChunk& chunk, | 732 PaintChunk& chunk, |
| 726 const FloatRect& rect) { | 733 const FloatRect& rect) { |
| 727 chunk.raster_invalidation_rects.push_back(rect); | 734 chunk.raster_invalidation_rects.push_back(rect); |
| 728 if (!paint_chunks_raster_invalidation_tracking_map_) | 735 if (!raster_invalidation_tracking_map_) |
| 729 return; | 736 return; |
| 730 RasterInvalidationInfo info; | 737 RasterInvalidationInfo info; |
| 731 info.rect = EnclosingIntRect(rect); | 738 info.rect = EnclosingIntRect(rect); |
| 732 info.client = client; | 739 info.client = client; |
| 733 if (client) { | 740 if (client) { |
| 734 info.client_debug_name = client->DebugName(); | 741 info.client_debug_name = client->DebugName(); |
| 735 info.reason = client->GetPaintInvalidationReason(); | 742 info.reason = client->GetPaintInvalidationReason(); |
| 736 } | 743 } |
| 737 RasterInvalidationTracking& tracking = | 744 raster_invalidation_tracking_map_->AddInvalidation(&chunk, info); |
| 738 paint_chunks_raster_invalidation_tracking_map_->Add(&chunk); | |
| 739 tracking.tracked_raster_invalidations.push_back(info); | |
| 740 } | 745 } |
| 741 | 746 |
| 742 void PaintController::GenerateChunkRasterInvalidationRectsComparingOldChunk( | 747 void PaintController::GenerateChunkRasterInvalidationRectsComparingOldChunk( |
| 743 PaintChunk& new_chunk, | 748 PaintChunk& new_chunk, |
| 744 const PaintChunk& old_chunk) { | 749 const PaintChunk& old_chunk) { |
| 745 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | 750 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
| 746 | 751 |
| 747 // TODO(wangxianzhu): Handle PaintInvalidationIncremental. | 752 // TODO(wangxianzhu): Handle PaintInvalidationIncremental. |
| 748 // TODO(wangxianzhu): Optimize paint offset change. | 753 // TODO(wangxianzhu): Optimize paint offset change. |
| 749 | 754 |
| 755 // We may track raster invalidations across multiple paints. The new chunk |
| 756 // should contain all previously tracked invalidations. |
| 757 if (raster_invalidation_tracking_map_) { |
| 758 // Add() must be before Find() otherwise Add() might invalidate the pointer |
| 759 // returned from Find(). |
| 760 auto& new_tracking = raster_invalidation_tracking_map_->Add(&new_chunk); |
| 761 if (auto* old_tracking = |
| 762 raster_invalidation_tracking_map_->Find(&old_chunk)) { |
| 763 new_tracking.tracked_invalidations.AppendVector( |
| 764 old_tracking->tracked_invalidations); |
| 765 } |
| 766 } |
| 767 |
| 750 HashSet<const DisplayItemClient*> invalidated_clients_in_old_chunk; | 768 HashSet<const DisplayItemClient*> invalidated_clients_in_old_chunk; |
| 751 size_t highest_moved_to_index = 0; | 769 size_t highest_moved_to_index = 0; |
| 752 for (size_t old_index = old_chunk.begin_index; | 770 for (size_t old_index = old_chunk.begin_index; |
| 753 old_index < old_chunk.end_index; ++old_index) { | 771 old_index < old_chunk.end_index; ++old_index) { |
| 754 const DisplayItem& old_item = | 772 const DisplayItem& old_item = |
| 755 current_paint_artifact_.GetDisplayItemList()[old_index]; | 773 current_paint_artifact_.GetDisplayItemList()[old_index]; |
| 756 const DisplayItemClient* client_to_invalidate = nullptr; | 774 const DisplayItemClient* client_to_invalidate = nullptr; |
| 757 bool is_potentially_invalid_client = false; | 775 bool is_potentially_invalid_client = false; |
| 758 if (!old_item.HasValidClient()) { | 776 if (!old_item.HasValidClient()) { |
| 759 size_t moved_to_index = items_moved_into_new_list_[old_index]; | 777 size_t moved_to_index = items_moved_into_new_list_[old_index]; |
| 760 if (new_display_item_list_[moved_to_index].DrawsContent()) { | 778 if (new_display_item_list_[moved_to_index].DrawsContent()) { |
| 761 if (moved_to_index < new_chunk.begin_index || | 779 if (moved_to_index < new_chunk.begin_index || |
| 762 moved_to_index >= new_chunk.end_index) { | 780 moved_to_index >= new_chunk.end_index) { |
| 763 // The item has been moved into another chunk, so need to invalidate | 781 // The item has been moved into another chunk, so need to invalidate |
| 764 // it in the old chunk. | 782 // it in the old chunk. |
| 765 client_to_invalidate = | 783 client_to_invalidate = |
| 766 &new_display_item_list_[moved_to_index].Client(); | 784 &new_display_item_list_[moved_to_index].Client(); |
| 767 // And invalidate in the new chunk into which the item was moved. | 785 // And invalidate in the new chunk into which the item was moved. |
| 768 PaintChunk& moved_to_chunk = | 786 PaintChunk& moved_to_chunk = |
| 769 new_paint_chunks_.FindChunkByDisplayItemIndex(moved_to_index); | 787 new_paint_chunks_.FindChunkByDisplayItemIndex(moved_to_index); |
| 770 AddRasterInvalidationInfo( | 788 AddRasterInvalidation(client_to_invalidate, moved_to_chunk, |
| 771 client_to_invalidate, moved_to_chunk, | 789 FloatRect(client_to_invalidate->VisualRect())); |
| 772 FloatRect(client_to_invalidate->VisualRect())); | |
| 773 } else if (moved_to_index < highest_moved_to_index) { | 790 } else if (moved_to_index < highest_moved_to_index) { |
| 774 // The item has been moved behind other cached items, so need to | 791 // The item has been moved behind other cached items, so need to |
| 775 // invalidate the area that is probably exposed by the item moved | 792 // invalidate the area that is probably exposed by the item moved |
| 776 // earlier. | 793 // earlier. |
| 777 client_to_invalidate = | 794 client_to_invalidate = |
| 778 &new_display_item_list_[moved_to_index].Client(); | 795 &new_display_item_list_[moved_to_index].Client(); |
| 779 } else { | 796 } else { |
| 780 highest_moved_to_index = moved_to_index; | 797 highest_moved_to_index = moved_to_index; |
| 781 } | 798 } |
| 782 } | 799 } |
| 783 } else if (old_item.DrawsContent()) { | 800 } else if (old_item.DrawsContent()) { |
| 784 is_potentially_invalid_client = true; | 801 is_potentially_invalid_client = true; |
| 785 client_to_invalidate = &old_item.Client(); | 802 client_to_invalidate = &old_item.Client(); |
| 786 } | 803 } |
| 787 if (client_to_invalidate && | 804 if (client_to_invalidate && |
| 788 invalidated_clients_in_old_chunk.insert(client_to_invalidate) | 805 invalidated_clients_in_old_chunk.insert(client_to_invalidate) |
| 789 .is_new_entry) { | 806 .is_new_entry) { |
| 790 AddRasterInvalidationInfo( | 807 AddRasterInvalidation( |
| 791 is_potentially_invalid_client ? nullptr : client_to_invalidate, | 808 is_potentially_invalid_client ? nullptr : client_to_invalidate, |
| 792 new_chunk, | 809 new_chunk, |
| 793 FloatRect(current_paint_artifact_.GetDisplayItemList().VisualRect( | 810 FloatRect(current_paint_artifact_.GetDisplayItemList().VisualRect( |
| 794 old_index))); | 811 old_index))); |
| 795 } | 812 } |
| 796 } | 813 } |
| 797 | 814 |
| 798 HashSet<const DisplayItemClient*> invalidated_clients_in_new_chunk; | 815 HashSet<const DisplayItemClient*> invalidated_clients_in_new_chunk; |
| 799 for (size_t new_index = new_chunk.begin_index; | 816 for (size_t new_index = new_chunk.begin_index; |
| 800 new_index < new_chunk.end_index; ++new_index) { | 817 new_index < new_chunk.end_index; ++new_index) { |
| 801 const DisplayItem& new_item = new_display_item_list_[new_index]; | 818 const DisplayItem& new_item = new_display_item_list_[new_index]; |
| 802 if (new_item.DrawsContent() && !ClientCacheIsValid(new_item.Client()) && | 819 if (new_item.DrawsContent() && !ClientCacheIsValid(new_item.Client()) && |
| 803 invalidated_clients_in_new_chunk.insert(&new_item.Client()) | 820 invalidated_clients_in_new_chunk.insert(&new_item.Client()) |
| 804 .is_new_entry) { | 821 .is_new_entry) { |
| 805 AddRasterInvalidationInfo(&new_item.Client(), new_chunk, | 822 AddRasterInvalidation(&new_item.Client(), new_chunk, |
| 806 FloatRect(new_item.Client().VisualRect())); | 823 FloatRect(new_item.Client().VisualRect())); |
| 807 } | 824 } |
| 808 } | 825 } |
| 809 } | 826 } |
| 810 | 827 |
| 811 void PaintController::ShowUnderInvalidationError( | 828 void PaintController::ShowUnderInvalidationError( |
| 812 const char* reason, | 829 const char* reason, |
| 813 const DisplayItem& new_item, | 830 const DisplayItem& new_item, |
| 814 const DisplayItem* old_item) const { | 831 const DisplayItem* old_item) const { |
| 815 LOG(ERROR) << under_invalidation_message_prefix_ << " " << reason; | 832 LOG(ERROR) << under_invalidation_message_prefix_ << " " << reason; |
| 816 #ifndef NDEBUG | 833 #ifndef NDEBUG |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 938 show_paint_records | 955 show_paint_records |
| 939 ? (DisplayItemList::JsonOptions::kShowPaintRecords | | 956 ? (DisplayItemList::JsonOptions::kShowPaintRecords | |
| 940 DisplayItemList::JsonOptions::kShowClientDebugName) | 957 DisplayItemList::JsonOptions::kShowClientDebugName) |
| 941 : DisplayItemList::JsonOptions::kShowClientDebugName) | 958 : DisplayItemList::JsonOptions::kShowClientDebugName) |
| 942 ->ToPrettyJSONString() | 959 ->ToPrettyJSONString() |
| 943 .Utf8() | 960 .Utf8() |
| 944 .data()); | 961 .data()); |
| 945 } | 962 } |
| 946 | 963 |
| 947 } // namespace blink | 964 } // namespace blink |
| OLD | NEW |