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
37namespace WebCore {
38
39namespace {
40
41// Helper methods to generate standard sizes.
42SkISize fullSize() { return SkISize::Make(100, 100); }
43SkISize scaledSize() { return SkISize::Make(50, 50); }
44
45} // namespace
46
47class ImageFrameGeneratorTest : public ::testing::Test, public MockImageDecoderClient {
48public:
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
87protected:
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
130TEST_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
145TEST_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
168TEST_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
196TEST_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
219TEST_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
242TEST_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
273TEST_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
309static void decodeThreadMain(ImageFrameGenerator* generator)
310{
311    const ScaledImageFragment* tempImage = generator->decodeAndScale(fullSize());
312    ImageDecodingStore::instance()->unlockCache(generator, tempImage);
313}
314
315TEST_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
347TEST_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
375TEST_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
391TEST_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
406TEST_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
423namespace {
424
425class MockAllocator : public SkBitmap::Allocator {
426public:
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
449TEST_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