Index: cc/tiles/checker_image_tracker.cc |
diff --git a/cc/tiles/checker_image_tracker.cc b/cc/tiles/checker_image_tracker.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f934a2a77f2b44d3cfe6e4596a18587802486930 |
--- /dev/null |
+++ b/cc/tiles/checker_image_tracker.cc |
@@ -0,0 +1,150 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "cc/tiles/checker_image_tracker.h" |
+ |
+#include "base/bind.h" |
+#include "base/trace_event/trace_event.h" |
+ |
+namespace cc { |
+namespace { |
+// The minimum size of an image that we should consider checkering. |
+size_t kMinImageSizeToCheckerBytes = 512 * 1024; |
+} // namespace |
+ |
+CheckerImageTracker::CheckerImageTracker(ImageController* image_controller, |
+ CheckerImageTrackerClient* client, |
+ bool enable_checker_imaging) |
+ : image_controller_(image_controller), |
+ client_(client), |
+ enable_checker_imaging_(enable_checker_imaging), |
+ weak_factory_(this) {} |
+ |
+CheckerImageTracker::~CheckerImageTracker() { |
+ // Unlock all images pending decode requests. |
+ for (auto it : image_id_to_decode_request_id_) |
+ image_controller_->UnlockImageDecode(it.second); |
+} |
+ |
+void CheckerImageTracker::FilterImagesForCheckeringForTile( |
+ std::vector<DrawImage>* images, |
+ std::unordered_set<ImageId>* checkered_images, |
+ WhichTree tree) { |
+ DCHECK(checkered_images->empty()); |
+ |
+ for (std::vector<DrawImage>::iterator it = images->begin(); |
+ it != images->end();) { |
+ const sk_sp<const SkImage> image = it->image(); |
vmpstr
2017/02/10 19:25:42
&
Khushal
2017/02/10 22:09:19
Done.
|
+ DCHECK(image->isLazyGenerated()); |
+ if (ShouldCheckerImage(image, tree)) { |
+ ScheduleImageDecodeIfNecessary(image); |
+ checkered_images->insert(image->uniqueID()); |
+ it = images->erase(it); |
+ } else { |
+ ++it; |
+ } |
+ } |
+} |
+ |
+const std::unordered_set<ImageId>& |
+CheckerImageTracker::TakeImagesToInvalidateOnSyncTree() { |
+ DCHECK(invalidated_images_on_current_sync_tree_.empty()) |
+ << "Sync tree can not be invalidated more than once"; |
+ |
+ invalidated_images_on_current_sync_tree_.swap(images_pending_invalidation_); |
vmpstr
2017/02/10 19:25:42
I think this should be
std::unordered_set<ImageId
Khushal
2017/02/10 22:09:19
But doesn't this unnecessarily create a copy?
|
+ images_pending_invalidation_.clear(); |
+ return invalidated_images_on_current_sync_tree_; |
+} |
+ |
+void CheckerImageTracker::DidActivateSyncTree() { |
+ for (auto image_id : invalidated_images_on_current_sync_tree_) { |
+ auto it = image_id_to_decode_request_id_.find(image_id); |
+ image_controller_->UnlockImageDecode(it->second); |
+ image_id_to_decode_request_id_.erase(it); |
+ } |
+ |
+ invalidated_images_on_current_sync_tree_.clear(); |
+} |
+ |
+void CheckerImageTracker::DidFinishImageDecode( |
+ ImageId image_id, |
+ ImageController::ImageDecodeRequestId request_id) { |
+ TRACE_EVENT_ASYNC_END0("cc", "CheckerImageTracker::DeferImageDecode", |
+ image_id); |
+ |
+ DCHECK_NE(pending_image_decodes_.count(image_id), 0U); |
+ pending_image_decodes_.erase(image_id); |
+ |
+ images_decoded_once_.insert(image_id); |
+ images_pending_invalidation_.insert(image_id); |
+ client_->NeedsInvalidationForCheckerImagedTiles(); |
+} |
+ |
+bool CheckerImageTracker::ShouldCheckerImage(const sk_sp<const SkImage> image, |
vmpstr
2017/02/10 19:25:42
&
Khushal
2017/02/10 22:09:19
Done.
|
+ WhichTree tree) const { |
+ TRACE_EVENT1("cc", "CheckerImageTracker::ShouldCheckerImage", "image_id", |
+ image->uniqueID()); |
+ |
+ if (!enable_checker_imaging_) |
+ return false; |
+ |
+ // If the image was invalidated on the current sync tree and the tile is |
+ // for the active tree, continue checkering it on the active tree to ensure |
+ // the image update is atomic for the frame. |
+ if (invalidated_images_on_current_sync_tree_.count(image->uniqueID()) != 0 && |
+ tree == WhichTree::ACTIVE_TREE) { |
+ return true; |
+ } |
+ |
+ // If a decode request is pending for this image, continue checkering it. |
+ if (pending_image_decodes_.find(image->uniqueID()) != |
+ pending_image_decodes_.end()) { |
+ return true; |
+ } |
+ |
+ // If the image is pending invalidation, continue checkering it. All tiles |
+ // for these images will be invalidated on the next pending tree. |
+ if (images_pending_invalidation_.find(image->uniqueID()) != |
+ images_pending_invalidation_.end()) { |
+ return true; |
+ } |
+ |
+ // If the image has been decoded once before, don't checker it again. |
+ if (images_decoded_once_.find(image->uniqueID()) != |
+ images_decoded_once_.end()) { |
+ return false; |
+ } |
+ |
+ base::CheckedNumeric<size_t> checked_size = 4; |
+ checked_size *= image->width(); |
+ checked_size *= image->height(); |
+ size_t image_size = |
+ checked_size.ValueOrDefault(std::numeric_limits<size_t>::max()); |
+ |
+ bool should_checker_image = image_size >= kMinImageSizeToCheckerBytes; |
vmpstr
2017/02/10 19:25:42
just return image_size >= kMinImageSizeToCheckerBy
Khushal
2017/02/10 22:09:19
Done.
|
+ return should_checker_image; |
+} |
+ |
+void CheckerImageTracker::ScheduleImageDecodeIfNecessary( |
+ const sk_sp<const SkImage> image) { |
+ ImageId image_id = image->uniqueID(); |
+ |
+ // If the image has already been decoded, or a decode request is pending, we |
+ // don't need to schedule another decode. |
+ if (images_decoded_once_.count(image_id) != 0 || |
+ pending_image_decodes_.count(image_id) != 0) |
vmpstr
2017/02/10 19:25:42
braces pls
Khushal
2017/02/10 22:09:19
Done.
|
+ return; |
+ |
+ TRACE_EVENT_ASYNC_BEGIN0("cc", "CheckerImageTracker::DeferImageDecode", |
+ image_id); |
+ DCHECK_EQ(image_id_to_decode_request_id_.count(image_id), 0U); |
+ |
+ image_id_to_decode_request_id_[image_id] = |
+ image_controller_->QueueImageDecode( |
+ image, base::Bind(&CheckerImageTracker::DidFinishImageDecode, |
+ weak_factory_.GetWeakPtr(), image_id)); |
+ pending_image_decodes_.insert(image_id); |
+} |
+ |
+} // namespace cc |