Title: [270478] trunk
Revision
270478
Author
wenson_hs...@apple.com
Date
2020-12-05 14:17:10 -0800 (Sat, 05 Dec 2020)

Log Message

[Concurrent display lists] Synchronize display list rendering across remote image buffers
https://bugs.webkit.org/show_bug.cgi?id=219091
<rdar://problem/71747695>

Reviewed by Geoff Garen.

Source/WebCore:

See Source/WebKit/ChangeLog for more details.

* platform/graphics/ImageBuffer.h:
* platform/graphics/displaylists/DisplayList.cpp:
(WebCore::DisplayList::DisplayList::append):
* platform/graphics/displaylists/DisplayListItemBuffer.cpp:
(WebCore::DisplayList::ItemHandle::apply):
(WebCore::DisplayList::ItemHandle::destroy):
(WebCore::DisplayList::ItemHandle::copyTo const):
(WebCore::DisplayList::ItemBuffer::swapWritableBufferIfNeeded):

Add plumbing so that `didAppendData` can inform the client whether the data was appended after switching to a
new buffer. In WebKit2's remote image buffer, we use this information to determine whether or not we need to
send a wakeup message to the GPU process. Namely, in the case of `DidChangeItemBuffer::Yes`, we don't need to
wake up the GPU process even though the unread bytes count was 0 before we advanced, since the GPU process will
automatically progress to this item buffer when it's done processing items in the previous item buffer.

See WebKit changes (in `RemoteImageBufferProxy`) for more details.

(WebCore::DisplayList::ItemBuffer::append):
(WebCore::DisplayList::ItemBuffer::didAppendData):
(WebCore::DisplayList::ItemBuffer::appendEncodedData): Deleted.
* platform/graphics/displaylists/DisplayListItemBuffer.h:

Add a new `ItemBufferWritingClient` method to inform clients when new bytes are appended to an item buffer,
given the additional number of bytes added and the item buffer handle.

(WebCore::DisplayList::ItemBuffer::append):
(WebCore::DisplayList::ItemBuffer::uncheckedAppend):
* platform/graphics/displaylists/DisplayListItemType.cpp:
(WebCore::DisplayList::sizeOfItemInBytes):
(WebCore::DisplayList::isDrawingItem):
(WebCore::DisplayList::isInlineItem):

Remove MetaCommandEnd. I introduced this item type because I was going to make the GPU process always sleep for
more display list item data, but I've since changed the approach so that the GPU process goes to sleep naturally
when it's done processing all unread bytes.

* platform/graphics/displaylists/DisplayListItemType.h:
* platform/graphics/displaylists/DisplayListItems.cpp:
(WebCore::DisplayList::operator<<):
* platform/graphics/displaylists/DisplayListItems.h:
* platform/graphics/displaylists/DisplayListRecorder.h:
(WebCore::DisplayList::Recorder::flushContext):

Add a new helper method to append a `FlushContext` item via the display list recorder, to ensure that the
appropriate recorder delegate methods are invoked when appending a "flush context" item.

* platform/graphics/displaylists/DisplayListReplayer.cpp:
(WebCore::DisplayList::Replayer::replay):
* platform/graphics/displaylists/DisplayListReplayer.h:

Source/WebKit:

Refactors the existing concurrent display list processing mechanism, such that we no longer update the unread
bytes count every 512 items (or when flushing the drawing context), and instead update it every time we append
display list item data. In order to achieve this without making it impossible for multiple display-list backed
image buffers to render simultaneously, we also add support for synchronizing display list items across
different image buffers by using the new meta command items added in bug #219262. As detailed in the ChangeLog
for that bug, a stream of display list data written by the web process and consumed by the GPU process is now
structured like so:

Wakeup message initiates display list processing with Image Buffer A and Item Buffer 1
    |
    |   MetaCommandChangeDestinationImageBuffer(B)
    |                       |
    |                       |                  MetaCommandChangeItemBuffer(2)
    |                       |                                |
    |                       |                                |
    v                       v                                v
    +-----------------------+--------------------------------++
    | +--------------------+ +------------------------------+ |
    | | Destination        | | Destination                  | | Item Buffer 1
    | | Image Buffer A     | | Image Buffer B               | |
    | +--------------------+ +------------------------------+ |
    +---------------------------------------------------------+

    +---------------------------------------------------------+
    | +--------------+ +-----------------------+              |
    | | Dst. Image   | | Destination Image     |  Unused      | Item Buffer 2
    | | Buffer B     | | Buffer A              |  Capacity    |
    | +--------------+ +-----------------------+              |
    +-----------------+-------------------------+-------------+
                      ^
                      |
                      |
    MetaCommandChangeDestinationImageBuffer(A)

(Note that the `MetaCommandEnd` item has been omitted, since we no longer need to explicitly tell the GPU
process to go to sleep with the latest iteration of this patch).

In order to write display list data conforming to this format, we add a mechanism to the web process that keeps
track of the "current destination image buffer" (i.e. the image buffer that has most recently
appended a display list item). Right before this destination is about to change, we append a new
`MetaCommandChangeDestinationImageBuffer` item before proceeding to append display list items for the new
current destination.

Since we now bump the unread count every time, we need to do some additional work to avoid an excessive number
of wakeups and sleeps in the GPU process, which would otherwise cause a massive regression. To do this, we
introduce an item count hysteresis in the web process, such that we will wait for 512 items to be written before
attempting to send the wakeup message. This allows the web process to get a small head start over the GPU
process, and thus allows the GPU process to be more consistently busy over the course of a single frame.

On the reader (GPU process) side, we make some minor adjustments so that the main display list processing loop
of the GPU process is capable of changing destination image buffers while processing a stream of display list
items.

See below for more details.

* GPUProcess/graphics/DisplayListReaderHandle.cpp:
(WebKit::DisplayListReaderHandle::advance):

Update `advance` so that it just performs a single 8-byte atomic `exchangeSub` rather than grabbing a spinlock.

* GPUProcess/graphics/RemoteRenderingBackend.cpp:
(WebKit::RemoteRenderingBackend::submit):
(WebKit::RemoteRenderingBackend::nextDestinationImageBufferAfterApplyingDisplayLists):

Rename `applyDisplayListsFromHandle` to `nextDestinationImageBufferAfterApplyingDisplayLists`, and make it
return the current image buffer to use as the destination for replaying display list commands. This helper is
still responsible for replaying a display list item buffer until it has no more data (that is, until we
encounter a `MetaCommandChangeItemBuffer` item informing us of the next item buffer to consume).

(WebKit::RemoteRenderingBackend::wakeUpAndApplyDisplayList):

Adjust this to call `nextDestinationImageBufferAfterApplyingDisplayLists`.

(WebKit::RemoteRenderingBackend::decodeItem):
(WebKit::RemoteRenderingBackend::applyDisplayListsFromHandle): Deleted.
* GPUProcess/graphics/RemoteRenderingBackend.h:
* Shared/SharedDisplayListHandle.h:

Remove `SharedDisplayListHandle::Lock` altogether, now that we just have a single atomic `uint64_t` counter to
represent the number of unread bytes.

(WebKit::SharedDisplayListHandle::unreadBytes):
(WebKit::SharedDisplayListHandle::Lock::Lock): Deleted.
(WebKit::SharedDisplayListHandle::Lock::~Lock): Deleted.
* WebProcess/GPU/graphics/DisplayListWriterHandle.cpp:
(WebKit::DisplayListWriterHandle::advance):

Make this use the single atomic counter, instead of grabbing a spinlock.

(WebKit::DisplayListWriterHandle::moveWritableOffsetToStartIfPossible):
(WebKit::DisplayListWriterHandle::resetWritableOffsetIfPossible): Deleted.

Rename `resetWritableOffsetIfPossible` to the more accurate `moveWritableOffsetToStartIfPossible`.

* WebProcess/GPU/graphics/DisplayListWriterHandle.h:
* WebProcess/GPU/graphics/RemoteImageBufferProxy.h:
(WebKit::RemoteImageBufferProxy::changeDestinationImageBuffer):

Add a helper method to append a `MetaCommandChangeDestinationImageBuffer` item to the display list, given the
identifier of this next item buffer.

(WebKit::RemoteImageBufferProxy::clearDisplayList):

Add a helper method to clear the display list, such that the `RemoteImageBufferProxy` will be asked for a new
buffer handle the next time we append an item.

(WebKit::RemoteImageBufferProxy::waitForDidFlushWithTimeout):

Make this hit the maximum `waitForAndDispatchImmediately` attempt count and "fail" only if the call to
`waitForAndDispatchImmediately` actually times out. This change is necessary to ensure that the scenario of
multiple image buffers simultaneously appending display list items works when all image buffers perform (non-
blocking) flushes simultaneously, followed by a sync-wait (blocking) flush. In this situation, the web process
may receive more than three `DidFlush` messages in rapid succession, causing it to hit this maximum limit of 3
instantly and avoid waiting for the expected `DidFlush` message to arrive.

(WebKit::RemoteImageBufferProxy::submitDisplayList): Deleted.
* WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp:
(WebKit::RemoteRenderingBackendProxy::gpuProcessConnectionDidClose):

Reset state when the GPU process is terminated.

(WebKit::RemoteRenderingBackendProxy::willAppendItem):

Update the current destination image buffer (`m_currentDestinationImageBufferIdentifier`). If this identifier
changed, then we append a `MetaCommandChangeDestinationImageBuffer` item to the previous destination before
setting the new destination image buffer. We also need to clear the new destination image buffer's display list
before writing new items, to prevent it from overwriting shared display list item data.

