Diff
Modified: trunk/Source/WebCore/ChangeLog (225427 => 225428)
--- trunk/Source/WebCore/ChangeLog 2017-12-02 00:00:40 UTC (rev 225427)
+++ trunk/Source/WebCore/ChangeLog 2017-12-02 00:01:54 UTC (rev 225428)
@@ -1,3 +1,100 @@
+2017-12-01 Said Abou-Hallawa <[email protected]>
+
+ Rename ImageFrameCache to ImageSource
+ https://bugs.webkit.org/show_bug.cgi?id=180172
+
+ Reviewed by Per Arne Vollan.
+
+ This is a follow-up for r225300. ImageSource is the intended name after
+ merging ImageFrameCache and ImageSource.
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * platform/graphics/BitmapImage.cpp:
+ (WebCore::BitmapImage::BitmapImage):
+ * platform/graphics/BitmapImage.h:
+ * platform/graphics/ImageFrame.h:
+ * platform/graphics/ImageFrameCache.cpp: Removed.
+ * platform/graphics/ImageFrameCache.h: Removed.
+ * platform/graphics/ImageSource.cpp: Added.
+ (WebCore::ImageSource::ImageSource):
+ (WebCore::ImageSource::~ImageSource):
+ (WebCore::ImageSource::ensureDecoderAvailable):
+ (WebCore::ImageSource::setData):
+ (WebCore::ImageSource::resetData):
+ (WebCore::ImageSource::dataChanged):
+ (WebCore::ImageSource::isAllDataReceived):
+ (WebCore::ImageSource::destroyDecodedData):
+ (WebCore::ImageSource::destroyIncompleteDecodedData):
+ (WebCore::ImageSource::clearFrameBufferCache):
+ (WebCore::ImageSource::decodedSizeChanged):
+ (WebCore::ImageSource::decodedSizeIncreased):
+ (WebCore::ImageSource::decodedSizeDecreased):
+ (WebCore::ImageSource::decodedSizeReset):
+ (WebCore::ImageSource::didDecodeProperties):
+ (WebCore::ImageSource::growFrames):
+ (WebCore::ImageSource::setNativeImage):
+ (WebCore::ImageSource::cacheMetadataAtIndex):
+ (WebCore::ImageSource::cacheNativeImageAtIndex):
+ (WebCore::ImageSource::cacheNativeImageAtIndexAsync):
+ (WebCore::ImageSource::decodingQueue):
+ (WebCore::ImageSource::frameRequestQueue):
+ (WebCore::ImageSource::canUseAsyncDecoding):
+ (WebCore::ImageSource::startAsyncDecodingQueue):
+ (WebCore::ImageSource::requestFrameAsyncDecodingAtIndex):
+ (WebCore::ImageSource::isAsyncDecodingQueueIdle const):
+ (WebCore::ImageSource::stopAsyncDecodingQueue):
+ (WebCore::ImageSource::frameAtIndexCacheIfNeeded):
+ (WebCore::ImageSource::clearMetadata):
+ (WebCore::ImageSource::sourceURL const):
+ (WebCore::ImageSource::mimeType const):
+ (WebCore::ImageSource::expectedContentLength const):
+ (WebCore::ImageSource::metadata):
+ (WebCore::ImageSource::frameMetadataAtIndex):
+ (WebCore::ImageSource::frameMetadataAtIndexCacheIfNeeded):
+ (WebCore::ImageSource::encodedDataStatus):
+ (WebCore::ImageSource::frameCount):
+ (WebCore::ImageSource::repetitionCount):
+ (WebCore::ImageSource::uti):
+ (WebCore::ImageSource::filenameExtension):
+ (WebCore::ImageSource::hotSpot):
+ (WebCore::ImageSource::size):
+ (WebCore::ImageSource::sizeRespectingOrientation):
+ (WebCore::ImageSource::singlePixelSolidColor):
+ (WebCore::ImageSource::maximumSubsamplingLevel):
+ (WebCore::ImageSource::frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex):
+ (WebCore::ImageSource::frameDecodingStatusAtIndex):
+ (WebCore::ImageSource::frameHasAlphaAtIndex):
+ (WebCore::ImageSource::frameHasFullSizeNativeImageAtIndex):
+ (WebCore::ImageSource::frameHasDecodedNativeImageCompatibleWithOptionsAtIndex):
+ (WebCore::ImageSource::frameSubsamplingLevelAtIndex):
+ (WebCore::ImageSource::frameSizeAtIndex):
+ (WebCore::ImageSource::frameBytesAtIndex):
+ (WebCore::ImageSource::frameDurationAtIndex):
+ (WebCore::ImageSource::frameOrientationAtIndex):
+ (WebCore::ImageSource::setTargetContext):
+ (WebCore::ImageSource::createFrameImageAtIndex):
+ (WebCore::ImageSource::frameImageAtIndex):
+ (WebCore::ImageSource::frameImageAtIndexCacheIfNeeded):
+ (WebCore::ImageSource::dump):
+ * platform/graphics/ImageSource.h: Added.
+ (WebCore::ImageSource::create):
+ (WebCore::ImageSource::decodedSize const):
+ (WebCore::ImageSource::destroyAllDecodedData):
+ (WebCore::ImageSource::destroyAllDecodedDataExcludeFrame):
+ (WebCore::ImageSource::destroyDecodedDataBeforeFrame):
+ (WebCore::ImageSource::clearImage):
+ (WebCore::ImageSource::requestFrameAsyncDecodingAtIndex):
+ (WebCore::ImageSource::hasAsyncDecodingQueue const):
+ (WebCore::ImageSource::isSizeAvailable):
+ (WebCore::ImageSource::isDecoderAvailable const):
+ (WebCore::ImageSource::frameAtIndexCacheIfNeeded):
+ (WebCore::ImageSource::ImageFrameRequest::operator== const):
+ * platform/graphics/cairo/GraphicsContext3DCairo.cpp:
+ (WebCore::GraphicsContext3D::ImageExtractor::extractImage):
+ * platform/graphics/cg/GraphicsContext3DCG.cpp:
+ (WebCore::GraphicsContext3D::ImageExtractor::extractImage):
+
2017-12-01 Youenn Fablet <[email protected]>
Implement https://w3c.github.io/ServiceWorker/#clients-get
Modified: trunk/Source/WebCore/Sources.txt (225427 => 225428)
--- trunk/Source/WebCore/Sources.txt 2017-12-02 00:00:40 UTC (rev 225427)
+++ trunk/Source/WebCore/Sources.txt 2017-12-02 00:01:54 UTC (rev 225428)
@@ -1524,8 +1524,8 @@
platform/graphics/ImageBuffer.cpp
platform/graphics/ImageDecoder.cpp
platform/graphics/ImageFrame.cpp
-platform/graphics/ImageFrameCache.cpp
platform/graphics/ImageOrientation.cpp
+platform/graphics/ImageSource.cpp
platform/graphics/IntPoint.cpp
platform/graphics/IntRect.cpp
platform/graphics/IntSize.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (225427 => 225428)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-12-02 00:00:40 UTC (rev 225427)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-12-02 00:01:54 UTC (rev 225428)
@@ -1606,11 +1606,11 @@
53ED3FDE167A88E7006762E6 /* JSInternalSettingsGenerated.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53ED3FDC167A88E7006762E6 /* JSInternalSettingsGenerated.cpp */; };
53ED3FDF167A88E7006762E6 /* JSInternalSettingsGenerated.h in Headers */ = {isa = PBXBuildFile; fileRef = 53ED3FDD167A88E7006762E6 /* JSInternalSettingsGenerated.h */; };
550A0BCA085F6039007353D6 /* QualifiedName.h in Headers */ = {isa = PBXBuildFile; fileRef = 550A0BC8085F6039007353D6 /* QualifiedName.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 5546757B1FD212A9003B10B0 /* ImageSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 554675781FD1FC1A003B10B0 /* ImageSource.h */; settings = {ATTRIBUTES = (Private, ); }; };
5550CB421E955E3C00111AA0 /* ImageTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 5550CB411E955E3C00111AA0 /* ImageTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
555130011E7CCCCB00A69E38 /* DecodingOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 555130001E7CCCCA00A69E38 /* DecodingOptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
555B87ED1CAAF0AB00349425 /* ImageDecoderCG.h in Headers */ = {isa = PBXBuildFile; fileRef = 555B87EB1CAAF0AB00349425 /* ImageDecoderCG.h */; };
5576A5651D88A70800CCC04C /* ImageFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 5576A5631D88A70800CCC04C /* ImageFrame.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 5597F8271D91C3130066BC21 /* ImageFrameCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 5597F8251D91C3130066BC21 /* ImageFrameCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
55A336F71D8209F40022C4C7 /* NativeImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 55A336F61D8209F40022C4C7 /* NativeImage.h */; };
55A336F91D821E3C0022C4C7 /* ImageBackingStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 55A336F81D821E3C0022C4C7 /* ImageBackingStore.h */; settings = {ATTRIBUTES = (Private, ); }; };
55AF14E61EAAC59B0026EEAA /* UTIRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 55AF14E41EAAC59B0026EEAA /* UTIRegistry.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -8051,6 +8051,8 @@
53ED3FDD167A88E7006762E6 /* JSInternalSettingsGenerated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSInternalSettingsGenerated.h; sourceTree = "<group>"; };
550A0BC7085F6039007353D6 /* QualifiedName.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = QualifiedName.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
550A0BC8085F6039007353D6 /* QualifiedName.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = QualifiedName.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
+ 554675771FD1FC1A003B10B0 /* ImageSource.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ImageSource.cpp; sourceTree = "<group>"; };
+ 554675781FD1FC1A003B10B0 /* ImageSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ImageSource.h; sourceTree = "<group>"; };
5550CB411E955E3C00111AA0 /* ImageTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageTypes.h; sourceTree = "<group>"; };
555130001E7CCCCA00A69E38 /* DecodingOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DecodingOptions.h; sourceTree = "<group>"; };
555B87EA1CAAF0AB00349425 /* ImageDecoderCG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageDecoderCG.cpp; sourceTree = "<group>"; };
@@ -8057,8 +8059,6 @@
555B87EB1CAAF0AB00349425 /* ImageDecoderCG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageDecoderCG.h; sourceTree = "<group>"; };
5576A5621D88A70800CCC04C /* ImageFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFrame.cpp; sourceTree = "<group>"; };
5576A5631D88A70800CCC04C /* ImageFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFrame.h; sourceTree = "<group>"; };
- 5597F8241D91C3130066BC21 /* ImageFrameCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFrameCache.cpp; sourceTree = "<group>"; };
- 5597F8251D91C3130066BC21 /* ImageFrameCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFrameCache.h; sourceTree = "<group>"; };
55A336F61D8209F40022C4C7 /* NativeImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeImage.h; sourceTree = "<group>"; };
55A336F81D821E3C0022C4C7 /* ImageBackingStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageBackingStore.h; sourceTree = "<group>"; };
55AF14E31EAAC59B0026EEAA /* UTIRegistry.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = UTIRegistry.cpp; sourceTree = "<group>"; };
@@ -22711,12 +22711,12 @@
CD19FEA61F573972000C42FB /* ImageDecoder.h */,
5576A5621D88A70800CCC04C /* ImageFrame.cpp */,
5576A5631D88A70800CCC04C /* ImageFrame.h */,
- 5597F8241D91C3130066BC21 /* ImageFrameCache.cpp */,
- 5597F8251D91C3130066BC21 /* ImageFrameCache.h */,
BC7F44A70B9E324E00A9D081 /* ImageObserver.h */,
A8748D7412CC3F89001FBA41 /* ImageOrientation.cpp */,
A8748D6612CC3763001FBA41 /* ImageOrientation.h */,
49291E4A134172C800E753DE /* ImageRenderingMode.h */,
+ 554675771FD1FC1A003B10B0 /* ImageSource.cpp */,
+ 554675781FD1FC1A003B10B0 /* ImageSource.h */,
5550CB411E955E3C00111AA0 /* ImageTypes.h */,
07941793166EA04E009416C2 /* InbandTextTrackPrivate.h */,
07CE77D416712A6A00C55A47 /* InbandTextTrackPrivateClient.h */,
@@ -27190,7 +27190,6 @@
555B87ED1CAAF0AB00349425 /* ImageDecoderCG.h in Headers */,
97205AB61239291000B17380 /* ImageDocument.h in Headers */,
5576A5651D88A70800CCC04C /* ImageFrame.h in Headers */,
- 5597F8271D91C3130066BC21 /* ImageFrameCache.h in Headers */,
F55B3DC21251F12D003EF269 /* ImageInputType.h in Headers */,
089582560E857A7E00F82C83 /* ImageLoader.h in Headers */,
BC7F44A80B9E324E00A9D081 /* ImageObserver.h in Headers */,
@@ -27198,6 +27197,7 @@
B51A2F3F17D7D3AE0072517A /* ImageQualityController.h in Headers */,
49291E4B134172C800E753DE /* ImageRenderingMode.h in Headers */,
7C193BC11F5E0EED0088F3E6 /* ImageSmoothingQuality.h in Headers */,
+ 5546757B1FD212A9003B10B0 /* ImageSource.h in Headers */,
4B3480940EEF50D400AC1B41 /* ImageSourceCG.h in Headers */,
5550CB421E955E3C00111AA0 /* ImageTypes.h in Headers */,
26F756B31B3B66F70005DD79 /* ImmutableNFA.h in Headers */,
Modified: trunk/Source/WebCore/platform/graphics/BitmapImage.cpp (225427 => 225428)
--- trunk/Source/WebCore/platform/graphics/BitmapImage.cpp 2017-12-02 00:00:40 UTC (rev 225427)
+++ trunk/Source/WebCore/platform/graphics/BitmapImage.cpp 2017-12-02 00:01:54 UTC (rev 225428)
@@ -47,13 +47,13 @@
BitmapImage::BitmapImage(ImageObserver* observer)
: Image(observer)
- , m_source(ImageFrameCache::create(this))
+ , m_source(ImageSource::create(this))
{
}
BitmapImage::BitmapImage(NativeImagePtr&& image, ImageObserver* observer)
: Image(observer)
- , m_source(ImageFrameCache::create(WTFMove(image)))
+ , m_source(ImageSource::create(WTFMove(image)))
{
}
Modified: trunk/Source/WebCore/platform/graphics/BitmapImage.h (225427 => 225428)
--- trunk/Source/WebCore/platform/graphics/BitmapImage.h 2017-12-02 00:00:40 UTC (rev 225427)
+++ trunk/Source/WebCore/platform/graphics/BitmapImage.h 2017-12-02 00:01:54 UTC (rev 225428)
@@ -29,9 +29,9 @@
#include "Image.h"
#include "Color.h"
-#include "ImageFrameCache.h"
#include "ImageObserver.h"
#include "ImageOrientation.h"
+#include "ImageSource.h"
#include "IntSize.h"
#if USE(CG) || USE(APPKIT)
@@ -205,7 +205,7 @@
// Animated images over a certain size are considered large enough that we'll only hang on to one frame at a time.
static const unsigned LargeAnimationCutoff = 30 * 1024 * 1024;
- mutable Ref<ImageFrameCache> m_source;
+ mutable Ref<ImageSource> m_source;
size_t m_currentFrame { 0 }; // The index of the current frame of animation.
SubsamplingLevel m_currentSubsamplingLevel { SubsamplingLevel::Default };
Modified: trunk/Source/WebCore/platform/graphics/ImageFrame.h (225427 => 225428)
--- trunk/Source/WebCore/platform/graphics/ImageFrame.h 2017-12-02 00:00:40 UTC (rev 225427)
+++ trunk/Source/WebCore/platform/graphics/ImageFrame.h 2017-12-02 00:01:54 UTC (rev 225428)
@@ -37,7 +37,7 @@
namespace WebCore {
class ImageFrame {
- friend class ImageFrameCache;
+ friend class ImageSource;
public:
enum class Caching { Metadata, MetadataAndImage };
Deleted: trunk/Source/WebCore/platform/graphics/ImageFrameCache.cpp (225427 => 225428)
--- trunk/Source/WebCore/platform/graphics/ImageFrameCache.cpp 2017-12-02 00:00:40 UTC (rev 225427)
+++ trunk/Source/WebCore/platform/graphics/ImageFrameCache.cpp 2017-12-02 00:01:54 UTC (rev 225428)
@@ -1,672 +0,0 @@
-/*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "ImageFrameCache.h"
-
-#include "Image.h"
-#include "ImageObserver.h"
-#include "Logging.h"
-#include "URL.h"
-#include <wtf/SystemTracing.h>
-
-#if USE(CG)
-#include "ImageDecoderCG.h"
-#elif USE(DIRECT2D)
-#include "ImageDecoderDirect2D.h"
-#include <WinCodec.h>
-#else
-#include "ImageDecoder.h"
-#endif
-
-#include <wtf/CheckedArithmetic.h>
-#include <wtf/MainThread.h>
-#include <wtf/RunLoop.h>
-
-namespace WebCore {
-
-ImageFrameCache::ImageFrameCache(Image* image, AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
- : m_image(image)
- , m_alphaOption(alphaOption)
- , m_gammaAndColorProfileOption(gammaAndColorProfileOption)
-{
-}
-
-ImageFrameCache::ImageFrameCache(NativeImagePtr&& nativeImage)
-{
- m_frameCount = 1;
- m_encodedDataStatus = EncodedDataStatus::Complete;
- growFrames();
-
- setNativeImage(WTFMove(nativeImage));
-
- m_decodedSize = m_frames[0].frameBytes();
-
- // The assumption is the memory image will be displayed with the default
- // orientation. So set m_sizeRespectingOrientation to be the same as m_size.
- m_size = m_frames[0].size();
- m_sizeRespectingOrientation = m_size;
-}
-
-ImageFrameCache::~ImageFrameCache()
-{
- ASSERT(!hasAsyncDecodingQueue());
-}
-
-bool ImageFrameCache::ensureDecoderAvailable(SharedBuffer* data)
-{
- if (!data || isDecoderAvailable())
- return true;
-
- m_decoder = ImageDecoder::create(*data, mimeType(), m_alphaOption, m_gammaAndColorProfileOption);
- if (!isDecoderAvailable())
- return false;
-
- if (auto expectedContentSize = expectedContentLength())
- m_decoder->setExpectedContentSize(expectedContentSize);
-
- // Changing the decoder has to stop the decoding thread. The current frame will
- // continue decoding safely because the decoding thread has its own
- // reference of the old decoder.
- stopAsyncDecodingQueue();
- return true;
-}
-
-void ImageFrameCache::setData(SharedBuffer* data, bool allDataReceived)
-{
- if (!data || !ensureDecoderAvailable(data))
- return;
-
- m_decoder->setData(*data, allDataReceived);
-}
-
-void ImageFrameCache::resetData(SharedBuffer* data)
-{
- m_decoder = nullptr;
- setData(data, isAllDataReceived());
-}
-
-EncodedDataStatus ImageFrameCache::dataChanged(SharedBuffer* data, bool allDataReceived)
-{
- setData(data, allDataReceived);
- clearMetadata();
- EncodedDataStatus status = encodedDataStatus();
- if (status >= EncodedDataStatus::SizeAvailable)
- growFrames();
- return status;
-}
-
-bool ImageFrameCache::isAllDataReceived()
-{
- return isDecoderAvailable() ? m_decoder->isAllDataReceived() : frameCount();
-}
-
-void ImageFrameCache::destroyDecodedData(size_t frameCount, size_t excludeFrame)
-{
- unsigned decodedSize = 0;
-
- ASSERT(frameCount <= m_frames.size());
-
- for (size_t index = 0; index < frameCount; ++index) {
- if (index == excludeFrame)
- continue;
- decodedSize += m_frames[index].clearImage();
- }
-
- decodedSizeReset(decodedSize);
-}
-
-void ImageFrameCache::destroyIncompleteDecodedData()
-{
- unsigned decodedSize = 0;
-
- for (auto& frame : m_frames) {
- if (!frame.hasMetadata() || frame.isComplete())
- continue;
-
- decodedSize += frame.clear();
- }
-
- decodedSizeDecreased(decodedSize);
-}
-
-void ImageFrameCache::clearFrameBufferCache(size_t beforeFrame)
-{
- if (!isDecoderAvailable())
- return;
- m_decoder->clearFrameBufferCache(beforeFrame);
-}
-
-void ImageFrameCache::decodedSizeChanged(long long decodedSize)
-{
- if (!decodedSize || !m_image || !m_image->imageObserver())
- return;
-
- m_image->imageObserver()->decodedSizeChanged(*m_image, decodedSize);
-}
-
-void ImageFrameCache::decodedSizeIncreased(unsigned decodedSize)
-{
- if (!decodedSize)
- return;
-
- m_decodedSize += decodedSize;
-
- // The fully-decoded frame will subsume the partially decoded data used
- // to determine image properties.
- long long changeSize = static_cast<long long>(decodedSize) - m_decodedPropertiesSize;
- m_decodedPropertiesSize = 0;
- decodedSizeChanged(changeSize);
-}
-
-void ImageFrameCache::decodedSizeDecreased(unsigned decodedSize)
-{
- if (!decodedSize)
- return;
-
- ASSERT(m_decodedSize >= decodedSize);
- m_decodedSize -= decodedSize;
- decodedSizeChanged(-static_cast<long long>(decodedSize));
-}
-
-void ImageFrameCache::decodedSizeReset(unsigned decodedSize)
-{
- ASSERT(m_decodedSize >= decodedSize);
- m_decodedSize -= decodedSize;
-
- // Clearing the ImageSource destroys the extra decoded data used for
- // determining image properties.
- decodedSize += m_decodedPropertiesSize;
- m_decodedPropertiesSize = 0;
- decodedSizeChanged(-static_cast<long long>(decodedSize));
-}
-
-void ImageFrameCache::didDecodeProperties(unsigned decodedPropertiesSize)
-{
- if (m_decodedSize)
- return;
-
- long long decodedSize = static_cast<long long>(decodedPropertiesSize) - m_decodedPropertiesSize;
- m_decodedPropertiesSize = decodedPropertiesSize;
- decodedSizeChanged(decodedSize);
-}
-
-void ImageFrameCache::growFrames()
-{
- ASSERT(isSizeAvailable());
- auto newSize = frameCount();
- if (newSize > m_frames.size())
- m_frames.grow(newSize);
-}
-
-void ImageFrameCache::setNativeImage(NativeImagePtr&& nativeImage)
-{
- ASSERT(m_frames.size() == 1);
- ImageFrame& frame = m_frames[0];
-
- ASSERT(!isDecoderAvailable());
-
- frame.m_nativeImage = WTFMove(nativeImage);
-
- frame.m_decodingStatus = DecodingStatus::Complete;
- frame.m_size = nativeImageSize(frame.m_nativeImage);
- frame.m_hasAlpha = nativeImageHasAlpha(frame.m_nativeImage);
-}
-
-void ImageFrameCache::cacheMetadataAtIndex(size_t index, SubsamplingLevel subsamplingLevel, DecodingStatus decodingStatus)
-{
- ASSERT(index < m_frames.size());
- ImageFrame& frame = m_frames[index];
-
- ASSERT(isDecoderAvailable());
- if (decodingStatus == DecodingStatus::Invalid)
- frame.m_decodingStatus = m_decoder->frameIsCompleteAtIndex(index) ? DecodingStatus::Complete : DecodingStatus::Partial;
- else
- frame.m_decodingStatus = decodingStatus;
-
- if (frame.hasMetadata())
- return;
-
- frame.m_subsamplingLevel = subsamplingLevel;
-
- if (frame.m_decodingOptions.hasSizeForDrawing()) {
- ASSERT(frame.hasNativeImage());
- frame.m_size = nativeImageSize(frame.nativeImage());
- } else
- frame.m_size = m_decoder->frameSizeAtIndex(index, subsamplingLevel);
-
- frame.m_orientation = m_decoder->frameOrientationAtIndex(index);
- frame.m_hasAlpha = m_decoder->frameHasAlphaAtIndex(index);
-
- if (repetitionCount())
- frame.m_duration = m_decoder->frameDurationAtIndex(index);
-}
-
-void ImageFrameCache::cacheNativeImageAtIndex(NativeImagePtr&& nativeImage, size_t index, SubsamplingLevel subsamplingLevel, const DecodingOptions& decodingOptions, DecodingStatus decodingStatus)
-{
- ASSERT(index < m_frames.size());
- ImageFrame& frame = m_frames[index];
-
- // Clear the current image frame and update the observer with this clearance.
- decodedSizeDecreased(frame.clear());
-
- // Do not cache the NativeImage if adding its frameByes to the MemoryCache will cause numerical overflow.
- size_t frameBytes = size().unclampedArea() * sizeof(RGBA32);
- if (!WTF::isInBounds<unsigned>(frameBytes + decodedSize()))
- return;
-
- // Move the new image to the cache.
- frame.m_nativeImage = WTFMove(nativeImage);
- frame.m_decodingOptions = decodingOptions;
- cacheMetadataAtIndex(index, subsamplingLevel, decodingStatus);
-
- // Update the observer with the new image frame bytes.
- decodedSizeIncreased(frame.frameBytes());
-}
-
-void ImageFrameCache::cacheNativeImageAtIndexAsync(NativeImagePtr&& nativeImage, size_t index, SubsamplingLevel subsamplingLevel, const DecodingOptions& decodingOptions, DecodingStatus decodingStatus)
-{
- if (!isDecoderAvailable())
- return;
-
- ASSERT(index < m_frames.size());
-
- // Clean the old native image and set a new one
- cacheNativeImageAtIndex(WTFMove(nativeImage), index, subsamplingLevel, decodingOptions, decodingStatus);
- LOG(Images, "ImageFrameCache::%s - %p - url: %s [frame %ld has been cached]", __FUNCTION__, this, sourceURL().string().utf8().data(), index);
-
- // Notify the image with the readiness of the new frame NativeImage.
- if (m_image)
- m_image->imageFrameAvailableAtIndex(index);
-}
-
-WorkQueue& ImageFrameCache::decodingQueue()
-{
- if (!m_decodingQueue)
- m_decodingQueue = WorkQueue::create("org.webkit.ImageDecoder", WorkQueue::Type::Serial, WorkQueue::QOS::Default);
-
- return *m_decodingQueue;
-}
-
-ImageFrameCache::FrameRequestQueue& ImageFrameCache::frameRequestQueue()
-{
- if (!m_frameRequestQueue)
- m_frameRequestQueue = FrameRequestQueue::create();
-
- return *m_frameRequestQueue;
-}
-
-bool ImageFrameCache::canUseAsyncDecoding()
-{
- if (!isDecoderAvailable())
- return false;
- // FIXME: figure out the best heuristic for enabling async image decoding.
- return size().area() * sizeof(RGBA32) >= (frameCount() > 1 ? 100 * KB : 500 * KB);
-}
-
-void ImageFrameCache::startAsyncDecodingQueue()
-{
- if (hasAsyncDecodingQueue() || !isDecoderAvailable())
- return;
-
- // We need to protect this, m_decodingQueue and m_decoder from being deleted while we are in the decoding loop.
- decodingQueue().dispatch([protectedThis = makeRef(*this), protectedDecodingQueue = makeRef(decodingQueue()), protectedFrameRequestQueue = makeRef(frameRequestQueue()), protectedDecoder = makeRef(*m_decoder), sourceURL = sourceURL().string().isolatedCopy()] {
- ImageFrameRequest frameRequest;
-
- while (protectedFrameRequestQueue->dequeue(frameRequest)) {
- TraceScope tracingScope(AsyncImageDecodeStart, AsyncImageDecodeEnd);
-
- // Get the frame NativeImage on the decoding thread.
- NativeImagePtr nativeImage = protectedDecoder->createFrameImageAtIndex(frameRequest.index, frameRequest.subsamplingLevel, frameRequest.decodingOptions);
- if (nativeImage)
- LOG(Images, "ImageFrameCache::%s - %p - url: %s [frame %ld has been decoded]", __FUNCTION__, protectedThis.ptr(), sourceURL.utf8().data(), frameRequest.index);
- else {
- LOG(Images, "ImageFrameCache::%s - %p - url: %s [decoding for frame %ld has failed]", __FUNCTION__, protectedThis.ptr(), sourceURL.utf8().data(), frameRequest.index);
- continue;
- }
-
- // Update the cached frames on the main thread to avoid updating the MemoryCache from a different thread.
- callOnMainThread([protectedThis = protectedThis.copyRef(), protectedQueue = protectedDecodingQueue.copyRef(), protectedDecoder = protectedDecoder.copyRef(), sourceURL = sourceURL.isolatedCopy(), nativeImage = WTFMove(nativeImage), frameRequest] () mutable {
- // The queue may have been closed if after we got the frame NativeImage, stopAsyncDecodingQueue() was called.
- if (protectedQueue.ptr() == protectedThis->m_decodingQueue && protectedDecoder.ptr() == protectedThis->m_decoder) {
- ASSERT(protectedThis->m_frameCommitQueue.first() == frameRequest);
- protectedThis->m_frameCommitQueue.removeFirst();
- protectedThis->cacheNativeImageAtIndexAsync(WTFMove(nativeImage), frameRequest.index, frameRequest.subsamplingLevel, frameRequest.decodingOptions, frameRequest.decodingStatus);
- } else
- LOG(Images, "ImageFrameCache::%s - %p - url: %s [frame %ld will not cached]", __FUNCTION__, protectedThis.ptr(), sourceURL.utf8().data(), frameRequest.index);
- });
- }
- });
-}
-
-void ImageFrameCache::requestFrameAsyncDecodingAtIndex(size_t index, SubsamplingLevel subsamplingLevel, const std::optional<IntSize>& sizeForDrawing)
-{
- ASSERT(isDecoderAvailable());
- if (!hasAsyncDecodingQueue())
- startAsyncDecodingQueue();
-
- ASSERT(index < m_frames.size());
- DecodingStatus decodingStatus = m_decoder->frameIsCompleteAtIndex(index) ? DecodingStatus::Complete : DecodingStatus::Partial;
-
- LOG(Images, "ImageFrameCache::%s - %p - url: %s [enqueuing frame %ld for decoding]", __FUNCTION__, this, sourceURL().string().utf8().data(), index);
- m_frameRequestQueue->enqueue({ index, subsamplingLevel, sizeForDrawing, decodingStatus });
- m_frameCommitQueue.append({ index, subsamplingLevel, sizeForDrawing, decodingStatus });
-}
-
-bool ImageFrameCache::isAsyncDecodingQueueIdle() const
-{
- return m_frameCommitQueue.isEmpty();
-}
-
-void ImageFrameCache::stopAsyncDecodingQueue()
-{
- if (!hasAsyncDecodingQueue())
- return;
-
- std::for_each(m_frameCommitQueue.begin(), m_frameCommitQueue.end(), [this](const ImageFrameRequest& frameRequest) {
- ImageFrame& frame = m_frames[frameRequest.index];
- if (!frame.isInvalid()) {
- LOG(Images, "ImageFrameCache::%s - %p - url: %s [decoding has been cancelled for frame %ld]", __FUNCTION__, this, sourceURL().string().utf8().data(), frameRequest.index);
- frame.clear();
- }
- });
-
- // Close m_frameRequestQueue then set it to nullptr. A new decoding thread might start and a
- // new m_frameRequestQueue will be created. So the terminating thread will not have access to it.
- m_frameRequestQueue->close();
- m_frameRequestQueue = nullptr;
- m_frameCommitQueue.clear();
- m_decodingQueue = nullptr;
- LOG(Images, "ImageFrameCache::%s - %p - url: %s [decoding has been stopped]", __FUNCTION__, this, sourceURL().string().utf8().data());
-}
-
-const ImageFrame& ImageFrameCache::frameAtIndexCacheIfNeeded(size_t index, ImageFrame::Caching caching, const std::optional<SubsamplingLevel>& subsamplingLevel)
-{
- ASSERT(index < m_frames.size());
- ImageFrame& frame = m_frames[index];
- if (!isDecoderAvailable() || frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(index, DecodingMode::Asynchronous))
- return frame;
-
- SubsamplingLevel subsamplingLevelValue = subsamplingLevel ? subsamplingLevel.value() : frame.subsamplingLevel();
-
- switch (caching) {
- case ImageFrame::Caching::Metadata:
- // Retrieve the metadata from ImageDecoder if the ImageFrame isn't complete.
- if (frame.isComplete())
- break;
- cacheMetadataAtIndex(index, subsamplingLevelValue);
- break;
-
- case ImageFrame::Caching::MetadataAndImage:
- // Cache the image and retrieve the metadata from ImageDecoder only if there was not valid image stored.
- if (frame.hasFullSizeNativeImage(subsamplingLevel))
- break;
- // We have to perform synchronous image decoding in this code.
- NativeImagePtr nativeImage = m_decoder->createFrameImageAtIndex(index, subsamplingLevelValue);
- // Clean the old native image and set a new one.
- cacheNativeImageAtIndex(WTFMove(nativeImage), index, subsamplingLevelValue, DecodingMode::Synchronous);
- break;
- }
-
- return frame;
-}
-
-void ImageFrameCache::clearMetadata()
-{
- m_frameCount = std::nullopt;
- m_repetitionCount = std::nullopt;
- m_singlePixelSolidColor = std::nullopt;
- m_encodedDataStatus = std::nullopt;
- m_uti = std::nullopt;
-}
-
-URL ImageFrameCache::sourceURL() const
-{
- return m_image ? m_image->sourceURL() : URL();
-}
-
-String ImageFrameCache::mimeType() const
-{
- return m_image ? m_image->mimeType() : emptyString();
-}
-
-long long ImageFrameCache::expectedContentLength() const
-{
- return m_image ? m_image->expectedContentLength() : 0;
-}
-
-template<typename T, T (ImageDecoder::*functor)() const>
-T ImageFrameCache::metadata(const T& defaultValue, std::optional<T>* cachedValue)
-{
- if (cachedValue && *cachedValue)
- return cachedValue->value();
-
- if (!isDecoderAvailable() || !m_decoder->isSizeAvailable())
- return defaultValue;
-
- if (!cachedValue)
- return (*m_decoder.*functor)();
-
- *cachedValue = (*m_decoder.*functor)();
- didDecodeProperties(m_decoder->bytesDecodedToDetermineProperties());
- return cachedValue->value();
-}
-
-template<typename T, typename... Args>
-T ImageFrameCache::frameMetadataAtIndex(size_t index, T (ImageFrame::*functor)(Args...) const, Args&&... args)
-{
- const ImageFrame& frame = index < m_frames.size() ? m_frames[index] : ImageFrame::defaultFrame();
- return (frame.*functor)(std::forward<Args>(args)...);
-}
-
-template<typename T, typename... Args>
-T ImageFrameCache::frameMetadataAtIndexCacheIfNeeded(size_t index, T (ImageFrame::*functor)() const, std::optional<T>* cachedValue, Args&&... args)
-{
- if (cachedValue && *cachedValue)
- return cachedValue->value();
-
- const ImageFrame& frame = index < m_frames.size() ? frameAtIndexCacheIfNeeded(index, std::forward<Args>(args)...) : ImageFrame::defaultFrame();
-
- // Don't cache any unavailable frame metadata.
- if (!frame.hasMetadata() || !cachedValue)
- return (frame.*functor)();
-
- *cachedValue = (frame.*functor)();
- return cachedValue->value();
-}
-
-EncodedDataStatus ImageFrameCache::encodedDataStatus()
-{
- return metadata<EncodedDataStatus, (&ImageDecoder::encodedDataStatus)>(EncodedDataStatus::Unknown, &m_encodedDataStatus);
-}
-
-size_t ImageFrameCache::frameCount()
-{
- return metadata<size_t, (&ImageDecoder::frameCount)>(m_frames.size(), &m_frameCount);
-}
-
-RepetitionCount ImageFrameCache::repetitionCount()
-{
- return metadata<RepetitionCount, (&ImageDecoder::repetitionCount)>(RepetitionCountNone, &m_repetitionCount);
-}
-
-String ImageFrameCache::uti()
-{
-#if USE(CG)
- return metadata<String, (&ImageDecoder::uti)>(String(), &m_uti);
-#else
- return String();
-#endif
-}
-
-String ImageFrameCache::filenameExtension()
-{
- return metadata<String, (&ImageDecoder::filenameExtension)>(String(), &m_filenameExtension);
-}
-
-std::optional<IntPoint> ImageFrameCache::hotSpot()
-{
- return metadata<std::optional<IntPoint>, (&ImageDecoder::hotSpot)>(std::nullopt, &m_hotSpot);
-}
-
-IntSize ImageFrameCache::size()
-{
-#if !USE(CG)
- // It's possible that we have decoded the metadata, but not frame contents yet. In that case ImageDecoder claims to
- // have the size available, but the frame cache is empty. Return the decoder size without caching in such case.
- if (m_frames.isEmpty() && isDecoderAvailable())
- return m_decoder->size();
-#endif
- return frameMetadataAtIndexCacheIfNeeded<IntSize>(0, (&ImageFrame::size), &m_size, ImageFrame::Caching::Metadata, SubsamplingLevel::Default);
-}
-
-IntSize ImageFrameCache::sizeRespectingOrientation()
-{
- return frameMetadataAtIndexCacheIfNeeded<IntSize>(0, (&ImageFrame::sizeRespectingOrientation), &m_sizeRespectingOrientation, ImageFrame::Caching::Metadata, SubsamplingLevel::Default);
-}
-
-Color ImageFrameCache::singlePixelSolidColor()
-{
- if (!m_singlePixelSolidColor && (size() != IntSize(1, 1) || frameCount() != 1))
- m_singlePixelSolidColor = Color();
-
- if (m_singlePixelSolidColor)
- return m_singlePixelSolidColor.value();
-
- return frameMetadataAtIndexCacheIfNeeded<Color>(0, (&ImageFrame::singlePixelSolidColor), &m_singlePixelSolidColor, ImageFrame::Caching::MetadataAndImage);
-}
-
-SubsamplingLevel ImageFrameCache::maximumSubsamplingLevel()
-{
- if (m_maximumSubsamplingLevel)
- return m_maximumSubsamplingLevel.value();
-
- if (!isDecoderAvailable() || !m_decoder->frameAllowSubsamplingAtIndex(0))
- return SubsamplingLevel::Default;
-
- // FIXME: this value was chosen to be appropriate for iOS since the image
- // subsampling is only enabled by default on iOS. Choose a different value
- // if image subsampling is enabled on other platform.
- const int maximumImageAreaBeforeSubsampling = 5 * 1024 * 1024;
- SubsamplingLevel level = SubsamplingLevel::First;
-
- for (; level < SubsamplingLevel::Last; ++level) {
- if (frameSizeAtIndex(0, level).area().unsafeGet() < maximumImageAreaBeforeSubsampling)
- break;
- }
-
- m_maximumSubsamplingLevel = level;
- return m_maximumSubsamplingLevel.value();
-}
-
-bool ImageFrameCache::frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(size_t index, const DecodingOptions& decodingOptions)
-{
- auto it = std::find_if(m_frameCommitQueue.begin(), m_frameCommitQueue.end(), [index, &decodingOptions](const ImageFrameRequest& frameRequest) {
- return frameRequest.index == index && frameRequest.decodingOptions.isAsynchronousCompatibleWith(decodingOptions);
- });
- return it != m_frameCommitQueue.end();
-}
-
-DecodingStatus ImageFrameCache::frameDecodingStatusAtIndex(size_t index)
-{
- return frameMetadataAtIndex<DecodingStatus>(index, (&ImageFrame::decodingStatus));
-}
-
-bool ImageFrameCache::frameHasAlphaAtIndex(size_t index)
-{
- return frameMetadataAtIndex<bool>(index, (&ImageFrame::hasAlpha));
-}
-
-bool ImageFrameCache::frameHasFullSizeNativeImageAtIndex(size_t index, const std::optional<SubsamplingLevel>& subsamplingLevel)
-{
- return frameMetadataAtIndex<bool>(index, (&ImageFrame::hasFullSizeNativeImage), subsamplingLevel);
-}
-
-bool ImageFrameCache::frameHasDecodedNativeImageCompatibleWithOptionsAtIndex(size_t index, const std::optional<SubsamplingLevel>& subsamplingLevel, const DecodingOptions& decodingOptions)
-{
- return frameMetadataAtIndex<bool>(index, (&ImageFrame::hasDecodedNativeImageCompatibleWithOptions), subsamplingLevel, decodingOptions);
-}
-
-SubsamplingLevel ImageFrameCache::frameSubsamplingLevelAtIndex(size_t index)
-{
- return frameMetadataAtIndex<SubsamplingLevel>(index, (&ImageFrame::subsamplingLevel));
-}
-
-IntSize ImageFrameCache::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
-{
- return frameMetadataAtIndexCacheIfNeeded<IntSize>(index, (&ImageFrame::size), nullptr, ImageFrame::Caching::Metadata, subsamplingLevel);
-}
-
-unsigned ImageFrameCache::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
-{
- return frameMetadataAtIndexCacheIfNeeded<unsigned>(index, (&ImageFrame::frameBytes), nullptr, ImageFrame::Caching::Metadata, subsamplingLevel);
-}
-
-Seconds ImageFrameCache::frameDurationAtIndex(size_t index)
-{
- return frameMetadataAtIndexCacheIfNeeded<Seconds>(index, (&ImageFrame::duration), nullptr, ImageFrame::Caching::Metadata);
-}
-
-ImageOrientation ImageFrameCache::frameOrientationAtIndex(size_t index)
-{
- return frameMetadataAtIndexCacheIfNeeded<ImageOrientation>(index, (&ImageFrame::orientation), nullptr, ImageFrame::Caching::Metadata);
-}
-
-#if USE(DIRECT2D)
-void ImageFrameCache::setTargetContext(const GraphicsContext* targetContext)
-{
- if (isDecoderAvailable() && targetContext)
- m_decoder->setTargetContext(targetContext->platformContext())
-}
-#endif
-
-NativeImagePtr ImageFrameCache::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
-{
- return isDecoderAvailable() ? m_decoder->createFrameImageAtIndex(index, subsamplingLevel) : nullptr;
-}
-
-NativeImagePtr ImageFrameCache::frameImageAtIndex(size_t index)
-{
- return frameMetadataAtIndex<NativeImagePtr>(index, (&ImageFrame::nativeImage));
-}
-
-NativeImagePtr ImageFrameCache::frameImageAtIndexCacheIfNeeded(size_t index, SubsamplingLevel subsamplingLevel)
-{
- return frameMetadataAtIndexCacheIfNeeded<NativeImagePtr>(index, (&ImageFrame::nativeImage), nullptr, ImageFrame::Caching::MetadataAndImage, subsamplingLevel);
-}
-
-void ImageFrameCache::dump(TextStream& ts)
-{
- ts.dumpProperty("type", filenameExtension());
- ts.dumpProperty("frame-count", frameCount());
- ts.dumpProperty("repetitions", repetitionCount());
- ts.dumpProperty("solid-color", singlePixelSolidColor());
-
- ImageOrientation orientation = frameOrientationAtIndex(0);
- if (orientation != OriginTopLeft)
- ts.dumpProperty("orientation", orientation);
-}
-
-}
Deleted: trunk/Source/WebCore/platform/graphics/ImageFrameCache.h (225427 => 225428)
--- trunk/Source/WebCore/platform/graphics/ImageFrameCache.h 2017-12-02 00:00:40 UTC (rev 225427)
+++ trunk/Source/WebCore/platform/graphics/ImageFrameCache.h 2017-12-02 00:01:54 UTC (rev 225428)
@@ -1,199 +0,0 @@
-/*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include "ImageFrame.h"
-
-#include <wtf/Forward.h>
-#include <wtf/Optional.h>
-#include <wtf/SynchronizedFixedQueue.h>
-#include <wtf/WorkQueue.h>
-#include <wtf/text/TextStream.h>
-
-namespace WebCore {
-
-class GraphicsContext;
-class Image;
-class ImageDecoder;
-class URL;
-
-class ImageFrameCache : public ThreadSafeRefCounted<ImageFrameCache> {
- friend class BitmapImage;
-public:
- ImageFrameCache(Image*, AlphaOption = AlphaOption::Premultiplied, GammaAndColorProfileOption = GammaAndColorProfileOption::Applied);
- ImageFrameCache(NativeImagePtr&&);
- ~ImageFrameCache();
-
- static Ref<ImageFrameCache> create(Image* image, AlphaOption alphaOption = AlphaOption::Premultiplied, GammaAndColorProfileOption gammaAndColorProfileOption = GammaAndColorProfileOption::Applied)
- {
- return adoptRef(*new ImageFrameCache(image, alphaOption, gammaAndColorProfileOption));
- }
-
- static Ref<ImageFrameCache> create(NativeImagePtr&& nativeImage)
- {
- return adoptRef(*new ImageFrameCache(WTFMove(nativeImage)));
- }
-
- void setData(SharedBuffer* data, bool allDataReceived);
- void resetData(SharedBuffer* data);
- EncodedDataStatus dataChanged(SharedBuffer* data, bool allDataReceived);
- bool isAllDataReceived();
-
- unsigned decodedSize() const { return m_decodedSize; }
- void destroyAllDecodedData() { destroyDecodedData(frameCount(), frameCount()); }
- void destroyAllDecodedDataExcludeFrame(size_t excludeFrame) { destroyDecodedData(frameCount(), excludeFrame); }
- void destroyDecodedDataBeforeFrame(size_t beforeFrame) { destroyDecodedData(beforeFrame, beforeFrame); }
- void destroyIncompleteDecodedData();
- void clearFrameBufferCache(size_t beforeFrame);
-
- void growFrames();
- void clearMetadata();
- void clearImage() { m_image = nullptr; }
- URL sourceURL() const;
- String mimeType() const;
- long long expectedContentLength() const;
-
- // Asynchronous image decoding
- bool canUseAsyncDecoding();
- void startAsyncDecodingQueue();
- void requestFrameAsyncDecodingAtIndex(size_t, SubsamplingLevel, const std::optional<IntSize>& = { });
- void stopAsyncDecodingQueue();
- bool hasAsyncDecodingQueue() const { return m_decodingQueue; }
- bool isAsyncDecodingQueueIdle() const;
-
- // Image metadata which is calculated either by the ImageDecoder or directly
- // from the NativeImage if this class was created for a memory image.
- EncodedDataStatus encodedDataStatus();
- bool isSizeAvailable() { return encodedDataStatus() >= EncodedDataStatus::SizeAvailable; }
- size_t frameCount();
- RepetitionCount repetitionCount();
- String uti();
- String filenameExtension();
- std::optional<IntPoint> hotSpot();
-
- // Image metadata which is calculated from the first ImageFrame.
- IntSize size();
- IntSize sizeRespectingOrientation();
- Color singlePixelSolidColor();
- SubsamplingLevel maximumSubsamplingLevel();
-
- // ImageFrame metadata which does not require caching the ImageFrame.
- bool frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(size_t, const DecodingOptions&);
- DecodingStatus frameDecodingStatusAtIndex(size_t);
- bool frameHasAlphaAtIndex(size_t);
- bool frameHasImageAtIndex(size_t);
- bool frameHasFullSizeNativeImageAtIndex(size_t, const std::optional<SubsamplingLevel>&);
- bool frameHasDecodedNativeImageCompatibleWithOptionsAtIndex(size_t, const std::optional<SubsamplingLevel>&, const DecodingOptions&);
- SubsamplingLevel frameSubsamplingLevelAtIndex(size_t);
-
- // ImageFrame metadata which forces caching or re-caching the ImageFrame.
- IntSize frameSizeAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
- unsigned frameBytesAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
- Seconds frameDurationAtIndex(size_t);
- ImageOrientation frameOrientationAtIndex(size_t);
-
-#if USE(DIRECT2D)
- void setTargetContext(const GraphicsContext*);
-#endif
- NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
- NativeImagePtr frameImageAtIndex(size_t);
- NativeImagePtr frameImageAtIndexCacheIfNeeded(size_t, SubsamplingLevel = SubsamplingLevel::Default);
-
-private:
- template<typename T, T (ImageDecoder::*functor)() const>
- T metadata(const T& defaultValue, std::optional<T>* cachedValue = nullptr);
-
- template<typename T, typename... Args>
- T frameMetadataAtIndex(size_t, T (ImageFrame::*functor)(Args...) const, Args&&...);
-
- template<typename T, typename... Args>
- T frameMetadataAtIndexCacheIfNeeded(size_t, T (ImageFrame::*functor)() const, std::optional<T>* cachedValue, Args&&...);
-
- bool ensureDecoderAvailable(SharedBuffer* data);
- bool isDecoderAvailable() const { return m_decoder; }
- void destroyDecodedData(size_t frameCount, size_t excludeFrame);
- void decodedSizeChanged(long long decodedSize);
- void didDecodeProperties(unsigned decodedPropertiesSize);
- void decodedSizeIncreased(unsigned decodedSize);
- void decodedSizeDecreased(unsigned decodedSize);
- void decodedSizeReset(unsigned decodedSize);
-
- void setNativeImage(NativeImagePtr&&);
- void cacheMetadataAtIndex(size_t, SubsamplingLevel, DecodingStatus = DecodingStatus::Invalid);
- void cacheNativeImageAtIndex(NativeImagePtr&&, size_t, SubsamplingLevel, const DecodingOptions&, DecodingStatus = DecodingStatus::Invalid);
- void cacheNativeImageAtIndexAsync(NativeImagePtr&&, size_t, SubsamplingLevel, const DecodingOptions&, DecodingStatus);
-
- struct ImageFrameRequest;
- static const int BufferSize = 8;
- WorkQueue& decodingQueue();
- SynchronizedFixedQueue<ImageFrameRequest, BufferSize>& frameRequestQueue();
-
- const ImageFrame& frameAtIndexCacheIfNeeded(size_t, ImageFrame::Caching, const std::optional<SubsamplingLevel>& = { });
-
- void dump(TextStream&);
-
- Image* m_image { nullptr };
- RefPtr<ImageDecoder> m_decoder;
- AlphaOption m_alphaOption { AlphaOption::Premultiplied };
- GammaAndColorProfileOption m_gammaAndColorProfileOption { GammaAndColorProfileOption::Applied };
-
- unsigned m_decodedSize { 0 };
- unsigned m_decodedPropertiesSize { 0 };
- Vector<ImageFrame, 1> m_frames;
-
- // Asynchronous image decoding.
- struct ImageFrameRequest {
- size_t index;
- SubsamplingLevel subsamplingLevel;
- DecodingOptions decodingOptions;
- DecodingStatus decodingStatus;
- bool operator==(const ImageFrameRequest& other) const
- {
- return index == other.index && subsamplingLevel == other.subsamplingLevel && decodingOptions == other.decodingOptions && decodingStatus == other.decodingStatus;
- }
- };
- using FrameRequestQueue = SynchronizedFixedQueue<ImageFrameRequest, BufferSize>;
- using FrameCommitQueue = Deque<ImageFrameRequest, BufferSize>;
- RefPtr<FrameRequestQueue> m_frameRequestQueue;
- FrameCommitQueue m_frameCommitQueue;
- RefPtr<WorkQueue> m_decodingQueue;
-
- // Image metadata.
- std::optional<EncodedDataStatus> m_encodedDataStatus;
- std::optional<size_t> m_frameCount;
- std::optional<RepetitionCount> m_repetitionCount;
- std::optional<String> m_uti;
- std::optional<String> m_filenameExtension;
- std::optional<std::optional<IntPoint>> m_hotSpot;
-
- // Image metadata which is calculated from the first ImageFrame.
- std::optional<IntSize> m_size;
- std::optional<IntSize> m_sizeRespectingOrientation;
- std::optional<Color> m_singlePixelSolidColor;
- std::optional<SubsamplingLevel> m_maximumSubsamplingLevel;
-};
-
-}
Copied: trunk/Source/WebCore/platform/graphics/ImageSource.cpp (from rev 225427, trunk/Source/WebCore/platform/graphics/ImageFrameCache.cpp) (0 => 225428)
--- trunk/Source/WebCore/platform/graphics/ImageSource.cpp (rev 0)
+++ trunk/Source/WebCore/platform/graphics/ImageSource.cpp 2017-12-02 00:01:54 UTC (rev 225428)
@@ -0,0 +1,672 @@
+/*
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ImageSource.h"
+
+#include "Image.h"
+#include "ImageObserver.h"
+#include "Logging.h"
+#include "URL.h"
+#include <wtf/SystemTracing.h>
+
+#if USE(CG)
+#include "ImageDecoderCG.h"
+#elif USE(DIRECT2D)
+#include "ImageDecoderDirect2D.h"
+#include <WinCodec.h>
+#else
+#include "ImageDecoder.h"
+#endif
+
+#include <wtf/CheckedArithmetic.h>
+#include <wtf/MainThread.h>
+#include <wtf/RunLoop.h>
+
+namespace WebCore {
+
+ImageSource::ImageSource(Image* image, AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
+ : m_image(image)
+ , m_alphaOption(alphaOption)
+ , m_gammaAndColorProfileOption(gammaAndColorProfileOption)
+{
+}
+
+ImageSource::ImageSource(NativeImagePtr&& nativeImage)
+{
+ m_frameCount = 1;
+ m_encodedDataStatus = EncodedDataStatus::Complete;
+ growFrames();
+
+ setNativeImage(WTFMove(nativeImage));
+
+ m_decodedSize = m_frames[0].frameBytes();
+
+ // The assumption is the memory image will be displayed with the default
+ // orientation. So set m_sizeRespectingOrientation to be the same as m_size.
+ m_size = m_frames[0].size();
+ m_sizeRespectingOrientation = m_size;
+}
+
+ImageSource::~ImageSource()
+{
+ ASSERT(!hasAsyncDecodingQueue());
+}
+
+bool ImageSource::ensureDecoderAvailable(SharedBuffer* data)
+{
+ if (!data || isDecoderAvailable())
+ return true;
+
+ m_decoder = ImageDecoder::create(*data, mimeType(), m_alphaOption, m_gammaAndColorProfileOption);
+ if (!isDecoderAvailable())
+ return false;
+
+ if (auto expectedContentSize = expectedContentLength())
+ m_decoder->setExpectedContentSize(expectedContentSize);
+
+ // Changing the decoder has to stop the decoding thread. The current frame will
+ // continue decoding safely because the decoding thread has its own
+ // reference of the old decoder.
+ stopAsyncDecodingQueue();
+ return true;
+}
+
+void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
+{
+ if (!data || !ensureDecoderAvailable(data))
+ return;
+
+ m_decoder->setData(*data, allDataReceived);
+}
+
+void ImageSource::resetData(SharedBuffer* data)
+{
+ m_decoder = nullptr;
+ setData(data, isAllDataReceived());
+}
+
+EncodedDataStatus ImageSource::dataChanged(SharedBuffer* data, bool allDataReceived)
+{
+ setData(data, allDataReceived);
+ clearMetadata();
+ EncodedDataStatus status = encodedDataStatus();
+ if (status >= EncodedDataStatus::SizeAvailable)
+ growFrames();
+ return status;
+}
+
+bool ImageSource::isAllDataReceived()
+{
+ return isDecoderAvailable() ? m_decoder->isAllDataReceived() : frameCount();
+}
+
+void ImageSource::destroyDecodedData(size_t frameCount, size_t excludeFrame)
+{
+ unsigned decodedSize = 0;
+
+ ASSERT(frameCount <= m_frames.size());
+
+ for (size_t index = 0; index < frameCount; ++index) {
+ if (index == excludeFrame)
+ continue;
+ decodedSize += m_frames[index].clearImage();
+ }
+
+ decodedSizeReset(decodedSize);
+}
+
+void ImageSource::destroyIncompleteDecodedData()
+{
+ unsigned decodedSize = 0;
+
+ for (auto& frame : m_frames) {
+ if (!frame.hasMetadata() || frame.isComplete())
+ continue;
+
+ decodedSize += frame.clear();
+ }
+
+ decodedSizeDecreased(decodedSize);
+}
+
+void ImageSource::clearFrameBufferCache(size_t beforeFrame)
+{
+ if (!isDecoderAvailable())
+ return;
+ m_decoder->clearFrameBufferCache(beforeFrame);
+}
+
+void ImageSource::decodedSizeChanged(long long decodedSize)
+{
+ if (!decodedSize || !m_image || !m_image->imageObserver())
+ return;
+
+ m_image->imageObserver()->decodedSizeChanged(*m_image, decodedSize);
+}
+
+void ImageSource::decodedSizeIncreased(unsigned decodedSize)
+{
+ if (!decodedSize)
+ return;
+
+ m_decodedSize += decodedSize;
+
+ // The fully-decoded frame will subsume the partially decoded data used
+ // to determine image properties.
+ long long changeSize = static_cast<long long>(decodedSize) - m_decodedPropertiesSize;
+ m_decodedPropertiesSize = 0;
+ decodedSizeChanged(changeSize);
+}
+
+void ImageSource::decodedSizeDecreased(unsigned decodedSize)
+{
+ if (!decodedSize)
+ return;
+
+ ASSERT(m_decodedSize >= decodedSize);
+ m_decodedSize -= decodedSize;
+ decodedSizeChanged(-static_cast<long long>(decodedSize));
+}
+
+void ImageSource::decodedSizeReset(unsigned decodedSize)
+{
+ ASSERT(m_decodedSize >= decodedSize);
+ m_decodedSize -= decodedSize;
+
+ // Clearing the ImageSource destroys the extra decoded data used for
+ // determining image properties.
+ decodedSize += m_decodedPropertiesSize;
+ m_decodedPropertiesSize = 0;
+ decodedSizeChanged(-static_cast<long long>(decodedSize));
+}
+
+void ImageSource::didDecodeProperties(unsigned decodedPropertiesSize)
+{
+ if (m_decodedSize)
+ return;
+
+ long long decodedSize = static_cast<long long>(decodedPropertiesSize) - m_decodedPropertiesSize;
+ m_decodedPropertiesSize = decodedPropertiesSize;
+ decodedSizeChanged(decodedSize);
+}
+
+void ImageSource::growFrames()
+{
+ ASSERT(isSizeAvailable());
+ auto newSize = frameCount();
+ if (newSize > m_frames.size())
+ m_frames.grow(newSize);
+}
+
+void ImageSource::setNativeImage(NativeImagePtr&& nativeImage)
+{
+ ASSERT(m_frames.size() == 1);
+ ImageFrame& frame = m_frames[0];
+
+ ASSERT(!isDecoderAvailable());
+
+ frame.m_nativeImage = WTFMove(nativeImage);
+
+ frame.m_decodingStatus = DecodingStatus::Complete;
+ frame.m_size = nativeImageSize(frame.m_nativeImage);
+ frame.m_hasAlpha = nativeImageHasAlpha(frame.m_nativeImage);
+}
+
+void ImageSource::cacheMetadataAtIndex(size_t index, SubsamplingLevel subsamplingLevel, DecodingStatus decodingStatus)
+{
+ ASSERT(index < m_frames.size());
+ ImageFrame& frame = m_frames[index];
+
+ ASSERT(isDecoderAvailable());
+ if (decodingStatus == DecodingStatus::Invalid)
+ frame.m_decodingStatus = m_decoder->frameIsCompleteAtIndex(index) ? DecodingStatus::Complete : DecodingStatus::Partial;
+ else
+ frame.m_decodingStatus = decodingStatus;
+
+ if (frame.hasMetadata())
+ return;
+
+ frame.m_subsamplingLevel = subsamplingLevel;
+
+ if (frame.m_decodingOptions.hasSizeForDrawing()) {
+ ASSERT(frame.hasNativeImage());
+ frame.m_size = nativeImageSize(frame.nativeImage());
+ } else
+ frame.m_size = m_decoder->frameSizeAtIndex(index, subsamplingLevel);
+
+ frame.m_orientation = m_decoder->frameOrientationAtIndex(index);
+ frame.m_hasAlpha = m_decoder->frameHasAlphaAtIndex(index);
+
+ if (repetitionCount())
+ frame.m_duration = m_decoder->frameDurationAtIndex(index);
+}
+
+void ImageSource::cacheNativeImageAtIndex(NativeImagePtr&& nativeImage, size_t index, SubsamplingLevel subsamplingLevel, const DecodingOptions& decodingOptions, DecodingStatus decodingStatus)
+{
+ ASSERT(index < m_frames.size());
+ ImageFrame& frame = m_frames[index];
+
+ // Clear the current image frame and update the observer with this clearance.
+ decodedSizeDecreased(frame.clear());
+
+ // Do not cache the NativeImage if adding its frameByes to the MemoryCache will cause numerical overflow.
+ size_t frameBytes = size().unclampedArea() * sizeof(RGBA32);
+ if (!WTF::isInBounds<unsigned>(frameBytes + decodedSize()))
+ return;
+
+ // Move the new image to the cache.
+ frame.m_nativeImage = WTFMove(nativeImage);
+ frame.m_decodingOptions = decodingOptions;
+ cacheMetadataAtIndex(index, subsamplingLevel, decodingStatus);
+
+ // Update the observer with the new image frame bytes.
+ decodedSizeIncreased(frame.frameBytes());
+}
+
+void ImageSource::cacheNativeImageAtIndexAsync(NativeImagePtr&& nativeImage, size_t index, SubsamplingLevel subsamplingLevel, const DecodingOptions& decodingOptions, DecodingStatus decodingStatus)
+{
+ if (!isDecoderAvailable())
+ return;
+
+ ASSERT(index < m_frames.size());
+
+ // Clean the old native image and set a new one
+ cacheNativeImageAtIndex(WTFMove(nativeImage), index, subsamplingLevel, decodingOptions, decodingStatus);
+ LOG(Images, "ImageSource::%s - %p - url: %s [frame %ld has been cached]", __FUNCTION__, this, sourceURL().string().utf8().data(), index);
+
+ // Notify the image with the readiness of the new frame NativeImage.
+ if (m_image)
+ m_image->imageFrameAvailableAtIndex(index);
+}
+
+WorkQueue& ImageSource::decodingQueue()
+{
+ if (!m_decodingQueue)
+ m_decodingQueue = WorkQueue::create("org.webkit.ImageDecoder", WorkQueue::Type::Serial, WorkQueue::QOS::Default);
+
+ return *m_decodingQueue;
+}
+
+ImageSource::FrameRequestQueue& ImageSource::frameRequestQueue()
+{
+ if (!m_frameRequestQueue)
+ m_frameRequestQueue = FrameRequestQueue::create();
+
+ return *m_frameRequestQueue;
+}
+
+bool ImageSource::canUseAsyncDecoding()
+{
+ if (!isDecoderAvailable())
+ return false;
+ // FIXME: figure out the best heuristic for enabling async image decoding.
+ return size().area() * sizeof(RGBA32) >= (frameCount() > 1 ? 100 * KB : 500 * KB);
+}
+
+void ImageSource::startAsyncDecodingQueue()
+{
+ if (hasAsyncDecodingQueue() || !isDecoderAvailable())
+ return;
+
+ // We need to protect this, m_decodingQueue and m_decoder from being deleted while we are in the decoding loop.
+ decodingQueue().dispatch([protectedThis = makeRef(*this), protectedDecodingQueue = makeRef(decodingQueue()), protectedFrameRequestQueue = makeRef(frameRequestQueue()), protectedDecoder = makeRef(*m_decoder), sourceURL = sourceURL().string().isolatedCopy()] {
+ ImageFrameRequest frameRequest;
+
+ while (protectedFrameRequestQueue->dequeue(frameRequest)) {
+ TraceScope tracingScope(AsyncImageDecodeStart, AsyncImageDecodeEnd);
+
+ // Get the frame NativeImage on the decoding thread.
+ NativeImagePtr nativeImage = protectedDecoder->createFrameImageAtIndex(frameRequest.index, frameRequest.subsamplingLevel, frameRequest.decodingOptions);
+ if (nativeImage)
+ LOG(Images, "ImageSource::%s - %p - url: %s [frame %ld has been decoded]", __FUNCTION__, protectedThis.ptr(), sourceURL.utf8().data(), frameRequest.index);
+ else {
+ LOG(Images, "ImageSource::%s - %p - url: %s [decoding for frame %ld has failed]", __FUNCTION__, protectedThis.ptr(), sourceURL.utf8().data(), frameRequest.index);
+ continue;
+ }
+
+ // Update the cached frames on the main thread to avoid updating the MemoryCache from a different thread.
+ callOnMainThread([protectedThis = protectedThis.copyRef(), protectedQueue = protectedDecodingQueue.copyRef(), protectedDecoder = protectedDecoder.copyRef(), sourceURL = sourceURL.isolatedCopy(), nativeImage = WTFMove(nativeImage), frameRequest] () mutable {
+ // The queue may have been closed if after we got the frame NativeImage, stopAsyncDecodingQueue() was called.
+ if (protectedQueue.ptr() == protectedThis->m_decodingQueue && protectedDecoder.ptr() == protectedThis->m_decoder) {
+ ASSERT(protectedThis->m_frameCommitQueue.first() == frameRequest);
+ protectedThis->m_frameCommitQueue.removeFirst();
+ protectedThis->cacheNativeImageAtIndexAsync(WTFMove(nativeImage), frameRequest.index, frameRequest.subsamplingLevel, frameRequest.decodingOptions, frameRequest.decodingStatus);
+ } else
+ LOG(Images, "ImageSource::%s - %p - url: %s [frame %ld will not cached]", __FUNCTION__, protectedThis.ptr(), sourceURL.utf8().data(), frameRequest.index);
+ });
+ }
+ });
+}
+
+void ImageSource::requestFrameAsyncDecodingAtIndex(size_t index, SubsamplingLevel subsamplingLevel, const std::optional<IntSize>& sizeForDrawing)
+{
+ ASSERT(isDecoderAvailable());
+ if (!hasAsyncDecodingQueue())
+ startAsyncDecodingQueue();
+
+ ASSERT(index < m_frames.size());
+ DecodingStatus decodingStatus = m_decoder->frameIsCompleteAtIndex(index) ? DecodingStatus::Complete : DecodingStatus::Partial;
+
+ LOG(Images, "ImageSource::%s - %p - url: %s [enqueuing frame %ld for decoding]", __FUNCTION__, this, sourceURL().string().utf8().data(), index);
+ m_frameRequestQueue->enqueue({ index, subsamplingLevel, sizeForDrawing, decodingStatus });
+ m_frameCommitQueue.append({ index, subsamplingLevel, sizeForDrawing, decodingStatus });
+}
+
+bool ImageSource::isAsyncDecodingQueueIdle() const
+{
+ return m_frameCommitQueue.isEmpty();
+}
+
+void ImageSource::stopAsyncDecodingQueue()
+{
+ if (!hasAsyncDecodingQueue())
+ return;
+
+ std::for_each(m_frameCommitQueue.begin(), m_frameCommitQueue.end(), [this](const ImageFrameRequest& frameRequest) {
+ ImageFrame& frame = m_frames[frameRequest.index];
+ if (!frame.isInvalid()) {
+ LOG(Images, "ImageSource::%s - %p - url: %s [decoding has been cancelled for frame %ld]", __FUNCTION__, this, sourceURL().string().utf8().data(), frameRequest.index);
+ frame.clear();
+ }
+ });
+
+ // Close m_frameRequestQueue then set it to nullptr. A new decoding thread might start and a
+ // new m_frameRequestQueue will be created. So the terminating thread will not have access to it.
+ m_frameRequestQueue->close();
+ m_frameRequestQueue = nullptr;
+ m_frameCommitQueue.clear();
+ m_decodingQueue = nullptr;
+ LOG(Images, "ImageSource::%s - %p - url: %s [decoding has been stopped]", __FUNCTION__, this, sourceURL().string().utf8().data());
+}
+
+const ImageFrame& ImageSource::frameAtIndexCacheIfNeeded(size_t index, ImageFrame::Caching caching, const std::optional<SubsamplingLevel>& subsamplingLevel)
+{
+ ASSERT(index < m_frames.size());
+ ImageFrame& frame = m_frames[index];
+ if (!isDecoderAvailable() || frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(index, DecodingMode::Asynchronous))
+ return frame;
+
+ SubsamplingLevel subsamplingLevelValue = subsamplingLevel ? subsamplingLevel.value() : frame.subsamplingLevel();
+
+ switch (caching) {
+ case ImageFrame::Caching::Metadata:
+ // Retrieve the metadata from ImageDecoder if the ImageFrame isn't complete.
+ if (frame.isComplete())
+ break;
+ cacheMetadataAtIndex(index, subsamplingLevelValue);
+ break;
+
+ case ImageFrame::Caching::MetadataAndImage:
+ // Cache the image and retrieve the metadata from ImageDecoder only if there was not valid image stored.
+ if (frame.hasFullSizeNativeImage(subsamplingLevel))
+ break;
+ // We have to perform synchronous image decoding in this code.
+ NativeImagePtr nativeImage = m_decoder->createFrameImageAtIndex(index, subsamplingLevelValue);
+ // Clean the old native image and set a new one.
+ cacheNativeImageAtIndex(WTFMove(nativeImage), index, subsamplingLevelValue, DecodingMode::Synchronous);
+ break;
+ }
+
+ return frame;
+}
+
+void ImageSource::clearMetadata()
+{
+ m_frameCount = std::nullopt;
+ m_repetitionCount = std::nullopt;
+ m_singlePixelSolidColor = std::nullopt;
+ m_encodedDataStatus = std::nullopt;
+ m_uti = std::nullopt;
+}
+
+URL ImageSource::sourceURL() const
+{
+ return m_image ? m_image->sourceURL() : URL();
+}
+
+String ImageSource::mimeType() const
+{
+ return m_image ? m_image->mimeType() : emptyString();
+}
+
+long long ImageSource::expectedContentLength() const
+{
+ return m_image ? m_image->expectedContentLength() : 0;
+}
+
+template<typename T, T (ImageDecoder::*functor)() const>
+T ImageSource::metadata(const T& defaultValue, std::optional<T>* cachedValue)
+{
+ if (cachedValue && *cachedValue)
+ return cachedValue->value();
+
+ if (!isDecoderAvailable() || !m_decoder->isSizeAvailable())
+ return defaultValue;
+
+ if (!cachedValue)
+ return (*m_decoder.*functor)();
+
+ *cachedValue = (*m_decoder.*functor)();
+ didDecodeProperties(m_decoder->bytesDecodedToDetermineProperties());
+ return cachedValue->value();
+}
+
+template<typename T, typename... Args>
+T ImageSource::frameMetadataAtIndex(size_t index, T (ImageFrame::*functor)(Args...) const, Args&&... args)
+{
+ const ImageFrame& frame = index < m_frames.size() ? m_frames[index] : ImageFrame::defaultFrame();
+ return (frame.*functor)(std::forward<Args>(args)...);
+}
+
+template<typename T, typename... Args>
+T ImageSource::frameMetadataAtIndexCacheIfNeeded(size_t index, T (ImageFrame::*functor)() const, std::optional<T>* cachedValue, Args&&... args)
+{
+ if (cachedValue && *cachedValue)
+ return cachedValue->value();
+
+ const ImageFrame& frame = index < m_frames.size() ? frameAtIndexCacheIfNeeded(index, std::forward<Args>(args)...) : ImageFrame::defaultFrame();
+
+ // Don't cache any unavailable frame metadata.
+ if (!frame.hasMetadata() || !cachedValue)
+ return (frame.*functor)();
+
+ *cachedValue = (frame.*functor)();
+ return cachedValue->value();
+}
+
+EncodedDataStatus ImageSource::encodedDataStatus()
+{
+ return metadata<EncodedDataStatus, (&ImageDecoder::encodedDataStatus)>(EncodedDataStatus::Unknown, &m_encodedDataStatus);
+}
+
+size_t ImageSource::frameCount()
+{
+ return metadata<size_t, (&ImageDecoder::frameCount)>(m_frames.size(), &m_frameCount);
+}
+
+RepetitionCount ImageSource::repetitionCount()
+{
+ return metadata<RepetitionCount, (&ImageDecoder::repetitionCount)>(RepetitionCountNone, &m_repetitionCount);
+}
+
+String ImageSource::uti()
+{
+#if USE(CG)
+ return metadata<String, (&ImageDecoder::uti)>(String(), &m_uti);
+#else
+ return String();
+#endif
+}
+
+String ImageSource::filenameExtension()
+{
+ return metadata<String, (&ImageDecoder::filenameExtension)>(String(), &m_filenameExtension);
+}
+
+std::optional<IntPoint> ImageSource::hotSpot()
+{
+ return metadata<std::optional<IntPoint>, (&ImageDecoder::hotSpot)>(std::nullopt, &m_hotSpot);
+}
+
+IntSize ImageSource::size()
+{
+#if !USE(CG)
+ // It's possible that we have decoded the metadata, but not frame contents yet. In that case ImageDecoder claims to
+ // have the size available, but the frame cache is empty. Return the decoder size without caching in such case.
+ if (m_frames.isEmpty() && isDecoderAvailable())
+ return m_decoder->size();
+#endif
+ return frameMetadataAtIndexCacheIfNeeded<IntSize>(0, (&ImageFrame::size), &m_size, ImageFrame::Caching::Metadata, SubsamplingLevel::Default);
+}
+
+IntSize ImageSource::sizeRespectingOrientation()
+{
+ return frameMetadataAtIndexCacheIfNeeded<IntSize>(0, (&ImageFrame::sizeRespectingOrientation), &m_sizeRespectingOrientation, ImageFrame::Caching::Metadata, SubsamplingLevel::Default);
+}
+
+Color ImageSource::singlePixelSolidColor()
+{
+ if (!m_singlePixelSolidColor && (size() != IntSize(1, 1) || frameCount() != 1))
+ m_singlePixelSolidColor = Color();
+
+ if (m_singlePixelSolidColor)
+ return m_singlePixelSolidColor.value();
+
+ return frameMetadataAtIndexCacheIfNeeded<Color>(0, (&ImageFrame::singlePixelSolidColor), &m_singlePixelSolidColor, ImageFrame::Caching::MetadataAndImage);
+}
+
+SubsamplingLevel ImageSource::maximumSubsamplingLevel()
+{
+ if (m_maximumSubsamplingLevel)
+ return m_maximumSubsamplingLevel.value();
+
+ if (!isDecoderAvailable() || !m_decoder->frameAllowSubsamplingAtIndex(0))
+ return SubsamplingLevel::Default;
+
+ // FIXME: this value was chosen to be appropriate for iOS since the image
+ // subsampling is only enabled by default on iOS. Choose a different value
+ // if image subsampling is enabled on other platform.
+ const int maximumImageAreaBeforeSubsampling = 5 * 1024 * 1024;
+ SubsamplingLevel level = SubsamplingLevel::First;
+
+ for (; level < SubsamplingLevel::Last; ++level) {
+ if (frameSizeAtIndex(0, level).area().unsafeGet() < maximumImageAreaBeforeSubsampling)
+ break;
+ }
+
+ m_maximumSubsamplingLevel = level;
+ return m_maximumSubsamplingLevel.value();
+}
+
+bool ImageSource::frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(size_t index, const DecodingOptions& decodingOptions)
+{
+ auto it = std::find_if(m_frameCommitQueue.begin(), m_frameCommitQueue.end(), [index, &decodingOptions](const ImageFrameRequest& frameRequest) {
+ return frameRequest.index == index && frameRequest.decodingOptions.isAsynchronousCompatibleWith(decodingOptions);
+ });
+ return it != m_frameCommitQueue.end();
+}
+
+DecodingStatus ImageSource::frameDecodingStatusAtIndex(size_t index)
+{
+ return frameMetadataAtIndex<DecodingStatus>(index, (&ImageFrame::decodingStatus));
+}
+
+bool ImageSource::frameHasAlphaAtIndex(size_t index)
+{
+ return frameMetadataAtIndex<bool>(index, (&ImageFrame::hasAlpha));
+}
+
+bool ImageSource::frameHasFullSizeNativeImageAtIndex(size_t index, const std::optional<SubsamplingLevel>& subsamplingLevel)
+{
+ return frameMetadataAtIndex<bool>(index, (&ImageFrame::hasFullSizeNativeImage), subsamplingLevel);
+}
+
+bool ImageSource::frameHasDecodedNativeImageCompatibleWithOptionsAtIndex(size_t index, const std::optional<SubsamplingLevel>& subsamplingLevel, const DecodingOptions& decodingOptions)
+{
+ return frameMetadataAtIndex<bool>(index, (&ImageFrame::hasDecodedNativeImageCompatibleWithOptions), subsamplingLevel, decodingOptions);
+}
+
+SubsamplingLevel ImageSource::frameSubsamplingLevelAtIndex(size_t index)
+{
+ return frameMetadataAtIndex<SubsamplingLevel>(index, (&ImageFrame::subsamplingLevel));
+}
+
+IntSize ImageSource::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
+{
+ return frameMetadataAtIndexCacheIfNeeded<IntSize>(index, (&ImageFrame::size), nullptr, ImageFrame::Caching::Metadata, subsamplingLevel);
+}
+
+unsigned ImageSource::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
+{
+ return frameMetadataAtIndexCacheIfNeeded<unsigned>(index, (&ImageFrame::frameBytes), nullptr, ImageFrame::Caching::Metadata, subsamplingLevel);
+}
+
+Seconds ImageSource::frameDurationAtIndex(size_t index)
+{
+ return frameMetadataAtIndexCacheIfNeeded<Seconds>(index, (&ImageFrame::duration), nullptr, ImageFrame::Caching::Metadata);
+}
+
+ImageOrientation ImageSource::frameOrientationAtIndex(size_t index)
+{
+ return frameMetadataAtIndexCacheIfNeeded<ImageOrientation>(index, (&ImageFrame::orientation), nullptr, ImageFrame::Caching::Metadata);
+}
+
+#if USE(DIRECT2D)
+void ImageSource::setTargetContext(const GraphicsContext* targetContext)
+{
+ if (isDecoderAvailable() && targetContext)
+ m_decoder->setTargetContext(targetContext->platformContext())
+}
+#endif
+
+NativeImagePtr ImageSource::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
+{
+ return isDecoderAvailable() ? m_decoder->createFrameImageAtIndex(index, subsamplingLevel) : nullptr;
+}
+
+NativeImagePtr ImageSource::frameImageAtIndex(size_t index)
+{
+ return frameMetadataAtIndex<NativeImagePtr>(index, (&ImageFrame::nativeImage));
+}
+
+NativeImagePtr ImageSource::frameImageAtIndexCacheIfNeeded(size_t index, SubsamplingLevel subsamplingLevel)
+{
+ return frameMetadataAtIndexCacheIfNeeded<NativeImagePtr>(index, (&ImageFrame::nativeImage), nullptr, ImageFrame::Caching::MetadataAndImage, subsamplingLevel);
+}
+
+void ImageSource::dump(TextStream& ts)
+{
+ ts.dumpProperty("type", filenameExtension());
+ ts.dumpProperty("frame-count", frameCount());
+ ts.dumpProperty("repetitions", repetitionCount());
+ ts.dumpProperty("solid-color", singlePixelSolidColor());
+
+ ImageOrientation orientation = frameOrientationAtIndex(0);
+ if (orientation != OriginTopLeft)
+ ts.dumpProperty("orientation", orientation);
+}
+
+}
Copied: trunk/Source/WebCore/platform/graphics/ImageSource.h (from rev 225427, trunk/Source/WebCore/platform/graphics/ImageFrameCache.h) (0 => 225428)
--- trunk/Source/WebCore/platform/graphics/ImageSource.h (rev 0)
+++ trunk/Source/WebCore/platform/graphics/ImageSource.h 2017-12-02 00:01:54 UTC (rev 225428)
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "ImageFrame.h"
+
+#include <wtf/Forward.h>
+#include <wtf/Optional.h>
+#include <wtf/SynchronizedFixedQueue.h>
+#include <wtf/WorkQueue.h>
+#include <wtf/text/TextStream.h>
+
+namespace WebCore {
+
+class GraphicsContext;
+class Image;
+class ImageDecoder;
+class URL;
+
+class ImageSource : public ThreadSafeRefCounted<ImageSource> {
+ friend class BitmapImage;
+public:
+ ImageSource(Image*, AlphaOption = AlphaOption::Premultiplied, GammaAndColorProfileOption = GammaAndColorProfileOption::Applied);
+ ImageSource(NativeImagePtr&&);
+ ~ImageSource();
+
+ static Ref<ImageSource> create(Image* image, AlphaOption alphaOption = AlphaOption::Premultiplied, GammaAndColorProfileOption gammaAndColorProfileOption = GammaAndColorProfileOption::Applied)
+ {
+ return adoptRef(*new ImageSource(image, alphaOption, gammaAndColorProfileOption));
+ }
+
+ static Ref<ImageSource> create(NativeImagePtr&& nativeImage)
+ {
+ return adoptRef(*new ImageSource(WTFMove(nativeImage)));
+ }
+
+ void setData(SharedBuffer* data, bool allDataReceived);
+ void resetData(SharedBuffer* data);
+ EncodedDataStatus dataChanged(SharedBuffer* data, bool allDataReceived);
+ bool isAllDataReceived();
+
+ unsigned decodedSize() const { return m_decodedSize; }
+ void destroyAllDecodedData() { destroyDecodedData(frameCount(), frameCount()); }
+ void destroyAllDecodedDataExcludeFrame(size_t excludeFrame) { destroyDecodedData(frameCount(), excludeFrame); }
+ void destroyDecodedDataBeforeFrame(size_t beforeFrame) { destroyDecodedData(beforeFrame, beforeFrame); }
+ void destroyIncompleteDecodedData();
+ void clearFrameBufferCache(size_t beforeFrame);
+
+ void growFrames();
+ void clearMetadata();
+ void clearImage() { m_image = nullptr; }
+ URL sourceURL() const;
+ String mimeType() const;
+ long long expectedContentLength() const;
+
+ // Asynchronous image decoding
+ bool canUseAsyncDecoding();
+ void startAsyncDecodingQueue();
+ void requestFrameAsyncDecodingAtIndex(size_t, SubsamplingLevel, const std::optional<IntSize>& = { });
+ void stopAsyncDecodingQueue();
+ bool hasAsyncDecodingQueue() const { return m_decodingQueue; }
+ bool isAsyncDecodingQueueIdle() const;
+
+ // Image metadata which is calculated either by the ImageDecoder or directly
+ // from the NativeImage if this class was created for a memory image.
+ EncodedDataStatus encodedDataStatus();
+ bool isSizeAvailable() { return encodedDataStatus() >= EncodedDataStatus::SizeAvailable; }
+ size_t frameCount();
+ RepetitionCount repetitionCount();
+ String uti();
+ String filenameExtension();
+ std::optional<IntPoint> hotSpot();
+
+ // Image metadata which is calculated from the first ImageFrame.
+ IntSize size();
+ IntSize sizeRespectingOrientation();
+ Color singlePixelSolidColor();
+ SubsamplingLevel maximumSubsamplingLevel();
+
+ // ImageFrame metadata which does not require caching the ImageFrame.
+ bool frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(size_t, const DecodingOptions&);
+ DecodingStatus frameDecodingStatusAtIndex(size_t);
+ bool frameHasAlphaAtIndex(size_t);
+ bool frameHasImageAtIndex(size_t);
+ bool frameHasFullSizeNativeImageAtIndex(size_t, const std::optional<SubsamplingLevel>&);
+ bool frameHasDecodedNativeImageCompatibleWithOptionsAtIndex(size_t, const std::optional<SubsamplingLevel>&, const DecodingOptions&);
+ SubsamplingLevel frameSubsamplingLevelAtIndex(size_t);
+
+ // ImageFrame metadata which forces caching or re-caching the ImageFrame.
+ IntSize frameSizeAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
+ unsigned frameBytesAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
+ Seconds frameDurationAtIndex(size_t);
+ ImageOrientation frameOrientationAtIndex(size_t);
+
+#if USE(DIRECT2D)
+ void setTargetContext(const GraphicsContext*);
+#endif
+ NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
+ NativeImagePtr frameImageAtIndex(size_t);
+ NativeImagePtr frameImageAtIndexCacheIfNeeded(size_t, SubsamplingLevel = SubsamplingLevel::Default);
+
+private:
+ template<typename T, T (ImageDecoder::*functor)() const>
+ T metadata(const T& defaultValue, std::optional<T>* cachedValue = nullptr);
+
+ template<typename T, typename... Args>
+ T frameMetadataAtIndex(size_t, T (ImageFrame::*functor)(Args...) const, Args&&...);
+
+ template<typename T, typename... Args>
+ T frameMetadataAtIndexCacheIfNeeded(size_t, T (ImageFrame::*functor)() const, std::optional<T>* cachedValue, Args&&...);
+
+ bool ensureDecoderAvailable(SharedBuffer* data);
+ bool isDecoderAvailable() const { return m_decoder; }
+ void destroyDecodedData(size_t frameCount, size_t excludeFrame);
+ void decodedSizeChanged(long long decodedSize);
+ void didDecodeProperties(unsigned decodedPropertiesSize);
+ void decodedSizeIncreased(unsigned decodedSize);
+ void decodedSizeDecreased(unsigned decodedSize);
+ void decodedSizeReset(unsigned decodedSize);
+
+ void setNativeImage(NativeImagePtr&&);
+ void cacheMetadataAtIndex(size_t, SubsamplingLevel, DecodingStatus = DecodingStatus::Invalid);
+ void cacheNativeImageAtIndex(NativeImagePtr&&, size_t, SubsamplingLevel, const DecodingOptions&, DecodingStatus = DecodingStatus::Invalid);
+ void cacheNativeImageAtIndexAsync(NativeImagePtr&&, size_t, SubsamplingLevel, const DecodingOptions&, DecodingStatus);
+
+ struct ImageFrameRequest;
+ static const int BufferSize = 8;
+ WorkQueue& decodingQueue();
+ SynchronizedFixedQueue<ImageFrameRequest, BufferSize>& frameRequestQueue();
+
+ const ImageFrame& frameAtIndexCacheIfNeeded(size_t, ImageFrame::Caching, const std::optional<SubsamplingLevel>& = { });
+
+ void dump(TextStream&);
+
+ Image* m_image { nullptr };
+ RefPtr<ImageDecoder> m_decoder;
+ AlphaOption m_alphaOption { AlphaOption::Premultiplied };
+ GammaAndColorProfileOption m_gammaAndColorProfileOption { GammaAndColorProfileOption::Applied };
+
+ unsigned m_decodedSize { 0 };
+ unsigned m_decodedPropertiesSize { 0 };
+ Vector<ImageFrame, 1> m_frames;
+
+ // Asynchronous image decoding.
+ struct ImageFrameRequest {
+ size_t index;
+ SubsamplingLevel subsamplingLevel;
+ DecodingOptions decodingOptions;
+ DecodingStatus decodingStatus;
+ bool operator==(const ImageFrameRequest& other) const
+ {
+ return index == other.index && subsamplingLevel == other.subsamplingLevel && decodingOptions == other.decodingOptions && decodingStatus == other.decodingStatus;
+ }
+ };
+ using FrameRequestQueue = SynchronizedFixedQueue<ImageFrameRequest, BufferSize>;
+ using FrameCommitQueue = Deque<ImageFrameRequest, BufferSize>;
+ RefPtr<FrameRequestQueue> m_frameRequestQueue;
+ FrameCommitQueue m_frameCommitQueue;
+ RefPtr<WorkQueue> m_decodingQueue;
+
+ // Image metadata.
+ std::optional<EncodedDataStatus> m_encodedDataStatus;
+ std::optional<size_t> m_frameCount;
+ std::optional<RepetitionCount> m_repetitionCount;
+ std::optional<String> m_uti;
+ std::optional<String> m_filenameExtension;
+ std::optional<std::optional<IntPoint>> m_hotSpot;
+
+ // Image metadata which is calculated from the first ImageFrame.
+ std::optional<IntSize> m_size;
+ std::optional<IntSize> m_sizeRespectingOrientation;
+ std::optional<Color> m_singlePixelSolidColor;
+ std::optional<SubsamplingLevel> m_maximumSubsamplingLevel;
+};
+
+}
Modified: trunk/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp (225427 => 225428)
--- trunk/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp 2017-12-02 00:00:40 UTC (rev 225427)
+++ trunk/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp 2017-12-02 00:01:54 UTC (rev 225428)
@@ -35,7 +35,7 @@
#include "CairoUtilities.h"
#include "GraphicsContext3DPrivate.h"
#include "Image.h"
-#include "ImageFrameCache.h"
+#include "ImageSource.h"
#include "NotImplemented.h"
#include "PlatformContextCairo.h"
#include "RefPtrCairo.h"
@@ -286,14 +286,14 @@
// We need this to stay in scope because the native image is just a shallow copy of the data.
AlphaOption alphaOption = premultiplyAlpha ? AlphaOption::Premultiplied : AlphaOption::NotPremultiplied;
GammaAndColorProfileOption gammaAndColorProfileOption = ignoreGammaAndColorProfile ? GammaAndColorProfileOption::Ignored : GammaAndColorProfileOption::Applied;
- ImageFrameCache decoder(nullptr, alphaOption, gammaAndColorProfileOption);
+ ImageSource source(nullptr, alphaOption, gammaAndColorProfileOption);
m_alphaOp = AlphaDoNothing;
if (m_image->data()) {
- decoder.setData(m_image->data(), true);
- if (!decoder.frameCount())
+ source.setData(m_image->data(), true);
+ if (!source.frameCount())
return false;
- m_imageSurface = decoder.createFrameImageAtIndex(0);
+ m_imageSurface = source.createFrameImageAtIndex(0);
} else {
m_imageSurface = m_image->nativeImageForCurrentFrame();
// 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha had been applied and the alpha value is 0xFF for each pixel,
Modified: trunk/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp (225427 => 225428)
--- trunk/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp 2017-12-02 00:00:40 UTC (rev 225427)
+++ trunk/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp 2017-12-02 00:01:54 UTC (rev 225428)
@@ -325,12 +325,12 @@
return false;
bool hasAlpha = !m_image->currentFrameKnownToBeOpaque();
if ((ignoreGammaAndColorProfile || (hasAlpha && !premultiplyAlpha)) && m_image->data()) {
- ImageFrameCache decoder(nullptr, AlphaOption::NotPremultiplied, ignoreGammaAndColorProfile ? GammaAndColorProfileOption::Ignored : GammaAndColorProfileOption::Applied);
- decoder.setData(m_image->data(), true);
- if (!decoder.frameCount())
+ ImageSource source(nullptr, AlphaOption::NotPremultiplied, ignoreGammaAndColorProfile ? GammaAndColorProfileOption::Ignored : GammaAndColorProfileOption::Applied);
+ source.setData(m_image->data(), true);
+ if (!source.frameCount())
return false;
- m_decodedImage = decoder.createFrameImageAtIndex(0);
+ m_decodedImage = source.createFrameImageAtIndex(0);
m_cgImage = m_decodedImage;
} else
m_cgImage = m_image->nativeImageForCurrentFrame();