OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "cc/tiles/checker_image_tracker.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/trace_event/trace_event.h" | |
9 #include "skia/ext/skia_utils_base.h" | |
10 | |
11 namespace cc { | |
12 namespace { | |
13 // The minimum size of an image that we should consider checkering. | |
14 size_t kMinImageSizeToCheckerBytes = 512 * 1024; | |
15 } // namespace | |
16 | |
17 CheckerImageTracker::CheckerImageTracker(ImageController* image_controller, | |
18 CheckerImageTrackerClient* client, | |
19 bool enable_checker_imaging) | |
20 : image_controller_(image_controller), | |
21 client_(client), | |
22 enable_checker_imaging_(enable_checker_imaging), | |
23 weak_factory_(this) {} | |
24 | |
25 CheckerImageTracker::~CheckerImageTracker() { | |
26 // Unlock all images pending decode requests. | |
27 for (auto it : image_id_to_decode_request_id_) | |
28 image_controller_->UnlockImageDecode(it.second); | |
29 } | |
30 | |
31 void CheckerImageTracker::FilterImagesForCheckeringForTile( | |
32 std::vector<DrawImage>* images, | |
33 ImageIdFlatSet* checkered_images, | |
34 WhichTree tree) { | |
35 DCHECK(checkered_images->empty()); | |
36 | |
37 auto images_to_checker = std::remove_if( | |
enne (OOO)
2017/02/17 19:12:51
Sure, looks good!
| |
38 images->begin(), images->end(), | |
39 [this, tree, &checkered_images](const DrawImage& draw_image) { | |
40 const sk_sp<const SkImage>& image = draw_image.image(); | |
41 DCHECK(image->isLazyGenerated()); | |
42 if (ShouldCheckerImage(image, tree)) { | |
43 ScheduleImageDecodeIfNecessary(image); | |
44 checkered_images->insert(image->uniqueID()); | |
45 return true; | |
46 } | |
47 return false; | |
48 }); | |
49 images->erase(images_to_checker, images->end()); | |
50 } | |
51 | |
52 const ImageIdFlatSet& CheckerImageTracker::TakeImagesToInvalidateOnSyncTree() { | |
53 DCHECK_EQ(invalidated_images_on_current_sync_tree_.size(), 0u) | |
54 << "Sync tree can not be invalidated more than once"; | |
55 | |
56 invalidated_images_on_current_sync_tree_.swap(images_pending_invalidation_); | |
57 images_pending_invalidation_.clear(); | |
58 return invalidated_images_on_current_sync_tree_; | |
59 } | |
60 | |
61 void CheckerImageTracker::DidActivateSyncTree() { | |
62 for (auto image_id : invalidated_images_on_current_sync_tree_) { | |
63 auto it = image_id_to_decode_request_id_.find(image_id); | |
64 image_controller_->UnlockImageDecode(it->second); | |
65 image_id_to_decode_request_id_.erase(it); | |
66 } | |
67 | |
68 invalidated_images_on_current_sync_tree_.clear(); | |
69 } | |
70 | |
71 void CheckerImageTracker::DidFinishImageDecode( | |
72 ImageId image_id, | |
73 ImageController::ImageDecodeRequestId request_id) { | |
74 TRACE_EVENT_ASYNC_END0("cc", "CheckerImageTracker::DeferImageDecode", | |
75 image_id); | |
76 | |
77 DCHECK_NE(pending_image_decodes_.count(image_id), 0u); | |
78 pending_image_decodes_.erase(image_id); | |
79 | |
80 images_decoded_once_.insert(image_id); | |
81 images_pending_invalidation_.insert(image_id); | |
82 client_->NeedsInvalidationForCheckerImagedTiles(); | |
83 } | |
84 | |
85 bool CheckerImageTracker::ShouldCheckerImage(const sk_sp<const SkImage>& image, | |
86 WhichTree tree) const { | |
87 TRACE_EVENT1("cc", "CheckerImageTracker::ShouldCheckerImage", "image_id", | |
88 image->uniqueID()); | |
89 | |
90 if (!enable_checker_imaging_) | |
91 return false; | |
92 | |
93 // If the image was invalidated on the current sync tree and the tile is | |
94 // for the active tree, continue checkering it on the active tree to ensure | |
95 // the image update is atomic for the frame. | |
96 if (invalidated_images_on_current_sync_tree_.count(image->uniqueID()) != 0 && | |
97 tree == WhichTree::ACTIVE_TREE) { | |
98 return true; | |
99 } | |
100 | |
101 // If a decode request is pending for this image, continue checkering it. | |
102 if (pending_image_decodes_.find(image->uniqueID()) != | |
103 pending_image_decodes_.end()) { | |
104 return true; | |
105 } | |
106 | |
107 // If the image is pending invalidation, continue checkering it. All tiles | |
108 // for these images will be invalidated on the next pending tree. | |
109 if (images_pending_invalidation_.find(image->uniqueID()) != | |
110 images_pending_invalidation_.end()) { | |
111 return true; | |
112 } | |
113 | |
114 // If the image has been decoded once before, don't checker it again. | |
115 if (images_decoded_once_.find(image->uniqueID()) != | |
116 images_decoded_once_.end()) { | |
117 return false; | |
118 } | |
119 | |
120 return skia::SafeSizeOfImage(image.get()) >= kMinImageSizeToCheckerBytes; | |
121 } | |
122 | |
123 void CheckerImageTracker::ScheduleImageDecodeIfNecessary( | |
124 const sk_sp<const SkImage>& image) { | |
125 ImageId image_id = image->uniqueID(); | |
126 | |
127 // If the image has already been decoded, or a decode request is pending, we | |
128 // don't need to schedule another decode. | |
129 if (images_decoded_once_.count(image_id) != 0 || | |
130 pending_image_decodes_.count(image_id) != 0) { | |
131 return; | |
132 } | |
133 | |
134 TRACE_EVENT_ASYNC_BEGIN0("cc", "CheckerImageTracker::DeferImageDecode", | |
135 image_id); | |
136 DCHECK_EQ(image_id_to_decode_request_id_.count(image_id), 0U); | |
137 | |
138 image_id_to_decode_request_id_[image_id] = | |
139 image_controller_->QueueImageDecode( | |
140 image, base::Bind(&CheckerImageTracker::DidFinishImageDecode, | |
141 weak_factory_.GetWeakPtr(), image_id)); | |
142 pending_image_decodes_.insert(image_id); | |
143 } | |
144 | |
145 } // namespace cc | |
OLD | NEW |