(WebKit::RemoteRenderingBackendProxy::sendWakeupMessage):
(WebKit::RemoteRenderingBackendProxy::sendDeferredWakeupMessageIfNeeded):
(WebKit::RemoteRenderingBackendProxy::didAppendData):

Implement a new `ItemBufferWritingClient` hook by advancing the corresponding item buffer's unread count.
Additionally, schedule a wakeup message in the case where the unread count was zero when we advanced, and the
item buffer we've appended to is not "connected" to a previous item buffer by way of an item buffer change item.

Additionally, in the case where we don't schedule a new wakeup message, check whether or not there is a deferred
wakeup message; if there is, then decrement the remaining item count before we send the wakeup message, and send
the message if the count reaches 0.

(WebKit::RemoteRenderingBackendProxy::findReusableDisplayListHandle):

Pull logic to find a shared display list handle suitable for reuse into a separate helper method, and adjust it
so that if the most recently used display list handle has run out of available capacity, we move it to the end
of the reuse queue and only reuse the new first shared handle in the queue if its writable offset can be reset.
This ensures that the GPU process can always continue reading display list item data from the start of new item
buffers -- i.e., we don't end up with the web process writing out a stream of display list data like:

   (Start) Bytes (16, 65520) in ItemBuffer[1]
           Bytes (16, 65536) in ItemBuffer[2]
           Bytes (65520, 65536) in ItemBuffer[1]

(WebKit::RemoteRenderingBackendProxy::createItemBuffer):
(WebKit::RemoteRenderingBackendProxy::submitDisplayList): Deleted.
(WebKit::RemoteRenderingBackendProxy::updateReusableHandles): Deleted.
* WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h:

Tools:

* TestWebKitAPI/Tests/WebCore/DisplayListTests.cpp:
(TestWebKitAPI::TEST):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (270477 => 270478)


--- trunk/Source/WebCore/ChangeLog	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebCore/ChangeLog	2020-12-05 22:17:10 UTC (rev 270478)
@@ -1,3 +1,63 @@
+2020-12-04  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [Concurrent display lists] Synchronize display list rendering across remote image buffers
+        https://bugs.webkit.org/show_bug.cgi?id=219091
+        <rdar://problem/71747695>
+
+        Reviewed by Geoff Garen.
+
+        See Source/WebKit/ChangeLog for more details.
+
+        * platform/graphics/ImageBuffer.h:
+        * platform/graphics/displaylists/DisplayList.cpp:
+        (WebCore::DisplayList::DisplayList::append):
+        * platform/graphics/displaylists/DisplayListItemBuffer.cpp:
+        (WebCore::DisplayList::ItemHandle::apply):
+        (WebCore::DisplayList::ItemHandle::destroy):
+        (WebCore::DisplayList::ItemHandle::copyTo const):
+        (WebCore::DisplayList::ItemBuffer::swapWritableBufferIfNeeded):
+
+        Add plumbing so that `didAppendData` can inform the client whether the data was appended after switching to a
+        new buffer. In WebKit2's remote image buffer, we use this information to determine whether or not we need to
+        send a wakeup message to the GPU process. Namely, in the case of `DidChangeItemBuffer::Yes`, we don't need to
+        wake up the GPU process even though the unread bytes count was 0 before we advanced, since the GPU process will
+        automatically progress to this item buffer when it's done processing items in the previous item buffer.
+
+        See WebKit changes (in `RemoteImageBufferProxy`) for more details.
+
+        (WebCore::DisplayList::ItemBuffer::append):
+        (WebCore::DisplayList::ItemBuffer::didAppendData):
+        (WebCore::DisplayList::ItemBuffer::appendEncodedData): Deleted.
+        * platform/graphics/displaylists/DisplayListItemBuffer.h:
+
+        Add a new `ItemBufferWritingClient` method to inform clients when new bytes are appended to an item buffer,
+        given the additional number of bytes added and the item buffer handle.
+
+        (WebCore::DisplayList::ItemBuffer::append):
+        (WebCore::DisplayList::ItemBuffer::uncheckedAppend):
+        * platform/graphics/displaylists/DisplayListItemType.cpp:
+        (WebCore::DisplayList::sizeOfItemInBytes):
+        (WebCore::DisplayList::isDrawingItem):
+        (WebCore::DisplayList::isInlineItem):
+
+        Remove MetaCommandEnd. I introduced this item type because I was going to make the GPU process always sleep for
+        more display list item data, but I've since changed the approach so that the GPU process goes to sleep naturally
+        when it's done processing all unread bytes.
+
+        * platform/graphics/displaylists/DisplayListItemType.h:
+        * platform/graphics/displaylists/DisplayListItems.cpp:
+        (WebCore::DisplayList::operator<<):
+        * platform/graphics/displaylists/DisplayListItems.h:
+        * platform/graphics/displaylists/DisplayListRecorder.h:
+        (WebCore::DisplayList::Recorder::flushContext):
+
+        Add a new helper method to append a `FlushContext` item via the display list recorder, to ensure that the
+        appropriate recorder delegate methods are invoked when appending a "flush context" item.
+
+        * platform/graphics/displaylists/DisplayListReplayer.cpp:
+        (WebCore::DisplayList::Replayer::replay):
+        * platform/graphics/displaylists/DisplayListReplayer.h:
+
 2020-12-05  Fujii Hironori  <hironori.fu...@sony.com>
 
         Remove ENABLE_GRAPHICS_CONTEXT_GL by replacing it with ENABLE(WEBGL)

Modified: trunk/Source/WebCore/platform/graphics/ImageBuffer.h (270477 => 270478)


--- trunk/Source/WebCore/platform/graphics/ImageBuffer.h	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebCore/platform/graphics/ImageBuffer.h	2020-12-05 22:17:10 UTC (rev 270478)
@@ -79,9 +79,11 @@
     virtual bool prefersPreparationForDisplay() { return false; }
     virtual void flushDrawingContext() { }
     virtual void flushDrawingContextAndCommit() { }
-    virtual void submitDisplayList(const DisplayList::DisplayList&) { }
     virtual void didFlush(DisplayList::FlushIdentifier) { }
 
+    virtual void changeDestinationImageBuffer(RenderingResourceIdentifier) { }
+    virtual void clearDisplayList() { }
+
     virtual IntSize logicalSize() const = 0;
     virtual float resolutionScale() const = 0;
     virtual ColorSpace colorSpace() const = 0;

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayList.cpp (270477 => 270478)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayList.cpp	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayList.cpp	2020-12-05 22:17:10 UTC (rev 270478)
@@ -282,8 +282,6 @@
         return append<MetaCommandChangeDestinationImageBuffer>(item.get<MetaCommandChangeDestinationImageBuffer>());
     case ItemType::MetaCommandChangeItemBuffer:
         return append<MetaCommandChangeItemBuffer>(item.get<MetaCommandChangeItemBuffer>());
-    case ItemType::MetaCommandEnd:
-        return append<MetaCommandEnd>(item.get<MetaCommandEnd>());
     case ItemType::PutImageData:
         return append<PutImageData>(item.get<PutImageData>());
     case ItemType::PaintFrameForMedia:

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItemBuffer.cpp (270477 => 270478)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItemBuffer.cpp	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItemBuffer.cpp	2020-12-05 22:17:10 UTC (rev 270478)
@@ -228,7 +228,6 @@
     }
     case ItemType::MetaCommandChangeDestinationImageBuffer:
     case ItemType::MetaCommandChangeItemBuffer:
-    case ItemType::MetaCommandEnd:
         return;
     case ItemType::PutImageData: {
         get<PutImageData>().apply(context);
@@ -464,10 +463,6 @@
         static_assert(std::is_trivially_destructible<MetaCommandChangeItemBuffer>::value);
         return;
     }
-    case ItemType::MetaCommandEnd: {
-        static_assert(std::is_trivially_destructible<MetaCommandEnd>::value);
-        return;
-    }
     case ItemType::PaintFrameForMedia: {
         static_assert(std::is_trivially_destructible<PaintFrameForMedia>::value);
         return;
@@ -723,10 +718,6 @@
         new (itemOffset) MetaCommandChangeItemBuffer(get<MetaCommandChangeItemBuffer>());
         return;
     }
-    case ItemType::MetaCommandEnd: {
-        new (itemOffset) MetaCommandEnd(get<MetaCommandEnd>());
-        return;
-    }
     case ItemType::PaintFrameForMedia: {
         new (itemOffset) PaintFrameForMedia(get<PaintFrameForMedia>());
         return;
@@ -876,25 +867,25 @@
     m_writtenNumberOfBytes = 0;
 }
 
-void ItemBuffer::swapWritableBufferIfNeeded(size_t numberOfBytes)
+DidChangeItemBuffer ItemBuffer::swapWritableBufferIfNeeded(size_t numberOfBytes)
 {
     auto sizeForBufferSwitchItem = paddedSizeOfTypeAndItemInBytes(ItemType::MetaCommandChangeItemBuffer);
     if (m_writtenNumberOfBytes + numberOfBytes + sizeForBufferSwitchItem <= m_writableBuffer.capacity)
-        return;
+        return DidChangeItemBuffer::No;
 
     auto nextBuffer = createItemBuffer(numberOfBytes + sizeForBufferSwitchItem);
-    bool hadPreviousBuffer = m_writableBuffer;
-    if (hadPreviousBuffer)
-        uncheckedAppend<MetaCommandChangeItemBuffer>(nextBuffer.identifier);
-    auto previousBuffer = std::exchange(m_writableBuffer, { });
-    previousBuffer.capacity = std::exchange(m_writtenNumberOfBytes, 0);
-    if (hadPreviousBuffer)
-        m_readOnlyBuffers.append(WTFMove(previousBuffer));
-
+    bool hadPreviousBuffer = m_writableBuffer && m_writableBuffer.identifier != nextBuffer.identifier;
+    if (hadPreviousBuffer) {
+        uncheckedAppend<MetaCommandChangeItemBuffer>(DidChangeItemBuffer::No, nextBuffer.identifier);
+        m_writableBuffer.capacity = m_writtenNumberOfBytes;
+        m_readOnlyBuffers.append(m_writableBuffer);
+    }
+    m_writtenNumberOfBytes = 0;
     m_writableBuffer = WTFMove(nextBuffer);
+    return hadPreviousBuffer ? DidChangeItemBuffer::Yes : DidChangeItemBuffer::No;
 }
 
