1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 28 #include "core/platform/graphics/chromium/ImageDecodingStore.h" 29 30 #include "core/platform/SharedBuffer.h" 31 #include "core/platform/graphics/chromium/ImageFrameGenerator.h" 32 #include "core/platform/graphics/chromium/test/MockDiscardablePixelRef.h" 33 #include "core/platform/graphics/chromium/test/MockImageDecoder.h" 34 #include <gtest/gtest.h> 35 36 using namespace WebCore; 37 38 namespace { 39 40 class ImageDecodingStoreTest : public ::testing::Test, public MockImageDecoderClient { 41 public: 42 virtual void SetUp() 43 { 44 ImageDecodingStore::initializeOnce(); 45 m_data = SharedBuffer::create(); 46 m_generator = ImageFrameGenerator::create(SkISize::Make(100, 100), m_data, true); 47 m_decodersDestroyed = 0; 48 } 49 50 virtual void TearDown() 51 { 52 ImageDecodingStore::shutdown(); 53 } 54 55 virtual void decoderBeingDestroyed() 56 { 57 ++m_decodersDestroyed; 58 } 59 60 virtual void frameBufferRequested() 61 { 62 // Decoder is never used by ImageDecodingStore. 63 ASSERT_TRUE(false); 64 } 65 66 virtual ImageFrame::FrameStatus frameStatus() 67 { 68 return ImageFrame::FramePartial; 69 } 70 71 virtual size_t frameCount() { return 1; } 72 virtual int repetitionCount() const { return cAnimationNone; } 73 virtual float frameDuration() const { return 0; } 74 75 protected: 76 PassOwnPtr<ScaledImageFragment> createCompleteImage(const SkISize& size, bool discardable = false, size_t index = 0) 77 { 78 SkBitmap bitmap; 79 bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height()); 80 if (!discardable) 81 bitmap.allocPixels(); 82 else 83 bitmap.setPixelRef(new MockDiscardablePixelRef())->unref(); 84 return ScaledImageFragment::createComplete(size, index, bitmap); 85 } 86 87 PassOwnPtr<ScaledImageFragment> createIncompleteImage(const SkISize& size, bool discardable = false, size_t generation = 0) 88 { 89 SkBitmap bitmap; 90 bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height()); 91 if (!discardable) 92 bitmap.allocPixels(); 93 else 94 bitmap.setPixelRef(new MockDiscardablePixelRef())->unref(); 95 return ScaledImageFragment::createPartial(size, 0, generation, bitmap); 96 } 97 98 void insertCache(const SkISize& size) 99 { 100 const ScaledImageFragment* image = ImageDecodingStore::instance()->insertAndLockCache( 101 m_generator.get(), createCompleteImage(size)); 102 unlockCache(image); 103 } 104 105 const ScaledImageFragment* lockCache(const SkISize& size, size_t index = 0) 106 { 107 const ScaledImageFragment* cachedImage = 0; 108 if (ImageDecodingStore::instance()->lockCache(m_generator.get(), size, index, &cachedImage)) 109 return cachedImage; 110 return 0; 111 } 112 113 void unlockCache(const ScaledImageFragment* cachedImage) 114 { 115 ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage); 116 } 117 118 void evictOneCache() 119 { 120 size_t memoryUsageInBytes = ImageDecodingStore::instance()->memoryUsageInBytes(); 121 if (memoryUsageInBytes) 122 ImageDecodingStore::instance()->setCacheLimitInBytes(memoryUsageInBytes - 1); 123 else 124 ImageDecodingStore::instance()->setCacheLimitInBytes(0); 125 } 126 127 bool isCacheAlive(const SkISize& size) 128 { 129 const ScaledImageFragment* cachedImage = lockCache(size); 130 if (!cachedImage) 131 return false; 132 ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage); 133 return true; 134 } 135 136 RefPtr<SharedBuffer> m_data; 137 RefPtr<ImageFrameGenerator> m_generator; 138 int m_decodersDestroyed; 139 }; 140 141 TEST_F(ImageDecodingStoreTest, evictOneCache) 142 { 143 insertCache(SkISize::Make(1, 1)); 144 insertCache(SkISize::Make(2, 2)); 145 insertCache(SkISize::Make(3, 3)); 146 EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries()); 147 148 evictOneCache(); 149 EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries()); 150 151 evictOneCache(); 152 EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries()); 153 } 154 155 TEST_F(ImageDecodingStoreTest, pruneOrderIsLeastRecentlyUsed) 156 { 157 insertCache(SkISize::Make(1, 1)); 158 insertCache(SkISize::Make(2, 2)); 159 insertCache(SkISize::Make(3, 3)); 160 insertCache(SkISize::Make(4, 4)); 161 insertCache(SkISize::Make(5, 5)); 162 EXPECT_EQ(5u, ImageDecodingStore::instance()->cacheEntries()); 163 164 // Use cache in the order 3, 2, 4, 1, 5. 165 EXPECT_TRUE(isCacheAlive(SkISize::Make(3, 3))); 166 EXPECT_TRUE(isCacheAlive(SkISize::Make(2, 2))); 167 EXPECT_TRUE(isCacheAlive(SkISize::Make(4, 4))); 168 EXPECT_TRUE(isCacheAlive(SkISize::Make(1, 1))); 169 EXPECT_TRUE(isCacheAlive(SkISize::Make(5, 5))); 170 171 // Evict 3. 172 evictOneCache(); 173 EXPECT_FALSE(isCacheAlive(SkISize::Make(3, 3))); 174 EXPECT_EQ(4u, ImageDecodingStore::instance()->cacheEntries()); 175 176 // Evict 2. 177 evictOneCache(); 178 EXPECT_FALSE(isCacheAlive(SkISize::Make(2, 2))); 179 EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries()); 180 181 // Evict 4. 182 evictOneCache(); 183 EXPECT_FALSE(isCacheAlive(SkISize::Make(4, 4))); 184 EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries()); 185 186 // Evict 1. 187 evictOneCache(); 188 EXPECT_FALSE(isCacheAlive(SkISize::Make(1, 1))); 189 EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries()); 190 191 // Evict 5. 192 evictOneCache(); 193 EXPECT_FALSE(isCacheAlive(SkISize::Make(5, 5))); 194 EXPECT_EQ(0u, ImageDecodingStore::instance()->cacheEntries()); 195 } 196 197 TEST_F(ImageDecodingStoreTest, pruneCausedByInsertion) 198 { 199 ImageDecodingStore::instance()->setCacheLimitInBytes(100); 200 201 // Insert 100 entries. 202 // Cache entries stored should increase and eventually decrease to 1. 203 insertCache(SkISize::Make(1, 1)); 204 insertCache(SkISize::Make(2, 2)); 205 insertCache(SkISize::Make(3, 3)); 206 EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries()); 207 208 for (int i = 4; i <= 100; ++i) 209 insertCache(SkISize::Make(i, i)); 210 211 EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries()); 212 for (int i = 1; i <= 99; ++i) 213 EXPECT_FALSE(isCacheAlive(SkISize::Make(i, i))); 214 EXPECT_TRUE(isCacheAlive(SkISize::Make(100, 100))); 215 } 216 217 TEST_F(ImageDecodingStoreTest, cacheInUseNotEvicted) 218 { 219 insertCache(SkISize::Make(1, 1)); 220 insertCache(SkISize::Make(2, 2)); 221 insertCache(SkISize::Make(3, 3)); 222 EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries()); 223 224 const ScaledImageFragment* cachedImage = lockCache(SkISize::Make(1, 1)); 225 ASSERT_TRUE(cachedImage); 226 227 // Cache 2 is evicted because cache 1 is in use. 228 evictOneCache(); 229 EXPECT_TRUE(isCacheAlive(SkISize::Make(1, 1))); 230 EXPECT_FALSE(isCacheAlive(SkISize::Make(2, 2))); 231 EXPECT_TRUE(isCacheAlive(SkISize::Make(3, 3))); 232 233 EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries()); 234 unlockCache(cachedImage); 235 } 236 237 TEST_F(ImageDecodingStoreTest, destroyImageFrameGenerator) 238 { 239 insertCache(SkISize::Make(1, 1)); 240 insertCache(SkISize::Make(2, 2)); 241 insertCache(SkISize::Make(3, 3)); 242 OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this); 243 decoder->setSize(1, 1); 244 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release(), false); 245 EXPECT_EQ(4u, ImageDecodingStore::instance()->cacheEntries()); 246 247 m_generator.clear(); 248 EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries()); 249 } 250 251 TEST_F(ImageDecodingStoreTest, insertDecoder) 252 { 253 const SkISize size = SkISize::Make(1, 1); 254 OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this); 255 decoder->setSize(1, 1); 256 const ImageDecoder* refDecoder = decoder.get(); 257 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release(), false); 258 EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries()); 259 EXPECT_EQ(4u, ImageDecodingStore::instance()->memoryUsageInBytes()); 260 261 ImageDecoder* testDecoder; 262 EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), size, &testDecoder)); 263 EXPECT_TRUE(testDecoder); 264 EXPECT_EQ(refDecoder, testDecoder); 265 ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), testDecoder); 266 EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries()); 267 } 268 269 TEST_F(ImageDecodingStoreTest, evictDecoder) 270 { 271 OwnPtr<ImageDecoder> decoder1 = MockImageDecoder::create(this); 272 OwnPtr<ImageDecoder> decoder2 = MockImageDecoder::create(this); 273 OwnPtr<ImageDecoder> decoder3 = MockImageDecoder::create(this); 274 decoder1->setSize(1, 1); 275 decoder2->setSize(2, 2); 276 decoder3->setSize(3, 3); 277 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder1.release(), false); 278 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder2.release(), false); 279 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder3.release(), false); 280 EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries()); 281 EXPECT_EQ(56u, ImageDecodingStore::instance()->memoryUsageInBytes()); 282 283 evictOneCache(); 284 EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries()); 285 EXPECT_EQ(52u, ImageDecodingStore::instance()->memoryUsageInBytes()); 286 287 evictOneCache(); 288 EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries()); 289 EXPECT_EQ(36u, ImageDecodingStore::instance()->memoryUsageInBytes()); 290 291 evictOneCache(); 292 EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries()); 293 EXPECT_FALSE(ImageDecodingStore::instance()->memoryUsageInBytes()); 294 } 295 296 TEST_F(ImageDecodingStoreTest, decoderInUseNotEvicted) 297 { 298 OwnPtr<ImageDecoder> decoder1 = MockImageDecoder::create(this); 299 OwnPtr<ImageDecoder> decoder2 = MockImageDecoder::create(this); 300 OwnPtr<ImageDecoder> decoder3 = MockImageDecoder::create(this); 301 decoder1->setSize(1, 1); 302 decoder2->setSize(2, 2); 303 decoder3->setSize(3, 3); 304 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder1.release(), false); 305 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder2.release(), false); 306 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder3.release(), false); 307 EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries()); 308 309 ImageDecoder* testDecoder; 310 EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), SkISize::Make(2, 2), &testDecoder)); 311 312 evictOneCache(); 313 evictOneCache(); 314 evictOneCache(); 315 EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries()); 316 EXPECT_EQ(16u, ImageDecodingStore::instance()->memoryUsageInBytes()); 317 318 ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), testDecoder); 319 evictOneCache(); 320 EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries()); 321 EXPECT_FALSE(ImageDecodingStore::instance()->memoryUsageInBytes()); 322 } 323 324 TEST_F(ImageDecodingStoreTest, removeDecoder) 325 { 326 const SkISize size = SkISize::Make(1, 1); 327 OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this); 328 decoder->setSize(1, 1); 329 const ImageDecoder* refDecoder = decoder.get(); 330 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release(), false); 331 EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries()); 332 EXPECT_EQ(4u, ImageDecodingStore::instance()->memoryUsageInBytes()); 333 334 ImageDecoder* testDecoder; 335 EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), size, &testDecoder)); 336 EXPECT_TRUE(testDecoder); 337 EXPECT_EQ(refDecoder, testDecoder); 338 ImageDecodingStore::instance()->removeDecoder(m_generator.get(), testDecoder); 339 EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries()); 340 341 EXPECT_FALSE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), size, &testDecoder)); 342 } 343 344 TEST_F(ImageDecodingStoreTest, multipleIndex) 345 { 346 const SkISize size = SkISize::Make(1, 1); 347 const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache( 348 m_generator.get(), createCompleteImage(size, false, 0)); 349 unlockCache(refImage); 350 const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache( 351 m_generator.get(), createCompleteImage(size, false, 1)); 352 unlockCache(testImage); 353 EXPECT_NE(refImage, testImage); 354 EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries()); 355 356 EXPECT_TRUE(ImageDecodingStore::instance()->lockCache(m_generator.get(), size, 1, &refImage)); 357 EXPECT_EQ(refImage, testImage); 358 unlockCache(refImage); 359 } 360 361 TEST_F(ImageDecodingStoreTest, finalAndPartialImage) 362 { 363 const SkISize size = SkISize::Make(1, 1); 364 const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache( 365 m_generator.get(), createCompleteImage(size, false, 0)); 366 unlockCache(refImage); 367 const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache( 368 m_generator.get(), createIncompleteImage(size, false, 1)); 369 unlockCache(testImage); 370 EXPECT_NE(refImage, testImage); 371 EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries()); 372 373 EXPECT_TRUE(ImageDecodingStore::instance()->lockCache(m_generator.get(), size, 0, &refImage)); 374 EXPECT_NE(refImage, testImage); 375 unlockCache(refImage); 376 } 377 378 TEST_F(ImageDecodingStoreTest, insertNoGenerationCollision) 379 { 380 const SkISize size = SkISize::Make(1, 1); 381 const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache( 382 m_generator.get(), createIncompleteImage(size, false, 1)); 383 unlockCache(refImage); 384 const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache( 385 m_generator.get(), createIncompleteImage(size, false, 2)); 386 unlockCache(testImage); 387 EXPECT_NE(refImage, testImage); 388 EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries()); 389 } 390 391 TEST_F(ImageDecodingStoreTest, insertGenerationCollision) 392 { 393 const SkISize size = SkISize::Make(1, 1); 394 const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache( 395 m_generator.get(), createIncompleteImage(size, false, 1)); 396 unlockCache(refImage); 397 const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache( 398 m_generator.get(), createIncompleteImage(size, false, 1)); 399 unlockCache(testImage); 400 EXPECT_EQ(refImage, testImage); 401 EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries()); 402 } 403 404 TEST_F(ImageDecodingStoreTest, insertGenerationCollisionAfterMemoryDiscarded) 405 { 406 const SkISize size = SkISize::Make(1, 1); 407 const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache( 408 m_generator.get(), createIncompleteImage(size, true, 1)); 409 unlockCache(refImage); 410 MockDiscardablePixelRef* pixelRef = static_cast<MockDiscardablePixelRef*>(refImage->bitmap().pixelRef()); 411 pixelRef->discard(); 412 const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache( 413 m_generator.get(), createIncompleteImage(size, false, 1)); 414 unlockCache(testImage); 415 EXPECT_NE(refImage, testImage); 416 EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries()); 417 } 418 419 TEST_F(ImageDecodingStoreTest, lockCacheFailedAfterMemoryDiscarded) 420 { 421 const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache( 422 m_generator.get(), createCompleteImage(SkISize::Make(1, 1), true)); 423 unlockCache(cachedImage); 424 MockDiscardablePixelRef* pixelRef = static_cast<MockDiscardablePixelRef*>(cachedImage->bitmap().pixelRef()); 425 pixelRef->discard(); 426 EXPECT_EQ(0, lockCache(SkISize::Make(1, 1))); 427 EXPECT_EQ(0u, ImageDecodingStore::instance()->cacheEntries()); 428 } 429 430 TEST_F(ImageDecodingStoreTest, clear) 431 { 432 insertCache(SkISize::Make(1, 1)); 433 insertCache(SkISize::Make(2, 2)); 434 EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries()); 435 436 OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this); 437 decoder->setSize(1, 1); 438 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release(), false); 439 EXPECT_EQ(3u, ImageDecodingStore::instance()->cacheEntries()); 440 441 ImageDecodingStore::instance()->clear(); 442 EXPECT_EQ(0u, ImageDecodingStore::instance()->cacheEntries()); 443 } 444 445 TEST_F(ImageDecodingStoreTest, clearInUse) 446 { 447 insertCache(SkISize::Make(1, 1)); 448 insertCache(SkISize::Make(2, 2)); 449 EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries()); 450 451 const ScaledImageFragment* cachedImage = lockCache(SkISize::Make(1, 1)); 452 ASSERT_TRUE(cachedImage); 453 ImageDecodingStore::instance()->clear(); 454 EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries()); 455 456 unlockCache(cachedImage); 457 EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries()); 458 } 459 460 } // namespace 461