WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-90935-20120712145308.patch (text/plain), 90.81 KB, created by
Kwang Yul Seo
on 2012-07-11 22:53:11 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Kwang Yul Seo
Created:
2012-07-11 22:53:11 PDT
Size:
90.81 KB
patch
obsolete
>Subversion Revision: 122269 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 2a0ddf043a8c33b11dc3b8208a9c6fd5577ccfcd..690fcca5c5268c12f20e36cd0c0b6bb83c418007 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,5 +1,199 @@ > 2012-07-10 Huang Dongsung <luxtella@company100.net> > >+ Add parallel image decoders >+ https://bugs.webkit.org/show_bug.cgi?id=90935 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Authored by Huang Dongsung and Kwang Yul Seo. >+ >+ Make image decoding off the main thread, so that the main thread can spend more >+ time in loading, parsing, scripting and layout while image decoding threads decode >+ images in the background. >+ >+ Refer to https://docs.google.com/document/pub?id=12gf7MhNHfupeR3GdRF-h2Vzg86viCbwXq8_JByHKlg0 >+ for detailed explanation. >+ >+ No new tests, covered by existing tests. >+ >+ * CMakeLists.txt: >+ * GNUmakefile.list.am: >+ * Target.pri: >+ * WebCore.gypi: >+ * WebCore.vcproj/WebCore.vcproj: >+ * WebCore.xcodeproj/project.pbxproj: >+ * platform/graphics/BitmapImage.cpp: >+ (WebCore::BitmapImage::BitmapImage): >+ (WebCore::BitmapImage::dataChanged): >+ (WebCore::BitmapImage::ensureFrameIsCached): >+ (WebCore::BitmapImage::cacheFrame): >+ (WebCore::BitmapImage::retainedModeRendering): >+ (WebCore): >+ (WebCore::BitmapImage::didReceiveFrameAtIndex): >+ (WebCore::BitmapImage::frameIsCompleteAtIndex): >+ (WebCore::BitmapImage::currentFrameIsComplete): >+ * platform/graphics/BitmapImage.h: >+ (BitmapImage): BitmapImage now implements ImageSourceObserver and passes itself >+ to ImageSource on construction. When image decoding is finished or a cached image >+ is available, ImageSource notifies BitmapImage via >+ ImageSourceObserver::didReceiveImageFrameData(size_t, const ImageFrameData&). >+ * platform/graphics/ImageSource.cpp: >+ (WebCore): >+ (WebCore::ImageSource::clear): >+ (WebCore::ImageSource::setData): >+ (WebCore::ImageSource::filenameExtension): >+ (WebCore::ImageSource::isSizeAvailable): >+ (WebCore::ImageSource::size): >+ (WebCore::ImageSource::frameSizeAtIndex): >+ (WebCore::ImageSource::repetitionCount): >+ (WebCore::ImageSource::frameCount): >+ (WebCore::ImageSource::requestFrameAtIndex): >+ (WebCore::ImageSource::shouldDecodeParallel): >+ (WebCore::ImageSource::firstFrameIsComplete): >+ (WebCore::ImageSource::parallelDecode): >+ (WebCore::ImageSource::didDecode): >+ (WebCore::ImageSource::createParallelDecoderIfNeeded): >+ (WebCore::ImageSource::clearParallelDecoder): >+ (WebCore::ImageSource::serialDecode): >+ (WebCore::ImageSource::createFrameAtIndex): >+ * platform/graphics/ImageSource.h: >+ (WebCore): >+ (ImageSource): >+ * platform/graphics/ImageSourceObserver.h: >+ (ImageSourceObserver): >+ * platform/graphics/ParallelImageDecoder.cpp: Added. >+ (WebCore): Once RetainedModeBitmapImage and ImageSource decide it is okay to use >+ parallel image decoders, this class intercepts decoding requests from ImageSource >+ and performs image decoding on the decoder thread. Instead of reimplementing all >+ the decoders from scratch, it reuses the existing image decoders. >+ (WebCore::ParallelImageDecoder::ParallelImageDecoder): >+ (WebCore::ParallelImageDecoder::~ParallelImageDecoder): >+ (WebCore::ParallelImageDecoder::initialize): >+ (WebCore::ParallelImageDecoder::invalidate): >+ (WebCore::ParallelImageDecoder::setData): >+ (WebCore::ParallelImageDecoder::decode): >+ (WebCore::ParallelImageDecoder::extractSegmentForTask): >+ (ParallelFrameData): >+ (WebCore::ParallelFrameData::ParallelFrameData): >+ (WebCore::ParallelFrameData::~ParallelFrameData): >+ (WebCore::ParallelImageDecoder::decodeTask): >+ (WebCore::didDecodeTaskCallback): >+ (WebCore::createImageFrameData): >+ (WebCore::ParallelImageDecoder::didDecodeTask): >+ (WebCore::ParallelImageDecoder::didDecodePartial): >+ (WebCore::ParallelImageDecoder::appendDecodedDataToImageFrame): >+ (WebCore::ParallelImageDecoder::syncImageFrame): >+ (WebCore::ParallelImageDecoder::didDecodeComplete): >+ * platform/graphics/ParallelImageDecoder.h: Added. >+ (WebCore): >+ (ParallelImageDecoder): >+ (WebCore::ParallelImageDecoder::filenameExtension): >+ (WebCore::ParallelImageDecoder::size): >+ (WebCore::ParallelImageDecoder::valid): >+ (EncodedDataSegment): >+ (WebCore::ParallelImageDecoder::EncodedDataSegment::EncodedDataSegment): >+ * platform/graphics/ParallelImageDecoderObserver.h: Copied from Source/WebCore/platform/graphics/ImageSourceObserver.h. >+ (WebCore): >+ (ParallelImageDecoderObserver): >+ (WebCore::ParallelImageDecoderObserver::~ParallelImageDecoderObserver): >+ * platform/graphics/RetainedModeBitmapImage.cpp: Added. >+ (WebCore): Because image decoding is used in various contexts in WebKit, it is simply >+ impossible to make all parallel decoding parallel. Instead, we selectively use parallel >+ image decoders where possible and use the existing sequential image decoders otherwise. >+ RetainedModeBitmapImage wraps a BitmapImage and helps decide when it is safe and beneficial >+ to use parallel image decoders. >+ (WebCore::RetainedModeBitmapImage::create): >+ (WebCore::RetainedModeBitmapImage::RetainedModeBitmapImage): >+ (WebCore::RetainedModeBitmapImage::hasSingleSecurityOrigin): >+ (WebCore::RetainedModeBitmapImage::size): >+ (WebCore::RetainedModeBitmapImage::getHotSpot): >+ (WebCore::RetainedModeBitmapImage::dataChanged): >+ (WebCore::RetainedModeBitmapImage::filenameExtension): >+ (WebCore::RetainedModeBitmapImage::destroyDecodedData): >+ (WebCore::RetainedModeBitmapImage::decodedSize): >+ (WebCore::RetainedModeBitmapImage::startAnimation): >+ (WebCore::RetainedModeBitmapImage::stopAnimation): >+ (WebCore::RetainedModeBitmapImage::resetAnimation): >+ (WebCore::RetainedModeBitmapImage::nativeImageForCurrentFrame): >+ (WebCore::RetainedModeBitmapImage::currentFrameHasAlpha): >+ (WebCore::RetainedModeBitmapImage::currentFrameIsComplete): >+ (WebCore::RetainedModeBitmapImage::draw): >+ (WebCore::RetainedModeBitmapImage::mayFillWithSolidColor): >+ (WebCore::RetainedModeBitmapImage::solidColor): >+ (WebCore::RetainedModeSaver::RetainedModeSaver): >+ (WebCore::RetainedModeSaver::~RetainedModeSaver): >+ (WebCore::toRetainedModeBitmapImage): >+ (WebCore::toRetainedModeBitmapImageIfPossible): >+ * platform/graphics/RetainedModeBitmapImage.h: Added. >+ (WebCore): >+ (RetainedModeBitmapImage): >+ (WebCore::RetainedModeBitmapImage::~RetainedModeBitmapImage): >+ (WebCore::RetainedModeBitmapImage::retainedModeRendering): >+ (WebCore::RetainedModeBitmapImage::beginRetainedMode): >+ (WebCore::RetainedModeBitmapImage::endRetainedMode): >+ (RetainedModeSaver): >+ * platform/graphics/cairo/BitmapImageCairo.cpp: >+ (WebCore::BitmapImage::BitmapImage): >+ * platform/graphics/cairo/GraphicsContext3DCairo.cpp: >+ (WebCore::GraphicsContext3D::getImageData): >+ * platform/graphics/cg/GraphicsContext3DCG.cpp: >+ (WebCore::GraphicsContext3D::getImageData): >+ * platform/graphics/cg/ImageCG.cpp: >+ (WebCore::BitmapImage::BitmapImage): >+ * platform/graphics/cg/ImageSourceCG.cpp: >+ (WebCore::ImageSource::requestFrameAtIndex): >+ * platform/graphics/openvg/ImageOpenVG.cpp: >+ (WebCore::BitmapImage::BitmapImage): >+ * platform/graphics/qt/ImageQt.cpp: >+ (WebCore::BitmapImage::BitmapImage): >+ * platform/graphics/skia/GraphicsContext3DSkia.cpp: >+ (WebCore::GraphicsContext3D::getImageData): >+ * platform/graphics/wx/ImageWx.cpp: >+ (WebCore::BitmapImage::BitmapImage): >+ * platform/image-decoders/ImageDecoder.cpp: >+ (WebCore::ImageFrame::ImageFrame): >+ (WebCore::ImageFrame::clearPixelData): >+ (WebCore::ImageFrame::copyBitmapData): >+ (WebCore::ImageFrame::setSize): >+ * platform/image-decoders/ImageDecoder.h: >+ (WebCore::ImageFrame::lastDecodedRow): >+ (WebCore::ImageFrame::setLastDecodedRow): >+ (ImageFrame): >+ (WebCore::ImageDecoder::data): >+ (ImageDecoder): >+ (WebCore::ImageDecoder::firstImageFrameWithoutDecode): >+ * platform/image-decoders/blackberry/JPEGImageDecoder.cpp: >+ (WebCore::ImageReader::decode): >+ * platform/image-decoders/bmp/BMPImageDecoder.cpp: >+ (WebCore::BMPImageDecoder::isSizeAvailable): >+ * platform/image-decoders/bmp/BMPImageReader.cpp: >+ (WebCore::BMPImageReader::decodeBMP): >+ (WebCore::BMPImageReader::processRLEData): >+ (WebCore::BMPImageReader::processNonRLEData): >+ * platform/image-decoders/gif/GIFImageDecoder.cpp: >+ (WebCore::GIFImageDecoder::haveDecodedRow): >+ (WebCore::GIFImageDecoder::initFrameBuffer): >+ * platform/image-decoders/jpeg/JPEGImageDecoder.cpp: >+ (WebCore::JPEGImageDecoder::outputScanlines): >+ * platform/image-decoders/png/PNGImageDecoder.cpp: >+ (WebCore::PNGImageDecoder::rowAvailable): >+ * platform/image-decoders/skia/ImageDecoderSkia.cpp: >+ (WebCore::ImageFrame::clearPixelData): >+ (WebCore::ImageFrame::copyBitmapData): >+ (WebCore::ImageFrame::setSize): >+ * platform/image-decoders/webp/WEBPImageDecoder.cpp: >+ (WebCore::WEBPImageDecoder::decode): >+ * rendering/RenderImage.cpp: >+ (WebCore::RenderImage::paintReplaced): >+ (WebCore::RenderImage::paintIntoRect): >+ (WebCore::RenderImage::backgroundIsObscured): >+ * rendering/RenderLayerBacking.cpp: >+ (WebCore::RenderLayerBacking::updateImageContents): >+ * rendering/svg/RenderSVGImage.cpp: >+ (WebCore::RenderSVGImage::paint): >+ >+2012-07-10 Huang Dongsung <luxtella@company100.net> >+ > Refactoring metadata of BitmapImage. > https://bugs.webkit.org/show_bug.cgi?id=90758 > >diff --git a/Source/WebKit/chromium/ChangeLog b/Source/WebKit/chromium/ChangeLog >index d2d2b97e551658e3613bec9981095f58449321ba..4dbc4f95a905babfac9cbefedf2daa50d3af8fdd 100644 >--- a/Source/WebKit/chromium/ChangeLog >+++ b/Source/WebKit/chromium/ChangeLog >@@ -1,3 +1,24 @@ >+2012-07-10 Huang Dongsung <luxtella@company100.net> >+ >+ Add parallel image decoders >+ https://bugs.webkit.org/show_bug.cgi?id=90935 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Authored by Huang Dongsung and Kwang Yul Seo. >+ >+ Make image decoding off the main thread, so that the main thread can spend more >+ time in loading, parsing, scripting and layout while image decoding threads decode >+ images in the background. >+ >+ Refer to https://docs.google.com/document/pub?id=12gf7MhNHfupeR3GdRF-h2Vzg86viCbwXq8_JByHKlg0 >+ for detailed explanation. >+ >+ * src/WebImageCG.cpp: >+ (WebKit::WebImage::fromData): >+ * src/WebImageSkia.cpp: >+ (WebKit::WebImage::fromData): >+ > 2012-07-03 Huang Dongsung <luxtella@company100.net> > > Prepare for parallel image decoder. >diff --git a/Source/WebCore/CMakeLists.txt b/Source/WebCore/CMakeLists.txt >index 6d17219f064462061de5770956142e22d6a7053e..93216415204d4e3a60b4e67e9235c28f9988a112 100644 >--- a/Source/WebCore/CMakeLists.txt >+++ b/Source/WebCore/CMakeLists.txt >@@ -1200,6 +1200,8 @@ SET(WebCore_SOURCES > platform/graphics/Path.cpp > platform/graphics/PathTraversalState.cpp > platform/graphics/Pattern.cpp >+ platform/graphics/ParallelImageDecoder.cpp >+ platform/graphics/RetainedModeBitmapImage.cpp > platform/graphics/Region.cpp > platform/graphics/RoundedRect.cpp > platform/graphics/SegmentedFontData.cpp >diff --git a/Source/WebCore/GNUmakefile.list.am b/Source/WebCore/GNUmakefile.list.am >index 68224a8468ec30becc15db4412bddd46db2dde05..4c6be3198ced47a96f0c5e71461eb94d171b2e5e 100644 >--- a/Source/WebCore/GNUmakefile.list.am >+++ b/Source/WebCore/GNUmakefile.list.am >@@ -3193,6 +3193,11 @@ webcore_sources += \ > Source/WebCore/platform/graphics/ColorSpace.h \ > Source/WebCore/platform/graphics/DashArray.h \ > Source/WebCore/platform/graphics/Extensions3D.h \ >+ Source/WebCore/platform/graphics/ParallelImageDecoder.cpp \ >+ Source/WebCore/platform/graphics/ParallelImageDecoder.h \ >+ Source/WebCore/platform/graphics/ParallelImageDecoderObserver.h \ >+ Source/WebCore/platform/graphics/RetainedModeBitmapImage.cpp \ >+ Source/WebCore/platform/graphics/RetainedModeBitmapImage.h \ > Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp \ > Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp \ > Source/WebCore/platform/graphics/cairo/CairoUtilities.h \ >diff --git a/Source/WebCore/Target.pri b/Source/WebCore/Target.pri >index 016d70da63060e6b4123f7586129054ab99fcc97..1780ea3cab672e92663b42f4c3f7347daacfda1f 100644 >--- a/Source/WebCore/Target.pri >+++ b/Source/WebCore/Target.pri >@@ -1103,6 +1103,7 @@ SOURCES += \ > platform/graphics/FontFamily.cpp \ > platform/graphics/FontFeatureSettings.cpp \ > platform/graphics/BitmapImage.cpp \ >+ platform/graphics/RetainedModeBitmapImage.cpp \ > platform/graphics/Color.cpp \ > platform/graphics/CrossfadeGeneratedImage.cpp \ > platform/graphics/FloatPoint3D.cpp \ >@@ -1126,6 +1127,7 @@ SOURCES += \ > platform/graphics/ImageOrientation.cpp \ > platform/graphics/ImageSource.cpp \ > platform/graphics/IntRect.cpp \ >+ platform/graphics/ParallelImageDecoder.cpp \ > platform/graphics/Path.cpp \ > platform/graphics/PathTraversalState.cpp \ > platform/graphics/Pattern.cpp \ >@@ -2241,6 +2243,7 @@ HEADERS += \ > platform/mock/GeolocationClientMock.cpp \ > platform/mock/ScrollbarThemeMock.h \ > platform/graphics/BitmapImage.h \ >+ platform/graphics/RetainedModeBitmapImage.h \ > platform/graphics/Color.h \ > platform/graphics/CrossfadeGeneratedImage.h \ > platform/graphics/filters/CustomFilterGlobalContext.h \ >@@ -2307,6 +2310,8 @@ HEADERS += \ > platform/graphics/IntPointHash.h \ > platform/graphics/IntRect.h \ > platform/graphics/MediaPlayer.h \ >+ platform/graphics/ParallelImageDecoder.h \ >+ platform/graphics/ParallelImageDecoderObserver.h \ > platform/graphics/Path.h \ > platform/graphics/PathTraversalState.h \ > platform/graphics/Pattern.h \ >diff --git a/Source/WebCore/WebCore.gypi b/Source/WebCore/WebCore.gypi >index ba12baf2fd76c82b22bd9ba6b5e5cfc6ef162727..acbf840ff5c59a9795681724fd59e835ea58438a 100644 >--- a/Source/WebCore/WebCore.gypi >+++ b/Source/WebCore/WebCore.gypi >@@ -3503,11 +3503,16 @@ > 'platform/graphics/IntRect.cpp', > 'platform/graphics/MediaPlayer.cpp', > 'platform/graphics/MediaPlayerPrivate.h', >+ 'platform/graphics/ParallelImageDecoder.cpp', >+ 'platform/graphics/ParallelImageDecoder.h', >+ 'platform/graphics/ParallelImageDecoderObserver.h', > 'platform/graphics/Path.cpp', > 'platform/graphics/PathTraversalState.cpp', > 'platform/graphics/PathTraversalState.h', > 'platform/graphics/Pattern.cpp', > 'platform/graphics/Region.cpp', >+ 'platform/graphics/RetainedModeBitmapImage.cpp', >+ 'platform/graphics/RetainedModeBitmapImage.h', > 'platform/graphics/RoundedRect.cpp', > 'platform/graphics/SegmentedFontData.cpp', > 'platform/graphics/SegmentedFontData.h', >diff --git a/Source/WebCore/WebCore.vcproj/WebCore.vcproj b/Source/WebCore/WebCore.vcproj/WebCore.vcproj >index 5a107b1ab6f711bc6bc4549736eba93d8268be0c..654dfba3549323d9f4773b8b9fb88f8cedb13cbe 100755 >--- a/Source/WebCore/WebCore.vcproj/WebCore.vcproj >+++ b/Source/WebCore/WebCore.vcproj/WebCore.vcproj >@@ -29398,6 +29398,18 @@ > > > </File> > <File >+ RelativePath="..\platform\graphics\ParallelImageDecoder.cpp" >+ > >+ </File> >+ <File >+ RelativePath="..\platform\graphics\ParallelImageDecoder.h" >+ > >+ </File> >+ <File >+ RelativePath="..\platform\graphics\ParallelImageDecoderObserver.h" >+ > >+ </File> >+ <File > RelativePath="..\platform\graphics\PathTraversalState.cpp" > > > </File> >@@ -29426,6 +29438,14 @@ > > > </File> > <File >+ RelativePath="..\platform\graphics\RetainedModeBitmapImage.cpp" >+ > >+ </File> >+ <File >+ RelativePath="..\platform\graphics\RetainedModeBitmapImage.h" >+ > >+ </File> >+ <File > RelativePath="..\platform\graphics\RoundedRect.cpp" > > > </File> >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index 566676c5b944fdd7a384787d59cff5e5e582056c..245c6e6ca28720b960dc6ec3292ad6db4d1a248c 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -1418,6 +1418,8 @@ > 4B3043CD0AE0373B00A82647 /* Editor.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B3043CB0AE0373B00A82647 /* Editor.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 4B3480930EEF50D400AC1B41 /* ImageSourceCGMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B3480910EEF50D400AC1B41 /* ImageSourceCGMac.mm */; }; > 4B3480940EEF50D400AC1B41 /* ImageSourceCG.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B3480920EEF50D400AC1B41 /* ImageSourceCG.h */; }; >+ 5B3480930EEF50D400AC1B41 /* RetainedModeBitmapImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5B3480910EEF50D400AC1B41 /* RetainedModeBitmapImage.cpp */; }; >+ 5B3480940EEF50D400AC1B41 /* RetainedModeBitmapImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B3480920EEF50D400AC1B41 /* RetainedModeBitmapImage.h */; }; > 4B6FA6F40C39E48C00087011 /* SmartReplace.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B6FA6F20C39E48C00087011 /* SmartReplace.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 4B6FA6F50C39E48C00087011 /* SmartReplace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6FA6F30C39E48C00087011 /* SmartReplace.cpp */; }; > 4B6FA6F70C39E4A100087011 /* SmartReplaceCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6FA6F60C39E4A100087011 /* SmartReplaceCF.cpp */; }; >@@ -8510,6 +8512,8 @@ > 4B3043CB0AE0373B00A82647 /* Editor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Editor.h; sourceTree = "<group>"; }; > 4B3480910EEF50D400AC1B41 /* ImageSourceCGMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ImageSourceCGMac.mm; sourceTree = "<group>"; }; > 4B3480920EEF50D400AC1B41 /* ImageSourceCG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageSourceCG.h; sourceTree = "<group>"; }; >+ 5B3480910EEF50D400AC1B41 /* RetainedModeBitmapImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RetainedModeBitmapImage.cpp; sourceTree = "<group>"; }; >+ 5B3480920EEF50D400AC1B41 /* RetainedModeBitmapImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RetainedModeBitmapImage.h; sourceTree = "<group>"; }; > 4B6FA6F20C39E48C00087011 /* SmartReplace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SmartReplace.h; sourceTree = "<group>"; }; > 4B6FA6F30C39E48C00087011 /* SmartReplace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SmartReplace.cpp; sourceTree = "<group>"; }; > 4B6FA6F60C39E4A100087011 /* SmartReplaceCF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SmartReplaceCF.cpp; sourceTree = "<group>"; }; >@@ -19538,6 +19542,8 @@ > A80A38FD0E50CC8200A25EBC /* PatternCG.cpp */, > B27535360B053814002CE64F /* PDFDocumentImage.cpp */, > B27535370B053814002CE64F /* PDFDocumentImage.h */, >+ 5B3480910EEF50D400AC1B41 /* RetainedModeBitmapImage.cpp */, >+ 5B3480920EEF50D400AC1B41 /* RetainedModeBitmapImage.h */, > B275352A0B053814002CE64F /* TransformationMatrixCG.cpp */, > ); > path = cg; >@@ -24476,6 +24482,7 @@ > 7EE6846F12D26E3800E79415 /* ResourceRequestCFNet.h in Headers */, > 7EE6847012D26E3800E79415 /* ResourceResponse.h in Headers */, > 514C767F0CE923A1007EF3CD /* ResourceResponseBase.h in Headers */, >+ 5B3480940EEF50D400AC1B41 /* RetainedModeBitmapImage.h in Headers */, > FD3160A512B026F700C1A359 /* Reverb.h in Headers */, > FD3160A712B026F700C1A359 /* ReverbAccumulationBuffer.h in Headers */, > FD3160A912B026F700C1A359 /* ReverbConvolver.h in Headers */, >@@ -27655,6 +27662,7 @@ > 514C767E0CE923A1007EF3CD /* ResourceResponseBase.cpp in Sources */, > 7EE6847112D26E3800E79415 /* ResourceResponseCFNet.cpp in Sources */, > 514C76550CE9234F007EF3CD /* ResourceResponseMac.mm in Sources */, >+ 5B3480930EEF50D400AC1B41 /* RetainedModeBitmapImage.cpp in Sources */, > FD3160A412B026F700C1A359 /* Reverb.cpp in Sources */, > FD3160A612B026F700C1A359 /* ReverbAccumulationBuffer.cpp in Sources */, > FD3160A812B026F700C1A359 /* ReverbConvolver.cpp in Sources */, >diff --git a/Source/WebCore/platform/graphics/BitmapImage.cpp b/Source/WebCore/platform/graphics/BitmapImage.cpp >index 3276800ca52603dfb4d4c619913d1b3469034bcd..803e29d1412155b1c9ecd41b67ea734060c481b2 100644 >--- a/Source/WebCore/platform/graphics/BitmapImage.cpp >+++ b/Source/WebCore/platform/graphics/BitmapImage.cpp >@@ -64,6 +64,7 @@ BitmapImage::BitmapImage(ImageObserver* observer) > , m_sizeAvailable(false) > , m_hasUniformFrameSize(true) > , m_haveFrameCount(false) >+ , m_isCachingFrame(false) > { > } > >@@ -208,7 +209,12 @@ bool BitmapImage::dataChanged(bool allDataReceived) > // NOTE: Don't call frameIsCompleteAtIndex() here, that will try to > // decode any uncached (i.e. never-decoded or > // cleared-on-a-previous-pass) frames! >- if (m_frames[i].m_frame && !m_frames[i].m_isComplete) >+ >+ // NOTE: Don't clear the current frame, because the frame might have been decoded >+ // in retained mode and RenderImage hasn't render this decoded image yet. >+ // If the current frame is removed here, the image element will be rendered as white box. >+ // The current frame will be removed later when retained mode decoding is finished. >+ if (m_frames[i].m_frame && !m_frames[i].m_isComplete && m_currentFrame != i) > framesCleared += (m_frames[i].clear(true) ? 1 : 0); > } > destroyMetadataAndNotify(framesCleared); >@@ -256,8 +262,18 @@ bool BitmapImage::ensureFrameIsCached(size_t index) > if (index >= frameCount()) > return false; > >- if (index >= m_frames.size() || !m_frames[index].m_frame) >+ if (m_isCachingFrame) >+ return true; >+ >+ // m_frame can exist when m_isComplete is false, so we need to cache a new frame even if m_frame exists. >+ // See BitmapImage::dataChanged for explanation. >+ bool needToCache = index >= m_frames.size() || !m_frames[index].m_frame || !m_frames[index].m_isComplete; >+ if (needToCache) { >+ m_isCachingFrame = true; > cacheFrame(index); >+ m_isCachingFrame = false; >+ } >+ > return true; > } > >@@ -267,11 +283,27 @@ void BitmapImage::cacheFrame(size_t index) > if (m_frames.size() < numFrames) > m_frames.grow(numFrames); > >- m_source.requestFrameAtIndex(index); >+ m_source.requestFrameAtIndex(index, retainedModeRendering()); > } > >-void BitmapImage::didReceiveFrameAtIndex(size_t index, const ImageFrameData& imageFrameData) >+bool BitmapImage::retainedModeRendering() const > { >+ return m_retainedModeImage.get() && m_retainedModeImage->retainedModeRendering(); >+} >+ >+void BitmapImage::didReceiveFrameAtIndex(size_t index, const ImageFrameData& imageFrameData, bool retained, bool parallelDecoderCanceled) >+{ >+ // It is possible to call cacheFrame indirectly in this method. >+ RetainedModeSaver retainedModeSaver(m_retainedModeImage.get(), retained); >+ >+ // m_frames[index].m_frame must be cleared before it is replaced with new decoded frame. >+ // If we forget to clear m_frame, the old m_frame leaks. >+ // See BitmapImage::dataChanged for explanation why the decoded frame must be removed here. >+ int framesCleared = 0; >+ if (m_frames[index].m_frame) >+ framesCleared += (m_frames[index].clear(true) ? 1 : 0); >+ destroyMetadataAndNotify(framesCleared); >+ > m_frames[index].setFromImageFrameData(imageFrameData); > > size_t numFrames = frameCount(); >@@ -288,8 +320,12 @@ void BitmapImage::didReceiveFrameAtIndex(size_t index, const ImageFrameData& ima > // to determine image properties. > deltaBytes -= m_decodedPropertiesSize; > m_decodedPropertiesSize = 0; >- if (imageObserver()) >+ if (imageObserver()) { > imageObserver()->decodedSizeChanged(this, deltaBytes); >+ >+ if ((m_frames[index].m_isComplete && retained) || parallelDecoderCanceled) >+ imageObserver()->changedInRect(this, IntRect(IntPoint(), size())); >+ } > } > } > >@@ -309,7 +345,13 @@ bool BitmapImage::frameIsCompleteAtIndex(size_t index) > // (see destroyDecodedData() and frameDurationAtIndex()) > if (!ensureFrameIsCached(index)) > return false; >- return m_frames[index].m_isComplete; >+ // If the frame at the given index is decoded by parallel image decoders, m_frame can be 0 even if m_isComplete is true. >+ return m_frames[index].m_isComplete && m_frames[index].m_frame; >+} >+ >+bool BitmapImage::currentFrameIsComplete() >+{ >+ return frameIsCompleteAtIndex(m_currentFrame); > } > > float BitmapImage::frameDurationAtIndex(size_t index) >diff --git a/Source/WebCore/platform/graphics/BitmapImage.h b/Source/WebCore/platform/graphics/BitmapImage.h >index 8177273dcf90dc5c04355776025f2669a05121b5..8cbc6545537091fb6bc55c55f6e0937879675f3d 100644 >--- a/Source/WebCore/platform/graphics/BitmapImage.h >+++ b/Source/WebCore/platform/graphics/BitmapImage.h >@@ -33,6 +33,7 @@ > #include "ImageOrientation.h" > #include "ImageSourceObserver.h" > #include "IntSize.h" >+#include "RetainedModeBitmapImage.h" > > #if PLATFORM(MAC) > #include <wtf/RetainPtr.h> >@@ -120,10 +121,12 @@ private: > // ================================================= > > class BitmapImage : public Image, public ImageSourceObserver { >+ friend class RetainedModeBitmapImage; > friend class GeneratedImage; > friend class CrossfadeGeneratedImage; > friend class GeneratorGeneratedImage; > friend class GraphicsContext; >+ friend RetainedModeBitmapImage* toRetainedModeBitmapImage(Image*); > public: > static PassRefPtr<BitmapImage> create(NativeImagePtr nativeImage, ImageObserver* observer = 0) > { >@@ -201,7 +204,7 @@ public: > #endif > > // ImageSourceObserver >- virtual void didReceiveFrameAtIndex(size_t, const ImageFrameData&); >+ virtual void didReceiveFrameAtIndex(size_t, const ImageFrameData&, bool retained = false, bool parallelDecoderCanceled = false); > > private: > void updateSize() const; >@@ -238,6 +241,8 @@ protected: > bool frameIsCompleteAtIndex(size_t); > float frameDurationAtIndex(size_t); > >+ bool currentFrameIsComplete(); >+ > // Decodes and caches a frame. Never accessed except internally. > void cacheFrame(size_t index); > // Called before accessing m_frames[index]. Returns false on index out of bounds. >@@ -293,6 +298,8 @@ protected: > virtual bool mayFillWithSolidColor(); > virtual Color solidColor() const; > >+ bool retainedModeRendering() const; >+ > ImageSource m_source; > mutable IntSize m_size; // The size to use for the overall image (will just be the size of the first image). > mutable IntSize m_sizeRespectingOrientation; >@@ -317,6 +324,8 @@ protected: > mutable unsigned m_decodedPropertiesSize; // The size of data decoded by the source to determine image properties (e.g. size, frame count, etc). > size_t m_frameCount; > >+ RefPtr<RetainedModeBitmapImage> m_retainedModeImage; >+ > bool m_isSolidColor : 1; // Whether or not we are a 1x1 solid image. > bool m_checkedForSolidColor : 1; // Whether we've checked the frame for solid color. > >@@ -327,6 +336,8 @@ protected: > bool m_sizeAvailable : 1; // Whether or not we can obtain the size of the first image frame yet from ImageIO. > mutable bool m_hasUniformFrameSize : 1; > mutable bool m_haveFrameCount : 1; >+ >+ bool m_isCachingFrame : 1; > }; > > } >diff --git a/Source/WebCore/platform/graphics/ImageSource.cpp b/Source/WebCore/platform/graphics/ImageSource.cpp >index 020334ecfdd56ceda46e7aa9e321eef1592d4391..1099db5cacabe604267c98c3c755d4d1cd7d6688 100644 >--- a/Source/WebCore/platform/graphics/ImageSource.cpp >+++ b/Source/WebCore/platform/graphics/ImageSource.cpp >@@ -35,9 +35,13 @@ > #include "ImageOrientation.h" > #include "ImageSourceObserver.h" > #include "NotImplemented.h" >+#include "ParallelImageDecoder.h" >+#include <wtf/NumberOfCores.h> > > namespace WebCore { > >+static const unsigned s_resolutionThresholdForParallel = 512 * 512; >+ > #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) > unsigned ImageSource::s_maxPixelsPerDecodedImage = 1024 * 1024; > #endif >@@ -66,11 +70,15 @@ ImageSource::~ImageSource() > void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived) > { > if (!destroyAll) { >- if (m_decoder) >+ // Only GIF decoder implements clearFrameBufferCache. >+ if (m_decoder && !m_parallelDecoder) > m_decoder->clearFrameBufferCache(clearBeforeFrame); > return; > } > >+ if (m_parallelDecoder.get()) >+ clearParallelDecoder(); >+ > delete m_decoder; > m_decoder = 0; > if (data) >@@ -88,6 +96,13 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived) > // This method will examine the data and instantiate an instance of the appropriate decoder plugin. > // If insufficient bytes are available to determine the image type, no decoder plugin will be > // made. >+ >+ if (m_parallelDecoder.get()) { >+ ASSERT(m_decoder); >+ m_parallelDecoder->setData(data, allDataReceived); >+ return; >+ } >+ > if (!m_decoder) { > m_decoder = static_cast<NativeImageSourcePtr>(ImageDecoder::create(*data, m_alphaOption, m_gammaAndColorProfileOption)); > #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) >@@ -102,11 +117,15 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived) > > String ImageSource::filenameExtension() const > { >+ if (m_parallelDecoder.get()) >+ return m_parallelDecoder->filenameExtension(); > return m_decoder ? m_decoder->filenameExtension() : String(); > } > > bool ImageSource::isSizeAvailable() > { >+ if (m_parallelDecoder.get()) >+ return true; > return m_decoder && m_decoder->isSizeAvailable(); > } > >@@ -116,6 +135,8 @@ IntSize ImageSource::size(RespectImageOrientationEnum shouldRespectOrientation) > if (shouldRespectOrientation == RespectImageOrientation) > notImplemented(); > >+ if (m_parallelDecoder.get()) >+ return m_parallelDecoder->size(); > return m_decoder ? m_decoder->size() : IntSize(); > } > >@@ -125,6 +146,8 @@ IntSize ImageSource::frameSizeAtIndex(size_t index, RespectImageOrientationEnum > if (shouldRespectOrientation == RespectImageOrientation) > notImplemented(); > >+ if (m_parallelDecoder.get()) >+ return m_parallelDecoder->size(); > return m_decoder ? m_decoder->frameSizeAtIndex(index) : IntSize(); > } > >@@ -140,23 +163,120 @@ size_t ImageSource::bytesDecodedToDetermineProperties() const > > int ImageSource::repetitionCount() > { >+ if (m_parallelDecoder.get()) >+ return cAnimationNone; > return m_decoder ? m_decoder->repetitionCount() : cAnimationNone; > } > > size_t ImageSource::frameCount() const > { >+ if (m_parallelDecoder.get()) >+ return 1; > return m_decoder ? m_decoder->frameCount() : 0; > } > >-void ImageSource::requestFrameAtIndex(size_t index) >+ImageFrameData ImageSource::requestFrameAtIndex(size_t index, bool retainedModeRendering) >+{ >+ ASSERT(!(retainedModeRendering && index)); >+ ASSERT(!(retainedModeRendering && !m_observer)); >+ >+ if (!m_decoder) { >+ m_observer->didReceiveFrameAtIndex(index, ImageFrameData()); >+ return ImageFrameData(); >+ } >+ >+ if (!retainedModeRendering || !m_observer || firstFrameIsComplete()) >+ return serialDecode(index); >+ >+ if (shouldDecodeParallel()) { >+ parallelDecode(); >+ return ImageFrameData(); >+ } >+ >+ return serialDecode(index); >+} >+ >+bool ImageSource::shouldDecodeParallel() >+{ >+ ASSERT(m_decoder); >+ >+ if (m_parallelDecoder.get()) >+ return true; >+ >+ if (WTF::numberOfProcessorCores() == 1) >+ return false; >+ >+ String fileExt = filenameExtension(); >+ if (fileExt == "ico" || fileExt == "gif") >+ return false; >+ >+ if (!isSizeAvailable()) >+ return false; >+ >+ if (size().area() < s_resolutionThresholdForParallel) >+ return false; >+ >+ return true; >+} >+ >+bool ImageSource::firstFrameIsComplete() >+{ >+ ASSERT(m_decoder); >+ ImageFrame* imageFrame = 0; >+ if (!m_parallelDecoder) >+ imageFrame = m_decoder->firstImageFrameWithoutDecode(); >+ return imageFrame && frameIsCompleteAtIndex(imageFrame); >+} >+ >+void ImageSource::parallelDecode() >+{ >+ createParallelDecoderIfNeeded(); >+ m_parallelDecoder->decode(); >+} >+ >+void ImageSource::didDecode(const ImageFrameData& imageFrameData) >+{ >+ ASSERT(m_observer); >+ m_observer->didReceiveFrameAtIndex(0, imageFrameData, true); >+ >+ if (imageFrameData.m_isComplete) >+ clearParallelDecoder(); >+} >+ >+void ImageSource::createParallelDecoderIfNeeded() >+{ >+ if (!m_parallelDecoder) >+ m_parallelDecoder = adoptRef(new ParallelImageDecoder(this, m_decoder)); >+} >+ >+void ImageSource::clearParallelDecoder() > { > ASSERT(m_observer); >+ m_parallelDecoder->invalidate(); >+ m_parallelDecoder.clear(); >+} >+ >+ImageFrameData ImageSource::serialDecode(size_t index) >+{ >+ bool parallelDecoderCanceled = false; >+ // RenderImage and CanvasElement can share the same CachedImage. >+ if (m_parallelDecoder.get()) { >+ ASSERT(m_observer); >+ clearParallelDecoder(); >+ parallelDecoderCanceled = true; >+ } >+ > ImageFrameData imageFrameData = createFrameAtIndex(index); >- m_observer->didReceiveFrameAtIndex(index, imageFrameData); >+ >+ if (m_observer) >+ m_observer->didReceiveFrameAtIndex(index, imageFrameData, false /* retainedMode */, parallelDecoderCanceled); >+ >+ return imageFrameData; > } > > ImageFrameData ImageSource::createFrameAtIndex(size_t index) > { >+ ASSERT(!m_parallelDecoder); > if (!m_decoder) > return ImageFrameData(); > >diff --git a/Source/WebCore/platform/graphics/ImageSource.h b/Source/WebCore/platform/graphics/ImageSource.h >index 7b9c0205651c2a9e185637545ed4383bbdb05e0c..f04d73472593e80805b0bb9ff742c0a073b968c4 100644 >--- a/Source/WebCore/platform/graphics/ImageSource.h >+++ b/Source/WebCore/platform/graphics/ImageSource.h >@@ -29,6 +29,9 @@ > #define ImageSource_h > > #include "ImageOrientation.h" >+#if !USE(CG) >+#include "ParallelImageDecoderObserver.h" >+#endif > > #include <wtf/Forward.h> > #include <wtf/Noncopyable.h> >@@ -65,6 +68,9 @@ class ImageOrientation; > class ImageSourceObserver; > class IntPoint; > class IntSize; >+#if !USE(CG) >+class ParallelImageDecoder; >+#endif > class SharedBuffer; > > #if USE(CG) >@@ -143,7 +149,11 @@ const int cAnimationLoopOnce = 0; > const int cAnimationLoopInfinite = -1; > const int cAnimationNone = -2; > >-class ImageSource { >+class ImageSource >+#if !USE(CG) >+ : public ParallelImageDecoderObserver >+#endif >+{ > WTF_MAKE_NONCOPYABLE(ImageSource); > public: > enum AlphaOption { >@@ -210,17 +220,24 @@ public: > > size_t frameCount() const; > >- // Callers should not call this after calling clear() with a higher index; >+ // NOTE: Callers should not call this after calling clear() with a higher index; > // see comments on clear() above. >- void requestFrameAtIndex(size_t); >- ImageFrameData createFrameAtIndex(size_t); >+ // NOTE: If ImageSource has ImageSourceObserver, this method sends the result via didDecode(). >+ // Otherwise, this method returns the result. e.g. GraphicsContext3D >+ ImageFrameData requestFrameAtIndex(size_t, bool retainedModeRendering = false); > > #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) > static unsigned maxPixelsPerDecodedImage() { return s_maxPixelsPerDecodedImage; } > static void setMaxPixelsPerDecodedImage(unsigned maxPixels) { s_maxPixelsPerDecodedImage = maxPixels; } > #endif > >+#if !USE(CG) >+ // ParallelImageDecoderObserver >+ virtual void didDecode(const ImageFrameData&); >+#endif >+ > private: >+ ImageFrameData createFrameAtIndex(size_t); > #if USE(CG) > float frameDurationAtIndex(size_t); > bool frameHasAlphaAtIndex(size_t); // Whether or not the frame actually used any alpha. >@@ -233,8 +250,20 @@ private: > ImageOrientation orientationAtIndex(ImageFrame*) const; > #endif > >+#if !USE(CG) >+ void createParallelDecoderIfNeeded(); >+ void clearParallelDecoder(); >+ bool shouldDecodeParallel(); >+ bool firstFrameIsComplete(); >+ void parallelDecode(); >+ ImageFrameData serialDecode(size_t); >+ >+ RefPtr<ParallelImageDecoder> m_parallelDecoder; >+#endif >+ > NativeImageSourcePtr m_decoder; > ImageSourceObserver* m_observer; >+ > AlphaOption m_alphaOption; > GammaAndColorProfileOption m_gammaAndColorProfileOption; > #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) >diff --git a/Source/WebCore/platform/graphics/ImageSourceObserver.h b/Source/WebCore/platform/graphics/ImageSourceObserver.h >index 72af708c7ecd11f816e8a8e02729026060821428..d320782d8e830c04e99f01e143fd29a94a8320f3 100644 >--- a/Source/WebCore/platform/graphics/ImageSourceObserver.h >+++ b/Source/WebCore/platform/graphics/ImageSourceObserver.h >@@ -33,7 +33,7 @@ class ImageFrameData; > // Interface for notification about changes to an ImageSource, including decoding. > class ImageSourceObserver { > public: >- virtual void didReceiveFrameAtIndex(size_t, const ImageFrameData&) = 0; >+ virtual void didReceiveFrameAtIndex(size_t, const ImageFrameData&, bool retained = false, bool parallelDecoderCanceled = false) = 0; > > protected: > virtual ~ImageSourceObserver() { } >diff --git a/Source/WebCore/platform/graphics/ParallelImageDecoder.cpp b/Source/WebCore/platform/graphics/ParallelImageDecoder.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..6b9cfaf55311378450d3314642ed1c8836947a5a >--- /dev/null >+++ b/Source/WebCore/platform/graphics/ParallelImageDecoder.cpp >@@ -0,0 +1,304 @@ >+/* >+ * Copyright (C) 2012 Company 100 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 COMPUTER, 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 COMPUTER, 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 "ParallelImageDecoder.h" >+ >+#include <wtf/MainThread.h> >+#include <wtf/OwnArrayPtr.h> >+#include <wtf/OwnPtr.h> >+#include <wtf/PassOwnArrayPtr.h> >+#include <wtf/PassOwnPtr.h> >+ >+namespace WebCore { >+ >+struct ParallelFrameData; >+void didDecodeTaskCallback(ParallelFrameData*); >+static ImageFrameData createImageFrameData(ParallelFrameData*); >+ >+ParallelImageDecoder::ParallelImageDecoder(ParallelImageDecoderObserver* observer, ImageDecoder* decoder) >+ : m_observer(observer) >+ , m_isAllDataReceived(false) >+ , m_bytesOfDataConsumed(0) >+ , m_imageDecoder(0) >+{ >+ initialize(decoder); >+} >+ >+ParallelImageDecoder::~ParallelImageDecoder() >+{ >+ ASSERT(!valid()); >+} >+ >+void ParallelImageDecoder::initialize(ImageDecoder* decoder) >+{ >+ ASSERT(isMainThread()); >+ ASSERT(decoder->isSizeAvailable() && !decoder->size().isEmpty()); >+ >+ m_size = decoder->size(); >+ m_filenameExtension = decoder->filenameExtension(); >+ >+ setData(decoder->data(), decoder->isAllDataReceived()); >+ m_bytesOfDataConsumed = 0; >+ >+ m_imageFrame.setSize(m_size.width(), m_size.height()); >+ >+ m_imageDecoder = decoder; >+ m_imageDecoder->setData(0, false); >+ // After this line, it is illegal for the main thread to access m_imageDecoder. >+ >+ // This must be the last line because ImageDecodeWorker guarantees >+ // the visibility of members in the task thread. >+ m_decodeWorker = ImageDecodeWorker::acquireSharedWorker(); >+} >+ >+void ParallelImageDecoder::invalidate() >+{ >+ ASSERT(isMainThread()); >+ ASSERT(m_imageDecoder); >+ >+ if (m_decodeWorker.get()) { >+ m_decodeWorker->invalidate(); >+ m_decodeWorker.clear(); >+ } >+ // The main thread can use m_imageDecoder because other threads do not access m_imageDecoder after this line. >+ >+ m_imageDecoder->setData(m_data.get(), m_isAllDataReceived); >+ >+ m_size = IntSize(); >+ m_filenameExtension = ""; >+ >+ m_isAllDataReceived = false; >+ m_data.clear(); >+ m_bytesOfDataConsumed = 0; >+ >+ m_imageFrame = ImageFrame(); >+ >+ if (m_dataForTask.get()) >+ m_dataForTask.clear(); >+ >+ m_imageDecoder = 0; >+} >+ >+void ParallelImageDecoder::setData(SharedBuffer* data, bool allDataReceived) >+{ >+ ASSERT(isMainThread()); >+ m_isAllDataReceived = allDataReceived; >+ m_data = data; >+} >+ >+void ParallelImageDecoder::decode() >+{ >+ ASSERT(isMainThread()); >+ ASSERT(m_imageDecoder); >+ ASSERT(!m_size.isEmpty()); >+ >+ OwnPtr<EncodedDataSegment> segment = extractSegmentForTask(); >+ if (!segment.get()) >+ return; >+ m_decodeWorker->postTask(bind(&ParallelImageDecoder::decodeTask, this, segment.release())); >+} >+ >+PassOwnPtr<ParallelImageDecoder::EncodedDataSegment> ParallelImageDecoder::extractSegmentForTask() >+{ >+ ASSERT(m_bytesOfDataConsumed >= 0 && m_bytesOfDataConsumed <= m_data->size()); >+ >+ int sizeOfSegment = m_data->size() - m_bytesOfDataConsumed; >+ if (!sizeOfSegment) >+ return PassOwnPtr<EncodedDataSegment>(); >+ >+ OwnPtr<EncodedDataSegment> segment(adoptPtr(new EncodedDataSegment())); >+ const char* srcPtr = m_data->data() + m_bytesOfDataConsumed; >+ segment->m_segment.append(srcPtr, sizeOfSegment); >+ m_bytesOfDataConsumed = m_data->size(); >+ >+ segment->m_isAllDataReceived = m_isAllDataReceived; >+ >+ return segment.release(); >+} >+ >+struct ParallelFrameData { >+ WTF_MAKE_NONCOPYABLE(ParallelFrameData); >+ WTF_MAKE_FAST_ALLOCATED; >+public: >+ explicit ParallelFrameData(PassRefPtr<ParallelImageDecoder> parallelDecoder) >+ : m_parallelDecoder(parallelDecoder) >+ , m_decodedSegment() >+ , m_status(ImageFrame::FrameEmpty) >+ , m_hasAlpha(false) >+ , m_premultiplyAlpha(true) >+ { >+ } >+ >+ ~ParallelFrameData() >+ { >+ } >+ >+ RefPtr<ParallelImageDecoder> m_parallelDecoder; >+ OwnArrayPtr<ImageFrame::PixelData> m_decodedSegment; >+ ImageFrame::FrameStatus m_status; >+ bool m_hasAlpha; >+ bool m_premultiplyAlpha; >+ IntRect m_decodedRect; >+}; >+ >+void ParallelImageDecoder::decodeTask(PassOwnPtr<ParallelImageDecoder::EncodedDataSegment> passSegment) >+{ >+ ASSERT(!isMainThread()); >+ ASSERT(m_imageDecoder); >+ >+ OwnPtr<EncodedDataSegment> segment = passSegment; >+ >+ // 1. Send segment data to ImageDecoder. >+ if (!m_dataForTask) { >+ m_dataForTask = SharedBuffer::create(); >+#ifndef NDEBUG >+ // ThreadRestrictionVerifier does not allow two threads to access one RefCounted object. >+ // m_dataForTask is used by both the main thread and the task thread: >+ // The task thread creates, uses and removes m_dataForTask. The main thread may remove >+ // m_dataForTask if the task thread could not remove m_dataForTask. >+ // >+ // Parallel image decoders manage m_dataForTask in a thread-safe way. However, >+ // we can't tell the verifier that we are safe by simply passing a mutex >+ // because libdispatch does not even guarantee decodeTask is called by the same thread >+ // each time. So turn off the verifier here. >+ m_dataForTask->turnOffVerifier(); >+#endif >+ } >+ m_dataForTask->append(segment->m_segment); >+ m_imageDecoder->setData(m_dataForTask.get(), segment->m_isAllDataReceived); >+ >+ ImageFrame* oldBuffer = m_imageDecoder->firstImageFrameWithoutDecode(); >+ int lastDecodedRow = oldBuffer ? oldBuffer->lastDecodedRow() : 0; >+ >+ // 2. Decode an image incrementally. >+ ImageFrame* buffer = m_imageDecoder->frameBufferAtIndex(0); >+ if (!buffer || buffer->status() == ImageFrame::FrameEmpty) { >+ ASSERT(!segment->m_isAllDataReceived); >+ return; >+ } >+ >+ // 3. Make a ParallelFrameData in order to pass it to the main thread. >+ ParallelFrameData* parallelFrameData = new ParallelFrameData(this); >+ parallelFrameData->m_status = buffer->status(); >+ parallelFrameData->m_hasAlpha = buffer->hasAlpha(); >+ parallelFrameData->m_premultiplyAlpha = buffer->premultiplyAlpha(); >+ >+ int newLastDecodedRow = buffer->lastDecodedRow(); >+ // Only in BMP, lastDecodedRow can be bigger than newLastDecodedRow. >+ int lastDecodedMinRow = std::min(lastDecodedRow, newLastDecodedRow); >+ int lastDecodedMaxRow = std::max(lastDecodedRow, newLastDecodedRow); >+ parallelFrameData->m_decodedRect = IntRect(0, lastDecodedMinRow, m_imageDecoder->size().width(), lastDecodedMaxRow - lastDecodedMinRow + 1); >+ >+ // 4. Create decoded segment data in order to pass it to the main thread. >+ // If the status is FrameComplete, this is not needed because a NativeImage will be created using the decoder on the main thread. >+ if (parallelFrameData->m_status == ImageFrame::FramePartial) { >+ int segmentSize = parallelFrameData->m_decodedRect.size().area(); >+ parallelFrameData->m_decodedSegment = adoptArrayPtr(new ImageFrame::PixelData[segmentSize]); >+ >+ ImageFrame::PixelData* segmentAddr = parallelFrameData->m_decodedSegment.get(); >+ memcpy(segmentAddr, buffer->getAddr(0, lastDecodedMinRow), segmentSize * sizeof(ImageFrame::PixelData)); >+ } else { // FrameComplete >+ m_imageDecoder->setData(0, false); >+ m_dataForTask.clear(); >+ } >+ >+ callOnMainThread(bind(didDecodeTaskCallback, parallelFrameData)); >+} >+ >+void didDecodeTaskCallback(ParallelFrameData* parallelFrameData) >+{ >+ ASSERT(isMainThread()); >+ // If a client called ParallelImageDecoder::clear(), ParallelImageDecoder is invalidated. >+ if (parallelFrameData->m_parallelDecoder->valid()) >+ parallelFrameData->m_parallelDecoder->didDecodeTask(parallelFrameData); >+ delete parallelFrameData; >+} >+ >+ImageFrameData createImageFrameData(ParallelFrameData* parallelFrameData) >+{ >+ ImageFrameData imageFrameData; >+ imageFrameData.m_orientation = DefaultImageOrientation; >+ imageFrameData.m_isComplete = parallelFrameData->m_status == ImageFrame::FrameComplete; >+ imageFrameData.m_hasAlpha = !imageFrameData.m_isComplete || parallelFrameData->m_hasAlpha; >+ return imageFrameData; >+} >+ >+void ParallelImageDecoder::didDecodeTask(ParallelFrameData* parallelFrameData) >+{ >+ ASSERT(isMainThread()); >+ ASSERT(parallelFrameData->m_status != ImageFrame::FrameEmpty); >+ >+ ImageFrameData imageFrameData = createImageFrameData(parallelFrameData); >+ >+ if (!imageFrameData.m_isComplete) >+ didDecodePartial(imageFrameData, parallelFrameData); >+ else >+ didDecodeComplete(imageFrameData); >+} >+ >+void ParallelImageDecoder::didDecodePartial(ImageFrameData& imageFrameData, ParallelFrameData* parallelFrameData) >+{ >+ ASSERT(isMainThread()); >+ >+ appendDecodedDataToImageFrame(parallelFrameData); >+ syncImageFrame(parallelFrameData); >+ >+ imageFrameData.m_frame = m_imageFrame.asNewNativeImage(); >+ m_observer->didDecode(imageFrameData); >+} >+ >+void ParallelImageDecoder::appendDecodedDataToImageFrame(ParallelFrameData* parallelFrameData) >+{ >+ const ImageFrame::PixelData* const segmentAddr = parallelFrameData->m_decodedSegment.get(); >+ int segmentSize = parallelFrameData->m_decodedRect.size().area(); >+ ImageFrame::PixelData* destAddr = m_imageFrame.getAddr(0, parallelFrameData->m_decodedRect.y()); >+ memcpy(destAddr, segmentAddr, segmentSize * sizeof(ImageFrame::PixelData)); >+} >+ >+void ParallelImageDecoder::syncImageFrame(ParallelFrameData* parallelFrameData) >+{ >+ // The following lines are needed to create a valid native image in ImageFrame::asNewNativeImage(). >+ m_imageFrame.setStatus(parallelFrameData->m_status); >+ m_imageFrame.setHasAlpha(parallelFrameData->m_hasAlpha); >+ m_imageFrame.setPremultiplyAlpha(parallelFrameData->m_premultiplyAlpha); >+} >+ >+void ParallelImageDecoder::didDecodeComplete(ImageFrameData& imageFrameData) >+{ >+ ASSERT(isMainThread()); >+ >+ m_decodeWorker->invalidate(); >+ m_decodeWorker.clear(); >+ // The main thread can use m_imageDecoder because other threads do not access m_imageDecoder after this line. >+ >+ ImageFrame* buffer = m_imageDecoder->firstImageFrameWithoutDecode(); >+ ASSERT(buffer); >+ >+ imageFrameData.m_frame = buffer->asNewNativeImage(); >+ m_observer->didDecode(imageFrameData); >+} >+ >+} >diff --git a/Source/WebCore/platform/graphics/ParallelImageDecoder.h b/Source/WebCore/platform/graphics/ParallelImageDecoder.h >new file mode 100644 >index 0000000000000000000000000000000000000000..92f0a38ab7830be47fbf019f7702fd032d578f66 >--- /dev/null >+++ b/Source/WebCore/platform/graphics/ParallelImageDecoder.h >@@ -0,0 +1,104 @@ >+/* >+ * Copyright (C) 2012 Company 100 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 COMPUTER, 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 COMPUTER, 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. >+ */ >+ >+#ifndef ParallelImageDecoder_h >+#define ParallelImageDecoder_h >+ >+#include "ImageDecodeWorker.h" >+#include "ImageDecoder.h" >+#include "ParallelImageDecoderObserver.h" >+#include <wtf/Forward.h> >+#include <wtf/ThreadSafeRefCounted.h> >+#include <wtf/Vector.h> >+ >+namespace WebCore { >+class ImageFrameData; >+class ParallelFrameData; >+ >+class ParallelImageDecoder : public ThreadSafeRefCounted<ParallelImageDecoder> { >+public: >+ ParallelImageDecoder(ParallelImageDecoderObserver*, ImageDecoder*); >+ ~ParallelImageDecoder(); >+ >+ void invalidate(); >+ >+ void setData(SharedBuffer*, bool allDataReceived); >+ >+ void decode(); >+ >+ inline String filenameExtension() const { return m_filenameExtension; } >+ inline IntSize size() const { return m_size; } >+ >+private: >+ void initialize(ImageDecoder*); >+ >+ inline bool valid() const { return m_imageDecoder; } >+ >+ struct EncodedDataSegment { >+ WTF_MAKE_NONCOPYABLE(EncodedDataSegment); >+ WTF_MAKE_FAST_ALLOCATED; >+ public: >+ EncodedDataSegment() { } >+ Vector<char> m_segment; >+ bool m_isAllDataReceived; >+ }; >+ >+ PassOwnPtr<EncodedDataSegment> extractSegmentForTask(); >+ >+ // Only this method is called by the task thread. >+ void decodeTask(PassOwnPtr<EncodedDataSegment>); >+ >+ void didDecodeTask(ParallelFrameData*); >+ void didDecodePartial(ImageFrameData&, ParallelFrameData*); >+ void appendDecodedDataToImageFrame(ParallelFrameData*); >+ void syncImageFrame(ParallelFrameData*); >+ void didDecodeComplete(ImageFrameData&); >+ friend void didDecodeTaskCallback(ParallelFrameData*); >+ >+ ParallelImageDecoderObserver* m_observer; >+ >+ IntSize m_size; >+ String m_filenameExtension; >+ >+ // For input data >+ bool m_isAllDataReceived; >+ RefPtr<SharedBuffer> m_data; >+ int m_bytesOfDataConsumed; >+ >+ // For output data >+ ImageFrame m_imageFrame; >+ >+ // The task thread can access only m_dataForTask and m_imageDecoder. >+ RefPtr<SharedBuffer> m_dataForTask; >+ >+ ImageDecoder* m_imageDecoder; >+ >+ RefPtr<ImageDecodeWorker> m_decodeWorker; >+ >+}; >+ >+} // namespace WebCore >+ >+#endif >diff --git a/Source/WebCore/platform/graphics/ParallelImageDecoderObserver.h b/Source/WebCore/platform/graphics/ParallelImageDecoderObserver.h >new file mode 100644 >index 0000000000000000000000000000000000000000..4a7e19705e1e29c5f39adbdcbe97778a181d8e6d >--- /dev/null >+++ b/Source/WebCore/platform/graphics/ParallelImageDecoderObserver.h >@@ -0,0 +1,44 @@ >+/* >+ * Copyright (C) 2012 Company 100 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 COMPUTER, 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 COMPUTER, 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. >+ */ >+ >+#ifndef ParallelImageDecoderObserver_h >+#define ParallelImageDecoderObserver_h >+ >+namespace WebCore { >+ >+class ImageFrameData; >+ >+// Interface for notification about decoding completion of an ParallelImageDecoder. >+class ParallelImageDecoderObserver { >+public: >+ virtual void didDecode(const ImageFrameData&) = 0; >+ >+protected: >+ virtual ~ParallelImageDecoderObserver() { } >+}; >+ >+} >+ >+#endif >diff --git a/Source/WebCore/platform/graphics/RetainedModeBitmapImage.cpp b/Source/WebCore/platform/graphics/RetainedModeBitmapImage.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..09bab66557e1f71428710d35e858f593be8dddbb >--- /dev/null >+++ b/Source/WebCore/platform/graphics/RetainedModeBitmapImage.cpp >@@ -0,0 +1,172 @@ >+/* >+ * Copyright (C) 2012 Company 100 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 COMPUTER, 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 COMPUTER, 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 "RetainedModeBitmapImage.h" >+ >+#include "BitmapImage.h" >+ >+namespace WebCore { >+ >+PassRefPtr<RetainedModeBitmapImage> RetainedModeBitmapImage::create(BitmapImage* bitmapImage) >+{ >+ return adoptRef(new RetainedModeBitmapImage(bitmapImage)); >+} >+ >+RetainedModeBitmapImage::RetainedModeBitmapImage(BitmapImage* bitmapImage) >+ : m_bitmapImage(bitmapImage) >+ , m_retainedModeCount(0) >+{ >+} >+ >+bool RetainedModeBitmapImage::hasSingleSecurityOrigin() const >+{ >+ RetainedModeSaver retainedModeSaver(this); >+ return m_bitmapImage->hasSingleSecurityOrigin(); >+} >+ >+IntSize RetainedModeBitmapImage::size() const >+{ >+ RetainedModeSaver retainedModeSaver(this); >+ return m_bitmapImage->size(); >+} >+ >+bool RetainedModeBitmapImage::getHotSpot(IntPoint& point) const >+{ >+ RetainedModeSaver retainedModeSaver(this); >+ return m_bitmapImage->getHotSpot(point); >+} >+ >+bool RetainedModeBitmapImage::dataChanged(bool allDataReceived) >+{ >+ RetainedModeSaver retainedModeSaver(this); >+ return m_bitmapImage->dataChanged(allDataReceived); >+} >+ >+String RetainedModeBitmapImage::filenameExtension() const >+{ >+ RetainedModeSaver retainedModeSaver(this); >+ return m_bitmapImage->filenameExtension(); >+} >+ >+void RetainedModeBitmapImage::destroyDecodedData(bool destroyAll) >+{ >+ RetainedModeSaver retainedModeSaver(this); >+ m_bitmapImage->destroyDecodedData(destroyAll); >+} >+ >+unsigned RetainedModeBitmapImage::decodedSize() const >+{ >+ RetainedModeSaver retainedModeSaver(this); >+ return m_bitmapImage->decodedSize(); >+} >+ >+void RetainedModeBitmapImage::startAnimation(bool catchUpIfNecessary) >+{ >+ RetainedModeSaver retainedModeSaver(this); >+ m_bitmapImage->startAnimation(catchUpIfNecessary); >+} >+ >+void RetainedModeBitmapImage::stopAnimation() >+{ >+ RetainedModeSaver retainedModeSaver(this); >+ m_bitmapImage->stopAnimation(); >+} >+ >+void RetainedModeBitmapImage::resetAnimation() >+{ >+ RetainedModeSaver retainedModeSaver(this); >+ m_bitmapImage->resetAnimation(); >+} >+ >+NativeImagePtr RetainedModeBitmapImage::nativeImageForCurrentFrame() >+{ >+ RetainedModeSaver retainedModeSaver(this); >+ return m_bitmapImage->nativeImageForCurrentFrame(); >+} >+ >+bool RetainedModeBitmapImage::currentFrameHasAlpha() >+{ >+ RetainedModeSaver retainedModeSaver(this); >+ return m_bitmapImage->currentFrameHasAlpha(); >+} >+ >+bool RetainedModeBitmapImage::currentFrameIsComplete() >+{ >+ RetainedModeSaver retainedModeSaver(this); >+ return m_bitmapImage->currentFrameIsComplete(); >+} >+ >+void RetainedModeBitmapImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator op) >+{ >+ RetainedModeSaver retainedModeSaver(this); >+ m_bitmapImage->draw(context, dstRect, srcRect, styleColorSpace, op); >+} >+ >+bool RetainedModeBitmapImage::mayFillWithSolidColor() >+{ >+ RetainedModeSaver retainedModeSaver(this); >+ return m_bitmapImage->mayFillWithSolidColor(); >+} >+ >+Color RetainedModeBitmapImage::solidColor() const >+{ >+ RetainedModeSaver retainedModeSaver(this); >+ return m_bitmapImage->solidColor(); >+} >+ >+RetainedModeSaver::RetainedModeSaver(const RetainedModeBitmapImage* image, bool retained) >+ : m_image(image) >+ , m_retained(retained) >+{ >+ if (m_retained) >+ m_image->beginRetainedMode(); >+} >+ >+RetainedModeSaver::~RetainedModeSaver() >+{ >+ if (m_retained) >+ m_image->endRetainedMode(); >+} >+ >+RetainedModeBitmapImage* toRetainedModeBitmapImage(Image* image) >+{ >+ ASSERT(image->isBitmapImage()); >+ >+ BitmapImage* bitmapImage = static_cast<BitmapImage*>(image); >+ if (!bitmapImage->m_retainedModeImage.get()) >+ bitmapImage->m_retainedModeImage = RetainedModeBitmapImage::create(bitmapImage); >+ >+ return bitmapImage->m_retainedModeImage.get(); >+} >+ >+Image* toRetainedModeBitmapImageIfPossible(Image* image) >+{ >+ if (image && image->isBitmapImage()) >+ return toRetainedModeBitmapImage(image); >+ return image; >+} >+ >+} >diff --git a/Source/WebCore/platform/graphics/RetainedModeBitmapImage.h b/Source/WebCore/platform/graphics/RetainedModeBitmapImage.h >new file mode 100644 >index 0000000000000000000000000000000000000000..33e7a8c3855730ce9c99ae19f13809dafcf857e5 >--- /dev/null >+++ b/Source/WebCore/platform/graphics/RetainedModeBitmapImage.h >@@ -0,0 +1,101 @@ >+/* >+ * Copyright (C) 2012 Company 100 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 COMPUTER, 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 COMPUTER, 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. >+ */ >+ >+#ifndef RetainedModeBitmapImage_h >+#define RetainedModeBitmapImage_h >+ >+#include "Image.h" >+ >+namespace WebCore { >+ >+class BitmapImage; >+class RetainedModeSaver; >+ >+class RetainedModeBitmapImage : public Image { >+ friend class RetainedModeSaver; >+public: >+ static PassRefPtr<RetainedModeBitmapImage> create(BitmapImage*); >+ >+ virtual ~RetainedModeBitmapImage() { } >+ >+ virtual bool hasSingleSecurityOrigin() const; >+ >+ virtual IntSize size() const; >+ virtual bool getHotSpot(IntPoint&) const; >+ >+ virtual bool dataChanged(bool allDataReceived); >+ virtual String filenameExtension() const; >+ >+ virtual void destroyDecodedData(bool destroyAll = true); >+ virtual unsigned decodedSize() const; >+ >+ virtual void startAnimation(bool catchUpIfNecessary = true); >+ virtual void stopAnimation(); >+ virtual void resetAnimation(); >+ >+ virtual NativeImagePtr nativeImageForCurrentFrame(); >+ virtual bool currentFrameHasAlpha(); >+ >+ bool currentFrameIsComplete(); >+ >+ inline bool retainedModeRendering() const { return m_retainedModeCount; } >+ >+protected: >+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator); >+ >+ virtual bool mayFillWithSolidColor(); >+ virtual Color solidColor() const; >+ >+private: >+ explicit RetainedModeBitmapImage(BitmapImage*); >+ >+ inline void beginRetainedMode() const { m_retainedModeCount++; } >+ inline void endRetainedMode() const >+ { >+ m_retainedModeCount--; >+ ASSERT(m_retainedModeCount >= 0); >+ } >+ >+ BitmapImage* m_bitmapImage; >+ mutable int m_retainedModeCount; >+}; >+ >+class RetainedModeSaver { >+public: >+ RetainedModeSaver(const RetainedModeBitmapImage*, bool retained = true); >+ ~RetainedModeSaver(); >+ >+private: >+ const RetainedModeBitmapImage* m_image; >+ bool m_retained; >+}; >+ >+ >+RetainedModeBitmapImage* toRetainedModeBitmapImage(Image*); >+Image* toRetainedModeBitmapImageIfPossible(Image*); >+ >+} >+ >+#endif >diff --git a/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp b/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp >index dc6a4d4bcb72c6ae734fe739a8c4ce7d56415f47..d06b1f77bfda5934bed76ce192970a2c4c281214 100644 >--- a/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp >+++ b/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp >@@ -58,6 +58,7 @@ BitmapImage::BitmapImage(NativeImageCairo* nativeImage, ImageObserver* observer) > , m_haveSize(true) > , m_sizeAvailable(true) > , m_haveFrameCount(true) >+ , m_isCachingFrame(false) > { > cairo_surface_t* surface = nativeImage->surface(); > int width = cairo_image_surface_get_width(surface); >diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp >index 2542cf8fa91d0b8a714385a4e302396783d961dd..b7425a9e816fb3beedb32e007d7d2b8d31512d63 100644 >--- a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp >+++ b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp >@@ -165,7 +165,7 @@ bool GraphicsContext3D::getImageData(Image* image, unsigned int format, unsigned > decoder.setData(image->data(), true); > if (!decoder.frameCount()) > return false; >- ImageFrameData imageImageFrameData = decoder.createFrameAtIndex(0); >+ ImageFrameData imageImageFrameData = decoder.requestFrameAtIndex(0); > if (!imageImageFrameData.m_isComplete) > return false; > OwnPtr<NativeImageCairo> nativeImage = adoptPtr(imageImageFrameData.m_frame); >diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp >index 780ba44d841a600993988da2314630829d43393d..387f1ef52ede9138a40adddc9f6d578756c852a5 100644 >--- a/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp >+++ b/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp >@@ -107,7 +107,7 @@ bool GraphicsContext3D::getImageData(Image* image, > decoder.setData(image->data(), true); > if (!decoder.frameCount()) > return false; >- ImageFrameData imageFrameData = decoder.createFrameAtIndex(0); >+ ImageFrameData imageFrameData = decoder.requestFrameAtIndex(0); > decodedImage.adoptCF(imageFrameData.m_frame); > cgImage = decodedImage.get(); > } else >diff --git a/Source/WebCore/platform/graphics/cg/ImageCG.cpp b/Source/WebCore/platform/graphics/cg/ImageCG.cpp >index c85be4670eb2a7c79c25a0209825ae0ed408dcb9..1a7cafc83e550f9494594d5dc2359a7e136386fd 100644 >--- a/Source/WebCore/platform/graphics/cg/ImageCG.cpp >+++ b/Source/WebCore/platform/graphics/cg/ImageCG.cpp >@@ -81,6 +81,7 @@ BitmapImage::BitmapImage(CGImageRef cgImage, ImageObserver* observer) > , m_haveSize(true) > , m_sizeAvailable(true) > , m_haveFrameCount(true) >+ , m_isCachingFrame(false) > { > CGFloat width = CGImageGetWidth(cgImage); > CGFloat height = CGImageGetHeight(cgImage); >diff --git a/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp >index 60ba3c94b6380105806efe71855d3a4b43b37662..24d70232efd29f638da4a09a4675c7ee7e8a2744 100644 >--- a/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp >+++ b/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp >@@ -32,6 +32,7 @@ > #include "ImageOrientation.h" > #include "ImageSourceObserver.h" > #include "IntPoint.h" >+#include "IntRect.h" > #include "IntSize.h" > #include "MIMETypeRegistry.h" > #include "SharedBuffer.h" >@@ -309,11 +310,12 @@ size_t ImageSource::frameCount() const > return m_decoder ? CGImageSourceGetCount(m_decoder) : 0; > } > >-void ImageSource::requestFrameAtIndex(size_t index) >+ImageFrameData ImageSource::requestFrameAtIndex(size_t index, bool) > { > ASSERT(m_observer); > ImageFrameData imageFrameData = createFrameAtIndex(index); > m_observer->didReceiveFrameAtIndex(index, imageFrameData); >+ return imageFrameData; > } > > ImageFrameData ImageSource::createFrameAtIndex(size_t index) >diff --git a/Source/WebCore/platform/graphics/openvg/ImageOpenVG.cpp b/Source/WebCore/platform/graphics/openvg/ImageOpenVG.cpp >index cd8794e539cfd50ee88a77e07c45f82ab9cd7353..9000fc3dfb5b309cdafaa997125b7b9635ef3fb8 100644 >--- a/Source/WebCore/platform/graphics/openvg/ImageOpenVG.cpp >+++ b/Source/WebCore/platform/graphics/openvg/ImageOpenVG.cpp >@@ -67,6 +67,7 @@ BitmapImage::BitmapImage(TiledImageOpenVG* tiledImage, ImageObserver* observer) > , m_sizeAvailable(true) > , m_hasUniformFrameSize(true) > , m_haveFrameCount(true) >+ , m_isCachingFrame(false) > { > ASSERT(m_size.width() > 0); > ASSERT(m_size.height() > 0); >diff --git a/Source/WebCore/platform/graphics/qt/ImageQt.cpp b/Source/WebCore/platform/graphics/qt/ImageQt.cpp >index fca75905f5dc3d42696ec8950ec51e3fe77d0b3d..caf6606a81698fad5197dc9329f9e0b4796e9071 100644 >--- a/Source/WebCore/platform/graphics/qt/ImageQt.cpp >+++ b/Source/WebCore/platform/graphics/qt/ImageQt.cpp >@@ -209,6 +209,7 @@ BitmapImage::BitmapImage(QPixmap* pixmap, ImageObserver* observer) > , m_haveSize(true) > , m_sizeAvailable(true) > , m_haveFrameCount(true) >+ , m_isCachingFrame(false) > { > int width = pixmap->width(); > int height = pixmap->height(); >diff --git a/Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp b/Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp >index f56d7245ad10ec3ae85bed42709e6f6b472b2c50..1f0459c54ac505fc72bd3cb086eaee2688a5e2e3 100644 >--- a/Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp >+++ b/Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp >@@ -62,7 +62,7 @@ bool GraphicsContext3D::getImageData(Image* image, > decoder.setData(image->data(), true); > if (!decoder.frameCount()) > return false; >- ImageFrameData imageFrameData = decoder.createFrameAtIndex(0); >+ ImageFrameData imageFrameData = decoder.requestFrameAtIndex(0); > if (!imageFrameData.m_isComplete) > return false; > hasAlpha = imageFrameData.m_hasAlpha; >diff --git a/Source/WebCore/platform/graphics/wx/ImageWx.cpp b/Source/WebCore/platform/graphics/wx/ImageWx.cpp >index b7c2496c73b5265f1d8534e337ee8c20fe302989..b4b57be9ba34305d349fbf4c4e5b47675fb83142 100644 >--- a/Source/WebCore/platform/graphics/wx/ImageWx.cpp >+++ b/Source/WebCore/platform/graphics/wx/ImageWx.cpp >@@ -95,6 +95,7 @@ BitmapImage::BitmapImage(const wxBitmap& bitmap) > , m_decodedSize(0) > , m_haveFrameCount(true) > , m_frameCount(1) >+ , m_isCachingFrame(false) > { > m_decodedSize = bitmap.GetWidth() * bitmap.GetHeight() * 4; > m_size = IntSize(bitmap.GetWidth(), bitmap.GetHeight()); >diff --git a/Source/WebCore/platform/image-decoders/ImageDecoder.cpp b/Source/WebCore/platform/image-decoders/ImageDecoder.cpp >index 72b5ddc2de31d0040727d44e95162adf6bac76c7..904f86686332da8c326dd0f6eb57bb4556775d8e 100644 >--- a/Source/WebCore/platform/image-decoders/ImageDecoder.cpp >+++ b/Source/WebCore/platform/image-decoders/ImageDecoder.cpp >@@ -140,6 +140,7 @@ ImageDecoder* ImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaO > > ImageFrame::ImageFrame() > : m_hasAlpha(false) >+ , m_lastDecodedRow(0) > , m_status(FrameEmpty) > , m_duration(0) > , m_disposalMethod(DisposeNotSpecified) >@@ -165,6 +166,7 @@ void ImageFrame::clearPixelData() > { > m_backingStore.clear(); > m_bytes = 0; >+ m_lastDecodedRow = 0; > m_status = FrameEmpty; > // NOTE: Do not reset other members here; clearFrameBufferCache() calls this > // to free the bitmap data, but other functions like initFrameBuffer() and >@@ -187,6 +189,7 @@ bool ImageFrame::copyBitmapData(const ImageFrame& other) > m_bytes = m_backingStore.data(); > m_size = other.m_size; > setHasAlpha(other.m_hasAlpha); >+ m_lastDecodedRow = other.m_lastDecodedRow; > return true; > } > >@@ -199,6 +202,7 @@ bool ImageFrame::setSize(int newWidth, int newHeight) > m_backingStore.resize(backingStoreSize); > m_bytes = m_backingStore.data(); > m_size = IntSize(newWidth, newHeight); >+ m_lastDecodedRow = 0; > > zeroFillPixelData(); > return true; >diff --git a/Source/WebCore/platform/image-decoders/ImageDecoder.h b/Source/WebCore/platform/image-decoders/ImageDecoder.h >index 760ac93f857503af187673e74d601d2f28587f34..466fc1a6476d806a503e797b3d26c200f49383f9 100644 >--- a/Source/WebCore/platform/image-decoders/ImageDecoder.h >+++ b/Source/WebCore/platform/image-decoders/ImageDecoder.h >@@ -118,6 +118,7 @@ namespace WebCore { > NativeImagePtr asNewNativeImage() const; > > bool hasAlpha() const; >+ int lastDecodedRow() const { return m_lastDecodedRow; } > const IntRect& originalFrameRect() const { return m_originalFrameRect; } > FrameStatus status() const { return m_status; } > unsigned duration() const { return m_duration; } >@@ -125,6 +126,7 @@ namespace WebCore { > bool premultiplyAlpha() const { return m_premultiplyAlpha; } > > void setHasAlpha(bool alpha); >+ inline void setLastDecodedRow(int lastDecodedRow) { m_lastDecodedRow = lastDecodedRow; } > void setColorProfile(const ColorProfile&); > void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; } > void setStatus(FrameStatus status); >@@ -181,6 +183,7 @@ namespace WebCore { > // FIXME: Do we need m_colorProfile anymore? > ColorProfile m_colorProfile; > #endif >+ int m_lastDecodedRow; > IntRect m_originalFrameRect; // This will always just be the entire > // buffer except for GIF frames whose > // original rect was smaller than the >@@ -228,6 +231,8 @@ namespace WebCore { > m_isAllDataReceived = allDataReceived; > } > >+ SharedBuffer* data() const { return m_data.get(); } >+ > // Lazily-decodes enough of the image to get the size (if possible). > // FIXME: Right now that has to be done by each subclass; factor the > // decode call out and use it here. >@@ -276,6 +281,12 @@ namespace WebCore { > // ImageDecoder-owned pointer. > virtual ImageFrame* frameBufferAtIndex(size_t) = 0; > >+ // Returns an ImageDecoder-owned pointer without decoding more. >+ ImageFrame* firstImageFrameWithoutDecode() >+ { >+ return m_frameBufferCache.isEmpty() ? 0 : &m_frameBufferCache[0]; >+ } >+ > void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; } > bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; } > >diff --git a/Source/WebCore/platform/image-decoders/blackberry/JPEGImageDecoder.cpp b/Source/WebCore/platform/image-decoders/blackberry/JPEGImageDecoder.cpp >index 6a65e617d19e67bfa21805387c1195da4821db6d..bdcaef05ea40115d06cf735f0919aac4b219eee1 100644 >--- a/Source/WebCore/platform/image-decoders/blackberry/JPEGImageDecoder.cpp >+++ b/Source/WebCore/platform/image-decoders/blackberry/JPEGImageDecoder.cpp >@@ -157,6 +157,7 @@ int ImageReader::decode(size_t width, size_t height, ImageFrame* aFrame) > aFrame->setRGBA(i, j, curPtr[0], curPtr[1], curPtr[2], 255); > curPtr += 3; > } >+ aFrame->setLastDecodedRow(j); > } > return 0; > } >diff --git a/Source/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp b/Source/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp >index 20a248c7d3bcb11cad7c67695eb8275752782493..f74dde3a0dffaab79b05ab438bd1ff8fea2c24ab 100644 >--- a/Source/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp >+++ b/Source/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp >@@ -64,8 +64,15 @@ void BMPImageDecoder::setData(SharedBuffer* data, bool allDataReceived) > > bool BMPImageDecoder::isSizeAvailable() > { >- if (!ImageDecoder::isSizeAvailable()) >+ if (!ImageDecoder::isSizeAvailable()) { >+ // Only BMPImageDecoder must make m_frameBufferCache[0] in isSizeAvailable(), >+ // because the default value of ImageFrame::m_lastDecodedRow can be "height - 1". >+ if (m_frameBufferCache.isEmpty()) { >+ m_frameBufferCache.resize(1); >+ m_frameBufferCache.first().setPremultiplyAlpha(m_premultiplyAlpha); >+ } > decode(true); >+ } > > return ImageDecoder::isSizeAvailable(); > } >diff --git a/Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp b/Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp >index 5c005534ecd92134a13b32958927790f07ad0f81..4f7e3179e666338a3a114b1b22a1e3494839455f 100644 >--- a/Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp >+++ b/Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp >@@ -64,8 +64,11 @@ bool BMPImageReader::decodeBMP(bool onlySize) > return false; > > // processInfoHeader() set the size, so if that's all we needed, we're done. >- if (onlySize) >+ if (onlySize) { >+ if (!m_isTopDown) >+ m_buffer->setLastDecodedRow(m_parent->size().height() - 1); > return true; >+ } > > // Read and process the bitmasks, if needed. > if (m_needToProcessBitmasks && !processBitmasks()) >@@ -624,6 +627,7 @@ bool BMPImageReader::processRLEData() > > m_decodedOffset += 2; > } >+ m_buffer->setLastDecodedRow(m_coord.y()); > } > } > } >@@ -717,6 +721,7 @@ BMPImageReader::ProcessingResult BMPImageReader::processNonRLEData(bool inRLE, i > getComponent(pixel, 2), alpha); > } > } >+ m_buffer->setLastDecodedRow(m_coord.y()); > > // Success, keep going. > m_decodedOffset += paddedNumBytes; >diff --git a/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp >index 5f6193b8f9e1ba937b6e3fc7317492434daae2da..7198a11c1f156800c7abb1ffea401b2c759085bc 100644 >--- a/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp >+++ b/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp >@@ -249,10 +249,14 @@ bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex, unsigned char* rowBuff > buffer.setRGBA(x, yBegin, 0, 0, 0, 0); > } > } >+ buffer.setLastDecodedRow(yBegin); > > // Tell the frame to copy the row data if need be. >- if (repeatCount > 1) >+ if (repeatCount > 1) { > buffer.copyRowNTimes(xBegin, xEnd, yBegin, yEnd); >+ ASSERT((yEnd - 1) >= 0); >+ buffer.setLastDecodedRow(yEnd - 1); >+ } > > return true; > } >@@ -390,6 +394,7 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex) > for (int y = prevRect.y(); y < prevRect.maxY(); ++y) { > for (int x = prevRect.x(); x < prevRect.maxX(); ++x) > buffer->setRGBA(x, y, 0, 0, 0, 0); >+ buffer->setLastDecodedRow(y); > } > if ((prevRect.width() > 0) && (prevRect.height() > 0)) > buffer->setHasAlpha(true); >diff --git a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp >index 91f1236b359bc155af37c7fe2ce36ea73c509496..4861cb66723978cbdb3778e0b378198eeb9b04ca 100644 >--- a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp >+++ b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp >@@ -577,6 +577,7 @@ bool JPEGImageDecoder::outputScanlines() > if (turboSwizzled(info->out_color_space)) { > ASSERT(!m_scaled); > while (info->output_scanline < info->output_height) { >+ buffer.setLastDecodedRow(info->output_scanline); > unsigned char* row = reinterpret_cast<unsigned char*>(buffer.getAddr(0, info->output_scanline)); > if (jpeg_read_scanlines(info, &row, 1) != 1) > return false; >@@ -628,6 +629,7 @@ bool JPEGImageDecoder::outputScanlines() > return setFailed(); > } > } >+ buffer.setLastDecodedRow(destY); > } > > return true; >diff --git a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp >index 138d5c51291ea26f69643f6aa44884bb5c6480ef..810caa7208219fff6cf62974e8ef7ef1b3451b3a 100644 >--- a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp >+++ b/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp >@@ -520,6 +520,7 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, > > if (nonTrivialAlpha && !buffer.hasAlpha()) > buffer.setHasAlpha(nonTrivialAlpha); >+ buffer.setLastDecodedRow(y); > } > > void PNGImageDecoder::pngComplete() >diff --git a/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp b/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp >index 5cc132c4d48400b8152ee5f4fef2242c429db6b6..13318a3846ff5aebd9302ad32e15323dd8738cbc 100644 >--- a/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp >+++ b/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp >@@ -57,6 +57,7 @@ ImageFrame& ImageFrame::operator=(const ImageFrame& other) > void ImageFrame::clearPixelData() > { > m_bitmap.bitmap().reset(); >+ m_lastDecodedRow = 0; > m_status = FrameEmpty; > // NOTE: Do not reset other members here; clearFrameBufferCache() > // calls this to free the bitmap data, but other functions like >@@ -76,6 +77,7 @@ bool ImageFrame::copyBitmapData(const ImageFrame& other) > > m_bitmap.bitmap().reset(); > const NativeImageSkia& otherBitmap = other.m_bitmap; >+ m_lastDecodedRow = other.m_lastDecodedRow; > return otherBitmap.bitmap().copyTo(&m_bitmap.bitmap(), otherBitmap.bitmap().config()); > } > >@@ -84,6 +86,7 @@ bool ImageFrame::setSize(int newWidth, int newHeight) > // setSize() should only be called once, it leaks memory otherwise. > ASSERT(!width() && !height()); > >+ m_lastDecodedRow = 0; > m_bitmap.bitmap().setConfig(SkBitmap::kARGB_8888_Config, newWidth, newHeight); > if (!m_bitmap.bitmap().allocPixels()) > return false; >diff --git a/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp b/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp >index 082e33ddb2a360e3888d79b03a9c21ccdb8c03c2..a9f98ad80f6f198058d2afdebb6a409e23ae79de 100644 >--- a/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp >+++ b/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp >@@ -132,19 +132,26 @@ bool WEBPImageDecoder::decode(bool onlySize) > return setFailed(); > } > >- switch (WebPIUpdate(m_decoder, dataBytes, dataSize)) { >- case VP8_STATUS_OK: >- buffer.setStatus(ImageFrame::FrameComplete); >- WebPIDelete(m_decoder); >- m_decoder = 0; >- return true; >- case VP8_STATUS_SUSPENDED: >- return false; >- default: >+ const VP8StatusCode status = WebPIUpdate(m_decoder, dataBytes, dataSize); >+ if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) { > WebPIDelete(m_decoder); > m_decoder = 0; > return setFailed(); > } >+ int lastY = 0; >+ if (!WebPIDecGetRGB(m_decoder, &lastY, 0, 0, 0)) >+ return setFailed(); >+ ASSERT(lastY >= 0); >+ ASSERT(lastY <= size().height()); >+ buffer.setLastDecodedRow(lastY ? lastY - 1 : 0); >+ >+ if (status == VP8_STATUS_SUSPENDED) >+ return false; >+ >+ buffer.setStatus(ImageFrame::FrameComplete); >+ WebPIDelete(m_decoder); >+ m_decoder = 0; >+ return true; > } > > } // namespace WebCore >diff --git a/Source/WebCore/rendering/RenderImage.cpp b/Source/WebCore/rendering/RenderImage.cpp >index 776e2787bf28949d4f321b173543bc842c8e507e..edba680198c8a81b97e8cc4755bc7947cf129e7f 100644 >--- a/Source/WebCore/rendering/RenderImage.cpp >+++ b/Source/WebCore/rendering/RenderImage.cpp >@@ -311,7 +311,7 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOf > LayoutUnit usableWidth = cWidth - 2; > LayoutUnit usableHeight = cHeight - 2; > >- RefPtr<Image> image = m_imageResource->image(); >+ Image* image = toRetainedModeBitmapImageIfPossible(m_imageResource->image().get()); > > if (m_imageResource->errorOccurred() && !image->isNull() && usableWidth >= image->width() && usableHeight >= image->height()) { > float deviceScaleFactor = WebCore::deviceScaleFactor(frame()); >@@ -328,7 +328,7 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOf > if (centerY < 0) > centerY = 0; > imageOffset = LayoutSize(leftBorder + leftPad + centerX + 1, topBorder + topPad + centerY + 1); >- context->drawImage(image.get(), style()->colorSpace(), IntRect(roundedIntPoint(paintOffset + imageOffset), imageSize), CompositeSourceOver, shouldRespectImageOrientation()); >+ context->drawImage(image, style()->colorSpace(), IntRect(roundedIntPoint(paintOffset + imageOffset), imageSize), CompositeSourceOver, shouldRespectImageOrientation()); > errorPictureDrawn = true; > } > >@@ -442,7 +442,7 @@ void RenderImage::paintIntoRect(GraphicsContext* context, const LayoutRect& rect > if (!m_imageResource->hasImage() || m_imageResource->errorOccurred() || alignedRect.width() <= 0 || alignedRect.height() <= 0) > return; > >- RefPtr<Image> img = m_imageResource->image(alignedRect.width(), alignedRect.height()); >+ Image* img = toRetainedModeBitmapImageIfPossible(m_imageResource->image(alignedRect.width(), alignedRect.height()).get()); > if (!img || img->isNull()) > return; > >@@ -450,7 +450,7 @@ void RenderImage::paintIntoRect(GraphicsContext* context, const LayoutRect& rect > CompositeOperator compositeOperator = imageElt ? imageElt->compositeOperator() : CompositeSourceOver; > Image* image = m_imageResource->image().get(); > bool useLowQualityScaling = shouldPaintAtLowQuality(context, image, image, alignedRect.size()); >- context->drawImage(m_imageResource->image(alignedRect.width(), alignedRect.height()).get(), style()->colorSpace(), alignedRect, compositeOperator, shouldRespectImageOrientation(), useLowQualityScaling); >+ context->drawImage(img, style()->colorSpace(), alignedRect, compositeOperator, shouldRespectImageOrientation(), useLowQualityScaling); > } > > bool RenderImage::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox*) const >@@ -481,7 +481,7 @@ bool RenderImage::backgroundIsObscured() const > > // Check for bitmap image with alpha. > Image* image = m_imageResource->image().get(); >- if (!image || !image->isBitmapImage() || image->currentFrameHasAlpha()) >+ if (!image || !image->isBitmapImage() || toRetainedModeBitmapImage(image)->currentFrameHasAlpha()) > return false; > > return true; >diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp >index ee0a442f74dec09793783fbf6ad0cf056850f8d3..29a4f045e16d5e6d0828652c73ca4ad4ad644da4 100644 >--- a/Source/WebCore/rendering/RenderLayerBacking.cpp >+++ b/Source/WebCore/rendering/RenderLayerBacking.cpp >@@ -51,6 +51,7 @@ > #include "RenderEmbeddedObject.h" > #include "RenderVideo.h" > #include "RenderView.h" >+#include "RetainedModeBitmapImage.h" > #include "ScrollingCoordinator.h" > #include "StyleResolver.h" > #include "TiledBacking.h" >@@ -1076,6 +1077,10 @@ void RenderLayerBacking::updateImageContents() > if (!cachedImage->isLoaded()) > return; > >+ // We have to wait until the image is fully decoded before setting it on the layer. >+ if (image->isBitmapImage() && !toRetainedModeBitmapImage(image)->currentFrameIsComplete()) >+ return; >+ > // This is a no-op if the layer doesn't have an inner layer for the image. > m_graphicsLayer->setContentsToImage(image); > updateDrawsContent(); >diff --git a/Source/WebCore/rendering/svg/RenderSVGImage.cpp b/Source/WebCore/rendering/svg/RenderSVGImage.cpp >index 56be5cd416bcde26e0a855be1adcea2b43fc0b95..a196e75f8a9df1a28dc6e7ba9054e96f1551538a 100644 >--- a/Source/WebCore/rendering/svg/RenderSVGImage.cpp >+++ b/Source/WebCore/rendering/svg/RenderSVGImage.cpp >@@ -38,6 +38,7 @@ > #include "RenderLayer.h" > #include "RenderSVGResourceContainer.h" > #include "RenderSVGResourceFilter.h" >+#include "RetainedModeBitmapImage.h" > #include "SVGImageElement.h" > #include "SVGLength.h" > #include "SVGPreserveAspectRatio.h" >@@ -127,14 +128,14 @@ void RenderSVGImage::paint(PaintInfo& paintInfo, const LayoutPoint&) > SVGRenderingContext renderingContext(this, childPaintInfo); > > if (renderingContext.isRenderingPrepared()) { >- RefPtr<Image> image = m_imageResource->image(); >+ Image* image = toRetainedModeBitmapImageIfPossible(m_imageResource->image().get()); > FloatRect destRect = m_objectBoundingBox; > FloatRect srcRect(0, 0, image->width(), image->height()); > > SVGImageElement* imageElement = static_cast<SVGImageElement*>(node()); > imageElement->preserveAspectRatio().transformRect(destRect, srcRect); > >- childPaintInfo.context->drawImage(image.get(), ColorSpaceDeviceRGB, destRect, srcRect); >+ childPaintInfo.context->drawImage(image, ColorSpaceDeviceRGB, destRect, srcRect); > } > } > >diff --git a/Source/WebKit/chromium/src/WebImageCG.cpp b/Source/WebKit/chromium/src/WebImageCG.cpp >index 3baea27c9f55483af058aafb6181072e244a06d0..cde139fcecae5838f3625f9c87990a3772109462 100644 >--- a/Source/WebKit/chromium/src/WebImageCG.cpp >+++ b/Source/WebKit/chromium/src/WebImageCG.cpp >@@ -76,7 +76,7 @@ WebImage WebImage::fromData(const WebData& data, const WebSize& desiredSize) > } > } > >- ImageFrameData imageFrameData = source.createFrameAtIndex(index); >+ ImageFrameData imageFrameData = source.requestFrameAtIndex(index); > RetainPtr<CGImageRef> frame(AdoptCF, imageFrameData.m_frame); > if (!frame) > return WebImage(); >diff --git a/Source/WebKit/chromium/src/WebImageSkia.cpp b/Source/WebKit/chromium/src/WebImageSkia.cpp >index fb0df7caffca1fa0b37d6e63a9ee170828860605..5d864a27ba910600359291a576b24646b057e1f2 100644 >--- a/Source/WebKit/chromium/src/WebImageSkia.cpp >+++ b/Source/WebKit/chromium/src/WebImageSkia.cpp >@@ -77,7 +77,7 @@ WebImage WebImage::fromData(const WebData& data, const WebSize& desiredSize) > } > } > >- ImageFrameData imageFrameData = source.createFrameAtIndex(index); >+ ImageFrameData imageFrameData = source.requestFrameAtIndex(index); > OwnPtr<NativeImageSkia> frame = adoptPtr(imageFrameData.m_frame); > if (!frame) > return WebImage();
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 90935
:
151601
|
151864
|
151865
|
152868
|
152891
|
153219
|
153220
|
153221
|
154506
|
154507
|
154871