Title: [207182] trunk/Source/WebCore
Revision
207182
Author
[email protected]
Date
2016-10-11 18:40:14 -0700 (Tue, 11 Oct 2016)

Log 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 <[email protected]> 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.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (207181 => 207182)


--- trunk/Source/WebCore/ChangeLog	2016-10-12 00:25:55 UTC (rev 207181)
+++ trunk/Source/WebCore/ChangeLog	2016-10-12 01:40:14 UTC (rev 207182)
@@ -1,3 +1,48 @@
+2016-10-11  Said Abou-Hallawa  <[email protected]>
+
+        [CG] Add the option to immediately decode an image frame and control its memory caching
+        https://bugs.webkit.org/show_bug.cgi?id=163298
+
+        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.
+
 2016-10-11  Chris Dumez  <[email protected]>
 
         select.options may return too many option elements

Modified: trunk/Source/WebCore/platform/graphics/ImageFrame.h (207181 => 207182)


--- trunk/Source/WebCore/platform/graphics/ImageFrame.h	2016-10-12 00:25:55 UTC (rev 207181)
+++ trunk/Source/WebCore/platform/graphics/ImageFrame.h	2016-10-12 01:40:14 UTC (rev 207182)
@@ -73,6 +73,11 @@
     Ignored
 };
 
+enum class DecodingMode {
+    OnDemand,
+    Immediate
+};
+
 class ImageFrame {
     friend class ImageFrameCache;
 public:

Modified: trunk/Source/WebCore/platform/graphics/ImageFrameCache.cpp (207181 => 207182)


--- trunk/Source/WebCore/platform/graphics/ImageFrameCache.cpp	2016-10-12 00:25:55 UTC (rev 207181)
+++ trunk/Source/WebCore/platform/graphics/ImageFrameCache.cpp	2016-10-12 01:40:14 UTC (rev 207182)
@@ -31,10 +31,6 @@
 
 #if USE(CG)
 #include "ImageDecoderCG.h"
-#elif USE(DIRECT2D)
-#include "GraphicsContext.h"
-#include "ImageDecoderDirect2D.h"
-#include <WinCodec.h>
 #else
 #include "ImageDecoder.h"
 #endif
@@ -378,12 +374,4 @@
     return frameMetadataAtIndex<NativeImagePtr, (&ImageFrame::nativeImage)>(index, subsamplingLevel, ImageFrame::Caching::MetadataAndImage);
 }
 
-#if USE(DIRECT2D)
-void ImageFrameCache::setRenderTarget(GraphicsContext& context)
-{
-    if (m_decoder)
-        m_decoder->setRenderTarget(context.platformContext());
 }
-#endif
-
-}

Modified: trunk/Source/WebCore/platform/graphics/ImageFrameCache.h (207181 => 207182)


--- trunk/Source/WebCore/platform/graphics/ImageFrameCache.h	2016-10-12 00:25:55 UTC (rev 207181)
+++ trunk/Source/WebCore/platform/graphics/ImageFrameCache.h	2016-10-12 01:40:14 UTC (rev 207182)
@@ -82,10 +82,6 @@
     ImageOrientation frameOrientationAtIndex(size_t);
     NativeImagePtr frameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
 
-#if USE(DIRECT2D)
-    void setRenderTarget(GraphicsContext&);
-#endif
-
 private:
     template<typename T, T (ImageDecoder::*functor)() const>
     T metadata(const T& defaultValue, Optional<T>* cachedValue = nullptr);

Modified: trunk/Source/WebCore/platform/graphics/ImageSource.cpp (207181 => 207182)


--- trunk/Source/WebCore/platform/graphics/ImageSource.cpp	2016-10-12 00:25:55 UTC (rev 207181)
+++ trunk/Source/WebCore/platform/graphics/ImageSource.cpp	2016-10-12 01:40:14 UTC (rev 207182)
@@ -32,6 +32,7 @@
 #if USE(CG)
 #include "ImageDecoderCG.h"
 #elif USE(DIRECT2D)
+#include "GraphicsContext.h"
 #include "ImageDecoderDirect2D.h"
 #include <WinCodec.h>
 #else
@@ -114,6 +115,16 @@
     return true;
 }
 
