2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "platform/graphics/DeferredImageDecoder.h"
29 #include "platform/graphics/DecodingImageGenerator.h"
30 #include "platform/graphics/ImageDecodingStore.h"
31 #include "platform/graphics/LazyDecodingPixelRef.h"
32 #include "third_party/skia/include/core/SkImageInfo.h"
33 #include "wtf/PassOwnPtr.h"
39 // URI label for a lazily decoded SkPixelRef.
40 const char labelLazyDecoded[] = "lazy";
42 // URI label for SkDiscardablePixelRef.
43 const char labelDiscardable[] = "discardable";
47 bool DeferredImageDecoder::s_enabled = false;
48 bool DeferredImageDecoder::s_skiaDiscardableMemoryEnabled = false;
50 DeferredImageDecoder::DeferredImageDecoder(PassOwnPtr<ImageDecoder> actualDecoder)
51 : m_allDataReceived(false)
53 , m_dataChanged(false)
54 , m_actualDecoder(actualDecoder)
55 , m_orientation(DefaultImageOrientation)
56 , m_repetitionCount(cAnimationNone)
60 DeferredImageDecoder::~DeferredImageDecoder()
64 PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorOption)
66 OwnPtr<ImageDecoder> actualDecoder = ImageDecoder::create(data, alphaOption, gammaAndColorOption);
67 return actualDecoder ? adoptPtr(new DeferredImageDecoder(actualDecoder.release())) : nullptr;
70 PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::createForTesting(PassOwnPtr<ImageDecoder> decoder)
72 return adoptPtr(new DeferredImageDecoder(decoder));
75 bool DeferredImageDecoder::isLazyDecoded(const SkBitmap& bitmap)
77 return bitmap.pixelRef()
78 && bitmap.pixelRef()->getURI()
79 && (!memcmp(bitmap.pixelRef()->getURI(), labelLazyDecoded, sizeof(labelLazyDecoded))
80 || !memcmp(bitmap.pixelRef()->getURI(), labelDiscardable, sizeof(labelDiscardable)));
83 void DeferredImageDecoder::setEnabled(bool enabled)
87 // FIXME: This code is temporary to enable discardable memory for
88 // non-Android platforms. In the future all platforms will be
89 // the same and we can remove this code.
90 s_skiaDiscardableMemoryEnabled = enabled;
92 ImageDecodingStore::setImageCachingEnabled(false);
96 String DeferredImageDecoder::filenameExtension() const
98 return m_actualDecoder ? m_actualDecoder->filenameExtension() : m_filenameExtension;
101 ImageFrame* DeferredImageDecoder::frameBufferAtIndex(size_t index)
103 prepareLazyDecodedFrames();
104 if (index < m_lazyDecodedFrames.size()) {
105 // ImageFrameGenerator has the latest known alpha state. There will
106 // be a performance boost if this frame is opaque.
107 m_lazyDecodedFrames[index]->setHasAlpha(m_frameGenerator->hasAlpha(index));
108 return m_lazyDecodedFrames[index].get();
111 return m_actualDecoder->frameBufferAtIndex(index);
115 void DeferredImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
117 if (m_actualDecoder) {
118 const bool firstData = !m_data && data;
119 const bool moreData = data && data->size() > m_lastDataSize;
120 m_dataChanged = firstData || moreData;
122 m_lastDataSize = data->size();
123 m_allDataReceived = allDataReceived;
124 m_actualDecoder->setData(data, allDataReceived);
125 prepareLazyDecodedFrames();
128 if (m_frameGenerator)
129 m_frameGenerator->setData(data, allDataReceived);
132 bool DeferredImageDecoder::isSizeAvailable()
134 // m_actualDecoder is 0 only if image decoding is deferred and that
135 // means image header decoded successfully and size is available.
136 return m_actualDecoder ? m_actualDecoder->isSizeAvailable() : true;
139 IntSize DeferredImageDecoder::size() const
141 return m_actualDecoder ? m_actualDecoder->size() : m_size;
144 IntSize DeferredImageDecoder::frameSizeAtIndex(size_t index) const
146 // FIXME: LocalFrame size is assumed to be uniform. This might not be true for
147 // future supported codecs.
148 return m_actualDecoder ? m_actualDecoder->frameSizeAtIndex(index) : m_size;
151 size_t DeferredImageDecoder::frameCount()
153 return m_actualDecoder ? m_actualDecoder->frameCount() : m_lazyDecodedFrames.size();
156 int DeferredImageDecoder::repetitionCount() const
158 return m_actualDecoder ? m_actualDecoder->repetitionCount() : m_repetitionCount;
161 size_t DeferredImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame)
163 // If image decoding is deferred then frame buffer cache is managed by
164 // the compositor and this call is ignored.
165 return m_actualDecoder ? m_actualDecoder->clearCacheExceptFrame(clearExceptFrame) : 0;
168 bool DeferredImageDecoder::frameHasAlphaAtIndex(size_t index) const
171 return m_actualDecoder->frameHasAlphaAtIndex(index);
172 if (!m_frameGenerator->isMultiFrame())
173 return m_frameGenerator->hasAlpha(index);
177 bool DeferredImageDecoder::frameIsCompleteAtIndex(size_t index) const
180 return m_actualDecoder->frameIsCompleteAtIndex(index);
181 if (index < m_lazyDecodedFrames.size())
182 return m_lazyDecodedFrames[index]->status() == ImageFrame::FrameComplete;
186 float DeferredImageDecoder::frameDurationAtIndex(size_t index) const
189 return m_actualDecoder->frameDurationAtIndex(index);
190 if (index < m_lazyDecodedFrames.size())
191 return m_lazyDecodedFrames[index]->duration();
195 unsigned DeferredImageDecoder::frameBytesAtIndex(size_t index) const
197 // If frame decoding is deferred then it is not managed by MemoryCache
199 return m_frameGenerator ? 0 : m_actualDecoder->frameBytesAtIndex(index);
202 ImageOrientation DeferredImageDecoder::orientation() const
204 return m_actualDecoder ? m_actualDecoder->orientation() : m_orientation;
207 void DeferredImageDecoder::activateLazyDecoding()
209 if (m_frameGenerator)
211 m_size = m_actualDecoder->size();
212 m_orientation = m_actualDecoder->orientation();
213 m_filenameExtension = m_actualDecoder->filenameExtension();
214 const bool isSingleFrame = m_actualDecoder->repetitionCount() == cAnimationNone || (m_allDataReceived && m_actualDecoder->frameCount() == 1u);
215 m_frameGenerator = ImageFrameGenerator::create(SkISize::Make(m_actualDecoder->decodedSize().width(), m_actualDecoder->decodedSize().height()), m_data, m_allDataReceived, !isSingleFrame);
218 void DeferredImageDecoder::prepareLazyDecodedFrames()
222 || !m_actualDecoder->isSizeAvailable()
223 || m_actualDecoder->filenameExtension() == "ico")
226 activateLazyDecoding();
228 const size_t previousSize = m_lazyDecodedFrames.size();
229 m_lazyDecodedFrames.resize(m_actualDecoder->frameCount());
231 // We have encountered a broken image file. Simply bail.
232 if (m_lazyDecodedFrames.size() < previousSize)
235 for (size_t i = previousSize; i < m_lazyDecodedFrames.size(); ++i) {
236 OwnPtr<ImageFrame> frame(adoptPtr(new ImageFrame()));
237 frame->setSkBitmap(createBitmap(i));
238 frame->setDuration(m_actualDecoder->frameDurationAtIndex(i));
239 frame->setStatus(m_actualDecoder->frameIsCompleteAtIndex(i) ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
240 m_lazyDecodedFrames[i] = frame.release();
243 // The last lazy decoded frame created from previous call might be
244 // incomplete so update its state.
246 const size_t lastFrame = previousSize - 1;
247 m_lazyDecodedFrames[lastFrame]->setStatus(m_actualDecoder->frameIsCompleteAtIndex(lastFrame) ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
249 // If data has changed then create a new bitmap. This forces
250 // Skia to decode again.
252 m_dataChanged = false;
253 m_lazyDecodedFrames[lastFrame]->setSkBitmap(createBitmap(lastFrame));
257 if (m_allDataReceived) {
258 m_repetitionCount = m_actualDecoder->repetitionCount();
259 m_actualDecoder.clear();
264 // Creates either a SkBitmap backed by SkDiscardablePixelRef or a SkBitmap using the
265 // legacy LazyDecodingPixelRef.
266 SkBitmap DeferredImageDecoder::createBitmap(size_t index)
268 // This code is temporary until the transition to SkDiscardablePixelRef is complete.
269 if (s_skiaDiscardableMemoryEnabled)
270 return createSkiaDiscardableBitmap(index);
271 return createLazyDecodingBitmap(index);
274 // Creates a SkBitmap that is backed by SkDiscardablePixelRef.
275 SkBitmap DeferredImageDecoder::createSkiaDiscardableBitmap(size_t index)
277 IntSize decodedSize = m_actualDecoder->decodedSize();
278 ASSERT(decodedSize.width() > 0);
279 ASSERT(decodedSize.height() > 0);
282 info.fWidth = decodedSize.width();
283 info.fHeight = decodedSize.height();
284 info.fColorType = kBGRA_8888_SkColorType;
285 info.fAlphaType = kPremul_SkAlphaType;
288 DecodingImageGenerator* generator = new DecodingImageGenerator(m_frameGenerator, info, index);
289 bool installed = SkInstallDiscardablePixelRef(generator, &bitmap);
290 ASSERT_UNUSED(installed, installed);
291 bitmap.pixelRef()->setURI(labelDiscardable);
292 generator->setGenerationId(bitmap.getGenerationID());
296 SkBitmap DeferredImageDecoder::createLazyDecodingBitmap(size_t index)
298 IntSize decodedSize = m_actualDecoder->decodedSize();
299 ASSERT(decodedSize.width() > 0);
300 ASSERT(decodedSize.height() > 0);
303 info.fWidth = decodedSize.width();
304 info.fHeight = decodedSize.height();
305 info.fColorType = kPMColor_SkColorType;
306 info.fAlphaType = kPremul_SkAlphaType;
308 // Creates a lazily decoded SkPixelRef that references the entire image without scaling.
310 bitmap.setConfig(info);
311 bitmap.setPixelRef(new LazyDecodingPixelRef(info, m_frameGenerator, index))->unref();
313 // Use the URI to identify this as a lazily decoded SkPixelRef of type LazyDecodingPixelRef.
314 // FIXME: It would be more useful to give the actual image URI.
315 bitmap.pixelRef()->setURI(labelLazyDecoded);
317 // Inform the bitmap that we will never change the pixels. This is a performance hint
318 // subsystems that may try to cache this bitmap (e.g. pictures, pipes, gpu, pdf, etc.)
319 bitmap.setImmutable();
324 bool DeferredImageDecoder::hotSpot(IntPoint& hotSpot) const
327 return m_actualDecoder ? m_actualDecoder->hotSpot(hotSpot) : false;
330 } // namespace WebCore