Changeset 208511 in webkit


Ignore:
Timestamp:
Nov 9, 2016 5:13:05 PM (7 years ago)
Author:
commit-queue@webkit.org
Message:

Change the decoding for some animated images to be asynchronous
https://bugs.webkit.org/show_bug.cgi?id=161566

Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2016-11-09
Reviewed by Simon Fraser.

Source/WebCore:

Tests: fast/images/slower-animation-than-decoding-image.html

fast/images/slower-decoding-than-animation-image.html
fast/images/stopped-animation-deleted-image.html

Request the next frame before firing the animation timer. The asynchronous
image decoding work queue notifies the BitmapImage when the frame finishes
decoding. If the timer fires before the frame is decoded, no repaint will
be requested. Only when the image frame is ready, the animation will be
advanced and the image will be repainted.

  • loader/cache/CachedImage.cpp:

(WebCore::CachedImage::load): Cache the image settings in CachedImage.
(WebCore::CachedImage::createImage): No need to pass allowSubsampling to BitmapImage. It can be retrieved through Image::imageObserver().
(WebCore::CachedImage::changedInRect): Change the parameter to notifyObservers() to be a pointer.

  • loader/cache/CachedImage.h: Cache the settings: allowSubsampling, allowAsyncImageDecoding and showDebugBackground through m_loader.
  • platform/graphics/BitmapImage.cpp:

(WebCore::BitmapImage::dataChanged): Fix a logging message.
(WebCore::BitmapImage::draw): Store the current SubsamplingLevel to be used when requesting decoding the image of the next frame.
Draw a debug rectangle if the next frame is missed because it is being decoded and the setting showDebugBackground is on.
(WebCore::BitmapImage::startAnimation): Deleted. Moved to the header file.
(WebCore::BitmapImage::internalStartAnimation): Added. Request asynchronous image decoding for the next frame if required. Return the
result of starting the animation.
(WebCore::BitmapImage::advanceAnimation): Call internalAdvanceAnimation() if the frame image is not being decoded. If it is being decoded
and the setting showDebugBackground is on, force repaint so the debug rectangle is drawn.
(WebCore::BitmapImage::internalAdvanceAnimation): This is the old body of advanceAnimation().
(WebCore::BitmapImage::stopAnimation): Stop the asynchronous image decoding if it is started.
(WebCore::BitmapImage::newFrameNativeImageAvailableAtIndex): This function is called from the async image decoding work queue when finishing decoding a native image frame.

  • platform/graphics/BitmapImage.h:

(WebCore::BitmapImage::startAnimation): Added. It is now calls internalStartAnimation().

  • platform/graphics/Color.h: Define a constant for the yellow color.
  • platform/graphics/ImageFrameCache.cpp:

(WebCore::ImageFrameCache::clearMetadata): Delete unreferenced member.
(WebCore::ImageFrameCache::requestFrameAsyncDecodingAtIndex): Return true if the frame is requested for async decoding.

  • platform/graphics/ImageFrameCache.h:
  • platform/graphics/ImageObserver.h: Add virtual functions for allowSubsampling, allowAsyncImageDecoding and showDebugBackground.
  • platform/graphics/ImageSource.cpp:

(WebCore::ImageSource::maximumSubsamplingLevel): Move checking allowSubsampling() to the caller BitmapImage::draw().

  • platform/graphics/ImageSource.h: Remove the setting allowSubsampling(); it can be retrieved from imageObserver().

(WebCore::ImageSource::setAllowSubsampling): Deleted.

  • rendering/RenderImageResource.cpp:

(WebCore::RenderImageResource::shutdown): Stop the animation of an image when shutting down the resource.

  • rendering/RenderImageResourceStyleImage.cpp:

(WebCore::RenderImageResourceStyleImage::shutdown): Ditto.
svg/graphics/SVGImageClients.h: Change the parameter to ImageObserver::changedInRect() to be a pointer.
(WebCore::SVGImageChromeClient::invalidateContentsAndRootView):

  • testing/Internals.cpp:

