Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / graphics / DeferredImageDecoder.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  * 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 "platform/graphics/LazyDecodingPixelRef.h"
32 #include "third_party/skia/include/core/SkImageInfo.h"
33 #include "wtf/PassOwnPtr.h"
34
35 namespace WebCore {
36
37 namespace {
38
39 // URI label for a lazily decoded SkPixelRef.
40 const char labelLazyDecoded[] = "lazy";
41
42 // URI label for SkDiscardablePixelRef.
43 const char labelDiscardable[] = "discardable";
44
45 } // namespace
46
47 bool DeferredImageDecoder::s_enabled = false;
48 bool DeferredImageDecoder::s_skiaDiscardableMemoryEnabled = false;
49
50 DeferredImageDecoder::DeferredImageDecoder(PassOwnPtr<ImageDecoder> actualDecoder)
51     : m_allDataReceived(false)
52     , m_lastDataSize(0)
53     , m_dataChanged(false)
54     , m_actualDecoder(actualDecoder)
55     , m_orientation(DefaultImageOrientation)
56     , m_repetitionCount(cAnimationNone)
57 {
58 }
59
60 DeferredImageDecoder::~DeferredImageDecoder()
61 {
62 }
63
64 PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorOption)
65 {
66     OwnPtr<ImageDecoder> actualDecoder = ImageDecoder::create(data, alphaOption, gammaAndColorOption);
67     return actualDecoder ? adoptPtr(new DeferredImageDecoder(actualDecoder.release())) : nullptr;
68 }
69
70 PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::createForTesting(PassOwnPtr<ImageDecoder> decoder)
71 {
72     return adoptPtr(new DeferredImageDecoder(decoder));
73 }
74
75 bool DeferredImageDecoder::isLazyDecoded(const SkBitmap& bitmap)
76 {
77     return bitmap.pixelRef()
78         && bitmap.pixelRef()->getURI()
79         && (!memcmp(bitmap.pixelRef()->getURI(), labelLazyDecoded, sizeof(labelLazyDecoded))
80             || !memcmp(bitmap.pixelRef()->getURI(), labelDiscardable, sizeof(labelDiscardable)));
81 }
82
83 void DeferredImageDecoder::setEnabled(bool enabled)
84 {
85     s_enabled = enabled;
86 #if !OS(ANDROID)
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;
91     if (enabled)
92         ImageDecodingStore::setImageCachingEnabled(false);
93 #endif
94 }
95
96 String DeferredImageDecoder::filenameExtension() const
97 {
98     return m_actualDecoder ? m_actualDecoder->filenameExtension() : m_filenameExtension;
99 }
100
101 ImageFrame* DeferredImageDecoder::frameBufferAtIndex(size_t index)
102 {
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();
109     }
110     if (m_actualDecoder)
111         return m_actualDecoder->frameBufferAtIndex(index);
112     return 0;
113 }
114
115 void DeferredImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
116 {
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;
121         m_data = data;
122         m_lastDataSize = data->size();
123         m_allDataReceived = allDataReceived;
124         m_actualDecoder->setData(data, allDataReceived);
125         prepareLazyDecodedFrames();
126     }
127
128     if (m_frameGenerator)
129         m_frameGenerator->setData(data, allDataReceived);
130 }
131
132 bool DeferredImageDecoder::isSizeAvailable()
133 {
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;
137 }
138
139 IntSize DeferredImageDecoder::size() const
140 {
141     return m_actualDecoder ? m_actualDecoder->size() : m_size;
142 }
143
144 IntSize DeferredImageDecoder::frameSizeAtIndex(size_t index) const
145 {
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;
149 }
150
151 size_t DeferredImageDecoder::frameCount()
152 {
153     return m_actualDecoder ? m_actualDecoder->frameCount() : m_lazyDecodedFrames.size();
154 }
155
156 int DeferredImageDecoder::repetitionCount() const
157 {
158     return m_actualDecoder ? m_actualDecoder->repetitionCount() : m_repetitionCount;
159 }
160
161 size_t DeferredImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame)
162 {
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;
166 }
167
168 bool DeferredImageDecoder::frameHasAlphaAtIndex(size_t index) const
169 {
170     if (m_actualDecoder)
171         return m_actualDecoder->frameHasAlphaAtIndex(index);
172     if (!m_frameGenerator->isMultiFrame())
173         return m_frameGenerator->hasAlpha(index);
174     return true;
175 }
176
177 bool DeferredImageDecoder::frameIsCompleteAtIndex(size_t index) const
178 {
179     if (m_actualDecoder)
180         return m_actualDecoder->frameIsCompleteAtIndex(index);
181     if (index < m_lazyDecodedFrames.size())
182         return m_lazyDecodedFrames[index]->status() == ImageFrame::FrameComplete;
183     return false;
184 }
185
186 float DeferredImageDecoder::frameDurationAtIndex(size_t index) const
187 {
188     if (m_actualDecoder)
189         return m_actualDecoder->frameDurationAtIndex(index);
190     if (index < m_lazyDecodedFrames.size())
191         return m_lazyDecodedFrames[index]->duration();
192     return 0;
193 }
194
195 unsigned DeferredImageDecoder::frameBytesAtIndex(size_t index) const
196 {
197     // If frame decoding is deferred then it is not managed by MemoryCache
198     // so return 0 here.
199     return m_frameGenerator ? 0 : m_actualDecoder->frameBytesAtIndex(index);
200 }
201
202 ImageOrientation DeferredImageDecoder::orientation() const
203 {
204     return m_actualDecoder ? m_actualDecoder->orientation() : m_orientation;
205 }
206
207 void DeferredImageDecoder::activateLazyDecoding()
208 {
209     if (m_frameGenerator)
210         return;
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);
216 }
217
218 void DeferredImageDecoder::prepareLazyDecodedFrames()
219 {
220     if (!s_enabled
221         || !m_actualDecoder
222         || !m_actualDecoder->isSizeAvailable()
223         || m_actualDecoder->filenameExtension() == "ico")
224         return;
225
226     activateLazyDecoding();
227
228     const size_t previousSize = m_lazyDecodedFrames.size();
229     m_lazyDecodedFrames.resize(m_actualDecoder->frameCount());
230
231     // We have encountered a broken image file. Simply bail.
232     if (m_lazyDecodedFrames.size() < previousSize)
233         return;
234
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();
241     }
242
243     // The last lazy decoded frame created from previous call might be
244     // incomplete so update its state.
245     if (previousSize) {
246         const size_t lastFrame = previousSize - 1;
247         m_lazyDecodedFrames[lastFrame]->setStatus(m_actualDecoder->frameIsCompleteAtIndex(lastFrame) ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
248
249         // If data has changed then create a new bitmap. This forces
250         // Skia to decode again.
251         if (m_dataChanged) {
252             m_dataChanged = false;
253             m_lazyDecodedFrames[lastFrame]->setSkBitmap(createBitmap(lastFrame));
254         }
255     }
256
257     if (m_allDataReceived) {
258         m_repetitionCount = m_actualDecoder->repetitionCount();
259         m_actualDecoder.clear();
260         m_data = nullptr;
261     }
262 }
263
264 // Creates either a SkBitmap backed by SkDiscardablePixelRef or a SkBitmap using the
265 // legacy LazyDecodingPixelRef.
266 SkBitmap DeferredImageDecoder::createBitmap(size_t index)
267 {
268     // This code is temporary until the transition to SkDiscardablePixelRef is complete.
269     if (s_skiaDiscardableMemoryEnabled)
270         return createSkiaDiscardableBitmap(index);
271     return createLazyDecodingBitmap(index);
272 }
273
274 // Creates a SkBitmap that is backed by SkDiscardablePixelRef.
275 SkBitmap DeferredImageDecoder::createSkiaDiscardableBitmap(size_t index)
276 {
277     IntSize decodedSize = m_actualDecoder->decodedSize();
278     ASSERT(decodedSize.width() > 0);
279     ASSERT(decodedSize.height() > 0);
280
281     SkImageInfo info;
282     info.fWidth = decodedSize.width();
283     info.fHeight = decodedSize.height();
284     info.fColorType = kBGRA_8888_SkColorType;
285     info.fAlphaType = kPremul_SkAlphaType;
286
287     SkBitmap bitmap;
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());
293     return bitmap;
294 }
295
296 SkBitmap DeferredImageDecoder::createLazyDecodingBitmap(size_t index)
297 {
298     IntSize decodedSize = m_actualDecoder->decodedSize();
299     ASSERT(decodedSize.width() > 0);
300     ASSERT(decodedSize.height() > 0);
301
302     SkImageInfo info;
303     info.fWidth = decodedSize.width();
304     info.fHeight = decodedSize.height();
305     info.fColorType = kPMColor_SkColorType;
306     info.fAlphaType = kPremul_SkAlphaType;
307
308     // Creates a lazily decoded SkPixelRef that references the entire image without scaling.
309     SkBitmap bitmap;
310     bitmap.setConfig(info);
311     bitmap.setPixelRef(new LazyDecodingPixelRef(info, m_frameGenerator, index))->unref();
312
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);
316
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();
320
321     return bitmap;
322 }
323
324 bool DeferredImageDecoder::hotSpot(IntPoint& hotSpot) const
325 {
326     // TODO: Implement.
327     return m_actualDecoder ? m_actualDecoder->hotSpot(hotSpot) : false;
328 }
329
330 } // namespace WebCore