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 #include "platform/graphics/ImageFrameGenerator.h" 28 29 #include "platform/SharedBuffer.h" 30 #include "platform/Task.h" 31 #include "platform/graphics/ImageDecodingStore.h" 32 #include "platform/graphics/test/MockImageDecoder.h" 33 #include "public/platform/Platform.h" 34 #include "public/platform/WebThread.h" 35 #include <gtest/gtest.h> 36 37 namespace WebCore { 38 39 namespace { 40 41 // Helper methods to generate standard sizes. 42 SkISize fullSize() { return SkISize::Make(100, 100); } 43 SkISize scaledSize() { return SkISize::Make(50, 50); } 44 45 } // namespace 46 47 class ImageFrameGeneratorTest : public ::testing::Test, public MockImageDecoderClient { 48 public: 49 virtual void SetUp() OVERRIDE 50 { 51 ImageDecodingStore::initializeOnce(); 52 ImageDecodingStore::instance()->setImageCachingEnabled(true); 53 m_data = SharedBuffer::create(); 54 m_generator = ImageFrameGenerator::create(fullSize(), m_data, true); 55 useMockImageDecoderFactory(); 56 m_decodersDestroyed = 0; 57 m_frameBufferRequestCount = 0; 58 m_status = ImageFrame::FrameEmpty; 59 } 60 61 virtual void TearDown() OVERRIDE 62 { 63 ImageDecodingStore::shutdown(); 64 } 65 66 virtual void decoderBeingDestroyed() OVERRIDE 67 { 68 ++m_decodersDestroyed; 69 } 70 71 virtual void frameBufferRequested() OVERRIDE 72 { 73 ++m_frameBufferRequestCount; 74 } 75 76 virtual ImageFrame::Status status() OVERRIDE 77 { 78 ImageFrame::Status currentStatus = m_status; 79 m_status = m_nextFrameStatus; 80 return currentStatus; 81 } 82 83 virtual size_t frameCount() OVERRIDE { return 1; } 84 virtual int repetitionCount() const OVERRIDE { return cAnimationNone; } 85 virtual float frameDuration() const OVERRIDE { return 0; } 86 87 protected: 88 void useMockImageDecoderFactory() 89 { 90 m_generator->setImageDecoderFactory(MockImageDecoderFactory::create(this, fullSize())); 91 } 92 93 PassOwnPtr<ScaledImageFragment> createCompleteImage(const SkISize& size) 94 { 95 SkBitmap bitmap; 96 bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height()); 97 bitmap.allocPixels(); 98 return ScaledImageFragment::createComplete(size, 0, bitmap); 99 } 100 101 void addNewData() 102 { 103 m_data->append("g", 1); 104 m_generator->setData(m_data, false); 105 } 106 107 void setFrameStatus(ImageFrame::Status status) { m_status = m_nextFrameStatus = status; } 108 void setNextFrameStatus(ImageFrame::Status status) { m_nextFrameStatus = status; } 109 110 SkBitmap::Allocator* allocator() const { return m_generator->allocator(); } 111 void setAllocator(PassOwnPtr<SkBitmap::Allocator> allocator) 112 { 113 m_generator->setAllocator(allocator); 114 } 115 116 PassOwnPtr<ScaledImageFragment> decode(size_t index) 117 { 118 ImageDecoder* decoder = 0; 119 return m_generator->decode(index, &decoder); 120 } 121 122 RefPtr<SharedBuffer> m_data; 123 RefPtr<ImageFrameGenerator> m_generator; 124 int m_decodersDestroyed; 125 int m_frameBufferRequestCount; 126 ImageFrame::Status m_status; 127 ImageFrame::Status m_nextFrameStatus; 128 }; 129 130 TEST_F(ImageFrameGeneratorTest, cacheHit) 131 { 132 const ScaledImageFragment* fullImage = ImageDecodingStore::instance()->insertAndLockCache( 133 m_generator.get(), createCompleteImage(fullSize())); 134 EXPECT_EQ(fullSize(), fullImage->scaledSize()); 135 ImageDecodingStore::instance()->unlockCache(m_generator.get(), fullImage); 136 137 const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize()); 138 EXPECT_EQ(fullImage, tempImage); 139 EXPECT_EQ(fullSize(), tempImage->scaledSize()); 140 EXPECT_TRUE(m_generator->hasAlpha(0)); 141 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 142 EXPECT_EQ(0, m_frameBufferRequestCount); 143 } 144 145 TEST_F(ImageFrameGeneratorTest, cacheMissWithScale) 146 { 147 const ScaledImageFragment* fullImage = ImageDecodingStore::instance()->insertAndLockCache( 148 m_generator.get(), createCompleteImage(fullSize())); 149 EXPECT_EQ(fullSize(), fullImage->scaledSize()); 150 ImageDecodingStore::instance()->unlockCache(m_generator.get(), fullImage); 151 152 // Cache miss because of scaled size not found. 153 const ScaledImageFragment* scaledImage = m_generator->decodeAndScale(scaledSize()); 154 EXPECT_NE(fullImage, scaledImage); 155 EXPECT_EQ(scaledSize(), scaledImage->scaledSize()); 156 EXPECT_TRUE(m_generator->hasAlpha(0)); 157 ImageDecodingStore::instance()->unlockCache(m_generator.get(), scaledImage); 158 159 // Cache hit. 160 const ScaledImageFragment* tempImage = m_generator->decodeAndScale(scaledSize()); 161 EXPECT_EQ(scaledImage, tempImage); 162 EXPECT_EQ(scaledSize(), tempImage->scaledSize()); 163 EXPECT_TRUE(m_generator->hasAlpha(0)); 164 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 165 EXPECT_EQ(0, m_frameBufferRequestCount); 166 } 167 168 TEST_F(ImageFrameGeneratorTest, cacheMissWithDecodeAndScale) 169 { 170 setFrameStatus(ImageFrame::FrameComplete); 171 172 // Cache miss. 173 const ScaledImageFragment* scaledImage = m_generator->decodeAndScale(scaledSize()); 174 EXPECT_EQ(1, m_frameBufferRequestCount); 175 EXPECT_EQ(scaledSize(), scaledImage->scaledSize()); 176 EXPECT_FALSE(m_generator->hasAlpha(0)); 177 ImageDecodingStore::instance()->unlockCache(m_generator.get(), scaledImage); 178 EXPECT_EQ(1, m_decodersDestroyed); 179 180 // Cache hit. 181 const ScaledImageFragment* fullImage = m_generator->decodeAndScale(fullSize()); 182 EXPECT_NE(scaledImage, fullImage); 183 EXPECT_EQ(fullSize(), fullImage->scaledSize()); 184 EXPECT_FALSE(m_generator->hasAlpha(0)); 185 ImageDecodingStore::instance()->unlockCache(m_generator.get(), fullImage); 186 187 // Cache hit. 188 const ScaledImageFragment* tempImage = m_generator->decodeAndScale(scaledSize()); 189 EXPECT_EQ(scaledImage, tempImage); 190 EXPECT_EQ(scaledSize(), tempImage->scaledSize()); 191 EXPECT_FALSE(m_generator->hasAlpha(0)); 192 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 193 EXPECT_EQ(1, m_frameBufferRequestCount); 194 } 195 196 TEST_F(ImageFrameGeneratorTest, cacheMissWithIncompleteDecode) 197 { 198 setFrameStatus(ImageFrame::FramePartial); 199 200 const ScaledImageFragment* tempImage= m_generator->decodeAndScale(fullSize()); 201 EXPECT_FALSE(tempImage->isComplete()); 202 EXPECT_EQ(1, m_frameBufferRequestCount); 203 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 204 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries()); 205 EXPECT_EQ(1, ImageDecodingStore::instance()->imageCacheEntries()); 206 EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries()); 207 208 addNewData(); 209 tempImage = m_generator->decodeAndScale(fullSize()); 210 EXPECT_FALSE(tempImage->isComplete()); 211 EXPECT_EQ(2, m_frameBufferRequestCount); 212 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 213 EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries()); 214 EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries()); 215 EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries()); 216 EXPECT_EQ(0, m_decodersDestroyed); 217 } 218 219 TEST_F(ImageFrameGeneratorTest, cacheMissWithIncompleteDecodeAndScale) 220 { 221 setFrameStatus(ImageFrame::FramePartial); 222 223 const ScaledImageFragment* tempImage= m_generator->decodeAndScale(scaledSize()); 224 EXPECT_FALSE(tempImage->isComplete()); 225 EXPECT_EQ(1, m_frameBufferRequestCount); 226 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 227 EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries()); 228 EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries()); 229 EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries()); 230 231 addNewData(); 232 tempImage = m_generator->decodeAndScale(scaledSize()); 233 EXPECT_FALSE(tempImage->isComplete()); 234 EXPECT_EQ(2, m_frameBufferRequestCount); 235 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 236 EXPECT_EQ(5, ImageDecodingStore::instance()->cacheEntries()); 237 EXPECT_EQ(4, ImageDecodingStore::instance()->imageCacheEntries()); 238 EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries()); 239 EXPECT_EQ(0, m_decodersDestroyed); 240 } 241 242 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesComplete) 243 { 244 setFrameStatus(ImageFrame::FramePartial); 245 246 const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize()); 247 EXPECT_FALSE(tempImage->isComplete()); 248 EXPECT_EQ(1, m_frameBufferRequestCount); 249 EXPECT_EQ(0, m_decodersDestroyed); 250 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 251 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries()); 252 EXPECT_EQ(1, ImageDecodingStore::instance()->imageCacheEntries()); 253 EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries()); 254 255 setFrameStatus(ImageFrame::FrameComplete); 256 addNewData(); 257 258 tempImage = m_generator->decodeAndScale(fullSize()); 259 EXPECT_TRUE(tempImage->isComplete()); 260 EXPECT_EQ(2, m_frameBufferRequestCount); 261 EXPECT_EQ(1, m_decodersDestroyed); 262 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 263 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries()); 264 EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries()); 265 EXPECT_EQ(0, ImageDecodingStore::instance()->decoderCacheEntries()); 266 267 tempImage = m_generator->decodeAndScale(fullSize()); 268 EXPECT_TRUE(tempImage->isComplete()); 269 EXPECT_EQ(2, m_frameBufferRequestCount); 270 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 271 } 272 273 TEST_F(ImageFrameGeneratorTest, incompleteDecodeAndScaleBecomesComplete) 274 { 275 setFrameStatus(ImageFrame::FramePartial); 276 277 const ScaledImageFragment* tempImage = m_generator->decodeAndScale(scaledSize()); 278 EXPECT_FALSE(tempImage->isComplete()); 279 EXPECT_EQ(1, m_frameBufferRequestCount); 280 EXPECT_EQ(0, m_decodersDestroyed); 281 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 282 EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries()); 283 EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries()); 284 EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries()); 285 286 setFrameStatus(ImageFrame::FrameComplete); 287 addNewData(); 288 289 tempImage = m_generator->decodeAndScale(scaledSize()); 290 EXPECT_TRUE(tempImage->isComplete()); 291 EXPECT_EQ(2, m_frameBufferRequestCount); 292 EXPECT_EQ(1, m_decodersDestroyed); 293 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 294 EXPECT_EQ(4, ImageDecodingStore::instance()->cacheEntries()); 295 EXPECT_EQ(4, ImageDecodingStore::instance()->imageCacheEntries()); 296 EXPECT_EQ(0, ImageDecodingStore::instance()->decoderCacheEntries()); 297 298 tempImage = m_generator->decodeAndScale(scaledSize()); 299 EXPECT_TRUE(tempImage->isComplete()); 300 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 301 302 tempImage = m_generator->decodeAndScale(fullSize()); 303 EXPECT_TRUE(tempImage->isComplete()); 304 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 305 306 EXPECT_EQ(2, m_frameBufferRequestCount); 307 } 308 309 static void decodeThreadMain(ImageFrameGenerator* generator) 310 { 311 const ScaledImageFragment* tempImage = generator->decodeAndScale(fullSize()); 312 ImageDecodingStore::instance()->unlockCache(generator, tempImage); 313 } 314 315 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesCompleteMultiThreaded) 316 { 317 setFrameStatus(ImageFrame::FramePartial); 318 319 const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize()); 320 EXPECT_FALSE(tempImage->isComplete()); 321 EXPECT_EQ(1, m_frameBufferRequestCount); 322 EXPECT_EQ(0, m_decodersDestroyed); 323 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 324 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries()); 325 EXPECT_EQ(1, ImageDecodingStore::instance()->imageCacheEntries()); 326 EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries()); 327 328 // Frame can now be decoded completely. 329 setFrameStatus(ImageFrame::FrameComplete); 330 addNewData(); 331 OwnPtr<blink::WebThread> thread = adoptPtr(blink::Platform::current()->createThread("DecodeThread")); 332 thread->postTask(new Task(WTF::bind(&decodeThreadMain, m_generator.get()))); 333 thread.clear(); 334 335 EXPECT_EQ(2, m_frameBufferRequestCount); 336 EXPECT_EQ(1, m_decodersDestroyed); 337 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries()); 338 EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries()); 339 EXPECT_EQ(0, ImageDecodingStore::instance()->decoderCacheEntries()); 340 341 tempImage = m_generator->decodeAndScale(fullSize()); 342 EXPECT_TRUE(tempImage->isComplete()); 343 EXPECT_EQ(2, m_frameBufferRequestCount); 344 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 345 } 346 347 TEST_F(ImageFrameGeneratorTest, concurrentIncompleteDecodeAndScale) 348 { 349 setFrameStatus(ImageFrame::FramePartial); 350 351 const ScaledImageFragment* fullImage = m_generator->decodeAndScale(fullSize()); 352 const ScaledImageFragment* scaledImage = m_generator->decodeAndScale(scaledSize()); 353 EXPECT_FALSE(fullImage->isComplete()); 354 EXPECT_FALSE(scaledImage->isComplete()); 355 EXPECT_EQ(2, m_frameBufferRequestCount); 356 ImageDecodingStore::instance()->unlockCache(m_generator.get(), fullImage); 357 ImageDecodingStore::instance()->unlockCache(m_generator.get(), scaledImage); 358 EXPECT_EQ(4, ImageDecodingStore::instance()->cacheEntries()); 359 EXPECT_EQ(3, ImageDecodingStore::instance()->imageCacheEntries()); 360 EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries()); 361 EXPECT_EQ(0, m_decodersDestroyed); 362 363 addNewData(); 364 setFrameStatus(ImageFrame::FrameComplete); 365 scaledImage = m_generator->decodeAndScale(scaledSize()); 366 EXPECT_TRUE(scaledImage->isComplete()); 367 EXPECT_EQ(3, m_frameBufferRequestCount); 368 ImageDecodingStore::instance()->unlockCache(m_generator.get(), scaledImage); 369 EXPECT_EQ(5, ImageDecodingStore::instance()->cacheEntries()); 370 EXPECT_EQ(5, ImageDecodingStore::instance()->imageCacheEntries()); 371 EXPECT_EQ(0, ImageDecodingStore::instance()->decoderCacheEntries()); 372 EXPECT_EQ(1, m_decodersDestroyed); 373 } 374 375 TEST_F(ImageFrameGeneratorTest, incompleteBitmapCopied) 376 { 377 setFrameStatus(ImageFrame::FramePartial); 378 379 const ScaledImageFragment* tempImage= m_generator->decodeAndScale(fullSize()); 380 EXPECT_FALSE(tempImage->isComplete()); 381 EXPECT_EQ(1, m_frameBufferRequestCount); 382 383 ImageDecoder* tempDecoder = 0; 384 EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), fullSize(), &tempDecoder)); 385 ASSERT_TRUE(tempDecoder); 386 EXPECT_NE(tempDecoder->frameBufferAtIndex(0)->getSkBitmap().getPixels(), tempImage->bitmap().getPixels()); 387 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 388 ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), tempDecoder); 389 } 390 391 TEST_F(ImageFrameGeneratorTest, resumeDecodeEmptyFrameTurnsComplete) 392 { 393 m_generator = ImageFrameGenerator::create(fullSize(), m_data, false, true); 394 useMockImageDecoderFactory(); 395 setFrameStatus(ImageFrame::FrameComplete); 396 397 const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize(), 0); 398 EXPECT_TRUE(tempImage->isComplete()); 399 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage); 400 401 setFrameStatus(ImageFrame::FrameEmpty); 402 setNextFrameStatus(ImageFrame::FrameComplete); 403 EXPECT_FALSE(m_generator->decodeAndScale(fullSize(), 1)); 404 } 405 406 TEST_F(ImageFrameGeneratorTest, frameHasAlpha) 407 { 408 setFrameStatus(ImageFrame::FramePartial); 409 ImageDecodingStore::instance()->unlockCache(m_generator.get(), m_generator->decodeAndScale(fullSize(), 1)); 410 EXPECT_TRUE(m_generator->hasAlpha(1)); 411 412 ImageDecoder* tempDecoder = 0; 413 EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), fullSize(), &tempDecoder)); 414 ASSERT_TRUE(tempDecoder); 415 static_cast<MockImageDecoder*>(tempDecoder)->setFrameHasAlpha(false); 416 ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), tempDecoder); 417 418 setFrameStatus(ImageFrame::FrameComplete); 419 ImageDecodingStore::instance()->unlockCache(m_generator.get(), m_generator->decodeAndScale(fullSize(), 1)); 420 EXPECT_FALSE(m_generator->hasAlpha(1)); 421 } 422 423 namespace { 424 425 class MockAllocator : public SkBitmap::Allocator { 426 public: 427 // N starts from 0. 428 MockAllocator(int failAtNthCall) 429 : m_callCount(0) 430 , m_failAtNthCall(failAtNthCall) 431 , m_defaultAllocator(adoptPtr(new DiscardablePixelRefAllocator())) 432 { 433 } 434 435 virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* colorTable) OVERRIDE 436 { 437 if (m_callCount++ == m_failAtNthCall) 438 return false; 439 return m_defaultAllocator->allocPixelRef(bitmap, colorTable); 440 } 441 442 int m_callCount; 443 int m_failAtNthCall; 444 OwnPtr<SkBitmap::Allocator> m_defaultAllocator; 445 }; 446 447 } // namespace 448 449 TEST_F(ImageFrameGeneratorTest, decodingAllocatorFailure) 450 { 451 // Try to emulate allocation failures at different stages. For now, the 452 // first allocation is for the bitmap in ImageFrame, the second is for the 453 // copy of partial bitmap. The loop will still work if the number or purpose 454 // of allocations change in the future. 455 for (int i = 0; ; ++i) { 456 SCOPED_TRACE(testing::Message() << "Allocation failure at call " << i); 457 setFrameStatus(ImageFrame::FramePartial); 458 setAllocator(adoptPtr(new MockAllocator(i))); 459 OwnPtr<ScaledImageFragment> image = decode(0); 460 if (i >= static_cast<MockAllocator*>(allocator())->m_callCount) { 461 // We have tested failures of all stages. This time all allocations 462 // were successful. 463 EXPECT_TRUE(image); 464 break; 465 } 466 EXPECT_FALSE(image); 467 } 468 } 469 470 } // namespace WebCore 471