-void ItemBuffer::appendEncodedData(ItemHandle temporaryItem)
+void ItemBuffer::append(ItemHandle temporaryItem)
 {
     auto data = ""
     if (!data)
@@ -903,14 +894,21 @@
     auto dataLength = data->size();
     auto additionalCapacityForEncodedItem = 2 * sizeof(uint64_t) + roundUpToMultipleOf(alignof(uint64_t), dataLength);
 
-    swapWritableBufferIfNeeded(additionalCapacityForEncodedItem);
+    auto bufferChanged = swapWritableBufferIfNeeded(additionalCapacityForEncodedItem);
 
     m_writableBuffer.data[m_writtenNumberOfBytes] = static_cast<uint8_t>(temporaryItem.type());
     reinterpret_cast<uint64_t*>(m_writableBuffer.data + m_writtenNumberOfBytes)[1] = dataLength;
     memcpy(m_writableBuffer.data + m_writtenNumberOfBytes + 2 * sizeof(uint64_t), data->dataAsUInt8Ptr(), dataLength);
 
-    m_writtenNumberOfBytes += additionalCapacityForEncodedItem;
+    didAppendData(additionalCapacityForEncodedItem, bufferChanged);
 }
 
+void ItemBuffer::didAppendData(size_t numberOfBytes, DidChangeItemBuffer didChangeItemBuffer)
+{
+    m_writtenNumberOfBytes += numberOfBytes;
+    if (m_writingClient)
+        m_writingClient->didAppendData(m_writableBuffer, numberOfBytes, didChangeItemBuffer);
+}
+
 } // namespace DisplayList
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItemBuffer.h (270477 => 270478)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItemBuffer.h	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItemBuffer.h	2020-12-05 22:17:10 UTC (rev 270478)
@@ -83,6 +83,8 @@
     void copyTo(ItemHandle destination) const;
 };
 
+enum class DidChangeItemBuffer : bool { No, Yes };
+
 class ItemBufferWritingClient {
 public:
     virtual ~ItemBufferWritingClient() { }
@@ -89,6 +91,7 @@
 
     virtual ItemBufferHandle createItemBuffer(size_t) = 0;
     virtual RefPtr<SharedBuffer> encodeItem(ItemHandle) const = 0;
+    virtual void didAppendData(const ItemBufferHandle&, size_t numberOfBytes, DidChangeItemBuffer) = 0;
 };
 
 class ItemBufferReadingClient {
@@ -152,17 +155,17 @@
             static uint8_t temporaryItemBuffer[sizeof(uint64_t) + sizeof(T)];
             temporaryItemBuffer[0] = static_cast<uint8_t>(T::itemType);
             new (temporaryItemBuffer + sizeof(uint64_t)) T(std::forward<Args>(args)...);
-            appendEncodedData({ temporaryItemBuffer });
+            append({ temporaryItemBuffer });
             ItemHandle { temporaryItemBuffer }.destroy();
             return;
         }
 
-        swapWritableBufferIfNeeded(paddedSizeOfTypeAndItemInBytes(T::itemType));
+        auto bufferChanged = swapWritableBufferIfNeeded(paddedSizeOfTypeAndItemInBytes(T::itemType));
 
         if (!std::is_trivially_destructible<T>::value)
             m_itemsToDestroyInAllocatedBuffers.append({ &m_writableBuffer.data[m_writtenNumberOfBytes] });
 
-        uncheckedAppend<T>(std::forward<Args>(args)...);
+        uncheckedAppend<T>(bufferChanged, std::forward<Args>(args)...);
     }
 
     void setClient(ItemBufferWritingClient* client) { m_writingClient = client; }
@@ -171,15 +174,16 @@
 private:
     const ItemBufferHandles& readOnlyBuffers() const { return m_readOnlyBuffers; }
     void forEachItemBuffer(Function<void(const ItemBufferHandle&)>&&) const;
+    WEBCORE_EXPORT void didAppendData(size_t numberOfBytes, DidChangeItemBuffer);
 
-    WEBCORE_EXPORT void swapWritableBufferIfNeeded(size_t numberOfBytes);
-    WEBCORE_EXPORT void appendEncodedData(ItemHandle);
-    template<typename T, class... Args> void uncheckedAppend(Args&&... args)
+    WEBCORE_EXPORT DidChangeItemBuffer swapWritableBufferIfNeeded(size_t numberOfBytes);
+    WEBCORE_EXPORT void append(ItemHandle);
+    template<typename T, class... Args> void uncheckedAppend(DidChangeItemBuffer didChangeItemBuffer, Args&&... args)
     {
         auto* startOfItem = &m_writableBuffer.data[m_writtenNumberOfBytes];
         startOfItem[0] = static_cast<uint8_t>(T::itemType);
         new (startOfItem + sizeof(uint64_t)) T(std::forward<Args>(args)...);
-        m_writtenNumberOfBytes += paddedSizeOfTypeAndItemInBytes(T::itemType);
+        didAppendData(paddedSizeOfTypeAndItemInBytes(T::itemType), didChangeItemBuffer);
     }
 
     ItemBufferReadingClient* m_readingClient { nullptr };

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItemType.cpp (270477 => 270478)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItemType.cpp	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItemType.cpp	2020-12-05 22:17:10 UTC (rev 270478)
@@ -130,8 +130,6 @@
         return sizeof(MetaCommandChangeDestinationImageBuffer);
     case ItemType::MetaCommandChangeItemBuffer:
         return sizeof(MetaCommandChangeItemBuffer);
-    case ItemType::MetaCommandEnd:
-        return sizeof(MetaCommandEnd);
     case ItemType::PutImageData:
         return sizeof(PutImageData);
     case ItemType::PaintFrameForMedia:
@@ -186,7 +184,6 @@
     case ItemType::FlushContext:
     case ItemType::MetaCommandChangeDestinationImageBuffer:
     case ItemType::MetaCommandChangeItemBuffer:
-    case ItemType::MetaCommandEnd:
     case ItemType::Restore:
     case ItemType::Rotate:
     case ItemType::Save:
@@ -299,7 +296,6 @@
     case ItemType::FlushContext:
     case ItemType::MetaCommandChangeDestinationImageBuffer:
     case ItemType::MetaCommandChangeItemBuffer:
-    case ItemType::MetaCommandEnd:
     case ItemType::PaintFrameForMedia:
     case ItemType::Restore:
     case ItemType::Rotate:

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItemType.h (270477 => 270478)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItemType.h	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItemType.h	2020-12-05 22:17:10 UTC (rev 270478)
@@ -76,7 +76,6 @@
     FillPath,
     FillEllipse,
     FlushContext,
-    MetaCommandEnd,
     MetaCommandChangeDestinationImageBuffer,
     MetaCommandChangeItemBuffer,
     PutImageData,

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItems.cpp (270477 => 270478)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItems.cpp	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItems.cpp	2020-12-05 22:17:10 UTC (rev 270478)
@@ -1014,11 +1014,6 @@
     return ts;
 }
 
-static TextStream& operator<<(TextStream& ts, const MetaCommandEnd&)
-{
-    return ts;
-}
-
 static TextStream& operator<<(TextStream& ts, ItemType type)
 {
     switch (type) {
@@ -1070,7 +1065,6 @@
     case ItemType::FlushContext: ts << "flush-context"; break;
     case ItemType::MetaCommandChangeDestinationImageBuffer: ts << "meta-command-change-destination-image-buffer"; break;
     case ItemType::MetaCommandChangeItemBuffer: ts << "meta-command-change-item-buffer"; break;
-    case ItemType::MetaCommandEnd: ts << "meta-command-end"; break;
     case ItemType::PutImageData: ts << "put-image-data"; break;
     case ItemType::PaintFrameForMedia: ts << "paint-frame-for-media"; break;
     case ItemType::StrokeRect: ts << "stroke-rect"; break;
@@ -1232,9 +1226,6 @@
     case ItemType::MetaCommandChangeItemBuffer:
         ts << item.get<MetaCommandChangeItemBuffer>();
         break;
-    case ItemType::MetaCommandEnd:
-        ts << item.get<MetaCommandEnd>();
-        break;
     case ItemType::PutImageData:
         ts << item.get<PutImageData>();
         break;

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItems.h (270477 => 270478)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItems.h	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListItems.h	2020-12-05 22:17:10 UTC (rev 270478)
@@ -2250,13 +2250,6 @@
     ItemBufferIdentifier m_identifier;
 };
 
-class MetaCommandEnd {
-public:
-    static constexpr ItemType itemType = ItemType::MetaCommandEnd;
-    static constexpr bool isInlineItem = true;
-    static constexpr bool isDrawingItem = false;
-};
-
 class MetaCommandChangeDestinationImageBuffer {
 public:
     static constexpr ItemType itemType = ItemType::MetaCommandChangeDestinationImageBuffer;
@@ -2331,7 +2324,6 @@
     WebCore::DisplayList::ItemType::FillPath,
     WebCore::DisplayList::ItemType::FillEllipse,
     WebCore::DisplayList::ItemType::FlushContext,
-    WebCore::DisplayList::ItemType::MetaCommandEnd,
     WebCore::DisplayList::ItemType::MetaCommandChangeDestinationImageBuffer,
     WebCore::DisplayList::ItemType::MetaCommandChangeItemBuffer,
     WebCore::DisplayList::ItemType::PutImageData,

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.h (270477 => 270478)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.h	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.h	2020-12-05 22:17:10 UTC (rev 270478)
@@ -69,6 +69,8 @@
         virtual void cacheNativeImage(NativeImage&) { }
     };
 
+    void flushContext(FlushIdentifier identifier) { append<FlushContext>(identifier); }
+
 private:
     friend class DrawGlyphsRecorder;
     bool hasPlatformContext() const override { return false; }
@@ -164,8 +166,8 @@
         }
     }
 
