22 changes: 15 additions & 7 deletions Source/WebKit/Shared/RemoteLayerTree/RemoteLayerBackingStore.mm
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#import "ImageBufferBackendHandleSharing.h"
#import "Logging.h"
#import "PlatformCALayerRemote.h"
#import "RemoteImageBufferSetProxy.h"
#import "RemoteLayerBackingStoreCollection.h"
#import "RemoteLayerTreeContext.h"
#import "RemoteLayerTreeDrawingAreaProxy.h"
Expand Down Expand Up @@ -68,7 +69,7 @@

namespace {

class DelegatedContentsFenceFlusher final : public ThreadSafeImageBufferFlusher {
class DelegatedContentsFenceFlusher final : public ThreadSafeImageBufferSetFlusher {
WTF_MAKE_FAST_ALLOCATED;
WTF_MAKE_NONCOPYABLE(DelegatedContentsFenceFlusher);
public:
Expand All @@ -77,7 +78,7 @@
return std::unique_ptr<DelegatedContentsFenceFlusher> { new DelegatedContentsFenceFlusher(WTFMove(fence)) };
}

void flush() final
void flushAndCollectHandles(HashMap<RemoteImageBufferSetIdentifier, std::unique_ptr<BufferSetBackendHandle>>&) final
{
m_fence->waitFor(delegatedContentsFinishedTimeout);
}
Expand Down Expand Up @@ -150,9 +151,6 @@ static bool hasValue(const ImageBufferBackendHandle& backendHandle)

void RemoteLayerBackingStore::encode(IPC::Encoder& encoder) const
{
if (auto* collection = backingStoreCollection())
collection->backingStoreWillBeEncoded(*this);

encoder << m_parameters.isOpaque;
encoder << m_parameters.type;

Expand All @@ -173,6 +171,8 @@ static bool hasValue(const ImageBufferBackendHandle& backendHandle)

encoder << WTFMove(handle);

encoder << bufferSetIdentifier();

encodeBufferAndBackendInfos(encoder);
encoder << m_contentsRenderingResourceIdentifier;
encoder << m_previouslyPaintedRect;
Expand Down Expand Up @@ -422,7 +422,7 @@ static bool hasValue(const ImageBufferBackendHandle& backendHandle)
m_layer->owner()->platformCALayerLayerDidDisplay(m_layer);

m_previouslyPaintedRect = dirtyBounds;
m_frontBufferFlushers.appendVector(createFlushers());
m_frontBufferFlushers.append(createFlusher());
}

void RemoteLayerBackingStore::enumerateRectsBeingDrawn(GraphicsContext& context, void (^block)(FloatRect))
Expand Down Expand Up @@ -569,7 +569,15 @@ static bool hasValue(const ImageBufferBackendHandle& backendHandle)
node.setCachedContentsBuffers(WTFMove(cachedBuffers));
}

Vector<std::unique_ptr<ThreadSafeImageBufferFlusher>> RemoteLayerBackingStore::takePendingFlushers()
void RemoteLayerBackingStoreProperties::setBackendHandle(BufferSetBackendHandle& bufferSetHandle)
{
m_bufferHandle = std::exchange(bufferSetHandle.bufferHandle, std::nullopt);
m_frontBufferInfo = bufferSetHandle.frontBufferInfo;
m_backBufferInfo = bufferSetHandle.backBufferInfo;
m_secondaryBackBufferInfo = bufferSetHandle.secondaryBackBufferInfo;
}

Vector<std::unique_ptr<ThreadSafeImageBufferSetFlusher>> RemoteLayerBackingStore::takePendingFlushers()
{
return std::exchange(m_frontBufferFlushers, { });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ class RemoteLayerBackingStoreCollection : public CanMakeWeakPtr<RemoteLayerBacki

virtual void backingStoreWasCreated(RemoteLayerBackingStore&);
virtual void backingStoreWillBeDestroyed(RemoteLayerBackingStore&);
void backingStoreWillBeEncoded(const RemoteLayerBackingStore&);

void purgeFrontBufferForTesting(RemoteLayerBackingStore&);
void purgeBackBufferForTesting(RemoteLayerBackingStore&);
Expand All @@ -75,7 +74,7 @@ class RemoteLayerBackingStoreCollection : public CanMakeWeakPtr<RemoteLayerBacki
void willFlushLayers();
void willBuildTransaction();
void willCommitLayerTree(RemoteLayerTreeTransaction&);
Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>> didFlushLayers(RemoteLayerTreeTransaction&);
Vector<std::unique_ptr<ThreadSafeImageBufferSetFlusher>> didFlushLayers(RemoteLayerTreeTransaction&);

virtual void tryMarkAllBackingStoreVolatile(CompletionHandler<void(bool)>&&);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,19 +93,14 @@
}

if (prepareBuffersData.size()) {
remoteRenderingBackend.prepareImageBufferSetsForDisplay(WTFMove(prepareBuffersData), [backingStoreList = WTFMove(backingStoreList)](Vector<RemoteRenderingBackendProxy::SwapBuffersResult>&& swapResult) {
RELEASE_ASSERT(swapResult.size() == backingStoreList.size() || swapResult.isEmpty());
for (unsigned i = 0; i < swapResult.size(); ++i) {
auto& backingStoreSwapResult = swapResult[i];
auto& backingStore = backingStoreList[i];
if (!backingStore)
continue;
if (backingStoreSwapResult.displayRequirement == SwapBuffersDisplayRequirement::NeedsFullDisplay)
backingStore->setNeedsDisplay();
backingStore->setBufferCacheIdentifiers(WTFMove(backingStoreSwapResult.cacheIdentifiers));
backingStore->setBackendHandle(WTFMove(backingStoreSwapResult.backendHandle));
}
});
auto swapResult = remoteRenderingBackend.prepareImageBufferSetsForDisplay(WTFMove(prepareBuffersData));
RELEASE_ASSERT(swapResult.size() == backingStoreList.size() || swapResult.isEmpty());
for (unsigned i = 0; i < swapResult.size(); ++i) {
auto& backingStoreSwapResult = swapResult[i];
auto& backingStore = backingStoreList[i];
if (backingStoreSwapResult == SwapBuffersDisplayRequirement::NeedsFullDisplay)
backingStore->setNeedsDisplay();
}
}
}