(WebCore::Internals::setImageFrameDecodingDuration): Sets a fixed frame decoding duration for testing.

  • testing/Internals.h:
  • testing/Internals.idl: Adds an internal option for ImageFrameDecodingDuration.

LayoutTests:

  • fast/images/slower-animation-than-decoding-image-expected.txt: Added.
  • fast/images/slower-animation-than-decoding-image.html: Added.
  • fast/images/slower-decoding-than-animation-image-expected.txt: Added.
  • fast/images/slower-decoding-than-animation-image.html: Added.

In these tests, CanvasRenderingContext2D.drawImage() is used to better
control advancing the animation of an animated image. A setTimeout() is
used instead of the frame duration to schedule when the drawing happens.
The first test ensures that faster decoding does not overrule the frame
duration; the setTimeout interval in this case. The second test ensures
the animation is not advanced unless decoding the next frame has finished.

  • fast/images/stopped-animation-deleted-image-expected.txt: Added.
  • fast/images/stopped-animation-deleted-image.html: Added.

This test ensures that if an animated image is removed from the document,
its draw() method won't be called even if the animation timer fires or the
decoding new frame availability notification is received.

Location:
trunk
Files:
6 added
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r208509 r208511  
     12016-11-09  Said Abou-Hallawa  <sabouhallawa@apple.com>
     2
     3        Change the decoding for some animated images to be asynchronous
     4        https://bugs.webkit.org/show_bug.cgi?id=161566
     5
     6        Reviewed by Simon Fraser.
     7
     8        * fast/images/slower-animation-than-decoding-image-expected.txt: Added.
     9        * fast/images/slower-animation-than-decoding-image.html: Added.
     10        * fast/images/slower-decoding-than-animation-image-expected.txt: Added.
     11        * fast/images/slower-decoding-than-animation-image.html: Added.
     12        In these tests, CanvasRenderingContext2D.drawImage() is used to better
     13        control advancing the animation of an animated image. A setTimeout() is
     14        used instead of the frame duration to schedule when the drawing happens.
     15        The first test ensures that faster decoding does not overrule the frame
     16        duration; the setTimeout interval in this case. The second test ensures
     17        the animation is not advanced unless decoding the next frame has finished.
     18
     19        * fast/images/stopped-animation-deleted-image-expected.txt: Added.
     20        * fast/images/stopped-animation-deleted-image.html: Added.
     21        This test ensures that if an animated image is removed from the document,
     22        its draw() method won't be called even if the animation timer fires or the
     23        decoding new frame availability notification is received.
     24
    1252016-11-04  Brent Fulgham  <bfulgham@apple.com>
    226
  • trunk/Source/WebCore/ChangeLog

    r208509 r208511  
     12016-11-09  Said Abou-Hallawa  <sabouhallawa@apple.com>
     2
     3        Change the decoding for some animated images to be asynchronous
     4        https://bugs.webkit.org/show_bug.cgi?id=161566
     5
     6        Reviewed by Simon Fraser.
     7
     8        Tests: fast/images/slower-animation-than-decoding-image.html
     9               fast/images/slower-decoding-than-animation-image.html
     10               fast/images/stopped-animation-deleted-image.html
     11               
     12        Request the next frame before firing the animation timer. The asynchronous
     13        image decoding work queue notifies the BitmapImage when the frame finishes
     14        decoding. If the timer fires before the frame is decoded, no repaint will
     15        be requested. Only when the image frame is ready, the animation will be
     16        advanced and the image will be repainted.
     17
     18        * loader/cache/CachedImage.cpp:
     19        (WebCore::CachedImage::load): Cache the image settings in CachedImage.
     20        (WebCore::CachedImage::createImage): No need to pass allowSubsampling to BitmapImage. It can be retrieved through Image::imageObserver().
     21        (WebCore::CachedImage::changedInRect): Change the parameter to notifyObservers() to be a pointer.
     22        * loader/cache/CachedImage.h: Cache the settings: allowSubsampling, allowAsyncImageDecoding and showDebugBackground through m_loader.
     23        * platform/graphics/BitmapImage.cpp:
     24        (WebCore::BitmapImage::dataChanged): Fix a logging message.
     25        (WebCore::BitmapImage::draw): Store the current SubsamplingLevel to be used when requesting decoding the image of the next frame.
     26        Draw a debug rectangle if the next frame is missed because it is being decoded and the setting showDebugBackground is on.
     27        (WebCore::BitmapImage::startAnimation): Deleted. Moved to the header file.
     28        (WebCore::BitmapImage::internalStartAnimation): Added. Request asynchronous image decoding for the next frame if required. Return the
     29        result of starting the animation.
     30        (WebCore::BitmapImage::advanceAnimation): Call internalAdvanceAnimation() if the frame image is not being decoded. If it is being decoded
     31        and the setting showDebugBackground is on, force repaint so the debug rectangle is drawn.
     32        (WebCore::BitmapImage::internalAdvanceAnimation): This is the old body of advanceAnimation().
     33        (WebCore::BitmapImage::stopAnimation): Stop the asynchronous image decoding if it is started.
     34        (WebCore::BitmapImage::newFrameNativeImageAvailableAtIndex): This function is called from the async image decoding work queue when finishing decoding a native image frame.
     35        * platform/graphics/BitmapImage.h:
     36        (WebCore::BitmapImage::startAnimation): Added. It is now calls internalStartAnimation().
     37        * platform/graphics/Color.h: Define a constant for the yellow color.
     38        * platform/graphics/ImageFrameCache.cpp:
     39        (WebCore::ImageFrameCache::clearMetadata): Delete unreferenced member.
     40        (WebCore::ImageFrameCache::requestFrameAsyncDecodingAtIndex): Return true if the frame is requested for async decoding.
     41        * platform/graphics/ImageFrameCache.h:
     42        * platform/graphics/ImageObserver.h:  Add virtual functions for allowSubsampling, allowAsyncImageDecoding and showDebugBackground.
     43        * platform/graphics/ImageSource.cpp:
     44        (WebCore::ImageSource::maximumSubsamplingLevel): Move checking allowSubsampling() to the caller BitmapImage::draw().
     45        * platform/graphics/ImageSource.h: Remove the setting allowSubsampling(); it can be retrieved from imageObserver().
     46        (WebCore::ImageSource::setAllowSubsampling): Deleted.
     47        * rendering/RenderImageResource.cpp:
     48        (WebCore::RenderImageResource::shutdown): Stop the animation of an image when shutting down the resource.
     49        * rendering/RenderImageResourceStyleImage.cpp:
     50        (WebCore::RenderImageResourceStyleImage::shutdown): Ditto.
     51        svg/graphics/SVGImageClients.h: Change the parameter to ImageObserver::changedInRect() to be a pointer.
     52        (WebCore::SVGImageChromeClient::invalidateContentsAndRootView):
     53        * testing/Internals.cpp:
     54        (WebCore::Internals::setImageFrameDecodingDuration): Sets a fixed frame decoding duration for testing.
     55        * testing/Internals.h:
     56        * testing/Internals.idl: Adds an internal option for ImageFrameDecodingDuration.
     57
    1582016-11-04  Brent Fulgham  <bfulgham@apple.com>
    259
  • trunk/Source/WebCore/loader/cache/CachedImage.cpp

    r208102 r208511  
    9090    else
    9191        setLoading(false);
     92
     93    if (m_loader) {
     94        m_allowSubsampling = m_loader->frameLoader()->frame().settings().imageSubsamplingEnabled();
     95        m_allowAsyncImageDecoding = m_loader->frameLoader()->frame().settings().asyncImageDecodingEnabled();
     96        m_showDebugBackground = m_loader->frameLoader()->frame().settings().showDebugBorders();
     97    }
    9298}
    9399
     
    326332        m_svgImageCache = std::make_unique<SVGImageCache>(svgImage.ptr());
    327333        m_image = WTFMove(svgImage);
    328     } else {
     334    } else
    329335        m_image = BitmapImage::create(this);
    330         downcast<BitmapImage>(*m_image).setAllowSubsampling(m_loader && m_loader->frameLoader()->frame().settings().imageSubsamplingEnabled());
    331     }
    332336
    333337    if (m_image) {
     
    482486}
    483487
    484 void CachedImage::changedInRect(const Image* image, const IntRect& rect)
     488void CachedImage::changedInRect(const Image* image, const IntRect* rect)
    485489{
    486490    if (!image || image != m_image)
    487491        return;
    488     notifyObservers(&rect);
     492    notifyObservers(rect);
    489493}
    490494
  • trunk/Source/WebCore/loader/cache/CachedImage.h

    r206867 r208511  
    119119
    120120    // ImageObserver
     121    bool allowSubsampling() const override { return m_allowSubsampling; }
     122    bool allowAsyncImageDecoding() const override { return m_allowAsyncImageDecoding; }
     123    bool showDebugBackground() const override { return m_showDebugBackground; }
    121124    void decodedSizeChanged(const Image*, long long delta) override;
    122125    void didDraw(const Image*) override;
    123126
    124127    void animationAdvanced(const Image*) override;
    125     void changedInRect(const Image*, const IntRect&) override;
     128    void changedInRect(const Image*, const IntRect* changeRect = nullptr) override;
    126129
    127130    void addIncrementalDataBuffer(SharedBuffer&);
     
    137140    bool m_isManuallyCached { false };
    138141    bool m_shouldPaintBrokenImage { true };
     142
     143    // The default value of m_allowSubsampling should be the same as defaultImageSubsamplingEnabled in Settings.cpp
     144#if PLATFORM(IOS)
     145    bool m_allowSubsampling { true };
     146#else
     147    bool m_allowSubsampling { false };
     148#endif
     149    bool m_allowAsyncImageDecoding { true };
     150    bool m_showDebugBackground { false };
    139151};
    140152
  • trunk/Source/WebCore/platform/graphics/BitmapImage.cpp

    r208365 r208511  
    8484{
    8585    if (!frameHasValidNativeImageAtIndex(index, subsamplingLevel)) {
    86         LOG(Images, "BitmapImage %p frameImageAtIndex - subsamplingLevel was %d, resampling", this, static_cast<int>(frameSubsamplingLevelAtIndex(index)));
     86        LOG(Images, "BitmapImage %p %s - subsamplingLevel was %d, resampling", this, __FUNCTION__, static_cast<int>(frameSubsamplingLevelAtIndex(index)));
    8787        invalidatePlatformData();
    8888    }
     
    142142        return;
    143143
    144     startAnimation();
    145 
    146     Color color = singlePixelSolidColor();
     144    StartAnimationResult result = internalStartAnimation();
     145
     146    Color color;
     147    if (result == StartAnimationResult::DecodingActive && showDebugBackground())
     148        color = Color::yellow;
     149    else
     150        color = singlePixelSolidColor();
     151
    147152    if (color.isValid()) {
    148153        fillWithSolidColor(context, destRect, color, op);
     
    151156
    152157    float scale = subsamplingScale(context, destRect, srcRect);
    153     SubsamplingLevel subsamplingLevel = m_source.subsamplingLevelForScale(scale);
    154     LOG(Images, "BitmapImage %p draw - subsamplingLevel %d at scale %.4f", this, static_cast<int>(subsamplingLevel), scale);
    155 
    156     auto image = frameImageAtIndex(m_currentFrame, subsamplingLevel, &context);
     158    m_currentSubsamplingLevel = allowSubsampling() ? m_source.subsamplingLevelForScale(scale) : SubsamplingLevel::Default;
     159    LOG(Images, "BitmapImage %p draw - subsamplingLevel %d at scale %.4f", this, static_cast<int>(m_currentSubsamplingLevel), scale);
     160
     161    auto image = frameImageAtIndex(m_currentFrame, m_currentSubsamplingLevel, &context);
    157162    if (!image) // If it's too early we won't have an image yet.
    158163        return;
     
    224229}
    225230
    226 void BitmapImage::startAnimation()
    227 {
    228     if (m_frameTimer || !shouldAnimate() || frameCount() <= 1)
    229         return;
     231BitmapImage::StartAnimationResult BitmapImage::internalStartAnimation()
     232{
     233    if (!canAnimate())
     234        return StartAnimationResult::CannotStart;
     235
     236    if (m_frameTimer)
     237        return StartAnimationResult::TimerActive;
     238   
     239    // Don't start a new animation until we draw the frame that is currently being decoded.
     240    size_t nextFrame = (m_currentFrame + 1) % frameCount();
     241    if (frameIsBeingDecodedAtIndex(nextFrame))
     242        return StartAnimationResult::DecodingActive;
    230243
    231244    if (m_currentFrame >= frameCount() - 1) {
     
    235248        // wait on it.
    236249        if (!m_source.isAllDataReceived() && repetitionCount() == RepetitionCountOnce)
    237             return;
     250            return StartAnimationResult::IncompleteData;
    238251
    239252        ++m_repetitionsComplete;
     
    243256            m_animationFinished = true;
    244257            destroyDecodedDataIfNecessary(false);
    245             return;
     258            return StartAnimationResult::CannotStart;
    246259        }
    247260
     
    250263
    251264    // Don't advance the animation to an incomplete frame.
    252     size_t nextFrame = (m_currentFrame + 1) % frameCount();
    253265    if (!m_source.isAllDataReceived() && !frameIsCompleteAtIndex(nextFrame))
    254         return;
     266        return StartAnimationResult::IncompleteData;
    255267
    256268    double time = monotonicallyIncreasingTime();
     
    263275    m_desiredFrameStartTime = std::max(time, m_desiredFrameStartTime + frameDurationAtIndex(m_currentFrame));
    264276
     277    // Request async decoding for nextFrame only if this is required. If nextFrame is not in the frameCache,
     278    // it will be decoded on a separate work queue. When decoding nextFrame finishes, we will be notified
     279    // through the callback newFrameNativeImageAvailableAtIndex(). Otherwise, advanceAnimation() will be called
     280    // when the timer fires and m_currentFrame will be advanced to nextFrame since it is not being decoded.
     281    if ((allowAsyncImageDecoding() && m_source.isAsyncDecodingRequired()) || isAsyncDecodingForcedForTesting()) {
     282        if (!m_source.requestFrameAsyncDecodingAtIndex(nextFrame, m_currentSubsamplingLevel))
     283            LOG(Images, "BitmapImage %p %s - cachedFrameCount %ld nextFrame %ld", this, __FUNCTION__, ++m_cachedFrameCount, nextFrame);
     284        m_desiredFrameDecodeTimeForTesting = time + std::max(m_frameDecodingDurationForTesting, 0.0f);
     285    }
     286
    265287    ASSERT(!m_frameTimer);
    266288    startTimer(m_desiredFrameStartTime - time);
     289    return StartAnimationResult::Started;
    267290}
    268291
     
    271294    clearTimer();
    272295
     296    // Pretend as if decoding nextFrame has taken m_frameDecodingDurationForTesting from
     297    // the time this decoding was requested.
     298    if (isAsyncDecodingForcedForTesting()) {
     299        double time = monotonicallyIncreasingTime();
     300        // Start a timer with the remaining time from now till the m_desiredFrameDecodeTime.
     301        if (m_desiredFrameDecodeTimeForTesting > std::max(time, m_desiredFrameStartTime)) {
     302            startTimer(m_desiredFrameDecodeTimeForTesting - time);
     303            return;
     304        }
     305    }
     306   
     307    // Don't advance to nextFrame unless its decoding has finished or was not required.
     308    size_t nextFrame = (m_currentFrame + 1) % frameCount();
     309    if (!frameIsBeingDecodedAtIndex(nextFrame))
     310        internalAdvanceAnimation();
     311    else {
     312        // Force repaint if showDebugBackground() is on.
     313        if (showDebugBackground())
     314            imageObserver()->changedInRect(this);
     315        LOG(Images, "BitmapImage %p %s - lateFrameCount %ld nextFrame %ld", this, __FUNCTION__, ++m_lateFrameCount, nextFrame);
     316    }
     317}
     318
     319void BitmapImage::internalAdvanceAnimation()
     320{
    273321    m_currentFrame = (m_currentFrame + 1) % frameCount();
     322    ASSERT(!frameIsBeingDecodedAtIndex(m_currentFrame));
     323
    274324    destroyDecodedDataIfNecessary(false);
    275325
     
    283333    // the timer unless all renderers have stopped drawing.
    284334    clearTimer();
     335    m_source.stopAsyncDecodingQueue();
    285336}
    286337
     
    295346    // For extremely large animations, when the animation is reset, we just throw everything away.
    296347    destroyDecodedDataIfNecessary(true);
     348}
     349
     350void BitmapImage::newFrameNativeImageAvailableAtIndex(size_t index)
     351{
     352    UNUSED_PARAM(index);
     353    ASSERT(index == (m_currentFrame + 1) % frameCount());
     354
     355    // Don't advance to nextFrame unless the timer was fired before its decoding finishes.
     356    if (canAnimate() && !m_frameTimer)
     357        internalAdvanceAnimation();
     358    else
     359        LOG(Images, "BitmapImage %p %s - earlyFrameCount %ld nextFrame %ld", this, __FUNCTION__, ++m_earlyFrameCount, index);
    297360}
    298361
  • trunk/Source/WebCore/platform/graphics/BitmapImage.h

    r208365 r208511  
    3030#include "Image.h"
    3131#include "Color.h"
     32#include "ImageObserver.h"
    3233#include "ImageOrientation.h"
    3334#include "ImageSource.h"
     
    8182    Color singlePixelSolidColor() const override { return m_source.singlePixelSolidColor(); }
    8283
    83     void setAllowSubsampling(bool allowSubsampling) { m_source.setAllowSubsampling(allowSubsampling); }
    84 
    8584    bool frameIsBeingDecodedAtIndex(size_t index) const { return m_source.frameIsBeingDecodedAtIndex(index); }
    8685    bool frameIsCompleteAtIndex(size_t index) const { return m_source.frameIsCompleteAtIndex(index); }
     
    9695    ImageOrientation orientationForCurrentFrame() const override { return frameOrientationAtIndex(currentFrame()); }
    9796
     97    bool isAsyncDecodingForcedForTesting() const { return m_frameDecodingDurationForTesting > 0; }
     98    void setFrameDecodingDurationForTesting(float duration) { m_frameDecodingDurationForTesting = duration; }
     99
    98100    // Accessors for native image formats.
    99101#if USE(APPKIT)
     
    131133
    132134    NativeImagePtr frameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default, const GraphicsContext* = nullptr);
     135
     136    bool allowSubsampling() const { return imageObserver() && imageObserver()->allowSubsampling(); }
     137    bool allowAsyncImageDecoding() const { return imageObserver() && imageObserver()->allowAsyncImageDecoding(); }
     138    bool showDebugBackground() const { return imageObserver() && imageObserver()->showDebugBackground(); }
    133139
    134140    // Called to invalidate cached data. When |destroyAll| is true, we wipe out
     
    151157
    152158    // Animation.
     159    enum class StartAnimationResult { CannotStart, IncompleteData, TimerActive, DecodingActive, Started };
    153160    bool isAnimated() const override { return m_source.frameCount() > 1; }
    154161    bool shouldAnimate();
    155162    bool canAnimate();
    156     void startAnimation() override;
     163    void startAnimation() override { internalStartAnimation(); }
     164    StartAnimationResult internalStartAnimation();
    157165    void advanceAnimation();
     166    void internalAdvanceAnimation();
    158167
    159168    // It may look unusual that there is no start animation call as public API. This is because
     
    162171    void stopAnimation() override;
    163172    void resetAnimation() override;
     173    void newFrameNativeImageAvailableAtIndex(size_t) override;
    164174
    165175    // Handle platform-specific data
     
    183193
    184194    size_t m_currentFrame { 0 }; // The index of the current frame of animation.
     195    SubsamplingLevel m_currentSubsamplingLevel { SubsamplingLevel::Default };
    185196    std::unique_ptr<Timer> m_frameTimer;
    186197    RepetitionCount m_repetitionsComplete { RepetitionCountNone }; // How many repetitions we've finished.
     
    188199    bool m_animationFinished { false };
    189200
     201    float m_frameDecodingDurationForTesting { 0 };
     202    double m_desiredFrameDecodeTimeForTesting { 0 };
     203#if !LOG_DISABLED
     204    size_t m_lateFrameCount { 0 };
     205    size_t m_earlyFrameCount { 0 };
     206    size_t m_cachedFrameCount { 0 };
     207#endif
     208
    190209#if USE(APPKIT)
    191210    mutable RetainPtr<NSImage> m_nsImage; // A cached NSImage of all the frames. Only built lazily if someone actually queries for one.
  • trunk/Source/WebCore/platform/graphics/Color.h

    r208460 r208511  
    265265    WEBCORE_EXPORT static const RGBA32 transparent = 0x00000000;
    266266    static const RGBA32 cyan = 0xFF00FFFF;
     267    static const RGBA32 yellow = 0xFFFFFF00;
    267268
    268269#if PLATFORM(IOS)
  • trunk/Source/WebCore/platform/graphics/ImageFrameCache.cpp

    r208365 r208511  
    285285}
    286286
    287 void ImageFrameCache::requestFrameAsyncDecodingAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
     287bool ImageFrameCache::requestFrameAsyncDecodingAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
    288288{
    289289    if (!isDecoderAvailable())
    290         return;
     290        return false;
    291291
    292292    if (!hasDecodingQueue())
     
    300300   
    301301    if (frame.hasValidNativeImage(subsamplingLevel))
    302         return;
     302        return false;
    303303   
    304304    frame.setDecoding(ImageFrame::Decoding::BeingDecoded);
    305305    m_frameRequestQueue.enqueue({ index, subsamplingLevel });
     306    return true;
    306307}
    307308
     
    337338    m_frameCount = Nullopt;
    338339    m_singlePixelSolidColor = Nullopt;
    339     m_maximumSubsamplingLevel = Nullopt;
    340340}
    341341
  • trunk/Source/WebCore/platform/graphics/ImageFrameCache.h

    r208365 r208511  
    6969    // Asynchronous image decoding
    7070    void startAsyncDecodingQueue();
    71     void requestFrameAsyncDecodingAtIndex(size_t, SubsamplingLevel);
     71    bool requestFrameAsyncDecodingAtIndex(size_t, SubsamplingLevel);
    7272    void stopAsyncDecodingQueue();
    7373    bool hasDecodingQueue() { return m_decodingQueue; }
     
    163163    Optional<IntSize> m_size;
    164164    Optional<IntSize> m_sizeRespectingOrientation;
    165     Optional<SubsamplingLevel> m_maximumSubsamplingLevel;
    166165    Optional<Color> m_singlePixelSolidColor;
    167166};
  • trunk/Source/WebCore/platform/graphics/ImageObserver.h

    r206635 r208511  
    3838    virtual ~ImageObserver() {}
    3939public:
     40    virtual bool allowSubsampling() const = 0;
     41    virtual bool allowAsyncImageDecoding() const = 0;
     42    virtual bool showDebugBackground() const = 0;
    4043    virtual void decodedSizeChanged(const Image*, long long delta) = 0;
     44
    4145    virtual void didDraw(const Image*) = 0;
    4246
    4347    virtual void animationAdvanced(const Image*) = 0;
    4448
    45     virtual void changedInRect(const Image*, const IntRect&) = 0;
     49    virtual void changedInRect(const Image*, const IntRect* changeRect = nullptr) = 0;
    4650};
    4751
  • trunk/Source/WebCore/platform/graphics/ImageSource.cpp

    r208365 r208511  
    187187        return m_maximumSubsamplingLevel.value();
    188188
    189     if (!m_allowSubsampling || !isDecoderAvailable() || !m_decoder->frameAllowSubsamplingAtIndex(0))
     189    if (!isDecoderAvailable() || !m_decoder->frameAllowSubsamplingAtIndex(0))
    190190        return SubsamplingLevel::Default;
    191191
  • trunk/Source/WebCore/platform/graphics/ImageSource.h

    r208365 r208511  
    6767
    6868    bool isAsyncDecodingRequired();
    69     void requestFrameAsyncDecodingAtIndex(size_t index, SubsamplingLevel subsamplingLevel) { m_frameCache->requestFrameAsyncDecodingAtIndex(index, subsamplingLevel); }
     69    bool requestFrameAsyncDecodingAtIndex(size_t index, SubsamplingLevel subsamplingLevel) { return m_frameCache->requestFrameAsyncDecodingAtIndex(index, subsamplingLevel); }
    7070    void stopAsyncDecodingQueue() { m_frameCache->stopAsyncDecodingQueue(); }
    7171
     
    9999    SubsamplingLevel maximumSubsamplingLevel();
    100100    SubsamplingLevel subsamplingLevelForScale(float);
    101     void setAllowSubsampling(bool allowSubsampling) { m_allowSubsampling = allowSubsampling; }
    102101    NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
    103102
     
    114113    Optional<SubsamplingLevel> m_maximumSubsamplingLevel;
    115114
    116     // The default value of m_allowSubsampling should be the same as defaultImageSubsamplingEnabled in Settings.cpp
    117 #if PLATFORM(IOS)
    118     bool m_allowSubsampling { true };
    119 #else
    120     bool m_allowSubsampling { false };
    121 #endif
    122 
    123115#if PLATFORM(IOS)
    124116    // FIXME: We should expose a setting to enable/disable progressive loading so that we can remove the PLATFORM(IOS)-guard.
  • trunk/Source/WebCore/rendering/RenderImageResource.cpp

    r206867 r208511  
    5757    ASSERT(m_renderer);
    5858
    59     if (m_cachedImage)
     59    if (m_cachedImage) {
     60        image()->stopAnimation();
    6061        m_cachedImage->removeClient(*m_renderer);
     62    }
    6163}
    6264
  • trunk/Source/WebCore/rendering/RenderImageResourceStyleImage.cpp

    r205181 r208511  
    5858    ASSERT(m_renderer);
    5959    m_styleImage->removeClient(m_renderer);
    60     m_cachedImage = nullptr;
     60    if (m_cachedImage) {
     61        image()->stopAnimation();
     62        m_cachedImage = nullptr;
     63    }
    6164}
    6265
  • trunk/Source/WebCore/svg/graphics/SVGImageClients.h

    r203469 r208511  
    5555        // If m_image->m_page is null, we're being destructed, don't fire changedInRect() in that case.
    5656        if (m_image && m_image->imageObserver() && m_image->m_page)
    57             m_image->imageObserver()->changedInRect(m_image, r);
     57            m_image->imageObserver()->changedInRect(m_image, &r);
    5858    }
    5959   
  • trunk/Source/WebCore/testing/Internals.cpp

    r208475 r208511  
    650650}
    651651
     652void Internals::setImageFrameDecodingDuration(HTMLImageElement& element, float duration)
     653{
     654    auto* cachedImage = element.cachedImage();
     655    if (!cachedImage)
     656        return;
     657   
     658    auto* image = cachedImage->image();
     659    if (!is<BitmapImage>(image))
     660        return;
     661   
     662    downcast<BitmapImage>(*image).setFrameDecodingDurationForTesting(duration);
     663}
     664
    652665void Internals::clearPageCache()
    653666{
  • trunk/Source/WebCore/testing/Internals.h

    r208475 r208511  
    104104
    105105    unsigned imageFrameIndex(HTMLImageElement&);
     106    void setImageFrameDecodingDuration(HTMLImageElement&, float duration);
    106107
    107108    void clearPageCache();
  • trunk/Source/WebCore/testing/Internals.idl

    r208475 r208511  
    222222
    223223    unsigned long imageFrameIndex(HTMLImageElement element);
     224    void setImageFrameDecodingDuration(HTMLImageElement element, unrestricted float duration);
    224225
    225226    readonly attribute InternalSettings settings;
Note: See TracChangeset for help on using the changeset viewer.