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
34 namespace blink {
35
36 namespace {
37
38 // URI label for SkDiscardablePixelRef.
39 const char labelDiscardable[] = "discardable";
40
41 } // namespace
42
43 bool DeferredImageDecoder::s_enabled = false;
44
DeferredImageDecoder(PassOwnPtr<ImageDecoder> actualDecoder)45 DeferredImageDecoder::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
~DeferredImageDecoder()56 DeferredImageDecoder::~DeferredImageDecoder()
57 {
58 }
59
create(const SharedBuffer & data,ImageSource::AlphaOption alphaOption,ImageSource::GammaAndColorProfileOption gammaAndColorOption)60 PassOwnPtr<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
createForTesting(PassOwnPtr<ImageDecoder> decoder)66 PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::createForTesting(PassOwnPtr<ImageDecoder> decoder)
67 {
68 return adoptPtr(new DeferredImageDecoder(decoder));
69 }
70
isLazyDecoded(const SkBitmap & bitmap)71 bool DeferredImageDecoder::isLazyDecoded(const SkBitmap& bitmap)
72 {
73 return bitmap.pixelRef()
74 && bitmap.pixelRef()->getURI()
75 && !memcmp(bitmap.pixelRef()->getURI(), labelDiscardable, sizeof(labelDiscardable));
76 }
77
setEnabled(bool enabled)78 void DeferredImageDecoder::setEnabled(bool enabled)
79 {
80 s_enabled = enabled;
81 }
82
enabled()83 bool DeferredImageDecoder::enabled()
84 {
85 return s_enabled;
86 }
87
filenameExtension() const88 String DeferredImageDecoder::filenameExtension() const
89 {
90 return m_actualDecoder ? m_actualDecoder->filenameExtension() : m_filenameExtension;
91 }
92
frameBufferAtIndex(size_t index)93 ImageFrame* 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
setData(SharedBuffer & data,bool allDataReceived)107 void 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
isSizeAvailable()124 bool 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
hasColorProfile() const131 bool DeferredImageDecoder::hasColorProfile() const
132 {
133 return m_actualDecoder ? m_actualDecoder->hasColorProfile() : m_hasColorProfile;
134 }
135
size() const136 IntSize DeferredImageDecoder::size() const
137 {
138 return m_actualDecoder ? m_actualDecoder->size() : m_size;
139 }
140
frameSizeAtIndex(size_t index) const141 IntSize 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
frameCount()148 size_t DeferredImageDecoder::frameCount()
149 {
150 return m_actualDecoder ? m_actualDecoder->frameCount() : m_lazyDecodedFrames.size();
151 }
152
repetitionCount() const153 int DeferredImageDecoder::repetitionCount() const
154 {
155 return m_actualDecoder ? m_actualDecoder->repetitionCount() : m_repetitionCount;
156 }
157
clearCacheExceptFrame(size_t clearExceptFrame)158 size_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
frameHasAlphaAtIndex(size_t index) const165 bool 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
frameIsCompleteAtIndex(size_t index) const174 bool 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
frameDurationAtIndex(size_t index) const183 float 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
frameBytesAtIndex(size_t index) const192 unsigned 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
orientation() const199 ImageOrientation DeferredImageDecoder::orientation() const
200 {
201 return m_actualDecoder ? m_actualDecoder->orientation() : m_orientation;
202 }
203
activateLazyDecoding()204 void 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
prepareLazyDecodedFrames()216 void 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.
createBitmap(size_t index)263 SkBitmap 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
hotSpot(IntPoint & hotSpot) const285 bool DeferredImageDecoder::hotSpot(IntPoint& hotSpot) const
286 {
287 // TODO: Implement.
288 return m_actualDecoder ? m_actualDecoder->hotSpot(hotSpot) : false;
289 }
290
291 } // namespace blink
292