-    void willAppendItemOfType(ItemType);
-    void didAppendItemOfType(ItemType);
+    WEBCORE_EXPORT void willAppendItemOfType(ItemType);
+    WEBCORE_EXPORT void didAppendItemOfType(ItemType);
 
     void appendStateChangeItem(const GraphicsContextStateChange&, GraphicsContextState::StateChangeFlags);
 

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListReplayer.cpp (270477 => 270478)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListReplayer.cpp	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListReplayer.cpp	2020-12-05 22:17:10 UTC (rev 270478)
@@ -117,12 +117,6 @@
             break;
         }
 
-        if (item.is<MetaCommandEnd>()) {
-            result.numberOfBytesRead += itemSizeInBuffer;
-            result.reasonForStopping = StopReplayReason::EndOfDisplayList;
-            break;
-        }
-
         if (auto reasonForStopping = applyItem(item)) {
             result.reasonForStopping = *reasonForStopping;
             break;

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListReplayer.h (270477 => 270478)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListReplayer.h	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListReplayer.h	2020-12-05 22:17:10 UTC (rev 270478)
@@ -42,7 +42,6 @@
     ReplayedAllItems,
     MissingCachedResource,
     ChangeDestinationImageBuffer,
-    EndOfDisplayList,
     DecodingFailure // FIXME: Propagate decoding errors to display list replay clients through this enum as well.
 };
 

Modified: trunk/Source/WebKit/ChangeLog (270477 => 270478)


--- trunk/Source/WebKit/ChangeLog	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebKit/ChangeLog	2020-12-05 22:17:10 UTC (rev 270478)
@@ -1,3 +1,168 @@
+2020-12-04  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [Concurrent display lists] Synchronize display list rendering across remote image buffers
+        https://bugs.webkit.org/show_bug.cgi?id=219091
+        <rdar://problem/71747695>
+
+        Reviewed by Geoff Garen.
+
+        Refactors the existing concurrent display list processing mechanism, such that we no longer update the unread
+        bytes count every 512 items (or when flushing the drawing context), and instead update it every time we append
+        display list item data. In order to achieve this without making it impossible for multiple display-list backed
+        image buffers to render simultaneously, we also add support for synchronizing display list items across
+        different image buffers by using the new meta command items added in bug #219262. As detailed in the ChangeLog
+        for that bug, a stream of display list data written by the web process and consumed by the GPU process is now
+        structured like so:
+
+        Wakeup message initiates display list processing with Image Buffer A and Item Buffer 1
+            |
+            |   MetaCommandChangeDestinationImageBuffer(B)
+            |                       |
+            |                       |                  MetaCommandChangeItemBuffer(2)
+            |                       |                                |
+            |                       |                                |
+            v                       v                                v
+            +-----------------------+--------------------------------++
+            | +--------------------+ +------------------------------+ |
+            | | Destination        | | Destination                  | | Item Buffer 1
+            | | Image Buffer A     | | Image Buffer B               | |
+            | +--------------------+ +------------------------------+ |
+            +---------------------------------------------------------+
+
+            +---------------------------------------------------------+
+            | +--------------+ +-----------------------+              |
+            | | Dst. Image   | | Destination Image     |  Unused      | Item Buffer 2
+            | | Buffer B     | | Buffer A              |  Capacity    |
+            | +--------------+ +-----------------------+              |
+            +-----------------+-------------------------+-------------+
+                              ^
+                              |
+                              |
+            MetaCommandChangeDestinationImageBuffer(A)
+
+        (Note that the `MetaCommandEnd` item has been omitted, since we no longer need to explicitly tell the GPU
+        process to go to sleep with the latest iteration of this patch).
+
+        In order to write display list data conforming to this format, we add a mechanism to the web process that keeps
+        track of the "current destination image buffer" (i.e. the image buffer that has most recently
+        appended a display list item). Right before this destination is about to change, we append a new
+        `MetaCommandChangeDestinationImageBuffer` item before proceeding to append display list items for the new
+        current destination.
+
+        Since we now bump the unread count every time, we need to do some additional work to avoid an excessive number
+        of wakeups and sleeps in the GPU process, which would otherwise cause a massive regression. To do this, we
+        introduce an item count hysteresis in the web process, such that we will wait for 512 items to be written before
+        attempting to send the wakeup message. This allows the web process to get a small head start over the GPU
+        process, and thus allows the GPU process to be more consistently busy over the course of a single frame.
+
+        On the reader (GPU process) side, we make some minor adjustments so that the main display list processing loop
+        of the GPU process is capable of changing destination image buffers while processing a stream of display list
+        items.
+
+        See below for more details.
+
+        * GPUProcess/graphics/DisplayListReaderHandle.cpp:
+        (WebKit::DisplayListReaderHandle::advance):
+
+        Update `advance` so that it just performs a single 8-byte atomic `exchangeSub` rather than grabbing a spinlock.
+
+        * GPUProcess/graphics/RemoteRenderingBackend.cpp:
+        (WebKit::RemoteRenderingBackend::submit):
+        (WebKit::RemoteRenderingBackend::nextDestinationImageBufferAfterApplyingDisplayLists):
+
+        Rename `applyDisplayListsFromHandle` to `nextDestinationImageBufferAfterApplyingDisplayLists`, and make it
+        return the current image buffer to use as the destination for replaying display list commands. This helper is
+        still responsible for replaying a display list item buffer until it has no more data (that is, until we
+        encounter a `MetaCommandChangeItemBuffer` item informing us of the next item buffer to consume).
+
+        (WebKit::RemoteRenderingBackend::wakeUpAndApplyDisplayList):
+
+        Adjust this to call `nextDestinationImageBufferAfterApplyingDisplayLists`.
+
+        (WebKit::RemoteRenderingBackend::decodeItem):
+        (WebKit::RemoteRenderingBackend::applyDisplayListsFromHandle): Deleted.
+        * GPUProcess/graphics/RemoteRenderingBackend.h:
+        * Shared/SharedDisplayListHandle.h:
+
+        Remove `SharedDisplayListHandle::Lock` altogether, now that we just have a single atomic `uint64_t` counter to
+        represent the number of unread bytes.
+
+        (WebKit::SharedDisplayListHandle::unreadBytes):
+        (WebKit::SharedDisplayListHandle::Lock::Lock): Deleted.
+        (WebKit::SharedDisplayListHandle::Lock::~Lock): Deleted.
+        * WebProcess/GPU/graphics/DisplayListWriterHandle.cpp:
+        (WebKit::DisplayListWriterHandle::advance):
+
+        Make this use the single atomic counter, instead of grabbing a spinlock.
+
+        (WebKit::DisplayListWriterHandle::moveWritableOffsetToStartIfPossible):
+        (WebKit::DisplayListWriterHandle::resetWritableOffsetIfPossible): Deleted.
+
+        Rename `resetWritableOffsetIfPossible` to the more accurate `moveWritableOffsetToStartIfPossible`.
+
+        * WebProcess/GPU/graphics/DisplayListWriterHandle.h:
+        * WebProcess/GPU/graphics/RemoteImageBufferProxy.h:
+        (WebKit::RemoteImageBufferProxy::changeDestinationImageBuffer):
+
+        Add a helper method to append a `MetaCommandChangeDestinationImageBuffer` item to the display list, given the
+        identifier of this next item buffer.
+
+        (WebKit::RemoteImageBufferProxy::clearDisplayList):
+
+        Add a helper method to clear the display list, such that the `RemoteImageBufferProxy` will be asked for a new
+        buffer handle the next time we append an item.
+
+        (WebKit::RemoteImageBufferProxy::waitForDidFlushWithTimeout):
+
+        Make this hit the maximum `waitForAndDispatchImmediately` attempt count and "fail" only if the call to
+        `waitForAndDispatchImmediately` actually times out. This change is necessary to ensure that the scenario of
+        multiple image buffers simultaneously appending display list items works when all image buffers perform (non-
+        blocking) flushes simultaneously, followed by a sync-wait (blocking) flush. In this situation, the web process
+        may receive more than three `DidFlush` messages in rapid succession, causing it to hit this maximum limit of 3
+        instantly and avoid waiting for the expected `DidFlush` message to arrive.
+
+        (WebKit::RemoteImageBufferProxy::submitDisplayList): Deleted.
+        * WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp:
+        (WebKit::RemoteRenderingBackendProxy::gpuProcessConnectionDidClose):
+
+        Reset state when the GPU process is terminated.
+
+        (WebKit::RemoteRenderingBackendProxy::willAppendItem):
+
+        Update the current destination image buffer (`m_currentDestinationImageBufferIdentifier`). If this identifier
+        changed, then we append a `MetaCommandChangeDestinationImageBuffer` item to the previous destination before
+        setting the new destination image buffer. We also need to clear the new destination image buffer's display list
+        before writing new items, to prevent it from overwriting shared display list item data.
+
+        (WebKit::RemoteRenderingBackendProxy::sendWakeupMessage):
+        (WebKit::RemoteRenderingBackendProxy::sendDeferredWakeupMessageIfNeeded):
+        (WebKit::RemoteRenderingBackendProxy::didAppendData):
+
+        Implement a new `ItemBufferWritingClient` hook by advancing the corresponding item buffer's unread count.
+        Additionally, schedule a wakeup message in the case where the unread count was zero when we advanced, and the
+        item buffer we've appended to is not "connected" to a previous item buffer by way of an item buffer change item.
+
+        Additionally, in the case where we don't schedule a new wakeup message, check whether or not there is a deferred
+        wakeup message; if there is, then decrement the remaining item count before we send the wakeup message, and send
+        the message if the count reaches 0.
+
+        (WebKit::RemoteRenderingBackendProxy::findReusableDisplayListHandle):
+
+        Pull logic to find a shared display list handle suitable for reuse into a separate helper method, and adjust it
+        so that if the most recently used display list handle has run out of available capacity, we move it to the end
+        of the reuse queue and only reuse the new first shared handle in the queue if its writable offset can be reset.
+        This ensures that the GPU process can always continue reading display list item data from the start of new item
+        buffers -- i.e., we don't end up with the web process writing out a stream of display list data like:
+
+           (Start) Bytes (16, 65520) in ItemBuffer[1]
+                   Bytes (16, 65536) in ItemBuffer[2]
+                   Bytes (65520, 65536) in ItemBuffer[1]
+
+        (WebKit::RemoteRenderingBackendProxy::createItemBuffer):
+        (WebKit::RemoteRenderingBackendProxy::submitDisplayList): Deleted.
+        (WebKit::RemoteRenderingBackendProxy::updateReusableHandles): Deleted.
+        * WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h:
+
 2020-12-05  Fujii Hironori  <hironori.fu...@sony.com>
 
         Remove ENABLE_GRAPHICS_CONTEXT_GL by replacing it with ENABLE(WEBGL)