Expand Down Expand Up @@ -154,11 +149,11 @@
transaction.setLayerIDsWithNewlyUnreachableBackingStore(newlyUnreachableLayerIDs);
}

Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>> RemoteLayerBackingStoreCollection::didFlushLayers(RemoteLayerTreeTransaction& transaction)
Vector<std::unique_ptr<ThreadSafeImageBufferSetFlusher>> RemoteLayerBackingStoreCollection::didFlushLayers(RemoteLayerTreeTransaction& transaction)
{
bool needToScheduleVolatilityTimer = false;

Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>> flushers;
Vector<std::unique_ptr<ThreadSafeImageBufferSetFlusher>> flushers;
for (auto& layer : transaction.changedLayers()) {
if (layer->properties().changedProperties & LayerChange::BackingStoreChanged) {
needToScheduleVolatilityTimer = true;
Expand Down Expand Up @@ -471,10 +466,4 @@
}, forcePurge);
}

void RemoteLayerBackingStoreCollection::backingStoreWillBeEncoded(const RemoteLayerBackingStore&)
{
m_layerTreeContext.ensureRemoteRenderingBackendProxy().ensurePrepareCompleted();
}


} // namespace WebKit
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ header: "RemoteLayerBackingStore.h"
bool m_isOpaque;
WebKit::RemoteLayerBackingStore::Type m_type;
std::optional<WebKit::ImageBufferBackendHandle> m_bufferHandle;
std::optional<WebKit::RemoteImageBufferSetIdentifier> m_bufferSet;
std::optional<WebKit::BufferAndBackendInfo> m_frontBufferInfo;
std::optional<WebKit::BufferAndBackendInfo> m_backBufferInfo;
std::optional<WebKit::BufferAndBackendInfo> m_secondaryBackBufferInfo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class RemoteLayerWithInProcessRenderingBackingStore : public RemoteLayerBackingS

void prepareToDisplay() final;
void createContextAndPaintContents() final;
Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>> createFlushers() final;
std::unique_ptr<ThreadSafeImageBufferSetFlusher> createFlusher() final;

void clearBackingStore() final;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#import "ImageBufferShareableMappedIOSurfaceBackend.h"
#import "Logging.h"
#import "PlatformCALayerRemote.h"
#import "RemoteImageBufferSetProxy.h"
#import "RemoteLayerBackingStoreCollection.h"
#import "RemoteLayerTreeContext.h"
#import "SwapBuffersDisplayRequirement.h"
Expand Down Expand Up @@ -134,16 +135,33 @@
m_frontBuffer.isCleared = false;
}

Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>> RemoteLayerWithInProcessRenderingBackingStore::createFlushers()
{
Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>> flushers;
class ImageBufferBackingStoreFlusher final : public ThreadSafeImageBufferSetFlusher {
WTF_MAKE_FAST_ALLOCATED;
WTF_MAKE_NONCOPYABLE(ImageBufferBackingStoreFlusher);
public:
static std::unique_ptr<ImageBufferBackingStoreFlusher> create(std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher> imageBufferFlusher)
{
return std::unique_ptr<ImageBufferBackingStoreFlusher> { new ImageBufferBackingStoreFlusher(WTFMove(imageBufferFlusher)) };
}

m_frontBuffer.imageBuffer->flushDrawingContextAsync();
flushers.append(m_frontBuffer.imageBuffer->createFlusher());
void flushAndCollectHandles(HashMap<RemoteImageBufferSetIdentifier, std::unique_ptr<BufferSetBackendHandle>>&) final
{
m_imageBufferFlusher->flush();
}

return flushers;
}
private:
ImageBufferBackingStoreFlusher(std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher> imageBufferFlusher)
: m_imageBufferFlusher(WTFMove(imageBufferFlusher))
{
}
std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher> m_imageBufferFlusher;
};

std::unique_ptr<ThreadSafeImageBufferSetFlusher> RemoteLayerWithInProcessRenderingBackingStore::createFlusher()
{
m_frontBuffer.imageBuffer->flushDrawingContextAsync();
return ImageBufferBackingStoreFlusher::create(m_frontBuffer.imageBuffer->createFlusher());
}

