Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / graphics / ImageFrameGeneratorTest.cpp
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 blink {
38
39 namespace {
40
41 // Helper methods to generate standard sizes.
42 SkISize fullSize() { return SkISize::Make(100, 100); }
43
44 } // namespace
45
46 class ImageFrameGeneratorTest : public ::testing::Test, public MockImageDecoderClient {
47 public:
48     virtual void SetUp() OVERRIDE
49     {
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;
58     }
59
60     virtual void TearDown() OVERRIDE
61     {
62         ImageDecodingStore::instance()->clear();
63     }
64
65     virtual void decoderBeingDestroyed() OVERRIDE
66     {
67         ++m_decodersDestroyed;
68     }
69
70     virtual void frameBufferRequested() OVERRIDE
71     {
72         ++m_frameBufferRequestCount;
73     }
74
75     virtual ImageFrame::Status status() OVERRIDE
76     {
77         ImageFrame::Status currentStatus = m_status;
78         m_status = m_nextFrameStatus;
79         return currentStatus;
80     }
81
82     virtual size_t frameCount() OVERRIDE { return 1; }
83     virtual int repetitionCount() const OVERRIDE { return cAnimationNone; }
84     virtual float frameDuration() const OVERRIDE { return 0; }
85
86 protected:
87     void useMockImageDecoderFactory()
88     {
89         m_generator->setImageDecoderFactory(MockImageDecoderFactory::create(this, fullSize()));
90     }
91
92     PassOwnPtr<ScaledImageFragment> createCompleteImage(const SkISize& size)
93     {
94         SkBitmap bitmap;
95         if (!bitmap.allocN32Pixels(size.width(), size.height()))
96             return nullptr;
97         return ScaledImageFragment::createComplete(size, 0, bitmap);
98     }
99
100     void addNewData()
101     {
102         m_data->append("g", 1);
103         m_generator->setData(m_data, false);
104     }
105
106     void setFrameStatus(ImageFrame::Status status)  { m_status = m_nextFrameStatus = status; }
107     void setNextFrameStatus(ImageFrame::Status status)  { m_nextFrameStatus = status; }
108
109     SkBitmap::Allocator* allocator() const { return m_generator->allocator(); }
110     void setAllocator(PassOwnPtr<SkBitmap::Allocator> allocator)
111     {
112         m_generator->setAllocator(allocator);
113     }
114
115     PassOwnPtr<ScaledImageFragment> decode(size_t index)
116     {
117         ImageDecoder* decoder = 0;
118         OwnPtr<ScaledImageFragment> fragment = m_generator->decode(index, &decoder);
119         delete decoder;
120         return fragment.release();
121     }
122
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;
129 };
130
131 TEST_F(ImageFrameGeneratorTest, cacheHit)
132 {
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);
139
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);
146 }
147
148 TEST_F(ImageFrameGeneratorTest, cacheMissWithIncompleteDecode)
149 {
150     setFrameStatus(ImageFrame::FramePartial);
151
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());
159
160     addNewData();
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);
169 }
170
171 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesComplete)
172 {
173     setFrameStatus(ImageFrame::FramePartial);
174
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());
183
184     setFrameStatus(ImageFrame::FrameComplete);
185     addNewData();
186
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());
195
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);
200 }
201
202 static void decodeThreadMain(ImageFrameGenerator* generator)
203 {
204     const ScaledImageFragment* tempImage = generator->decodeAndScale(fullSize());
205     ImageDecodingStore::instance()->unlockCache(generator, tempImage);
206 }
207
208 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesCompleteMultiThreaded)
209 {
210     setFrameStatus(ImageFrame::FramePartial);
211
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());
220
221     // LocalFrame can now be decoded completely.
222     setFrameStatus(ImageFrame::FrameComplete);
223     addNewData();
224     OwnPtr<WebThread> thread = adoptPtr(Platform::current()->createThread("DecodeThread"));
225     thread->postTask(new Task(WTF::bind(&decodeThreadMain, m_generator.get())));
226     thread.clear();
227
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());
233
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);
238 }
239
240 TEST_F(ImageFrameGeneratorTest, incompleteBitmapCopied)
241 {
242     setFrameStatus(ImageFrame::FramePartial);
243
244     const ScaledImageFragment* tempImage= m_generator->decodeAndScale(fullSize());
245     EXPECT_FALSE(tempImage->isComplete());
246     EXPECT_EQ(1, m_frameBufferRequestCount);
247
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);
254 }
255
256 TEST_F(ImageFrameGeneratorTest, resumeDecodeEmptyFrameTurnsComplete)
257 {
258     m_generator = ImageFrameGenerator::create(fullSize(), m_data, false, true);
259     useMockImageDecoderFactory();
260     setFrameStatus(ImageFrame::FrameComplete);
261
262     const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize(), 0);
263     EXPECT_TRUE(tempImage->isComplete());
264     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
265
266     setFrameStatus(ImageFrame::FrameEmpty);
267     setNextFrameStatus(ImageFrame::FrameComplete);
268     EXPECT_FALSE(m_generator->decodeAndScale(fullSize(), 1));
269 }
270
271 TEST_F(ImageFrameGeneratorTest, frameHasAlpha)
272 {
273     setFrameStatus(ImageFrame::FramePartial);
274     ImageDecodingStore::instance()->unlockCache(m_generator.get(), m_generator->decodeAndScale(fullSize(), 1));
275     EXPECT_TRUE(m_generator->hasAlpha(1));
276
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);
282
283     setFrameStatus(ImageFrame::FrameComplete);
284     ImageDecodingStore::instance()->unlockCache(m_generator.get(), m_generator->decodeAndScale(fullSize(), 1));
285     EXPECT_FALSE(m_generator->hasAlpha(1));
286 }
287
288 namespace {
289
290 class MockAllocator : public SkBitmap::Allocator {
291 public:
292     // N starts from 0.
293     MockAllocator(int failAtNthCall)
294         : m_callCount(0)
295         , m_failAtNthCall(failAtNthCall)
296         , m_defaultAllocator(adoptPtr(new DiscardablePixelRefAllocator()))
297     {
298     }
299
300     virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* colorTable) OVERRIDE
301     {
302         if (m_callCount++ == m_failAtNthCall)
303             return false;
304         return m_defaultAllocator->allocPixelRef(bitmap, colorTable);
305     }
306
307     int m_callCount;
308     int m_failAtNthCall;
309     OwnPtr<SkBitmap::Allocator> m_defaultAllocator;
310 };
311
312 } // namespace
313
314 TEST_F(ImageFrameGeneratorTest, decodingAllocatorFailure)
315 {
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
327             // were successful.
328             EXPECT_TRUE(image);
329             break;
330         }
331         EXPECT_FALSE(image);
332     }
333 }
334
335 } // namespace blink