Modified: trunk/Source/WebKit/GPUProcess/graphics/DisplayListReaderHandle.cpp (270477 => 270478)


--- trunk/Source/WebKit/GPUProcess/graphics/DisplayListReaderHandle.cpp	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebKit/GPUProcess/graphics/DisplayListReaderHandle.cpp	2020-12-05 22:17:10 UTC (rev 270478)
@@ -31,14 +31,13 @@
 
 size_t DisplayListReaderHandle::advance(size_t amount)
 {
-    auto locker = SharedDisplayListHandle::Lock { *this };
-    if (LIKELY(amount <= header().unreadBytes))
-        return header().unreadBytes -= amount;
-
-    // FIXME: This should result in terminating the web process.
-    ASSERT_NOT_REACHED();
-    header().unreadBytes = 0;
-    return 0;
+    auto previousUnreadBytes = header().unreadBytes.exchangeSub(amount);
+    if (UNLIKELY(previousUnreadBytes < amount)) {
+        // FIXME: This should result in terminating the web process.
+        RELEASE_ASSERT_NOT_REACHED();
+        return 0;
+    }
+    return previousUnreadBytes - amount;
 }
 
 std::unique_ptr<DisplayList::DisplayList> DisplayListReaderHandle::displayListForReading(size_t offset, size_t capacity, DisplayList::ItemBufferReadingClient& client) const

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteImageBuffer.h (270477 => 270478)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteImageBuffer.h	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteImageBuffer.h	2020-12-05 22:17:10 UTC (rev 270478)
@@ -90,17 +90,6 @@
         return m_remoteRenderingBackend.applyMediaItem(item, context);
     }
 
-    void submitDisplayList(const WebCore::DisplayList::DisplayList& displayList) override
-    {
-        if (displayList.isEmpty())
-            return;
-
-        const auto& imageBuffers = m_remoteRenderingBackend.remoteResourceCache().imageBuffers();
-        const auto& nativeImages = m_remoteRenderingBackend.remoteResourceCache().nativeImages();
-        WebCore::DisplayList::Replayer replayer { BaseConcreteImageBuffer::context(), displayList, &imageBuffers, &nativeImages, this };
-        replayer.replay();
-    }
-
     RemoteRenderingBackend& m_remoteRenderingBackend;
     WebCore::RenderingResourceIdentifier m_renderingResourceIdentifier;
 };

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp (270477 => 270478)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp	2020-12-05 22:17:10 UTC (rev 270478)
@@ -129,33 +129,54 @@
     m_remoteResourceCache.cacheImageBuffer(makeRef(*imageBuffer));
 }
 
