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 "platform/graphics/ImageDecodingStore.h" 29 30 #include "platform/SharedBuffer.h" 31 #include "platform/graphics/ImageFrameGenerator.h" 32 #include "platform/graphics/test/MockDiscardablePixelRef.h" 33 #include "platform/graphics/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 ImageDecodingStore::instance()->setImageCachingEnabled(true); 46 m_data = SharedBuffer::create(); 47 m_generator = ImageFrameGenerator::create(SkISize::Make(100, 100), m_data, true); 48 m_decodersDestroyed = 0; 49 } 50 51 virtual void TearDown() 52 { 53 ImageDecodingStore::shutdown(); 54 } 55 56 virtual void decoderBeingDestroyed() 57 { 58 ++m_decodersDestroyed; 59 } 60 61 virtual void frameBufferRequested() 62 { 63 // Decoder is never used by ImageDecodingStore. 64 ASSERT_TRUE(false); 65 } 66 67 virtual ImageFrame::Status status() 68 { 69 return ImageFrame::FramePartial; 70 } 71 72 virtual size_t frameCount() { return 1; } 73 virtual int repetitionCount() const { return cAnimationNone; } 74 virtual float frameDuration() const { return 0; } 75 76 protected: 77 PassOwnPtr<ScaledImageFragment> createCompleteImage(const SkISize& size, bool discardable = false, size_t index = 0) 78 { 79 SkBitmap bitmap; 80 bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height()); 81 if (!discardable) 82 bitmap.allocPixels(); 83 else 84 bitmap.setPixelRef(new MockDiscardablePixelRef())->unref(); 85 return ScaledImageFragment::createComplete(size, index, bitmap); 86 } 87 88 PassOwnPtr<ScaledImageFragment> createIncompleteImage(const SkISize& size, bool discardable = false, size_t generation = 0) 89 { 90 SkBitmap bitmap; 91 bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height()); 92 if (!discardable) 93 bitmap.allocPixels(); 94 else 95 bitmap.setPixelRef(new MockDiscardablePixelRef())->unref(); 96 return ScaledImageFragment::createPartial(size, 0, generation, bitmap); 97 } 98 99 void insertCache(const SkISize& size) 100 { 101 const ScaledImageFragment* image = ImageDecodingStore::instance()->insertAndLockCache( 102 m_generator.get(), createCompleteImage(size)); 103 unlockCache(image); 104 } 105 106 const ScaledImageFragment* lockCache(const SkISize& size, size_t index = 0) 107 { 108 const ScaledImageFragment* cachedImage = 0; 109 if (ImageDecodingStore::instance()->lockCache(m_generator.get(), size, index, &cachedImage)) 110 return cachedImage; 111 return 0; 112 } 113 114 void unlockCache(const ScaledImageFragment* cachedImage) 115 { 116 ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage); 117 } 118 119 void evictOneCache() 120 { 121 size_t memoryUsageInBytes = ImageDecodingStore::instance()->memoryUsageInBytes(); 122 if (memoryUsageInBytes) 123 ImageDecodingStore::instance()->setCacheLimitInBytes(memoryUsageInBytes - 1); 124 else 125 ImageDecodingStore::instance()->setCacheLimitInBytes(0); 126 } 127 128 bool isCacheAlive(const SkISize& size) 129 { 130 const ScaledImageFragment* cachedImage = lockCache(size); 131 if (!cachedImage) 132 return false; 133 ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage); 134 return true; 135 } 136 137 RefPtr<SharedBuffer> m_data; 138 RefPtr<ImageFrameGenerator> m_generator; 139 int m_decodersDestroyed; 140 }; 141 142 TEST_F(ImageDecodingStoreTest, evictOneCache) 143 { 144 insertCache(SkISize::Make(1, 1)); 145 insertCache(SkISize::Make(2, 2)); 146 insertCache(SkISize::Make(3, 3)); 147 EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries()); 148 149 evictOneCache(); 150 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries()); 151 152 evictOneCache(); 153 EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries()); 154 } 155 156 TEST_F(ImageDecodingStoreTest, pruneOrderIsLeastRecentlyUsed) 157 { 158 insertCache(SkISize::Make(1, 1)); 159 insertCache(SkISize::Make(2, 2)); 160 insertCache(SkISize::Make(3, 3)); 161 insertCache(SkISize::Make(4, 4)); 162 insertCache(SkISize::Make(5, 5)); 163 EXPECT_EQ(5, ImageDecodingStore::instance()->cacheEntries()); 164 165 // Use cache in the order 3, 2, 4, 1, 5. 166 EXPECT_TRUE(isCacheAlive(SkISize::Make(3, 3))); 167 EXPECT_TRUE(isCacheAlive(SkISize::Make(2, 2))); 168 EXPECT_TRUE(isCacheAlive(SkISize::Make(4, 4))); 169 EXPECT_TRUE(isCacheAlive(SkISize::Make(1, 1))); 170 EXPECT_TRUE(isCacheAlive(SkISize::Make(5, 5))); 171 172 // Evict 3. 173 evictOneCache(); 174 EXPECT_FALSE(isCacheAlive(SkISize::Make(3, 3))); 175 EXPECT_EQ(4, ImageDecodingStore::instance()->cacheEntries()); 176 177 // Evict 2. 178 evictOneCache(); 179 EXPECT_FALSE(isCacheAlive(SkISize::Make(2, 2))); 180 EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries()); 181 182 // Evict 4. 183 evictOneCache(); 184 EXPECT_FALSE(isCacheAlive(SkISize::Make(4, 4))); 185 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries()); 186 187 // Evict 1. 188 evictOneCache(); 189 EXPECT_FALSE(isCacheAlive(SkISize::Make(1, 1))); 190 EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries()); 191 192 // Evict 5. 193 evictOneCache(); 194 EXPECT_FALSE(isCacheAlive(SkISize::Make(5, 5))); 195 EXPECT_EQ(0, ImageDecodingStore::instance()->cacheEntries()); 196 } 197 198 TEST_F(ImageDecodingStoreTest, pruneCausedByInsertion) 199 { 200 ImageDecodingStore::instance()->setCacheLimitInBytes(100); 201 202 // Insert 100 entries. 203 // Cache entries stored should increase and eventually decrease to 1. 204 insertCache(SkISize::Make(1, 1)); 205 insertCache(SkISize::Make(2, 2)); 206 insertCache(SkISize::Make(3, 3)); 207 EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries()); 208 209 for (int i = 4; i <= 100; ++i) 210 insertCache(SkISize::Make(i, i)); 211 212 EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries()); 213 for (int i = 1; i <= 99; ++i) 214 EXPECT_FALSE(isCacheAlive(SkISize::Make(i, i))); 215 EXPECT_TRUE(isCacheAlive(SkISize::Make(100, 100))); 216 } 217 218 TEST_F(ImageDecodingStoreTest, cacheInUseNotEvicted) 219 { 220 insertCache(SkISize::Make(1, 1)); 221 insertCache(SkISize::Make(2, 2)); 222 insertCache(SkISize::Make(3, 3)); 223 EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries()); 224 225 const ScaledImageFragment* cachedImage = lockCache(SkISize::Make(1, 1)); 226 ASSERT_TRUE(cachedImage); 227 228 // Cache 2 is evicted because cache 1 is in use. 229 evictOneCache(); 230 EXPECT_TRUE(isCacheAlive(SkISize::Make(1, 1))); 231 EXPECT_FALSE(isCacheAlive(SkISize::Make(2, 2))); 232 EXPECT_TRUE(isCacheAlive(SkISize::Make(3, 3))); 233 234 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries()); 235 unlockCache(cachedImage); 236 } 237 238 TEST_F(ImageDecodingStoreTest, destroyImageFrameGenerator) 239 { 240 insertCache(SkISize::Make(1, 1)); 241 insertCache(SkISize::Make(2, 2)); 242 insertCache(SkISize::Make(3, 3)); 243 OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this); 244 decoder->setSize(1, 1); 245 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release(), false); 246 EXPECT_EQ(4, ImageDecodingStore::instance()->cacheEntries()); 247 248 m_generator.clear(); 249 EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries()); 250 } 251 252 TEST_F(ImageDecodingStoreTest, insertDecoder) 253 { 254 const SkISize size = SkISize::Make(1, 1); 255 OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this); 256 decoder->setSize(1, 1); 257 const ImageDecoder* refDecoder = decoder.get(); 258 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release(), false); 259 EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries()); 260 EXPECT_EQ(4u, ImageDecodingStore::instance()->memoryUsageInBytes()); 261 262 ImageDecoder* testDecoder; 263 EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), size, &testDecoder)); 264 EXPECT_TRUE(testDecoder); 265 EXPECT_EQ(refDecoder, testDecoder); 266 ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), testDecoder); 267 EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries()); 268 } 269 270 TEST_F(ImageDecodingStoreTest, evictDecoder) 271 { 272 OwnPtr<ImageDecoder> decoder1 = MockImageDecoder::create(this); 273 OwnPtr<ImageDecoder> decoder2 = MockImageDecoder::create(this); 274 OwnPtr<ImageDecoder> decoder3 = MockImageDecoder::create(this); 275 decoder1->setSize(1, 1); 276 decoder2->setSize(2, 2); 277 decoder3->setSize(3, 3); 278 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder1.release(), false); 279 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder2.release(), false); 280 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder3.release(), false); 281 EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries()); 282 EXPECT_EQ(56u, ImageDecodingStore::instance()->memoryUsageInBytes()); 283 284 evictOneCache(); 285 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries()); 286 EXPECT_EQ(52u, ImageDecodingStore::instance()->memoryUsageInBytes()); 287 288 evictOneCache(); 289 EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries()); 290 EXPECT_EQ(36u, ImageDecodingStore::instance()->memoryUsageInBytes()); 291 292 evictOneCache(); 293 EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries()); 294 EXPECT_FALSE(ImageDecodingStore::instance()->memoryUsageInBytes()); 295 } 296 297 TEST_F(ImageDecodingStoreTest, decoderInUseNotEvicted) 298 { 299 OwnPtr<ImageDecoder> decoder1 = MockImageDecoder::create(this); 300 OwnPtr<ImageDecoder> decoder2 = MockImageDecoder::create(this); 301 OwnPtr<ImageDecoder> decoder3 = MockImageDecoder::create(this); 302 decoder1->setSize(1, 1); 303 decoder2->setSize(2, 2); 304 decoder3->setSize(3, 3); 305 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder1.release(), false); 306 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder2.release(), false); 307 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder3.release(), false); 308 EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries()); 309 310 ImageDecoder* testDecoder; 311 EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), SkISize::Make(2, 2), &testDecoder)); 312 313 evictOneCache(); 314 evictOneCache(); 315 evictOneCache(); 316 EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries()); 317 EXPECT_EQ(16u, ImageDecodingStore::instance()->memoryUsageInBytes()); 318 319 ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), testDecoder); 320 evictOneCache(); 321 EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries()); 322 EXPECT_FALSE(ImageDecodingStore::instance()->memoryUsageInBytes()); 323 } 324 325 TEST_F(ImageDecodingStoreTest, removeDecoder) 326 { 327 const SkISize size = SkISize::Make(1, 1); 328 OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this); 329 decoder->setSize(1, 1); 330 const ImageDecoder* refDecoder = decoder.get(); 331 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release(), false); 332 EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries()); 333 EXPECT_EQ(4u, ImageDecodingStore::instance()->memoryUsageInBytes()); 334 335 ImageDecoder* testDecoder; 336 EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), size, &testDecoder)); 337 EXPECT_TRUE(testDecoder); 338 EXPECT_EQ(refDecoder, testDecoder); 339 ImageDecodingStore::instance()->removeDecoder(m_generator.get(), testDecoder); 340 EXPECT_FALSE(ImageDecodingStore::instance()->cacheEntries()); 341 342 EXPECT_FALSE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), size, &testDecoder)); 343 } 344 345 TEST_F(ImageDecodingStoreTest, multipleIndex) 346 { 347 const SkISize size = SkISize::Make(1, 1); 348 const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache( 349 m_generator.get(), createCompleteImage(size, false, 0)); 350 unlockCache(refImage); 351 const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache( 352 m_generator.get(), createCompleteImage(size, false, 1)); 353 unlockCache(testImage); 354 EXPECT_NE(refImage, testImage); 355 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries()); 356 357 EXPECT_TRUE(ImageDecodingStore::instance()->lockCache(m_generator.get(), size, 1, &refImage)); 358 EXPECT_EQ(refImage, testImage); 359 unlockCache(refImage); 360 } 361 362 TEST_F(ImageDecodingStoreTest, finalAndPartialImage) 363 { 364 const SkISize size = SkISize::Make(1, 1); 365 const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache( 366 m_generator.get(), createCompleteImage(size, false, 0)); 367 unlockCache(refImage); 368 const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache( 369 m_generator.get(), createIncompleteImage(size, false, 1)); 370 unlockCache(testImage); 371 EXPECT_NE(refImage, testImage); 372 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries()); 373 374 EXPECT_TRUE(ImageDecodingStore::instance()->lockCache(m_generator.get(), size, 0, &refImage)); 375 EXPECT_NE(refImage, testImage); 376 unlockCache(refImage); 377 } 378 379 TEST_F(ImageDecodingStoreTest, insertNoGenerationCollision) 380 { 381 const SkISize size = SkISize::Make(1, 1); 382 const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache( 383 m_generator.get(), createIncompleteImage(size, false, 1)); 384 unlockCache(refImage); 385 const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache( 386 m_generator.get(), createIncompleteImage(size, false, 2)); 387 unlockCache(testImage); 388 EXPECT_NE(refImage, testImage); 389 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries()); 390 } 391 392 TEST_F(ImageDecodingStoreTest, insertGenerationCollision) 393 { 394 const SkISize size = SkISize::Make(1, 1); 395 const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache( 396 m_generator.get(), createIncompleteImage(size, false, 1)); 397 unlockCache(refImage); 398 const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache( 399 m_generator.get(), createIncompleteImage(size, false, 1)); 400 unlockCache(testImage); 401 EXPECT_EQ(refImage, testImage); 402 EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries()); 403 } 404 405 TEST_F(ImageDecodingStoreTest, insertGenerationCollisionAfterMemoryDiscarded) 406 { 407 const SkISize size = SkISize::Make(1, 1); 408 const ScaledImageFragment* refImage = ImageDecodingStore::instance()->insertAndLockCache( 409 m_generator.get(), createIncompleteImage(size, true, 1)); 410 unlockCache(refImage); 411 MockDiscardablePixelRef* pixelRef = static_cast<MockDiscardablePixelRef*>(refImage->bitmap().pixelRef()); 412 pixelRef->discard(); 413 const ScaledImageFragment* testImage = ImageDecodingStore::instance()->insertAndLockCache( 414 m_generator.get(), createIncompleteImage(size, false, 1)); 415 unlockCache(testImage); 416 EXPECT_NE(refImage, testImage); 417 EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries()); 418 } 419 420 TEST_F(ImageDecodingStoreTest, lockCacheFailedAfterMemoryDiscarded) 421 { 422 const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache( 423 m_generator.get(), createCompleteImage(SkISize::Make(1, 1), true)); 424 unlockCache(cachedImage); 425 MockDiscardablePixelRef* pixelRef = static_cast<MockDiscardablePixelRef*>(cachedImage->bitmap().pixelRef()); 426 pixelRef->discard(); 427 EXPECT_EQ(0, lockCache(SkISize::Make(1, 1))); 428 EXPECT_EQ(0, ImageDecodingStore::instance()->cacheEntries()); 429 } 430 431 TEST_F(ImageDecodingStoreTest, clear) 432 { 433 insertCache(SkISize::Make(1, 1)); 434 insertCache(SkISize::Make(2, 2)); 435 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries()); 436 437 OwnPtr<ImageDecoder> decoder = MockImageDecoder::create(this); 438 decoder->setSize(1, 1); 439 ImageDecodingStore::instance()->insertDecoder(m_generator.get(), decoder.release(), false); 440 EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries()); 441 442 ImageDecodingStore::instance()->clear(); 443 EXPECT_EQ(0, ImageDecodingStore::instance()->cacheEntries()); 444 } 445 446 TEST_F(ImageDecodingStoreTest, clearInUse) 447 { 448 insertCache(SkISize::Make(1, 1)); 449 insertCache(SkISize::Make(2, 2)); 450 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries()); 451 452 const ScaledImageFragment* cachedImage = lockCache(SkISize::Make(1, 1)); 453 ASSERT_TRUE(cachedImage); 454 ImageDecodingStore::instance()->clear(); 455 EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries()); 456 457 unlockCache(cachedImage); 458 EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries()); 459 } 460 461 TEST_F(ImageDecodingStoreTest, disableImageCaching) 462 { 463 ImageDecodingStore::instance()->setImageCachingEnabled(false); 464 insertCache(SkISize::Make(1, 1)); 465 insertCache(SkISize::Make(2, 2)); 466 EXPECT_EQ(0, ImageDecodingStore::instance()->cacheEntries()); 467 468 const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache( 469 m_generator.get(), createCompleteImage(SkISize::Make(3, 3), true)); 470 EXPECT_EQ(1, ImageDecodingStore::instance()->cacheEntries()); 471 unlockCache(cachedImage); 472 EXPECT_EQ(0, ImageDecodingStore::instance()->cacheEntries()); 473 } 474 475 } // namespace 476