Bug 110778 - Unlock partially decoded images after passing them to the ImageDecodingStore
Summary: Unlock partially decoded images after passing them to the ImageDecodingStore
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-02-25 11:43 PST by Min Qin
Modified: 2013-02-27 14:51 PST (History)
5 users (show)

See Also:


Attachments
Patch (15.17 KB, patch)
2013-02-25 11:48 PST, Min Qin
no flags Details | Formatted Diff | Diff
Patch (16.13 KB, patch)
2013-02-27 12:22 PST, Min Qin
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Min Qin 2013-02-25 11:43:21 PST
Unlock partially decoded images after passing them to the ImageDecodingStore
Comment 1 Min Qin 2013-02-25 11:48:56 PST
Created attachment 190101 [details]
Patch
Comment 2 Hin-Chung Lam 2013-02-25 12:03:41 PST
Comment on attachment 190101 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=190101&action=review

Please move locking logic of ImageDecoder into ImageDecodingStore. ImageFrameGenerator shouldn't know about the underlying, it should only know that when an entry is locked, all locked resources are ready to be used.

> Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp:145
> +        cachedDecoder->lockFrameBuffers();

You want to call this in ImageDecodingStore::lockCache() such that if lockFrameBuffers fails then a new decoder is created.

> Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp:150
> +            cachedDecoder->unlockFrameBuffers();

Move this to ImageDecodingStore as well.

> Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp:178
> +        decoder->unlockFrameBuffers();

Move this to ImageDecodingStore.
Comment 3 Min Qin 2013-02-25 12:32:47 PST
Comment on attachment 190101 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=190101&action=review

>> Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp:145
>> +        cachedDecoder->lockFrameBuffers();
> 
> You want to call this in ImageDecodingStore::lockCache() such that if lockFrameBuffers fails then a new decoder is created.

The lockFrameBuffers() will not fail here. We reach here only if ImageDecodingStore::lockCache() succeeds. Since that call will lock the DiscardablePixelRef, so lockFrameBuffers() will not fail. It only increments the pixelref lock count by 1.
Maybe I should add a comment to mention that the FrameBuffer is already locked when this gets called, so we are safe to use the same decoder.

>> Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp:150
>> +            cachedDecoder->unlockFrameBuffers();
> 
> Move this to ImageDecodingStore as well.

same reason

>> Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp:178
>> +        decoder->unlockFrameBuffers();
> 
> Move this to ImageDecodingStore.

same reason, we are safe to call this here.
Comment 4 Min Qin 2013-02-25 15:19:46 PST
Comment on attachment 190101 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=190101&action=review

>>> Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp:145
>>> +        cachedDecoder->lockFrameBuffers();
>> 
>> You want to call this in ImageDecodingStore::lockCache() such that if lockFrameBuffers fails then a new decoder is created.
> 
> The lockFrameBuffers() will not fail here. We reach here only if ImageDecodingStore::lockCache() succeeds. Since that call will lock the DiscardablePixelRef, so lockFrameBuffers() will not fail. It only increments the pixelref lock count by 1.
> Maybe I should add a comment to mention that the FrameBuffer is already locked when this gets called, so we are safe to use the same decoder.

One more thing: ImageDecodingStore doesn't know the status of the decoding, while ImageFrameGenerator keeps track of the decoding status.
If we lock the frameBuffer inside lockCache(), imageDecodingStore will have a problem to determine when to unlock the framebuffer. The next call can be either unlockCache, insertAndLockCache, or overwriteAndLockCache.
Since this lock is associated with decoder, i think it should belong to ImageFrameGenerator, not the ImageDecodingStore. ideas?
Comment 5 Hin-Chung Lam 2013-02-27 11:02:48 PST
Comment on attachment 190101 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=190101&action=review

>>>> Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp:145
>>>> +        cachedDecoder->lockFrameBuffers();
>>> 
>>> You want to call this in ImageDecodingStore::lockCache() such that if lockFrameBuffers fails then a new decoder is created.
>> 
>> The lockFrameBuffers() will not fail here. We reach here only if ImageDecodingStore::lockCache() succeeds. Since that call will lock the DiscardablePixelRef, so lockFrameBuffers() will not fail. It only increments the pixelref lock count by 1.
>> Maybe I should add a comment to mention that the FrameBuffer is already locked when this gets called, so we are safe to use the same decoder.
> 
> One more thing: ImageDecodingStore doesn't know the status of the decoding, while ImageFrameGenerator keeps track of the decoding status.
> If we lock the frameBuffer inside lockCache(), imageDecodingStore will have a problem to determine when to unlock the framebuffer. The next call can be either unlockCache, insertAndLockCache, or overwriteAndLockCache.
> Since this lock is associated with decoder, i think it should belong to ImageFrameGenerator, not the ImageDecodingStore. ideas?

This is probably okay for now for single frame images but won't work well for multiframe images.

Please add a comment here to explain why this call is safe and that it only works for single frame images. I would even do this:

