Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 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 | 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/tiles/checker_image_tracker.h" | 5 #include "cc/tiles/checker_image_tracker.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
| 10 #include "base/trace_event/trace_event.h" | 10 #include "base/trace_event/trace_event.h" |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 83 | 83 |
| 84 if (can_clear_decode_policy_tracking) { | 84 if (can_clear_decode_policy_tracking) { |
| 85 image_async_decode_state_.clear(); | 85 image_async_decode_state_.clear(); |
| 86 } else { | 86 } else { |
| 87 // If we can't clear the decode policy, we need to make sure we still | 87 // If we can't clear the decode policy, we need to make sure we still |
| 88 // re-decode and checker images that were pending invalidation. | 88 // re-decode and checker images that were pending invalidation. |
| 89 for (auto image_id : images_pending_invalidation_) { | 89 for (auto image_id : images_pending_invalidation_) { |
| 90 auto it = image_async_decode_state_.find(image_id); | 90 auto it = image_async_decode_state_.find(image_id); |
| 91 | 91 |
| 92 DCHECK(it != image_async_decode_state_.end()); | 92 DCHECK(it != image_async_decode_state_.end()); |
| 93 DCHECK_EQ(it->second, DecodePolicy::SYNC_DECODED_ONCE); | 93 DCHECK_EQ(it->second.policy, DecodePolicy::SYNC_DECODED_ONCE); |
| 94 | 94 |
| 95 it->second = DecodePolicy::ASYNC; | 95 it->second.policy = DecodePolicy::ASYNC; |
| 96 } | 96 } |
| 97 } | 97 } |
| 98 images_pending_invalidation_.clear(); | 98 images_pending_invalidation_.clear(); |
| 99 } | 99 } |
| 100 | 100 |
| 101 void CheckerImageTracker::DidFinishImageDecode( | 101 void CheckerImageTracker::DidFinishImageDecode( |
| 102 PaintImage::Id image_id, | 102 PaintImage::Id image_id, |
| 103 ImageController::ImageDecodeRequestId request_id, | 103 ImageController::ImageDecodeRequestId request_id, |
| 104 ImageController::ImageDecodeResult result) { | 104 ImageController::ImageDecodeResult result) { |
| 105 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 105 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
| 106 "CheckerImageTracker::DidFinishImageDecode"); | 106 "CheckerImageTracker::DidFinishImageDecode"); |
| 107 TRACE_EVENT_ASYNC_END0("cc", "CheckerImageTracker::DeferImageDecode", | 107 TRACE_EVENT_ASYNC_END0("cc", "CheckerImageTracker::DeferImageDecode", |
| 108 image_id); | 108 image_id); |
| 109 | 109 |
| 110 DCHECK_NE(ImageController::ImageDecodeResult::DECODE_NOT_REQUIRED, result); | 110 DCHECK_NE(ImageController::ImageDecodeResult::DECODE_NOT_REQUIRED, result); |
| 111 DCHECK_EQ(outstanding_image_decode_.value().stable_id(), image_id); | 111 DCHECK_EQ(outstanding_image_decode_.value().stable_id(), image_id); |
| 112 outstanding_image_decode_.reset(); | 112 outstanding_image_decode_.reset(); |
| 113 | 113 |
| 114 // The async decode state may have been cleared if the tracker was cleared | 114 // The async decode state may have been cleared if the tracker was cleared |
| 115 // before this decode could be finished. | 115 // before this decode could be finished. |
| 116 auto it = image_async_decode_state_.find(image_id); | 116 auto it = image_async_decode_state_.find(image_id); |
| 117 if (it == image_async_decode_state_.end()) { | 117 if (it == image_async_decode_state_.end()) { |
| 118 DCHECK_EQ(image_id_to_decode_.count(image_id), 0u); | 118 DCHECK_EQ(image_id_to_decode_.count(image_id), 0u); |
| 119 return; | 119 return; |
| 120 } | 120 } |
| 121 | 121 |
| 122 it->second = DecodePolicy::SYNC_DECODED_ONCE; | 122 it->second.policy = DecodePolicy::SYNC_DECODED_ONCE; |
| 123 images_pending_invalidation_.insert(image_id); | 123 images_pending_invalidation_.insert(image_id); |
| 124 ScheduleNextImageDecode(); | 124 ScheduleNextImageDecode(); |
| 125 client_->NeedsInvalidationForCheckerImagedTiles(); | 125 client_->NeedsInvalidationForCheckerImagedTiles(); |
| 126 } | 126 } |
| 127 | 127 |
| 128 bool CheckerImageTracker::ShouldCheckerImage(const PaintImage& image, | 128 bool CheckerImageTracker::ShouldCheckerImage(const DrawImage& draw_image, |
| 129 WhichTree tree) { | 129 WhichTree tree) { |
| 130 const PaintImage& image = draw_image.paint_image(); | |
| 131 PaintImage::Id image_id = image.stable_id(); | |
| 130 TRACE_EVENT1("cc", "CheckerImageTracker::ShouldCheckerImage", "image_id", | 132 TRACE_EVENT1("cc", "CheckerImageTracker::ShouldCheckerImage", "image_id", |
| 131 image.stable_id()); | 133 image_id); |
| 132 | 134 |
| 133 if (!enable_checker_imaging_) | 135 if (!enable_checker_imaging_) |
| 134 return false; | 136 return false; |
| 135 | 137 |
| 136 PaintImage::Id image_id = image.stable_id(); | |
| 137 | |
| 138 // If the image was invalidated on the current sync tree and the tile is | 138 // If the image was invalidated on the current sync tree and the tile is |
| 139 // for the active tree, continue checkering it on the active tree to ensure | 139 // for the active tree, continue checkering it on the active tree to ensure |
| 140 // the image update is atomic for the frame. | 140 // the image update is atomic for the frame. |
| 141 if (invalidated_images_on_current_sync_tree_.count(image_id) != 0 && | 141 if (invalidated_images_on_current_sync_tree_.count(image_id) != 0 && |
| 142 tree == WhichTree::ACTIVE_TREE) { | 142 tree == WhichTree::ACTIVE_TREE) { |
| 143 return true; | 143 return true; |
| 144 } | 144 } |
| 145 | 145 |
| 146 // If the image is pending invalidation, continue checkering it. All tiles | 146 // If the image is pending invalidation, continue checkering it. All tiles |
| 147 // for these images will be invalidated on the next pending tree. | 147 // for these images will be invalidated on the next pending tree. |
| 148 if (images_pending_invalidation_.find(image_id) != | 148 if (images_pending_invalidation_.find(image_id) != |
| 149 images_pending_invalidation_.end()) { | 149 images_pending_invalidation_.end()) { |
| 150 return true; | 150 return true; |
| 151 } | 151 } |
| 152 | 152 |
| 153 auto insert_result = | 153 auto insert_result = image_async_decode_state_.insert( |
| 154 image_async_decode_state_.insert(std::pair<PaintImage::Id, DecodePolicy>( | 154 std::pair<PaintImage::Id, DecodeState>(image_id, DecodeState())); |
| 155 image_id, DecodePolicy::SYNC_PERMANENT)); | |
| 156 auto it = insert_result.first; | 155 auto it = insert_result.first; |
| 157 if (insert_result.second) { | 156 if (insert_result.second) { |
| 158 bool can_checker_image = | 157 bool complete = |
| 159 image.animation_type() == PaintImage::AnimationType::STATIC && | |
| 160 image.completion_state() == PaintImage::CompletionState::DONE; | 158 image.completion_state() == PaintImage::CompletionState::DONE; |
| 161 if (can_checker_image) { | 159 bool static_image = |
| 160 image.animation_type() == PaintImage::AnimationType::STATIC; | |
| 161 // Only checker images that are static and completely loaded. | |
| 162 if (complete && static_image) { | |
| 162 size_t size = SafeSizeOfImage(image.sk_image().get()); | 163 size_t size = SafeSizeOfImage(image.sk_image().get()); |
| 163 it->second = (size >= kMinImageSizeToCheckerBytes && | 164 bool too_small = size < kMinImageSizeToCheckerBytes; |
| 164 size <= image_controller_->image_cache_max_limit_bytes()) | 165 bool too_large = size > image_controller_->image_cache_max_limit_bytes(); |
| 165 ? DecodePolicy::ASYNC | 166 it->second.policy = (too_small || too_large) |
|
ericrk
2017/06/06 22:39:51
The policy already defaults to SYNC_PERMANENT, and
Khushal
2017/06/07 00:43:31
How does it look now? I broke the size part sepera
| |
| 166 : DecodePolicy::SYNC_PERMANENT; | 167 ? DecodePolicy::SYNC_PERMANENT |
| 168 : DecodePolicy::ASYNC; | |
| 169 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | |
| 170 "CheckerImageTracker::CheckerImagingDecision", "too_small", | |
| 171 too_small, "too_large", too_large); | |
| 172 } else { | |
| 173 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | |
| 174 "CheckerImageTracker::CanNotChecker", "complete", complete, | |
| 175 "static", static_image); | |
|
ericrk
2017/06/06 22:39:51
nit: The naming of these trace values seems a bit
Khushal
2017/06/07 00:43:31
You're right. Its because I went to look for TRACE
| |
| 167 } | 176 } |
| 168 } | 177 } |
| 169 | 178 |
| 170 return it->second == DecodePolicy::ASYNC; | 179 // Update the decode state from the latest image we have seen. Note that it |
| 180 // is not necessary to perform this in the early out cases above since in | |
| 181 // each of those cases the image has already been decoded. | |
| 182 UpdateDecodeState(draw_image, image_id, &it->second); | |
| 183 | |
| 184 return it->second.policy == DecodePolicy::ASYNC; | |
| 185 } | |
| 186 | |
| 187 void CheckerImageTracker::UpdateDecodeState(const DrawImage& draw_image, | |
| 188 PaintImage::Id paint_image_id, | |
| 189 DecodeState* decode_state) { | |
| 190 // If the policy is not async then either we decoded this image already or | |
| 191 // we decided not to ever checker it. | |
| 192 if (decode_state->policy != DecodePolicy::ASYNC) | |
| 193 return; | |
| 194 | |
| 195 // If the decode is already in flight, then we will have to live with what we | |
| 196 // have now. | |
| 197 if (outstanding_image_decode_.has_value() && | |
| 198 outstanding_image_decode_.value().stable_id() == paint_image_id) { | |
| 199 return; | |
| 200 } | |
| 201 | |
| 202 // Choose the max scale, going up till the original decode size, and filter | |
| 203 // quality. This keeps the memory usage to the minimum possible while still | |
| 204 // increasing the possibility of getting a cache hit. | |
| 205 decode_state->scale.fWidth = std::min( | |
|
ericrk
2017/06/06 22:39:51
Do we really not want to scale up at this point? T
Khushal
2017/06/07 00:43:31
I don't think the memory impact would be much. Now
| |
| 206 1.0f, std::max(decode_state->scale.fWidth, draw_image.scale().fWidth)); | |
| 207 decode_state->scale.fHeight = std::min( | |
|
ericrk
2017/06/06 22:39:51
Is this ever called with a non-default DecodeState
Khushal
2017/06/07 00:43:31
It will be called with a non-default state if we s
| |
| 208 1.0f, std::max(decode_state->scale.fHeight, draw_image.scale().fHeight)); | |
| 209 decode_state->filter_quality = | |
| 210 std::max(decode_state->filter_quality, draw_image.filter_quality()); | |
| 211 decode_state->color_space = draw_image.target_color_space(); | |
| 171 } | 212 } |
| 172 | 213 |
| 173 void CheckerImageTracker::ScheduleNextImageDecode() { | 214 void CheckerImageTracker::ScheduleNextImageDecode() { |
| 174 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 215 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
| 175 "CheckerImageTracker::ScheduleNextImageDecode"); | 216 "CheckerImageTracker::ScheduleNextImageDecode"); |
| 176 // We can have only one outsanding decode pending completion with the decode | 217 // We can have only one outsanding decode pending completion with the decode |
| 177 // service. We'll come back here when it is completed. | 218 // service. We'll come back here when it is completed. |
| 178 if (outstanding_image_decode_.has_value()) | 219 if (outstanding_image_decode_.has_value()) |
| 179 return; | 220 return; |
| 180 | 221 |
| 222 DrawImage draw_image; | |
| 181 while (!image_decode_queue_.empty()) { | 223 while (!image_decode_queue_.empty()) { |
| 182 auto candidate = std::move(image_decode_queue_.front()); | 224 auto candidate = std::move(image_decode_queue_.front()); |
| 183 image_decode_queue_.erase(image_decode_queue_.begin()); | 225 image_decode_queue_.erase(image_decode_queue_.begin()); |
| 184 | 226 |
| 185 // Once an image has been decoded, it can still be present in the decode | 227 // Once an image has been decoded, it can still be present in the decode |
| 186 // queue (duplicate entries), or while an image is still being skipped on | 228 // queue (duplicate entries), or while an image is still being skipped on |
| 187 // the active tree. Check if the image is still ASYNC to see if a decode is | 229 // the active tree. Check if the image is still ASYNC to see if a decode is |
| 188 // needed. | 230 // needed. |
| 189 PaintImage::Id image_id = candidate.stable_id(); | 231 PaintImage::Id image_id = candidate.stable_id(); |
| 190 auto it = image_async_decode_state_.find(image_id); | 232 auto it = image_async_decode_state_.find(image_id); |
| 191 DCHECK(it != image_async_decode_state_.end()); | 233 DCHECK(it != image_async_decode_state_.end()); |
| 192 if (it->second != DecodePolicy::ASYNC) | 234 if (it->second.policy != DecodePolicy::ASYNC) |
| 193 continue; | 235 continue; |
| 194 | 236 |
| 237 draw_image = DrawImage(candidate, candidate.sk_image()->bounds(), | |
| 238 it->second.filter_quality, | |
| 239 SkMatrix::MakeScale(it->second.scale.width(), | |
| 240 it->second.scale.height()), | |
| 241 it->second.color_space); | |
| 195 outstanding_image_decode_.emplace(candidate); | 242 outstanding_image_decode_.emplace(candidate); |
| 196 break; | 243 break; |
| 197 } | 244 } |
| 198 | 245 |
| 199 // We either found an image to decode or we reached the end of the queue. If | 246 // We either found an image to decode or we reached the end of the queue. If |
| 200 // we couldn't find an image, we're done. | 247 // we couldn't find an image, we're done. |
| 201 if (!outstanding_image_decode_.has_value()) { | 248 if (!outstanding_image_decode_.has_value()) { |
| 202 DCHECK(image_decode_queue_.empty()); | 249 DCHECK(image_decode_queue_.empty()); |
| 203 return; | 250 return; |
| 204 } | 251 } |
| 205 | 252 |
| 206 PaintImage::Id image_id = outstanding_image_decode_.value().stable_id(); | 253 PaintImage::Id image_id = outstanding_image_decode_.value().stable_id(); |
| 207 DCHECK_EQ(image_id_to_decode_.count(image_id), 0u); | 254 DCHECK_EQ(image_id_to_decode_.count(image_id), 0u); |
| 208 TRACE_EVENT_ASYNC_BEGIN0("cc", "CheckerImageTracker::DeferImageDecode", | 255 TRACE_EVENT_ASYNC_BEGIN0("cc", "CheckerImageTracker::DeferImageDecode", |
| 209 image_id); | 256 image_id); |
| 210 ImageController::ImageDecodeRequestId request_id = | 257 ImageController::ImageDecodeRequestId request_id = |
| 211 image_controller_->QueueImageDecode( | 258 image_controller_->QueueImageDecode( |
| 212 outstanding_image_decode_.value().sk_image(), | 259 draw_image, base::Bind(&CheckerImageTracker::DidFinishImageDecode, |
| 213 base::Bind(&CheckerImageTracker::DidFinishImageDecode, | 260 weak_factory_.GetWeakPtr(), image_id)); |
| 214 weak_factory_.GetWeakPtr(), image_id)); | |
| 215 | 261 |
| 216 image_id_to_decode_.emplace(image_id, base::MakeUnique<ScopedDecodeHolder>( | 262 image_id_to_decode_.emplace(image_id, base::MakeUnique<ScopedDecodeHolder>( |
| 217 image_controller_, request_id)); | 263 image_controller_, request_id)); |
| 218 } | 264 } |
| 219 | 265 |
| 220 } // namespace cc | 266 } // namespace cc |
| OLD | NEW |