Changeset 207182 in webkit


Ignore:
Timestamp:
Oct 11, 2016 6:40:14 PM (7 years ago)
Author:
commit-queue@webkit.org
Message:

[CG] Add the option to immediately decode an image frame and control its memory caching
https://bugs.webkit.org/show_bug.cgi?id=163298

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

This patch fixes two things. (1) An option is added to immediately decode an
image frame. This can be done by adding kCGImageSourceShouldCacheImmediately
to the ImageSource options dictionary. (2) BitmapImage should also control
when the image frame is actually deleted from memory. This can be done by
calling CGImageSourceCreateThumbnailAtIndex(). CG does not keep a reference
to the returned CGImageRef.

  • platform/graphics/ImageFrame.h: Adding the DecodingMode enum class.

Ideally this should be a member of ImageDecoder class. But since we
have three header files for ImageDecoder, this can be added here till
the three files combined in one header file.

  • platform/graphics/ImageFrameCache.cpp:

(WebCore::ImageFrameCache::setRenderTarget): Deleted.

  • platform/graphics/ImageFrameCache.h:
  • platform/graphics/ImageSource.cpp:

(WebCore::ImageSource::setRenderTarget):

  • platform/graphics/ImageSource.h:

(WebCore::ImageSource::setRenderTarget): Deleted.
Unrelated change. The native image decoder is available from the ImageSource.
ImageSource::setTarget() does not need not to get it through ImageFrameCache.

  • platform/graphics/cg/ImageDecoderCG.cpp:

(WebCore::createImageSourceOptions): Clean this function by using CFMutableDictionary.
(WebCore::imageSourceOptions): Cache two default ImageSource options and create new
ones for the non default cases.

(WebCore::ImageDecoder::createFrameImageAtIndex): Use the appropriate ImageSource function

  • platform/graphics/cg/ImageDecoderCG.h:
  • platform/graphics/win/ImageDecoderDirect2D.cpp:

(WebCore::ImageDecoder::createFrameImageAtIndex):

  • platform/graphics/win/ImageDecoderDirect2D.h:
  • platform/image-decoders/ImageDecoder.cpp:

(WebCore::ImageDecoder::createFrameImageAtIndex):

  • platform/image-decoders/ImageDecoder.h: Change functions' signature to include a DecodingMode argument.
