Changeset 213618 in webkit


Ignore:
Timestamp:
Mar 8, 2017 6:16:51 PM (7 years ago)
Author:
commit-queue@webkit.org
Message:

Enable async image decoding for large images
https://bugs.webkit.org/show_bug.cgi?id=165039

Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2017-03-08
Reviewed by Simon Fraser.

Source/WebCore:

Once FrameView finishes flushing compositing, it will request all its
images, which intersect with the tileCoverageRect (aka the futureRect)
of the TileController, to start asynchronously decoding their image frames.
This should improve the image first time paint and the scrolling scenarios.
It also makes the scrolling more responsive by removing the decoding step
from the main thread.

For now we are going to disable the asynchronous image decoding for the
webkit test runner because drawing the image does not block the page rendering
anymore. An image can be repainted later when its frame is ready for painting.
This can cause a test to fail because the webkit test runner may capture
an image for the page before painting all the images. The asynchronous image
decoding can to be explicitly enabled from the test page. Once the specs
of the image 'async' attribute and 'ready' event is approved, this should
be revisited. It is important to test what we ship and eventually async
image decoding should be enabled in the webkit test runner.

  • html/HTMLImageElement.cpp:

(WebCore::HTMLImageElement::didAttachRenderers):
(WebCore::HTMLImageElement::willDetachRenderers):
Register/unregister the renderer of the HTMLImageElement for async image decoding
from the RenderView. I followed what HTMLMediaElement to registerForVisibleInViewportCallback().

  • html/HTMLImageElement.h:
  • page/FrameView.cpp:

(WebCore::FrameView::flushCompositingStateForThisFrame): For all the images inside
the tileCoverageRect of the TileController, request async image decoding.
(WebCore::FrameView::applyRecursivelyWithAbsoluteRect): Request the async image decoding for the
the images inside this FrameView and then recursively do the same thing for all sub FrameViews.
(WebCore::FrameView::requestAsyncDecodingForImagesInAbsoluteRect): Calls the RenderView to
make the request.
(WebCore::FrameView::requestAsyncDecodingForImagesInAbsoluteRectIncludingSubframes): Calls
applyRecursivelyWithAbsoluteRect giving an apply lambda which calls requestAsyncDecodingForImagesInAbsoluteRect.

  • page/FrameView.h:
  • platform/graphics/BitmapImage.cpp:

(WebCore::BitmapImage::destroyDecodedData): ImageSource::hasDecodingQueue() is renamed to ImageSource::hasAsyncDecodingQueue().
(WebCore::BitmapImage::dataChanged): Use String::utf8().data() instead of String::characters8().
(WebCore::BitmapImage::draw): If drawing the current frame is called while it is being
decoded, draw the the image if the current frame was decoded but for a different size
and and will not invoke decoding while painting. If the frame is being decoded and there
isn't a decoded frame, return without drawing but set a flag that that this image needs
a repaint.
(WebCore::BitmapImage::internalStartAnimation): Use String::utf8().data() instead of String::characters8().
(WebCore::BitmapImage::advanceAnimation): Ditto.
(WebCore::BitmapImage::internalAdvanceAnimation): Ditto.
(WebCore::BitmapImage::newFrameNativeImageAvailableAtIndex): Now this callback can be
called form the ImageFrameCache when finishing a frame of an animated image or the
frame of a large image. For large images, we need to call CachedImage::changedInRect()
if this image needs a repaint. If the decoding queue is idle, we should close it.
(WebCore::BitmapImage::requestAsyncDecoding): This is called form
RenderView::requestAsyncDecodingForImagesInRect().

  • platform/graphics/BitmapImage.h:
  • platform/graphics/Image.h:

(WebCore::Image::requestAsyncDecoding): Add the default implementation of a virtual function.

  • platform/graphics/ImageFrameCache.cpp:

(WebCore::ImageFrameCache::~ImageFrameCache): hasDecodingQueue() was renamed to hasAsyncDecodingQueue().
(WebCore::ImageFrameCache::decodingQueue): Change the QNS of the decoding thread to be WorkQueue::QOS::Default.
WorkQueue::QOS::UserInteractive causes the scrolling thread to preempted which can make the scrolling choppy.
(WebCore::ImageFrameCache::startAsyncDecodingQueue): hasDecodingQueue() was renamed to hasAsyncDecodingQueue().
(WebCore::ImageFrameCache::requestFrameAsyncDecodingAtIndex): Ditto.
(WebCore::ImageFrameCache::isAsyncDecodingQueueIdle): A helper function to tell whether the decoding thread is idle.
(WebCore::ImageFrameCache::stopAsyncDecodingQueue): hasDecodingQueue() was renamed to hasAsyncDecodingQueue().

  • platform/graphics/ImageFrameCache.h:

(WebCore::ImageFrameCache::hasAsyncDecodingQueue): Rename this function to be consistent with the rest of the functions.
(WebCore::ImageFrameCache::hasDecodingQueue): Deleted.

  • platform/graphics/ImageSource.h:

(WebCore::ImageSource::hasAsyncDecodingQueue): hasDecodingQueue() was renamed to hasAsyncDecodingQueue().
(WebCore::ImageSource::isAsyncDecodingQueueIdle): A wrapper for ImageFrameCache::isAsyncDecodingQueueIdle().
(WebCore::ImageSource::hasDecodingQueue): Deleted.

  • platform/graphics/TiledBacking.h: Fix a comment. tileGridExtent() is the only one that is used for testing.
  • rendering/RenderElement.cpp:

(WebCore::RenderElement::~RenderElement):
(WebCore::RenderElement::intersectsAbsoluteRect): Make this function does what shouldRepaintForImageAnimation()
was doing expect the check for document.activeDOMObjectsAreSuspended().
(WebCore::RenderElement::newImageAnimationFrameAvailable): Replace the call to
shouldRepaintForImageAnimation() by checking document().activeDOMObjectsAreSuspended() then a call to
RenderElement::intersectsAbsoluteRect().
(WebCore::RenderElement::repaintForPausedImageAnimationsIfNeeded): Ditto.
(WebCore::RenderElement::registerForAsyncImageDecodingCallback): Call the RenderView to register the renderer..
(WebCore::RenderElement::unregisterForAsyncImageDecodingCallback): Call the RenderView to unregister the renderer..
(WebCore::shouldRepaintForImageAnimation): Deleted.

  • rendering/RenderElement.h:
  • rendering/RenderObject.cpp:

