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::instance()->setCacheLimitInBytes(1024 * 1024);
51 ImageDecodingStore::instance()->setImageCachingEnabled(true);
52 m_data = SharedBuffer::create();
53 m_generator = ImageFrameGenerator::create(fullSize(), m_data, false);
54 useMockImageDecoderFactory();
55 m_decodersDestroyed = 0;
56 m_frameBufferRequestCount = 0;
57 m_status = ImageFrame::FrameEmpty;
60 virtual void TearDown() OVERRIDE
62 ImageDecodingStore::instance()->clear();
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 if (!bitmap.allocN32Pixels(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 OwnPtr<ScaledImageFragment> fragment = m_generator->decode(index, &decoder);
120 return fragment.release();
123 RefPtr<SharedBuffer> m_data;
124 RefPtr<ImageFrameGenerator> m_generator;
125 int m_decodersDestroyed;
126 int m_frameBufferRequestCount;
127 ImageFrame::Status m_status;
128 ImageFrame::Status m_nextFrameStatus;
131 TEST_F(ImageFrameGeneratorTest, cacheHit)
133 OwnPtr<ScaledImageFragment> completeImageTemp = createCompleteImage(fullSize());
134 ASSERT_TRUE(completeImageTemp);
135 const ScaledImageFragment* fullImage = ImageDecodingStore::instance()->insertAndLockCache(
136 m_generator.get(), completeImageTemp.release());
137 EXPECT_EQ(fullSize(), fullImage->scaledSize());
138 ImageDecodingStore::instance()->unlockCache(m_generator.get(), fullImage);
140 const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize());
141 EXPECT_EQ(fullImage, tempImage);
142 EXPECT_EQ(fullSize(), tempImage->scaledSize());
143 EXPECT_TRUE(m_generator->hasAlpha(0));
144 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
145 EXPECT_EQ(0, m_frameBufferRequestCount);
148 TEST_F(ImageFrameGeneratorTest, cacheMissWithIncompleteDecode)
150 setFrameStatus(ImageFrame::FramePartial);
152 const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize());
153 EXPECT_FALSE(tempImage->isComplete());
154 EXPECT_EQ(1, m_frameBufferRequestCount);
155 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
156 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
157 EXPECT_EQ(1, ImageDecodingStore::instance()->imageCacheEntries());
158 EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
161 tempImage = m_generator->decodeAndScale(fullSize());
162 EXPECT_FALSE(tempImage->isComplete());
163 EXPECT_EQ(2, m_frameBufferRequestCount);
164 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
165 EXPECT_EQ(3, ImageDecodingStore::instance()->cacheEntries());
166 EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries());
167 EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
168 EXPECT_EQ(0, m_decodersDestroyed);
171 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesComplete)
173 setFrameStatus(ImageFrame::FramePartial);
175 const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize());
176 EXPECT_FALSE(tempImage->isComplete());
177 EXPECT_EQ(1, m_frameBufferRequestCount);
178 EXPECT_EQ(0, m_decodersDestroyed);
179 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
180 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
181 EXPECT_EQ(1, ImageDecodingStore::instance()->imageCacheEntries());
182 EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
184 setFrameStatus(ImageFrame::FrameComplete);
187 tempImage = m_generator->decodeAndScale(fullSize());
188 EXPECT_TRUE(tempImage->isComplete());
189 EXPECT_EQ(2, m_frameBufferRequestCount);
190 EXPECT_EQ(1, m_decodersDestroyed);
191 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
192 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
193 EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries());
194 EXPECT_EQ(0, ImageDecodingStore::instance()->decoderCacheEntries());
196 tempImage = m_generator->decodeAndScale(fullSize());
197 EXPECT_TRUE(tempImage->isComplete());
198 EXPECT_EQ(2, m_frameBufferRequestCount);
199 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
202 static void decodeThreadMain(ImageFrameGenerator* generator)
204 const ScaledImageFragment* tempImage = generator->decodeAndScale(fullSize());
205 ImageDecodingStore::instance()->unlockCache(generator, tempImage);
208 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesCompleteMultiThreaded)
210 setFrameStatus(ImageFrame::FramePartial);
212 const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize());
213 EXPECT_FALSE(tempImage->isComplete());
214 EXPECT_EQ(1, m_frameBufferRequestCount);
215 EXPECT_EQ(0, m_decodersDestroyed);
216 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
217 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
218 EXPECT_EQ(1, ImageDecodingStore::instance()->imageCacheEntries());
219 EXPECT_EQ(1, ImageDecodingStore::instance()->decoderCacheEntries());
221 // LocalFrame can now be decoded completely.
222 setFrameStatus(ImageFrame::FrameComplete);
224 OwnPtr<WebThread> thread = adoptPtr(Platform::current()->createThread("DecodeThread"));
225 thread->postTask(new Task(WTF::bind(&decodeThreadMain, m_generator.get())));
228 EXPECT_EQ(2, m_frameBufferRequestCount);
229 EXPECT_EQ(1, m_decodersDestroyed);
230 EXPECT_EQ(2, ImageDecodingStore::instance()->cacheEntries());
231 EXPECT_EQ(2, ImageDecodingStore::instance()->imageCacheEntries());
232 EXPECT_EQ(0, ImageDecodingStore::instance()->decoderCacheEntries());
234 tempImage = m_generator->decodeAndScale(fullSize());
235 EXPECT_TRUE(tempImage->isComplete());
236 EXPECT_EQ(2, m_frameBufferRequestCount);
237 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
240 TEST_F(ImageFrameGeneratorTest, incompleteBitmapCopied)
242 setFrameStatus(ImageFrame::FramePartial);
244 const ScaledImageFragment* tempImage= m_generator->decodeAndScale(fullSize());
245 EXPECT_FALSE(tempImage->isComplete());
246 EXPECT_EQ(1, m_frameBufferRequestCount);
248 ImageDecoder* tempDecoder = 0;
249 EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), fullSize(), &tempDecoder));
250 ASSERT_TRUE(tempDecoder);
251 EXPECT_NE(tempDecoder->frameBufferAtIndex(0)->getSkBitmap().getPixels(), tempImage->bitmap().getPixels());
252 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
253 ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), tempDecoder);
256 TEST_F(ImageFrameGeneratorTest, resumeDecodeEmptyFrameTurnsComplete)
258 m_generator = ImageFrameGenerator::create(fullSize(), m_data, false, true);
259 useMockImageDecoderFactory();
260 setFrameStatus(ImageFrame::FrameComplete);
262 const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize(), 0);
263 EXPECT_TRUE(tempImage->isComplete());
264 ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
266 setFrameStatus(ImageFrame::FrameEmpty);
267 setNextFrameStatus(ImageFrame::FrameComplete);
268 EXPECT_FALSE(m_generator->decodeAndScale(fullSize(), 1));
271 TEST_F(ImageFrameGeneratorTest, frameHasAlpha)
273 setFrameStatus(ImageFrame::FramePartial);
274 ImageDecodingStore::instance()->unlockCache(m_generator.get(), m_generator->decodeAndScale(fullSize(), 1));
275 EXPECT_TRUE(m_generator->hasAlpha(1));
277 ImageDecoder* tempDecoder = 0;
278 EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), fullSize(), &tempDecoder));
279 ASSERT_TRUE(tempDecoder);
280 static_cast<MockImageDecoder*>(tempDecoder)->setFrameHasAlpha(false);
281 ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), tempDecoder);
283 setFrameStatus(ImageFrame::FrameComplete);
284 ImageDecodingStore::instance()->unlockCache(m_generator.get(), m_generator->decodeAndScale(fullSize(), 1));
285 EXPECT_FALSE(m_generator->hasAlpha(1));
290 class MockAllocator : public SkBitmap::Allocator {
293 MockAllocator(int failAtNthCall)
295 , m_failAtNthCall(failAtNthCall)
296 , m_defaultAllocator(adoptPtr(new DiscardablePixelRefAllocator()))
300 virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* colorTable) OVERRIDE
302 if (m_callCount++ == m_failAtNthCall)
304 return m_defaultAllocator->allocPixelRef(bitmap, colorTable);
309 OwnPtr<SkBitmap::Allocator> m_defaultAllocator;
314 TEST_F(ImageFrameGeneratorTest, decodingAllocatorFailure)
316 // Try to emulate allocation failures at different stages. For now, the
317 // first allocation is for the bitmap in ImageFrame, the second is for the
318 // copy of partial bitmap. The loop will still work if the number or purpose
319 // of allocations change in the future.
320 for (int i = 0; ; ++i) {
321 SCOPED_TRACE(testing::Message() << "Allocation failure at call " << i);
322 setFrameStatus(ImageFrame::FramePartial);
323 setAllocator(adoptPtr(new MockAllocator(i)));
324 OwnPtr<ScaledImageFragment> image = decode(0);
325 if (i >= static_cast<MockAllocator*>(allocator())->m_callCount) {
326 // We have tested failures of all stages. This time all allocations