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 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "platform/graphics/DeferredImageDecoder.h" 28 29#include "platform/graphics/DecodingImageGenerator.h" 30#include "platform/graphics/ImageDecodingStore.h" 31#include "third_party/skia/include/core/SkImageInfo.h" 32#include "wtf/PassOwnPtr.h" 33 34namespace blink { 35 36namespace { 37 38// URI label for SkDiscardablePixelRef. 39const char labelDiscardable[] = "discardable"; 40 41} // namespace 42 43bool DeferredImageDecoder::s_enabled = false; 44 45DeferredImageDecoder::DeferredImageDecoder(PassOwnPtr<ImageDecoder> actualDecoder) 46 : m_allDataReceived(false) 47 , m_lastDataSize(0) 48 , m_dataChanged(false) 49 , m_actualDecoder(actualDecoder) 50 , m_orientation(DefaultImageOrientation) 51 , m_repetitionCount(cAnimationNone) 52 , m_hasColorProfile(false) 53{ 54} 55 56DeferredImageDecoder::~DeferredImageDecoder() 57{ 58} 59 60PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorOption) 61{ 62 OwnPtr<ImageDecoder> actualDecoder = ImageDecoder::create(data, alphaOption, gammaAndColorOption); 63 return actualDecoder ? adoptPtr(new DeferredImageDecoder(actualDecoder.release())) : nullptr; 64} 65 66PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::createForTesting(PassOwnPtr<ImageDecoder> decoder) 67{ 68 return adoptPtr(new DeferredImageDecoder(decoder)); 69} 70 71bool DeferredImageDecoder::isLazyDecoded(const SkBitmap& bitmap) 72{ 73 return bitmap.pixelRef() 74 && bitmap.pixelRef()->getURI() 75 && !memcmp(bitmap.pixelRef()->getURI(), labelDiscardable, sizeof(labelDiscardable)); 76} 77 78void DeferredImageDecoder::setEnabled(bool enabled) 79{ 80 s_enabled = enabled; 81} 82 83bool DeferredImageDecoder::enabled() 84{ 85 return s_enabled; 86} 87 88String DeferredImageDecoder::filenameExtension() const 89{ 90 return m_actualDecoder ? m_actualDecoder->filenameExtension() : m_filenameExtension; 91} 92 93ImageFrame* DeferredImageDecoder::frameBufferAtIndex(size_t index) 94{ 95 prepareLazyDecodedFrames(); 96 if (index < m_lazyDecodedFrames.size()) { 97 // ImageFrameGenerator has the latest known alpha state. There will 98 // be a performance boost if this frame is opaque. 99 m_lazyDecodedFrames[index]->setHasAlpha(m_frameGenerator->hasAlpha(index)); 100 return m_lazyDecodedFrames[index].get(); 101 } 102 if (m_actualDecoder) 103 return m_actualDecoder->frameBufferAtIndex(index); 104 return 0; 105} 106 107void DeferredImageDecoder::setData(SharedBuffer& data, bool allDataReceived) 108{ 109 if (m_actualDecoder) { 110 const bool firstData = !m_data; 111 const bool moreData = data.size() > m_lastDataSize; 112 m_dataChanged = firstData || moreData; 113 m_data = RefPtr<SharedBuffer>(data); 114 m_lastDataSize = data.size(); 115 m_allDataReceived = allDataReceived; 116 m_actualDecoder->setData(&data, allDataReceived); 117 prepareLazyDecodedFrames(); 118 } 119 120 if (m_frameGenerator) 121 m_frameGenerator->setData(&data, allDataReceived); 122} 123 124bool DeferredImageDecoder::isSizeAvailable() 125{ 126 // m_actualDecoder is 0 only if image decoding is deferred and that means 127 // the image header decoded successfully and the size is available. 128 return m_actualDecoder ? m_actualDecoder->isSizeAvailable() : true; 129} 130 131bool DeferredImageDecoder::hasColorProfile() const 132{ 133 return m_actualDecoder ? m_actualDecoder->hasColorProfile() : m_hasColorProfile; 134} 135 136IntSize DeferredImageDecoder::size() const 137{ 138 return m_actualDecoder ? m_actualDecoder->size() : m_size; 139} 140 141IntSize DeferredImageDecoder::frameSizeAtIndex(size_t index) const 142{ 143 // FIXME: LocalFrame size is assumed to be uniform. This might not be true for 144 // future supported codecs. 145 return m_actualDecoder ? m_actualDecoder->frameSizeAtIndex(index) : m_size; 146} 147 148size_t DeferredImageDecoder::frameCount() 149{ 150 return m_actualDecoder ? m_actualDecoder->frameCount() : m_lazyDecodedFrames.size(); 151} 152 153int DeferredImageDecoder::repetitionCount() const 154{ 155 return m_actualDecoder ? m_actualDecoder->repetitionCount() : m_repetitionCount; 156} 157 158size_t DeferredImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame) 159{ 160 // If image decoding is deferred then frame buffer cache is managed by 161 // the compositor and this call is ignored. 162 return m_actualDecoder ? m_actualDecoder->clearCacheExceptFrame(clearExceptFrame) : 0; 163} 164 165bool DeferredImageDecoder::frameHasAlphaAtIndex(size_t index) const 166{ 167 if (m_actualDecoder) 168 return m_actualDecoder->frameHasAlphaAtIndex(index); 169 if (!m_frameGenerator->isMultiFrame()) 170 return m_frameGenerator->hasAlpha(index); 171 return true; 172} 173 174bool DeferredImageDecoder::frameIsCompleteAtIndex(size_t index) const 175{ 176 if (m_actualDecoder) 177 return m_actualDecoder->frameIsCompleteAtIndex(index); 178 if (index < m_lazyDecodedFrames.size()) 179 return m_lazyDecodedFrames[index]->status() == ImageFrame::FrameComplete; 180 return false; 181} 182 183float DeferredImageDecoder::frameDurationAtIndex(size_t index) const 184{ 185 if (m_actualDecoder) 186 return m_actualDecoder->frameDurationAtIndex(index); 187 if (index < m_lazyDecodedFrames.size()) 188 return m_lazyDecodedFrames[index]->duration(); 189 return 0; 190} 191 192unsigned DeferredImageDecoder::frameBytesAtIndex(size_t index) const 193{ 194 // If frame decoding is deferred then it is not managed by MemoryCache 195 // so return 0 here. 196 return m_frameGenerator ? 0 : m_actualDecoder->frameBytesAtIndex(index); 197} 198 199ImageOrientation DeferredImageDecoder::orientation() const 200{ 201 return m_actualDecoder ? m_actualDecoder->orientation() : m_orientation; 202} 203 204void DeferredImageDecoder::activateLazyDecoding() 205{ 206 if (m_frameGenerator) 207 return; 208 m_size = m_actualDecoder->size(); 209 m_orientation = m_actualDecoder->orientation(); 210 m_filenameExtension = m_actualDecoder->filenameExtension(); 211 m_hasColorProfile = m_actualDecoder->hasColorProfile(); 212 const bool isSingleFrame = m_actualDecoder->repetitionCount() == cAnimationNone || (m_allDataReceived && m_actualDecoder->frameCount() == 1u); 213 m_frameGenerator = ImageFrameGenerator::create(SkISize::Make(m_actualDecoder->decodedSize().width(), m_actualDecoder->decodedSize().height()), m_data, m_allDataReceived, !isSingleFrame); 214} 215 216void DeferredImageDecoder::prepareLazyDecodedFrames() 217{ 218 if (!s_enabled 219 || !m_actualDecoder 220 || !m_actualDecoder->isSizeAvailable() 221 || m_actualDecoder->filenameExtension() == "ico") 222 return; 223 224 activateLazyDecoding(); 225 226 const size_t previousSize = m_lazyDecodedFrames.size(); 227 m_lazyDecodedFrames.resize(m_actualDecoder->frameCount()); 228 229 // We have encountered a broken image file. Simply bail. 230 if (m_lazyDecodedFrames.size() < previousSize) 231 return; 232 233 for (size_t i = previousSize; i < m_lazyDecodedFrames.size(); ++i) { 234 OwnPtr<ImageFrame> frame(adoptPtr(new ImageFrame())); 235 frame->setSkBitmap(createBitmap(i)); 236 frame->setDuration(m_actualDecoder->frameDurationAtIndex(i)); 237 frame->setStatus(m_actualDecoder->frameIsCompleteAtIndex(i) ? ImageFrame::FrameComplete : ImageFrame::FramePartial); 238 m_lazyDecodedFrames[i] = frame.release(); 239 } 240 241 // The last lazy decoded frame created from previous call might be 242 // incomplete so update its state. 243 if (previousSize) { 244 const size_t lastFrame = previousSize - 1; 245 m_lazyDecodedFrames[lastFrame]->setStatus(m_actualDecoder->frameIsCompleteAtIndex(lastFrame) ? ImageFrame::FrameComplete : ImageFrame::FramePartial); 246 247 // If data has changed then create a new bitmap. This forces 248 // Skia to decode again. 249 if (m_dataChanged) { 250 m_dataChanged = false; 251 m_lazyDecodedFrames[lastFrame]->setSkBitmap(createBitmap(lastFrame)); 252 } 253 } 254 255 if (m_allDataReceived) { 256 m_repetitionCount = m_actualDecoder->repetitionCount(); 257 m_actualDecoder.clear(); 258 m_data = nullptr; 259 } 260} 261 262// Creates a SkBitmap that is backed by SkDiscardablePixelRef. 263SkBitmap DeferredImageDecoder::createBitmap(size_t index) 264{ 265 IntSize decodedSize = m_actualDecoder->decodedSize(); 266 ASSERT(decodedSize.width() > 0); 267 ASSERT(decodedSize.height() > 0); 268 269#if SK_B32_SHIFT // Little-endian RGBA pixels. (Android) 270 const SkColorType colorType = kRGBA_8888_SkColorType; 271#else 272 const SkColorType colorType = kBGRA_8888_SkColorType; 273#endif 274 const SkImageInfo info = SkImageInfo::Make(decodedSize.width(), decodedSize.height(), colorType, kPremul_SkAlphaType); 275 276 SkBitmap bitmap; 277 DecodingImageGenerator* generator = new DecodingImageGenerator(m_frameGenerator, info, index); 278 bool installed = SkInstallDiscardablePixelRef(generator, &bitmap); 279 ASSERT_UNUSED(installed, installed); 280 bitmap.pixelRef()->setURI(labelDiscardable); 281 generator->setGenerationId(bitmap.getGenerationID()); 282 return bitmap; 283} 284 285bool DeferredImageDecoder::hotSpot(IntPoint& hotSpot) const 286{ 287 // TODO: Implement. 288 return m_actualDecoder ? m_actualDecoder->hotSpot(hotSpot) : false; 289} 290 291} // namespace blink 292