[chromium] Minimize memcpy for encoded image data in ImageFrameGenerator
[WebKit-https.git] / Source / WebKit / chromium / tests / 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
28 #include "ImageFrameGenerator.h"
29
30 #include "ImageDecodingStore.h"
31 #include "MockImageDecoder.h"
32 #include "SharedBuffer.h"
33 #include <gtest/gtest.h>
34 #include <wtf/Threading.h>
35
36 using namespace WebCore;
37
38 namespace {
39
40 class ImageFrameGeneratorTest;
41
42 // Helper methods to generate standard sizes.
43 SkISize fullSize() { return SkISize::Make(100, 100); }
44 SkISize scaledSize() { return SkISize::Make(50, 50); }
45
46 class ImageFrameGeneratorTest;
47
48 class MockImageDecoderFactory : public ImageDecoderFactory {
49 public:
50     static PassOwnPtr<MockImageDecoderFactory> create(ImageFrameGeneratorTest* test)
51     {
52         return adoptPtr(new MockImageDecoderFactory(test));
53     }
54
55     virtual PassOwnPtr<ImageDecoder> create();
56
57 private:
58     MockImageDecoderFactory(ImageFrameGeneratorTest* test)
59         : m_test(test)
60     {
61     }
62
63     ImageFrameGeneratorTest* m_test;
64 };
65
66 class ImageFrameGeneratorTest : public ::testing::Test, public MockImageDecoderClient {
67 public:
68     virtual void SetUp()
69     {
70         ImageDecodingStore::initializeOnce();
71         m_data = SharedBuffer::create();
72         m_generator = ImageFrameGenerator::create(fullSize(), m_data, true);
73         m_generator->setImageDecoderFactoryForTesting(MockImageDecoderFactory::create(this));
74         m_decodersDestroyed = 0;
75         m_frameBufferRequestCount = 0;
76         m_frameStatus = ImageFrame::FrameEmpty;
77     }
78
79     virtual void TearDown()
80     {
81         ImageDecodingStore::shutdown();
82     }
83
84     virtual void decoderBeingDestroyed()
85     {
86         ++m_decodersDestroyed;
87     }
88
89     virtual void frameBufferRequested()
90     {
91         ++m_frameBufferRequestCount;
92     }
93
94     virtual ImageFrame::FrameStatus frameStatus()
95     {
96         return m_frameStatus;
97     }
98
99 protected:
100     PassOwnPtr<ScaledImageFragment> createCompleteImage(const SkISize& size)
101     {
102         SkBitmap bitmap;
103         bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
104         bitmap.allocPixels();
105         return ScaledImageFragment::create(size, bitmap, true);
106     }
107
108     void addNewData()
109     {
110         m_data->append("g", 1);
111         m_generator->setData(m_data, false);
112     }
113
114     void setFrameStatus(ImageFrame::FrameStatus status)  { m_frameStatus = status; }
115
116     RefPtr<SharedBuffer> m_data;
117     RefPtr<ImageFrameGenerator> m_generator;
118     int m_decodersDestroyed;
119     int m_frameBufferRequestCount;
120     ImageFrame::FrameStatus m_frameStatus;
121 };
122
123 PassOwnPtr<ImageDecoder> MockImageDecoderFactory::create()
124 {
125     OwnPtr<MockImageDecoder> decoder = MockImageDecoder::create(m_test);
126     decoder->setSize(fullSize().width(), fullSize().height());
127     return decoder.release();
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     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
141     EXPECT_EQ(0, m_frameBufferRequestCount);
142 }
143
144 TEST_F(ImageFrameGeneratorTest, cacheMissWithScale)
145 {
146     const ScaledImageFragment* fullImage = ImageDecodingStore::instance()->insertAndLockCache(
147         m_generator.get(), createCompleteImage(fullSize()));
148     EXPECT_EQ(fullSize(), fullImage->scaledSize());
149     ImageDecodingStore::instance()->unlockCache(m_generator.get(), fullImage);
150
151     // Cache miss because of scaled size not found.
152     const ScaledImageFragment* scaledImage = m_generator->decodeAndScale(scaledSize());
153     EXPECT_NE(fullImage, scaledImage);
154     EXPECT_EQ(scaledSize(), scaledImage->scaledSize());
155     ImageDecodingStore::instance()->unlockCache(m_generator.get(), scaledImage);
156
157     // Cache hit.
158     const ScaledImageFragment* tempImage = m_generator->decodeAndScale(scaledSize());
159     EXPECT_EQ(scaledImage, tempImage);
160     EXPECT_EQ(scaledSize(), tempImage->scaledSize());
161     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
162     EXPECT_EQ(0, m_frameBufferRequestCount);
163 }
164
165 TEST_F(ImageFrameGeneratorTest, cacheMissWithDecodeAndScale)
166 {
167     setFrameStatus(ImageFrame::FrameComplete);
168
169     // Cache miss.
170     const ScaledImageFragment* scaledImage = m_generator->decodeAndScale(scaledSize());
171     EXPECT_EQ(1, m_frameBufferRequestCount);
172     EXPECT_EQ(scaledSize(), scaledImage->scaledSize());
173     ImageDecodingStore::instance()->unlockCache(m_generator.get(), scaledImage);
174     EXPECT_EQ(1, m_decodersDestroyed);
175
176     // Cache hit.
177     const ScaledImageFragment* fullImage = m_generator->decodeAndScale(fullSize());
178     EXPECT_NE(scaledImage, fullImage);
179     EXPECT_EQ(fullSize(), fullImage->scaledSize());
180     ImageDecodingStore::instance()->unlockCache(m_generator.get(), fullImage);
181
182     // Cache hit.
183     const ScaledImageFragment* tempImage = m_generator->decodeAndScale(scaledSize());
184     EXPECT_EQ(scaledImage, tempImage);
185     EXPECT_EQ(scaledSize(), tempImage->scaledSize());
186     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
187     EXPECT_EQ(1, m_frameBufferRequestCount);
188 }
189
190 TEST_F(ImageFrameGeneratorTest, cacheMissWithIncompleteDecode)
191 {
192     setFrameStatus(ImageFrame::FramePartial);
193
194     const ScaledImageFragment* tempImage= m_generator->decodeAndScale(fullSize());
195     EXPECT_FALSE(tempImage->isComplete());
196     EXPECT_EQ(1, m_frameBufferRequestCount);
197     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
198     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
199
200     addNewData();
201     tempImage = m_generator->decodeAndScale(fullSize());
202     EXPECT_FALSE(tempImage->isComplete());
203     EXPECT_EQ(2, m_frameBufferRequestCount);
204     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
205     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
206     EXPECT_EQ(0, m_decodersDestroyed);
207 }
208
209 TEST_F(ImageFrameGeneratorTest, cacheMissWithIncompleteDecodeNoNewData)
210 {
211     setFrameStatus(ImageFrame::FramePartial);
212
213     const ScaledImageFragment* tempImage= m_generator->decodeAndScale(fullSize());
214     EXPECT_FALSE(tempImage->isComplete());
215     EXPECT_EQ(1, m_frameBufferRequestCount);
216     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
217     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
218
219     tempImage = m_generator->decodeAndScale(fullSize());
220     EXPECT_FALSE(tempImage->isComplete());
221     EXPECT_EQ(1, m_frameBufferRequestCount);
222     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
223     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
224     EXPECT_EQ(0, m_decodersDestroyed);
225 }
226
227 TEST_F(ImageFrameGeneratorTest, cacheMissWithIncompleteDecodeAndScale)
228 {
229     setFrameStatus(ImageFrame::FramePartial);
230
231     const ScaledImageFragment* tempImage= m_generator->decodeAndScale(scaledSize());
232     EXPECT_FALSE(tempImage->isComplete());
233     EXPECT_EQ(1, m_frameBufferRequestCount);
234     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
235     EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
236
237     addNewData();
238     tempImage = m_generator->decodeAndScale(scaledSize());
239     EXPECT_FALSE(tempImage->isComplete());
240     EXPECT_EQ(2, m_frameBufferRequestCount);
241     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
242     EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
243     EXPECT_EQ(0, m_decodersDestroyed);
244 }
245
246 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesComplete)
247 {
248     setFrameStatus(ImageFrame::FramePartial);
249
250     const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize());
251     EXPECT_FALSE(tempImage->isComplete());
252     EXPECT_EQ(1, m_frameBufferRequestCount);
253     EXPECT_EQ(0, m_decodersDestroyed);
254     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
255     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
256
257     setFrameStatus(ImageFrame::FrameComplete);
258     addNewData();
259
260     tempImage = m_generator->decodeAndScale(fullSize());
261     EXPECT_TRUE(tempImage->isComplete());
262     EXPECT_EQ(2, m_frameBufferRequestCount);
263     EXPECT_EQ(1, m_decodersDestroyed);
264     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
265     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
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(2u, ImageDecodingStore::instance()->cacheEntries());
283
284     setFrameStatus(ImageFrame::FrameComplete);
285     addNewData();
286
287     tempImage = m_generator->decodeAndScale(scaledSize());
288     EXPECT_TRUE(tempImage->isComplete());
289     EXPECT_EQ(2, m_frameBufferRequestCount);
290     EXPECT_EQ(1, m_decodersDestroyed);
291     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
292     EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
293
294     tempImage = m_generator->decodeAndScale(scaledSize());
295     EXPECT_TRUE(tempImage->isComplete());
296     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
297
298     tempImage = m_generator->decodeAndScale(fullSize());
299     EXPECT_TRUE(tempImage->isComplete());
300     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
301
302     EXPECT_EQ(2, m_frameBufferRequestCount);
303 }
304
305 static void decodeThreadMain(void* arg)
306 {
307     ImageFrameGenerator* generator = reinterpret_cast<ImageFrameGenerator*>(arg);
308     const ScaledImageFragment* tempImage = generator->decodeAndScale(fullSize());
309     ImageDecodingStore::instance()->unlockCache(generator, tempImage);
310 }
311
312 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesCompleteMultiThreaded)
313 {
314     WTF::initializeThreading();
315     setFrameStatus(ImageFrame::FramePartial);
316
317     const ScaledImageFragment* tempImage = m_generator->decodeAndScale(fullSize());
318     EXPECT_FALSE(tempImage->isComplete());
319     EXPECT_EQ(1, m_frameBufferRequestCount);
320     EXPECT_EQ(0, m_decodersDestroyed);
321     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
322     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
323
324     // Frame can now be decoded completely.
325     setFrameStatus(ImageFrame::FrameComplete);
326     addNewData();
327     ThreadIdentifier threadID = createThread(&decodeThreadMain, m_generator.get(), "DecodeThread");
328     waitForThreadCompletion(threadID);
329
330     EXPECT_EQ(2, m_frameBufferRequestCount);
331     EXPECT_EQ(1, m_decodersDestroyed);
332     EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
333
334     tempImage = m_generator->decodeAndScale(fullSize());
335     EXPECT_TRUE(tempImage->isComplete());
336     EXPECT_EQ(2, m_frameBufferRequestCount);
337     ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
338 }
339
340 } // namespace