Source/WebCore/ChangeLog

 12012-07-10 Huang Dongsung <luxtella@company100.net>
 2
 3 Add parallel image decoders
 4 https://bugs.webkit.org/show_bug.cgi?id=90935
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Authored by Huang Dongsung and Kwang Yul Seo.
 9
 10 Make image decoding off the main thread, so that the main thread can spend more
 11 time in loading, parsing, scripting and layout while image decoding threads decode
 12 images in the background.
 13
 14 Refer to https://docs.google.com/document/pub?id=12gf7MhNHfupeR3GdRF-h2Vzg86viCbwXq8_JByHKlg0
 15 for detailed explanation.
 16
 17 No new tests, covered by existing tests.
 18
 19 * CMakeLists.txt:
 20 * GNUmakefile.list.am:
 21 * Target.pri:
 22 * WebCore.gypi:
 23 * WebCore.vcproj/WebCore.vcproj:
 24 * WebCore.xcodeproj/project.pbxproj:
 25 * platform/graphics/BitmapImage.cpp:
 26 (WebCore::BitmapImage::BitmapImage):
 27 (WebCore::BitmapImage::dataChanged):
 28 (WebCore::BitmapImage::ensureFrameIsCached):
 29 (WebCore::BitmapImage::cacheFrame):
 30 (WebCore::BitmapImage::retainedModeRendering):
 31 (WebCore):
 32 (WebCore::BitmapImage::didReceiveFrameAtIndex):
 33 (WebCore::BitmapImage::frameIsCompleteAtIndex):
 34 (WebCore::BitmapImage::currentFrameIsComplete):
 35 * platform/graphics/BitmapImage.h:
 36 (BitmapImage): BitmapImage now implements ImageSourceObserver and passes itself
 37 to ImageSource on construction. When image decoding is finished or a cached image
 38 is available, ImageSource notifies BitmapImage via
 39 ImageSourceObserver::didReceiveImageFrameData(size_t, const ImageFrameData&).
 40 * platform/graphics/ImageSource.cpp:
 41 (WebCore):
 42 (WebCore::ImageSource::clear):
 43 (WebCore::ImageSource::setData):
 44 (WebCore::ImageSource::filenameExtension):
 45 (WebCore::ImageSource::isSizeAvailable):
 46 (WebCore::ImageSource::size):
 47 (WebCore::ImageSource::frameSizeAtIndex):
 48 (WebCore::ImageSource::repetitionCount):
 49 (WebCore::ImageSource::frameCount):
 50 (WebCore::ImageSource::requestFrameAtIndex):
 51 (WebCore::ImageSource::shouldDecodeParallel):
 52 (WebCore::ImageSource::firstFrameIsComplete):
 53 (WebCore::ImageSource::parallelDecode):
 54 (WebCore::ImageSource::didDecode):
 55 (WebCore::ImageSource::createParallelDecoderIfNeeded):
 56 (WebCore::ImageSource::clearParallelDecoder):
 57 (WebCore::ImageSource::serialDecode):
 58 (WebCore::ImageSource::createFrameAtIndex):
 59 * platform/graphics/ImageSource.h:
 60 (WebCore):
 61 (ImageSource):
 62 * platform/graphics/ImageSourceObserver.h:
 63 (ImageSourceObserver):
 64 * platform/graphics/ParallelImageDecoder.cpp: Added.
 65 (WebCore): Once RetainedModeBitmapImage and ImageSource decide it is okay to use
 66 parallel image decoders, this class intercepts decoding requests from ImageSource
 67 and performs image decoding on the decoder thread. Instead of reimplementing all
 68 the decoders from scratch, it reuses the existing image decoders.
 69 (WebCore::ParallelImageDecoder::ParallelImageDecoder):
 70 (WebCore::ParallelImageDecoder::~ParallelImageDecoder):
 71 (WebCore::ParallelImageDecoder::initialize):
 72 (WebCore::ParallelImageDecoder::invalidate):
 73 (WebCore::ParallelImageDecoder::setData):
 74 (WebCore::ParallelImageDecoder::decode):
 75 (WebCore::ParallelImageDecoder::extractSegmentForTask):
 76 (ParallelFrameData):
 77 (WebCore::ParallelFrameData::ParallelFrameData):
 78 (WebCore::ParallelFrameData::~ParallelFrameData):
 79 (WebCore::ParallelImageDecoder::decodeTask):
 80 (WebCore::didDecodeTaskCallback):
 81 (WebCore::createImageFrameData):
 82 (WebCore::ParallelImageDecoder::didDecodeTask):
 83 (WebCore::ParallelImageDecoder::didDecodePartial):
 84 (WebCore::ParallelImageDecoder::appendDecodedDataToImageFrame):
 85 (WebCore::ParallelImageDecoder::syncImageFrame):
 86 (WebCore::ParallelImageDecoder::didDecodeComplete):
 87 * platform/graphics/ParallelImageDecoder.h: Added.
 88 (WebCore):
 89 (ParallelImageDecoder):
 90 (WebCore::ParallelImageDecoder::filenameExtension):
 91 (WebCore::ParallelImageDecoder::size):
 92 (WebCore::ParallelImageDecoder::valid):
 93 (EncodedDataSegment):
 94 (WebCore::ParallelImageDecoder::EncodedDataSegment::EncodedDataSegment):
 95 * platform/graphics/ParallelImageDecoderObserver.h: Copied from Source/WebCore/platform/graphics/ImageSourceObserver.h.
 96 (WebCore):
 97 (ParallelImageDecoderObserver):
 98 (WebCore::ParallelImageDecoderObserver::~ParallelImageDecoderObserver):
 99 * platform/graphics/RetainedModeBitmapImage.cpp: Added.
 100 (WebCore): Because image decoding is used in various contexts in WebKit, it is simply
 101 impossible to make all parallel decoding parallel. Instead, we selectively use parallel
 102 image decoders where possible and use the existing sequential image decoders otherwise.
 103 RetainedModeBitmapImage wraps a BitmapImage and helps decide when it is safe and beneficial
 104 to use parallel image decoders.
 105 (WebCore::RetainedModeBitmapImage::create):
 106 (WebCore::RetainedModeBitmapImage::RetainedModeBitmapImage):
 107 (WebCore::RetainedModeBitmapImage::hasSingleSecurityOrigin):
 108 (WebCore::RetainedModeBitmapImage::size):
 109 (WebCore::RetainedModeBitmapImage::getHotSpot):
 110 (WebCore::RetainedModeBitmapImage::dataChanged):
 111 (WebCore::RetainedModeBitmapImage::filenameExtension):
 112 (WebCore::RetainedModeBitmapImage::destroyDecodedData):
 113 (WebCore::RetainedModeBitmapImage::decodedSize):
 114 (WebCore::RetainedModeBitmapImage::startAnimation):
 115 (WebCore::RetainedModeBitmapImage::stopAnimation):
 116 (WebCore::RetainedModeBitmapImage::resetAnimation):
 117 (WebCore::RetainedModeBitmapImage::nativeImageForCurrentFrame):
 118 (WebCore::RetainedModeBitmapImage::currentFrameHasAlpha):
 119 (WebCore::RetainedModeBitmapImage::currentFrameIsComplete):
 120 (WebCore::RetainedModeBitmapImage::draw):
 121 (WebCore::RetainedModeBitmapImage::mayFillWithSolidColor):
 122 (WebCore::RetainedModeBitmapImage::solidColor):
 123 (WebCore::RetainedModeSaver::RetainedModeSaver):
 124 (WebCore::RetainedModeSaver::~RetainedModeSaver):
 125 (WebCore::toRetainedModeBitmapImage):
 126 (WebCore::toRetainedModeBitmapImageIfPossible):
 127 * platform/graphics/RetainedModeBitmapImage.h: Added.
 128 (WebCore):
 129 (RetainedModeBitmapImage):
 130 (WebCore::RetainedModeBitmapImage::~RetainedModeBitmapImage):
 131 (WebCore::RetainedModeBitmapImage::retainedModeRendering):
 132 (WebCore::RetainedModeBitmapImage::beginRetainedMode):
 133 (WebCore::RetainedModeBitmapImage::endRetainedMode):
 134 (RetainedModeSaver):
 135 * platform/graphics/cairo/BitmapImageCairo.cpp:
 136 (WebCore::BitmapImage::BitmapImage):
 137 * platform/graphics/cairo/GraphicsContext3DCairo.cpp:
 138 (WebCore::GraphicsContext3D::getImageData):
 139 * platform/graphics/cg/GraphicsContext3DCG.cpp:
 140 (WebCore::GraphicsContext3D::getImageData):
 141 * platform/graphics/cg/ImageCG.cpp:
 142 (WebCore::BitmapImage::BitmapImage):
 143 * platform/graphics/cg/ImageSourceCG.cpp:
 144 (WebCore::ImageSource::requestFrameAtIndex):
 145 * platform/graphics/openvg/ImageOpenVG.cpp:
 146 (WebCore::BitmapImage::BitmapImage):
 147 * platform/graphics/qt/ImageQt.cpp:
 148 (WebCore::BitmapImage::BitmapImage):
 149 * platform/graphics/skia/GraphicsContext3DSkia.cpp:
 150 (WebCore::GraphicsContext3D::getImageData):
 151 * platform/graphics/wx/ImageWx.cpp:
 152 (WebCore::BitmapImage::BitmapImage):
 153 * platform/image-decoders/ImageDecoder.cpp:
 154 (WebCore::ImageFrame::ImageFrame):
 155 (WebCore::ImageFrame::clearPixelData):
 156 (WebCore::ImageFrame::copyBitmapData):
 157 (WebCore::ImageFrame::setSize):
 158 * platform/image-decoders/ImageDecoder.h:
 159 (WebCore::ImageFrame::lastDecodedRow):
 160 (WebCore::ImageFrame::setLastDecodedRow):
 161 (ImageFrame):
 162 (WebCore::ImageDecoder::data):
 163 (ImageDecoder):
 164 (WebCore::ImageDecoder::firstImageFrameWithoutDecode):
 165 * platform/image-decoders/blackberry/JPEGImageDecoder.cpp:
 166 (WebCore::ImageReader::decode):
 167 * platform/image-decoders/bmp/BMPImageDecoder.cpp:
 168 (WebCore::BMPImageDecoder::isSizeAvailable):
 169 * platform/image-decoders/bmp/BMPImageReader.cpp:
 170 (WebCore::BMPImageReader::decodeBMP):
 171 (WebCore::BMPImageReader::processRLEData):
 172 (WebCore::BMPImageReader::processNonRLEData):
 173 * platform/image-decoders/gif/GIFImageDecoder.cpp:
 174 (WebCore::GIFImageDecoder::haveDecodedRow):
 175 (WebCore::GIFImageDecoder::initFrameBuffer):
 176 * platform/image-decoders/jpeg/JPEGImageDecoder.cpp:
 177 (WebCore::JPEGImageDecoder::outputScanlines):
 178 * platform/image-decoders/png/PNGImageDecoder.cpp:
 179 (WebCore::PNGImageDecoder::rowAvailable):
 180 * platform/image-decoders/skia/ImageDecoderSkia.cpp:
 181 (WebCore::ImageFrame::clearPixelData):
 182 (WebCore::ImageFrame::copyBitmapData):
 183 (WebCore::ImageFrame::setSize):
 184 * platform/image-decoders/webp/WEBPImageDecoder.cpp:
 185 (WebCore::WEBPImageDecoder::decode):
 186 * rendering/RenderImage.cpp:
 187 (WebCore::RenderImage::paintReplaced):
 188 (WebCore::RenderImage::paintIntoRect):
 189 (WebCore::RenderImage::backgroundIsObscured):
 190 * rendering/RenderLayerBacking.cpp:
 191 (WebCore::RenderLayerBacking::updateImageContents):
 192 * rendering/svg/RenderSVGImage.cpp:
 193 (WebCore::RenderSVGImage::paint):
 194
