REGRESSION (216471): Infinite repaint-drawing loop when asynchronously decoding incom...
[WebKit-https.git] / Source / WebCore / platform / graphics / BitmapImage.cpp
1 /*
2  * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
3  * Copyright (C) 2004, 2005, 2006, 2008, 2015 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "BitmapImage.h"
29
30 #include "FloatRect.h"
31 #include "GraphicsContext.h"
32 #include "ImageBuffer.h"
33 #include "ImageObserver.h"
34 #include "IntRect.h"
35 #include "Logging.h"
36 #include "Settings.h"
37 #include "TextStream.h"
38 #include "Timer.h"
39 #include <wtf/CurrentTime.h>
40 #include <wtf/Vector.h>
41 #include <wtf/text/WTFString.h>
42
43 #if PLATFORM(IOS)
44 #include <limits>
45 #endif
46
47 namespace WebCore {
48
49 BitmapImage::BitmapImage(ImageObserver* observer)
50     : Image(observer)
51     , m_source(this)
52 {
53 }
54
55 BitmapImage::BitmapImage(NativeImagePtr&& image, ImageObserver* observer)
56     : Image(observer)
57     , m_source(WTFMove(image))
58 {
59 }
60
61 BitmapImage::~BitmapImage()
62 {
63     invalidatePlatformData();
64     clearTimer();
65     m_source.stopAsyncDecodingQueue();
66 }
67
68 void BitmapImage::updateFromSettings(const Settings& settings)
69 {
70     m_allowSubsampling = settings.imageSubsamplingEnabled();
71     m_allowLargeImageAsyncDecoding = settings.largeImageAsyncDecodingEnabled();
72     m_allowAnimatedImageAsyncDecoding = settings.animatedImageAsyncDecodingEnabled();
73     m_showDebugBackground = settings.showDebugBorders();
74 }
75
76 void BitmapImage::destroyDecodedData(bool destroyAll)
77 {
78     LOG(Images, "BitmapImage::%s - %p - url: %s", __FUNCTION__, this, sourceURL().string().utf8().data());
79
80     if (!destroyAll)
81         m_source.destroyDecodedDataBeforeFrame(m_currentFrame);
82     else if (m_source.hasAsyncDecodingQueue())
83         m_source.destroyAllDecodedDataExcludeFrame(m_currentFrame);
84     else {
85         m_source.destroyAllDecodedData();
86         m_currentFrameDecodingStatus = ImageFrame::DecodingStatus::Invalid;
87     }
88
89     // There's no need to throw away the decoder unless we're explicitly asked
90     // to destroy all of the frames.
91     if (!destroyAll || m_source.hasAsyncDecodingQueue())
92         m_source.clearFrameBufferCache(m_currentFrame);
93     else
94         m_source.clear(data());
95
96     invalidatePlatformData();
97 }
98
99 void BitmapImage::destroyDecodedDataIfNecessary(bool destroyAll)
100 {
101     // If we have decoded frames but there is no encoded data, we shouldn't destroy
102     // the decoded image since we won't be able to reconstruct it later.
103     if (!data() && frameCount())
104         return;
105
106     if (m_source.decodedSize() < LargeAnimationCutoff)
107         return;
108
109     destroyDecodedData(destroyAll);
110 }
111
112 EncodedDataStatus BitmapImage::dataChanged(bool allDataReceived)
113 {
114     if (!shouldUseAsyncDecodingForLargeImages())
115         m_source.destroyIncompleteDecodedData();
116
117     m_currentFrameDecodingStatus = ImageFrame::DecodingStatus::Invalid;
118     return m_source.dataChanged(data(), allDataReceived);
119 }
120
121 NativeImagePtr BitmapImage::frameImageAtIndexCacheIfNeeded(size_t index, SubsamplingLevel subsamplingLevel, const GraphicsContext* targetContext)
122 {
123     if (!frameHasFullSizeNativeImageAtIndex(index, subsamplingLevel)) {
124         LOG(Images, "BitmapImage::%s - %p - url: %s [subsamplingLevel was %d, resampling]", __FUNCTION__, this, sourceURL().string().utf8().data(), static_cast<int>(frameSubsamplingLevelAtIndex(index)));
125         invalidatePlatformData();
126     }
127
128     return m_source.frameImageAtIndexCacheIfNeeded(index, subsamplingLevel, targetContext);
129 }
130
131 NativeImagePtr BitmapImage::nativeImage(const GraphicsContext* targetContext)
132 {
133     return frameImageAtIndexCacheIfNeeded(0, SubsamplingLevel::Default, targetContext);
134 }
135
136 NativeImagePtr BitmapImage::nativeImageForCurrentFrame(const GraphicsContext* targetContext)
137 {
138     return frameImageAtIndexCacheIfNeeded(m_currentFrame, SubsamplingLevel::Default, targetContext);
139 }
140
141 #if USE(CG)
142 NativeImagePtr BitmapImage::nativeImageOfSize(const IntSize& size, const GraphicsContext* targetContext)
143 {
144     size_t count = frameCount();
145
146     for (size_t i = 0; i < count; ++i) {
147         auto image = frameImageAtIndexCacheIfNeeded(i, SubsamplingLevel::Default, targetContext);
148         if (image && nativeImageSize(image) == size)
149             return image;
150     }
151
152     // Fallback to the first frame image if we can't find the right size
153     return frameImageAtIndexCacheIfNeeded(0, SubsamplingLevel::Default, targetContext);
154 }
155
156 Vector<NativeImagePtr> BitmapImage::framesNativeImages()
157 {
158     Vector<NativeImagePtr> images;
159     size_t count = frameCount();
160
161     for (size_t i = 0; i < count; ++i) {
162         if (auto image = frameImageAtIndexCacheIfNeeded(i))
163             images.append(image);
164     }
165
166     return images;
167 }
168 #endif
169
170 #if !ASSERT_DISABLED
171 bool BitmapImage::notSolidColor()
172 {
173     return size().width() != 1 || size().height() != 1 || frameCount() > 1;
174 }
175 #endif
176
177 void BitmapImage::draw(GraphicsContext& context, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, BlendMode mode, DecodingMode decodingMode, ImageOrientationDescription description)
178 {
179     if (destRect.isEmpty() || srcRect.isEmpty())
180         return;
181
182     FloatSize scaleFactorForDrawing = context.scaleFactorForDrawing(destRect, srcRect);
183     IntSize sizeForDrawing = expandedIntSize(size() * scaleFactorForDrawing);
184     
185     m_currentSubsamplingLevel = m_allowSubsampling ? m_source.subsamplingLevelForScaleFactor(context, scaleFactorForDrawing) : SubsamplingLevel::Default;
186     LOG(Images, "BitmapImage::%s - %p - url: %s [subsamplingLevel = %d scaleFactorForDrawing = (%.4f, %.4f)]", __FUNCTION__, this, sourceURL().string().utf8().data(), static_cast<int>(m_currentSubsamplingLevel), scaleFactorForDrawing.width(), scaleFactorForDrawing.height());
187
188     NativeImagePtr image;
189     if (decodingMode == DecodingMode::Asynchronous && shouldUseAsyncDecodingForLargeImages()) {
190         ASSERT(!canAnimate() && !m_currentFrame);
191
192         bool frameIsCompatible = frameHasDecodedNativeImageCompatibleWithOptionsAtIndex(m_currentFrame, m_currentSubsamplingLevel, DecodingOptions(sizeForDrawing));
193         bool frameIsBeingDecoded = frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(m_currentFrame, DecodingOptions(sizeForDrawing));
194
195         // If the current frame is incomplete, a new request for decoding this frame has to be made even if
196         // it is currently being decoded. New data may have been received since the previous request was made.
197         if ((!frameIsCompatible && !frameIsBeingDecoded) || m_currentFrameDecodingStatus == ImageFrame::DecodingStatus::Invalid) {
198             LOG(Images, "BitmapImage::%s - %p - url: %s [requesting large async decoding]", __FUNCTION__, this, sourceURL().string().utf8().data());
199             m_source.requestFrameAsyncDecodingAtIndex(0, m_currentSubsamplingLevel, sizeForDrawing);
200             m_currentFrameDecodingStatus = ImageFrame::DecodingStatus::Decoding;
201         }
202
203         if (!frameHasDecodedNativeImageCompatibleWithOptionsAtIndex(m_currentFrame, m_currentSubsamplingLevel, DecodingMode::Asynchronous)) {
204             if (m_showDebugBackground)
205                 fillWithSolidColor(context, destRect, Color(Color::yellow).colorWithAlpha(0.5), op);
206             return;
207         }
208
209         image = frameImageAtIndex(m_currentFrame);
210         LOG(Images, "BitmapImage::%s - %p - url: %s [a decoded image frame is available for drawing]", __FUNCTION__, this, sourceURL().string().utf8().data());
211     } else {
212         StartAnimationStatus status = internalStartAnimation();
213         ASSERT_IMPLIES(status == StartAnimationStatus::DecodingActive, frameHasFullSizeNativeImageAtIndex(m_currentFrame, m_currentSubsamplingLevel));
214
215         if (status == StartAnimationStatus::DecodingActive && m_showDebugBackground) {
216             fillWithSolidColor(context, destRect, Color(Color::yellow).colorWithAlpha(0.5), op);
217             return;
218         }
219
220         if (frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(m_currentFrame, DecodingMode::Asynchronous)) {
221             // FIXME: instead of showing the yellow rectangle and returning we need to wait for this the frame to finish decoding.
222             if (m_showDebugBackground) {
223                 fillWithSolidColor(context, destRect, Color(Color::yellow).colorWithAlpha(0.5), op);
224                 LOG(Images, "BitmapImage::%s - %p - url: %s [waiting for async decoding to finish]", __FUNCTION__, this, sourceURL().string().utf8().data());
225             }
226             return;
227         }
228
229         image = frameImageAtIndexCacheIfNeeded(m_currentFrame, m_currentSubsamplingLevel, &context);
230         if (!image) // If it's too early we won't have an image yet.
231             return;
232     }
233
234     ASSERT(image);
235     Color color = singlePixelSolidColor();
236     if (color.isValid()) {
237         fillWithSolidColor(context, destRect, color, op);
238         return;
239     }
240
241     ImageOrientation orientation(description.imageOrientation());
242     if (description.respectImageOrientation() == RespectImageOrientation)
243         orientation = frameOrientationAtIndex(m_currentFrame);
244
245     drawNativeImage(image, context, destRect, srcRect, IntSize(size()), op, mode, orientation);
246     m_currentFrameDecodingStatus = frameDecodingStatusAtIndex(m_currentFrame);
247
248     if (imageObserver())
249         imageObserver()->didDraw(this);
250 }
251
252 void BitmapImage::drawPattern(GraphicsContext& ctxt, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& transform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode)
253 {
254     if (tileRect.isEmpty())
255         return;
256
257     if (!ctxt.drawLuminanceMask()) {
258         Image::drawPattern(ctxt, destRect, tileRect, transform, phase, spacing, op, blendMode);
259         return;
260     }
261
262     if (!m_cachedImage) {
263         auto buffer = ImageBuffer::createCompatibleBuffer(expandedIntSize(tileRect.size()), ColorSpaceSRGB, ctxt);
264         if (!buffer)
265             return;
266
267         ImageObserver* observer = imageObserver();
268
269         // Temporarily reset image observer, we don't want to receive any changeInRect() calls due to this relayout.
270         setImageObserver(nullptr);
271
272         draw(buffer->context(), tileRect, tileRect, op, blendMode, DecodingMode::Synchronous, ImageOrientationDescription());
273
274         setImageObserver(observer);
275         buffer->convertToLuminanceMask();
276
277         m_cachedImage = buffer->copyImage(DontCopyBackingStore, Unscaled);
278         if (!m_cachedImage)
279             return;
280     }
281
282     ctxt.setDrawLuminanceMask(false);
283     m_cachedImage->drawPattern(ctxt, destRect, tileRect, transform, phase, spacing, op, blendMode);
284 }
285
286 bool BitmapImage::shouldAnimate()
287 {
288     return repetitionCount() && !m_animationFinished && imageObserver();
289 }
290
291 bool BitmapImage::canAnimate()
292 {
293     return shouldAnimate() && frameCount() > 1;
294 }
295
296 bool BitmapImage::shouldUseAsyncDecodingForLargeImages()
297 {
298     return !canAnimate() && m_allowLargeImageAsyncDecoding && m_source.shouldUseAsyncDecoding();
299 }
300
301 bool BitmapImage::shouldUseAsyncDecodingForAnimatedImages()
302 {
303     return canAnimate() && m_allowAnimatedImageAsyncDecoding && (shouldUseAsyncDecodingForAnimatedImagesForTesting() || m_source.shouldUseAsyncDecoding());
304 }
305
306 void BitmapImage::clearTimer()
307 {
308     m_frameTimer = nullptr;
309 }
310
311 void BitmapImage::startTimer(Seconds delay)
312 {
313     ASSERT(!m_frameTimer);
314     m_frameTimer = std::make_unique<Timer>(*this, &BitmapImage::advanceAnimation);
315     m_frameTimer->startOneShot(delay);
316 }
317
318 BitmapImage::StartAnimationStatus BitmapImage::internalStartAnimation()
319 {
320     if (!canAnimate())
321         return StartAnimationStatus::CannotStart;
322
323     if (m_frameTimer)
324         return StartAnimationStatus::TimerActive;
325
326     // Don't start a new animation until we draw the frame that is currently being decoded.
327     size_t nextFrame = (m_currentFrame + 1) % frameCount();
328     if (frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(nextFrame, DecodingMode::Asynchronous)) {
329         LOG(Images, "BitmapImage::%s - %p - url: %s [nextFrame = %ld is being decoded]", __FUNCTION__, this, sourceURL().string().utf8().data(), nextFrame);
330         return StartAnimationStatus::DecodingActive;
331     }
332
333     if (m_currentFrame >= frameCount() - 1) {
334         // Don't advance past the last frame if we haven't decoded the whole image
335         // yet and our repetition count is potentially unset. The repetition count
336         // in a GIF can potentially come after all the rest of the image data, so
337         // wait on it.
338         if (!m_source.isAllDataReceived() && repetitionCount() == RepetitionCountOnce)
339             return StartAnimationStatus::IncompleteData;
340
341         ++m_repetitionsComplete;
342
343         // Check for the end of animation.
344         if (repetitionCount() != RepetitionCountInfinite && m_repetitionsComplete >= repetitionCount()) {
345             m_animationFinished = true;
346             destroyDecodedDataIfNecessary(false);
347             return StartAnimationStatus::CannotStart;
348         }
349
350         destroyDecodedDataIfNecessary(true);
351     }
352
353     // Don't advance the animation to an incomplete frame.
354     if (!m_source.isAllDataReceived() && !frameIsCompleteAtIndex(nextFrame))
355         return StartAnimationStatus::IncompleteData;
356
357     MonotonicTime time = MonotonicTime::now();
358
359     // Handle initial state.
360     if (!m_desiredFrameStartTime)
361         m_desiredFrameStartTime = time;
362
363     // Setting 'm_desiredFrameStartTime' to 'time' means we are late; otherwise we are early.
364     m_desiredFrameStartTime = std::max(time, m_desiredFrameStartTime + Seconds { frameDurationAtIndex(m_currentFrame) });
365
366     // Request async decoding for nextFrame only if this is required. If nextFrame is not in the frameCache,
367     // it will be decoded on a separate work queue. When decoding nextFrame finishes, we will be notified
368     // through the callback newFrameNativeImageAvailableAtIndex(). Otherwise, advanceAnimation() will be called
369     // when the timer fires and m_currentFrame will be advanced to nextFrame since it is not being decoded.
370     if (shouldUseAsyncDecodingForAnimatedImages()) {
371         if (frameHasDecodedNativeImageCompatibleWithOptionsAtIndex(nextFrame, m_currentSubsamplingLevel, { }))
372             LOG(Images, "BitmapImage::%s - %p - url: %s [cachedFrameCount = %ld nextFrame = %ld]", __FUNCTION__, this, sourceURL().string().utf8().data(), ++m_cachedFrameCount, nextFrame);
373         else {
374             m_source.requestFrameAsyncDecodingAtIndex(nextFrame, m_currentSubsamplingLevel);
375             m_currentFrameDecodingStatus = ImageFrame::DecodingStatus::Decoding;
376             LOG(Images, "BitmapImage::%s - %p - url: %s [requesting async decoding for nextFrame = %ld]", __FUNCTION__, this, sourceURL().string().utf8().data(), nextFrame);
377         }
378
379         m_desiredFrameDecodeTimeForTesting = time + std::max(m_frameDecodingDurationForTesting, 0_s);
380         if (m_clearDecoderAfterAsyncFrameRequestForTesting)
381             m_source.clear(data());
382     }
383
384     ASSERT(!m_frameTimer);
385     startTimer(m_desiredFrameStartTime - time);
386     return StartAnimationStatus::Started;
387 }
388
389 void BitmapImage::advanceAnimation()
390 {
391     clearTimer();
392
393     // Pretend as if decoding nextFrame has taken m_frameDecodingDurationForTesting from
394     // the time this decoding was requested.
395     if (shouldUseAsyncDecodingForAnimatedImagesForTesting()) {
396         MonotonicTime time = MonotonicTime::now();
397         // Start a timer with the remaining time from now till the m_desiredFrameDecodeTime.
398         if (m_desiredFrameDecodeTimeForTesting > std::max(time, m_desiredFrameStartTime)) {
399             startTimer(m_desiredFrameDecodeTimeForTesting - time);
400             return;
401         }
402     }
403
404     // Don't advance to nextFrame unless its decoding has finished or was not required.
405     size_t nextFrame = (m_currentFrame + 1) % frameCount();
406     if (!frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(nextFrame, DecodingMode::Asynchronous))
407         internalAdvanceAnimation();
408     else {
409         // Force repaint if showDebugBackground() is on.
410         if (m_showDebugBackground)
411             imageObserver()->changedInRect(this);
412         LOG(Images, "BitmapImage::%s - %p - url: %s [lateFrameCount = %ld nextFrame = %ld]", __FUNCTION__, this, sourceURL().string().utf8().data(), ++m_lateFrameCount, nextFrame);
413     }
414 }
415
416 void BitmapImage::internalAdvanceAnimation()
417 {
418     m_currentFrame = (m_currentFrame + 1) % frameCount();
419     ASSERT(!frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(m_currentFrame, DecodingMode::Asynchronous));
420
421     destroyDecodedDataIfNecessary(false);
422
423     if (m_currentFrameDecodingStatus == ImageFrame::DecodingStatus::Decoding)
424         m_currentFrameDecodingStatus = frameDecodingStatusAtIndex(m_currentFrame);
425     if (imageObserver())
426         imageObserver()->imageFrameAvailable(this, ImageAnimatingState::Yes);
427
428     LOG(Images, "BitmapImage::%s - %p - url: %s [m_currentFrame = %ld]", __FUNCTION__, this, sourceURL().string().utf8().data(), m_currentFrame);
429 }
430
431 bool BitmapImage::isAnimating() const
432 {
433     return !!m_frameTimer;
434 }
435
436 void BitmapImage::stopAnimation()
437 {
438     // This timer is used to animate all occurrences of this image. Don't invalidate
439     // the timer unless all renderers have stopped drawing.
440     clearTimer();
441     if (canAnimate())
442         m_source.stopAsyncDecodingQueue();
443 }
444
445 void BitmapImage::resetAnimation()
446 {
447     stopAnimation();
448     m_currentFrame = 0;
449     m_repetitionsComplete = RepetitionCountNone;
450     m_desiredFrameStartTime = { };
451     m_animationFinished = false;
452
453     // For extremely large animations, when the animation is reset, we just throw everything away.
454     destroyDecodedDataIfNecessary(true);
455 }
456
457 void BitmapImage::imageFrameAvailableAtIndex(size_t index)
458 {
459     UNUSED_PARAM(index);
460     LOG(Images, "BitmapImage::%s - %p - url: %s [requested frame %ld is now available]", __FUNCTION__, this, sourceURL().string().utf8().data(), index);
461
462     if (canAnimate()) {
463         ASSERT(index == (m_currentFrame + 1) % frameCount());
464         
465         // Don't advance to nextFrame unless the timer was fired before its decoding finishes.
466         if (canAnimate() && !m_frameTimer)
467             internalAdvanceAnimation();
468         else
469             LOG(Images, "BitmapImage::%s - %p - url: %s [earlyFrameCount = %ld nextFrame = %ld]", __FUNCTION__, this, sourceURL().string().utf8().data(), ++m_earlyFrameCount, index);
470     } else {
471         ASSERT(index == m_currentFrame && !m_currentFrame);
472         if (m_source.isAsyncDecodingQueueIdle())
473             m_source.stopAsyncDecodingQueue();
474         if (m_currentFrameDecodingStatus == ImageFrame::DecodingStatus::Decoding)
475             m_currentFrameDecodingStatus = frameDecodingStatusAtIndex(m_currentFrame);
476         if (imageObserver())
477             imageObserver()->imageFrameAvailable(this, ImageAnimatingState::No);
478     }
479 }
480
481 void BitmapImage::dump(TextStream& ts) const
482 {
483     Image::dump(ts);
484     
485     if (isAnimated())
486         ts.dumpProperty("current-frame", m_currentFrame);
487     
488     m_source.dump(ts);
489 }
490
491 }