SwapBuffersDisplayRequirement RemoteLayerWithInProcessRenderingBackingStore::prepareBuffers()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,13 @@ class RemoteLayerWithRemoteRenderingBackingStore : public RemoteLayerBackingStor

RefPtr<RemoteImageBufferSetProxy> protectedBufferSet() { return m_bufferSet; }

Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>> createFlushers() final;
std::unique_ptr<ThreadSafeImageBufferSetFlusher> createFlusher() final;
std::optional<ImageBufferBackendHandle> frontBufferHandle() const final { return std::exchange(const_cast<RemoteLayerWithRemoteRenderingBackingStore*>(this)->m_backendHandle, std::nullopt); }
#if ENABLE(RE_DYNAMIC_CONTENT_SCALING)
std::optional<ImageBufferBackendHandle> displayListHandle() const final;
#endif
void encodeBufferAndBackendInfos(IPC::Encoder&) const final;
std::optional<RemoteImageBufferSetIdentifier> bufferSetIdentifier() const final;

void ensureBackingStore(const Parameters&) final;
bool hasFrontBuffer() const final;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@
m_cleared = true;
}

Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>> RemoteLayerWithRemoteRenderingBackingStore::createFlushers()
std::unique_ptr<ThreadSafeImageBufferSetFlusher> RemoteLayerWithRemoteRenderingBackingStore::createFlusher()
{
if (!m_bufferSet)
return { };
return Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>>::from(m_bufferSet->flushFrontBufferAsync());
return m_bufferSet->flushFrontBufferAsync();
}

void RemoteLayerWithRemoteRenderingBackingStore::createContextAndPaintContents()
Expand Down Expand Up @@ -122,6 +122,13 @@
encodeBuffer(m_bufferCacheIdentifiers.secondaryBack);
}

std::optional<RemoteImageBufferSetIdentifier> RemoteLayerWithRemoteRenderingBackingStore::bufferSetIdentifier() const
{
if (!m_bufferSet)
return std::nullopt;
return m_bufferSet->identifier();
}

