| 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/run_loop.h" | 9 #include "base/run_loop.h" |
| 10 #include "base/threading/thread_task_runner_handle.h" | 10 #include "base/threading/thread_task_runner_handle.h" |
| 11 #include "cc/test/skia_common.h" | 11 #include "cc/test/skia_common.h" |
| 12 #include "cc/tiles/image_controller.h" | 12 #include "cc/tiles/image_controller.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" |
| 14 | 14 |
| 15 namespace cc { | 15 namespace cc { |
| 16 namespace { | 16 namespace { |
| 17 | 17 |
| 18 // 5MB max image cache size. |
| 19 const size_t kMaxImageCacheSizeBytes = 5 * 1024 * 1024; |
| 20 |
| 18 const int kCheckerableImageDimension = 512; | 21 const int kCheckerableImageDimension = 512; |
| 19 const int kNonCheckerableImageDimension = 16; | 22 // This size will result in an image just over kMaxImageCacheSizeBytes. |
| 23 const int kLargeNonCheckerableImageDimension = 1145; |
| 24 const int kSmallNonCheckerableImageDimension = 16; |
| 20 | 25 |
| 21 class TestImageController : public ImageController { | 26 class TestImageController : public ImageController { |
| 22 public: | 27 public: |
| 23 // We can use the same thread for the image worker because all use of it in | 28 // We can use the same thread for the image worker because all use of it in |
| 24 // the ImageController is over-ridden here. | 29 // the ImageController is over-ridden here. |
| 25 TestImageController() | 30 TestImageController() |
| 26 : ImageController(base::ThreadTaskRunnerHandle::Get().get(), | 31 : ImageController(base::ThreadTaskRunnerHandle::Get().get(), |
| 27 base::ThreadTaskRunnerHandle::Get()) {} | 32 base::ThreadTaskRunnerHandle::Get()) { |
| 33 SetMaxImageCacheLimitBytesForTesting(kMaxImageCacheSizeBytes); |
| 34 } |
| 28 | 35 |
| 29 ~TestImageController() override { DCHECK_EQ(locked_images_.size(), 0U); } | 36 ~TestImageController() override { DCHECK_EQ(locked_images_.size(), 0U); } |
| 30 | 37 |
| 31 int num_of_locked_images() const { return locked_images_.size(); } | 38 int num_of_locked_images() const { return locked_images_.size(); } |
| 32 const ImageIdFlatSet& decodes_requested() const { return decodes_requested_; } | 39 const ImageIdFlatSet& decodes_requested() const { return decodes_requested_; } |
| 33 | 40 |
| 34 void UnlockImageDecode(ImageDecodeRequestId id) override { | 41 void UnlockImageDecode(ImageDecodeRequestId id) override { |
| 35 DCHECK_EQ(locked_images_.count(id), 1U); | 42 DCHECK_EQ(locked_images_.count(id), 1U); |
| 36 locked_images_.erase(id); | 43 locked_images_.erase(id); |
| 37 } | 44 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 58 | 65 |
| 59 private: | 66 private: |
| 60 ImageDecodeRequestId next_image_request_id_ = 1U; | 67 ImageDecodeRequestId next_image_request_id_ = 1U; |
| 61 std::unordered_set<ImageDecodeRequestId> locked_images_; | 68 std::unordered_set<ImageDecodeRequestId> locked_images_; |
| 62 ImageIdFlatSet decodes_requested_; | 69 ImageIdFlatSet decodes_requested_; |
| 63 }; | 70 }; |
| 64 | 71 |
| 65 class CheckerImageTrackerTest : public testing::Test, | 72 class CheckerImageTrackerTest : public testing::Test, |
| 66 public CheckerImageTrackerClient { | 73 public CheckerImageTrackerClient { |
| 67 public: | 74 public: |
| 68 enum class ImageType { CHECKERABLE, NON_CHECKERABLE }; | 75 enum class ImageType { |
| 76 CHECKERABLE, |
| 77 SMALL_NON_CHECKERABLE, |
| 78 LARGE_NON_CHECKERABLE |
| 79 }; |
| 69 | 80 |
| 70 void SetUpTracker(bool checker_images_enabled) { | 81 void SetUpTracker(bool checker_images_enabled) { |
| 71 checker_image_tracker_ = base::MakeUnique<CheckerImageTracker>( | 82 checker_image_tracker_ = base::MakeUnique<CheckerImageTracker>( |
| 72 &image_controller_, this, checker_images_enabled); | 83 &image_controller_, this, checker_images_enabled); |
| 73 } | 84 } |
| 74 | 85 |
| 75 void TearDown() override { checker_image_tracker_.reset(); } | 86 void TearDown() override { checker_image_tracker_.reset(); } |
| 76 | 87 |
| 77 DrawImage CreateImage(ImageType image_type) { | 88 DrawImage CreateImage(ImageType image_type) { |
| 78 int dimension = image_type == ImageType::CHECKERABLE | 89 int dimension = 0; |
| 79 ? kCheckerableImageDimension | 90 switch (image_type) { |
| 80 : kNonCheckerableImageDimension; | 91 case ImageType::CHECKERABLE: |
| 92 dimension = kCheckerableImageDimension; |
| 93 break; |
| 94 case ImageType::SMALL_NON_CHECKERABLE: |
| 95 dimension = kSmallNonCheckerableImageDimension; |
| 96 break; |
| 97 case ImageType::LARGE_NON_CHECKERABLE: |
| 98 dimension = kLargeNonCheckerableImageDimension; |
| 99 break; |
| 100 } |
| 101 |
| 81 sk_sp<SkImage> image = | 102 sk_sp<SkImage> image = |
| 82 CreateDiscardableImage(gfx::Size(dimension, dimension)); | 103 CreateDiscardableImage(gfx::Size(dimension, dimension)); |
| 83 gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateSRGB(); | 104 gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateSRGB(); |
| 84 return DrawImage(image, SkIRect::MakeWH(image->width(), image->height()), | 105 return DrawImage(image, SkIRect::MakeWH(image->width(), image->height()), |
| 85 kNone_SkFilterQuality, SkMatrix::I(), target_color_space); | 106 kNone_SkFilterQuality, SkMatrix::I(), target_color_space); |
| 86 } | 107 } |
| 87 | 108 |
| 88 CheckerImageTracker::ImageDecodeQueue BuildImageDecodeQueue( | 109 CheckerImageTracker::ImageDecodeQueue BuildImageDecodeQueue( |
| 89 std::vector<DrawImage> draw_images, | 110 std::vector<DrawImage> draw_images, |
| 90 WhichTree tree) { | 111 WhichTree tree) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 119 EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage( | 140 EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage( |
| 120 draw_image.image(), WhichTree::PENDING_TREE)); | 141 draw_image.image(), WhichTree::PENDING_TREE)); |
| 121 EXPECT_EQ(image_controller_.num_of_locked_images(), 0); | 142 EXPECT_EQ(image_controller_.num_of_locked_images(), 0); |
| 122 } | 143 } |
| 123 | 144 |
| 124 TEST_F(CheckerImageTrackerTest, UpdatesImagesAtomically) { | 145 TEST_F(CheckerImageTrackerTest, UpdatesImagesAtomically) { |
| 125 // Ensures that the tracker updates images atomically for each frame. | 146 // Ensures that the tracker updates images atomically for each frame. |
| 126 SetUpTracker(true); | 147 SetUpTracker(true); |
| 127 | 148 |
| 128 DrawImage checkerable_image = CreateImage(ImageType::CHECKERABLE); | 149 DrawImage checkerable_image = CreateImage(ImageType::CHECKERABLE); |
| 129 DrawImage non_checkerable_image = CreateImage(ImageType::NON_CHECKERABLE); | 150 DrawImage small_non_checkerable_image = |
| 130 std::vector<DrawImage> draw_images; | 151 CreateImage(ImageType::SMALL_NON_CHECKERABLE); |
| 152 DrawImage large_non_checkerable_image = |
| 153 CreateImage(ImageType::LARGE_NON_CHECKERABLE); |
| 131 CheckerImageTracker::ImageDecodeQueue image_decode_queue; | 154 CheckerImageTracker::ImageDecodeQueue image_decode_queue; |
| 132 | 155 |
| 133 // First request to filter images. | 156 // First request to filter images. |
| 134 draw_images.push_back(checkerable_image); | 157 std::vector<DrawImage> draw_images = { |
| 135 draw_images.push_back(non_checkerable_image); | 158 checkerable_image, small_non_checkerable_image, |
| 136 draw_images.push_back(checkerable_image); | 159 large_non_checkerable_image, checkerable_image}; |
| 137 image_decode_queue = | 160 image_decode_queue = |
| 138 BuildImageDecodeQueue(draw_images, WhichTree::PENDING_TREE); | 161 BuildImageDecodeQueue(draw_images, WhichTree::PENDING_TREE); |
| 139 | 162 |
| 140 EXPECT_EQ(image_decode_queue.size(), 2U); | 163 ASSERT_EQ(2u, image_decode_queue.size()); |
| 141 EXPECT_EQ(image_decode_queue[0], checkerable_image.image()); | 164 EXPECT_EQ(checkerable_image.image(), image_decode_queue[0]); |
| 142 EXPECT_EQ(image_decode_queue[1], checkerable_image.image()); | 165 EXPECT_EQ(checkerable_image.image(), image_decode_queue[1]); |
| 143 | 166 |
| 144 checker_image_tracker_->ScheduleImageDecodeQueue(image_decode_queue); | 167 checker_image_tracker_->ScheduleImageDecodeQueue(image_decode_queue); |
| 145 EXPECT_EQ(image_controller_.num_of_locked_images(), 1); | 168 EXPECT_EQ(image_controller_.num_of_locked_images(), 1); |
| 146 | 169 |
| 147 // Run pending task to indicate completion of decode request to the tracker. | 170 // Run pending task to indicate completion of decode request to the tracker. |
| 148 // This should send an impl-side invalidation request to the client. The | 171 // This should send an impl-side invalidation request to the client. The |
| 149 // images must remain locked until the sync tree to which the invalidations | 172 // images must remain locked until the sync tree to which the invalidations |
| 150 // are added is activated. | 173 // are added is activated. |
| 151 base::RunLoop().RunUntilIdle(); | 174 base::RunLoop().RunUntilIdle(); |
| 152 EXPECT_TRUE(invalidation_request_pending_); | 175 EXPECT_TRUE(invalidation_request_pending_); |
| 153 EXPECT_EQ(image_controller_.num_of_locked_images(), 1); | 176 EXPECT_EQ(image_controller_.num_of_locked_images(), 1); |
| 154 | 177 |
| 155 // Continue checkering the image until the set of images to invalidate is | 178 // Continue checkering the image until the set of images to invalidate is |
| 156 // pulled. | 179 // pulled. |
| 157 EXPECT_TRUE(checker_image_tracker_->ShouldCheckerImage( | 180 EXPECT_TRUE(checker_image_tracker_->ShouldCheckerImage( |
| 158 checkerable_image.image(), WhichTree::PENDING_TREE)); | 181 checkerable_image.image(), WhichTree::PENDING_TREE)); |
| 159 | 182 |
| 160 ImageIdFlatSet invalidated_images = | 183 ImageIdFlatSet invalidated_images = |
| 161 checker_image_tracker_->TakeImagesToInvalidateOnSyncTree(); | 184 checker_image_tracker_->TakeImagesToInvalidateOnSyncTree(); |
| 162 EXPECT_EQ(invalidated_images.size(), 1U); | 185 EXPECT_EQ(invalidated_images.size(), 1U); |
| 163 EXPECT_EQ(invalidated_images.count(checkerable_image.image()->uniqueID()), | 186 EXPECT_EQ(invalidated_images.count(checkerable_image.image()->uniqueID()), |
| 164 1U); | 187 1U); |
| 165 | 188 |
| 166 // Use the same set of draw images to ensure that they are not checkered on | 189 // Use the same set of draw images to ensure that they are not checkered on |
| 167 // the pending tree now. | 190 // the pending tree now. |
| 168 EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage( | 191 EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage( |
| 169 checkerable_image.image(), WhichTree::PENDING_TREE)); | 192 checkerable_image.image(), WhichTree::PENDING_TREE)); |
| 170 EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage( | 193 EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage( |
| 171 non_checkerable_image.image(), WhichTree::PENDING_TREE)); | 194 small_non_checkerable_image.image(), WhichTree::PENDING_TREE)); |
| 195 EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage( |
| 196 large_non_checkerable_image.image(), WhichTree::PENDING_TREE)); |
| 172 | 197 |
| 173 // Use this set to make the same request from the active tree, we should | 198 // Use this set to make the same request from the active tree, we should |
| 174 // continue checkering this image on the active tree until activation. | 199 // continue checkering this image on the active tree until activation. |
| 175 EXPECT_TRUE(checker_image_tracker_->ShouldCheckerImage( | 200 EXPECT_TRUE(checker_image_tracker_->ShouldCheckerImage( |
| 176 checkerable_image.image(), WhichTree::ACTIVE_TREE)); | 201 checkerable_image.image(), WhichTree::ACTIVE_TREE)); |
| 177 EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage( | 202 EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage( |
| 178 non_checkerable_image.image(), WhichTree::ACTIVE_TREE)); | 203 small_non_checkerable_image.image(), WhichTree::ACTIVE_TREE)); |
| 204 EXPECT_FALSE(checker_image_tracker_->ShouldCheckerImage( |
| 205 large_non_checkerable_image.image(), WhichTree::ACTIVE_TREE)); |
| 179 | 206 |
| 180 // Activate the sync tree. The images should be unlocked upon activation. | 207 // Activate the sync tree. The images should be unlocked upon activation. |
| 181 EXPECT_EQ(image_controller_.num_of_locked_images(), 1); | 208 EXPECT_EQ(image_controller_.num_of_locked_images(), 1); |
| 182 checker_image_tracker_->DidActivateSyncTree(); | 209 checker_image_tracker_->DidActivateSyncTree(); |
| 183 } | 210 } |
| 184 | 211 |
| 185 TEST_F(CheckerImageTrackerTest, NoConsecutiveCheckeringForImage) { | 212 TEST_F(CheckerImageTrackerTest, NoConsecutiveCheckeringForImage) { |
| 186 // Ensures that if an image is decoded and invalidated once, it is not | 213 // Ensures that if an image is decoded and invalidated once, it is not |
| 187 // checkered again in subsequent frames. | 214 // checkered again in subsequent frames. |
| 188 SetUpTracker(true); | 215 SetUpTracker(true); |
| 189 | 216 |
| 190 DrawImage checkerable_image = CreateImage(ImageType::CHECKERABLE); | 217 DrawImage checkerable_image = CreateImage(ImageType::CHECKERABLE); |
| 191 DrawImage non_checkerable_image = CreateImage(ImageType::NON_CHECKERABLE); | 218 std::vector<DrawImage> draw_images = {checkerable_image}; |
| 192 std::vector<DrawImage> draw_images; | |
| 193 | 219 |
| 194 draw_images.clear(); | |
| 195 draw_images.push_back(checkerable_image); | |
| 196 CheckerImageTracker::ImageDecodeQueue image_decode_queue = | 220 CheckerImageTracker::ImageDecodeQueue image_decode_queue = |
| 197 BuildImageDecodeQueue(draw_images, WhichTree::PENDING_TREE); | 221 BuildImageDecodeQueue(draw_images, WhichTree::PENDING_TREE); |
| 198 EXPECT_EQ(image_decode_queue.size(), 1U); | 222 EXPECT_EQ(image_decode_queue.size(), 1U); |
| 199 checker_image_tracker_->ScheduleImageDecodeQueue(image_decode_queue); | 223 checker_image_tracker_->ScheduleImageDecodeQueue(image_decode_queue); |
| 200 | 224 |
| 201 // Trigger decode completion, take images to invalidate and activate the sync | 225 // Trigger decode completion, take images to invalidate and activate the sync |
| 202 // tree. | 226 // tree. |
| 203 base::RunLoop().RunUntilIdle(); | 227 base::RunLoop().RunUntilIdle(); |
| 204 checker_image_tracker_->TakeImagesToInvalidateOnSyncTree(); | 228 checker_image_tracker_->TakeImagesToInvalidateOnSyncTree(); |
| 205 checker_image_tracker_->DidActivateSyncTree(); | 229 checker_image_tracker_->DidActivateSyncTree(); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 base::RunLoop().RunUntilIdle(); | 327 base::RunLoop().RunUntilIdle(); |
| 304 EXPECT_EQ(image_controller_.decodes_requested().size(), 2U); | 328 EXPECT_EQ(image_controller_.decodes_requested().size(), 2U); |
| 305 EXPECT_EQ(image_controller_.decodes_requested().count( | 329 EXPECT_EQ(image_controller_.decodes_requested().count( |
| 306 checkerable_image3.image()->uniqueID()), | 330 checkerable_image3.image()->uniqueID()), |
| 307 1U); | 331 1U); |
| 308 EXPECT_EQ(image_controller_.num_of_locked_images(), 2); | 332 EXPECT_EQ(image_controller_.num_of_locked_images(), 2); |
| 309 } | 333 } |
| 310 | 334 |
| 311 } // namespace | 335 } // namespace |
| 312 } // namespace cc | 336 } // namespace cc |
| OLD | NEW |