bool frameBuffersLocked = cacheDecoder->lockFrameBuffers();
ASSERT_UNUSED(frameBuffersLocked, frameBuffersLocked);

>>> Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp:150
>>> +            cachedDecoder->unlockFrameBuffers();
>> 
>> Move this to ImageDecodingStore as well.
> 
> same reason

Also add an explanation here why unlock is needed. The reason here is because ImageDecodingStore deletes the ImageDecoder if image is complete.

>>> Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp:178
>>> +        decoder->unlockFrameBuffers();
>> 
>> Move this to ImageDecodingStore.
> 
> same reason, we are safe to call this here.

Same here, add explanation please.

> Source/WebCore/platform/image-decoders/ImageDecoder.h:426
> +        virtual void lockFrameBuffers()

Can you change this to bool? It returns true if all frames are locked, false otherwise.
Comment 6 Hin-Chung Lam 2013-02-27 11:03:34 PST
I'm okay to keep this change simple and leave the problems for multiframe images later.

A few more changes and this is good to go! :)
Comment 7 Min Qin 2013-02-27 12:22:11 PST
Created attachment 190576 [details]
Patch
Comment 8 Min Qin 2013-02-27 12:23:27 PST
Comment on attachment 190101 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=190101&action=review

>>>>> Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp:145
>>>>> +        cachedDecoder->lockFrameBuffers();
>>>> 
>>>> You want to call this in ImageDecodingStore::lockCache() such that if lockFrameBuffers fails then a new decoder is created.
>>> 
>>> The lockFrameBuffers() will not fail here. We reach here only if ImageDecodingStore::lockCache() succeeds. Since that call will lock the DiscardablePixelRef, so lockFrameBuffers() will not fail. It only increments the pixelref lock count by 1.
>>> Maybe I should add a comment to mention that the FrameBuffer is already locked when this gets called, so we are safe to use the same decoder.
>> 
>> One more thing: ImageDecodingStore doesn't know the status of the decoding, while ImageFrameGenerator keeps track of the decoding status.
>> If we lock the frameBuffer inside lockCache(), imageDecodingStore will have a problem to determine when to unlock the framebuffer. The next call can be either unlockCache, insertAndLockCache, or overwriteAndLockCache.
>> Since this lock is associated with decoder, i think it should belong to ImageFrameGenerator, not the ImageDecodingStore. ideas?
> 
> This is probably okay for now for single frame images but won't work well for multiframe images.
> 
> Please add a comment here to explain why this call is safe and that it only works for single frame images. I would even do this:
> 
> bool frameBuffersLocked = cacheDecoder->lockFrameBuffers();
> ASSERT_UNUSED(frameBuffersLocked, frameBuffersLocked);

Done.

>>>> Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp:150
>>>> +            cachedDecoder->unlockFrameBuffers();
>>> 
>>> Move this to ImageDecodingStore as well.
>> 
>> same reason
> 
> Also add an explanation here why unlock is needed. The reason here is because ImageDecodingStore deletes the ImageDecoder if image is complete.

Done.

>>>> Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp:178
>>>> +        decoder->unlockFrameBuffers();
>>> 
>>> Move this to ImageDecodingStore.
>> 
>> same reason, we are safe to call this here.
> 
> Same here, add explanation please.

Done.

>> Source/WebCore/platform/image-decoders/ImageDecoder.h:426
>> +        virtual void lockFrameBuffers()
> 
> Can you change this to bool? It returns true if all frames are locked, false otherwise.

Done.
Comment 9 Hin-Chung Lam 2013-02-27 13:42:02 PST
Comment on attachment 190576 [details]
Patch

LGTM.
Comment 10 Min Qin 2013-02-27 13:42:58 PST
Stephen, would you please take a look? Thanks
Comment 11 Stephen White 2013-02-27 13:53:38 PST
Comment on attachment 190576 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=190576&action=review

Pretty much a rubber-stamp.  r=me

> Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp:157
> +        // ImageDecodingStore should have deleted the decoder here.

Nit:  Is this something worth asserting in code of instead of in a comment, if possible?
Comment 12 Min Qin 2013-02-27 14:09:10 PST
Comment on attachment 190576 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=190576&action=review

>> Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp:157
>> +        // ImageDecodingStore should have deleted the decoder here.
> 
> Nit:  Is this something worth asserting in code of instead of in a comment, if possible?

hmm... probably this is not a good place to put the assertion. The cachedDecoder here is a dumb pointer. In order to check whether the decoder is deleted, we have to call lockCache() again. But that would break the lock/unlock situation.
An alternative is to put the assertion check into overwriteAndLockCache(). But the logic is already pretty straightforward inside that function.
Comment 13 WebKit Review Bot 2013-02-27 14:51:26 PST
Comment on attachment 190576 [details]
Patch

Clearing flags on attachment: 190576

Committed r144242: <http://trac.webkit.org/changeset/144242>
Comment 14 WebKit Review Bot 2013-02-27 14:51:29 PST
All reviewed patches have been landed.  Closing bug.