Changeset 222427 in webkit
- Timestamp:
- Sep 23, 2017 2:05:52 PM (7 years ago)
- Location:
- trunk/Source
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WTF/ChangeLog
r222422 r222427 1 2017-09-23 Said Abou-Hallawa <sabouhallawa@apple.com> 2 3 Images may render partial frames even after loading all the encoded data 4 https://bugs.webkit.org/show_bug.cgi?id=177406 5 6 Reviewed by Simon Fraser. 7 8 Make it possible to create a RefPtr<SynchronizedFixedQueue>. 9 10 * wtf/SynchronizedFixedQueue.h: 11 (WTF::SynchronizedFixedQueue::create): 12 (WTF::SynchronizedFixedQueue::enqueue): 13 (WTF::SynchronizedFixedQueue::dequeue): 14 1 15 2017-09-22 Zalan Bujtas <zalan@apple.com> 2 16 -
trunk/Source/WTF/wtf/SynchronizedFixedQueue.h
r218594 r222427 29 29 #include <wtf/Deque.h> 30 30 #include <wtf/Lock.h> 31 #include <wtf/ThreadSafeRefCounted.h> 31 32 32 33 namespace WTF { 33 34 34 35 template<typename T, size_t BufferSize> 35 class SynchronizedFixedQueue {36 class SynchronizedFixedQueue : public ThreadSafeRefCounted<SynchronizedFixedQueue<T, BufferSize>> { 36 37 public: 38 static Ref<SynchronizedFixedQueue> create() 39 { 40 return adoptRef(*new SynchronizedFixedQueue()); 41 } 42 37 43 SynchronizedFixedQueue() 38 44 { 39 45 static_assert(!((BufferSize - 1) & BufferSize), "BufferSize must be power of 2."); 40 46 } 41 47 42 48 void open() 43 49 { … … 50 56 m_queue.clear(); 51 57 } 52 58 53 59 void close() 54 60 { … … 61 67 m_condition.notifyAll(); 62 68 } 63 69 64 70 bool isOpen() 65 71 { … … 74 80 // Wait for an empty place to be available in the queue. 75 81 m_condition.wait(m_mutex, [this]() { return !m_open || m_queue.size() < BufferSize; }); 76 82 77 83 // The queue is closing, exit immediately. 78 84 if (!m_open) 79 85 return false; 80 86 81 87 // Add the item in the queue. 82 88 m_queue.append(value); … … 86 92 return true; 87 93 } 88 94 89 95 bool dequeue(T& value) 90 96 { 91 97 LockHolder lockHolder(m_mutex); 92 98 93 99 // Wait for an item to be added. 94 100 m_condition.wait(m_mutex, [this]() { return !m_open || m_queue.size(); }); -
trunk/Source/WebCore/ChangeLog
r222422 r222427 1 2017-09-23 Said Abou-Hallawa <sabouhallawa@apple.com> 2 3 Images may render partial frames even after loading all the encoded data 4 https://bugs.webkit.org/show_bug.cgi?id=177406 5 6 Reviewed by Simon Fraser. 7 8 Because we do not want to block the main thread waiting for the image decoding 9 thread to terminate, we let the decoding thread finish its work even it will 10 be thrown away. If a new decoding thread is created and the SynchronizedFixedQueue 11 is reopened, the terminating decoding thread might have the chance to process 12 a new frame request. After it finishes decoding it, it realize that it is 13 terminating so it will drop the decoded frame to the floor. So the new request 14 was not processed by the new thread and because it was processed by the 15 terminating thread, nothing will be reported to the BitmapImage object and 16 the renderer will not be repainted. 17 18 The fix is to create a new SynchronizedFixedQueue every time a decoding 19 thread is created. This will guarantee that the terminating thread won't 20 have access to the new frame request and will shut down after being notified 21 by the old SynchronizedFixedQueue that it has been closed. 22 23 * platform/graphics/ImageFrameCache.cpp: 24 (WebCore::ImageFrameCache::frameRequestQueue): 25 (WebCore::ImageFrameCache::startAsyncDecodingQueue): 26 (WebCore::ImageFrameCache::requestFrameAsyncDecodingAtIndex): 27 (WebCore::ImageFrameCache::stopAsyncDecodingQueue): 28 * platform/graphics/ImageFrameCache.h: 29 1 30 2017-09-22 Zalan Bujtas <zalan@apple.com> 2 31 -
trunk/Source/WebCore/platform/graphics/ImageFrameCache.cpp
r222225 r222427 271 271 } 272 272 273 Ref<ImageFrameCache::FrameRequestQueue> ImageFrameCache::frameRequestQueue() 274 { 275 if (!m_frameRequestQueue) 276 m_frameRequestQueue = FrameRequestQueue::create(); 277 278 return *m_frameRequestQueue; 279 } 280 273 281 void ImageFrameCache::startAsyncDecodingQueue() 274 282 { … … 276 284 return; 277 285 278 m_frameRequestQueue.open();279 280 286 // We need to protect this, m_decodingQueue and m_decoder from being deleted while we are in the decoding loop. 281 decodingQueue()->dispatch([protectedThis = makeRef(*this), protected Queue = decodingQueue(), protectedDecoder = makeRef(*m_decoder), sourceURL = sourceURL().string().isolatedCopy()] {287 decodingQueue()->dispatch([protectedThis = makeRef(*this), protectedDecodingQueue = decodingQueue(), protectedFrameRequestQueue = frameRequestQueue(), protectedDecoder = makeRef(*m_decoder), sourceURL = sourceURL().string().isolatedCopy()] { 282 288 ImageFrameRequest frameRequest; 283 289 284 while (protected This->m_frameRequestQueue.dequeue(frameRequest)) {290 while (protectedFrameRequestQueue->dequeue(frameRequest)) { 285 291 TraceScope tracingScope(AsyncImageDecodeStart, AsyncImageDecodeEnd); 286 292 … … 295 301 296 302 // Update the cached frames on the main thread to avoid updating the MemoryCache from a different thread. 297 callOnMainThread([protectedThis = protectedThis.copyRef(), protectedQueue = protected Queue.copyRef(), protectedDecoder = protectedDecoder.copyRef(), sourceURL = sourceURL.isolatedCopy(), nativeImage = WTFMove(nativeImage), frameRequest] () mutable {303 callOnMainThread([protectedThis = protectedThis.copyRef(), protectedQueue = protectedDecodingQueue.copyRef(), protectedDecoder = protectedDecoder.copyRef(), sourceURL = sourceURL.isolatedCopy(), nativeImage = WTFMove(nativeImage), frameRequest] () mutable { 298 304 // The queue may have been closed if after we got the frame NativeImage, stopAsyncDecodingQueue() was called. 299 305 if (protectedQueue.ptr() == protectedThis->m_decodingQueue && protectedDecoder.ptr() == protectedThis->m_decoder) { … … 318 324 319 325 LOG(Images, "ImageFrameCache::%s - %p - url: %s [enqueuing frame %ld for decoding]", __FUNCTION__, this, sourceURL().string().utf8().data(), index); 320 m_frameRequestQueue .enqueue({ index, subsamplingLevel, sizeForDrawing, decodingStatus });326 m_frameRequestQueue->enqueue({ index, subsamplingLevel, sizeForDrawing, decodingStatus }); 321 327 m_frameCommitQueue.append({ index, subsamplingLevel, sizeForDrawing, decodingStatus }); 322 328 } … … 340 346 }); 341 347 342 m_frameRequestQueue.close(); 348 // Close m_frameRequestQueue then set it to nullptr. A new decoding thread might start and a 349 // new m_frameRequestQueue will be created. So the terminating thread will not have access to it. 350 m_frameRequestQueue->close(); 351 m_frameRequestQueue = nullptr; 343 352 m_frameCommitQueue.clear(); 344 353 m_decodingQueue = nullptr; -
trunk/Source/WebCore/platform/graphics/ImageFrameCache.h
r222225 r222427 138 138 void cacheNativeImageAtIndexAsync(NativeImagePtr&&, size_t, SubsamplingLevel, const DecodingOptions&, DecodingStatus); 139 139 140 struct ImageFrameRequest; 141 static const int BufferSize = 8; 140 142 Ref<WorkQueue> decodingQueue(); 143 Ref<SynchronizedFixedQueue<ImageFrameRequest, BufferSize>> frameRequestQueue(); 141 144 142 145 const ImageFrame& frameAtIndexCacheIfNeeded(size_t, ImageFrame::Caching, const std::optional<SubsamplingLevel>& = { }); … … 160 163 } 161 164 }; 162 static const int BufferSize = 8;163 165 using FrameRequestQueue = SynchronizedFixedQueue<ImageFrameRequest, BufferSize>; 164 166 using FrameCommitQueue = Deque<ImageFrameRequest, BufferSize>; 165 FrameRequestQueuem_frameRequestQueue;167 RefPtr<FrameRequestQueue> m_frameRequestQueue; 166 168 FrameCommitQueue m_frameCommitQueue; 167 169 RefPtr<WorkQueue> m_decodingQueue;
Note: See TracChangeset
for help on using the changeset viewer.