RESOLVED FIXED 103796
[chromium] ImageDecodingStore should cache partially decoded images
https://bugs.webkit.org/show_bug.cgi?id=103796
Summary [chromium] ImageDecodingStore should cache partially decoded images
Hin-Chung Lam
Reported 2012-11-30 18:14:07 PST
Current implementation does not cache partially decoded images. The result is that when an image is partially decoded, the bitmap and corresponding ImageDecoder is deleted. The means any subsequent decoding will have to start from scratch. Redoing image decoding many times is very expensive and should be avoided. The solution to this is to cache partially decoded bitmap together with the ImageDecoder.
Attachments
Patch (42.92 KB, patch)
2012-12-05 00:05 PST, Hin-Chung Lam
no flags
Patch (43.63 KB, patch)
2012-12-07 15:27 PST, Hin-Chung Lam
no flags
Patch for landing (43.63 KB, patch)
2012-12-07 18:14 PST, Hin-Chung Lam
no flags
Hin-Chung Lam
Comment 1 2012-12-05 00:05:00 PST
Hin-Chung Lam
Comment 2 2012-12-05 00:12:11 PST
Comment on attachment 177684 [details] Patch The seems big but if you focus on ImageDecodingStore and ImageFrameGenerator the others are just test and changes to mock modules. ImageDecodingStore Added logic to handle incomplete cache entries. ImageFrameGenerator Added logic to resume decoding using a cached decoder. The change has some code move involved to share code with decoding starting from scratch.
Hin-Chung Lam
Comment 3 2012-12-05 14:29:18 PST
Woohoo! Tested this with Chrome and it works with large JPEG files too, which means this incomplete image caching is working.
Hin-Chung Lam
Comment 4 2012-12-07 11:38:34 PST
nduca, senorblanco: have time to have a look? As we have discussed we'll change the resampling algorithm later so it's now in it's own function and easy to swap out.
Stephen White
Comment 5 2012-12-07 12:14:32 PST
Comment on attachment 177684 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=177684&action=review Please fix the anonymous bool. The rest are nits and suggestions, which you can heed or ignore at your whim. > Source/WebCore/platform/graphics/chromium/ImageDecodingStore.cpp:80 > +bool ImageDecodingStore::lockCache(const ImageFrameGenerator* generator, const SkISize& scaledSize, bool cacheMustBeComplete, const ScaledImageFragment** cachedImage, ImageDecoder** decoder) For cacheMustBeComplete: "Prefer enums to bools on function parameters if callers are likely to be passing constants, since named constants are easier to read at the call site." > Source/WebCore/platform/graphics/chromium/ImageDecodingStore.cpp:82 > CacheEntry* cacheEntry = 0; Maybe ASSERT(cachedImage) here? Seems to be non-optional outparam. (I'd actually keep it as the actual return value, since only decoder seems to be optional, but that's just personal style.) > Source/WebCore/platform/graphics/chromium/ImageDecodingStore.cpp:103 > + if (decoder) > + *decoder = cacheEntry->cachedDecoder(); (Suggestion) Would it make sense to have this function return a cacheEntry instead, so the caller could just get the decoder from it? Or would that expose too much implementation to the caller? > Source/WebCore/platform/graphics/chromium/ImageDecodingStore.cpp:152 > + OwnPtr<ImageDecoder> trash; Does this really need to live to end of function scope? (I'm guessing yes, just making sure.) > Source/WebCore/platform/graphics/chromium/ImageDecodingStore.cpp:168 > + cacheEntry->overwriteCachedImage(newImage); > + newCachedImage = cacheEntry->cachedImage(); > + > + // Image is complete then decoder is not needed. > + if (cacheEntry->cachedImage()->isComplete()) > + trash = cacheEntry->releaseCachedDecoder(); (Suggestion) It seems like the only place you releaseCachedDecoder() is right after calling overwriteCachedImage(). If that's always going to be true, perhaps you should just have overwriteCachedImage() release the decoder itself if isComplete() is true?
Hin-Chung Lam
Comment 6 2012-12-07 15:27:13 PST
Hin-Chung Lam
Comment 7 2012-12-07 15:27:19 PST
Comment on attachment 177684 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=177684&action=review >> Source/WebCore/platform/graphics/chromium/ImageDecodingStore.cpp:80 >> +bool ImageDecodingStore::lockCache(const ImageFrameGenerator* generator, const SkISize& scaledSize, bool cacheMustBeComplete, const ScaledImageFragment** cachedImage, ImageDecoder** decoder) > > For cacheMustBeComplete: "Prefer enums to bools on function parameters if callers are likely to be passing constants, since named constants are easier to read at the call site." Okay. >> Source/WebCore/platform/graphics/chromium/ImageDecodingStore.cpp:82 >> CacheEntry* cacheEntry = 0; > > Maybe ASSERT(cachedImage) here? Seems to be non-optional outparam. (I'd actually keep it as the actual return value, since only decoder seems to be optional, but that's just personal style.) Done. >> Source/WebCore/platform/graphics/chromium/ImageDecodingStore.cpp:103 >> + *decoder = cacheEntry->cachedDecoder(); > > (Suggestion) Would it make sense to have this function return a cacheEntry instead, so the caller could just get the decoder from it? Or would that expose too much implementation to the caller? I want to keep CacheEntry internal to ImageDecodingStore. >> Source/WebCore/platform/graphics/chromium/ImageDecodingStore.cpp:152 >> + OwnPtr<ImageDecoder> trash; > > Does this really need to live to end of function scope? (I'm guessing yes, just making sure.) Yes so that deleting the object doesn't live inside the lock. >> Source/WebCore/platform/graphics/chromium/ImageDecodingStore.cpp:168 >> + trash = cacheEntry->releaseCachedDecoder(); > > (Suggestion) It seems like the only place you releaseCachedDecoder() is right after calling overwriteCachedImage(). If that's always going to be true, perhaps you should just have overwriteCachedImage() release the decoder itself if isComplete() is true? Good idea, will do.
Stephen White
Comment 8 2012-12-07 16:36:31 PST
Comment on attachment 178292 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=178292&action=review OK. The logic still seems a bit complex, but perhaps that can be cleaned up later. r=me > Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp:191 > + *decoder = m_imageDecoderFactory->create().leakPtr(); I wonder if this function (and others) should take an OwnPtr<ImageDecoder>* instead? Then you wouldn't have to call leakPtr() here.
Hin-Chung Lam
Comment 9 2012-12-07 18:13:21 PST
(In reply to comment #8) > (From update of attachment 178292 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=178292&action=review > > OK. The logic still seems a bit complex, but perhaps that can be cleaned up later. r=me > > > Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp:191 > > + *decoder = m_imageDecoderFactory->create().leakPtr(); > ImageDecodingStore is pretty close to complete and concise. There will be some more work in ImageFrameGenerator later. > I wonder if this function (and others) should take an OwnPtr<ImageDecoder>* instead? Then you wouldn't have to call leakPtr() here. One caller doesn't transfer ownership hence it's a ** parameter.
Hin-Chung Lam
Comment 10 2012-12-07 18:14:31 PST
Created attachment 178317 [details] Patch for landing
WebKit Review Bot
Comment 11 2012-12-07 19:01:15 PST
Comment on attachment 178317 [details] Patch for landing Clearing flags on attachment: 178317 Committed r137008: <http://trac.webkit.org/changeset/137008>
WebKit Review Bot
Comment 12 2012-12-07 19:01:20 PST
All reviewed patches have been landed. Closing bug.
Min Qin
Comment 13 2012-12-10 22:16:33 PST
*** Bug 104311 has been marked as a duplicate of this bug. ***
Note You need to log in before you can comment on or make changes to this bug.