-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Move image decoding WorkQueue to a separate class named ImageFrameWorkQueue #23318
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
EWS run on previous version of this PR (hash 44c7b71) Details
|
…kQueue https://bugs.webkit.org/show_bug.cgi?id=268184 rdar://121677190 Reviewed by NOBODY (OOPS!). ImageSource will ask ImageFrameWorkQueue to decode the image frames. Once the image frame is decoded, ImageSource will be notifed to cache the decoded frame and tell the observer to repaint its renderer. Alos ImageFrameWorkQueue will answer whether a frame is being decoded or not. * Source/WebCore/Headers.cmake: * Source/WebCore/Sources.txt: * Source/WebCore/WebCore.xcodeproj/project.pbxproj: * Source/WebCore/loader/cache/CachedImage.cpp: (WebCore::CachedImage::removeAllClientsWaitingForAsyncDecoding): * Source/WebCore/platform/graphics/BitmapImage.cpp: (WebCore::BitmapImage::~BitmapImage): (WebCore::BitmapImage::destroyDecodedData): (WebCore::BitmapImage::draw): (WebCore::BitmapImage::canDestroyDecodedData): (WebCore::BitmapImage::internalStartAnimation): (WebCore::BitmapImage::advanceAnimation): (WebCore::BitmapImage::internalAdvanceAnimation): (WebCore::BitmapImage::stopAnimation): (WebCore::BitmapImage::decode): (WebCore::BitmapImage::imageFrameAvailableAtIndex): * Source/WebCore/platform/graphics/BitmapImage.h: * Source/WebCore/platform/graphics/ImageFrameWorkQueue.cpp: Added. (WebCore::ImageFrameWorkQueue::create): (WebCore::ImageFrameWorkQueue::ImageFrameWorkQueue): (WebCore::ImageFrameWorkQueue::requestQueue): (WebCore::ImageFrameWorkQueue::start): (WebCore::ImageFrameWorkQueue::dispatch): (WebCore::ImageFrameWorkQueue::stop): (WebCore::ImageFrameWorkQueue::isPendingDecodingAtIndex const): (WebCore::ImageFrameWorkQueue::dump const): * Source/WebCore/platform/graphics/ImageFrameWorkQueue.h: Added. (WebCore::ImageFrameWorkQueue::isIdle const): (WebCore::ImageFrameWorkQueue::setMinimumDecodingDurationForTesting): (WebCore::ImageFrameWorkQueue::decodeQueue): (WebCore::ImageFrameWorkQueue::minimumDecodingDurationForTesting const): * Source/WebCore/platform/graphics/ImageSource.cpp: (WebCore::ImageSource::~ImageSource): (WebCore::ImageSource::ensureDecoderAvailable): (WebCore::ImageSource::cacheNativeImageAtIndex): (WebCore::ImageSource::cacheNativeImageAtIndexAsync): (WebCore::ImageSource::clearFrameAtIndex): (WebCore::ImageSource::workQueue): (WebCore::ImageSource::requestFrameAsyncDecodingAtIndex): (WebCore::ImageSource::stopWorkQueue): (WebCore::ImageSource::setMinimumDecodingDurationForTesting): (WebCore::ImageSource::frameAtIndexCacheIfNeeded): (WebCore::ImageSource::sourceUTF8 const): (WebCore::ImageSource::frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex): (WebCore::ImageSource::cachePlatformImageAtIndex): Deleted. (WebCore::ImageSource::cachePlatformImageAtIndexAsync): Deleted. (WebCore::ImageSource::decodingQueue): Deleted. (WebCore::ImageSource::frameRequestQueue): Deleted. (WebCore::ImageSource::startAsyncDecodingQueue): Deleted. (WebCore::ImageSource::isAsyncDecodingQueueIdle const): Deleted. (WebCore::ImageSource::stopAsyncDecodingQueue): Deleted. * Source/WebCore/platform/graphics/ImageSource.h: * Source/WebCore/testing/Internals.cpp: (WebCore::Internals::setImageFrameDecodingDuration):
44c7b71 to
d20aed3
Compare
|
EWS run on current version of this PR (hash d20aed3) Details
|
| ASSERT((!index && !m_currentFrame) || !canAnimate()); | ||
| if (m_source->isAsyncDecodingQueueIdle()) | ||
| m_source->stopAsyncDecodingQueue(); | ||
| if (m_source->isWorkQueueIdle()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should hold a Ref to the source on the stack:
if (Ref source = m_source; source->isWorkQueueIdle())
source->stopWorkQueue();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will be fixed in #20916 but in ImageFrameProvider::stopDecodingWorkQueue().
|
|
||
| bool shouldUseAsyncDecodingForTesting() const { return m_source->frameDecodingDurationForTesting() > 0_s; } | ||
| void setFrameDecodingDurationForTesting(Seconds duration) { m_source->setFrameDecodingDurationForTesting(duration); } | ||
| void setMinimumDecodingDurationForTesting(Seconds duration) { m_source->setMinimumDecodingDurationForTesting(duration); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ref { m_source }->setMinimumDecodingDurationForTesting(duration) per our new smart pointer guidelines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can also add a protectedSource() getter which returns a Ref<> if you want to make this look nicer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will be fixed in #20916.
| void setAsyncDecodingEnabledForTesting(bool enabled) { m_asyncDecodingEnabledForTesting = enabled; } | ||
| bool isAsyncDecodingEnabledForTesting() const { return m_asyncDecodingEnabledForTesting; } | ||
| void stopAsyncDecodingQueue() { m_source->stopAsyncDecodingQueue(); } | ||
| void stopWorkQueue() { m_source->stopWorkQueue(); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will be fixed in #20916.
| if (m_workQueue) | ||
| return; | ||
|
|
||
| ASSERT(isMainThread()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to move this above, before the early return.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will be fixed in #20916.
| if (minimumDecodingDuration > 0_s) | ||
| startingTime = MonotonicTime::now(); | ||
|
|
||
| auto platformImage = decoder->createFrameImageAtIndex(request.index, request.subsamplingLevel, request.options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please do not obfuscate smart pointers with auto, use RefPtr
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will be fixed in #20916.
| { | ||
| if (hasAsyncDecodingQueue() || !isDecoderAvailable()) | ||
| return; | ||
| if (!m_workQueue) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this always called on the same thread? If not, we have a thread-safety issue here and would need a Lock.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes this is called only on the main thread. In #20916. ImageFrameProvider will owns the ImageFrameWorkQueue.
| }); | ||
| LOG(Images, "ImageSource::%s - %p - url: %s. Decoding work queue will be stopped.", __FUNCTION__, this, sourceUTF8()); | ||
|
|
||
| m_workQueue->stop(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need a Ref/RefPtr on the stack before you call stop(), e.g. RefPtr { m_workQueue }->stop() or protectedWorkQueue()->stop()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be fixed in #20916 but in ImageFrameProvider since it will own the ImageFrameWorkQueue.
|
|
||
| // We have to perform synchronous image decoding in this code. | ||
| auto platformImage = m_decoder->createFrameImageAtIndex(index, subsamplingLevelValue, decodingOptions); | ||
| auto platformImage = m_decoder->createFrameImageAtIndex(index, currentSubsamplingLevel, decodingOptions); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't hide smart pointers with auto.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will be fixed in #20916. All auto platformImage = ... are replaced by `PlatformImagePtr platformImage = ...
| // We have to perform synchronous image decoding in this code. | ||
| auto platformImage = m_decoder->createFrameImageAtIndex(index, subsamplingLevelValue, decodingOptions); | ||
| auto platformImage = m_decoder->createFrameImageAtIndex(index, currentSubsamplingLevel, decodingOptions); | ||
| auto nativeImage = NativeImage::create(WTFMove(platformImage)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will be fixed in #20916. All auto nativeImage = ... are replaced by RefPtr nativeImage = ...
|
|
||
| m_workQueue->dispatch([protectedThis = Ref { *this }, protectedWorkQueue = Ref { *m_workQueue }, protectedSource = Ref { source() }] () mutable { | ||
| Request request; | ||
| while (protectedThis->requestQueue().dequeue(request)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to look into the implementation of this requestQueue(). I assume it does locking?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, it's a SynchronizedFixedQueue which does indeed Lock internally. All good.
d20aed3
d20aed3