11952012-07-09 Huang Dongsung <luxtella@company100.net>
2196
3197 Refactoring metadata of BitmapImage.

Source/WebKit/chromium/ChangeLog

 12012-07-10 Huang Dongsung <luxtella@company100.net>
 2
 3 Add parallel image decoders
 4 https://bugs.webkit.org/show_bug.cgi?id=90935
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Authored by Huang Dongsung and Kwang Yul Seo.
 9
 10 Make image decoding off the main thread, so that the main thread can spend more
 11 time in loading, parsing, scripting and layout while image decoding threads decode
 12 images in the background.
 13
 14 Refer to https://docs.google.com/document/pub?id=12gf7MhNHfupeR3GdRF-h2Vzg86viCbwXq8_JByHKlg0
 15 for detailed explanation.
 16
 17 * src/WebImageCG.cpp:
 18 (WebKit::WebImage::fromData):
 19 * src/WebImageSkia.cpp:
 20 (WebKit::WebImage::fromData):
 21
1222012-07-03 Huang Dongsung <luxtella@company100.net>
223
324 Prepare for parallel image decoder.

Source/WebCore/CMakeLists.txt

@@SET(WebCore_SOURCES
11991199 platform/graphics/Path.cpp
12001200 platform/graphics/PathTraversalState.cpp
12011201 platform/graphics/Pattern.cpp
 1202 platform/graphics/ParallelImageDecoder.cpp
 1203 platform/graphics/RetainedModeBitmapImage.cpp
12021204 platform/graphics/Region.cpp
12031205 platform/graphics/RoundedRect.cpp
12041206 platform/graphics/SegmentedFontData.cpp

Source/WebCore/GNUmakefile.list.am

@@webcore_sources += \
31933193 Source/WebCore/platform/graphics/ColorSpace.h \
31943194 Source/WebCore/platform/graphics/DashArray.h \
31953195 Source/WebCore/platform/graphics/Extensions3D.h \
 3196 Source/WebCore/platform/graphics/ParallelImageDecoder.cpp \
 3197 Source/WebCore/platform/graphics/ParallelImageDecoder.h \
 3198 Source/WebCore/platform/graphics/ParallelImageDecoderObserver.h \
 3199 Source/WebCore/platform/graphics/RetainedModeBitmapImage.cpp \
 3200 Source/WebCore/platform/graphics/RetainedModeBitmapImage.h \
31963201 Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp \
31973202 Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp \
31983203 Source/WebCore/platform/graphics/cairo/CairoUtilities.h \

Source/WebCore/Target.pri

@@SOURCES += \
11031103 platform/graphics/FontFamily.cpp \
11041104 platform/graphics/FontFeatureSettings.cpp \
11051105 platform/graphics/BitmapImage.cpp \
 1106 platform/graphics/RetainedModeBitmapImage.cpp \
11061107 platform/graphics/Color.cpp \
11071108 platform/graphics/CrossfadeGeneratedImage.cpp \
11081109 platform/graphics/FloatPoint3D.cpp \

@@SOURCES += \
11261127 platform/graphics/ImageOrientation.cpp \
11271128 platform/graphics/ImageSource.cpp \
11281129 platform/graphics/IntRect.cpp \
 1130 platform/graphics/ParallelImageDecoder.cpp \
11291131 platform/graphics/Path.cpp \
11301132 platform/graphics/PathTraversalState.cpp \
11311133 platform/graphics/Pattern.cpp \

@@HEADERS += \
22412243 platform/mock/GeolocationClientMock.cpp \
22422244 platform/mock/ScrollbarThemeMock.h \
22432245 platform/graphics/BitmapImage.h \
 2246 platform/graphics/RetainedModeBitmapImage.h \
22442247 platform/graphics/Color.h \
22452248 platform/graphics/CrossfadeGeneratedImage.h \
22462249 platform/graphics/filters/CustomFilterGlobalContext.h \

@@HEADERS += \
23072310 platform/graphics/IntPointHash.h \
23082311 platform/graphics/IntRect.h \
23092312 platform/graphics/MediaPlayer.h \
 2313 platform/graphics/ParallelImageDecoder.h \
 2314 platform/graphics/ParallelImageDecoderObserver.h \
23102315 platform/graphics/Path.h \
23112316 platform/graphics/PathTraversalState.h \
23122317 platform/graphics/Pattern.h \

Source/WebCore/WebCore.gypi

35013501 'platform/graphics/IntRect.cpp',
35023502 'platform/graphics/MediaPlayer.cpp',
35033503 'platform/graphics/MediaPlayerPrivate.h',
 3504 'platform/graphics/ParallelImageDecoder.cpp',
 3505 'platform/graphics/ParallelImageDecoder.h',
 3506 'platform/graphics/ParallelImageDecoderObserver.h',
35043507 'platform/graphics/Path.cpp',
35053508 'platform/graphics/PathTraversalState.cpp',
35063509 'platform/graphics/PathTraversalState.h',
35073510 'platform/graphics/Pattern.cpp',
35083511 'platform/graphics/Region.cpp',
 3512 'platform/graphics/RetainedModeBitmapImage.cpp',
 3513 'platform/graphics/RetainedModeBitmapImage.h',
35093514 'platform/graphics/RoundedRect.cpp',
35103515 'platform/graphics/SegmentedFontData.cpp',
35113516 'platform/graphics/SegmentedFontData.h',

Source/WebCore/WebCore.vcproj/WebCore.vcproj

2939029390 >
2939129391 </File>
2939229392 <File
 29393 RelativePath="..\platform\graphics\ParallelImageDecoder.cpp"
 29394 >
 29395 </File>
 29396 <File
 29397 RelativePath="..\platform\graphics\ParallelImageDecoder.h"
 29398 >
 29399 </File>
 29400 <File
 29401 RelativePath="..\platform\graphics\ParallelImageDecoderObserver.h"
 29402 >
 29403 </File>
 29404 <File
2939329405 RelativePath="..\platform\graphics\PathTraversalState.cpp"
2939429406 >
2939529407 </File>

2941829430 >
2941929431 </File>
2942029432 <File
 29433 RelativePath="..\platform\graphics\RetainedModeBitmapImage.cpp"
 29434 >
 29435 </File>
 29436 <File
 29437 RelativePath="..\platform\graphics\RetainedModeBitmapImage.h"
 29438 >
 29439 </File>
 29440 <File
2942129441 RelativePath="..\platform\graphics\RoundedRect.cpp"
2942229442 >
2942329443 </File>

Source/WebCore/WebCore.xcodeproj/project.pbxproj

14181418 4B3043CD0AE0373B00A82647 /* Editor.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B3043CB0AE0373B00A82647 /* Editor.h */; settings = {ATTRIBUTES = (Private, ); }; };
14191419 4B3480930EEF50D400AC1B41 /* ImageSourceCGMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B3480910EEF50D400AC1B41 /* ImageSourceCGMac.mm */; };
14201420 4B3480940EEF50D400AC1B41 /* ImageSourceCG.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B3480920EEF50D400AC1B41 /* ImageSourceCG.h */; };
 1421 5B3480930EEF50D400AC1B41 /* RetainedModeBitmapImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5B3480910EEF50D400AC1B41 /* RetainedModeBitmapImage.cpp */; };
 1422 5B3480940EEF50D400AC1B41 /* RetainedModeBitmapImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B3480920EEF50D400AC1B41 /* RetainedModeBitmapImage.h */; };
14211423 4B6FA6F40C39E48C00087011 /* SmartReplace.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B6FA6F20C39E48C00087011 /* SmartReplace.h */; settings = {ATTRIBUTES = (Private, ); }; };
14221424 4B6FA6F50C39E48C00087011 /* SmartReplace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6FA6F30C39E48C00087011 /* SmartReplace.cpp */; };
14231425 4B6FA6F70C39E4A100087011 /* SmartReplaceCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6FA6F60C39E4A100087011 /* SmartReplaceCF.cpp */; };

85088510 4B3043CB0AE0373B00A82647 /* Editor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Editor.h; sourceTree = "<group>"; };
85098511 4B3480910EEF50D400AC1B41 /* ImageSourceCGMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ImageSourceCGMac.mm; sourceTree = "<group>"; };
85108512 4B3480920EEF50D400AC1B41 /* ImageSourceCG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageSourceCG.h; sourceTree = "<group>"; };
 8513 5B3480910EEF50D400AC1B41 /* RetainedModeBitmapImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RetainedModeBitmapImage.cpp; sourceTree = "<group>"; };
 8514 5B3480920EEF50D400AC1B41 /* RetainedModeBitmapImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RetainedModeBitmapImage.h; sourceTree = "<group>"; };
85118515 4B6FA6F20C39E48C00087011 /* SmartReplace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SmartReplace.h; sourceTree = "<group>"; };
85128516 4B6FA6F30C39E48C00087011 /* SmartReplace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SmartReplace.cpp; sourceTree = "<group>"; };
85138517 4B6FA6F60C39E4A100087011 /* SmartReplaceCF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SmartReplaceCF.cpp; sourceTree = "<group>"; };

1953419538 A80A38FD0E50CC8200A25EBC /* PatternCG.cpp */,
1953519539 B27535360B053814002CE64F /* PDFDocumentImage.cpp */,
1953619540 B27535370B053814002CE64F /* PDFDocumentImage.h */,
 19541 5B3480910EEF50D400AC1B41 /* RetainedModeBitmapImage.cpp */,
 19542 5B3480920EEF50D400AC1B41 /* RetainedModeBitmapImage.h */,
1953719543 B275352A0B053814002CE64F /* TransformationMatrixCG.cpp */,
1953819544 );
1953919545 path = cg;