-void RemoteRenderingBackend::applyDisplayListsFromHandle(ImageBuffer& destination, DisplayListReaderHandle& handle, size_t initialOffset)
+DisplayList::ReplayResult RemoteRenderingBackend::submit(const DisplayList::DisplayList& displayList, ImageBuffer& destination)
 {
+    if (displayList.isEmpty())
+        return { };
+
+    DisplayList::Replayer::Delegate* replayerDelegate = nullptr;
+    if (destination.renderingMode() == RenderingMode::Accelerated)
+        replayerDelegate = static_cast<AcceleratedRemoteImageBuffer*>(&destination);
+    else
+        replayerDelegate = static_cast<UnacceleratedRemoteImageBuffer*>(&destination);
+
+    return WebCore::DisplayList::Replayer {
+        destination.context(),
+        displayList,
+        &remoteResourceCache().imageBuffers(),
+        &remoteResourceCache().nativeImages(),
+        replayerDelegate
+    }.replay();
+}
+
+RefPtr<ImageBuffer> RemoteRenderingBackend::nextDestinationImageBufferAfterApplyingDisplayLists(ImageBuffer& initialDestination, size_t initialOffset, DisplayListReaderHandle& handle)
+{
+    auto destination = makeRefPtr(initialDestination);
     auto handleProtector = makeRef(handle);
 
-    size_t offset = initialOffset;
+    auto offset = initialOffset;
     size_t sizeToRead = 0;
-
     do {
         sizeToRead = handle.unreadBytes();
     } while (!sizeToRead);
 
-    while (sizeToRead) {
+    while (destination && !m_nextItemBufferToRead) {
         auto displayList = handle.displayListForReading(offset, sizeToRead, *this);
         if (UNLIKELY(!displayList)) {
             // FIXME: Add a message check to terminate the web process.
             ASSERT_NOT_REACHED();
-            return;
+            break;
         }
 
-        destination.submitDisplayList(*displayList);
+        auto result = submit(*displayList, *destination);
+        sizeToRead = handle.advance(result.numberOfBytesRead);
 
         CheckedSize checkedOffset = offset;
-        checkedOffset += sizeToRead;
+        checkedOffset += result.numberOfBytesRead;
         if (UNLIKELY(checkedOffset.hasOverflowed())) {
             // FIXME: Add a message check to terminate the web process.
             ASSERT_NOT_REACHED();
-            return;
+            break;
         }
 
         offset = checkedOffset.unsafeGet();
@@ -163,18 +184,24 @@
         if (UNLIKELY(offset > handle.sharedMemory().size())) {
             // FIXME: Add a message check to terminate the web process.
             ASSERT_NOT_REACHED();
-            return;
+            break;
         }
 
-        sizeToRead = handle.advance(sizeToRead);
+        if (result.reasonForStopping == DisplayList::StopReplayReason::ChangeDestinationImageBuffer)
+            destination = makeRefPtr(m_remoteResourceCache.cachedImageBuffer(*result.nextDestinationImageBuffer));
+
+        if (!sizeToRead)
+            break;
     }
+
+    return destination;
 }
 
 void RemoteRenderingBackend::wakeUpAndApplyDisplayList(DisplayList::ItemBufferIdentifier initialIdentifier, uint64_t initialOffset, RenderingResourceIdentifier destinationBufferIdentifier)
 {
     TraceScope tracingScope(WakeUpAndApplyDisplayListStart, WakeUpAndApplyDisplayListEnd);
-    auto imageBuffer = m_remoteResourceCache.cachedImageBuffer(destinationBufferIdentifier);
-    if (UNLIKELY(!imageBuffer)) {
+    auto destinationImageBuffer = makeRefPtr(m_remoteResourceCache.cachedImageBuffer(destinationBufferIdentifier));
+    if (UNLIKELY(!destinationImageBuffer)) {
         // FIXME: Add a message check to terminate the web process.
         ASSERT_NOT_REACHED();
         return;
@@ -187,8 +214,13 @@
         return;
     }
 
-    applyDisplayListsFromHandle(*imageBuffer, *initialHandle, initialOffset);
+    destinationImageBuffer = nextDestinationImageBufferAfterApplyingDisplayLists(*destinationImageBuffer, initialOffset, *initialHandle);
 
+    if (!destinationImageBuffer) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
     while (m_nextItemBufferToRead) {
         auto nextHandle = m_sharedDisplayListHandles.get(m_nextItemBufferToRead);
         if (!nextHandle) {
@@ -196,9 +228,15 @@
             // IPC message with a shared memory handle to the next item buffer.
             break;
         }
+
         // Otherwise, continue reading the next display list item buffer from the start.
         m_nextItemBufferToRead = { };
-        applyDisplayListsFromHandle(*imageBuffer, *nextHandle, SharedDisplayListHandle::headerSize());
+        destinationImageBuffer = nextDestinationImageBufferAfterApplyingDisplayLists(*destinationImageBuffer, SharedDisplayListHandle::headerSize(), *nextHandle);
+
+        if (!destinationImageBuffer) {
+            ASSERT_NOT_REACHED();
+            return;
+        }
     }
 }
 
@@ -317,7 +355,6 @@
     case DisplayList::ItemType::FlushContext:
     case DisplayList::ItemType::MetaCommandChangeDestinationImageBuffer:
     case DisplayList::ItemType::MetaCommandChangeItemBuffer:
-    case DisplayList::ItemType::MetaCommandEnd:
     case DisplayList::ItemType::PaintFrameForMedia:
     case DisplayList::ItemType::Restore:
     case DisplayList::ItemType::Rotate:

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.h (270477 => 270478)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.h	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.h	2020-12-05 22:17:10 UTC (rev 270478)
@@ -37,6 +37,7 @@
 #include <WebCore/ColorSpace.h>
 #include <WebCore/DisplayList.h>
 #include <WebCore/DisplayListItems.h>
+#include <WebCore/DisplayListReplayer.h>
 #include <wtf/WeakPtr.h>
 
 namespace WebCore {
@@ -92,7 +93,8 @@
         return WTF::nullopt;
     }
 
-    void applyDisplayListsFromHandle(WebCore::ImageBuffer& destination, DisplayListReaderHandle&, size_t offset);
+    WebCore::DisplayList::ReplayResult submit(const WebCore::DisplayList::DisplayList&, WebCore::ImageBuffer& destination);
+    RefPtr<WebCore::ImageBuffer> nextDestinationImageBufferAfterApplyingDisplayLists(WebCore::ImageBuffer& initialDestination, size_t initialOffset, DisplayListReaderHandle&);
 
     // IPC::MessageSender.
     IPC::Connection* messageSenderConnection() const override;

Modified: trunk/Source/WebKit/Shared/SharedDisplayListHandle.h (270477 => 270478)


--- trunk/Source/WebKit/Shared/SharedDisplayListHandle.h	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebKit/Shared/SharedDisplayListHandle.h	2020-12-05 22:17:10 UTC (rev 270478)
@@ -50,38 +50,12 @@
 
     uint64_t unreadBytes()
     {
-        auto locker = SharedDisplayListHandle::Lock { *this };
-        return header().unreadBytes;
+        return header().unreadBytes.load();
     }
 
     virtual size_t advance(size_t amount) = 0;
 
 protected:
-    class Lock {
-    public:
-        Lock(SharedDisplayListHandle& handle)
-            : m_handle(handle)
-        {
-            auto& atomicValue = m_handle.header().lock;
-            while (true) {
-                // FIXME: We need to avoid waiting forever in the case where the web content process
-                // holds on to the lock indefinitely (or crashes while holding the lock).
-                uint64_t unlocked = 0;
-                if (atomicValue.compareExchangeWeak(unlocked, 1))
-                    break;
-                Thread::yield();
-            }
-        }
-
-        ~Lock()
-        {
-            m_handle.header().lock.store(0);
-        }
-
-    private:
-        SharedDisplayListHandle& m_handle;
-    };
-
     SharedDisplayListHandle(WebCore::DisplayList::ItemBufferIdentifier identifier, Ref<SharedMemory>&& sharedMemory)
         : m_identifier(identifier)
         , m_sharedMemory(WTFMove(sharedMemory))
@@ -89,8 +63,7 @@
     }
 
     struct DisplayListSharedMemoryHeader {
-        Atomic<uint64_t> lock;
-        uint64_t unreadBytes;
+        Atomic<uint64_t> unreadBytes;
     };
 
     DisplayListSharedMemoryHeader& header() { return *reinterpret_cast<DisplayListSharedMemoryHeader*>(data()); }

Modified: trunk/Source/WebKit/WebProcess/GPU/graphics/DisplayListWriterHandle.cpp (270477 => 270478)


--- trunk/Source/WebKit/WebProcess/GPU/graphics/DisplayListWriterHandle.cpp	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebKit/WebProcess/GPU/graphics/DisplayListWriterHandle.cpp	2020-12-05 22:17:10 UTC (rev 270478)
@@ -33,20 +33,8 @@
 
 size_t DisplayListWriterHandle::advance(size_t amount)
 {
-    CheckedSize checkedWritableOffset = m_writableOffset;
-    checkedWritableOffset += amount;
-    if (UNLIKELY(checkedWritableOffset.hasOverflowed()))
-        RELEASE_ASSERT_NOT_REACHED();
-
-    auto locker = SharedDisplayListHandle::Lock { *this };
-    CheckedSize checkedUnreadBytes = header().unreadBytes;
-    checkedUnreadBytes += amount;
-    if (UNLIKELY(checkedUnreadBytes.hasOverflowed()))
-        RELEASE_ASSERT_NOT_REACHED();
-
-    m_writableOffset = checkedWritableOffset.unsafeGet();
-    header().unreadBytes = checkedUnreadBytes.unsafeGet();
-    return checkedUnreadBytes.unsafeGet();
+    m_writableOffset = (CheckedSize { m_writableOffset } + amount).unsafeGet();
+    return (CheckedSize { header().unreadBytes.exchangeAdd(amount) } + amount).unsafeGet();
 }
 
 size_t DisplayListWriterHandle::availableCapacity() const
@@ -66,7 +54,7 @@
     };
 }
 
