Chromium Code Reviews| 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 |