2447024476 7EE6846F12D26E3800E79415 /* ResourceRequestCFNet.h in Headers */,
2447124477 7EE6847012D26E3800E79415 /* ResourceResponse.h in Headers */,
2447224478 514C767F0CE923A1007EF3CD /* ResourceResponseBase.h in Headers */,
 24479 5B3480940EEF50D400AC1B41 /* RetainedModeBitmapImage.h in Headers */,
2447324480 FD3160A512B026F700C1A359 /* Reverb.h in Headers */,
2447424481 FD3160A712B026F700C1A359 /* ReverbAccumulationBuffer.h in Headers */,
2447524482 FD3160A912B026F700C1A359 /* ReverbConvolver.h in Headers */,

2764927656 514C767E0CE923A1007EF3CD /* ResourceResponseBase.cpp in Sources */,
2765027657 7EE6847112D26E3800E79415 /* ResourceResponseCFNet.cpp in Sources */,
2765127658 514C76550CE9234F007EF3CD /* ResourceResponseMac.mm in Sources */,
 27659 5B3480930EEF50D400AC1B41 /* RetainedModeBitmapImage.cpp in Sources */,
2765227660 FD3160A412B026F700C1A359 /* Reverb.cpp in Sources */,
2765327661 FD3160A612B026F700C1A359 /* ReverbAccumulationBuffer.cpp in Sources */,
2765427662 FD3160A812B026F700C1A359 /* ReverbConvolver.cpp in Sources */,

Source/WebCore/platform/graphics/BitmapImage.cpp

@@BitmapImage::BitmapImage(ImageObserver* observer)
6464 , m_sizeAvailable(false)
6565 , m_hasUniformFrameSize(true)
6666 , m_haveFrameCount(false)
 67 , m_isCachingFrame(false)
6768{
6869}
6970

@@bool BitmapImage::dataChanged(bool allDataReceived)
208209 // NOTE: Don't call frameIsCompleteAtIndex() here, that will try to
209210 // decode any uncached (i.e. never-decoded or
210211 // cleared-on-a-previous-pass) frames!
211  if (m_frames[i].m_frame && !m_frames[i].m_isComplete)
 212
 213 // NOTE: Don't clear the current frame, because the frame might have been decoded
 214 // in retained mode and RenderImage hasn't render this decoded image yet.
 215 // If the current frame is removed here, the image element will be rendered as white box.
 216 // The current frame will be removed later when retained mode decoding is finished.
 217 if (m_frames[i].m_frame && !m_frames[i].m_isComplete && m_currentFrame != i)
212218 framesCleared += (m_frames[i].clear(true) ? 1 : 0);
213219 }
214220 destroyMetadataAndNotify(framesCleared);

@@bool BitmapImage::ensureFrameIsCached(size_t index)
256262 if (index >= frameCount())
257263 return false;
258264
259  if (index >= m_frames.size() || !m_frames[index].m_frame)
 265 if (m_isCachingFrame)
 266 return true;
 267
 268 // m_frame can exist when m_isComplete is false, so we need to cache a new frame even if m_frame exists.
 269 // See BitmapImage::dataChanged for explanation.
 270 bool needToCache = index >= m_frames.size() || !m_frames[index].m_frame || !m_frames[index].m_isComplete;
 271 if (needToCache) {
 272 m_isCachingFrame = true;
260273 cacheFrame(index);
 274 m_isCachingFrame = false;
 275 }
 276
261277 return true;
262278}
263279

@@void BitmapImage::cacheFrame(size_t index)
267283 if (m_frames.size() < numFrames)
268284 m_frames.grow(numFrames);
269285
270  m_source.requestFrameAtIndex(index);
 286 m_source.requestFrameAtIndex(index, retainedModeRendering());
271287}
272288
273 void BitmapImage::didReceiveFrameAtIndex(size_t index, const ImageFrameData& imageFrameData)
 289bool BitmapImage::retainedModeRendering() const
274290{
 291 return m_retainedModeImage.get() && m_retainedModeImage->retainedModeRendering();
 292}
 293
 294void BitmapImage::didReceiveFrameAtIndex(size_t index, const ImageFrameData& imageFrameData, bool retained, bool parallelDecoderCanceled)
 295{
 296 // It is possible to call cacheFrame indirectly in this method.
 297 RetainedModeSaver retainedModeSaver(m_retainedModeImage.get(), retained);
 298
 299 // m_frames[index].m_frame must be cleared before it is replaced with new decoded frame.
 300 // If we forget to clear m_frame, the old m_frame leaks.
 301 // See BitmapImage::dataChanged for explanation why the decoded frame must be removed here.
 302 int framesCleared = 0;
 303 if (m_frames[index].m_frame)
 304 framesCleared += (m_frames[index].clear(true) ? 1 : 0);
 305 destroyMetadataAndNotify(framesCleared);
 306
275307 m_frames[index].setFromImageFrameData(imageFrameData);
276308
277309 size_t numFrames = frameCount();

@@void BitmapImage::didReceiveFrameAtIndex(size_t index, const ImageFrameData& ima
288320 // to determine image properties.
289321 deltaBytes -= m_decodedPropertiesSize;
290322 m_decodedPropertiesSize = 0;
291  if (imageObserver())
 323 if (imageObserver()) {
292324 imageObserver()->decodedSizeChanged(this, deltaBytes);
 325
 326 if ((m_frames[index].m_isComplete && retained) || parallelDecoderCanceled)
 327 imageObserver()->changedInRect(this, IntRect(IntPoint(), size()));
 328 }
293329 }
294330}
295331

@@bool BitmapImage::frameIsCompleteAtIndex(size_t index)
309345 // (see destroyDecodedData() and frameDurationAtIndex())
310346 if (!ensureFrameIsCached(index))
311347 return false;
312  return m_frames[index].m_isComplete;
 348 // If the frame at the given index is decoded by parallel image decoders, m_frame can be 0 even if m_isComplete is true.
 349 return m_frames[index].m_isComplete && m_frames[index].m_frame;
 350}
 351
 352bool BitmapImage::currentFrameIsComplete()
 353{
 354 return frameIsCompleteAtIndex(m_currentFrame);
313355}
314356
315357float BitmapImage::frameDurationAtIndex(size_t index)

Source/WebCore/platform/graphics/BitmapImage.h

3333#include "ImageOrientation.h"
3434#include "ImageSourceObserver.h"
3535#include "IntSize.h"
 36#include "RetainedModeBitmapImage.h"
3637
3738#if PLATFORM(MAC)
3839#include <wtf/RetainPtr.h>

@@private:
120121// =================================================
121122
122123class BitmapImage : public Image, public ImageSourceObserver {
 124 friend class RetainedModeBitmapImage;
123125 friend class GeneratedImage;
124126 friend class CrossfadeGeneratedImage;
125127 friend class GeneratorGeneratedImage;
126128 friend class GraphicsContext;
 129 friend RetainedModeBitmapImage* toRetainedModeBitmapImage(Image*);
127130public:
128131 static PassRefPtr<BitmapImage> create(NativeImagePtr nativeImage, ImageObserver* observer = 0)
129132 {

@@public:
201204#endif
202205
203206 // ImageSourceObserver
204  virtual void didReceiveFrameAtIndex(size_t, const ImageFrameData&);
 207 virtual void didReceiveFrameAtIndex(size_t, const ImageFrameData&, bool retained = false, bool parallelDecoderCanceled = false);
205208
206209private:
207210 void updateSize() const;

@@protected:
238241 bool frameIsCompleteAtIndex(size_t);
239242 float frameDurationAtIndex(size_t);
240243
 244 bool currentFrameIsComplete();
 245
241246 // Decodes and caches a frame. Never accessed except internally.
242247 void cacheFrame(size_t index);
243248 // Called before accessing m_frames[index]. Returns false on index out of bounds.

@@protected:
293298 virtual bool mayFillWithSolidColor();
294299 virtual Color solidColor() const;
295300
 301 bool retainedModeRendering() const;
 302
296303 ImageSource m_source;
297304 mutable IntSize m_size; // The size to use for the overall image (will just be the size of the first image).
298305 mutable IntSize m_sizeRespectingOrientation;

@@protected:
317324 mutable unsigned m_decodedPropertiesSize; // The size of data decoded by the source to determine image properties (e.g. size, frame count, etc).
318325 size_t m_frameCount;
319326
 327 RefPtr<RetainedModeBitmapImage> m_retainedModeImage;
 328
320329 bool m_isSolidColor : 1; // Whether or not we are a 1x1 solid image.
321330 bool m_checkedForSolidColor : 1; // Whether we've checked the frame for solid color.
322331

@@protected:
327336 bool m_sizeAvailable : 1; // Whether or not we can obtain the size of the first image frame yet from ImageIO.
328337 mutable bool m_hasUniformFrameSize : 1;
329338 mutable bool m_haveFrameCount : 1;
 339
 340 bool m_isCachingFrame : 1;
330341};
331342
332343}

Source/WebCore/platform/graphics/ImageSource.cpp

3535#include "ImageOrientation.h"
3636#include "ImageSourceObserver.h"
3737#include "NotImplemented.h"
 38#include "ParallelImageDecoder.h"
 39#include <wtf/NumberOfCores.h>