-bool DisplayListWriterHandle::resetWritableOffsetIfPossible()
+bool DisplayListWriterHandle::moveWritableOffsetToStartIfPossible()
 {
     if (m_writableOffset <= SharedDisplayListHandle::headerSize()) {
         RELEASE_ASSERT(m_writableOffset == SharedDisplayListHandle::headerSize());

Modified: trunk/Source/WebKit/WebProcess/GPU/graphics/DisplayListWriterHandle.h (270477 => 270478)


--- trunk/Source/WebKit/WebProcess/GPU/graphics/DisplayListWriterHandle.h	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebKit/WebProcess/GPU/graphics/DisplayListWriterHandle.h	2020-12-05 22:17:10 UTC (rev 270478)
@@ -41,7 +41,7 @@
     size_t writableOffset() const { return m_writableOffset; }
     size_t availableCapacity() const;
 
-    bool resetWritableOffsetIfPossible();
+    bool moveWritableOffsetToStartIfPossible();
 
     size_t advance(size_t amount) override;
     WebCore::DisplayList::ItemBufferHandle createHandle() const;

Modified: trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteImageBufferProxy.h (270477 => 270478)


--- trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteImageBufferProxy.h	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteImageBufferProxy.h	2020-12-05 22:17:10 UTC (rev 270478)
@@ -119,9 +119,12 @@
             return;
 
         // Wait for our DisplayList to be flushed but do not hang.
-        static constexpr unsigned maxWaitingFlush = 3;
-        for (unsigned numWaitingFlush = 0; numWaitingFlush < maxWaitingFlush && hasPendingFlush(); ++numWaitingFlush)
-            m_remoteRenderingBackendProxy->waitForDidFlush();
+        static constexpr unsigned maximumNumberOfTimeouts = 3;
+        unsigned numberOfTimeouts = 0;
+        while (numberOfTimeouts < maximumNumberOfTimeouts && hasPendingFlush()) {
+            if (!m_remoteRenderingBackendProxy->waitForDidFlush())
+                ++numberOfTimeouts;
+        }
     }
 
     BackendType* ensureBackendCreated() const override
@@ -133,18 +136,10 @@
 
     RefPtr<WebCore::ImageData> getImageData(WebCore::AlphaPremultiplication outputFormat, const WebCore::IntRect& srcRect) const override
     {
-        if (!m_remoteRenderingBackendProxy)
+        if (UNLIKELY(!m_remoteRenderingBackendProxy))
             return nullptr;
 
-        auto& mutableThis = const_cast<RemoteImageBufferProxy&>(*this);
-        auto& displayList = mutableThis.m_drawingContext.displayList();
-        if (!displayList.isEmpty()) {
-            mutableThis.submitDisplayList(displayList);
-            mutableThis.m_itemCountInCurrentDisplayList = 0;
-            displayList.clear();
-        }
-
-        // getImageData is synchronous, which means we've already received the CommitImageBufferFlushContext message.
+        m_remoteRenderingBackendProxy->sendDeferredWakeupMessageIfNeeded();
         return m_remoteRenderingBackendProxy->getImageData(outputFormat, srcRect, m_renderingResourceIdentifier);
     }
 
@@ -166,6 +161,9 @@
 
     void flushDrawingContext() override
     {
+        if (UNLIKELY(!m_remoteRenderingBackendProxy))
+            return;
+
         TraceScope tracingScope(FlushRemoteImageBufferStart, FlushRemoteImageBufferEnd);
         flushDrawingContextAndCommit();
         waitForDidFlushWithTimeout();
@@ -173,49 +171,58 @@
 
     void flushDrawingContextAndCommit() override
     {
-        if (!m_remoteRenderingBackendProxy)
+        if (UNLIKELY(!m_remoteRenderingBackendProxy))
             return;
 
-        auto& displayList = m_drawingContext.displayList();
-        if (displayList.isEmpty())
-            return;
+        if (!m_drawingContext.displayList().isEmpty()) {
+            m_sentFlushIdentifier = WebCore::DisplayList::FlushIdentifier::generate();
+            m_drawingContext.recorder().flushContext(m_sentFlushIdentifier);
+        }
 
-        m_sentFlushIdentifier = WebCore::DisplayList::FlushIdentifier::generate();
-        displayList.template append<WebCore::DisplayList::FlushContext>(m_sentFlushIdentifier);
-        submitDisplayList(displayList);
-        displayList.clear();
-        m_itemCountInCurrentDisplayList = 0;
+        m_remoteRenderingBackendProxy->sendDeferredWakeupMessageIfNeeded();
+        clearDisplayList();
     }
 
-    void submitDisplayList(const WebCore::DisplayList::DisplayList& displayList) override
+    void cacheNativeImage(WebCore::NativeImage& image) override
     {
-        if (!m_remoteRenderingBackendProxy || displayList.isEmpty())
-            return;
+        if (m_remoteRenderingBackendProxy)
+            m_remoteRenderingBackendProxy->remoteResourceCacheProxy().cacheNativeImage(image);
+    }
 
-        m_remoteRenderingBackendProxy->submitDisplayList(displayList, m_renderingResourceIdentifier);
+    void changeDestinationImageBuffer(WebCore::RenderingResourceIdentifier nextImageBuffer) final
+    {
+        bool wasEmpty = m_drawingContext.displayList().isEmpty();
+        m_drawingContext.displayList().template append<WebCore::DisplayList::MetaCommandChangeDestinationImageBuffer>(nextImageBuffer);
+        if (wasEmpty)
+            clearDisplayList();
     }
 
+    void clearDisplayList() final
+    {
+        m_drawingContext.displayList().clear();
+    }
+
     void willAppendItemOfType(WebCore::DisplayList::ItemType) override
     {
-        constexpr size_t DisplayListBatchSize = 512;
-        auto& displayList = m_drawingContext.displayList();
-        if (++m_itemCountInCurrentDisplayList < DisplayListBatchSize)
-            return;
+        if (LIKELY(m_remoteRenderingBackendProxy))
+            m_remoteRenderingBackendProxy->willAppendItem(m_renderingResourceIdentifier);
+    }
 
-        m_itemCountInCurrentDisplayList = 0;
-        submitDisplayList(displayList);
-        displayList.clear();
+    void didAppendData(const WebCore::DisplayList::ItemBufferHandle& handle, size_t numberOfBytes, WebCore::DisplayList::DidChangeItemBuffer didChangeItemBuffer) override
+    {
+        if (LIKELY(m_remoteRenderingBackendProxy))
+            m_remoteRenderingBackendProxy->didAppendData(handle, numberOfBytes, didChangeItemBuffer, m_renderingResourceIdentifier);
     }
 
-    void cacheNativeImage(WebCore::NativeImage& image) override
+    void didAppendItemOfType(WebCore::DisplayList::ItemType type) override
     {
-        if (m_remoteRenderingBackendProxy)
-            m_remoteRenderingBackendProxy->remoteResourceCacheProxy().cacheNativeImage(image);
+        if (type == WebCore::DisplayList::ItemType::DrawImageBuffer)
+            flushDrawingContext();
     }
 
     WebCore::DisplayList::ItemBufferHandle createItemBuffer(size_t capacity) override
     {
-        if (m_remoteRenderingBackendProxy)
+        if (LIKELY(m_remoteRenderingBackendProxy))
             return m_remoteRenderingBackendProxy->createItemBuffer(capacity, m_renderingResourceIdentifier);
 
         ASSERT_NOT_REACHED();
@@ -289,7 +296,6 @@
         case WebCore::DisplayList::ItemType::FlushContext:
         case WebCore::DisplayList::ItemType::MetaCommandChangeDestinationImageBuffer:
         case WebCore::DisplayList::ItemType::MetaCommandChangeItemBuffer:
-        case WebCore::DisplayList::ItemType::MetaCommandEnd:
         case WebCore::DisplayList::ItemType::PaintFrameForMedia:
         case WebCore::DisplayList::ItemType::Restore:
         case WebCore::DisplayList::ItemType::Rotate:
@@ -318,12 +324,6 @@
         }
     }
 
-    void didAppendItemOfType(WebCore::DisplayList::ItemType type) override
-    {
-        if (type == WebCore::DisplayList::ItemType::DrawImageBuffer)
-            flushDrawingContext();
-    }
-
     std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher> createFlusher() override
     {
         return WTF::makeUnique<ThreadSafeRemoteImageBufferFlusher<BackendType>>(*this);

Modified: trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp (270477 => 270478)


--- trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp	2020-12-05 22:17:10 UTC (rev 270478)
@@ -87,8 +87,10 @@
     previousConnection.removeClient(*this);
 
     m_identifiersOfReusableHandles.clear();
-    m_identifiersOfHandlesAvailableForWriting.clear();
     m_sharedDisplayListHandles.clear();
+    m_currentDestinationImageBufferIdentifier = WTF::nullopt;
+    m_deferredWakeupMessageArguments = WTF::nullopt;
+    m_remainingItemsToAppendBeforeSendingWakeup = 0;
 
     reestablishGPUProcessConnection();
 }
@@ -147,30 +149,6 @@
     return imageDataReference.buffer();
 }
 
-void RemoteRenderingBackendProxy::submitDisplayList(const DisplayList::DisplayList& displayList, RenderingResourceIdentifier destinationBufferIdentifier)
-{
-    Optional<std::pair<DisplayList::ItemBufferIdentifier, size_t>> identifierAndOffsetForWakeUpMessage;
-    bool isFirstHandle = true;
-
-    displayList.forEachItemBuffer([&] (auto& handle) {
-        m_identifiersOfHandlesAvailableForWriting.add(handle.identifier);
-
-        auto* sharedHandle = m_sharedDisplayListHandles.get(handle.identifier);
-        RELEASE_ASSERT_WITH_MESSAGE(sharedHandle, "%s failed to find shared display list", WTF_PRETTY_FUNCTION);
-
-        bool unreadCountWasEmpty = sharedHandle->advance(handle.capacity) == handle.capacity;
-        if (isFirstHandle && unreadCountWasEmpty)
-            identifierAndOffsetForWakeUpMessage = {{ handle.identifier, handle.data - sharedHandle->data() }};
-
-        isFirstHandle = false;
-    });
-
-    if (identifierAndOffsetForWakeUpMessage) {
-        auto [identifier, offset] = *identifierAndOffsetForWakeUpMessage;
-        send(Messages::RemoteRenderingBackend::WakeUpAndApplyDisplayList(identifier, offset, destinationBufferIdentifier), m_renderingBackendIdentifier);
-    }
-}
-
 void RemoteRenderingBackendProxy::cacheNativeImage(const ShareableBitmap::Handle& handle, RenderingResourceIdentifier renderingResourceIdentifier)
 {
     send(Messages::RemoteRenderingBackend::CacheNativeImage(handle, renderingResourceIdentifier), m_renderingBackendIdentifier);
@@ -201,37 +179,93 @@
         imageBuffer->didFlush(flushIdentifier);
 }
 