(WebCore::RenderObject::setIsRegisteredForAsyncImageDecodingCallback):

  • rendering/RenderObject.h:

(WebCore::RenderObject::isRegisteredForAsyncImageDecodingCallback):
(WebCore::RenderObject::RenderObjectRareData::RenderObjectRareData):
Mark/unmark the renderer for being RegisteredForAsyncImageDecodingCallback.

  • rendering/RenderReplaced.h: Make intrinsicSize() be a public function.
  • rendering/RenderView.cpp:

(WebCore::RenderView::registerForAsyncImageDecodingCallback): Register a renderer for async image decoding.
(WebCore::RenderView::unregisterForAsyncImageDecodingCallback): Remove a renderer from the list of async image decoding.
(WebCore::RenderView::requestAsyncDecodingForImagesInAbsoluteRect):This loops through all the registered RenderImages
inside this RenderView and if any of them intersects with the rectangle, requestAsyncDecoding for it.

  • rendering/RenderView.h:

Source/WebKit2:

Add WK2 preferences for setting/getting LargeImageAsyncDecoding and
AnimatedImageAsyncDecoding.

  • UIProcess/API/C/WKPreferences.cpp:

(WKPreferencesSetLargeImageAsyncDecodingEnabled):
(WKPreferencesGetLargeImageAsyncDecodingEnabled):
(WKPreferencesSetAnimatedImageAsyncDecodingEnabled):
(WKPreferencesGetAnimatedImageAsyncDecodingEnabled):

  • UIProcess/API/C/WKPreferencesRefPrivate.h:

Tools:

Disable LargeImageAsyncDecoding for DRT/WTR.

  • DumpRenderTree/mac/DumpRenderTree.mm:

(resetWebPreferencesToConsistentValues):

  • WebKitTestRunner/TestController.cpp:

(WTR::TestController::resetPreferencesToConsistentValues):

