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 RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { | 25 RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { |
26 raster_invalidation_tracking_map_ = | 26 raster_invalidation_tracking_info_ = |
27 WTF::WrapUnique(new RasterInvalidationTrackingMap<const PaintChunk>); | 27 WTF::MakeUnique<RasterInvalidationTrackingInfo>(); |
| 28 |
| 29 // This is called just after a full document cycle update, so all clients in |
| 30 // current_paint_artifact_ should be still alive. |
| 31 DCHECK(new_display_item_list_.IsEmpty()); |
| 32 for (const auto& item : current_paint_artifact_.GetDisplayItemList()) { |
| 33 raster_invalidation_tracking_info_->old_client_debug_names.Set( |
| 34 &item.Client(), item.Client().DebugName()); |
| 35 } |
28 } else { | 36 } else { |
29 raster_invalidation_tracking_map_ = nullptr; | 37 raster_invalidation_tracking_info_ = nullptr; |
30 } | 38 } |
31 } | 39 } |
32 | 40 |
33 const PaintArtifact& PaintController::GetPaintArtifact() const { | 41 const PaintArtifact& PaintController::GetPaintArtifact() const { |
34 DCHECK(new_display_item_list_.IsEmpty()); | 42 DCHECK(new_display_item_list_.IsEmpty()); |
35 DCHECK(new_paint_chunks_.IsInInitialState()); | 43 DCHECK(new_paint_chunks_.IsInInitialState()); |
36 return current_paint_artifact_; | 44 return current_paint_artifact_; |
37 } | 45 } |
38 | 46 |
39 bool PaintController::UseCachedDrawingIfPossible( | 47 bool PaintController::UseCachedDrawingIfPossible( |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 | 249 |
242 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS | 250 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
243 if (display_item.IsCacheable()) { | 251 if (display_item.IsCacheable()) { |
244 BeginShouldKeepAlive(display_item.Client()); | 252 BeginShouldKeepAlive(display_item.Client()); |
245 } | 253 } |
246 #endif | 254 #endif |
247 | 255 |
248 if (IsSkippingCache()) | 256 if (IsSkippingCache()) |
249 display_item.SetSkippedCache(); | 257 display_item.SetSkippedCache(); |
250 | 258 |
| 259 if (raster_invalidation_tracking_info_) { |
| 260 raster_invalidation_tracking_info_->new_client_debug_names.insert( |
| 261 &display_item.Client(), display_item.Client().DebugName()); |
| 262 } |
| 263 |
251 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 264 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
252 size_t last_chunk_index = new_paint_chunks_.LastChunkIndex(); | 265 size_t last_chunk_index = new_paint_chunks_.LastChunkIndex(); |
253 if (new_paint_chunks_.IncrementDisplayItemIndex(display_item)) { | 266 if (new_paint_chunks_.IncrementDisplayItemIndex(display_item)) { |
254 DCHECK(last_chunk_index != new_paint_chunks_.LastChunkIndex()); | 267 DCHECK(last_chunk_index != new_paint_chunks_.LastChunkIndex()); |
255 if (last_chunk_index != kNotFound) { | 268 if (last_chunk_index != kNotFound) { |
256 GenerateRasterInvalidations( | 269 GenerateRasterInvalidations( |
257 new_paint_chunks_.PaintChunkAt(last_chunk_index)); | 270 new_paint_chunks_.PaintChunkAt(last_chunk_index)); |
258 } | 271 } |
259 } | 272 } |
260 } | 273 } |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
593 } | 606 } |
594 } | 607 } |
595 } | 608 } |
596 | 609 |
597 for (auto* client : skipped_cache_clients) | 610 for (auto* client : skipped_cache_clients) |
598 client->SetDisplayItemsUncached(); | 611 client->SetDisplayItemsUncached(); |
599 | 612 |
600 // The new list will not be appended to again so we can release unused memory. | 613 // The new list will not be appended to again so we can release unused memory. |
601 new_display_item_list_.ShrinkToFit(); | 614 new_display_item_list_.ShrinkToFit(); |
602 | 615 |
603 if (raster_invalidation_tracking_map_) { | 616 if (raster_invalidation_tracking_info_) { |
604 for (const auto& chunk : current_paint_artifact_.PaintChunks()) | 617 for (const auto& chunk : current_paint_artifact_.PaintChunks()) |
605 raster_invalidation_tracking_map_->Remove(&chunk); | 618 raster_invalidation_tracking_info_->map.Remove(&chunk); |
606 } | 619 } |
607 current_paint_artifact_ = PaintArtifact( | 620 current_paint_artifact_ = PaintArtifact( |
608 std::move(new_display_item_list_), new_paint_chunks_.ReleasePaintChunks(), | 621 std::move(new_display_item_list_), new_paint_chunks_.ReleasePaintChunks(), |
609 num_slow_paths <= kMaxNumberOfSlowPathsBeforeVeto); | 622 num_slow_paths <= kMaxNumberOfSlowPathsBeforeVeto); |
610 | 623 |
611 ResetCurrentListIndices(); | 624 ResetCurrentListIndices(); |
612 out_of_order_item_indices_.clear(); | 625 out_of_order_item_indices_.clear(); |
613 out_of_order_chunk_indices_.clear(); | 626 out_of_order_chunk_indices_.clear(); |
614 items_moved_into_new_list_.clear(); | 627 items_moved_into_new_list_.clear(); |
615 | 628 |
616 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 629 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
617 for (const auto& chunk : current_paint_artifact_.PaintChunks()) { | 630 for (const auto& chunk : current_paint_artifact_.PaintChunks()) { |
618 if (chunk.id && chunk.id->client.IsJustCreated()) | 631 if (chunk.id && chunk.id->client.IsJustCreated()) |
619 chunk.id->client.ClearIsJustCreated(); | 632 chunk.id->client.ClearIsJustCreated(); |
620 } | 633 } |
621 } | 634 } |
622 | 635 |
623 // We'll allocate the initial buffer when we start the next paint. | 636 // We'll allocate the initial buffer when we start the next paint. |
624 new_display_item_list_ = DisplayItemList(0); | 637 new_display_item_list_ = DisplayItemList(0); |
625 | 638 |
626 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS | 639 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
627 DisplayItemClient::EndShouldKeepAliveAllClients(this); | 640 DisplayItemClient::EndShouldKeepAliveAllClients(this); |
628 #endif | 641 #endif |
629 | 642 |
630 #ifndef NDEBUG | 643 #ifndef NDEBUG |
631 num_sequential_matches_ = 0; | 644 num_sequential_matches_ = 0; |
632 num_out_of_order_matches_ = 0; | 645 num_out_of_order_matches_ = 0; |
633 num_indexed_items_ = 0; | 646 num_indexed_items_ = 0; |
634 #endif | 647 #endif |
| 648 |
| 649 if (raster_invalidation_tracking_info_) { |
| 650 raster_invalidation_tracking_info_->old_client_debug_names.clear(); |
| 651 std::swap(raster_invalidation_tracking_info_->old_client_debug_names, |
| 652 raster_invalidation_tracking_info_->new_client_debug_names); |
| 653 } |
635 } | 654 } |
636 | 655 |
637 size_t PaintController::ApproximateUnsharedMemoryUsage() const { | 656 size_t PaintController::ApproximateUnsharedMemoryUsage() const { |
638 size_t memory_usage = sizeof(*this); | 657 size_t memory_usage = sizeof(*this); |
639 | 658 |
640 // Memory outside this class due to m_currentPaintArtifact. | 659 // Memory outside this class due to m_currentPaintArtifact. |
641 memory_usage += current_paint_artifact_.ApproximateUnsharedMemoryUsage() - | 660 memory_usage += current_paint_artifact_.ApproximateUnsharedMemoryUsage() - |
642 sizeof(current_paint_artifact_); | 661 sizeof(current_paint_artifact_); |
643 | 662 |
644 // TODO(jbroman): If display items begin to have significant external memory | 663 // TODO(jbroman): If display items begin to have significant external memory |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 } | 695 } |
677 | 696 |
678 void PaintController::GenerateRasterInvalidations(PaintChunk& new_chunk) { | 697 void PaintController::GenerateRasterInvalidations(PaintChunk& new_chunk) { |
679 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | 698 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
680 if (new_chunk.begin_index >= | 699 if (new_chunk.begin_index >= |
681 current_cached_subsequence_begin_index_in_new_list_) | 700 current_cached_subsequence_begin_index_in_new_list_) |
682 return; | 701 return; |
683 | 702 |
684 static FloatRect infinite_float_rect(LayoutRect::InfiniteIntRect()); | 703 static FloatRect infinite_float_rect(LayoutRect::InfiniteIntRect()); |
685 if (!new_chunk.id) { | 704 if (!new_chunk.id) { |
686 AddRasterInvalidation(nullptr, new_chunk, infinite_float_rect); | 705 // This chunk is not cacheable, so always invalidate the whole chunk. |
| 706 AddRasterInvalidation( |
| 707 new_display_item_list_[new_chunk.begin_index].Client(), new_chunk, |
| 708 infinite_float_rect); |
687 return; | 709 return; |
688 } | 710 } |
689 | 711 |
690 // Try to match old chunk sequentially first. | 712 // Try to match old chunk sequentially first. |
691 const auto& old_chunks = current_paint_artifact_.PaintChunks(); | 713 const auto& old_chunks = current_paint_artifact_.PaintChunks(); |
692 while (next_chunk_to_match_ < old_chunks.size()) { | 714 while (next_chunk_to_match_ < old_chunks.size()) { |
693 const PaintChunk& old_chunk = old_chunks[next_chunk_to_match_]; | 715 const PaintChunk& old_chunk = old_chunks[next_chunk_to_match_]; |
694 if (new_chunk.Matches(old_chunk)) { | 716 if (new_chunk.Matches(old_chunk)) { |
695 GenerateRasterInvalidationsComparingChunks(new_chunk, old_chunk); | 717 GenerateRasterInvalidationsComparingChunks(new_chunk, old_chunk); |
696 ++next_chunk_to_match_; | 718 ++next_chunk_to_match_; |
(...skipping 19 matching lines...) Expand all Loading... |
716 if (it != out_of_order_chunk_indices_.end()) { | 738 if (it != out_of_order_chunk_indices_.end()) { |
717 for (size_t i : it->value) { | 739 for (size_t i : it->value) { |
718 if (new_chunk.Matches(old_chunks[i])) { | 740 if (new_chunk.Matches(old_chunks[i])) { |
719 GenerateRasterInvalidationsComparingChunks(new_chunk, old_chunks[i]); | 741 GenerateRasterInvalidationsComparingChunks(new_chunk, old_chunks[i]); |
720 return; | 742 return; |
721 } | 743 } |
722 } | 744 } |
723 } | 745 } |
724 | 746 |
725 // We reach here because the chunk is new. | 747 // We reach here because the chunk is new. |
726 AddRasterInvalidation(nullptr, new_chunk, infinite_float_rect); | 748 AddRasterInvalidation(new_display_item_list_[new_chunk.begin_index].Client(), |
| 749 new_chunk, infinite_float_rect); |
727 } | 750 } |
728 | 751 |
729 void PaintController::AddRasterInvalidation(const DisplayItemClient* client, | 752 void PaintController::AddRasterInvalidation(const DisplayItemClient& client, |
730 PaintChunk& chunk, | 753 PaintChunk& chunk, |
731 const FloatRect& rect) { | 754 const FloatRect& rect) { |
732 chunk.raster_invalidation_rects.push_back(rect); | 755 chunk.raster_invalidation_rects.push_back(rect); |
733 if (raster_invalidation_tracking_map_) | 756 if (raster_invalidation_tracking_info_) |
734 TrackRasterInvalidation(client, chunk, rect); | 757 TrackRasterInvalidation(client, chunk, rect); |
735 } | 758 } |
736 | 759 |
737 void PaintController::TrackRasterInvalidation(const DisplayItemClient* client, | 760 void PaintController::TrackRasterInvalidation(const DisplayItemClient& client, |
738 PaintChunk& chunk, | 761 PaintChunk& chunk, |
739 const FloatRect& rect) { | 762 const FloatRect& rect) { |
740 DCHECK(raster_invalidation_tracking_map_); | 763 DCHECK(raster_invalidation_tracking_info_); |
741 | 764 |
742 RasterInvalidationInfo info; | 765 RasterInvalidationInfo info; |
743 info.rect = EnclosingIntRect(rect); | 766 info.rect = EnclosingIntRect(rect); |
744 info.client = client; | 767 info.client = &client; |
745 if (client) { | 768 auto it = |
746 info.client_debug_name = client->DebugName(); | 769 raster_invalidation_tracking_info_->new_client_debug_names.find(&client); |
747 info.reason = client->GetPaintInvalidationReason(); | 770 if (it == raster_invalidation_tracking_info_->new_client_debug_names.end()) { |
| 771 it = raster_invalidation_tracking_info_->old_client_debug_names.find( |
| 772 &client); |
| 773 // The client should be either in new list or in old list. |
| 774 DCHECK(it != |
| 775 raster_invalidation_tracking_info_->old_client_debug_names.end()); |
| 776 info.reason = kPaintInvalidationLayoutObjectRemoval; |
| 777 } else { |
| 778 info.reason = client.GetPaintInvalidationReason(); |
748 } | 779 } |
749 raster_invalidation_tracking_map_->Add(&chunk).invalidations.push_back(info); | 780 info.client_debug_name = it->value; |
| 781 raster_invalidation_tracking_info_->map.Add(&chunk).invalidations.push_back( |
| 782 info); |
750 } | 783 } |
751 | 784 |
752 void PaintController::GenerateRasterInvalidationsComparingChunks( | 785 void PaintController::GenerateRasterInvalidationsComparingChunks( |
753 PaintChunk& new_chunk, | 786 PaintChunk& new_chunk, |
754 const PaintChunk& old_chunk) { | 787 const PaintChunk& old_chunk) { |
755 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | 788 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
756 | 789 |
757 // TODO(wangxianzhu): Handle PaintInvalidationIncremental. | 790 // TODO(wangxianzhu): Handle PaintInvalidationIncremental. |
758 // TODO(wangxianzhu): Optimize paint offset change. | 791 // TODO(wangxianzhu): Optimize paint offset change. |
759 | 792 |
760 HashSet<const DisplayItemClient*> invalidated_clients_in_old_chunk; | 793 HashSet<const DisplayItemClient*> invalidated_clients_in_old_chunk; |
761 size_t highest_moved_to_index = 0; | 794 size_t highest_moved_to_index = 0; |
762 for (size_t old_index = old_chunk.begin_index; | 795 for (size_t old_index = old_chunk.begin_index; |
763 old_index < old_chunk.end_index; ++old_index) { | 796 old_index < old_chunk.end_index; ++old_index) { |
764 const DisplayItem& old_item = | 797 const DisplayItem& old_item = |
765 current_paint_artifact_.GetDisplayItemList()[old_index]; | 798 current_paint_artifact_.GetDisplayItemList()[old_index]; |
766 const DisplayItemClient* client_to_invalidate = nullptr; | 799 const DisplayItemClient* client_to_invalidate = nullptr; |
767 bool is_potentially_invalid_client = false; | 800 |
768 if (!old_item.HasValidClient()) { | 801 if (!old_item.HasValidClient()) { |
769 size_t moved_to_index = items_moved_into_new_list_[old_index]; | 802 size_t moved_to_index = items_moved_into_new_list_[old_index]; |
770 if (new_display_item_list_[moved_to_index].DrawsContent()) { | 803 if (new_display_item_list_[moved_to_index].DrawsContent()) { |
771 if (moved_to_index < new_chunk.begin_index || | 804 if (moved_to_index < new_chunk.begin_index || |
772 moved_to_index >= new_chunk.end_index) { | 805 moved_to_index >= new_chunk.end_index) { |
773 // The item has been moved into another chunk, so need to invalidate | 806 // The item has been moved into another chunk, so need to invalidate |
774 // it in the old chunk. | 807 // it in the old chunk. |
775 client_to_invalidate = | 808 client_to_invalidate = |
776 &new_display_item_list_[moved_to_index].Client(); | 809 &new_display_item_list_[moved_to_index].Client(); |
777 // And invalidate in the new chunk into which the item was moved. | 810 // And invalidate in the new chunk into which the item was moved. |
778 PaintChunk& moved_to_chunk = | 811 PaintChunk& moved_to_chunk = |
779 new_paint_chunks_.FindChunkByDisplayItemIndex(moved_to_index); | 812 new_paint_chunks_.FindChunkByDisplayItemIndex(moved_to_index); |
780 AddRasterInvalidation(client_to_invalidate, moved_to_chunk, | 813 AddRasterInvalidation(*client_to_invalidate, moved_to_chunk, |
781 FloatRect(client_to_invalidate->VisualRect())); | 814 FloatRect(client_to_invalidate->VisualRect())); |
782 } else if (moved_to_index < highest_moved_to_index) { | 815 } else if (moved_to_index < highest_moved_to_index) { |
783 // The item has been moved behind other cached items, so need to | 816 // The item has been moved behind other cached items, so need to |
784 // invalidate the area that is probably exposed by the item moved | 817 // invalidate the area that is probably exposed by the item moved |
785 // earlier. | 818 // earlier. |
786 client_to_invalidate = | 819 client_to_invalidate = |
787 &new_display_item_list_[moved_to_index].Client(); | 820 &new_display_item_list_[moved_to_index].Client(); |
788 } else { | 821 } else { |
789 highest_moved_to_index = moved_to_index; | 822 highest_moved_to_index = moved_to_index; |
790 } | 823 } |
791 } | 824 } |
792 } else if (old_item.DrawsContent()) { | 825 } else if (old_item.DrawsContent()) { |
793 is_potentially_invalid_client = true; | |
794 client_to_invalidate = &old_item.Client(); | 826 client_to_invalidate = &old_item.Client(); |
795 } | 827 } |
796 if (client_to_invalidate && | 828 if (client_to_invalidate && |
797 invalidated_clients_in_old_chunk.insert(client_to_invalidate) | 829 invalidated_clients_in_old_chunk.insert(client_to_invalidate) |
798 .is_new_entry) { | 830 .is_new_entry) { |
799 AddRasterInvalidation( | 831 AddRasterInvalidation( |
800 is_potentially_invalid_client ? nullptr : client_to_invalidate, | 832 *client_to_invalidate, new_chunk, |
801 new_chunk, | |
802 FloatRect(current_paint_artifact_.GetDisplayItemList().VisualRect( | 833 FloatRect(current_paint_artifact_.GetDisplayItemList().VisualRect( |
803 old_index))); | 834 old_index))); |
804 } | 835 } |
805 } | 836 } |
806 | 837 |
807 HashSet<const DisplayItemClient*> invalidated_clients_in_new_chunk; | 838 HashSet<const DisplayItemClient*> invalidated_clients_in_new_chunk; |
808 for (size_t new_index = new_chunk.begin_index; | 839 for (size_t new_index = new_chunk.begin_index; |
809 new_index < new_chunk.end_index; ++new_index) { | 840 new_index < new_chunk.end_index; ++new_index) { |
810 const DisplayItem& new_item = new_display_item_list_[new_index]; | 841 const DisplayItem& new_item = new_display_item_list_[new_index]; |
811 if (new_item.DrawsContent() && !ClientCacheIsValid(new_item.Client()) && | 842 if (new_item.DrawsContent() && !ClientCacheIsValid(new_item.Client()) && |
812 invalidated_clients_in_new_chunk.insert(&new_item.Client()) | 843 invalidated_clients_in_new_chunk.insert(&new_item.Client()) |
813 .is_new_entry) { | 844 .is_new_entry) { |
814 AddRasterInvalidation(&new_item.Client(), new_chunk, | 845 AddRasterInvalidation(new_item.Client(), new_chunk, |
815 FloatRect(new_item.Client().VisualRect())); | 846 FloatRect(new_item.Client().VisualRect())); |
816 } | 847 } |
817 } | 848 } |
818 } | 849 } |
819 | 850 |
820 void PaintController::ShowUnderInvalidationError( | 851 void PaintController::ShowUnderInvalidationError( |
821 const char* reason, | 852 const char* reason, |
822 const DisplayItem& new_item, | 853 const DisplayItem& new_item, |
823 const DisplayItem* old_item) const { | 854 const DisplayItem* old_item) const { |
824 LOG(ERROR) << under_invalidation_message_prefix_ << " " << reason; | 855 LOG(ERROR) << under_invalidation_message_prefix_ << " " << reason; |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
947 show_paint_records | 978 show_paint_records |
948 ? (DisplayItemList::JsonOptions::kShowPaintRecords | | 979 ? (DisplayItemList::JsonOptions::kShowPaintRecords | |
949 DisplayItemList::JsonOptions::kShowClientDebugName) | 980 DisplayItemList::JsonOptions::kShowClientDebugName) |
950 : DisplayItemList::JsonOptions::kShowClientDebugName) | 981 : DisplayItemList::JsonOptions::kShowClientDebugName) |
951 ->ToPrettyJSONString() | 982 ->ToPrettyJSONString() |
952 .Utf8() | 983 .Utf8() |
953 .data()); | 984 .data()); |
954 } | 985 } |
955 | 986 |
956 } // namespace blink | 987 } // namespace blink |
OLD | NEW |