• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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