3840
3941namespace WebCore {
4042
 43static const unsigned s_resolutionThresholdForParallel = 512 * 512;
 44
4145#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
4246unsigned ImageSource::s_maxPixelsPerDecodedImage = 1024 * 1024;
4347#endif

@@ImageSource::~ImageSource()
6670void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived)
6771{
6872 if (!destroyAll) {
69  if (m_decoder)
 73 // Only GIF decoder implements clearFrameBufferCache.
 74 if (m_decoder && !m_parallelDecoder)
7075 m_decoder->clearFrameBufferCache(clearBeforeFrame);
7176 return;
7277 }
7378
 79 if (m_parallelDecoder.get())
 80 clearParallelDecoder();
 81
7482 delete m_decoder;
7583 m_decoder = 0;
7684 if (data)

@@void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
8896 // This method will examine the data and instantiate an instance of the appropriate decoder plugin.
8997 // If insufficient bytes are available to determine the image type, no decoder plugin will be
9098 // made.
 99
 100 if (m_parallelDecoder.get()) {
 101 ASSERT(m_decoder);
 102 m_parallelDecoder->setData(data, allDataReceived);
 103 return;
 104 }
 105
91106 if (!m_decoder) {
92107 m_decoder = static_cast<NativeImageSourcePtr>(ImageDecoder::create(*data, m_alphaOption, m_gammaAndColorProfileOption));
93108#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)

@@void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
102117
103118String ImageSource::filenameExtension() const
104119{
 120 if (m_parallelDecoder.get())
 121 return m_parallelDecoder->filenameExtension();
105122 return m_decoder ? m_decoder->filenameExtension() : String();
106123}
107124
108125bool ImageSource::isSizeAvailable()
109126{
 127 if (m_parallelDecoder.get())
 128 return true;
110129 return m_decoder && m_decoder->isSizeAvailable();
111130}
112131

@@IntSize ImageSource::size(RespectImageOrientationEnum shouldRespectOrientation)
116135 if (shouldRespectOrientation == RespectImageOrientation)
117136 notImplemented();
118137
 138 if (m_parallelDecoder.get())
 139 return m_parallelDecoder->size();
119140 return m_decoder ? m_decoder->size() : IntSize();
120141}
121142

@@IntSize ImageSource::frameSizeAtIndex(size_t index, RespectImageOrientationEnum
125146 if (shouldRespectOrientation == RespectImageOrientation)
126147 notImplemented();
127148
 149 if (m_parallelDecoder.get())
 150 return m_parallelDecoder->size();
128151 return m_decoder ? m_decoder->frameSizeAtIndex(index) : IntSize();
129152}
130153

@@size_t ImageSource::bytesDecodedToDetermineProperties() const
140163
141164int ImageSource::repetitionCount()
142165{
 166 if (m_parallelDecoder.get())
 167 return cAnimationNone;
143168 return m_decoder ? m_decoder->repetitionCount() : cAnimationNone;
144169}
145170
146171size_t ImageSource::frameCount() const
147172{
 173 if (m_parallelDecoder.get())
 174 return 1;
148175 return m_decoder ? m_decoder->frameCount() : 0;
149176}
150177
151 void ImageSource::requestFrameAtIndex(size_t index)
 178ImageFrameData ImageSource::requestFrameAtIndex(size_t index, bool retainedModeRendering)
 179{
 180 ASSERT(!(retainedModeRendering && index));
 181 ASSERT(!(retainedModeRendering && !m_observer));
 182
 183 if (!m_decoder) {
 184 m_observer->didReceiveFrameAtIndex(index, ImageFrameData());
 185 return ImageFrameData();
 186 }
 187
 188 if (!retainedModeRendering || !m_observer || firstFrameIsComplete())
 189 return serialDecode(index);
 190
 191 if (shouldDecodeParallel()) {
 192 parallelDecode();
 193 return ImageFrameData();
 194 }
 195
 196 return serialDecode(index);
 197}
 198
 199bool ImageSource::shouldDecodeParallel()
 200{
 201 ASSERT(m_decoder);
 202
 203 if (m_parallelDecoder.get())
 204 return true;
 205
 206 if (WTF::numberOfProcessorCores() == 1)
 207 return false;
 208
 209 String fileExt = filenameExtension();
 210 if (fileExt == "ico" || fileExt == "gif")
 211 return false;
 212
 213 if (!isSizeAvailable())
 214 return false;
 215
 216 if (size().area() < s_resolutionThresholdForParallel)
 217 return false;
 218
 219 return true;
 220}
 221
 222bool ImageSource::firstFrameIsComplete()
 223{
 224 ASSERT(m_decoder);
 225 ImageFrame* imageFrame = 0;
 226 if (!m_parallelDecoder)
 227 imageFrame = m_decoder->firstImageFrameWithoutDecode();
 228 return imageFrame && frameIsCompleteAtIndex(imageFrame);
 229}
 230
 231void ImageSource::parallelDecode()
 232{
 233 createParallelDecoderIfNeeded();
 234 m_parallelDecoder->decode();
 235}
 236
 237void ImageSource::didDecode(const ImageFrameData& imageFrameData)
 238{
 239 ASSERT(m_observer);
 240 m_observer->didReceiveFrameAtIndex(0, imageFrameData, true);
 241
 242 if (imageFrameData.m_isComplete)
 243 clearParallelDecoder();
 244}
 245
 246void ImageSource::createParallelDecoderIfNeeded()
 247{
 248 if (!m_parallelDecoder)
 249 m_parallelDecoder = adoptRef(new ParallelImageDecoder(this, m_decoder));
 250}
 251
 252void ImageSource::clearParallelDecoder()
152253{
153254 ASSERT(m_observer);
 255 m_parallelDecoder->invalidate();
 256 m_parallelDecoder.clear();
 257}
 258
 259ImageFrameData ImageSource::serialDecode(size_t index)
 260{
 261 bool parallelDecoderCanceled = false;
 262 // RenderImage and CanvasElement can share the same CachedImage.
 263 if (m_parallelDecoder.get()) {
 264 ASSERT(m_observer);
 265 clearParallelDecoder();
 266 parallelDecoderCanceled = true;
 267 }
 268
154269 ImageFrameData imageFrameData = createFrameAtIndex(index);
155  m_observer->didReceiveFrameAtIndex(index, imageFrameData);
 270
 271 if (m_observer)
 272 m_observer->didReceiveFrameAtIndex(index, imageFrameData, false /* retainedMode */, parallelDecoderCanceled);
 273
 274 return imageFrameData;
156275}
157276
158277ImageFrameData ImageSource::createFrameAtIndex(size_t index)
159278{
 279 ASSERT(!m_parallelDecoder);
160280 if (!m_decoder)
161281 return ImageFrameData();
162282

Source/WebCore/platform/graphics/ImageSource.h

2929#define ImageSource_h
3030
3131#include "ImageOrientation.h"
 32#if !USE(CG)
 33#include "ParallelImageDecoderObserver.h"
 34#endif
3235
3336#include <wtf/Forward.h>
3437#include <wtf/Noncopyable.h>

@@class ImageOrientation;
6568class ImageSourceObserver;
6669class IntPoint;
6770class IntSize;
 71#if !USE(CG)
 72class ParallelImageDecoder;
 73#endif
6874class SharedBuffer;
6975
7076#if USE(CG)

@@const int cAnimationLoopOnce = 0;
143149const int cAnimationLoopInfinite = -1;
144150const int cAnimationNone = -2;
145151
146 class ImageSource {
 152class ImageSource
 153#if !USE(CG)
 154 : public ParallelImageDecoderObserver
 155#endif
 156{
147157 WTF_MAKE_NONCOPYABLE(ImageSource);
148158public:
149159 enum AlphaOption {

@@public:
210220
211221 size_t frameCount() const;
212222
213  // Callers should not call this after calling clear() with a higher index;
 223 // NOTE: Callers should not call this after calling clear() with a higher index;
214224 // see comments on clear() above.
215  void requestFrameAtIndex(size_t);
216  ImageFrameData createFrameAtIndex(size_t);
 225 // NOTE: If ImageSource has ImageSourceObserver, this method sends the result via didDecode().
 226 // Otherwise, this method returns the result. e.g. GraphicsContext3D
 227 ImageFrameData requestFrameAtIndex(size_t, bool retainedModeRendering = false);
217228
218229#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
219230 static unsigned maxPixelsPerDecodedImage() { return s_maxPixelsPerDecodedImage; }
220231 static void setMaxPixelsPerDecodedImage(unsigned maxPixels) { s_maxPixelsPerDecodedImage = maxPixels; }
221232#endif
222233
 234#if !USE(CG)
 235 // ParallelImageDecoderObserver
 236 virtual void didDecode(const ImageFrameData&);
 237#endif
 238
223239private:
 240 ImageFrameData createFrameAtIndex(size_t);
224241#if USE(CG)
225242 float frameDurationAtIndex(size_t);
226243 bool frameHasAlphaAtIndex(size_t); // Whether or not the frame actually used any alpha.

@@private:
233250 ImageOrientation orientationAtIndex(ImageFrame*) const;
234251#endif
235252
 253#if !USE(CG)
 254 void createParallelDecoderIfNeeded();
 255 void clearParallelDecoder();
 256 bool shouldDecodeParallel();
 257 bool firstFrameIsComplete();
 258 void parallelDecode();
 259 ImageFrameData serialDecode(size_t);
 260
 261 RefPtr<ParallelImageDecoder> m_parallelDecoder;
 262#endif
 263
236264 NativeImageSourcePtr m_decoder;
237265 ImageSourceObserver* m_observer;
 266
238267 AlphaOption m_alphaOption;
239268 GammaAndColorProfileOption m_gammaAndColorProfileOption;
240269#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)

Source/WebCore/platform/graphics/ImageSourceObserver.h

@@class ImageFrameData;
3333// Interface for notification about changes to an ImageSource, including decoding.
3434class ImageSourceObserver {
3535public:
36  virtual void didReceiveFrameAtIndex(size_t, const ImageFrameData&) = 0;
 36 virtual void didReceiveFrameAtIndex(size_t, const ImageFrameData&, bool retained = false, bool parallelDecoderCanceled = false) = 0;
3737
3838protected:
3939 virtual ~ImageSourceObserver() { }

Source/WebCore/platform/graphics/ParallelImageDecoder.cpp

 1/*
 2 * Copyright (C) 2012 Company 100 Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27#include "ParallelImageDecoder.h"
 28
 29#include <wtf/MainThread.h>
 30#include <wtf/OwnArrayPtr.h>
 31#include <wtf/OwnPtr.h>
 32#include <wtf/PassOwnArrayPtr.h>
 33#include <wtf/PassOwnPtr.h>
 34
 35namespace WebCore {
 36
 37struct ParallelFrameData;
 38void didDecodeTaskCallback(ParallelFrameData*);
 39static ImageFrameData createImageFrameData(ParallelFrameData*);
 40
 41ParallelImageDecoder::ParallelImageDecoder(ParallelImageDecoderObserver* observer, ImageDecoder* decoder)
 42 : m_observer(observer)
 43 , m_isAllDataReceived(false)
 44 , m_bytesOfDataConsumed(0)
 45 , m_imageDecoder(0)
 46{
 47 initialize(decoder);
 48}
 49
 50ParallelImageDecoder::~ParallelImageDecoder()
 51{
 52 ASSERT(!valid());
 53}
 54
 55void ParallelImageDecoder::initialize(ImageDecoder* decoder)
 56{
 57 ASSERT(isMainThread());
 58 ASSERT(decoder->isSizeAvailable() && !decoder->size().isEmpty());
 59
 60 m_size = decoder->size();
 61 m_filenameExtension = decoder->filenameExtension();
 62
 63 setData(decoder->data(), decoder->isAllDataReceived());
 64 m_bytesOfDataConsumed = 0;
 65
 66 m_imageFrame.setSize(m_size.width(), m_size.height());
 67
 68 m_imageDecoder = decoder;
 69 m_imageDecoder->setData(0, false);
 70 // After this line, it is illegal for the main thread to access m_imageDecoder.
 71
 72 // This must be the last line because ImageDecodeWorker guarantees
 73 // the visibility of members in the task thread.
 74 m_decodeWorker = ImageDecodeWorker::acquireSharedWorker();
 75}
 76
 77void ParallelImageDecoder::invalidate()
 78{
 79 ASSERT(isMainThread());
 80 ASSERT(m_imageDecoder);
 81
 82 m_decodeWorker.clear();
 83 // The main thread can use m_imageDecoder because other threads do not access m_imageDecoder after this line.
 84
 85 m_imageDecoder->setData(m_data.get(), m_isAllDataReceived);
 86
 87 m_size = IntSize();
 88 m_filenameExtension = "";
 89
 90 m_isAllDataReceived = false;
 91 m_data.clear();
 92 m_bytesOfDataConsumed = 0;
 93
 94 m_imageFrame = ImageFrame();
 95
 96 if (m_dataForTask.get())
 97 m_dataForTask.clear();
 98
 99 m_imageDecoder = 0;
 100}
 101
 102void ParallelImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
 103{
 104 ASSERT(isMainThread());
 105 m_isAllDataReceived = allDataReceived;
 106 m_data = data;
 107}
 108
 109void ParallelImageDecoder::decode()
 110{
 111 ASSERT(isMainThread());
 112 ASSERT(m_imageDecoder);
 113 ASSERT(!m_size.isEmpty());
 114
 115 OwnPtr<EncodedDataSegment> segment = extractSegmentForTask();
 116 if (!segment.get())
 117 return;
 118 m_decodeWorker->postTask(bind(&ParallelImageDecoder::decodeTask, this, segment.release()));
 119}
 120
 121PassOwnPtr<ParallelImageDecoder::EncodedDataSegment> ParallelImageDecoder::extractSegmentForTask()
 122{
 123 ASSERT(m_bytesOfDataConsumed >= 0 && m_bytesOfDataConsumed <= m_data->size());
 124
 125 int sizeOfSegment = m_data->size() - m_bytesOfDataConsumed;
 126 if (!sizeOfSegment)
 127 return PassOwnPtr<EncodedDataSegment>();
 128
 129 OwnPtr<EncodedDataSegment> segment(adoptPtr(new EncodedDataSegment()));
 130 const char* srcPtr = m_data->data() + m_bytesOfDataConsumed;
 131 segment->m_segment.append(srcPtr, sizeOfSegment);
 132 m_bytesOfDataConsumed = m_data->size();
 133
 134 segment->m_isAllDataReceived = m_isAllDataReceived;
 135
 136 return segment.release();
 137}
 138
 139struct ParallelFrameData {
 140 WTF_MAKE_NONCOPYABLE(ParallelFrameData);
 141 WTF_MAKE_FAST_ALLOCATED;
 142public:
 143 explicit ParallelFrameData(PassRefPtr<ParallelImageDecoder> parallelDecoder)
 144 : m_parallelDecoder(parallelDecoder)
 145 , m_decodedSegment()
 146 , m_status(ImageFrame::FrameEmpty)
 147 , m_hasAlpha(false)
 148 , m_premultiplyAlpha(true)
 149 {
 150 }
 151
 152 ~ParallelFrameData()
 153 {
 154 }
 155
 156 RefPtr<ParallelImageDecoder> m_parallelDecoder;
 157 OwnArrayPtr<ImageFrame::PixelData> m_decodedSegment;
 158 ImageFrame::FrameStatus m_status;
 159 bool m_hasAlpha;
 160 bool m_premultiplyAlpha;
 161 IntRect m_decodedRect;
 162};
 163
 164void ParallelImageDecoder::decodeTask(PassOwnPtr<ParallelImageDecoder::EncodedDataSegment> passSegment)
 165{
 166 ASSERT(!isMainThread());
 167 ASSERT(m_imageDecoder);
 168
 169 OwnPtr<EncodedDataSegment> segment = passSegment;
 170
 171 // 1. Send segment data to ImageDecoder.
 172 if (!m_dataForTask) {
 173 m_dataForTask = SharedBuffer::create();
 174#ifndef NDEBUG
 175 // ThreadRestrictionVerifier does not allow two threads to access one RefCounted object.
 176 // m_dataForTask is used by both the main thread and the task thread:
 177 // The task thread creates, uses and removes m_dataForTask. The main thread may remove
 178 // m_dataForTask if the task thread could not remove m_dataForTask.
 179 //
 180 // Parallel image decoders manage m_dataForTask in a thread-safe way. However,
 181 // we can't tell the verifier that we are safe by simply passing a mutex
 182 // because libdispatch does not even guarantee decodeTask is called by the same thread
 183 // each time. So turn off the verifier here.
 184 m_dataForTask->turnOffVerifier();
 185#endif
 186 }
 187 m_dataForTask->append(segment->m_segment);
 188 m_imageDecoder->setData(m_dataForTask.get(), segment->m_isAllDataReceived);
 189
 190 ImageFrame* oldBuffer = m_imageDecoder->firstImageFrameWithoutDecode();
 191 int lastDecodedRow = oldBuffer ? oldBuffer->lastDecodedRow() : 0;
 192
 193 // 2. Decode an image incrementally.
 194 ImageFrame* buffer = m_imageDecoder->frameBufferAtIndex(0);
 195 if (!buffer || buffer->status() == ImageFrame::FrameEmpty) {
 196 ASSERT(!segment->m_isAllDataReceived);
 197 return;
 198 }
 199
 200 // 3. Make a ParallelFrameData in order to pass it to the main thread.
 201 ParallelFrameData* parallelFrameData = new ParallelFrameData(this);
 202 parallelFrameData->m_status = buffer->status();
 203 parallelFrameData->m_hasAlpha = buffer->hasAlpha();
 204 parallelFrameData->m_premultiplyAlpha = buffer->premultiplyAlpha();
 205
 206 int newLastDecodedRow = buffer->lastDecodedRow();
 207 // Only in BMP, lastDecodedRow can be bigger than newLastDecodedRow.
 208 int lastDecodedMinRow = std::min(lastDecodedRow, newLastDecodedRow);
 209 int lastDecodedMaxRow = std::max(lastDecodedRow, newLastDecodedRow);
 210 parallelFrameData->m_decodedRect = IntRect(0, lastDecodedMinRow, m_imageDecoder->size().width(), lastDecodedMaxRow - lastDecodedMinRow + 1);
 211
 212 // 4. Create decoded segment data in order to pass it to the main thread.
 213 // If the status is FrameComplete, this is not needed because a NativeImage will be created using the decoder on the main thread.
 214 if (parallelFrameData->m_status == ImageFrame::FramePartial) {
 215 int segmentSize = parallelFrameData->m_decodedRect.size().area();
 216 parallelFrameData->m_decodedSegment = adoptArrayPtr(new ImageFrame::PixelData[segmentSize]);
 217
 218 ImageFrame::PixelData* segmentAddr = parallelFrameData->m_decodedSegment.get();
 219 memcpy(segmentAddr, buffer->getAddr(0, lastDecodedMinRow), segmentSize * sizeof(ImageFrame::PixelData));
 220 } else { // FrameComplete
 221 m_imageDecoder->setData(0, false);
 222 m_dataForTask.clear();
 223 }
 224
 225 callOnMainThread(bind(didDecodeTaskCallback, parallelFrameData));
 226}
 227
 228void didDecodeTaskCallback(ParallelFrameData* parallelFrameData)
 229{
 230 ASSERT(isMainThread());
 231 // If a client called ParallelImageDecoder::clear(), ParallelImageDecoder is invalidated.
 232 if (parallelFrameData->m_parallelDecoder->valid())
 233 parallelFrameData->m_parallelDecoder->didDecodeTask(parallelFrameData);
 234 delete parallelFrameData;
 235}
 236
 237ImageFrameData createImageFrameData(ParallelFrameData* parallelFrameData)
 238{
 239 ImageFrameData imageFrameData;
 240 imageFrameData.m_orientation = DefaultImageOrientation;
 241 imageFrameData.m_isComplete = parallelFrameData->m_status == ImageFrame::FrameComplete;
 242 imageFrameData.m_hasAlpha = !imageFrameData.m_isComplete || parallelFrameData->m_hasAlpha;
 243 return imageFrameData;
 244}
 245
 246void ParallelImageDecoder::didDecodeTask(ParallelFrameData* parallelFrameData)
 247{
 248 ASSERT(isMainThread());
 249 ASSERT(parallelFrameData->m_status != ImageFrame::FrameEmpty);
 250
 251 ImageFrameData imageFrameData = createImageFrameData(parallelFrameData);
 252
 253 if (!imageFrameData.m_isComplete)
 254 didDecodePartial(imageFrameData, parallelFrameData);
 255 else
 256 didDecodeComplete(imageFrameData);
 257}
 258
 259void ParallelImageDecoder::didDecodePartial(ImageFrameData& imageFrameData, ParallelFrameData* parallelFrameData)
 260{
 261 ASSERT(isMainThread());
 262
 263 appendDecodedDataToImageFrame(parallelFrameData);
 264 syncImageFrame(parallelFrameData);
 265
 266 imageFrameData.m_frame = m_imageFrame.asNewNativeImage();
 267 m_observer->didDecode(imageFrameData);
 268}
 269
 270void ParallelImageDecoder::appendDecodedDataToImageFrame(ParallelFrameData* parallelFrameData)
 271{
 272 const ImageFrame::PixelData* const segmentAddr = parallelFrameData->m_decodedSegment.get();
 273 int segmentSize = parallelFrameData->m_decodedRect.size().area();
 274 ImageFrame::PixelData* destAddr = m_imageFrame.getAddr(0, parallelFrameData->m_decodedRect.y());
 275 memcpy(destAddr, segmentAddr, segmentSize * sizeof(ImageFrame::PixelData));
 276}
 277
 278void ParallelImageDecoder::syncImageFrame(ParallelFrameData* parallelFrameData)
 279{
 280 // The following lines are needed to create a valid native image in ImageFrame::asNewNativeImage().
 281 m_imageFrame.setStatus(parallelFrameData->m_status);
 282 m_imageFrame.setHasAlpha(parallelFrameData->m_hasAlpha);
 283 m_imageFrame.setPremultiplyAlpha(parallelFrameData->m_premultiplyAlpha);
 284}
 285
 286void ParallelImageDecoder::didDecodeComplete(ImageFrameData& imageFrameData)
 287{
 288 ASSERT(isMainThread());
 289
 290 m_decodeWorker.clear();
 291 // The main thread can use m_imageDecoder because other threads do not access m_imageDecoder after this line.
 292
 293 ImageFrame* buffer = m_imageDecoder->firstImageFrameWithoutDecode();
 294 ASSERT(buffer);
 295
 296 imageFrameData.m_frame = buffer->asNewNativeImage();
 297 m_observer->didDecode(imageFrameData);
 298}
 299
 300}

Source/WebCore/platform/graphics/ParallelImageDecoder.h

 1/*
 2 * Copyright (C) 2012 Company 100 Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef ParallelImageDecoder_h
 27#define ParallelImageDecoder_h
 28
 29#include "ImageDecodeWorker.h"
 30#include "ImageDecoder.h"
 31#include "ParallelImageDecoderObserver.h"
 32#include <wtf/Forward.h>
 33#include <wtf/ThreadSafeRefCounted.h>
 34#include <wtf/Vector.h>
 35
 36namespace WebCore {
 37class ImageFrameData;
 38class ParallelFrameData;
 39
 40class ParallelImageDecoder : public ThreadSafeRefCounted<ParallelImageDecoder> {
 41public:
 42 ParallelImageDecoder(ParallelImageDecoderObserver*, ImageDecoder*);
 43 ~ParallelImageDecoder();
 44
 45 void invalidate();
 46
 47 void setData(SharedBuffer*, bool allDataReceived);
 48
 49 void decode();
 50
 51 inline String filenameExtension() const { return m_filenameExtension; }
 52 inline IntSize size() const { return m_size; }
 53
 54private:
 55 void initialize(ImageDecoder*);
 56
 57 inline bool valid() const { return m_imageDecoder; }
 58
 59 struct EncodedDataSegment {
 60 WTF_MAKE_NONCOPYABLE(EncodedDataSegment);
 61 WTF_MAKE_FAST_ALLOCATED;
 62 public:
 63 EncodedDataSegment() { }
 64 Vector<char> m_segment;
 65 bool m_isAllDataReceived;
 66 };
 67
 68 PassOwnPtr<EncodedDataSegment> extractSegmentForTask();
 69
 70 // Only this method is called by the task thread.
 71 void decodeTask(PassOwnPtr<EncodedDataSegment>);
 72
 73 void didDecodeTask(ParallelFrameData*);
 74 void didDecodePartial(ImageFrameData&, ParallelFrameData*);
 75 void appendDecodedDataToImageFrame(ParallelFrameData*);
 76 void syncImageFrame(ParallelFrameData*);
 77 void didDecodeComplete(ImageFrameData&);
 78 friend void didDecodeTaskCallback(ParallelFrameData*);
 79
 80 ParallelImageDecoderObserver* m_observer;
 81
 82 IntSize m_size;
 83 String m_filenameExtension;
 84
 85 // For input data
 86 bool m_isAllDataReceived;
 87 RefPtr<SharedBuffer> m_data;
 88 int m_bytesOfDataConsumed;
 89
 90 // For output data
 91 ImageFrame m_imageFrame;
 92
 93 // The task thread can access only m_dataForTask and m_imageDecoder.
 94 RefPtr<SharedBuffer> m_dataForTask;
 95
 96 ImageDecoder* m_imageDecoder;
 97
 98 RefPtr<ImageDecodeWorker> m_decodeWorker;
 99
 100};
 101
 102} // namespace WebCore
 103
 104#endif

Source/WebCore/platform/graphics/ParallelImageDecoderObserver.h

 1/*
 2 * Copyright (C) 2012 Company 100 Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef ParallelImageDecoderObserver_h
 27#define ParallelImageDecoderObserver_h
 28
 29namespace WebCore {
 30
 31class ImageFrameData;
 32
 33// Interface for notification about decoding completion of an ParallelImageDecoder.
 34class ParallelImageDecoderObserver {
 35public:
 36 virtual void didDecode(const ImageFrameData&) = 0;
 37
 38protected:
 39 virtual ~ParallelImageDecoderObserver() { }
 40};
 41
 42}
 43
 44#endif

Source/WebCore/platform/graphics/RetainedModeBitmapImage.cpp

 1/*
 2 * Copyright (C) 2012 Company 100 Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27#include "RetainedModeBitmapImage.h"
 28
 29#include "BitmapImage.h"
 30
 31namespace WebCore {
 32
 33PassRefPtr<RetainedModeBitmapImage> RetainedModeBitmapImage::create(BitmapImage* bitmapImage)
 34{
 35 return adoptRef(new RetainedModeBitmapImage(bitmapImage));
 36}
 37
 38RetainedModeBitmapImage::RetainedModeBitmapImage(BitmapImage* bitmapImage)
 39 : m_bitmapImage(bitmapImage)
 40 , m_retainedModeCount(0)
 41{
 42}
 43
 44bool RetainedModeBitmapImage::hasSingleSecurityOrigin() const
 45{
 46 RetainedModeSaver retainedModeSaver(this);
 47 return m_bitmapImage->hasSingleSecurityOrigin();
 48}
 49
 50IntSize RetainedModeBitmapImage::size() const
 51{
 52 RetainedModeSaver retainedModeSaver(this);
 53 return m_bitmapImage->size();
 54}
 55
 56bool RetainedModeBitmapImage::getHotSpot(IntPoint& point) const
 57{
 58 RetainedModeSaver retainedModeSaver(this);
 59 return m_bitmapImage->getHotSpot(point);
 60}
 61
 62bool RetainedModeBitmapImage::dataChanged(bool allDataReceived)
 63{
 64 RetainedModeSaver retainedModeSaver(this);
 65 return m_bitmapImage->dataChanged(allDataReceived);
 66}
 67
 68String RetainedModeBitmapImage::filenameExtension() const
 69{
 70 RetainedModeSaver retainedModeSaver(this);
 71 return m_bitmapImage->filenameExtension();
 72}
 73
 74void RetainedModeBitmapImage::destroyDecodedData(bool destroyAll)
 75{
 76 RetainedModeSaver retainedModeSaver(this);
 77 m_bitmapImage->destroyDecodedData(destroyAll);
 78}
 79
 80unsigned RetainedModeBitmapImage::decodedSize() const
 81{
 82 RetainedModeSaver retainedModeSaver(this);
 83 return m_bitmapImage->decodedSize();
 84}
 85
 86void RetainedModeBitmapImage::startAnimation(bool catchUpIfNecessary)
 87{
 88 RetainedModeSaver retainedModeSaver(this);
 89 m_bitmapImage->startAnimation(catchUpIfNecessary);
 90}
 91
 92void RetainedModeBitmapImage::stopAnimation()
 93{
 94 RetainedModeSaver retainedModeSaver(this);
 95 m_bitmapImage->stopAnimation();
 96}
 97
 98void RetainedModeBitmapImage::resetAnimation()
 99{
 100 RetainedModeSaver retainedModeSaver(this);
 101 m_bitmapImage->resetAnimation();
 102}
 103
 104NativeImagePtr RetainedModeBitmapImage::nativeImageForCurrentFrame()
 105{
 106 RetainedModeSaver retainedModeSaver(this);
 107 return m_bitmapImage->nativeImageForCurrentFrame();
 108}
 109
 110bool RetainedModeBitmapImage::currentFrameHasAlpha()
 111{
 112 RetainedModeSaver retainedModeSaver(this);
 113 return m_bitmapImage->currentFrameHasAlpha();
 114}
 115
 116bool RetainedModeBitmapImage::currentFrameIsComplete()
 117{
 118 RetainedModeSaver retainedModeSaver(this);
 119 return m_bitmapImage->currentFrameIsComplete();
 120}
 121
 122void RetainedModeBitmapImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator op)
 123{
 124 RetainedModeSaver retainedModeSaver(this);
 125 m_bitmapImage->draw(context, dstRect, srcRect, styleColorSpace, op);
 126}
 127
 128bool RetainedModeBitmapImage::mayFillWithSolidColor()
 129{
 130 RetainedModeSaver retainedModeSaver(this);
 131 return m_bitmapImage->mayFillWithSolidColor();
 132}
 133
 134Color RetainedModeBitmapImage::solidColor() const
 135{
 136 RetainedModeSaver retainedModeSaver(this);
 137 return m_bitmapImage->solidColor();
 138}
 139
 140RetainedModeSaver::RetainedModeSaver(const RetainedModeBitmapImage* image, bool retained)
 141 : m_image(image)
 142 , m_retained(retained)
 143{
 144 if (m_retained)
 145 m_image->beginRetainedMode();
 146}
 147
 148RetainedModeSaver::~RetainedModeSaver()
 149{
 150 if (m_retained)
 151 m_image->endRetainedMode();
 152}
 153
 154RetainedModeBitmapImage* toRetainedModeBitmapImage(Image* image)
 155{
 156 ASSERT(image->isBitmapImage());
 157
 158 BitmapImage* bitmapImage = static_cast<BitmapImage*>(image);
 159 if (!bitmapImage->m_retainedModeImage.get())
 160 bitmapImage->m_retainedModeImage = RetainedModeBitmapImage::create(bitmapImage);
 161
 162 return bitmapImage->m_retainedModeImage.get();
 163}
 164
 165Image* toRetainedModeBitmapImageIfPossible(Image* image)
 166{
 167 if (image && image->isBitmapImage())
 168 return toRetainedModeBitmapImage(image);
 169 return image;
 170}
 171
 172}

Source/WebCore/platform/graphics/RetainedModeBitmapImage.h

 1/*
 2 * Copyright (C) 2012 Company 100 Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef RetainedModeBitmapImage_h
 27#define RetainedModeBitmapImage_h
 28
 29#include "Image.h"
 30
 31namespace WebCore {
 32
 33class BitmapImage;
 34class RetainedModeSaver;
 35
 36class RetainedModeBitmapImage : public Image {
 37 friend class RetainedModeSaver;
 38public:
 39 static PassRefPtr<RetainedModeBitmapImage> create(BitmapImage*);
 40
 41 virtual ~RetainedModeBitmapImage() { }
 42
 43 virtual bool hasSingleSecurityOrigin() const;
 44
 45 virtual IntSize size() const;
 46 virtual bool getHotSpot(IntPoint&) const;
 47
 48 virtual bool dataChanged(bool allDataReceived);
 49 virtual String filenameExtension() const;
 50
 51 virtual void destroyDecodedData(bool destroyAll = true);
 52 virtual unsigned decodedSize() const;
 53
 54 virtual void startAnimation(bool catchUpIfNecessary = true);
 55 virtual void stopAnimation();
 56 virtual void resetAnimation();
 57
 58 virtual NativeImagePtr nativeImageForCurrentFrame();
 59 virtual bool currentFrameHasAlpha();
 60
 61 bool currentFrameIsComplete();
 62
 63 inline bool retainedModeRendering() const { return m_retainedModeCount; }
 64
 65protected:
 66 virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator);
 67
 68 virtual bool mayFillWithSolidColor();
 69 virtual Color solidColor() const;
 70
 71private:
 72 explicit RetainedModeBitmapImage(BitmapImage*);
 73
 74 inline void beginRetainedMode() const { m_retainedModeCount++; }
 75 inline void endRetainedMode() const
 76 {
 77 m_retainedModeCount--;
 78 ASSERT(m_retainedModeCount >= 0);
 79 }
 80
 81 BitmapImage* m_bitmapImage;
 82 mutable int m_retainedModeCount;
 83};
 84
 85class RetainedModeSaver {
 86public:
 87 RetainedModeSaver(const RetainedModeBitmapImage*, bool retained = true);
 88 ~RetainedModeSaver();
 89
 90private:
 91 const RetainedModeBitmapImage* m_image;
 92 bool m_retained;
 93};
 94
 95
 96RetainedModeBitmapImage* toRetainedModeBitmapImage(Image*);
 97Image* toRetainedModeBitmapImageIfPossible(Image*);
 98
 99}
 100
 101#endif

Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp

@@BitmapImage::BitmapImage(NativeImageCairo* nativeImage, ImageObserver* observer)
5858 , m_haveSize(true)
5959 , m_sizeAvailable(true)
6060 , m_haveFrameCount(true)
 61 , m_isCachingFrame(false)
6162{
6263 cairo_surface_t* surface = nativeImage->surface();
6364 int width = cairo_image_surface_get_width(surface);

Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp

@@bool GraphicsContext3D::getImageData(Image* image, unsigned int format, unsigned
165165 decoder.setData(image->data(), true);
166166 if (!decoder.frameCount())
167167 return false;
168  ImageFrameData imageImageFrameData = decoder.createFrameAtIndex(0);
 168 ImageFrameData imageImageFrameData = decoder.requestFrameAtIndex(0);
169169 if (!imageImageFrameData.m_isComplete)
170170 return false;
171171 OwnPtr<NativeImageCairo> nativeImage = adoptPtr(imageImageFrameData.m_frame);

Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp

@@bool GraphicsContext3D::getImageData(Image* image,
107107 decoder.setData(image->data(), true);
108108 if (!decoder.frameCount())
109109 return false;
110  ImageFrameData imageFrameData = decoder.createFrameAtIndex(0);
 110 ImageFrameData imageFrameData = decoder.requestFrameAtIndex(0);
111111 decodedImage.adoptCF(imageFrameData.m_frame);
112112 cgImage = decodedImage.get();
113113 } else

Source/WebCore/platform/graphics/cg/ImageCG.cpp

@@BitmapImage::BitmapImage(CGImageRef cgImage, ImageObserver* observer)
8181 , m_haveSize(true)
8282 , m_sizeAvailable(true)
8383 , m_haveFrameCount(true)
 84 , m_isCachingFrame(false)
8485{
8586 CGFloat width = CGImageGetWidth(cgImage);
8687 CGFloat height = CGImageGetHeight(cgImage);

Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp

3232#include "ImageOrientation.h"
3333#include "ImageSourceObserver.h"
3434#include "IntPoint.h"
 35#include "IntRect.h"
3536#include "IntSize.h"
3637#include "MIMETypeRegistry.h"
3738#include "SharedBuffer.h"

@@size_t ImageSource::frameCount() const
309310 return m_decoder ? CGImageSourceGetCount(m_decoder) : 0;
310311}
311312
312 void ImageSource::requestFrameAtIndex(size_t index)
 313ImageFrameData ImageSource::requestFrameAtIndex(size_t index, bool)
313314{
314315 ASSERT(m_observer);
315316 ImageFrameData imageFrameData = createFrameAtIndex(index);
316317 m_observer->didReceiveFrameAtIndex(index, imageFrameData);
 318 return imageFrameData;
317319}
318320
319321ImageFrameData ImageSource::createFrameAtIndex(size_t index)

Source/WebCore/platform/graphics/openvg/ImageOpenVG.cpp

@@BitmapImage::BitmapImage(TiledImageOpenVG* tiledImage, ImageObserver* observer)
6767 , m_sizeAvailable(true)
6868 , m_hasUniformFrameSize(true)
6969 , m_haveFrameCount(true)
 70 , m_isCachingFrame(false)
7071{
7172 ASSERT(m_size.width() > 0);
7273 ASSERT(m_size.height() > 0);

Source/WebCore/platform/graphics/qt/ImageQt.cpp

@@BitmapImage::BitmapImage(QPixmap* pixmap, ImageObserver* observer)
209209 , m_haveSize(true)
210210 , m_sizeAvailable(true)
211211 , m_haveFrameCount(true)
 212 , m_isCachingFrame(false)
212213{
213214 int width = pixmap->width();
214215 int height = pixmap->height();

Source/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp

@@bool GraphicsContext3D::getImageData(Image* image,
6262 decoder.setData(image->data(), true);
6363 if (!decoder.frameCount())
6464 return false;
65  ImageFrameData imageFrameData = decoder.createFrameAtIndex(0);
 65 ImageFrameData imageFrameData = decoder.requestFrameAtIndex(0);
6666 if (!imageFrameData.m_isComplete)
6767 return false;
6868 hasAlpha = imageFrameData.m_hasAlpha;

Source/WebCore/platform/graphics/wx/ImageWx.cpp

@@BitmapImage::BitmapImage(const wxBitmap& bitmap)
9595 , m_decodedSize(0)
9696 , m_haveFrameCount(true)
9797 , m_frameCount(1)
 98 , m_isCachingFrame(false)
9899{
99100 m_decodedSize = bitmap.GetWidth() * bitmap.GetHeight() * 4;
100101 m_size = IntSize(bitmap.GetWidth(), bitmap.GetHeight());

Source/WebCore/platform/image-decoders/ImageDecoder.cpp

@@ImageDecoder* ImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaO
140140
141141ImageFrame::ImageFrame()
142142 : m_hasAlpha(false)
 143 , m_lastDecodedRow(0)
143144 , m_status(FrameEmpty)
144145 , m_duration(0)
145146 , m_disposalMethod(DisposeNotSpecified)

@@void ImageFrame::clearPixelData()
165166{
166167 m_backingStore.clear();
167168 m_bytes = 0;
 169 m_lastDecodedRow = 0;
168170 m_status = FrameEmpty;
169171 // NOTE: Do not reset other members here; clearFrameBufferCache() calls this
170172 // to free the bitmap data, but other functions like initFrameBuffer() and

@@bool ImageFrame::copyBitmapData(const ImageFrame& other)
187189 m_bytes = m_backingStore.data();
188190 m_size = other.m_size;
189191 setHasAlpha(other.m_hasAlpha);
 192 m_lastDecodedRow = other.m_lastDecodedRow;
190193 return true;
191194}
192195

@@bool ImageFrame::setSize(int newWidth, int newHeight)
199202 m_backingStore.resize(backingStoreSize);
200203 m_bytes = m_backingStore.data();
201204 m_size = IntSize(newWidth, newHeight);
 205 m_lastDecodedRow = 0;
202206
203207 zeroFillPixelData();
204208 return true;

Source/WebCore/platform/image-decoders/ImageDecoder.h

@@namespace WebCore {
118118 NativeImagePtr asNewNativeImage() const;
119119
120120 bool hasAlpha() const;
 121 int lastDecodedRow() const { return m_lastDecodedRow; }
121122 const IntRect& originalFrameRect() const { return m_originalFrameRect; }
122123 FrameStatus status() const { return m_status; }
123124 unsigned duration() const { return m_duration; }

@@namespace WebCore {
125126 bool premultiplyAlpha() const { return m_premultiplyAlpha; }
126127
127128 void setHasAlpha(bool alpha);
 129 inline void setLastDecodedRow(int lastDecodedRow) { m_lastDecodedRow = lastDecodedRow; }
128130 void setColorProfile(const ColorProfile&);
129131 void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; }
130132 void setStatus(FrameStatus status);

@@namespace WebCore {
181183 // FIXME: Do we need m_colorProfile anymore?
182184 ColorProfile m_colorProfile;
183185#endif
 186 int m_lastDecodedRow;
184187 IntRect m_originalFrameRect; // This will always just be the entire
185188 // buffer except for GIF frames whose
186189 // original rect was smaller than the

@@namespace WebCore {
228231 m_isAllDataReceived = allDataReceived;
229232 }
230233
 234 SharedBuffer* data() const { return m_data.get(); }
 235
231236 // Lazily-decodes enough of the image to get the size (if possible).
232237 // FIXME: Right now that has to be done by each subclass; factor the
233238 // decode call out and use it here.

@@namespace WebCore {
276281 // ImageDecoder-owned pointer.
277282 virtual ImageFrame* frameBufferAtIndex(size_t) = 0;
278283
 284 // Returns an ImageDecoder-owned pointer without decoding more.
 285 ImageFrame* firstImageFrameWithoutDecode()
 286 {
 287 return m_frameBufferCache.isEmpty() ? 0 : &m_frameBufferCache[0];
 288 }
 289
279290 void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; }
280291 bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; }
281292

Source/WebCore/platform/image-decoders/blackberry/JPEGImageDecoder.cpp

@@int ImageReader::decode(size_t width, size_t height, ImageFrame* aFrame)
157157 aFrame->setRGBA(i, j, curPtr[0], curPtr[1], curPtr[2], 255);
158158 curPtr += 3;
159159 }
 160 aFrame->setLastDecodedRow(j);
160161 }
161162 return 0;
162163}

Source/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp

@@void BMPImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
6464
6565bool BMPImageDecoder::isSizeAvailable()
6666{
67  if (!ImageDecoder::isSizeAvailable())
 67 if (!ImageDecoder::isSizeAvailable()) {
 68 // Only BMPImageDecoder must make m_frameBufferCache[0] in isSizeAvailable(),
 69 // because the default value of ImageFrame::m_lastDecodedRow can be "height - 1".
 70 if (m_frameBufferCache.isEmpty()) {
 71 m_frameBufferCache.resize(1);
 72 m_frameBufferCache.first().setPremultiplyAlpha(m_premultiplyAlpha);
 73 }
6874 decode(true);
 75 }
6976
7077 return ImageDecoder::isSizeAvailable();
7178}

Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp

@@bool BMPImageReader::decodeBMP(bool onlySize)
6464 return false;
6565
6666 // processInfoHeader() set the size, so if that's all we needed, we're done.
67  if (onlySize)
 67 if (onlySize) {
 68 if (!m_isTopDown)
 69 m_buffer->setLastDecodedRow(m_parent->size().height() - 1);
6870 return true;
 71 }
6972
7073 // Read and process the bitmasks, if needed.
7174 if (m_needToProcessBitmasks && !processBitmasks())

@@bool BMPImageReader::processRLEData()
624627
625628 m_decodedOffset += 2;
626629 }
 630 m_buffer->setLastDecodedRow(m_coord.y());
627631 }
628632 }
629633}

@@BMPImageReader::ProcessingResult BMPImageReader::processNonRLEData(bool inRLE, i
717721 getComponent(pixel, 2), alpha);
718722 }
719723 }
 724 m_buffer->setLastDecodedRow(m_coord.y());
720725
721726 // Success, keep going.
722727 m_decodedOffset += paddedNumBytes;

Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp

@@bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex, unsigned char* rowBuff
249249 buffer.setRGBA(x, yBegin, 0, 0, 0, 0);
250250 }
251251 }
 252 buffer.setLastDecodedRow(yBegin);
252253
253254 // Tell the frame to copy the row data if need be.
254  if (repeatCount > 1)
 255 if (repeatCount > 1) {
255256 buffer.copyRowNTimes(xBegin, xEnd, yBegin, yEnd);
 257 ASSERT((yEnd - 1) >= 0);
 258 buffer.setLastDecodedRow(yEnd - 1);
 259 }
256260
257261 return true;
258262}

@@bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
390394 for (int y = prevRect.y(); y < prevRect.maxY(); ++y) {
391395 for (int x = prevRect.x(); x < prevRect.maxX(); ++x)
392396 buffer->setRGBA(x, y, 0, 0, 0, 0);
 397 buffer->setLastDecodedRow(y);
393398 }
394399 if ((prevRect.width() > 0) && (prevRect.height() > 0))
395400 buffer->setHasAlpha(true);

Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp

@@bool JPEGImageDecoder::outputScanlines()
577577 if (turboSwizzled(info->out_color_space)) {
578578 ASSERT(!m_scaled);
579579 while (info->output_scanline < info->output_height) {
 580 buffer.setLastDecodedRow(info->output_scanline);
580581 unsigned char* row = reinterpret_cast<unsigned char*>(buffer.getAddr(0, info->output_scanline));
581582 if (jpeg_read_scanlines(info, &row, 1) != 1)
582583 return false;

@@bool JPEGImageDecoder::outputScanlines()
628629 return setFailed();
629630 }
630631 }
 632 buffer.setLastDecodedRow(destY);
631633 }
632634
633635 return true;

Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp

@@void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex,
520520
521521 if (nonTrivialAlpha && !buffer.hasAlpha())
522522 buffer.setHasAlpha(nonTrivialAlpha);
 523 buffer.setLastDecodedRow(y);
523524}
524525
525526void PNGImageDecoder::pngComplete()

Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp

@@ImageFrame& ImageFrame::operator=(const ImageFrame& other)
5757void ImageFrame::clearPixelData()
5858{
5959 m_bitmap.bitmap().reset();
 60 m_lastDecodedRow = 0;
6061 m_status = FrameEmpty;
6162 // NOTE: Do not reset other members here; clearFrameBufferCache()
6263 // calls this to free the bitmap data, but other functions like

@@bool ImageFrame::copyBitmapData(const ImageFrame& other)
7677
7778 m_bitmap.bitmap().reset();
7879 const NativeImageSkia& otherBitmap = other.m_bitmap;
 80 m_lastDecodedRow = other.m_lastDecodedRow;
7981 return otherBitmap.bitmap().copyTo(&m_bitmap.bitmap(), otherBitmap.bitmap().config());
8082}
8183

@@bool ImageFrame::setSize(int newWidth, int newHeight)
8486 // setSize() should only be called once, it leaks memory otherwise.
8587 ASSERT(!width() && !height());
8688
 89 m_lastDecodedRow = 0;
8790 m_bitmap.bitmap().setConfig(SkBitmap::kARGB_8888_Config, newWidth, newHeight);
8891 if (!m_bitmap.bitmap().allocPixels())
8992 return false;

Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp

@@bool WEBPImageDecoder::decode(bool onlySize)
132132 return setFailed();
133133 }
134134
135  switch (WebPIUpdate(m_decoder, dataBytes, dataSize)) {
136  case VP8_STATUS_OK:
137  buffer.setStatus(ImageFrame::FrameComplete);
138  WebPIDelete(m_decoder);
139  m_decoder = 0;
140  return true;
141  case VP8_STATUS_SUSPENDED:
142  return false;
143  default:
 135 const VP8StatusCode status = WebPIUpdate(m_decoder, dataBytes, dataSize);
 136 if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) {
144137 WebPIDelete(m_decoder);
145138 m_decoder = 0;
146139 return setFailed();
147140 }
 141 int lastY = 0;
 142 if (!WebPIDecGetRGB(m_decoder, &lastY, 0, 0, 0))
 143 return setFailed();
 144 ASSERT(lastY >= 0);
 145 ASSERT(lastY <= size().height());
 146 buffer.setLastDecodedRow(lastY ? lastY - 1 : 0);
 147
 148 if (status == VP8_STATUS_SUSPENDED)
 149 return false;
 150
 151 buffer.setStatus(ImageFrame::FrameComplete);
 152 WebPIDelete(m_decoder);
 153 m_decoder = 0;
 154 return true;
148155}
149156
150157} // namespace WebCore

Source/WebCore/rendering/RenderImage.cpp

@@void RenderImage::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOf
311311 LayoutUnit usableWidth = cWidth - 2;
312312 LayoutUnit usableHeight = cHeight - 2;
313313
314  RefPtr<Image> image = m_imageResource->image();
 314 Image* image = toRetainedModeBitmapImageIfPossible(m_imageResource->image().get());
315315
316316 if (m_imageResource->errorOccurred() && !image->isNull() && usableWidth >= image->width() && usableHeight >= image->height()) {
317317 float deviceScaleFactor = WebCore::deviceScaleFactor(frame());

@@void RenderImage::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOf
328328 if (centerY < 0)
329329 centerY = 0;
330330 imageOffset = LayoutSize(leftBorder + leftPad + centerX + 1, topBorder + topPad + centerY + 1);
331  context->drawImage(image.get(), style()->colorSpace(), IntRect(roundedIntPoint(paintOffset + imageOffset), imageSize), CompositeSourceOver, shouldRespectImageOrientation());
 331 context->drawImage(image, style()->colorSpace(), IntRect(roundedIntPoint(paintOffset + imageOffset), imageSize), CompositeSourceOver, shouldRespectImageOrientation());
332332 errorPictureDrawn = true;
333333 }
334334

@@void RenderImage::paintIntoRect(GraphicsContext* context, const LayoutRect& rect
442442 if (!m_imageResource->hasImage() || m_imageResource->errorOccurred() || alignedRect.width() <= 0 || alignedRect.height() <= 0)
443443 return;
444444
445  RefPtr<Image> img = m_imageResource->image(alignedRect.width(), alignedRect.height());
 445 Image* img = toRetainedModeBitmapImageIfPossible(m_imageResource->image(alignedRect.width(), alignedRect.height()).get());
446446 if (!img || img->isNull())
447447 return;
448448

@@void RenderImage::paintIntoRect(GraphicsContext* context, const LayoutRect& rect
450450 CompositeOperator compositeOperator = imageElt ? imageElt->compositeOperator() : CompositeSourceOver;
451451 Image* image = m_imageResource->image().get();
452452 bool useLowQualityScaling = shouldPaintAtLowQuality(context, image, image, alignedRect.size());
453  context->drawImage(m_imageResource->image(alignedRect.width(), alignedRect.height()).get(), style()->colorSpace(), alignedRect, compositeOperator, shouldRespectImageOrientation(), useLowQualityScaling);
 453 context->drawImage(img, style()->colorSpace(), alignedRect, compositeOperator, shouldRespectImageOrientation(), useLowQualityScaling);
454454}
455455
456456bool RenderImage::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox*) const

@@bool RenderImage::backgroundIsObscured() const
481481
482482 // Check for bitmap image with alpha.
483483 Image* image = m_imageResource->image().get();
484  if (!image || !image->isBitmapImage() || image->currentFrameHasAlpha())
 484 if (!image || !image->isBitmapImage() || toRetainedModeBitmapImage(image)->currentFrameHasAlpha())
485485 return false;
486486
487487 return true;

Source/WebCore/rendering/RenderLayerBacking.cpp

5151#include "RenderEmbeddedObject.h"
5252#include "RenderVideo.h"
5353#include "RenderView.h"
 54#include "RetainedModeBitmapImage.h"
5455#include "ScrollingCoordinator.h"
5556#include "StyleResolver.h"
5657#include "TiledBacking.h"

@@void RenderLayerBacking::updateImageContents()
10761077 if (!cachedImage->isLoaded())
10771078 return;
10781079
 1080 // We have to wait until the image is fully decoded before setting it on the layer.
 1081 if (image->isBitmapImage() && !toRetainedModeBitmapImage(image)->currentFrameIsComplete())
 1082 return;
 1083
10791084 // This is a no-op if the layer doesn't have an inner layer for the image.
10801085 m_graphicsLayer->setContentsToImage(image);
10811086 updateDrawsContent();

Source/WebCore/rendering/svg/RenderSVGImage.cpp

3838#include "RenderLayer.h"
3939#include "RenderSVGResourceContainer.h"
4040#include "RenderSVGResourceFilter.h"
 41#include "RetainedModeBitmapImage.h"
4142#include "SVGImageElement.h"
4243#include "SVGLength.h"
4344#include "SVGPreserveAspectRatio.h"

@@void RenderSVGImage::paint(PaintInfo& paintInfo, const LayoutPoint&)
127128 SVGRenderingContext renderingContext(this, childPaintInfo);
128129
129130 if (renderingContext.isRenderingPrepared()) {
130  RefPtr<Image> image = m_imageResource->image();
 131 Image* image = toRetainedModeBitmapImageIfPossible(m_imageResource->image().get());
131132 FloatRect destRect = m_objectBoundingBox;
132133 FloatRect srcRect(0, 0, image->width(), image->height());
133134
134135 SVGImageElement* imageElement = static_cast<SVGImageElement*>(node());
135136 imageElement->preserveAspectRatio().transformRect(destRect, srcRect);
136137
137  childPaintInfo.context->drawImage(image.get(), ColorSpaceDeviceRGB, destRect, srcRect);
 138 childPaintInfo.context->drawImage(image, ColorSpaceDeviceRGB, destRect, srcRect);
138139 }
139140 }
140141

Source/WebKit/chromium/src/WebImageCG.cpp

@@WebImage WebImage::fromData(const WebData& data, const WebSize& desiredSize)
7676 }
7777 }
7878
79  ImageFrameData imageFrameData = source.createFrameAtIndex(index);
 79 ImageFrameData imageFrameData = source.requestFrameAtIndex(index);
8080 RetainPtr<CGImageRef> frame(AdoptCF, imageFrameData.m_frame);
8181 if (!frame)
8282 return WebImage();

Source/WebKit/chromium/src/WebImageSkia.cpp

@@WebImage WebImage::fromData(const WebData& data, const WebSize& desiredSize)
7777 }
7878 }
7979
80  ImageFrameData imageFrameData = source.createFrameAtIndex(index);
 80 ImageFrameData imageFrameData = source.requestFrameAtIndex(index);
8181 OwnPtr<NativeImageSkia> frame = adoptPtr(imageFrameData.m_frame);
8282 if (!frame)
8383 return WebImage();