Location:
trunk/Source/WebCore
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r207181 r207182  
     12016-10-11  Said Abou-Hallawa  <sabouhallawa@apple.com>
     2
     3        [CG] Add the option to immediately decode an image frame and control its memory caching
     4        https://bugs.webkit.org/show_bug.cgi?id=163298
     5
     6        Reviewed by Simon Fraser.
     7
     8        This patch fixes two things. (1) An option is added to immediately decode an
     9        image frame. This can be done by adding kCGImageSourceShouldCacheImmediately
     10        to the ImageSource options dictionary. (2) BitmapImage should also control
     11        when the image frame is actually deleted from memory. This can be done by
     12        calling CGImageSourceCreateThumbnailAtIndex(). CG does not keep a reference
     13        to the returned CGImageRef.
     14
     15        * platform/graphics/ImageFrame.h: Adding the DecodingMode enum class.
     16        Ideally this should be a member of ImageDecoder class. But since we
     17        have three header files for ImageDecoder, this can be added here till
     18        the three files combined in one header file.
     19
     20        * platform/graphics/ImageFrameCache.cpp:
     21        (WebCore::ImageFrameCache::setRenderTarget): Deleted.
     22        * platform/graphics/ImageFrameCache.h:
     23        * platform/graphics/ImageSource.cpp:
     24        (WebCore::ImageSource::setRenderTarget):
     25        * platform/graphics/ImageSource.h:
     26        (WebCore::ImageSource::setRenderTarget): Deleted.
     27        Unrelated change. The native image decoder is available from the ImageSource.
     28        ImageSource::setTarget() does not need not to get it through ImageFrameCache.
     29       
     30        * platform/graphics/cg/ImageDecoderCG.cpp:
     31        (WebCore::createImageSourceOptions): Clean this function by using CFMutableDictionary.
     32        (WebCore::imageSourceOptions): Cache two default ImageSource options and create new
     33        ones for the non default cases.
     34
     35        (WebCore::ImageDecoder::createFrameImageAtIndex): Use the appropriate ImageSource function
     36
     37        * platform/graphics/cg/ImageDecoderCG.h:
     38        * platform/graphics/win/ImageDecoderDirect2D.cpp:
     39        (WebCore::ImageDecoder::createFrameImageAtIndex):
     40        * platform/graphics/win/ImageDecoderDirect2D.h:
     41        * platform/image-decoders/ImageDecoder.cpp:
     42        (WebCore::ImageDecoder::createFrameImageAtIndex):
     43        * platform/image-decoders/ImageDecoder.h:
     44         Change functions' signature to include a DecodingMode argument.
     45
    1462016-10-11  Chris Dumez  <cdumez@apple.com>
    247
  • trunk/Source/WebCore/platform/graphics/ImageFrame.h

    r206481 r207182  
    7272    Applied,
    7373    Ignored
     74};
     75
     76enum class DecodingMode {
     77    OnDemand,
     78    Immediate
    7479};
    7580
  • trunk/Source/WebCore/platform/graphics/ImageFrameCache.cpp

    r206742 r207182  
    3232#if USE(CG)
    3333#include "ImageDecoderCG.h"
    34 #elif USE(DIRECT2D)
    35 #include "GraphicsContext.h"
    36 #include "ImageDecoderDirect2D.h"
    37 #include <WinCodec.h>
    3834#else
    3935#include "ImageDecoder.h"
     
    379375}
    380376
    381 #if USE(DIRECT2D)
    382 void ImageFrameCache::setRenderTarget(GraphicsContext& context)
    383 {
    384     if (m_decoder)
    385         m_decoder->setRenderTarget(context.platformContext());
    386 }
    387 #endif
    388 
    389 }
     377}
  • trunk/Source/WebCore/platform/graphics/ImageFrameCache.h

    r206742 r207182  
    8383    NativeImagePtr frameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
    8484
    85 #if USE(DIRECT2D)
    86     void setRenderTarget(GraphicsContext&);
    87 #endif
    88 
    8985private:
    9086    template<typename T, T (ImageDecoder::*functor)() const>
  • trunk/Source/WebCore/platform/graphics/ImageSource.cpp

    r206742 r207182  
    3333#include "ImageDecoderCG.h"
    3434#elif USE(DIRECT2D)
     35#include "GraphicsContext.h"
    3536#include "ImageDecoderDirect2D.h"
    3637#include <WinCodec.h>
     
    114115    return true;
    115116}
     117
     118#if USE(DIRECT2D)
     119void ImageSource::setRenderTarget(GraphicsContext& context)
     120{
     121    if (!isDecoderAvailable())
     122        return;
     123
     124    m_decoder->setRenderTarget(context.platformContext());
     125}
     126#endif
    116127
    117128void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
  • trunk/Source/WebCore/platform/graphics/ImageSource.h

    r206742 r207182  
    6060    bool isDecoderAvailable() const { return m_decoder.get(); }
    6161
     62#if USE(DIRECT2D)
     63    void setRenderTarget(GraphicsContext&);
     64#endif
     65
    6266    void setData(SharedBuffer* data, bool allDataReceived);
    6367    bool dataChanged(SharedBuffer* data, bool allDataReceived);
     
    97101    NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
    98102
    99 #if USE(DIRECT2D)
    100     void setRenderTarget(GraphicsContext& context) { m_frameCache.setRenderTarget(context); }
    101 #endif
    102 
    103103private:
    104104    void clearFrameBufferCache(size_t);
  • trunk/Source/WebCore/platform/graphics/cg/ImageDecoderCG.cpp

    r206481 r207182  
    5858const CFStringRef kCGImageSourceSkipMetadata = CFSTR("kCGImageSourceSkipMetadata");
    5959
    60 static RetainPtr<CFDictionaryRef> createImageSourceOptions(SubsamplingLevel subsamplingLevel)
    61 {
    62     if (subsamplingLevel == SubsamplingLevel::First) {
    63         const unsigned numOptions = 3;
    64         const void* keys[numOptions] = { kCGImageSourceShouldCache, kCGImageSourceShouldPreferRGB32, kCGImageSourceSkipMetadata };
    65         const void* values[numOptions] = { kCFBooleanTrue, kCFBooleanTrue, kCFBooleanTrue };
    66         return CFDictionaryCreate(nullptr, keys, values, numOptions, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    67     }
    68    
    69     subsamplingLevel = std::min(SubsamplingLevel::Last, std::max(SubsamplingLevel::First, subsamplingLevel));
    70     int subsampleInt = 1 << static_cast<int>(subsamplingLevel); // [0..3] => [1, 2, 4, 8]
    71    
    72     RetainPtr<CFNumberRef> subsampleNumber = adoptCF(CFNumberCreate(nullptr,  kCFNumberIntType,  &subsampleInt));
    73     const CFIndex numOptions = 4;
    74     const void* keys[numOptions] = { kCGImageSourceShouldCache, kCGImageSourceShouldPreferRGB32, kCGImageSourceSkipMetadata, kCGImageSourceSubsampleFactor };
    75     const void* values[numOptions] = { kCFBooleanTrue, kCFBooleanTrue, kCFBooleanTrue, subsampleNumber.get() };
    76     return adoptCF(CFDictionaryCreate(nullptr, keys, values, numOptions, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
    77 }
    78 
    79 static RetainPtr<CFDictionaryRef> imageSourceOptions(SubsamplingLevel subsamplingLevel = SubsamplingLevel::Default)
     60static RetainPtr<CFDictionaryRef> createImageSourceOptions(SubsamplingLevel subsamplingLevel, DecodingMode decodingMode)
     61{
     62    RetainPtr<CFMutableDictionaryRef> options = adoptCF(CFDictionaryCreateMutable(nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
     63
     64    CFDictionarySetValue(options.get(), kCGImageSourceShouldCache, kCFBooleanTrue);
     65    CFDictionarySetValue(options.get(), kCGImageSourceShouldPreferRGB32, kCFBooleanTrue);
     66    CFDictionarySetValue(options.get(), kCGImageSourceSkipMetadata, kCFBooleanTrue);
     67
     68    if (subsamplingLevel > SubsamplingLevel::First) {
     69        RetainPtr<CFNumberRef> subsampleNumber;
     70        subsamplingLevel = std::min(SubsamplingLevel::Last, std::max(SubsamplingLevel::First, subsamplingLevel));
     71        int subsampleInt = 1 << static_cast<int>(subsamplingLevel); // [0..3] => [1, 2, 4, 8]
     72        subsampleNumber = adoptCF(CFNumberCreate(nullptr,  kCFNumberIntType,  &subsampleInt));
     73        CFDictionarySetValue(options.get(), kCGImageSourceSubsampleFactor, subsampleNumber.get());
     74    }
     75
     76    if (decodingMode == DecodingMode::Immediate) {
     77        CFDictionarySetValue(options.get(), kCGImageSourceShouldCacheImmediately, kCFBooleanTrue);
     78        CFDictionarySetValue(options.get(), kCGImageSourceCreateThumbnailFromImageAlways, kCFBooleanTrue);
     79    }
     80
     81    return options;
     82}
     83
     84static RetainPtr<CFDictionaryRef> imageSourceOptions(SubsamplingLevel subsamplingLevel = SubsamplingLevel::Default, DecodingMode decodingMode = DecodingMode::OnDemand)
    8085{
    8186    if (subsamplingLevel > SubsamplingLevel::First)
    82         return createImageSourceOptions(subsamplingLevel);
    83    
    84     static NeverDestroyed<RetainPtr<CFDictionaryRef>> options = createImageSourceOptions(SubsamplingLevel::First);
    85     return options;
     87        return createImageSourceOptions(subsamplingLevel, decodingMode);
     88
     89    static NeverDestroyed<RetainPtr<CFDictionaryRef>> optionsOnDemand = createImageSourceOptions(SubsamplingLevel::First, DecodingMode::OnDemand);
     90    static NeverDestroyed<RetainPtr<CFDictionaryRef>> optionsImmediate = createImageSourceOptions(SubsamplingLevel::First, DecodingMode::Immediate);
     91
     92    return decodingMode == DecodingMode::OnDemand ? optionsOnDemand : optionsImmediate;
    8693}
    8794
     
    332339}
    333340
    334 NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
     341NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, DecodingMode decodingMode) const
    335342{
    336343    LOG(Images, "ImageDecoder %p createFrameImageAtIndex %lu", this, index);
    337344
    338     RetainPtr<CGImageRef> image = adoptCF(CGImageSourceCreateImageAtIndex(m_nativeDecoder.get(), index, imageSourceOptions(subsamplingLevel).get()));
     345    const auto* options = imageSourceOptions(subsamplingLevel, decodingMode).get();
     346    RetainPtr<CGImageRef> image;
     347
     348    if (decodingMode == DecodingMode::OnDemand)
     349        image = adoptCF(CGImageSourceCreateImageAtIndex(m_nativeDecoder.get(), index, options));
     350    else
     351        image = adoptCF(CGImageSourceCreateThumbnailAtIndex(m_nativeDecoder.get(), index, options));
    339352   
    340353#if PLATFORM(IOS)
  • trunk/Source/WebCore/platform/graphics/cg/ImageDecoderCG.h

    r206481 r207182  
    6363    unsigned frameBytesAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default) const;
    6464   
    65     NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default) const;
     65    NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default, DecodingMode = DecodingMode::OnDemand) const;
    6666   
    6767    void setData(SharedBuffer&, bool allDataReceived);
  • trunk/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.cpp

    r206742 r207182  
    193193}
    194194
    195 NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
     195NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, DecodingMode) const
    196196{
    197197    if (!m_nativeDecoder)
  • trunk/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.h

    r206742 r207182  
    6868    unsigned frameBytesAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default) const;
    6969   
    70     NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default) const;
     70    NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default, DecodingMode = DecodingMode::OnDemand) const;
    7171   
    7272    void setData(SharedBuffer&, bool allDataReceived);
  • trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp

    r206481 r207182  
    208208}
    209209
    210 NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel)
     210NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel, DecodingMode)
    211211{
    212212    // Zero-height images can cause problems for some ports. If we have an empty image dimension, just bail.
  • trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h

    r206481 r207182  
    138138        float frameDurationAtIndex(size_t);
    139139       
    140         NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel);
     140        NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default, DecodingMode = DecodingMode::OnDemand);
    141141
    142142        void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; }
Note: See TracChangeset for help on using the changeset viewer.