| 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 28 matching lines...) Expand all Loading... |
| 39 "CheckerImageTracker::ScheduleImageDecodeQueue"); | 39 "CheckerImageTracker::ScheduleImageDecodeQueue"); |
| 40 // Only checker-imaged (async updated) images are decoded using the image | 40 // Only checker-imaged (async updated) images are decoded using the image |
| 41 // decode service. If |enable_checker_imaging_| is false, no image should | 41 // decode service. If |enable_checker_imaging_| is false, no image should |
| 42 // be checkered. | 42 // be checkered. |
| 43 DCHECK(image_decode_queue.empty() || enable_checker_imaging_); | 43 DCHECK(image_decode_queue.empty() || enable_checker_imaging_); |
| 44 | 44 |
| 45 image_decode_queue_ = std::move(image_decode_queue); | 45 image_decode_queue_ = std::move(image_decode_queue); |
| 46 ScheduleNextImageDecode(); | 46 ScheduleNextImageDecode(); |
| 47 } | 47 } |
| 48 | 48 |
| 49 const ImageIdFlatSet& CheckerImageTracker::TakeImagesToInvalidateOnSyncTree() { | 49 const PaintImageIdFlatSet& |
| 50 CheckerImageTracker::TakeImagesToInvalidateOnSyncTree() { |
| 50 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 51 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
| 51 "CheckerImageTracker::TakeImagesToInvalidateOnSyncTree"); | 52 "CheckerImageTracker::TakeImagesToInvalidateOnSyncTree"); |
| 52 DCHECK_EQ(invalidated_images_on_current_sync_tree_.size(), 0u) | 53 DCHECK_EQ(invalidated_images_on_current_sync_tree_.size(), 0u) |
| 53 << "Sync tree can not be invalidated more than once"; | 54 << "Sync tree can not be invalidated more than once"; |
| 54 | 55 |
| 55 invalidated_images_on_current_sync_tree_.swap(images_pending_invalidation_); | 56 invalidated_images_on_current_sync_tree_.swap(images_pending_invalidation_); |
| 56 images_pending_invalidation_.clear(); | 57 images_pending_invalidation_.clear(); |
| 57 return invalidated_images_on_current_sync_tree_; | 58 return invalidated_images_on_current_sync_tree_; |
| 58 } | 59 } |
| 59 | 60 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 DCHECK(it != image_async_decode_state_.end()); | 92 DCHECK(it != image_async_decode_state_.end()); |
| 92 DCHECK_EQ(it->second, DecodePolicy::SYNC_DECODED_ONCE); | 93 DCHECK_EQ(it->second, DecodePolicy::SYNC_DECODED_ONCE); |
| 93 | 94 |
| 94 it->second = DecodePolicy::ASYNC; | 95 it->second = DecodePolicy::ASYNC; |
| 95 } | 96 } |
| 96 } | 97 } |
| 97 images_pending_invalidation_.clear(); | 98 images_pending_invalidation_.clear(); |
| 98 } | 99 } |
| 99 | 100 |
| 100 void CheckerImageTracker::DidFinishImageDecode( | 101 void CheckerImageTracker::DidFinishImageDecode( |
| 101 ImageId image_id, | 102 PaintImage::Id image_id, |
| 102 ImageController::ImageDecodeRequestId request_id, | 103 ImageController::ImageDecodeRequestId request_id, |
| 103 ImageController::ImageDecodeResult result) { | 104 ImageController::ImageDecodeResult result) { |
| 104 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 105 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
| 105 "CheckerImageTracker::DidFinishImageDecode"); | 106 "CheckerImageTracker::DidFinishImageDecode"); |
| 106 TRACE_EVENT_ASYNC_END0("cc", "CheckerImageTracker::DeferImageDecode", | 107 TRACE_EVENT_ASYNC_END0("cc", "CheckerImageTracker::DeferImageDecode", |
| 107 image_id); | 108 image_id); |
| 108 | 109 |
| 109 DCHECK_NE(ImageController::ImageDecodeResult::DECODE_NOT_REQUIRED, result); | 110 DCHECK_NE(ImageController::ImageDecodeResult::DECODE_NOT_REQUIRED, result); |
| 110 DCHECK_EQ(outstanding_image_decode_->uniqueID(), image_id); | 111 DCHECK_EQ(outstanding_image_decode_.value().stable_id(), image_id); |
| 111 outstanding_image_decode_ = nullptr; | 112 outstanding_image_decode_.reset(); |
| 112 | 113 |
| 113 // 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 |
| 114 // before this decode could be finished. | 115 // before this decode could be finished. |
| 115 auto it = image_async_decode_state_.find(image_id); | 116 auto it = image_async_decode_state_.find(image_id); |
| 116 if (it == image_async_decode_state_.end()) { | 117 if (it == image_async_decode_state_.end()) { |
| 117 DCHECK_EQ(image_id_to_decode_.count(image_id), 0u); | 118 DCHECK_EQ(image_id_to_decode_.count(image_id), 0u); |
| 118 return; | 119 return; |
| 119 } | 120 } |
| 120 | 121 |
| 121 it->second = DecodePolicy::SYNC_DECODED_ONCE; | 122 it->second = DecodePolicy::SYNC_DECODED_ONCE; |
| 122 images_pending_invalidation_.insert(image_id); | 123 images_pending_invalidation_.insert(image_id); |
| 123 ScheduleNextImageDecode(); | 124 ScheduleNextImageDecode(); |
| 124 client_->NeedsInvalidationForCheckerImagedTiles(); | 125 client_->NeedsInvalidationForCheckerImagedTiles(); |
| 125 } | 126 } |
| 126 | 127 |
| 127 bool CheckerImageTracker::ShouldCheckerImage(const sk_sp<const SkImage>& image, | 128 bool CheckerImageTracker::ShouldCheckerImage(const PaintImage& image, |
| 128 WhichTree tree) { | 129 WhichTree tree) { |
| 129 TRACE_EVENT1("cc", "CheckerImageTracker::ShouldCheckerImage", "image_id", | 130 TRACE_EVENT1("cc", "CheckerImageTracker::ShouldCheckerImage", "image_id", |
| 130 image->uniqueID()); | 131 image.stable_id()); |
| 131 | 132 |
| 132 if (!enable_checker_imaging_) | 133 if (!enable_checker_imaging_) |
| 133 return false; | 134 return false; |
| 134 | 135 |
| 136 PaintImage::Id image_id = image.stable_id(); |
| 137 |
| 135 // 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 |
| 136 // 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 |
| 137 // the image update is atomic for the frame. | 140 // the image update is atomic for the frame. |
| 138 if (invalidated_images_on_current_sync_tree_.count(image->uniqueID()) != 0 && | 141 if (invalidated_images_on_current_sync_tree_.count(image_id) != 0 && |
| 139 tree == WhichTree::ACTIVE_TREE) { | 142 tree == WhichTree::ACTIVE_TREE) { |
| 140 return true; | 143 return true; |
| 141 } | 144 } |
| 142 | 145 |
| 143 // If the image is pending invalidation, continue checkering it. All tiles | 146 // If the image is pending invalidation, continue checkering it. All tiles |
| 144 // for these images will be invalidated on the next pending tree. | 147 // for these images will be invalidated on the next pending tree. |
| 145 if (images_pending_invalidation_.find(image->uniqueID()) != | 148 if (images_pending_invalidation_.find(image_id) != |
| 146 images_pending_invalidation_.end()) { | 149 images_pending_invalidation_.end()) { |
| 147 return true; | 150 return true; |
| 148 } | 151 } |
| 149 | 152 |
| 150 ImageId image_id = image->uniqueID(); | 153 auto insert_result = |
| 151 auto insert_result = image_async_decode_state_.insert( | 154 image_async_decode_state_.insert(std::pair<PaintImage::Id, DecodePolicy>( |
| 152 std::pair<ImageId, DecodePolicy>(image_id, DecodePolicy::ASYNC)); | 155 image_id, DecodePolicy::SYNC_PERMANENT)); |
| 153 auto it = insert_result.first; | 156 auto it = insert_result.first; |
| 154 if (insert_result.second) { | 157 if (insert_result.second) { |
| 155 size_t size = SafeSizeOfImage(image.get()); | 158 bool can_checker_image = |
| 156 it->second = (size >= kMinImageSizeToCheckerBytes && | 159 image.animation_type() == PaintImage::AnimationType::STATIC && |
| 157 size <= image_controller_->image_cache_max_limit_bytes()) | 160 image.completion_state() == PaintImage::CompletionState::DONE; |
| 158 ? DecodePolicy::ASYNC | 161 if (can_checker_image) { |
| 159 : DecodePolicy::SYNC_PERMANENT; | 162 size_t size = SafeSizeOfImage(image.sk_image().get()); |
| 163 it->second = (size >= kMinImageSizeToCheckerBytes && |
| 164 size <= image_controller_->image_cache_max_limit_bytes()) |
| 165 ? DecodePolicy::ASYNC |
| 166 : DecodePolicy::SYNC_PERMANENT; |
| 167 } |
| 160 } | 168 } |
| 161 | 169 |
| 162 return it->second == DecodePolicy::ASYNC; | 170 return it->second == DecodePolicy::ASYNC; |
| 163 } | 171 } |
| 164 | 172 |
| 165 void CheckerImageTracker::ScheduleNextImageDecode() { | 173 void CheckerImageTracker::ScheduleNextImageDecode() { |
| 166 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 174 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
| 167 "CheckerImageTracker::ScheduleNextImageDecode"); | 175 "CheckerImageTracker::ScheduleNextImageDecode"); |
| 168 // We can have only one outsanding decode pending completion with the decode | 176 // We can have only one outsanding decode pending completion with the decode |
| 169 // service. We'll come back here when it is completed. | 177 // service. We'll come back here when it is completed. |
| 170 if (outstanding_image_decode_) | 178 if (outstanding_image_decode_.has_value()) |
| 171 return; | 179 return; |
| 172 | 180 |
| 173 while (!image_decode_queue_.empty()) { | 181 while (!image_decode_queue_.empty()) { |
| 174 auto candidate = std::move(image_decode_queue_.front()); | 182 auto candidate = std::move(image_decode_queue_.front()); |
| 175 image_decode_queue_.erase(image_decode_queue_.begin()); | 183 image_decode_queue_.erase(image_decode_queue_.begin()); |
| 176 | 184 |
| 177 // Once an image has been decoded, it can still be present in the decode | 185 // Once an image has been decoded, it can still be present in the decode |
| 178 // queue (duplicate entries), or while an image is still being skipped on | 186 // queue (duplicate entries), or while an image is still being skipped on |
| 179 // the active tree. Check if the image is still ASYNC to see if a decode is | 187 // the active tree. Check if the image is still ASYNC to see if a decode is |
| 180 // needed. | 188 // needed. |
| 181 ImageId image_id = candidate->uniqueID(); | 189 PaintImage::Id image_id = candidate.stable_id(); |
| 182 auto it = image_async_decode_state_.find(image_id); | 190 auto it = image_async_decode_state_.find(image_id); |
| 183 DCHECK(it != image_async_decode_state_.end()); | 191 DCHECK(it != image_async_decode_state_.end()); |
| 184 if (it->second != DecodePolicy::ASYNC) | 192 if (it->second != DecodePolicy::ASYNC) |
| 185 continue; | 193 continue; |
| 186 | 194 |
| 187 outstanding_image_decode_ = std::move(candidate); | 195 outstanding_image_decode_.emplace(candidate); |
| 188 break; | 196 break; |
| 189 } | 197 } |
| 190 | 198 |
| 191 // We either found an image to decode or we reached the end of the queue. If | 199 // We either found an image to decode or we reached the end of the queue. If |
| 192 // we couldn't find an image, we're done. | 200 // we couldn't find an image, we're done. |
| 193 if (!outstanding_image_decode_) { | 201 if (!outstanding_image_decode_.has_value()) { |
| 194 DCHECK(image_decode_queue_.empty()); | 202 DCHECK(image_decode_queue_.empty()); |
| 195 return; | 203 return; |
| 196 } | 204 } |
| 197 | 205 |
| 198 ImageId image_id = outstanding_image_decode_->uniqueID(); | 206 PaintImage::Id image_id = outstanding_image_decode_.value().stable_id(); |
| 199 DCHECK_EQ(image_id_to_decode_.count(image_id), 0u); | 207 DCHECK_EQ(image_id_to_decode_.count(image_id), 0u); |
| 200 TRACE_EVENT_ASYNC_BEGIN0("cc", "CheckerImageTracker::DeferImageDecode", | 208 TRACE_EVENT_ASYNC_BEGIN0("cc", "CheckerImageTracker::DeferImageDecode", |
| 201 image_id); | 209 image_id); |
| 202 ImageController::ImageDecodeRequestId request_id = | 210 ImageController::ImageDecodeRequestId request_id = |
| 203 image_controller_->QueueImageDecode( | 211 image_controller_->QueueImageDecode( |
| 204 outstanding_image_decode_, | 212 outstanding_image_decode_.value().sk_image(), |
| 205 base::Bind(&CheckerImageTracker::DidFinishImageDecode, | 213 base::Bind(&CheckerImageTracker::DidFinishImageDecode, |
| 206 weak_factory_.GetWeakPtr(), image_id)); | 214 weak_factory_.GetWeakPtr(), image_id)); |
| 207 | 215 |
| 208 image_id_to_decode_.emplace(image_id, base::MakeUnique<ScopedDecodeHolder>( | 216 image_id_to_decode_.emplace(image_id, base::MakeUnique<ScopedDecodeHolder>( |
| 209 image_controller_, request_id)); | 217 image_controller_, request_id)); |
| 210 } | 218 } |
| 211 | 219 |
| 212 } // namespace cc | 220 } // namespace cc |
| OLD | NEW |