2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "platform/graphics/ImageFrameGenerator.h"
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>
41 // Helper methods to generate standard sizes.
42 SkISize fullSize() { return SkISize::Make(100, 100); }
46 class ImageFrameGeneratorTest : public ::testing::Test, public MockImageDecoderClient {
48 virtual void SetUp() OVERRIDE
50 ImageDecodingStore::initializeOnce();
51 ImageDecodingStore::instance()->setImageCachingEnabled(true);
52 m_data = SharedBuffer::create();
53 m_generator = ImageFrameGenerator::create(fullSize(), m_data, true);
54 useMockImageDecoderFactory();
55 m_decodersDestroyed = 0;
56 m_frameBufferRequestCount = 0;
57 m_status = ImageFrame::FrameEmpty;
60 virtual void TearDown() OVERRIDE
62 ImageDecodingStore::shutdown();
65 virtual void decoderBeingDestroyed() OVERRIDE
67 ++m_decodersDestroyed;
70 virtual void frameBufferRequested() OVERRIDE
72 ++m_frameBufferRequestCount;
75 virtual ImageFrame::Status status() OVERRIDE
77 ImageFrame::Status currentStatus = m_status;
78 m_status = m_nextFrameStatus;
82 virtual size_t frameCount() OVERRIDE { return 1; }
83 virtual int repetitionCount() const OVERRIDE { return cAnimationNone; }
84 virtual float frameDuration() const OVERRIDE { return 0; }
87 void useMockImageDecoderFactory()
89 m_generator->setImageDecoderFactory(MockImageDecoderFactory::create(this, fullSize()));
92 PassOwnPtr<ScaledImageFragment> createCompleteImage(const SkISize& size)
95 bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
97 return ScaledImageFragment::createComplete(size, 0, bitmap);
102 m_data->append("g", 1);
103 m_generator->setData(m_data, false);
106 void setFrameStatus(ImageFrame::Status status) { m_status = m_nextFrameStatus = status; }
107 void setNextFrameStatus(ImageFrame::Status status) { m_nextFrameStatus = status; }
109 SkBitmap::Allocator* allocator() const { return m_generator->allocator(); }
110 void setAllocator(PassOwnPtr<SkBitmap::Allocator> allocator)
112 m_generator->setAllocator(allocator);
115 PassOwnPtr<ScaledImageFragment> decode(size_t index)
117 ImageDecoder* decoder = 0;
118 return m_generator->decode(index, &decoder);
121 RefPtr<SharedBuffer> m_data;
122 RefPtr<ImageFrameGenerator> m_generator;
123 int m_decodersDestroyed;
124 int m_frameBufferRequestCount;
125 ImageFrame::Status m_status;
126 ImageFrame::Status m_nextFrameStatus;
129 TEST_F(ImageFrameGeneratorTest, cacheHit)
131 const ScaledImageFragment* fullImage = ImageDecodingStore::instance()->insertAndLockCache(
132 m_generator.get(), createCompleteImage(fullSize()));
133 EXPECT_EQ(fullSize(), fullImage->scaledSize());
134 ImageDecodingStore::instance()->unlockCache(m_generator.get(), fullImage);
136 const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize());
137 EXPECT_EQ(fullImage, tempImage);
138 EXPECT_EQ(fullSize(), tempImage->scaledSize());
139 EXPECT_TRUE(m_generator->hasAlpha(0));
140 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
141 EXPECT_EQ(0, m_frameBufferRequestCount);
144 TEST_F(ImageFrameGeneratorTest, cacheMissWithIncompleteDecode)
146 setFrameStatus(ImageFrame::FramePartial);
148 const ScaledImageFragment* tempImage= m_generator->decodeAndScale(fullSize());
149 EXPECT_FALSE(tempImage->isComplete());
150 EXPECT_EQ(1, m_frameBufferRequestCount);
151 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
152 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
153 EXPECT_EQ(1, ImageDecodingStore::instance()->imageCacheEntries());
154 EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
157 tempImage = m_generator->decodeAndScale(fullSize());
158 EXPECT_FALSE(tempImage->isComplete());
159 EXPECT_EQ(2, m_frameBufferRequestCount);
160 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
161 EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries());
162 EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries());
163 EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
164 EXPECT_EQ(0, m_decodersDestroyed);
167 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesComplete)
169 setFrameStatus(ImageFrame::FramePartial);
171 const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize());
172 EXPECT_FALSE(tempImage->isComplete());
173 EXPECT_EQ(1, m_frameBufferRequestCount);
174 EXPECT_EQ(0, m_decodersDestroyed);
175 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
176 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
177 EXPECT_EQ(1, ImageDecodingStore::instance()->imageCacheEntries());
178 EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
180 setFrameStatus(ImageFrame::FrameComplete);
183 tempImage = m_generator->decodeAndScale(fullSize());
184 EXPECT_TRUE(tempImage->isComplete());
185 EXPECT_EQ(2, m_frameBufferRequestCount);
186 EXPECT_EQ(1, m_decodersDestroyed);
187 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
188 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
189 EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries());
190 EXPECT_EQ(0, ImageDecodingStore::instance()->decoderCacheEntries());
192 tempImage = m_generator->decodeAndScale(fullSize());
193 EXPECT_TRUE(tempImage->isComplete());
194 EXPECT_EQ(2, m_frameBufferRequestCount);
195 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
198 static void decodeThreadMain(ImageFrameGenerator* generator)
200 const ScaledImageFragment* tempImage = generator->decodeAndScale(fullSize());
201 ImageDecodingStore::instance()->unlockCache(generator, tempImage);
204 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesCompleteMultiThreaded)
206 setFrameStatus(ImageFrame::FramePartial);
208 const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize());
209 EXPECT_FALSE(tempImage->isComplete());
210 EXPECT_EQ(1, m_frameBufferRequestCount);
211 EXPECT_EQ(0, m_decodersDestroyed);
212 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
213 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
214 EXPECT_EQ(1, ImageDecodingStore::instance()->imageCacheEntries());
215 EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
217 // Frame can now be decoded completely.
218 setFrameStatus(ImageFrame::FrameComplete);
220 OwnPtr<blink::WebThread> thread = adoptPtr(blink::Platform::current()->createThread("DecodeThread"));
221 thread->postTask(new Task(WTF::bind(&decodeThreadMain, m_generator.get())));
224 EXPECT_EQ(2, m_frameBufferRequestCount);
225 EXPECT_EQ(1, m_decodersDestroyed);
226 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
227 EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries());
228 EXPECT_EQ(0, ImageDecodingStore::instance()->decoderCacheEntries());
230 tempImage = m_generator->decodeAndScale(fullSize());
231 EXPECT_TRUE(tempImage->isComplete());
232 EXPECT_EQ(2, m_frameBufferRequestCount);
233 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
236 TEST_F(ImageFrameGeneratorTest, incompleteBitmapCopied)
238 setFrameStatus(ImageFrame::FramePartial);
240 const ScaledImageFragment* tempImage= m_generator->decodeAndScale(fullSize());
241 EXPECT_FALSE(tempImage->isComplete());
242 EXPECT_EQ(1, m_frameBufferRequestCount);
244 ImageDecoder* tempDecoder = 0;
245 EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), fullSize(), &tempDecoder));
246 ASSERT_TRUE(tempDecoder);
247 EXPECT_NE(tempDecoder->frameBufferAtIndex(0)->getSkBitmap().getPixels(), tempImage->bitmap().getPixels());
248 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
249 ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), tempDecoder);
252 TEST_F(ImageFrameGeneratorTest, resumeDecodeEmptyFrameTurnsComplete)
254 m_generator = ImageFrameGenerator::create(fullSize(), m_data, false, true);
255 useMockImageDecoderFactory();
256 setFrameStatus(ImageFrame::FrameComplete);
258 const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize(), 0);
259 EXPECT_TRUE(tempImage->isComplete());
260 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
262 setFrameStatus(ImageFrame::FrameEmpty);
263 setNextFrameStatus(ImageFrame::FrameComplete);
264 EXPECT_FALSE(m_generator->decodeAndScale(fullSize(), 1));
267 TEST_F(ImageFrameGeneratorTest, frameHasAlpha)
269 setFrameStatus(ImageFrame::FramePartial);
270 ImageDecodingStore::instance()->unlockCache(m_generator.get(), m_generator->decodeAndScale(fullSize(), 0));
271 EXPECT_TRUE(m_generator->hasAlpha(0));
273 ImageDecoder* tempDecoder = 0;
274 EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), fullSize(), &tempDecoder));
275 ASSERT_TRUE(tempDecoder);
276 static_cast<MockImageDecoder*>(tempDecoder)->setFrameHasAlpha(false);
277 ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), tempDecoder);
279 setFrameStatus(ImageFrame::FrameComplete);
280 ImageDecodingStore::instance()->unlockCache(m_generator.get(), m_generator->decodeAndScale(fullSize(), 0));
281 EXPECT_FALSE(m_generator->hasAlpha(0));
286 class MockAllocator : public SkBitmap::Allocator {
289 MockAllocator(int failAtNthCall)
291 , m_failAtNthCall(failAtNthCall)
292 , m_defaultAllocator(adoptPtr(new DiscardablePixelRefAllocator()))
296 virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* colorTable) OVERRIDE
298 if (m_callCount++ == m_failAtNthCall)
300 return m_defaultAllocator->allocPixelRef(bitmap, colorTable);
305 OwnPtr<SkBitmap::Allocator> m_defaultAllocator;
310 TEST_F(ImageFrameGeneratorTest, decodingAllocatorFailure)
312 // Try to emulate allocation failures at different stages. For now, the
313 // first allocation is for the bitmap in ImageFrame, the second is for the
314 // copy of partial bitmap. The loop will still work if the number or purpose
315 // of allocations change in the future.
316 for (int i = 0; ; ++i) {
317 SCOPED_TRACE(testing::Message() << "Allocation failure at call " << i);
318 setFrameStatus(ImageFrame::FramePartial);
319 setAllocator(adoptPtr(new MockAllocator(i)));
320 OwnPtr<ScaledImageFragment> image = decode(0);
321 if (i >= static_cast<MockAllocator*>(allocator())->m_callCount) {
322 // We have tested failures of all stages. This time all allocations
331 } // namespace WebCore