Location:
trunk
Files:
25 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r213616 r213618  
     12017-03-08  Said Abou-Hallawa  <sabouhallawa@apple.com>
     2
     3        Enable async image decoding for large images
     4        https://bugs.webkit.org/show_bug.cgi?id=165039
     5
     6        Reviewed by Simon Fraser.
     7
     8        Once FrameView finishes flushing compositing, it will request all its
     9        images, which intersect with the tileCoverageRect (aka the futureRect)
     10        of the  TileController, to start asynchronously decoding their image frames.
     11        This should improve the image first time paint and the scrolling scenarios.
     12        It also makes the scrolling more responsive by removing the decoding step
     13        from the main thread.
     14       
     15        For now we are going to disable the asynchronous image decoding for the
     16        webkit test runner because drawing the image does not block the page rendering
     17        anymore. An image can be repainted later when its frame is ready for painting.
     18        This can cause a test to fail because the webkit test runner may capture
     19        an image for the page before painting all the images. The asynchronous image
     20        decoding can to be explicitly enabled from the test page. Once the specs
     21        of the image 'async' attribute and 'ready' event is approved, this should
     22        be revisited. It is important to test what we ship and eventually async
     23        image decoding should be enabled in the webkit test runner.
     24
     25        * html/HTMLImageElement.cpp:
     26        (WebCore::HTMLImageElement::didAttachRenderers):
     27        (WebCore::HTMLImageElement::willDetachRenderers):
     28        Register/unregister the renderer of the HTMLImageElement for async image decoding
     29        from the RenderView. I followed what HTMLMediaElement to registerForVisibleInViewportCallback().
     30        * html/HTMLImageElement.h:
     31       
     32        * page/FrameView.cpp:
     33        (WebCore::FrameView::flushCompositingStateForThisFrame): For all the images inside
     34        the  tileCoverageRect of the TileController, request async image decoding.
     35        (WebCore::FrameView::applyRecursivelyWithAbsoluteRect): Request the async image decoding for the
     36        the images inside this FrameView and then recursively do the same thing for all sub FrameViews.
     37        (WebCore::FrameView::requestAsyncDecodingForImagesInAbsoluteRect): Calls the RenderView to
     38        make the request.
     39        (WebCore::FrameView::requestAsyncDecodingForImagesInAbsoluteRectIncludingSubframes): Calls
     40        applyRecursivelyWithAbsoluteRect giving an apply lambda which calls requestAsyncDecodingForImagesInAbsoluteRect.
     41        * page/FrameView.h:
     42
     43        * platform/graphics/BitmapImage.cpp:
     44        (WebCore::BitmapImage::destroyDecodedData): ImageSource::hasDecodingQueue() is renamed to ImageSource::hasAsyncDecodingQueue().
     45        (WebCore::BitmapImage::dataChanged): Use String::utf8().data() instead of String::characters8().
     46        (WebCore::BitmapImage::draw): If drawing the current frame is called while it is being
     47        decoded, draw the the image if the current frame was decoded but for a different size
     48        and and will not invoke decoding while painting. If the frame is being decoded and there
     49        isn't a decoded frame, return without drawing but set a flag that that this image needs
     50        a repaint.
     51        (WebCore::BitmapImage::internalStartAnimation): Use String::utf8().data() instead of String::characters8().
     52        (WebCore::BitmapImage::advanceAnimation): Ditto.
     53        (WebCore::BitmapImage::internalAdvanceAnimation): Ditto.
     54        (WebCore::BitmapImage::newFrameNativeImageAvailableAtIndex): Now this callback can be
     55        called form the ImageFrameCache when finishing a frame of an animated image or the
     56        frame of a large image. For large images, we need to call CachedImage::changedInRect()
     57        if this image needs a repaint. If the decoding queue is idle, we should close it.
     58        (WebCore::BitmapImage::requestAsyncDecoding): This is called form
     59        RenderView::requestAsyncDecodingForImagesInRect().
     60        * platform/graphics/BitmapImage.h:
     61
     62        * platform/graphics/Image.h:
     63        (WebCore::Image::requestAsyncDecoding): Add the default implementation of a virtual function.
     64
     65        * platform/graphics/ImageFrameCache.cpp:
     66        (WebCore::ImageFrameCache::~ImageFrameCache): hasDecodingQueue() was renamed to hasAsyncDecodingQueue().
     67        (WebCore::ImageFrameCache::decodingQueue): Change the QNS of the decoding thread to be WorkQueue::QOS::Default.
     68        WorkQueue::QOS::UserInteractive causes the scrolling thread to preempted  which can make the scrolling choppy.
     69        (WebCore::ImageFrameCache::startAsyncDecodingQueue): hasDecodingQueue() was renamed to hasAsyncDecodingQueue().
     70        (WebCore::ImageFrameCache::requestFrameAsyncDecodingAtIndex): Ditto.
     71        (WebCore::ImageFrameCache::isAsyncDecodingQueueIdle): A helper function to tell whether the decoding thread is idle.
     72        (WebCore::ImageFrameCache::stopAsyncDecodingQueue): hasDecodingQueue() was renamed to hasAsyncDecodingQueue().
     73        * platform/graphics/ImageFrameCache.h:
     74        (WebCore::ImageFrameCache::hasAsyncDecodingQueue): Rename this function to be consistent with the rest of the functions.
     75        (WebCore::ImageFrameCache::hasDecodingQueue): Deleted.
     76
     77        * platform/graphics/ImageSource.h:
     78        (WebCore::ImageSource::hasAsyncDecodingQueue): hasDecodingQueue() was renamed to hasAsyncDecodingQueue().
     79        (WebCore::ImageSource::isAsyncDecodingQueueIdle): A wrapper for ImageFrameCache::isAsyncDecodingQueueIdle().
     80        (WebCore::ImageSource::hasDecodingQueue): Deleted.
     81       
     82        * platform/graphics/TiledBacking.h: Fix a comment. tileGridExtent() is the only one that is used for testing.
     83
     84        * rendering/RenderElement.cpp:
     85        (WebCore::RenderElement::~RenderElement):
     86        (WebCore::RenderElement::intersectsAbsoluteRect): Make this function does what shouldRepaintForImageAnimation()
     87        was doing expect the check for document.activeDOMObjectsAreSuspended().
     88        (WebCore::RenderElement::newImageAnimationFrameAvailable): Replace the call to
     89        shouldRepaintForImageAnimation() by checking document().activeDOMObjectsAreSuspended() then a call to
     90        RenderElement::intersectsAbsoluteRect().
     91        (WebCore::RenderElement::repaintForPausedImageAnimationsIfNeeded): Ditto.
     92        (WebCore::RenderElement::registerForAsyncImageDecodingCallback): Call the RenderView to register the renderer..
     93        (WebCore::RenderElement::unregisterForAsyncImageDecodingCallback): Call the RenderView to unregister the renderer..
     94        (WebCore::shouldRepaintForImageAnimation): Deleted.
     95        * rendering/RenderElement.h:
     96
     97        * rendering/RenderObject.cpp:
     98        (WebCore::RenderObject::setIsRegisteredForAsyncImageDecodingCallback):
     99        * rendering/RenderObject.h:
     100        (WebCore::RenderObject::isRegisteredForAsyncImageDecodingCallback):
     101        (WebCore::RenderObject::RenderObjectRareData::RenderObjectRareData):
     102        Mark/unmark the renderer for being RegisteredForAsyncImageDecodingCallback.
     103
     104        * rendering/RenderReplaced.h: Make intrinsicSize() be a public function.
     105
     106        * rendering/RenderView.cpp:
     107        (WebCore::RenderView::registerForAsyncImageDecodingCallback): Register a renderer for async image decoding.
     108        (WebCore::RenderView::unregisterForAsyncImageDecodingCallback): Remove a renderer from the list of async image decoding.
     109        (WebCore::RenderView::requestAsyncDecodingForImagesInAbsoluteRect):This loops through all the registered RenderImages
     110        inside this RenderView and if any of them intersects with the rectangle, requestAsyncDecoding for it.
     111        * rendering/RenderView.h:
     112
    11132017-03-08  Michael Catanzaro  <mcatanzaro@igalia.com>
    2114
  • trunk/Source/WebCore/html/HTMLImageElement.cpp

    r211964 r213618  
    290290    if (!m_imageLoader.image() && !renderImageResource.cachedImage())
    291291        renderImage.setImageSizeForAltText();
     292   
     293    renderImage.registerForAsyncImageDecodingCallback();
     294}
     295   
     296void HTMLImageElement::willDetachRenderers()
     297{
     298    if (!is<RenderImage>(renderer()))
     299        return;
     300
     301    renderer()->unregisterForAsyncImageDecodingCallback();
    292302}
    293303
  • trunk/Source/WebCore/html/HTMLImageElement.h

    r209810 r213618  
    106106
    107107    void didAttachRenderers() override;
     108    void willDetachRenderers() override;
    108109    RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) override;
    109110    void setBestFitURLAndDPRFromImageCandidate(const ImageCandidate&);
  • trunk/Source/WebCore/page/FrameView.cpp

    r213214 r213618  
    10591059
    10601060    renderView->compositor().flushPendingLayerChanges(&rootFrameForFlush == m_frame.ptr());
     1061   
     1062    if (TiledBacking* tiledBacking = this->tiledBacking())
     1063        requestAsyncDecodingForImagesInAbsoluteRectIncludingSubframes(tiledBacking->tileCoverageRect());
     1064   
    10611065    return true;
    10621066}
     
    25282532    viewportContentsChanged();
    25292533}
     2534   
     2535void FrameView::applyRecursivelyWithAbsoluteRect(const IntRect& rect, const std::function<void(FrameView&, const IntRect&)>& apply)
     2536{
     2537    apply(*this, rect);
     2538
     2539    // Recursive call for subframes. We cache the current FrameView's windowClipRect to avoid recomputing it for every subframe.
     2540    IntRect windowClipRect = contentsToWindow(rect);
     2541    SetForScope<IntRect*> windowClipRectCache(m_cachedWindowClipRect, &windowClipRect);
     2542    for (Frame* childFrame = frame().tree().firstChild(); childFrame; childFrame = childFrame->tree().nextSibling()) {
     2543        if (auto* childView = childFrame->view())
     2544            childView->applyRecursivelyWithAbsoluteRect(rect, apply);
     2545    }
     2546}
    25302547
    25312548void FrameView::applyRecursivelyWithVisibleRect(const std::function<void (FrameView& frameView, const IntRect& visibleRect)>& apply)
     
    25792596    applyRecursivelyWithVisibleRect([] (FrameView& frameView, const IntRect& visibleRect) {
    25802597        frameView.resumeVisibleImageAnimations(visibleRect);
     2598    });
     2599}
     2600
     2601void FrameView::requestAsyncDecodingForImagesInAbsoluteRect(const IntRect& rect)
     2602{
     2603    if (!frame().view()) {
     2604        // The frame is being destroyed.
     2605        return;
     2606    }
     2607
     2608    if (rect.isEmpty())
     2609        return;
     2610
     2611    if (auto* renderView = frame().contentRenderer())
     2612        renderView->requestAsyncDecodingForImagesInAbsoluteRect(rect);
     2613}
     2614
     2615void FrameView::requestAsyncDecodingForImagesInAbsoluteRectIncludingSubframes(const IntRect& rect)
     2616{
     2617    if (!frame().settings().largeImageAsyncDecodingEnabled())
     2618        return;
     2619
     2620    applyRecursivelyWithAbsoluteRect(rect, [] (FrameView& frameView, const IntRect& rect) {
     2621        frameView.requestAsyncDecodingForImagesInAbsoluteRect(rect);
    25812622    });
    25822623}
  • trunk/Source/WebCore/page/FrameView.h

    r211910 r213618  
    276276    void viewportContentsChanged();
    277277    WEBCORE_EXPORT void resumeVisibleImageAnimationsIncludingSubframes();
     278    void requestAsyncDecodingForImagesInAbsoluteRectIncludingSubframes(const IntRect&);
    278279
    279280    String mediaType() const;
     
    646647    void autoSizeIfEnabled();
    647648
     649    void applyRecursivelyWithAbsoluteRect(const IntRect&, const std::function<void(FrameView& frameView, const IntRect& rect)>&);
    648650    void applyRecursivelyWithVisibleRect(const std::function<void (FrameView& frameView, const IntRect& visibleRect)>&);
    649651    void resumeVisibleImageAnimations(const IntRect& visibleRect);
    650652    void updateScriptedAnimationsAndTimersThrottlingState(const IntRect& visibleRect);
     653    void requestAsyncDecodingForImagesInAbsoluteRect(const IntRect&);
    651654
    652655    void updateLayerFlushThrottling();
  • trunk/Source/WebCore/platform/graphics/BitmapImage.cpp

    r213563 r213618  
    6868    if (!destroyAll)
    6969        m_source.destroyDecodedDataBeforeFrame(m_currentFrame);
    70     else if (m_source.hasDecodingQueue())
     70    else if (m_source.hasAsyncDecodingQueue())
    7171        m_source.destroyAllDecodedDataExcludeFrame(m_currentFrame);
    7272    else
     
    7575    // There's no need to throw away the decoder unless we're explicitly asked
    7676    // to destroy all of the frames.
    77     if (!destroyAll || m_source.hasDecodingQueue())
     77    if (!destroyAll || m_source.hasAsyncDecodingQueue())
    7878        m_source.clearFrameBufferCache(m_currentFrame);
    7979    else
     
    104104{
    105105    if (!frameHasValidNativeImageAtIndex(index, subsamplingLevel, sizeForDrawing)) {
    106         LOG(Images, "BitmapImage::%s - %p - url: %s [subsamplingLevel was %d, resampling]", __FUNCTION__, this, sourceURL().characters8(), static_cast<int>(frameSubsamplingLevelAtIndex(index)));
     106        LOG(Images, "BitmapImage::%s - %p - url: %s [subsamplingLevel was %d, resampling]", __FUNCTION__, this, sourceURL().utf8().data(), static_cast<int>(frameSubsamplingLevelAtIndex(index)));
    107107        invalidatePlatformData();
    108108    }
     
    165165    StartAnimationResult result = internalStartAnimation();
    166166
    167     Color color;
    168     if (result == StartAnimationResult::DecodingActive && showDebugBackground())
    169         color = Color::yellow;
    170     else
    171         color = singlePixelSolidColor();
    172 
     167    if (result == StartAnimationResult::DecodingActive && showDebugBackground()) {
     168        fillWithSolidColor(context, destRect, Color::yellow, op);
     169        return;
     170    }
     171
     172    NativeImagePtr image;
     173    if (frameIsBeingDecodedAtIndex(m_currentFrame, m_sizeForDrawing)) {
     174        ASSERT(!canAnimate() && !m_currentFrame);
     175        m_needsRepaint = true;
     176
     177        if (!frameHasDecodedNativeImage(m_currentFrame)) {
     178            if (showDebugBackground())
     179                fillWithSolidColor(context, destRect, Color::yellow, op);
     180            return;
     181        }
     182
     183        image = frameImageAtIndex(m_currentFrame);
     184    } else {
     185        float scale = subsamplingScale(context, destRect, srcRect);
     186        m_currentSubsamplingLevel = allowSubsampling() ? m_source.subsamplingLevelForScale(scale) : SubsamplingLevel::Default;
     187        LOG(Images, "BitmapImage::%s - %p - url: %s [subsamplingLevel = %d scale = %.4f]", __FUNCTION__, this, sourceURL().utf8().data(), static_cast<int>(m_currentSubsamplingLevel), scale);
     188
     189        ASSERT_IMPLIES(result == StartAnimationResult::DecodingActive, m_source.frameHasValidNativeImageAtIndex(m_currentFrame, m_currentSubsamplingLevel, m_sizeForDrawing));
     190        image = frameImageAtIndex(m_currentFrame, m_currentSubsamplingLevel, m_sizeForDrawing, &context);
     191    }
     192
     193    if (!image) // If it's too early we won't have an image yet.
     194        return;
     195
     196    Color color = singlePixelSolidColor();
    173197    if (color.isValid()) {
    174198        fillWithSolidColor(context, destRect, color, op);
    175199        return;
    176200    }
    177 
    178     float scale = subsamplingScale(context, destRect, srcRect);
    179     m_currentSubsamplingLevel = allowSubsampling() ? m_source.subsamplingLevelForScale(scale) : SubsamplingLevel::Default;
    180     LOG(Images, "BitmapImage::%s - %p - url: %s [m_currentFrame = %ld subsamplingLevel = %d scale = %.4f]", __FUNCTION__, this, sourceURL().characters8(), m_currentFrame, static_cast<int>(m_currentSubsamplingLevel), scale);
    181 
    182     ASSERT_IMPLIES(result == StartAnimationResult::DecodingActive, m_source.frameHasValidNativeImageAtIndex(m_currentFrame, m_currentSubsamplingLevel, m_sizeForDrawing));
    183     auto image = frameImageAtIndex(m_currentFrame, m_currentSubsamplingLevel, m_sizeForDrawing, &context);
    184     if (!image) // If it's too early we won't have an image yet.
    185         return;
    186201
    187202    ImageOrientation orientation(description.imageOrientation());
     
    268283    if (m_frameTimer)
    269284        return StartAnimationResult::TimerActive;
    270    
     285
    271286    // Don't start a new animation until we draw the frame that is currently being decoded.
    272287    size_t nextFrame = (m_currentFrame + 1) % frameCount();
    273288    if (frameIsBeingDecodedAtIndex(nextFrame, m_sizeForDrawing)) {
    274         LOG(Images, "BitmapImage::%s - %p - url: %s [nextFrame = %ld is being decoded]", __FUNCTION__, this, sourceURL().characters8(), nextFrame);
     289        LOG(Images, "BitmapImage::%s - %p - url: %s [nextFrame = %ld is being decoded]", __FUNCTION__, this, sourceURL().utf8().data(), nextFrame);
    275290        return StartAnimationResult::DecodingActive;
    276291    }
     
    318333#if !LOG_DISABLED
    319334        if (isAsyncDecode)
    320             LOG(Images, "BitmapImage::%s - %p - url: %s [requesting async decoding for nextFrame = %ld]", __FUNCTION__, this, sourceURL().characters8(), nextFrame);
     335            LOG(Images, "BitmapImage::%s - %p - url: %s [requesting async decoding for nextFrame = %ld]", __FUNCTION__, this, sourceURL().utf8().data(), nextFrame);
    321336        else
    322             LOG(Images, "BitmapImage::%s - %p - url: %s [cachedFrameCount = %ld nextFrame = %ld]", __FUNCTION__, this, sourceURL().characters8(), ++m_cachedFrameCount, nextFrame);
     337            LOG(Images, "BitmapImage::%s - %p - url: %s [cachedFrameCount = %ld nextFrame = %ld]", __FUNCTION__, this, sourceURL().utf8().data(), ++m_cachedFrameCount, nextFrame);
    323338#else
    324339        UNUSED_PARAM(isAsyncDecode);
     
    347362        }
    348363    }
    349    
     364
    350365    // Don't advance to nextFrame unless its decoding has finished or was not required.
    351366    size_t nextFrame = (m_currentFrame + 1) % frameCount();
     
    356371        if (showDebugBackground())
    357372            imageObserver()->changedInRect(this);
    358         LOG(Images, "BitmapImage::%s - %p - url: %s [lateFrameCount = %ld nextFrame = %ld]", __FUNCTION__, this, sourceURL().characters8(), ++m_lateFrameCount, nextFrame);
     373        LOG(Images, "BitmapImage::%s - %p - url: %s [lateFrameCount = %ld nextFrame = %ld]", __FUNCTION__, this, sourceURL().utf8().data(), ++m_lateFrameCount, nextFrame);
    359374    }
    360375}
     
    370385        imageObserver()->animationAdvanced(this);
    371386
    372     LOG(Images, "BitmapImage::%s - %p - url: %s [m_currentFrame = %ld]", __FUNCTION__, this, sourceURL().characters8(), m_currentFrame);
     387    LOG(Images, "BitmapImage::%s - %p - url: %s [m_currentFrame = %ld]", __FUNCTION__, this, sourceURL().utf8().data(), m_currentFrame);
    373388}
    374389
     
    396411{
    397412    UNUSED_PARAM(index);
    398     ASSERT(index == (m_currentFrame + 1) % frameCount());
    399 
    400     // Don't advance to nextFrame unless the timer was fired before its decoding finishes.
    401     if (canAnimate() && !m_frameTimer)
    402         internalAdvanceAnimation();
    403     else
    404         LOG(Images, "BitmapImage::%s - %p - url: %s [earlyFrameCount = %ld nextFrame = %ld]", __FUNCTION__, this, sourceURL().characters8(), ++m_earlyFrameCount, index);
     413    if (canAnimate()) {
     414        ASSERT(index == (m_currentFrame + 1) % frameCount());
     415       
     416        // Don't advance to nextFrame unless the timer was fired before its decoding finishes.
     417        if (canAnimate() && !m_frameTimer)
     418            internalAdvanceAnimation();
     419        else
     420            LOG(Images, "BitmapImage::%s - %p - url: %s [earlyFrameCount = %ld nextFrame = %ld]", __FUNCTION__, this, sourceURL().utf8().data(), ++m_earlyFrameCount, index);
     421    } else {
     422        ASSERT(index == m_currentFrame && !m_currentFrame);
     423       
     424        if (m_needsRepaint) {
     425            imageObserver()->changedInRect(this, nullptr);
     426            m_needsRepaint = false;
     427        }
     428       
     429        // Keep the number of decoding threads under control.
     430        if (m_source.isAsyncDecodingQueueIdle())
     431            m_source.stopAsyncDecodingQueue();
     432    }
     433}
     434
     435void BitmapImage::requestAsyncDecoding(const IntSize& sizeForDrawing)
     436{
     437    if (!isLargeImageAsyncDecodingRequired())
     438        return;
     439
     440    ASSERT(!m_currentFrame);
     441    bool isAsyncDecode = m_source.requestFrameAsyncDecodingAtIndex(0, m_currentSubsamplingLevel, sizeForDrawing);
     442
     443#if !LOG_DISABLED
     444    if (isAsyncDecode)
     445        LOG(Images, "BitmapImage::%s - %p - url: %s", __FUNCTION__, this, sourceURL().utf8().data());
     446#else
     447    UNUSED_PARAM(isAsyncDecode);
     448#endif
    405449}
    406450
  • trunk/Source/WebCore/platform/graphics/BitmapImage.h

    r213563 r213618  
    174174    void resetAnimation() override;
    175175    void newFrameNativeImageAvailableAtIndex(size_t) override;
     176    void requestAsyncDecoding(const IntSize& sizeForDrawing) override;
    176177
    177178    // Handle platform-specific data
     
    208209    double m_desiredFrameStartTime { 0 }; // The system time at which we hope to see the next call to startAnimation().
    209210    bool m_animationFinished { false };
     211    bool m_needsRepaint { false };
    210212
    211213    float m_frameDecodingDurationForTesting { 0 };
  • trunk/Source/WebCore/platform/graphics/Image.h

    r212484 r213618  
    131131    virtual void resetAnimation() {}
    132132    virtual void newFrameNativeImageAvailableAtIndex(size_t) { }
     133    virtual void requestAsyncDecoding(const IntSize&) { }
    133134   
    134135    // Typically the CachedImage that owns us.
  • trunk/Source/WebCore/platform/graphics/ImageFrameCache.cpp

    r213563 r213618  
    6868ImageFrameCache::~ImageFrameCache()
    6969{
    70     ASSERT(!hasDecodingQueue());
     70    ASSERT(!hasAsyncDecodingQueue());
    7171}
    7272
     
    257257{
    258258    if (!m_decodingQueue)
    259         m_decodingQueue = WorkQueue::create("org.webkit.ImageDecoder", WorkQueue::Type::Serial, WorkQueue::QOS::UserInteractive);
     259        m_decodingQueue = WorkQueue::create("org.webkit.ImageDecoder", WorkQueue::Type::Serial, WorkQueue::QOS::Default);
    260260   
    261261    return *m_decodingQueue;
     
    264264void ImageFrameCache::startAsyncDecodingQueue()
    265265{
    266     if (hasDecodingQueue() || !isDecoderAvailable())
     266    if (hasAsyncDecodingQueue() || !isDecoderAvailable())
    267267        return;
    268268
     
    307307        return false;
    308308
    309     if (!hasDecodingQueue())
     309    if (!hasAsyncDecodingQueue())
    310310        startAsyncDecodingQueue();
    311311   
     
    315315}
    316316
     317bool ImageFrameCache::isAsyncDecodingQueueIdle() const
     318{
     319    for (const ImageFrame& frame : m_frames) {
     320        if (frame.isBeingDecoded())
     321            return false;
     322    }
     323    return true;
     324}
     325   
    317326void ImageFrameCache::stopAsyncDecodingQueue()
    318327{
    319     if (!hasDecodingQueue())
     328    if (!hasAsyncDecodingQueue())
    320329        return;
    321330   
  • trunk/Source/WebCore/platform/graphics/ImageFrameCache.h

    r213563 r213618  
    7272    bool requestFrameAsyncDecodingAtIndex(size_t, SubsamplingLevel, const IntSize&);
    7373    void stopAsyncDecodingQueue();
    74     bool hasDecodingQueue() { return m_decodingQueue; }
     74    bool hasAsyncDecodingQueue() const { return m_decodingQueue; }
     75    bool isAsyncDecodingQueueIdle() const;
    7576
    7677    // Image metadata which is calculated either by the ImageDecoder or directly
  • trunk/Source/WebCore/platform/graphics/ImageSource.h

    r213563 r213618  
    7171    bool isAsyncDecodingRequired();
    7272    bool requestFrameAsyncDecodingAtIndex(size_t index, SubsamplingLevel subsamplingLevel, const IntSize& sizeForDrawing) { return m_frameCache->requestFrameAsyncDecodingAtIndex(index, subsamplingLevel, sizeForDrawing); }
    73     bool hasDecodingQueue() const { return m_frameCache->hasDecodingQueue(); }
     73    bool hasAsyncDecodingQueue() const { return m_frameCache->hasAsyncDecodingQueue(); }
     74    bool isAsyncDecodingQueueIdle() const  { return m_frameCache->isAsyncDecodingQueueIdle(); }
    7475    void stopAsyncDecodingQueue() { m_frameCache->stopAsyncDecodingQueue(); }
    7576
  • trunk/Source/WebCore/platform/graphics/TiledBacking.h

    r211910 r213618  
    146146    virtual IntRect boundsWithoutMargin() const = 0;
    147147
     148    virtual IntRect tileCoverageRect() const = 0;
     149    virtual void setScrollingModeIndication(ScrollingModeIndication) = 0;
     150
    148151    // Exposed for testing
    149     virtual IntRect tileCoverageRect() const = 0;
    150152    virtual IntRect tileGridExtent() const = 0;
    151     virtual void setScrollingModeIndication(ScrollingModeIndication) = 0;
    152153
    153154#if USE(CA)
  • trunk/Source/WebCore/rendering/RenderElement.cpp

    r213455 r213618  
    155155    if (isRegisteredForVisibleInViewportCallback())
    156156        view().unregisterForVisibleInViewportCallback(*this);
     157    if (isRegisteredForAsyncImageDecodingCallback())
     158        view().unregisterForAsyncImageDecodingCallback(*this);
    157159}
    158160
     
    14351437}
    14361438
    1437 static bool shouldRepaintForImageAnimation(const RenderElement& renderer, const IntRect& visibleRect)
    1438 {
    1439     const Document& document = renderer.document();
    1440     if (document.activeDOMObjectsAreSuspended())
     1439bool RenderElement::intersectsAbsoluteRect(const IntRect& rect) const
     1440{
     1441    if (style().visibility() != VISIBLE)
    14411442        return false;
    1442     if (renderer.style().visibility() != VISIBLE)
    1443         return false;
    1444     if (renderer.view().frameView().isOffscreen())
     1443    if (view().frameView().isOffscreen())
    14451444        return false;
    14461445
     
    14491448    // be propagated to the root. At this point, we unfortunately don't have access to the image anymore so we
    14501449    // can no longer check if it is a background image.
    1451     bool backgroundIsPaintedByRoot = renderer.isDocumentElementRenderer();
    1452     if (renderer.isBody()) {
    1453         auto& rootRenderer = *renderer.parent(); // If <body> has a renderer then <html> does too.
     1450    bool backgroundIsPaintedByRoot = isDocumentElementRenderer();
     1451    if (isBody()) {
     1452        auto& rootRenderer = *parent(); // If <body> has a renderer then <html> does too.
    14541453        ASSERT(rootRenderer.isDocumentElementRenderer());
    14551454        ASSERT(is<HTMLHtmlElement>(rootRenderer.element()));
     
    14581457
    14591458    }
    1460     LayoutRect backgroundPaintingRect = backgroundIsPaintedByRoot ? renderer.view().backgroundRect() : renderer.absoluteClippedOverflowRect();
    1461     if (!visibleRect.intersects(enclosingIntRect(backgroundPaintingRect)))
    1462         return false;
    1463 
    1464     return true;
     1459    LayoutRect backgroundPaintingRect = backgroundIsPaintedByRoot ? view().backgroundRect() : absoluteClippedOverflowRect();
     1460    return rect.intersects(enclosingIntRect(backgroundPaintingRect));
    14651461}
    14661462
     
    14971493    auto& frameView = view().frameView();
    14981494    auto visibleRect = frameView.windowToContents(frameView.windowClipRect());
    1499     if (!shouldRepaintForImageAnimation(*this, visibleRect)) {
     1495    if (document().activeDOMObjectsAreSuspended() || !intersectsAbsoluteRect(visibleRect)) {
    15001496        // FIXME: It would be better to pass the image along with the renderer
    15011497        // so that we can be smarter about detecting if the image is inside the
     
    15101506{
    15111507    ASSERT(m_hasPausedImageAnimations);
    1512     if (!shouldRepaintForImageAnimation(*this, visibleRect))
     1508    if (document().activeDOMObjectsAreSuspended() || !intersectsAbsoluteRect(visibleRect))
    15131509        return false;
    15141510
     
    15201516
    15211517    return true;
     1518}
     1519   
     1520void RenderElement::registerForAsyncImageDecodingCallback()
     1521{
     1522    if (isRegisteredForAsyncImageDecodingCallback())
     1523        return;
     1524
     1525    view().registerForAsyncImageDecodingCallback(*this);
     1526    setIsRegisteredForAsyncImageDecodingCallback(true);
     1527}
     1528   
     1529void RenderElement::unregisterForAsyncImageDecodingCallback()
     1530{
     1531    if (!isRegisteredForAsyncImageDecodingCallback())
     1532        return;
     1533
     1534    view().unregisterForAsyncImageDecodingCallback(*this);
     1535    setIsRegisteredForAsyncImageDecodingCallback(false);
    15221536}
    15231537
  • trunk/Source/WebCore/rendering/RenderElement.h

    r213455 r213618  
    139139    bool borderImageIsLoadedAndCanBeRendered() const;
    140140    bool mayCauseRepaintInsideViewport(const IntRect* visibleRect = nullptr) const;
     141    bool intersectsAbsoluteRect(const IntRect&) const;
    141142
    142143    // Returns true if this renderer requires a new stacking context.
     
    191192    bool hasPausedImageAnimations() const { return m_hasPausedImageAnimations; }
    192193    void setHasPausedImageAnimations(bool b) { m_hasPausedImageAnimations = b; }
     194   
     195    void registerForAsyncImageDecodingCallback();
     196    void unregisterForAsyncImageDecodingCallback();
    193197
    194198    void setRenderBoxNeedsLazyRepaint(bool b) { m_renderBoxNeedsLazyRepaint = b; }
  • trunk/Source/WebCore/rendering/RenderObject.cpp

    r213455 r213618  
    19961996        ensureRareData().setVisibleInViewportState(visible);
    19971997}
     1998   
     1999void RenderObject::setIsRegisteredForAsyncImageDecodingCallback(bool registered)
     2000{
     2001    if (registered || hasRareData())
     2002        ensureRareData().setIsRegisteredForAsyncImageDecodingCallback(registered);
     2003}
    19982004
    19992005RenderObject::RareDataMap& RenderObject::rareDataMap()
  • trunk/Source/WebCore/rendering/RenderObject.h

    r213455 r213618  
    459459    };
    460460    VisibleInViewportState visibleInViewportState() { return m_bitfields.hasRareData() ? rareData().visibleInViewportState() : VisibilityUnknown; }
     461   
     462    bool isRegisteredForAsyncImageDecodingCallback() { return m_bitfields.hasRareData() && rareData().isRegisteredForAsyncImageDecodingCallback(); }
    461463
    462464    bool hasLayer() const { return m_bitfields.hasLayer(); }
     
    570572    void setIsRegisteredForVisibleInViewportCallback(bool);
    571573    void setVisibleInViewportState(VisibleInViewportState);
     574    void setIsRegisteredForAsyncImageDecodingCallback(bool);
    572575
    573576    // Hook so that RenderTextControl can return the line height of its inner renderer.
     
    986989            , m_isRegisteredForVisibleInViewportCallback(false)
    987990            , m_visibleInViewportState(VisibilityUnknown)
     991            , m_isRegisteredForAsyncImageDecodingCallback(false)
    988992        {
    989993        }
     
    9961000        ADD_BOOLEAN_BITFIELD(isRegisteredForVisibleInViewportCallback, IsRegisteredForVisibleInViewportCallback);
    9971001        ADD_ENUM_BITFIELD(visibleInViewportState, VisibleInViewportState, VisibleInViewportState, 2);
     1002        ADD_BOOLEAN_BITFIELD(isRegisteredForAsyncImageDecodingCallback, IsRegisteredForAsyncImageDecodingCallback);
    9981003        std::unique_ptr<RenderStyle> cachedFirstLineStyle;
    9991004    };
  • trunk/Source/WebCore/rendering/RenderReplaced.h

    r208668 r213618  
    3333    LayoutUnit computeReplacedLogicalHeight() const override;
    3434
     35    LayoutSize intrinsicSize() const final { return m_intrinsicSize; }
    3536    LayoutRect replacedContentRect(const LayoutSize& intrinsicSize) const;
    3637
     
    4647    void layout() override;
    4748
    48     LayoutSize intrinsicSize() const final { return m_intrinsicSize; }
    4949    void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const override;
    5050
  • trunk/Source/WebCore/rendering/RenderView.cpp

    r212843 r213618  
    3636#include "HTMLIFrameElement.h"
    3737#include "HitTestResult.h"
     38#include "Image.h"
    3839#include "ImageQualityController.h"
    3940#include "NodeTraversal.h"
    4041#include "Page.h"
     42#include "RenderDescendantIterator.h"
    4143#include "RenderGeometryMap.h"
     44#include "RenderImage.h"
    4245#include "RenderIterator.h"
    4346#include "RenderLayer.h"
     
    14221425}
    14231426
     1427void RenderView::registerForAsyncImageDecodingCallback(RenderElement& renderer)
     1428{
     1429    ASSERT(!m_asyncDecodingImageRenderers.contains(&renderer));
     1430    m_asyncDecodingImageRenderers.add(&renderer);
     1431}
     1432
     1433void RenderView::unregisterForAsyncImageDecodingCallback(RenderElement& renderer)
     1434{
     1435    ASSERT(m_asyncDecodingImageRenderers.contains(&renderer));
     1436    m_asyncDecodingImageRenderers.remove(&renderer);
     1437}
     1438   
     1439void RenderView::requestAsyncDecodingForImagesInAbsoluteRect(const IntRect& rect)
     1440{
     1441    for (auto* renderer : m_asyncDecodingImageRenderers) {
     1442        if (!renderer->intersectsAbsoluteRect(rect))
     1443            continue;
     1444       
     1445        auto& renderImage = downcast<RenderImage>(*renderer);
     1446       
     1447        CachedImage* image = renderImage.cachedImage();
     1448        if (!image || !image->hasImage())
     1449            continue;
     1450
     1451        // Get the destination rectangle of the image scaled by the all the scaling factors
     1452        // that will eventually be applied to the graphics context.
     1453        LayoutRect replacedContentRect = renderImage.replacedContentRect(renderImage.intrinsicSize());
     1454        FloatRect rect = snapRectToDevicePixels(replacedContentRect, document().deviceScaleFactor());
     1455        rect.scale(frame().page()->pageScaleFactor() * frame().pageZoomFactor() * document().deviceScaleFactor());
     1456
     1457        image->image()->requestAsyncDecoding(expandedIntSize(rect.size()));
     1458    }
     1459}
     1460
    14241461RenderView::RepaintRegionAccumulator::RepaintRegionAccumulator(RenderView* view)
    14251462    : m_rootView(view ? view->document().topDocument().renderView() : nullptr)
  • trunk/Source/WebCore/rendering/RenderView.h

    r212843 r213618  
    232232    void addRendererWithPausedImageAnimations(RenderElement&);
    233233    void removeRendererWithPausedImageAnimations(RenderElement&);
     234    void registerForAsyncImageDecodingCallback(RenderElement&);
     235    void unregisterForAsyncImageDecodingCallback(RenderElement&);
     236    void requestAsyncDecodingForImagesInAbsoluteRect(const IntRect&);
    234237
    235238    class RepaintRegionAccumulator {
     
    389392    HashSet<RenderElement*> m_renderersWithPausedImageAnimation;
    390393    HashSet<RenderElement*> m_visibleInViewportRenderers;
     394    HashSet<RenderElement*> m_asyncDecodingImageRenderers;
    391395    Vector<RefPtr<RenderWidget>> m_protectedRenderWidgets;
    392396
  • trunk/Source/WebKit2/ChangeLog

    r213614 r213618  
     12017-03-08  Said Abou-Hallawa  <sabouhallawa@apple.com>
     2
     3        Enable async image decoding for large images
     4        https://bugs.webkit.org/show_bug.cgi?id=165039
     5
     6        Reviewed by Simon Fraser.
     7
     8        Add WK2 preferences for setting/getting LargeImageAsyncDecoding and
     9        AnimatedImageAsyncDecoding.
     10       
     11        * UIProcess/API/C/WKPreferences.cpp:
     12        (WKPreferencesSetLargeImageAsyncDecodingEnabled):
     13        (WKPreferencesGetLargeImageAsyncDecodingEnabled):
     14        (WKPreferencesSetAnimatedImageAsyncDecodingEnabled):
     15        (WKPreferencesGetAnimatedImageAsyncDecodingEnabled):
     16        * UIProcess/API/C/WKPreferencesRefPrivate.h:
     17
    1182017-03-08  Wenson Hsieh  <wenson_hsieh@apple.com>
    219
  • trunk/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp

    r213283 r213618  
    16821682}
    16831683
     1684void WKPreferencesSetLargeImageAsyncDecodingEnabled(WKPreferencesRef preferencesRef, bool flag)
     1685{
     1686    toImpl(preferencesRef)->setLargeImageAsyncDecodingEnabled(flag);
     1687}
     1688
     1689bool WKPreferencesGetLargeImageAsyncDecodingEnabled(WKPreferencesRef preferencesRef)
     1690{
     1691    return toImpl(preferencesRef)->largeImageAsyncDecodingEnabled();
     1692}
     1693
     1694void WKPreferencesSetAnimatedImageAsyncDecodingEnabled(WKPreferencesRef preferencesRef, bool flag)
     1695{
     1696    toImpl(preferencesRef)->setAnimatedImageAsyncDecodingEnabled(flag);
     1697}
     1698
     1699bool WKPreferencesGetAnimatedImageAsyncDecodingEnabled(WKPreferencesRef preferencesRef)
     1700{
     1701    return toImpl(preferencesRef)->animatedImageAsyncDecodingEnabled();
     1702}
     1703
    16841704void WKPreferencesSetShouldSuppressKeyboardInputDuringProvisionalNavigation(WKPreferencesRef preferencesRef, bool flag)
    16851705{
  • trunk/Source/WebKit2/UIProcess/API/C/WKPreferencesRefPrivate.h

    r213283 r213618  
    466466WK_EXPORT bool WKPreferencesGetSubtleCryptoEnabled(WKPreferencesRef);
    467467
     468// Defaults to true.
     469WK_EXPORT void WKPreferencesSetLargeImageAsyncDecodingEnabled(WKPreferencesRef preferencesRef, bool flag);
     470WK_EXPORT bool WKPreferencesGetLargeImageAsyncDecodingEnabled(WKPreferencesRef preferencesRef);
     471
     472// Defaults to true.
     473WK_EXPORT void WKPreferencesSetAnimatedImageAsyncDecodingEnabled(WKPreferencesRef preferencesRef, bool flag);
     474WK_EXPORT bool WKPreferencesGetAnimatedImageAsyncDecodingEnabled(WKPreferencesRef preferencesRef);
     475
    468476// Defaults to false
    469477WK_EXPORT void WKPreferencesSetShouldSuppressKeyboardInputDuringProvisionalNavigation(WKPreferencesRef, bool flag);
  • trunk/Tools/ChangeLog

    r213586 r213618  
     12017-03-08  Said Abou-Hallawa  <sabouhallawa@apple.com>
     2
     3        Enable async image decoding for large images
     4        https://bugs.webkit.org/show_bug.cgi?id=165039
     5
     6        Reviewed by Simon Fraser.
     7
     8        Disable LargeImageAsyncDecoding for DRT/WTR.
     9
     10        * DumpRenderTree/mac/DumpRenderTree.mm:
     11        (resetWebPreferencesToConsistentValues):
     12        * WebKitTestRunner/TestController.cpp:
     13        (WTR::TestController::resetPreferencesToConsistentValues):
     14
    1152017-03-08  Matt Rajca  <mrajca@apple.com>
    216
  • trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm

    r213410 r213618  
    956956   
    957957    [preferences setMediaStreamEnabled:YES];
     958   
     959    [preferences setLargeImageAsyncDecodingEnabled:NO];
    958960
    959961    [WebPreferences _clearNetworkLoaderSession];
  • trunk/Tools/WebKitTestRunner/TestController.cpp

    r213042 r213618  
    719719
    720720    WKPreferencesSetMockCaptureDevicesEnabled(preferences, true);
     721   
     722    WKPreferencesSetLargeImageAsyncDecodingEnabled(preferences, false);
    721723
    722724    platformResetPreferencesToConsistentValues();
Note: See TracChangeset for help on using the changeset viewer.