#if ENABLE(RE_DYNAMIC_CONTENT_SCALING)
std::optional<ImageBufferBackendHandle> RemoteLayerWithRemoteRenderingBackingStore::displayListHandle() const
{
Expand Down
1 change: 1 addition & 0 deletions Source/WebKit/SourcesCocoa.txt
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,7 @@ RemoteMediaSessionCoordinatorMessageReceiver.cpp
RemoteMediaSessionCoordinatorProxyMessageReceiver.cpp
RemoteImageBufferMessageReceiver.cpp
RemoteImageBufferProxyMessageReceiver.cpp
RemoteImageBufferSetProxyMessageReceiver.cpp
RemoteImageBufferSetMessageReceiver.cpp
RemoteRenderingBackendMessageReceiver.cpp
RemoteRenderingBackendProxyMessageReceiver.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#pragma once

#include "DrawingAreaProxy.h"
#include "RemoteImageBufferSetIdentifier.h"
#include "RemoteLayerTreeHost.h"
#include "TransactionID.h"
#include <WebCore/AnimationFrameRate.h>
Expand Down Expand Up @@ -136,7 +137,7 @@ class RemoteLayerTreeDrawingAreaProxy : public DrawingAreaProxy {

void willCommitLayerTree(IPC::Connection&, TransactionID);
void commitLayerTreeNotTriggered(IPC::Connection&, TransactionID);
void commitLayerTree(IPC::Connection&, const Vector<std::pair<RemoteLayerTreeTransaction, RemoteScrollingCoordinatorTransaction>>&);
void commitLayerTree(IPC::Connection&, const Vector<std::pair<RemoteLayerTreeTransaction, RemoteScrollingCoordinatorTransaction>>&, HashMap<RemoteImageBufferSetIdentifier, std::unique_ptr<BufferSetBackendHandle>>&&);
void commitLayerTreeTransaction(IPC::Connection&, const RemoteLayerTreeTransaction&, const RemoteScrollingCoordinatorTransaction&);
virtual void didCommitLayerTree(IPC::Connection&, const RemoteLayerTreeTransaction&, const RemoteScrollingCoordinatorTransaction&) { }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ messages -> RemoteLayerTreeDrawingAreaProxy : DrawingAreaProxy NotRefCounted {
void SetPreferredFramesPerSecond(unsigned preferredFramesPerSecond)
void WillCommitLayerTree(WebKit::TransactionID transactionID)
void CommitLayerTreeNotTriggered(WebKit::TransactionID nextCommitTransactionID)
void CommitLayerTree(Vector<std::pair<WebKit::RemoteLayerTreeTransaction, WebKit::RemoteScrollingCoordinatorTransaction>> transactions) CanDispatchOutOfOrder
void CommitLayerTree(Vector<std::pair<WebKit::RemoteLayerTreeTransaction, WebKit::RemoteScrollingCoordinatorTransaction>> transactions, HashMap<WebKit::RemoteImageBufferSetIdentifier, std::unique_ptr<WebKit::BufferSetBackendHandle>> handlesMap) CanDispatchOutOfOrder
void AsyncSetLayerContents(WebCore::PlatformLayerIdentifier layer, WebKit::ImageBufferBackendHandle handle, WebCore::RenderingResourceIdentifier identifier)
}
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,20 @@
state.pendingLayerTreeTransactionID = transactionID;
}

void RemoteLayerTreeDrawingAreaProxy::commitLayerTree(IPC::Connection& connection, const Vector<std::pair<RemoteLayerTreeTransaction, RemoteScrollingCoordinatorTransaction>>& transactions)
void RemoteLayerTreeDrawingAreaProxy::commitLayerTree(IPC::Connection& connection, const Vector<std::pair<RemoteLayerTreeTransaction, RemoteScrollingCoordinatorTransaction>>& transactions, HashMap<RemoteImageBufferSetIdentifier, std::unique_ptr<BufferSetBackendHandle>>&& handlesMap)
{
Vector<MachSendRight> sendRights;
for (auto& transaction : transactions) {
// commitLayerTreeTransaction consumes the incoming buffers, so we need to grab them first.
for (auto& [layerID, properties] : transaction.first.changedLayerProperties()) {
const auto* backingStoreProperties = properties->backingStoreOrProperties.properties.get();
auto* backingStoreProperties = properties->backingStoreOrProperties.properties.get();
if (!backingStoreProperties)
continue;
if (backingStoreProperties->bufferSetIdentifier()) {
auto iter = handlesMap.find(*backingStoreProperties->bufferSetIdentifier());
if (iter != handlesMap.end())
backingStoreProperties->setBackendHandle(*iter->value);
}
if (const auto& backendHandle = backingStoreProperties->bufferHandle()) {
if (const auto* sendRight = std::get_if<MachSendRight>(&backendHandle.value()))
sendRights.append(*sendRight);
Expand Down
2 changes: 2 additions & 0 deletions Source/WebKit/WebKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -6868,6 +6868,7 @@
A78CCDD8193AC9E3005ECC25 /* com.apple.WebKit.Networking.sb.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.WebKit.Networking.sb.in; sourceTree = "<group>"; };
A7A3D552289395E2008D683D /* WebWorkerClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebWorkerClient.cpp; sourceTree = "<group>"; };
A7A3D553289395E2008D683D /* WebWorkerClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebWorkerClient.h; sourceTree = "<group>"; };
A7B94DE32B5D9DBB0058780B /* RemoteImageBufferSetProxy.messages.in */ = {isa = PBXFileReference; explicitFileType = text; path = RemoteImageBufferSetProxy.messages.in; sourceTree = "<group>"; };
A7D792D41767CB0900881CBE /* ActivityAssertion.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ActivityAssertion.h; sourceTree = "<group>"; };
A7D792D51767CB6E00881CBE /* ActivityAssertion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ActivityAssertion.cpp; sourceTree = "<group>"; };
A7E1503A2B1D6F030000E921 /* RemoteImageBuffer.messages.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = RemoteImageBuffer.messages.in; sourceTree = "<group>"; };
Expand Down Expand Up @@ -11925,6 +11926,7 @@
7BE66B942A388C200059B6F2 /* RemoteImageBufferProxy.messages.in */,
A78A5FE52B0EE4C3005036D3 /* RemoteImageBufferSetProxy.cpp */,
A78A5FE62B0EE4C3005036D3 /* RemoteImageBufferSetProxy.h */,
A7B94DE32B5D9DBB0058780B /* RemoteImageBufferSetProxy.messages.in */,
5506409D2407160900AAE045 /* RemoteRenderingBackendProxy.cpp */,
5506409E2407160900AAE045 /* RemoteRenderingBackendProxy.h */,
550640A0240719E100AAE045 /* RemoteRenderingBackendProxy.messages.in */,
Expand Down
87 changes: 71 additions & 16 deletions Source/WebKit/WebProcess/GPU/graphics/RemoteImageBufferSetProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "config.h"
#include "RemoteImageBufferSetProxy.h"

#include "BufferAndBackendInfo.h"
#include "Logging.h"
#include "RemoteImageBufferSetMessages.h"
#include "RemoteRenderingBackendProxy.h"
Expand All @@ -40,9 +41,9 @@ class RemoteImageBufferSetProxyFlushFence : public ThreadSafeRefCounted<RemoteIm
WTF_MAKE_NONCOPYABLE(RemoteImageBufferSetProxyFlushFence);
WTF_MAKE_FAST_ALLOCATED;
public:
static Ref<RemoteImageBufferSetProxyFlushFence> create(IPC::Event event)
static Ref<RemoteImageBufferSetProxyFlushFence> create(IPC::Event event, RenderingUpdateID renderingUpdateID)
{
return adoptRef(*new RemoteImageBufferSetProxyFlushFence { WTFMove(event) });
return adoptRef(*new RemoteImageBufferSetProxyFlushFence { WTFMove(event), renderingUpdateID });
}

~RemoteImageBufferSetProxyFlushFence()
Expand All @@ -51,15 +52,17 @@ class RemoteImageBufferSetProxyFlushFence : public ThreadSafeRefCounted<RemoteIm
tracePoint(FlushRemoteImageBufferEnd, reinterpret_cast<uintptr_t>(this), 1u);
}

bool waitFor(Seconds timeout)
bool waitFor(Seconds relativeTimeout)
{
IPC::Timeout timeout(relativeTimeout);
Locker locker { m_lock };
if (m_signaled)
return true;
if (!m_handles)
m_condition.waitFor(m_lock, timeout.secondsUntilDeadline());
ASSERT(!m_signaled);
m_signaled = m_event.waitFor(timeout);
if (m_signaled)
tracePoint(FlushRemoteImageBufferEnd, reinterpret_cast<uintptr_t>(this), 0u);
return m_signaled;
return m_signaled && m_handles;
}

std::optional<IPC::Event> tryTakeEvent()
Expand All @@ -70,33 +73,58 @@ class RemoteImageBufferSetProxyFlushFence : public ThreadSafeRefCounted<RemoteIm
return WTFMove(m_event);
}

void setHandles(BufferSetBackendHandle&& handles)
{
Locker locker { m_lock };
m_handles = WTFMove(handles);
m_condition.notifyOne();
}

std::optional<BufferSetBackendHandle> takeHandles()
{
Locker locker { m_lock };
return std::exchange(m_handles, std::nullopt);
}

RenderingUpdateID renderingUpdateID() const { return m_renderingUpdateID; }

private:
RemoteImageBufferSetProxyFlushFence(IPC::Event event)
RemoteImageBufferSetProxyFlushFence(IPC::Event event, RenderingUpdateID renderingUpdateID)
: m_event(WTFMove(event))
, m_renderingUpdateID(renderingUpdateID)
{
tracePoint(FlushRemoteImageBufferStart, reinterpret_cast<uintptr_t>(this));
}
Lock m_lock;
Condition m_condition;
std::atomic<bool> m_signaled { false };
IPC::Event WTF_GUARDED_BY_LOCK(m_lock) m_event;
std::optional<BufferSetBackendHandle> m_handles WTF_GUARDED_BY_LOCK(m_lock);
RenderingUpdateID m_renderingUpdateID;
};

namespace {

class RemoteImageBufferSetProxyFlusher final : public ThreadSafeImageBufferFlusher {
class RemoteImageBufferSetProxyFlusher final : public ThreadSafeImageBufferSetFlusher {
WTF_MAKE_FAST_ALLOCATED;
public:
RemoteImageBufferSetProxyFlusher(Ref<RemoteImageBufferSetProxyFlushFence> flushState)
: m_flushState(WTFMove(flushState))
RemoteImageBufferSetProxyFlusher(RemoteImageBufferSetIdentifier identifier, Ref<RemoteImageBufferSetProxyFlushFence> flushState, unsigned generation)
: m_identifier(identifier)
, m_flushState(WTFMove(flushState))
, m_generation(generation)
{ }

void flush() final
void flushAndCollectHandles(HashMap<RemoteImageBufferSetIdentifier, std::unique_ptr<BufferSetBackendHandle>>& handlesMap) final
{
m_flushState->waitFor(RemoteRenderingBackendProxy::defaultTimeout);
if (m_flushState->waitFor(RemoteRenderingBackendProxy::defaultTimeout))
handlesMap.add(m_identifier, makeUnique<BufferSetBackendHandle>(*m_flushState->takeHandles()));

}

private:
RemoteImageBufferSetIdentifier m_identifier;
Ref<RemoteImageBufferSetProxyFlushFence> m_flushState;
unsigned m_generation;
};

}
Expand Down Expand Up @@ -167,6 +195,30 @@ void RemoteImageBufferSetProxy::clearVolatilityUntilAfter(MarkSurfacesAsVolatile
m_minimumVolatilityRequest = previousVolatilityRequest;
}

#if PLATFORM(COCOA)
void RemoteImageBufferSetProxy::didPrepareForDisplay(ImageBufferSetPrepareBufferForDisplayOutputData outputData, RenderingUpdateID renderingUpdateID)
{
if (m_pendingFlush && m_pendingFlush->renderingUpdateID() == renderingUpdateID) {
BufferSetBackendHandle handle;

handle.bufferHandle = WTFMove(outputData.backendHandle);

auto createBufferAndBackendInfo = [&](const std::optional<WebCore::RenderingResourceIdentifier>& bufferIdentifier) {
if (bufferIdentifier)
return std::optional { BufferAndBackendInfo { *bufferIdentifier, m_generation } };
return std::optional<BufferAndBackendInfo>();
};

handle.frontBufferInfo = createBufferAndBackendInfo(outputData.bufferCacheIdentifiers.front);
handle.backBufferInfo = createBufferAndBackendInfo(outputData.bufferCacheIdentifiers.back);
handle.secondaryBackBufferInfo = createBufferAndBackendInfo(outputData.bufferCacheIdentifiers.secondaryBack);

m_pendingFlush->setHandles(WTFMove(handle));
}
if (m_remoteRenderingBackendProxy)
m_remoteRenderingBackendProxy->didPrepareForDisplay(*this);
}
#endif

void RemoteImageBufferSetProxy::setConfiguration(WebCore::FloatSize size, float scale, const WebCore::DestinationColorSpace& colorSpace, WebCore::PixelFormat pixelFormat, WebCore::RenderingMode renderingMode, WebCore::RenderingPurpose renderingPurpose)
{
Expand All @@ -179,7 +231,7 @@ void RemoteImageBufferSetProxy::setConfiguration(WebCore::FloatSize size, float
m_remoteNeedsConfigurationUpdate = true;
}

std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher> RemoteImageBufferSetProxy::flushFrontBufferAsync()
std::unique_ptr<ThreadSafeImageBufferSetFlusher> RemoteImageBufferSetProxy::flushFrontBufferAsync()
{
if (!m_remoteRenderingBackendProxy)
return nullptr;
Expand All @@ -197,9 +249,9 @@ std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher> RemoteImageBufferSetProxy
}

send(Messages::RemoteImageBufferSet::Flush());
m_pendingFlush = RemoteImageBufferSetProxyFlushFence::create(WTFMove(*event));
m_pendingFlush = RemoteImageBufferSetProxyFlushFence::create(WTFMove(*event), m_remoteRenderingBackendProxy->renderingUpdateID());

return makeUnique<RemoteImageBufferSetProxyFlusher>(Ref { *m_pendingFlush });
return makeUnique<RemoteImageBufferSetProxyFlusher>(m_identifier, Ref { *m_pendingFlush }, m_generation);
}

void RemoteImageBufferSetProxy::willPrepareForDisplay()
Expand All @@ -218,9 +270,12 @@ void RemoteImageBufferSetProxy::willPrepareForDisplay()

void RemoteImageBufferSetProxy::remoteBufferSetWasDestroyed()
{
if (m_pendingFlush) {
m_pendingFlush->setHandles(BufferSetBackendHandle { });
m_pendingFlush = nullptr;
}
m_generation++;
m_remoteNeedsConfigurationUpdate = true;
m_pendingFlush = nullptr;
}

GraphicsContext& RemoteImageBufferSetProxy::context()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,31 @@
#include "MarkSurfacesAsVolatileRequestIdentifier.h"
#include "RemoteDisplayListRecorderProxy.h"
#include "RemoteImageBufferSetIdentifier.h"
#include "RenderingUpdateID.h"

#if ENABLE(GPU_PROCESS)

namespace IPC {
class Connection;
class Decoder;
}

namespace WebKit {

class RemoteImageBufferSetProxyFlushFence;
struct BufferSetBackendHandle;

// FIXME: We should have a generic 'ImageBufferSet' class that contains
// the code that isn't specific to being remote, and this helper belongs
// there.
class ThreadSafeImageBufferSetFlusher {
WTF_MAKE_FAST_ALLOCATED;
WTF_MAKE_NONCOPYABLE(ThreadSafeImageBufferSetFlusher);
public:
ThreadSafeImageBufferSetFlusher() = default;
virtual ~ThreadSafeImageBufferSetFlusher() = default;
virtual void flushAndCollectHandles(HashMap<RemoteImageBufferSetIdentifier, std::unique_ptr<BufferSetBackendHandle>>&) = 0;
};

// A RemoteImageBufferSet is a set of three ImageBuffers (front, back,
// secondary back) owned by the GPU process, for the purpose of drawing
Expand All @@ -60,12 +79,16 @@ class RemoteImageBufferSetProxy : public RefCounted<RemoteImageBufferSetProxy>,
void addRequestedVolatility(OptionSet<BufferInSetType> request);
void setConfirmedVolatility(MarkSurfacesAsVolatileRequestIdentifier, OptionSet<BufferInSetType> types);

#if PLATFORM(COCOA)
void didPrepareForDisplay(ImageBufferSetPrepareBufferForDisplayOutputData, RenderingUpdateID);
#endif

WebCore::GraphicsContext& context();
bool hasContext() const { return !!m_displayListRecorder; }

WebCore::RenderingResourceIdentifier displayListResourceIdentifier() const { return m_displayListIdentifier; }

std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher> flushFrontBufferAsync();
std::unique_ptr<ThreadSafeImageBufferSetFlusher> flushFrontBufferAsync();

void setConfiguration(WebCore::FloatSize, float, const WebCore::DestinationColorSpace&, WebCore::PixelFormat, WebCore::RenderingMode, WebCore::RenderingPurpose);
void willPrepareForDisplay();
Expand All @@ -77,6 +100,8 @@ class RemoteImageBufferSetProxy : public RefCounted<RemoteImageBufferSetProxy>,

unsigned generation() const { return m_generation; }

void didReceiveMessage(IPC::Connection&, IPC::Decoder&);

private:
template<typename T> void send(T&& message);
template<typename T> auto sendSync(T&& message);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright (C) 2024 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#if ENABLE(GPU_PROCESS)

messages -> RemoteImageBufferSetProxy NotRefCounted {
#if PLATFORM(COCOA)
DidPrepareForDisplay(struct WebKit::ImageBufferSetPrepareBufferForDisplayOutputData outputData, WebKit::RenderingUpdateID renderingUpdateID)
#endif
}

#endif // ENABLE(GPU_PROCESS)
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "RemoteImageBufferProxy.h"
#include "RemoteImageBufferProxyMessages.h"
#include "RemoteImageBufferSetProxy.h"
#include "RemoteImageBufferSetProxyMessages.h"
#include "RemoteRenderingBackendMessages.h"
#include "RemoteRenderingBackendProxyMessages.h"
#include "SwapBuffersDisplayRequirement.h"
Expand Down Expand Up @@ -140,6 +141,7 @@ void RemoteRenderingBackendProxy::didClose(IPC::Connection&)
bufferSet.value->remoteBufferSetWasDestroyed();
send(Messages::RemoteRenderingBackend::CreateRemoteImageBufferSet(bufferSet.value->identifier(), bufferSet.value->displayListResourceIdentifier()));
}
m_bufferSetsInDisplay.clear();
}

void RemoteRenderingBackendProxy::disconnectGPUProcess()
Expand Down Expand Up @@ -358,12 +360,10 @@ void RemoteRenderingBackendProxy::releaseAllImageResources()
}

#if PLATFORM(COCOA)
void RemoteRenderingBackendProxy::prepareImageBufferSetsForDisplay(Vector<LayerPrepareBuffersData>&& prepareBuffersInput, CompletionHandler<void(Vector<SwapBuffersResult>&&)> callback)
Vector<SwapBuffersDisplayRequirement> RemoteRenderingBackendProxy::prepareImageBufferSetsForDisplay(Vector<LayerPrepareBuffersData>&& prepareBuffersInput)
{
if (prepareBuffersInput.isEmpty()) {
callback(Vector<SwapBuffersResult>());
return;
}
if (prepareBuffersInput.isEmpty())
return Vector<SwapBuffersDisplayRequirement>();

bool needsSync = false;

Expand All @@ -378,6 +378,9 @@ void RemoteRenderingBackendProxy::prepareImageBufferSetsForDisplay(Vector<LayerP
perLayerData.bufferSet->clearVolatilityUntilAfter(m_currentVolatilityRequest);
perLayerData.bufferSet->willPrepareForDisplay();

auto addResult = m_bufferSetsInDisplay.add(perLayerData.bufferSet->identifier(), perLayerData.bufferSet);
ASSERT_UNUSED(addResult, addResult.isNewEntry);

return ImageBufferSetPrepareBufferForDisplayInputData {
perLayerData.bufferSet->identifier(),
perLayerData.dirtyRegion,
Expand All @@ -389,23 +392,28 @@ void RemoteRenderingBackendProxy::prepareImageBufferSetsForDisplay(Vector<LayerP

LOG_WITH_STREAM(RemoteLayerBuffers, stream << "RemoteRenderingBackendProxy::prepareImageBufferSetsForDisplay - input buffers " << inputData);

m_prepareReply = streamConnection().sendWithAsyncReply(Messages::RemoteRenderingBackend::PrepareImageBufferSetsForDisplay(inputData), [prepareBuffersInput = WTFMove(prepareBuffersInput), callback = WTFMove(callback)](Vector<ImageBufferSetPrepareBufferForDisplayOutputData>&& outputData) mutable {
Vector<SwapBuffersResult> result;
for (auto& data : outputData)
result.append(SwapBuffersResult { WTFMove(data.backendHandle), data.displayRequirement, data.bufferCacheIdentifiers });
callback(WTFMove(result));
}, renderingBackendIdentifier(), defaultTimeout);

if (needsSync)
ensurePrepareCompleted();
Vector<SwapBuffersDisplayRequirement> result;
if (needsSync) {
auto sendResult = streamConnection().sendSync(Messages::RemoteRenderingBackend::PrepareImageBufferSetsForDisplaySync(inputData, m_renderingUpdateID), renderingBackendIdentifier(), defaultTimeout);
if (!sendResult.succeeded()) {
result.grow(inputData.size());
for (auto& displayRequirement : result)
displayRequirement = SwapBuffersDisplayRequirement::NeedsFullDisplay;
} else
std::tie(result) = sendResult.takeReply();
} else {
streamConnection().send(Messages::RemoteRenderingBackend::PrepareImageBufferSetsForDisplay(inputData, m_renderingUpdateID), renderingBackendIdentifier(), defaultTimeout);
result.grow(inputData.size());
for (auto& displayRequirement : result)
displayRequirement = SwapBuffersDisplayRequirement::NeedsNormalDisplay;
}
return result;
}

void RemoteRenderingBackendProxy::ensurePrepareCompleted()
void RemoteRenderingBackendProxy::didPrepareForDisplay(RemoteImageBufferSetProxy& bufferSet)
{
if (m_prepareReply) {
streamConnection().waitForAsyncReplyAndDispatchImmediately<Messages::RemoteRenderingBackend::PrepareImageBufferSetsForDisplay>(m_prepareReply, defaultTimeout);
m_prepareReply = { };
}
bool success = m_bufferSetsInDisplay.remove(bufferSet.identifier());
ASSERT_UNUSED(success, success);
}
#endif

Expand Down Expand Up @@ -464,6 +472,13 @@ bool RemoteRenderingBackendProxy::dispatchMessage(IPC::Connection& connection, I
// Messages to already removed instances are ok.
return true;
}
if (decoder.messageReceiverName() == Messages::RemoteImageBufferSetProxy::messageReceiverName()) {
RefPtr bufferSet = m_bufferSetsInDisplay.get(RemoteImageBufferSetIdentifier { decoder.destinationID() });
ASSERT(bufferSet);
if (bufferSet)
bufferSet->didReceiveMessage(connection, decoder);
return true;
}
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
#include "RenderingUpdateID.h"
#include "SharedMemory.h"
#include "StreamClientConnection.h"
#include "ThreadSafeObjectHeap.h"
#include "WorkQueueMessageReceiver.h"
#include <WebCore/RenderingResourceIdentifier.h>
#include <WebCore/Timer.h>
#include <span>
Expand Down Expand Up @@ -135,14 +137,8 @@ class RemoteRenderingBackendProxy
};

#if PLATFORM(COCOA)
struct SwapBuffersResult {
std::optional<ImageBufferBackendHandle> backendHandle;
SwapBuffersDisplayRequirement displayRequirement;
BufferIdentifierSet cacheIdentifiers;
};

void prepareImageBufferSetsForDisplay(Vector<LayerPrepareBuffersData>&&, CompletionHandler<void(Vector<SwapBuffersResult>&&)>);
void ensurePrepareCompleted();
Vector<SwapBuffersDisplayRequirement> prepareImageBufferSetsForDisplay(Vector<LayerPrepareBuffersData>&&);
void didPrepareForDisplay(RemoteImageBufferSetProxy&);
#endif

void finalizeRenderingUpdate();
Expand Down Expand Up @@ -204,12 +200,11 @@ class RemoteRenderingBackendProxy
MarkSurfacesAsVolatileRequestIdentifier m_currentVolatilityRequest;
HashMap<MarkSurfacesAsVolatileRequestIdentifier, CompletionHandler<void(bool)>> m_markAsVolatileRequests;
HashMap<RemoteImageBufferSetIdentifier, WeakPtr<RemoteImageBufferSetProxy>> m_bufferSets;
HashMap<RemoteImageBufferSetIdentifier, RefPtr<RemoteImageBufferSetProxy>> m_bufferSetsInDisplay;
SerialFunctionDispatcher& m_dispatcher;

RenderingUpdateID m_renderingUpdateID;
RenderingUpdateID m_didRenderingUpdateID;

IPC::Connection::AsyncReplyID m_prepareReply;
};

} // namespace WebKit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ class RemoteLayerTreeDrawingArea : public DrawingArea, public WebCore::GraphicsL
public:
static Ref<BackingStoreFlusher> create(Ref<IPC::Connection>&&);

void flush(UniqueRef<IPC::Encoder>&&, Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>>&&);
void flush(UniqueRef<IPC::Encoder>&&, Vector<std::unique_ptr<ThreadSafeImageBufferSetFlusher>>&&);

bool hasPendingFlush() const { return m_hasPendingFlush; }
void markHasPendingFlush()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#import "GraphicsLayerCARemote.h"
#import "MessageSenderInlines.h"
#import "PlatformCALayerRemote.h"
#import "RemoteImageBufferSetProxy.h"
#import "RemoteLayerBackingStoreCollection.h"
#import "RemoteLayerTreeContext.h"
#import "RemoteLayerTreeDrawingAreaProxyMessages.h"
Expand Down Expand Up @@ -397,11 +398,10 @@
for (auto& transaction : transactions)
backingStoreCollection.willCommitLayerTree(transaction.first);

Messages::RemoteLayerTreeDrawingAreaProxy::CommitLayerTree message(transactions);
auto commitEncoder = makeUniqueRef<IPC::Encoder>(Messages::RemoteLayerTreeDrawingAreaProxy::CommitLayerTree::name(), m_identifier.toUInt64());
commitEncoder.get() << WTFMove(message).arguments();
commitEncoder.get() << transactions;

Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>> flushers;
Vector<std::unique_ptr<ThreadSafeImageBufferSetFlusher>> flushers;
for (auto& transaction : transactions)
flushers.appendVector(backingStoreCollection.didFlushLayers(transaction.first));
bool haveFlushers = flushers.size();
Expand Down Expand Up @@ -488,14 +488,17 @@
{
}

void RemoteLayerTreeDrawingArea::BackingStoreFlusher::flush(UniqueRef<IPC::Encoder>&& commitEncoder, Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>>&& flushers)
void RemoteLayerTreeDrawingArea::BackingStoreFlusher::flush(UniqueRef<IPC::Encoder>&& commitEncoder, Vector<std::unique_ptr<ThreadSafeImageBufferSetFlusher>>&& flushers)
{
ASSERT(m_hasPendingFlush);

TraceScope tracingScope(BackingStoreFlushStart, BackingStoreFlushEnd);

HashMap<RemoteImageBufferSetIdentifier, std::unique_ptr<BufferSetBackendHandle>> handles;
for (auto& flusher : flushers)
flusher->flush();
flusher->flushAndCollectHandles(handles);

commitEncoder.get() << WTFMove(handles);

m_hasPendingFlush = false;

Expand Down