+#if USE(DIRECT2D)
+void ImageSource::setRenderTarget(GraphicsContext& context)
+{
+    if (!isDecoderAvailable())
+        return;
+
+    m_decoder->setRenderTarget(context.platformContext());
+}
+#endif
+
 void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
 {
     if (!data || !ensureDecoderAvailable(data))

Modified: trunk/Source/WebCore/platform/graphics/ImageSource.h (207181 => 207182)


--- trunk/Source/WebCore/platform/graphics/ImageSource.h	2016-10-12 00:25:55 UTC (rev 207181)
+++ trunk/Source/WebCore/platform/graphics/ImageSource.h	2016-10-12 01:40:14 UTC (rev 207182)
@@ -59,6 +59,10 @@
     bool ensureDecoderAvailable(SharedBuffer*);
     bool isDecoderAvailable() const { return m_decoder.get(); }
 
+#if USE(DIRECT2D)
+    void setRenderTarget(GraphicsContext&);
+#endif
+
     void setData(SharedBuffer* data, bool allDataReceived);
     bool dataChanged(SharedBuffer* data, bool allDataReceived);
 
@@ -96,10 +100,6 @@
     void setAllowSubsampling(bool allowSubsampling) { m_allowSubsampling = allowSubsampling; }
     NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
 
-#if USE(DIRECT2D)
-    void setRenderTarget(GraphicsContext& context) { m_frameCache.setRenderTarget(context); }
-#endif
-
 private:
     void clearFrameBufferCache(size_t);
     void clear(bool destroyAll, size_t count, SharedBuffer* data);

Modified: trunk/Source/WebCore/platform/graphics/cg/ImageDecoderCG.cpp (207181 => 207182)


--- trunk/Source/WebCore/platform/graphics/cg/ImageDecoderCG.cpp	2016-10-12 00:25:55 UTC (rev 207181)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageDecoderCG.cpp	2016-10-12 01:40:14 UTC (rev 207182)
@@ -57,32 +57,39 @@
 const CFStringRef kCGImageSourceShouldPreferRGB32 = CFSTR("kCGImageSourceShouldPreferRGB32");
 const CFStringRef kCGImageSourceSkipMetadata = CFSTR("kCGImageSourceSkipMetadata");
 
-static RetainPtr<CFDictionaryRef> createImageSourceOptions(SubsamplingLevel subsamplingLevel)
+static RetainPtr<CFDictionaryRef> createImageSourceOptions(SubsamplingLevel subsamplingLevel, DecodingMode decodingMode)
 {
-    if (subsamplingLevel == SubsamplingLevel::First) {
-        const unsigned numOptions = 3;
-        const void* keys[numOptions] = { kCGImageSourceShouldCache, kCGImageSourceShouldPreferRGB32, kCGImageSourceSkipMetadata };
-        const void* values[numOptions] = { kCFBooleanTrue, kCFBooleanTrue, kCFBooleanTrue };
-        return CFDictionaryCreate(nullptr, keys, values, numOptions, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+    RetainPtr<CFMutableDictionaryRef> options = adoptCF(CFDictionaryCreateMutable(nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+
+    CFDictionarySetValue(options.get(), kCGImageSourceShouldCache, kCFBooleanTrue);
+    CFDictionarySetValue(options.get(), kCGImageSourceShouldPreferRGB32, kCFBooleanTrue);
+    CFDictionarySetValue(options.get(), kCGImageSourceSkipMetadata, kCFBooleanTrue);
+
+    if (subsamplingLevel > SubsamplingLevel::First) {
+        RetainPtr<CFNumberRef> subsampleNumber;
+        subsamplingLevel = std::min(SubsamplingLevel::Last, std::max(SubsamplingLevel::First, subsamplingLevel));
+        int subsampleInt = 1 << static_cast<int>(subsamplingLevel); // [0..3] => [1, 2, 4, 8]
+        subsampleNumber = adoptCF(CFNumberCreate(nullptr,  kCFNumberIntType,  &subsampleInt));
+        CFDictionarySetValue(options.get(), kCGImageSourceSubsampleFactor, subsampleNumber.get());
     }
-    
-    subsamplingLevel = std::min(SubsamplingLevel::Last, std::max(SubsamplingLevel::First, subsamplingLevel));
-    int subsampleInt = 1 << static_cast<int>(subsamplingLevel); // [0..3] => [1, 2, 4, 8]
-    
-    RetainPtr<CFNumberRef> subsampleNumber = adoptCF(CFNumberCreate(nullptr,  kCFNumberIntType,  &subsampleInt));
-    const CFIndex numOptions = 4;
-    const void* keys[numOptions] = { kCGImageSourceShouldCache, kCGImageSourceShouldPreferRGB32, kCGImageSourceSkipMetadata, kCGImageSourceSubsampleFactor };
-    const void* values[numOptions] = { kCFBooleanTrue, kCFBooleanTrue, kCFBooleanTrue, subsampleNumber.get() };
-    return adoptCF(CFDictionaryCreate(nullptr, keys, values, numOptions, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+
+    if (decodingMode == DecodingMode::Immediate) {
+        CFDictionarySetValue(options.get(), kCGImageSourceShouldCacheImmediately, kCFBooleanTrue);
+        CFDictionarySetValue(options.get(), kCGImageSourceCreateThumbnailFromImageAlways, kCFBooleanTrue);
+    }
+
+    return options;
 }
 
-static RetainPtr<CFDictionaryRef> imageSourceOptions(SubsamplingLevel subsamplingLevel = SubsamplingLevel::Default)
+static RetainPtr<CFDictionaryRef> imageSourceOptions(SubsamplingLevel subsamplingLevel = SubsamplingLevel::Default, DecodingMode decodingMode = DecodingMode::OnDemand)
 {
     if (subsamplingLevel > SubsamplingLevel::First)
-        return createImageSourceOptions(subsamplingLevel);
-    
-    static NeverDestroyed<RetainPtr<CFDictionaryRef>> options = createImageSourceOptions(SubsamplingLevel::First);
-    return options;
+        return createImageSourceOptions(subsamplingLevel, decodingMode);
+
+    static NeverDestroyed<RetainPtr<CFDictionaryRef>> optionsOnDemand = createImageSourceOptions(SubsamplingLevel::First, DecodingMode::OnDemand);
+    static NeverDestroyed<RetainPtr<CFDictionaryRef>> optionsImmediate = createImageSourceOptions(SubsamplingLevel::First, DecodingMode::Immediate);
+
+    return decodingMode == DecodingMode::OnDemand ? optionsOnDemand : optionsImmediate;
 }
 
 static ImageOrientation orientationFromProperties(CFDictionaryRef imageProperties)
@@ -331,11 +338,17 @@
     return frameSize.area() * 4;
 }
 
-NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
+NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, DecodingMode decodingMode) const
 {
     LOG(Images, "ImageDecoder %p createFrameImageAtIndex %lu", this, index);
 
-    RetainPtr<CGImageRef> image = adoptCF(CGImageSourceCreateImageAtIndex(m_nativeDecoder.get(), index, imageSourceOptions(subsamplingLevel).get()));
+    const auto* options = imageSourceOptions(subsamplingLevel, decodingMode).get();
+    RetainPtr<CGImageRef> image;
+
+    if (decodingMode == DecodingMode::OnDemand)
+        image = adoptCF(CGImageSourceCreateImageAtIndex(m_nativeDecoder.get(), index, options));
+    else
+        image = adoptCF(CGImageSourceCreateThumbnailAtIndex(m_nativeDecoder.get(), index, options));
     
 #if PLATFORM(IOS)
     // <rdar://problem/7371198> - CoreGraphics changed the default caching behaviour in iOS 4.0 to kCGImageCachingTransient

Modified: trunk/Source/WebCore/platform/graphics/cg/ImageDecoderCG.h (207181 => 207182)


--- trunk/Source/WebCore/platform/graphics/cg/ImageDecoderCG.h	2016-10-12 00:25:55 UTC (rev 207181)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageDecoderCG.h	2016-10-12 01:40:14 UTC (rev 207182)
@@ -62,7 +62,7 @@
     bool frameAllowSubsamplingAtIndex(size_t) const;
     unsigned frameBytesAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default) const;
     
-    NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default) const;
+    NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default, DecodingMode = DecodingMode::OnDemand) const;
     
     void setData(SharedBuffer&, bool allDataReceived);
     bool isAllDataReceived() const { return m_isAllDataReceived; }

Modified: trunk/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.cpp (207181 => 207182)


--- trunk/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.cpp	2016-10-12 00:25:55 UTC (rev 207181)
+++ trunk/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.cpp	2016-10-12 01:40:14 UTC (rev 207182)
@@ -192,7 +192,7 @@
     m_renderTarget = renderTarget;
 }
 
-NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
+NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, DecodingMode) const
 {
     if (!m_nativeDecoder)
         return nullptr;

Modified: trunk/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.h (207181 => 207182)


--- trunk/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.h	2016-10-12 00:25:55 UTC (rev 207181)
+++ trunk/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.h	2016-10-12 01:40:14 UTC (rev 207182)
@@ -67,7 +67,7 @@
     bool frameAllowSubsamplingAtIndex(size_t) const;
     unsigned frameBytesAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default) const;
     
-    NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default) const;
+    NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default, DecodingMode = DecodingMode::OnDemand) const;
     
     void setData(SharedBuffer&, bool allDataReceived);
     bool isAllDataReceived() const { return m_isAllDataReceived; }

Modified: trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp (207181 => 207182)


--- trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp	2016-10-12 00:25:55 UTC (rev 207181)
+++ trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp	2016-10-12 01:40:14 UTC (rev 207182)
@@ -207,7 +207,7 @@
     return duration;
 }
 
-NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel)
+NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel, DecodingMode)
 {
     // Zero-height images can cause problems for some ports. If we have an empty image dimension, just bail.
     if (size().isEmpty())

Modified: trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h (207181 => 207182)


--- trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h	2016-10-12 00:25:55 UTC (rev 207181)
+++ trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h	2016-10-12 01:40:14 UTC (rev 207182)
@@ -137,7 +137,7 @@
         
         float frameDurationAtIndex(size_t);
         
-        NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel);
+        NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default, DecodingMode = DecodingMode::OnDemand);
 
         void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; }
         bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to