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