Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(282)

Side by Side Diff: third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.cpp

Issue 1925533003: High CPU and increased memory usage fix for high-res (GIF, WEBP...) animations. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: @scroggo, thanks a lot - this makes page [3] to use 250MB (was 750MB) Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 10 matching lines...) Expand all
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */ 24 */
25 25
26 #include "platform/graphics/DeferredImageDecoder.h" 26 #include "platform/graphics/DeferredImageDecoder.h"
27 27
28 #include "platform/RuntimeEnabledFeatures.h" 28 #include "platform/RuntimeEnabledFeatures.h"
29 #include "platform/SharedBuffer.h" 29 #include "platform/SharedBuffer.h"
30 #include "platform/graphics/DecodingImageGenerator.h" 30 #include "platform/graphics/DecodingImageGenerator.h"
31 #include "platform/graphics/FrameData.h"
32 #include "platform/graphics/ImageDecodingStore.h" 31 #include "platform/graphics/ImageDecodingStore.h"
33 #include "platform/graphics/ImageFrameGenerator.h" 32 #include "platform/graphics/ImageFrameGenerator.h"
34 #include "platform/image-decoders/SegmentReader.h" 33 #include "platform/image-decoders/SegmentReader.h"
35 #include "third_party/skia/include/core/SkImage.h" 34 #include "third_party/skia/include/core/SkImage.h"
36 #include "wtf/PassOwnPtr.h" 35 #include "wtf/PassOwnPtr.h"
37 36
38 namespace blink { 37 namespace blink {
39 38
39 struct DeferredFrameData {
40 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
41 WTF_MAKE_NONCOPYABLE(DeferredFrameData);
42 public:
43 DeferredFrameData()
44 : m_orientation(DefaultImageOrientation)
45 , m_duration(0)
46 , m_isComplete(false)
47 , m_frameBytes(0)
48 , m_uniqueID(DecodingImageGenerator::NeedNewImageUniqueID)
49 {}
50
51 ImageOrientation m_orientation;
52 float m_duration;
53 bool m_isComplete;
54 size_t m_frameBytes;
55 uint32_t m_uniqueID;
56 };
57
40 bool DeferredImageDecoder::s_enabled = true; 58 bool DeferredImageDecoder::s_enabled = true;
41 59
42 PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::create(const SharedBuffer & data, ImageDecoder::AlphaOption alphaOption, ImageDecoder::GammaAndColorProfil eOption colorOptions) 60 PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::create(const SharedBuffer & data, ImageDecoder::AlphaOption alphaOption, ImageDecoder::GammaAndColorProfil eOption colorOptions)
43 { 61 {
44 OwnPtr<ImageDecoder> actualDecoder = ImageDecoder::create(data, alphaOption, colorOptions); 62 OwnPtr<ImageDecoder> actualDecoder = ImageDecoder::create(data, alphaOption, colorOptions);
45 63
46 if (!actualDecoder) 64 if (!actualDecoder)
47 return nullptr; 65 return nullptr;
48 66
49 return adoptPtr(new DeferredImageDecoder(actualDecoder.release())); 67 return adoptPtr(new DeferredImageDecoder(actualDecoder.release()));
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 } 101 }
84 102
85 PassRefPtr<SkImage> DeferredImageDecoder::createFrameAtIndex(size_t index) 103 PassRefPtr<SkImage> DeferredImageDecoder::createFrameAtIndex(size_t index)
86 { 104 {
87 if (m_frameGenerator && m_frameGenerator->decodeFailed()) 105 if (m_frameGenerator && m_frameGenerator->decodeFailed())
88 return nullptr; 106 return nullptr;
89 107
90 prepareLazyDecodedFrames(); 108 prepareLazyDecodedFrames();
91 109
92 if (index < m_frameData.size()) { 110 if (index < m_frameData.size()) {
93 FrameData* frameData = &m_frameData[index]; 111 DeferredFrameData* frameData = &m_frameData[index];
94 // ImageFrameGenerator has the latest known alpha state. There will be a
95 // performance boost if this frame is opaque.
96 ASSERT(m_frameGenerator);
97 frameData->m_hasAlpha = m_frameGenerator->hasAlpha(index);
98 if (m_actualDecoder) 112 if (m_actualDecoder)
99 frameData->m_frameBytes = m_actualDecoder->frameBytesAtIndex(index); 113 frameData->m_frameBytes = m_actualDecoder->frameBytesAtIndex(index);
100 else 114 else
101 frameData->m_frameBytes = m_size.area() * sizeof(ImageFrame::PixelDa ta); 115 frameData->m_frameBytes = m_size.area() * sizeof(ImageFrame::PixelDa ta);
102 return createFrameImageAtIndex(index, !frameData->m_hasAlpha); 116 // ImageFrameGenerator has the latest known alpha state. There will be a
117 // performance boost if this frame is opaque.
118 ASSERT(m_frameGenerator);
119 return createFrameImageAtIndex(index, !m_frameGenerator->hasAlpha(index) );
103 } 120 }
104 121
105 if (!m_actualDecoder || m_actualDecoder->failed()) 122 if (!m_actualDecoder || m_actualDecoder->failed())
106 return nullptr; 123 return nullptr;
107 124
108 ImageFrame* frame = m_actualDecoder->frameBufferAtIndex(index); 125 ImageFrame* frame = m_actualDecoder->frameBufferAtIndex(index);
109 if (!frame || frame->getStatus() == ImageFrame::FrameEmpty) 126 if (!frame || frame->getStatus() == ImageFrame::FrameEmpty)
110 return nullptr; 127 return nullptr;
111 128
112 return adoptRef(SkImage::NewFromBitmap(frame->bitmap())); 129 return adoptRef(SkImage::NewFromBitmap(frame->bitmap()));
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 activateLazyDecoding(); 268 activateLazyDecoding();
252 269
253 const size_t previousSize = m_frameData.size(); 270 const size_t previousSize = m_frameData.size();
254 m_frameData.resize(m_actualDecoder->frameCount()); 271 m_frameData.resize(m_actualDecoder->frameCount());
255 272
256 // We have encountered a broken image file. Simply bail. 273 // We have encountered a broken image file. Simply bail.
257 if (m_frameData.size() < previousSize) 274 if (m_frameData.size() < previousSize)
258 return; 275 return;
259 276
260 for (size_t i = previousSize; i < m_frameData.size(); ++i) { 277 for (size_t i = previousSize; i < m_frameData.size(); ++i) {
261 m_frameData[i].m_haveMetadata = true;
262 m_frameData[i].m_duration = m_actualDecoder->frameDurationAtIndex(i); 278 m_frameData[i].m_duration = m_actualDecoder->frameDurationAtIndex(i);
263 m_frameData[i].m_orientation = m_actualDecoder->orientation(); 279 m_frameData[i].m_orientation = m_actualDecoder->orientation();
264 m_frameData[i].m_isComplete = m_actualDecoder->frameIsCompleteAtIndex(i) ; 280 m_frameData[i].m_isComplete = m_actualDecoder->frameIsCompleteAtIndex(i) ;
265 } 281 }
266 282
267 // The last lazy decoded frame created from previous call might be 283 // The last lazy decoded frame created from previous call might be
268 // incomplete so update its state. 284 // incomplete so update its state.
269 if (previousSize) { 285 if (previousSize) {
270 const size_t lastFrame = previousSize - 1; 286 const size_t lastFrame = previousSize - 1;
271 m_frameData[lastFrame].m_isComplete = m_actualDecoder->frameIsCompleteAt Index(lastFrame); 287 m_frameData[lastFrame].m_isComplete = m_actualDecoder->frameIsCompleteAt Index(lastFrame);
272 } 288 }
273 289
274 if (m_allDataReceived) { 290 if (m_allDataReceived) {
275 m_repetitionCount = m_actualDecoder->repetitionCount(); 291 m_repetitionCount = m_actualDecoder->repetitionCount();
276 m_actualDecoder.clear(); 292 m_actualDecoder.clear();
277 // Hold on to m_rwBuffer, which is still needed by createFrameAtIndex. 293 // Hold on to m_rwBuffer, which is still needed by createFrameAtIndex.
278 } 294 }
279 } 295 }
280 296
281 inline SkImageInfo imageInfoFrom(const SkISize& decodedSize, bool knownToBeOpaqu e) 297 inline SkImageInfo imageInfoFrom(const SkISize& decodedSize, bool knownToBeOpaqu e)
282 { 298 {
283 return SkImageInfo::MakeN32(decodedSize.width(), decodedSize.height(), known ToBeOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType); 299 return SkImageInfo::MakeN32(decodedSize.width(), decodedSize.height(), known ToBeOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
284 } 300 }
285 301
286 PassRefPtr<SkImage> DeferredImageDecoder::createFrameImageAtIndex(size_t index, bool knownToBeOpaque) const 302 PassRefPtr<SkImage> DeferredImageDecoder::createFrameImageAtIndex(size_t index, bool knownToBeOpaque)
287 { 303 {
288 const SkISize& decodedSize = m_frameGenerator->getFullSize(); 304 const SkISize& decodedSize = m_frameGenerator->getFullSize();
289 ASSERT(decodedSize.width() > 0); 305 ASSERT(decodedSize.width() > 0);
290 ASSERT(decodedSize.height() > 0); 306 ASSERT(decodedSize.height() > 0);
291 307
292 RefPtr<SkROBuffer> roBuffer = adoptRef(m_rwBuffer->newRBufferSnapshot()); 308 RefPtr<SkROBuffer> roBuffer = adoptRef(m_rwBuffer->newRBufferSnapshot());
293 RefPtr<SegmentReader> segmentReader = SegmentReader::createFromSkROBuffer(ro Buffer.release()); 309 RefPtr<SegmentReader> segmentReader = SegmentReader::createFromSkROBuffer(ro Buffer.release());
294 DecodingImageGenerator* generator = new DecodingImageGenerator(m_frameGenera tor, imageInfoFrom(decodedSize, knownToBeOpaque), segmentReader.release(), m_all DataReceived, index); 310 DecodingImageGenerator* generator = new DecodingImageGenerator(m_frameGenera tor, imageInfoFrom(decodedSize, knownToBeOpaque), segmentReader.release(), m_all DataReceived, index, m_frameData[index].m_uniqueID);
295 RefPtr<SkImage> image = adoptRef(SkImage::NewFromGenerator(generator)); // S kImage takes ownership of the generator. 311 RefPtr<SkImage> image = adoptRef(SkImage::NewFromGenerator(generator)); // S kImage takes ownership of the generator.
296 if (!image) 312 if (!image)
297 return nullptr; 313 return nullptr;
298 314
315 m_frameData[index].m_uniqueID = (m_allDataReceived || (m_actualDecoder && m_ actualDecoder->frameIsCompleteAtIndex(index))) ? image->uniqueID() : DecodingIma geGenerator::NeedNewImageUniqueID;
scroggo_chromium 2016/05/03 13:08:52 Thanks, yes, I forgot to look at the GIF decoder o
Peter Kasting 2016/05/04 03:01:07 I also would think that if m_allDataReceived, then
aleksandar.stojiljkovic 2016/05/04 20:56:29 It is important to have this check: if (m_allDataR
scroggo_chromium 2016/05/04 21:15:54 Ah, of course! I find it very confusing that frame
299 generator->setCanYUVDecode(m_canYUVDecode); 316 generator->setCanYUVDecode(m_canYUVDecode);
300 317
301 return image.release(); 318 return image.release();
302 } 319 }
303 320
304 bool DeferredImageDecoder::hotSpot(IntPoint& hotSpot) const 321 bool DeferredImageDecoder::hotSpot(IntPoint& hotSpot) const
305 { 322 {
306 // TODO: Implement. 323 // TODO: Implement.
307 return m_actualDecoder ? m_actualDecoder->hotSpot(hotSpot) : false; 324 return m_actualDecoder ? m_actualDecoder->hotSpot(hotSpot) : false;
308 } 325 }
309 326
310 } // namespace blink 327 } // namespace blink
328
329 namespace WTF {
330 template<> struct VectorTraits<blink::DeferredFrameData> : public SimpleClassVec torTraits<blink::DeferredFrameData> {
331 STATIC_ONLY(VectorTraits);
332 static const bool canInitializeWithMemset = false; // Not all DeferredFrameD ata members initialize to 0.
333 };
334 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698