-void RemoteRenderingBackendProxy::updateReusableHandles()
+void RemoteRenderingBackendProxy::willAppendItem(RenderingResourceIdentifier newDestinationIdentifier)
 {
-    for (auto identifier : m_identifiersOfHandlesAvailableForWriting) {
-        auto* handle = m_sharedDisplayListHandles.get(identifier);
-        if (!handle->resetWritableOffsetIfPossible())
-            continue;
+    if (m_currentDestinationImageBufferIdentifier == newDestinationIdentifier)
+        return;
 
-        if (m_identifiersOfReusableHandles.contains(identifier))
-            continue;
+    if (auto previousDestinationBufferIdentifier = std::exchange(m_currentDestinationImageBufferIdentifier, newDestinationIdentifier)) {
+        if (auto imageBuffer = m_remoteResourceCacheProxy.cachedImageBuffer(*previousDestinationBufferIdentifier))
+            imageBuffer->changeDestinationImageBuffer(newDestinationIdentifier);
+        else
+            ASSERT_NOT_REACHED();
+    }
 
-        m_identifiersOfReusableHandles.append(identifier);
+    if (auto imageBuffer = m_remoteResourceCacheProxy.cachedImageBuffer(newDestinationIdentifier))
+        imageBuffer->clearDisplayList();
+}
+
+void RemoteRenderingBackendProxy::sendWakeupMessage(const WakeupMessageArguments& arguments)
+{
+    send(Messages::RemoteRenderingBackend::WakeUpAndApplyDisplayList(arguments.itemBufferIdentifier, arguments.initialOffset, arguments.imageBufferIdentifier), m_renderingBackendIdentifier);
+}
+
+void RemoteRenderingBackendProxy::sendDeferredWakeupMessageIfNeeded()
+{
+    auto arguments = std::exchange(m_deferredWakeupMessageArguments, WTF::nullopt);
+    if (!arguments)
+        return;
+
+    sendWakeupMessage(*arguments);
+    m_remainingItemsToAppendBeforeSendingWakeup = 0;
+}
+
+void RemoteRenderingBackendProxy::didAppendData(const DisplayList::ItemBufferHandle& handle, size_t numberOfBytes, DisplayList::DidChangeItemBuffer didChangeItemBuffer, RenderingResourceIdentifier destinationImageBuffer)
+{
+    auto* sharedHandle = m_sharedDisplayListHandles.get(handle.identifier);
+    if (UNLIKELY(!sharedHandle))
+        RELEASE_ASSERT_NOT_REACHED();
+
+    bool wasEmpty = sharedHandle->advance(numberOfBytes) == numberOfBytes;
+    if (!wasEmpty || didChangeItemBuffer == DisplayList::DidChangeItemBuffer::Yes) {
+        if (m_deferredWakeupMessageArguments && !--m_remainingItemsToAppendBeforeSendingWakeup)
+            sendWakeupMessage(*std::exchange(m_deferredWakeupMessageArguments, WTF::nullopt));
+        return;
     }
+
+    sendDeferredWakeupMessageIfNeeded();
+
+    // Instead of sending the wakeup message immediately, wait for some additional data. This gives the
+    // web process a "head start", decreasing the likelihood that the GPU process will encounter frequent
+    // wakeups when processing a large amount of display list items.
+    constexpr unsigned itemCountHysteresisBeforeSendingWakeup = 512;
+
+    m_remainingItemsToAppendBeforeSendingWakeup = itemCountHysteresisBeforeSendingWakeup;
+    m_deferredWakeupMessageArguments = {{
+        handle.identifier,
+        sharedHandle->writableOffset() - numberOfBytes,
+        destinationImageBuffer
+    }};
 }
 
-DisplayList::ItemBufferHandle RemoteRenderingBackendProxy::createItemBuffer(size_t capacity, RenderingResourceIdentifier destinationBufferIdentifier)
+RefPtr<DisplayListWriterHandle> RemoteRenderingBackendProxy::findReusableDisplayListHandle(size_t capacity)
 {
-    updateReusableHandles();
+    if (UNLIKELY(m_identifiersOfReusableHandles.isEmpty()))
+        return nullptr;
 
-    while (!m_identifiersOfReusableHandles.isEmpty()) {
-        auto identifier = m_identifiersOfReusableHandles.first();
-        auto* reusableHandle = m_sharedDisplayListHandles.get(identifier);
-        RELEASE_ASSERT_WITH_MESSAGE(reusableHandle, "%s failed to find shared display list", WTF_PRETTY_FUNCTION);
+    auto mostRecentlyUsedIdentifier = m_identifiersOfReusableHandles.first();
+    auto handle = makeRefPtr(m_sharedDisplayListHandles.get(mostRecentlyUsedIdentifier));
+    handle->moveWritableOffsetToStartIfPossible();
+    if (handle->availableCapacity() >= capacity)
+        return handle;
 
-        if (m_identifiersOfHandlesAvailableForWriting.contains(identifier) && reusableHandle->availableCapacity() >= capacity) {
-            m_identifiersOfHandlesAvailableForWriting.remove(identifier);
-            return reusableHandle->createHandle();
-        }
+    m_identifiersOfReusableHandles.append(m_identifiersOfReusableHandles.takeFirst());
 
-        m_identifiersOfReusableHandles.removeFirst();
+    auto leastRecentlyUsedIdentifier = m_identifiersOfReusableHandles.first();
+    if (leastRecentlyUsedIdentifier != mostRecentlyUsedIdentifier) {
+        auto handle = makeRefPtr(m_sharedDisplayListHandles.get(leastRecentlyUsedIdentifier));
+        if (handle->moveWritableOffsetToStartIfPossible() && handle->availableCapacity() >= capacity)
+            return handle;
     }
 
+    return nullptr;
+}
+
+DisplayList::ItemBufferHandle RemoteRenderingBackendProxy::createItemBuffer(size_t capacity, RenderingResourceIdentifier destinationBufferIdentifier)
+{
+    if (auto handle = findReusableDisplayListHandle(capacity))
+        return handle->createHandle();
+
     static constexpr size_t defaultSharedItemBufferSize = 1 << 16;
     static_assert(defaultSharedItemBufferSize > SharedDisplayListHandle::headerSize());
 
@@ -248,7 +282,7 @@
     auto newHandle = DisplayListWriterHandle::create(identifier, sharedMemory.releaseNonNull());
     auto displayListHandle = newHandle->createHandle();
 
-    m_identifiersOfReusableHandles.append(identifier);
+    m_identifiersOfReusableHandles.prepend(identifier);
     m_sharedDisplayListHandles.set(identifier, WTFMove(newHandle));
 
     return displayListHandle;

Modified: trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h (270477 => 270478)


--- trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h	2020-12-05 22:17:10 UTC (rev 270478)
@@ -66,6 +66,10 @@
     RemoteResourceCacheProxy& remoteResourceCacheProxy() { return m_remoteResourceCacheProxy; }
     WebCore::DisplayList::ItemBufferHandle createItemBuffer(size_t capacity, WebCore::RenderingResourceIdentifier destinationBufferIdentifier);
 
+    void didAppendData(const WebCore::DisplayList::ItemBufferHandle&, size_t numberOfBytes, WebCore::DisplayList::DidChangeItemBuffer, WebCore::RenderingResourceIdentifier destinationImageBuffer);
+    void willAppendItem(WebCore::RenderingResourceIdentifier);
+    void sendDeferredWakeupMessageIfNeeded();
+
     // IPC::MessageSender.
     IPC::Connection* messageSenderConnection() const override;
     uint64_t messageSenderDestinationID() const override;
@@ -76,7 +80,6 @@
     // Messages to be sent.
     RefPtr<WebCore::ImageBuffer> createImageBuffer(const WebCore::FloatSize&, WebCore::RenderingMode, float resolutionScale, WebCore::ColorSpace, WebCore::PixelFormat);
     RefPtr<WebCore::ImageData> getImageData(WebCore::AlphaPremultiplication outputFormat, const WebCore::IntRect& srcRect, WebCore::RenderingResourceIdentifier);
-    void submitDisplayList(const WebCore::DisplayList::DisplayList&, WebCore::RenderingResourceIdentifier destinationBufferIdentifier);
     WebCore::DisplayList::FlushIdentifier flushDisplayListAndCommit(const WebCore::DisplayList::DisplayList&, WebCore::RenderingResourceIdentifier);
     void cacheNativeImage(const ShareableBitmap::Handle&, WebCore::RenderingResourceIdentifier);
     void releaseRemoteResource(WebCore::RenderingResourceIdentifier);
@@ -92,17 +95,28 @@
 
     void connectToGPUProcess();
     void reestablishGPUProcessConnection();
-    void updateReusableHandles();
 
     // Messages to be received.
     void didCreateImageBufferBackend(ImageBufferBackendHandle, WebCore::RenderingResourceIdentifier);
     void didFlush(WebCore::DisplayList::FlushIdentifier, WebCore::RenderingResourceIdentifier);
 
+    RefPtr<DisplayListWriterHandle> findReusableDisplayListHandle(size_t capacity);
+
+    struct WakeupMessageArguments {
+        WebCore::DisplayList::ItemBufferIdentifier itemBufferIdentifier;
+        size_t initialOffset;
+        WebCore::RenderingResourceIdentifier imageBufferIdentifier;
+    };
+
+    void sendWakeupMessage(const WakeupMessageArguments&);
+
     RemoteResourceCacheProxy m_remoteResourceCacheProxy { *this };
     HashMap<WebCore::DisplayList::ItemBufferIdentifier, RefPtr<DisplayListWriterHandle>> m_sharedDisplayListHandles;
     Deque<WebCore::DisplayList::ItemBufferIdentifier> m_identifiersOfReusableHandles;
-    HashSet<WebCore::DisplayList::ItemBufferIdentifier> m_identifiersOfHandlesAvailableForWriting;
     RenderingBackendIdentifier m_renderingBackendIdentifier { RenderingBackendIdentifier::generate() };
+    Optional<WebCore::RenderingResourceIdentifier> m_currentDestinationImageBufferIdentifier;
+    Optional<WakeupMessageArguments> m_deferredWakeupMessageArguments;
+    unsigned m_remainingItemsToAppendBeforeSendingWakeup { 0 };
 };
 
 } // namespace WebKit

Modified: trunk/Tools/ChangeLog (270477 => 270478)


--- trunk/Tools/ChangeLog	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Tools/ChangeLog	2020-12-05 22:17:10 UTC (rev 270478)
@@ -1,3 +1,14 @@
+2020-12-04  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [Concurrent display lists] Synchronize display list rendering across remote image buffers
+        https://bugs.webkit.org/show_bug.cgi?id=219091
+        <rdar://problem/71747695>
+
+        Reviewed by Geoff Garen.
+
+        * TestWebKitAPI/Tests/WebCore/DisplayListTests.cpp:
+        (TestWebKitAPI::TEST):
+
 2020-12-04  Jonathan Bedard  <jbed...@apple.com>
 
         [webkitscmpy] local.Svn reports incorrect timestamps

Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/DisplayListTests.cpp (270477 => 270478)


--- trunk/Tools/TestWebKitAPI/Tests/WebCore/DisplayListTests.cpp	2020-12-05 21:28:48 UTC (rev 270477)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/DisplayListTests.cpp	2020-12-05 22:17:10 UTC (rev 270478)
@@ -173,7 +173,7 @@
         }
 
     private:
-        Optional<ItemHandle> WARN_UNUSED_RETURN decodeItem(const uint8_t* data, size_t dataLength, ItemType type, uint8_t* handleLocation)
+        Optional<ItemHandle> WARN_UNUSED_RETURN decodeItem(const uint8_t* data, size_t dataLength, ItemType type, uint8_t* handleLocation) final
         {
             EXPECT_EQ(type, ItemType::StrokePath);
             EXPECT_EQ(dataLength, sizeof(size_t));
@@ -205,6 +205,8 @@
             return SharedBuffer::create(reinterpret_cast<uint8_t*>(&index), sizeof(size_t));
         }
 
+        void didAppendData(const ItemBufferHandle&, size_t, DidChangeItemBuffer) final { }
+
         Vector<StrokePath>& m_items;
     };
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to