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 blink { 38 39namespace { 40 41// Helper methods to generate standard sizes. 42SkISize fullSize() { return SkISize::Make(100, 100); } 43 44SkImageInfo imageInfo() 45{ 46 return SkImageInfo::Make(100, 100, kBGRA_8888_SkColorType, kOpaque_SkAlphaType); 47} 48 49} // namespace 50 51class ImageFrameGeneratorTest : public ::testing::Test, public MockImageDecoderClient { 52public: 53 virtual void SetUp() OVERRIDE 54 { 55 ImageDecodingStore::instance()->setCacheLimitInBytes(1024 * 1024); 56 m_data = SharedBuffer::create(); 57 m_generator = ImageFrameGenerator::create(fullSize(), m_data, false); 58 useMockImageDecoderFactory(); 59 m_decodersDestroyed = 0; 60 m_frameBufferRequestCount = 0; 61 m_status = ImageFrame::FrameEmpty; 62 } 63 64 virtual void TearDown() OVERRIDE 65 { 66 ImageDecodingStore::instance()->clear(); 67 } 68 69 virtual void decoderBeingDestroyed() OVERRIDE 70 { 71 ++m_decodersDestroyed; 72 } 73 74 virtual void frameBufferRequested() OVERRIDE 75 { 76 ++m_frameBufferRequestCount; 77 } 78 79 virtual ImageFrame::Status status() OVERRIDE 80 { 81 ImageFrame::Status currentStatus = m_status; 82 m_status = m_nextFrameStatus; 83 return currentStatus; 84 } 85 86 virtual size_t frameCount() OVERRIDE { return 1; } 87 virtual int repetitionCount() const OVERRIDE { return cAnimationNone; } 88 virtual float frameDuration() const OVERRIDE { return 0; } 89 90protected: 91 void useMockImageDecoderFactory() 92 { 93 m_generator->setImageDecoderFactory(MockImageDecoderFactory::create(this, fullSize())); 94 } 95 96 void addNewData() 97 { 98 m_data->append("g", 1); 99 m_generator->setData(m_data, false); 100 } 101 102 void setFrameStatus(ImageFrame::Status status) { m_status = m_nextFrameStatus = status; } 103 void setNextFrameStatus(ImageFrame::Status status) { m_nextFrameStatus = status; } 104 105 RefPtr<SharedBuffer> m_data; 106 RefPtr<ImageFrameGenerator> m_generator; 107 int m_decodersDestroyed; 108 int m_frameBufferRequestCount; 109 ImageFrame::Status m_status; 110 ImageFrame::Status m_nextFrameStatus; 111}; 112 113TEST_F(ImageFrameGeneratorTest, incompleteDecode) 114{ 115 setFrameStatus(ImageFrame::FramePartial); 116 117 char buffer[100 * 100 * 4]; 118 m_generator->decodeAndScale(imageInfo(), 0, buffer, 100 * 4); 119 EXPECT_EQ(1, m_frameBufferRequestCount); 120 121 addNewData(); 122 m_generator->decodeAndScale(imageInfo(), 0, buffer, 100 * 4); 123 EXPECT_EQ(2, m_frameBufferRequestCount); 124 EXPECT_EQ(0, m_decodersDestroyed); 125} 126 127TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesComplete) 128{ 129 setFrameStatus(ImageFrame::FramePartial); 130 131 char buffer[100 * 100 * 4]; 132 m_generator->decodeAndScale(imageInfo(), 0, buffer, 100 * 4); 133 EXPECT_EQ(1, m_frameBufferRequestCount); 134 EXPECT_EQ(0, m_decodersDestroyed); 135 136 setFrameStatus(ImageFrame::FrameComplete); 137 addNewData(); 138 139 m_generator->decodeAndScale(imageInfo(), 0, buffer, 100 * 4); 140 EXPECT_EQ(2, m_frameBufferRequestCount); 141 EXPECT_EQ(1, m_decodersDestroyed); 142 143 // Decoder created again. 144 m_generator->decodeAndScale(imageInfo(), 0, buffer, 100 * 4); 145 EXPECT_EQ(3, m_frameBufferRequestCount); 146} 147 148static void decodeThreadMain(ImageFrameGenerator* generator) 149{ 150 char buffer[100 * 100 * 4]; 151 generator->decodeAndScale(imageInfo(), 0, buffer, 100 * 4); 152} 153 154TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesCompleteMultiThreaded) 155{ 156 setFrameStatus(ImageFrame::FramePartial); 157 158 char buffer[100 * 100 * 4]; 159 m_generator->decodeAndScale(imageInfo(), 0, buffer, 100 * 4); 160 EXPECT_EQ(1, m_frameBufferRequestCount); 161 EXPECT_EQ(0, m_decodersDestroyed); 162 163 // LocalFrame can now be decoded completely. 164 setFrameStatus(ImageFrame::FrameComplete); 165 addNewData(); 166 OwnPtr<WebThread> thread = adoptPtr(Platform::current()->createThread("DecodeThread")); 167 thread->postTask(new Task(WTF::bind(&decodeThreadMain, m_generator.get()))); 168 thread.clear(); 169 EXPECT_EQ(2, m_frameBufferRequestCount); 170 EXPECT_EQ(1, m_decodersDestroyed); 171 172 // Decoder created again. 173 m_generator->decodeAndScale(imageInfo(), 0, buffer, 100 * 4); 174 EXPECT_EQ(3, m_frameBufferRequestCount); 175} 176 177TEST_F(ImageFrameGeneratorTest, frameHasAlpha) 178{ 179 setFrameStatus(ImageFrame::FramePartial); 180 181 char buffer[100 * 100 * 4]; 182 m_generator->decodeAndScale(imageInfo(), 1, buffer, 100 * 4); 183 EXPECT_TRUE(m_generator->hasAlpha(1)); 184 EXPECT_EQ(1, m_frameBufferRequestCount); 185 186 ImageDecoder* tempDecoder = 0; 187 EXPECT_TRUE(ImageDecodingStore::instance()->lockDecoder(m_generator.get(), fullSize(), &tempDecoder)); 188 ASSERT_TRUE(tempDecoder); 189 static_cast<MockImageDecoder*>(tempDecoder)->setFrameHasAlpha(false); 190 ImageDecodingStore::instance()->unlockDecoder(m_generator.get(), tempDecoder); 191 192 setFrameStatus(ImageFrame::FrameComplete); 193 m_generator->decodeAndScale(imageInfo(), 1, buffer, 100 * 4); 194 EXPECT_EQ(2, m_frameBufferRequestCount); 195 EXPECT_FALSE(m_generator->hasAlpha(1)); 196} 197 198} // namespace blink 199