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/stl_util.h" | 9 #include "base/stl_util.h" |
| 9 #include "base/trace_event/trace_event.h" | 10 #include "base/trace_event/trace_event.h" |
| 10 | 11 |
| 11 namespace cc { | 12 namespace cc { |
| 12 namespace { | 13 namespace { |
| 13 // The minimum size of an image that we should consider checkering. | 14 // The minimum size of an image that we should consider checkering. |
| 14 size_t kMinImageSizeToCheckerBytes = 512 * 1024; | 15 size_t kMinImageSizeToCheckerBytes = 512 * 1024; |
| 15 | 16 |
| 16 size_t SafeSizeOfImage(const SkImage* image) { | 17 size_t SafeSizeOfImage(const SkImage* image) { |
| 17 base::CheckedNumeric<size_t> checked_size = 4; | 18 base::CheckedNumeric<size_t> checked_size = 4; |
| 18 checked_size *= image->width(); | 19 checked_size *= image->width(); |
| 19 checked_size *= image->height(); | 20 checked_size *= image->height(); |
| 20 return checked_size.ValueOrDefault(std::numeric_limits<size_t>::max()); | 21 return checked_size.ValueOrDefault(std::numeric_limits<size_t>::max()); |
| 21 } | 22 } |
| 22 | 23 |
| 23 } // namespace | 24 } // namespace |
| 24 | 25 |
| 25 CheckerImageTracker::CheckerImageTracker(ImageController* image_controller, | 26 CheckerImageTracker::CheckerImageTracker(ImageController* image_controller, |
| 26 CheckerImageTrackerClient* client, | 27 CheckerImageTrackerClient* client, |
| 27 bool enable_checker_imaging) | 28 bool enable_checker_imaging) |
| 28 : image_controller_(image_controller), | 29 : image_controller_(image_controller), |
| 29 client_(client), | 30 client_(client), |
| 30 enable_checker_imaging_(enable_checker_imaging), | 31 enable_checker_imaging_(enable_checker_imaging), |
| 31 weak_factory_(this) {} | 32 weak_factory_(this) {} |
| 32 | 33 |
| 33 CheckerImageTracker::~CheckerImageTracker() { | 34 CheckerImageTracker::~CheckerImageTracker() = default; |
| 34 // Unlock all images pending decode requests. | |
| 35 for (auto it : image_id_to_decode_request_id_) | |
| 36 image_controller_->UnlockImageDecode(it.second); | |
| 37 } | |
| 38 | 35 |
| 39 void CheckerImageTracker::ScheduleImageDecodeQueue( | 36 void CheckerImageTracker::ScheduleImageDecodeQueue( |
| 40 ImageDecodeQueue image_decode_queue) { | 37 ImageDecodeQueue image_decode_queue) { |
| 41 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 38 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
| 42 "CheckerImageTracker::ScheduleImageDecodeQueue"); | 39 "CheckerImageTracker::ScheduleImageDecodeQueue"); |
| 43 // Only checker-imaged (async updated) images are decoded using the image | 40 // Only checker-imaged (async updated) images are decoded using the image |
| 44 // decode service. If |enable_checker_imaging_| is false, no image should | 41 // decode service. If |enable_checker_imaging_| is false, no image should |
| 45 // be checkered. | 42 // be checkered. |
| 46 DCHECK(image_decode_queue.empty() || enable_checker_imaging_); | 43 DCHECK(image_decode_queue.empty() || enable_checker_imaging_); |
| 47 | 44 |
| 48 image_decode_queue_ = std::move(image_decode_queue); | 45 image_decode_queue_ = std::move(image_decode_queue); |
| 49 ScheduleNextImageDecode(); | 46 ScheduleNextImageDecode(); |
| 50 } | 47 } |
| 51 | 48 |
| 52 const ImageIdFlatSet& CheckerImageTracker::TakeImagesToInvalidateOnSyncTree() { | 49 const ImageIdFlatSet& CheckerImageTracker::TakeImagesToInvalidateOnSyncTree() { |
| 53 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 50 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
| 54 "CheckerImageTracker::TakeImagesToInvalidateOnSyncTree"); | 51 "CheckerImageTracker::TakeImagesToInvalidateOnSyncTree"); |
| 55 DCHECK_EQ(invalidated_images_on_current_sync_tree_.size(), 0u) | 52 DCHECK_EQ(invalidated_images_on_current_sync_tree_.size(), 0u) |
| 56 << "Sync tree can not be invalidated more than once"; | 53 << "Sync tree can not be invalidated more than once"; |
| 57 | 54 |
| 58 invalidated_images_on_current_sync_tree_.swap(images_pending_invalidation_); | 55 invalidated_images_on_current_sync_tree_.swap(images_pending_invalidation_); |
| 59 images_pending_invalidation_.clear(); | 56 images_pending_invalidation_.clear(); |
| 60 return invalidated_images_on_current_sync_tree_; | 57 return invalidated_images_on_current_sync_tree_; |
| 61 } | 58 } |
| 62 | 59 |
| 63 void CheckerImageTracker::DidActivateSyncTree() { | 60 void CheckerImageTracker::DidActivateSyncTree() { |
| 64 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 61 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
| 65 "CheckerImageTracker::DidActivateSyncTree"); | 62 "CheckerImageTracker::DidActivateSyncTree"); |
| 66 for (auto image_id : invalidated_images_on_current_sync_tree_) { | 63 for (auto image_id : invalidated_images_on_current_sync_tree_) |
| 67 auto it = image_id_to_decode_request_id_.find(image_id); | 64 image_id_to_decode_.erase(image_id); |
| 68 image_controller_->UnlockImageDecode(it->second); | 65 invalidated_images_on_current_sync_tree_.clear(); |
| 69 image_id_to_decode_request_id_.erase(it); | 66 } |
| 67 | |
| 68 void CheckerImageTracker::ClearTracker(bool can_clear_decode_policy_tracking) { | |
| 69 // Unlock all images and tracking for images pending invalidation. The | |
| 70 // |images_invalidated_on_current_sync_tree_| will be cleared when the sync | |
| 71 // tree is activated. | |
| 72 // | |
| 73 // Note that we assume that any images with DecodePolicy::ASYNC, which may be | |
| 74 // checkered, are safe to stop tracking here and will either be re-checkered | |
| 75 // and invalidated when the decode completes or be invalidated externally. | |
| 76 // This is because the policy decision for checkering an image is based on | |
| 77 // inputs received from a PaintImage in the DisplayItemList. The policy chosen | |
| 78 // for a PaintImage should remain unchanged. | |
| 79 // If the external inputs for deciding the decode policy for an image change, | |
| 80 // they should be accompanied with an invalidation during paint. | |
| 81 image_id_to_decode_.clear(); | |
| 82 | |
| 83 if (can_clear_decode_policy_tracking) { | |
| 84 image_async_decode_state_.clear(); | |
| 85 } else { | |
| 86 // If we can't clear the decode policy, we need to make sure we still | |
| 87 // re-decode and checker images that were pending invalidation. | |
| 88 for (auto image_id : images_pending_invalidation_) { | |
|
Khushal
2017/05/13 03:24:43
Realized I was missing this case. I've added a tes
| |
| 89 auto it = image_async_decode_state_.find(image_id); | |
| 90 | |
| 91 DCHECK(it != image_async_decode_state_.end()); | |
| 92 DCHECK_EQ(it->second, DecodePolicy::SYNC_DECODED_ONCE); | |
| 93 | |
| 94 it->second = DecodePolicy::ASYNC; | |
| 95 } | |
| 70 } | 96 } |
| 71 | 97 images_pending_invalidation_.clear(); |
| 72 invalidated_images_on_current_sync_tree_.clear(); | |
| 73 } | 98 } |
| 74 | 99 |
| 75 void CheckerImageTracker::DidFinishImageDecode( | 100 void CheckerImageTracker::DidFinishImageDecode( |
| 76 ImageId image_id, | 101 ImageId image_id, |
| 77 ImageController::ImageDecodeRequestId request_id, | 102 ImageController::ImageDecodeRequestId request_id, |
| 78 ImageController::ImageDecodeResult result) { | 103 ImageController::ImageDecodeResult result) { |
| 79 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 104 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
| 80 "CheckerImageTracker::DidFinishImageDecode"); | 105 "CheckerImageTracker::DidFinishImageDecode"); |
| 81 TRACE_EVENT_ASYNC_END0("cc", "CheckerImageTracker::DeferImageDecode", | 106 TRACE_EVENT_ASYNC_END0("cc", "CheckerImageTracker::DeferImageDecode", |
| 82 image_id); | 107 image_id); |
| 83 | 108 |
| 84 DCHECK_NE(ImageController::ImageDecodeResult::DECODE_NOT_REQUIRED, result); | 109 DCHECK_NE(ImageController::ImageDecodeResult::DECODE_NOT_REQUIRED, result); |
| 85 DCHECK_EQ(outstanding_image_decode_->uniqueID(), image_id); | 110 DCHECK_EQ(outstanding_image_decode_->uniqueID(), image_id); |
| 111 outstanding_image_decode_ = nullptr; | |
| 86 | 112 |
| 87 outstanding_image_decode_ = nullptr; | 113 // The async decode state may have been cleared if the tracker was cleared |
| 88 image_async_decode_state_[image_id] = DecodePolicy::SYNC_DECODED_ONCE; | 114 // before this decode could be finished. |
| 115 auto it = image_async_decode_state_.find(image_id); | |
| 116 if (it == image_async_decode_state_.end()) { | |
| 117 DCHECK_EQ(image_id_to_decode_.count(image_id), 0u); | |
| 118 return; | |
| 119 } | |
| 120 | |
| 121 it->second = DecodePolicy::SYNC_DECODED_ONCE; | |
| 89 images_pending_invalidation_.insert(image_id); | 122 images_pending_invalidation_.insert(image_id); |
| 90 | |
| 91 ScheduleNextImageDecode(); | 123 ScheduleNextImageDecode(); |
| 92 client_->NeedsInvalidationForCheckerImagedTiles(); | 124 client_->NeedsInvalidationForCheckerImagedTiles(); |
| 93 } | 125 } |
| 94 | 126 |
| 95 bool CheckerImageTracker::ShouldCheckerImage(const sk_sp<const SkImage>& image, | 127 bool CheckerImageTracker::ShouldCheckerImage(const sk_sp<const SkImage>& image, |
| 96 WhichTree tree) { | 128 WhichTree tree) { |
| 97 TRACE_EVENT1("cc", "CheckerImageTracker::ShouldCheckerImage", "image_id", | 129 TRACE_EVENT1("cc", "CheckerImageTracker::ShouldCheckerImage", "image_id", |
| 98 image->uniqueID()); | 130 image->uniqueID()); |
| 99 | 131 |
| 100 if (!enable_checker_imaging_) | 132 if (!enable_checker_imaging_) |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 157 } | 189 } |
| 158 | 190 |
| 159 // We either found an image to decode or we reached the end of the queue. If | 191 // We either found an image to decode or we reached the end of the queue. If |
| 160 // we couldn't find an image, we're done. | 192 // we couldn't find an image, we're done. |
| 161 if (!outstanding_image_decode_) { | 193 if (!outstanding_image_decode_) { |
| 162 DCHECK(image_decode_queue_.empty()); | 194 DCHECK(image_decode_queue_.empty()); |
| 163 return; | 195 return; |
| 164 } | 196 } |
| 165 | 197 |
| 166 ImageId image_id = outstanding_image_decode_->uniqueID(); | 198 ImageId image_id = outstanding_image_decode_->uniqueID(); |
| 167 DCHECK_EQ(image_id_to_decode_request_id_.count(image_id), 0u); | 199 DCHECK_EQ(image_id_to_decode_.count(image_id), 0u); |
| 168 TRACE_EVENT_ASYNC_BEGIN0("cc", "CheckerImageTracker::DeferImageDecode", | 200 TRACE_EVENT_ASYNC_BEGIN0("cc", "CheckerImageTracker::DeferImageDecode", |
| 169 image_id); | 201 image_id); |
| 170 image_id_to_decode_request_id_[image_id] = | 202 ImageController::ImageDecodeRequestId request_id = |
| 171 image_controller_->QueueImageDecode( | 203 image_controller_->QueueImageDecode( |
| 172 outstanding_image_decode_, | 204 outstanding_image_decode_, |
| 173 base::Bind(&CheckerImageTracker::DidFinishImageDecode, | 205 base::Bind(&CheckerImageTracker::DidFinishImageDecode, |
| 174 weak_factory_.GetWeakPtr(), image_id)); | 206 weak_factory_.GetWeakPtr(), image_id)); |
| 207 | |
| 208 image_id_to_decode_.emplace(image_id, base::MakeUnique<ScopedDecodeHolder>( | |
| 209 image_controller_, request_id)); | |
| 175 } | 210 } |
| 176 | 211 |
| 177 } // namespace cc | 212 } // namespace cc |
| OLD | NEW |