102 changes: 102 additions & 0 deletions Source/WebKit/GPUProcess/graphics/RemoteImageBufferSet.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright (C) 2020-2023 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. ``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
* 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.
*/

#pragma once

#if ENABLE(GPU_PROCESS)

#include "IPCEvent.h"
#include "PrepareBackingStoreBuffersData.h"
#include "RemoteImageBufferSetIdentifier.h"
#include "StreamConnectionWorkQueue.h"
#include "StreamMessageReceiver.h"
#include <WebCore/ImageBuffer.h>

namespace WebKit {

class RemoteRenderingBackend;

class RemoteImageBufferSet : public IPC::StreamMessageReceiver {
public:
static Ref<RemoteImageBufferSet> create(RemoteImageBufferSetIdentifier, WebCore::RenderingResourceIdentifier displayListIdentifier, RemoteRenderingBackend&);
~RemoteImageBufferSet();
void stopListeningForIPC();

// Ensures frontBuffer is valid, either by swapping an existing back
// buffer, or allocating a new one.
void ensureBufferForDisplay(const ImageBufferSetPrepareBufferForDisplayInputData&, ImageBufferSetPrepareBufferForDisplayOutputData&);

// Initializes the contents of the new front buffer using the previous
// frames (if applicable), clips to the dirty region, and clears the pixels
// to be drawn (unless drawing will be opaque).
void prepareBufferForDisplay(const WebCore::Region& dirtyRegion, bool requiresClearedPixels);

bool makeBuffersVolatile(OptionSet<BufferInSetType> requestedBuffers, OptionSet<BufferInSetType>& volatileBuffers);

private:
RemoteImageBufferSet(RemoteImageBufferSetIdentifier, WebCore::RenderingResourceIdentifier, RemoteRenderingBackend&);
void startListeningForIPC();
IPC::StreamConnectionWorkQueue& workQueue() const;

// IPC::StreamMessageReceiver
void didReceiveStreamMessage(IPC::StreamServerConnection&, IPC::Decoder&) final;

// Messages
void updateConfiguration(const WebCore::FloatSize&, WebCore::RenderingMode, float resolutionScale, const WebCore::DestinationColorSpace&, WebCore::PixelFormat);
void setFlushSignal(IPC::Signal&&);
void flush();

bool isOpaque() const
{
return m_pixelFormat == WebCore::PixelFormat::RGB10 || m_pixelFormat == WebCore::PixelFormat::BGRX8;
}

RefPtr<RemoteRenderingBackend> m_backend;
RemoteImageBufferSetIdentifier m_identifier;
WebCore::RenderingResourceIdentifier m_displayListIdentifier;

RefPtr<WebCore::ImageBuffer> m_frontBuffer;
RefPtr<WebCore::ImageBuffer> m_backBuffer;
RefPtr<WebCore::ImageBuffer> m_secondaryBackBuffer;

RefPtr<WebCore::ImageBuffer> m_previousFrontBuffer;

WebCore::FloatSize m_logicalSize;
WebCore::RenderingMode m_renderingMode;
WebCore::RenderingPurpose m_purpose;
float m_resolutionScale { 1.0f };
WebCore::DestinationColorSpace m_colorSpace { WebCore::DestinationColorSpace::SRGB() };
WebCore::PixelFormat m_pixelFormat;
bool m_frontBufferIsCleared { false };

std::optional<WebCore::IntRect> m_previouslyPaintedRect;

std::optional<IPC::Signal> m_flushSignal;
};


} // namespace WebKit

#endif
31 changes: 31 additions & 0 deletions Source/WebKit/GPUProcess/graphics/RemoteImageBufferSet.messages.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright (C) 2023 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 -> RemoteImageBufferSet NotRefCounted Stream {
UpdateConfiguration(WebCore::FloatSize logicalSize, WebCore::RenderingMode renderingMode, float resolutionScale, WebCore::DestinationColorSpace colorSpace, enum:uint8_t WebCore::PixelFormat pixelFormat)
SetFlushSignal(IPC::Signal signal) NotStreamEncodable
Flush()
}

#endif
174 changes: 76 additions & 98 deletions Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

#include "BufferIdentifierSet.h"
#include "GPUConnectionToWebProcess.h"
#include "GPUProcess.h"
#include "GPUProcessProxyMessages.h"
#include "ImageBufferShareableBitmapBackend.h"
#include "Logging.h"
#include "MessageSenderInlines.h"
Expand All @@ -41,6 +43,7 @@
#include "RemoteFaceDetectorMessages.h"
#include "RemoteImageBuffer.h"
#include "RemoteImageBufferProxyMessages.h"
#include "RemoteImageBufferSet.h"
#include "RemoteMediaPlayerManagerProxy.h"
#include "RemoteMediaPlayerProxy.h"
#include "RemoteRenderingBackendCreationParameters.h"
Expand All @@ -51,6 +54,7 @@
#include "ShapeDetectionObjectHeap.h"
#include "SwapBuffersDisplayRequirement.h"
#include "WebCoreArgumentCoders.h"
#include "WebPageProxy.h"
#include <WebCore/HTMLCanvasElement.h>
#include <WebCore/NullImageBufferBackend.h>
#include <WebCore/RenderingResourceIdentifier.h>
Expand Down Expand Up @@ -82,15 +86,13 @@
namespace WebKit {
using namespace WebCore;

#if PLATFORM(COCOA)
static bool isSmallLayerBacking(const ImageBufferParameters& parameters)
bool isSmallLayerBacking(const ImageBufferParameters& parameters)
{
const unsigned maxSmallLayerBackingArea = 64u * 64u; // 4096 == 16kb backing store which equals 1 page on AS.
return parameters.purpose == RenderingPurpose::LayerBacking
&& ImageBuffer::calculateBackendSize(parameters.logicalSize, parameters.resolutionScale).area() <= maxSmallLayerBackingArea
&& (parameters.pixelFormat == PixelFormat::BGRA8 || parameters.pixelFormat == PixelFormat::BGRX8);
}
#endif

Ref<RemoteRenderingBackend> RemoteRenderingBackend::create(GPUConnectionToWebProcess& gpuConnectionToWebProcess, RemoteRenderingBackendCreationParameters&& creationParameters, Ref<IPC::StreamServerConnection>&& streamConnection)
{
Expand Down Expand Up @@ -163,6 +165,23 @@ uint64_t RemoteRenderingBackend::messageSenderDestinationID() const
return m_renderingBackendIdentifier.toUInt64();
}

void RemoteRenderingBackend::createDisplayListRecorder(RefPtr<ImageBuffer> imageBuffer, RenderingResourceIdentifier identifier)
{
assertIsCurrent(workQueue());
if (!imageBuffer) {
auto errorImage = ImageBuffer::create<NullImageBufferBackend>({ 0, 0 }, 1, DestinationColorSpace::SRGB(), PixelFormat::BGRA8, RenderingPurpose::Unspecified, { }, identifier);
m_remoteDisplayLists.add(identifier, RemoteDisplayListRecorder::create(*errorImage.get(), identifier, *this));
return;
}
m_remoteDisplayLists.add(identifier, RemoteDisplayListRecorder::create(*imageBuffer.get(), identifier, *this));
}

void RemoteRenderingBackend::releaseDisplayListRecorder(RenderingResourceIdentifier identifier)
{
assertIsCurrent(workQueue());
m_remoteDisplayLists.take(identifier);
}

void RemoteRenderingBackend::didFailCreateImageBuffer(RenderingResourceIdentifier imageBufferIdentifier)
{
// On failure to create a remote image buffer we still create a null display list recorder.
Expand Down Expand Up @@ -219,7 +238,7 @@ void RemoteRenderingBackend::moveToImageBuffer(RenderingResourceIdentifier image
didCreateImageBuffer(imageBuffer.releaseNonNull());
}

void RemoteRenderingBackend::createImageBuffer(const FloatSize& logicalSize, RenderingMode renderingMode, RenderingPurpose purpose, float resolutionScale, const DestinationColorSpace& colorSpace, PixelFormat pixelFormat, RenderingResourceIdentifier imageBufferIdentifier)
RefPtr<ImageBuffer> RemoteRenderingBackend::allocateImageBuffer(const FloatSize& logicalSize, RenderingMode renderingMode, RenderingPurpose purpose, float resolutionScale, const DestinationColorSpace& colorSpace, PixelFormat pixelFormat, RenderingResourceIdentifier imageBufferIdentifier)
{
assertIsCurrent(workQueue());
RefPtr<ImageBuffer> imageBuffer;
Expand All @@ -238,6 +257,14 @@ void RemoteRenderingBackend::createImageBuffer(const FloatSize& logicalSize, Ren
#else
imageBuffer = ImageBuffer::create<ImageBufferShareableBitmapBackend>(logicalSize, resolutionScale, colorSpace, pixelFormat, purpose, creationContext, imageBufferIdentifier);
#endif
return imageBuffer;
}


void RemoteRenderingBackend::createImageBuffer(const FloatSize& logicalSize, RenderingMode renderingMode, RenderingPurpose purpose, float resolutionScale, const DestinationColorSpace& colorSpace, PixelFormat pixelFormat, RenderingResourceIdentifier imageBufferIdentifier)
{
assertIsCurrent(workQueue());
RefPtr<ImageBuffer> imageBuffer = allocateImageBuffer(logicalSize, renderingMode, purpose, resolutionScale, colorSpace, pixelFormat, imageBufferIdentifier);

if (imageBuffer)
didCreateImageBuffer(imageBuffer.releaseNonNull());
Expand All @@ -255,6 +282,19 @@ void RemoteRenderingBackend::releaseImageBuffer(RenderingResourceIdentifier rend
MESSAGE_CHECK(success, "Resource is being released before being cached."_s);
}

void RemoteRenderingBackend::createRemoteImageBufferSet(RemoteImageBufferSetIdentifier bufferSetIdentifier, WebCore::RenderingResourceIdentifier displayListIdentifier)
{
assertIsCurrent(workQueue());
m_remoteImageBufferSets.add(bufferSetIdentifier, RemoteImageBufferSet::create(bufferSetIdentifier, displayListIdentifier, *this));
}

void RemoteRenderingBackend::releaseRemoteImageBufferSet(RemoteImageBufferSetIdentifier bufferSetIdentifier)
{
assertIsCurrent(workQueue());
bool success = m_remoteImageBufferSets.take(bufferSetIdentifier).get();
MESSAGE_CHECK(success, "BufferSet is being released before being created"_s);
}

void RemoteRenderingBackend::destroyGetPixelBufferSharedMemory()
{
m_getPixelBufferSharedMemory = nullptr;
Expand Down Expand Up @@ -338,119 +378,57 @@ void RemoteRenderingBackend::releaseRenderingResource(RenderingResourceIdentifie
}

#if PLATFORM(COCOA)
static std::optional<ImageBufferBackendHandle> handleFromBuffer(ImageBuffer& buffer)
void RemoteRenderingBackend::prepareImageBufferSetsForDisplay(Vector<ImageBufferSetPrepareBufferForDisplayInputData> swapBuffersInput, CompletionHandler<void(Vector<ImageBufferSetPrepareBufferForDisplayOutputData>&&)>&& completionHandler)
{
auto* sharing = buffer.toBackendSharing();
if (is<ImageBufferBackendHandleSharing>(sharing))
return downcast<ImageBufferBackendHandleSharing>(*sharing).createBackendHandle();

return std::nullopt;
}
assertIsCurrent(workQueue());

void RemoteRenderingBackend::prepareBuffersForDisplay(Vector<PrepareBackingStoreBuffersInputData> swapBuffersInput, CompletionHandler<void(Vector<PrepareBackingStoreBuffersOutputData>&&)>&& completionHandler)
{
Vector<PrepareBackingStoreBuffersOutputData> outputData;
Vector<ImageBufferSetPrepareBufferForDisplayOutputData> outputData;
outputData.resizeToFit(swapBuffersInput.size());

for (unsigned i = 0; i < swapBuffersInput.size(); ++i)
prepareLayerBuffersForDisplay(swapBuffersInput[i], outputData[i]);

completionHandler(WTFMove(outputData));
}

// This is the GPU Process version of RemoteLayerBackingStore::prepareBuffers().
void RemoteRenderingBackend::prepareLayerBuffersForDisplay(const PrepareBackingStoreBuffersInputData& inputData, PrepareBackingStoreBuffersOutputData& outputData)
{
auto fetchBuffer = [&](std::optional<RenderingResourceIdentifier> identifier) -> RefPtr<ImageBuffer> {
return identifier ? imageBuffer(*identifier) : nullptr;
};

auto bufferIdentifier = [](RefPtr<WebCore::ImageBuffer> buffer) -> std::optional<RenderingResourceIdentifier> {
if (!buffer)
return std::nullopt;
return buffer->renderingResourceIdentifier();
};

auto frontBuffer = fetchBuffer(inputData.bufferSet.front);
auto backBuffer = fetchBuffer(inputData.bufferSet.back);
auto secondaryBackBuffer = fetchBuffer(inputData.bufferSet.secondaryBack);

LOG_WITH_STREAM(RemoteLayerBuffers, stream << "GPU Process: RemoteRenderingBackend::prepareBuffersForDisplay - front "
<< inputData.bufferSet.front << " (in-use " << (frontBuffer && frontBuffer->isInUse()) << ") "
<< inputData.bufferSet.back << " (in-use " << (backBuffer && backBuffer->isInUse()) << ") "
<< inputData.bufferSet.secondaryBack << " (in-use " << (secondaryBackBuffer && secondaryBackBuffer->isInUse()) << ") ");

bool needsFullDisplay = false;

if (frontBuffer) {
auto previousState = frontBuffer->setNonVolatile();
if (previousState == SetNonVolatileResult::Empty)
needsFullDisplay = true;
}

if (frontBuffer && !needsFullDisplay && inputData.hasEmptyDirtyRegion) {
// No swap necessary, but we do need to return the front buffer handle.
outputData.frontBufferHandle = handleFromBuffer(*frontBuffer);
outputData.bufferSet = BufferIdentifierSet { bufferIdentifier(frontBuffer), bufferIdentifier(backBuffer), bufferIdentifier(secondaryBackBuffer) };
outputData.displayRequirement = SwapBuffersDisplayRequirement::NeedsNoDisplay;
return;
for (unsigned i = 0; i < swapBuffersInput.size(); ++i) {
RefPtr<RemoteImageBufferSet> remoteImageBufferSet = m_remoteImageBufferSets.get(swapBuffersInput[i].remoteBufferSet);
MESSAGE_CHECK(remoteImageBufferSet, "BufferSet is being updated before being created"_s);
remoteImageBufferSet->ensureBufferForDisplay(swapBuffersInput[i], outputData[i]);
}

if (!frontBuffer || !inputData.supportsPartialRepaint || isSmallLayerBacking(frontBuffer->parameters()))
needsFullDisplay = true;
completionHandler(WTFMove(outputData));

if (!backBuffer || backBuffer->isInUse()) {
std::swap(backBuffer, secondaryBackBuffer);
// Defer preparing all the front buffers (which triggers pixel copy
// operations) until after we've sent the completion handler (and any
// buffer backend created messages) to unblock the WebProcess as soon
// as possible.
for (unsigned i = 0; i < swapBuffersInput.size(); ++i) {
RefPtr<RemoteImageBufferSet> remoteImageBufferSet = m_remoteImageBufferSets.get(swapBuffersInput[i].remoteBufferSet);
MESSAGE_CHECK(remoteImageBufferSet, "BufferSet is being updated before being created"_s);

// When pulling the secondary back buffer out of hibernation (to become
// the new front buffer), if it is somehow still in use (e.g. we got
// three swaps ahead of the render server), just give up and discard it.
if (backBuffer && backBuffer->isInUse())
backBuffer = nullptr;
remoteImageBufferSet->prepareBufferForDisplay(swapBuffersInput[i].dirtyRegion, swapBuffersInput[i].requiresClearedPixels);
}

std::swap(frontBuffer, backBuffer);

outputData.bufferSet = BufferIdentifierSet { bufferIdentifier(frontBuffer), bufferIdentifier(backBuffer), bufferIdentifier(secondaryBackBuffer) };
if (frontBuffer) {
auto previousState = frontBuffer->setNonVolatile();
if (previousState == SetNonVolatileResult::Empty)
needsFullDisplay = true;

outputData.frontBufferHandle = handleFromBuffer(*frontBuffer);
} else
needsFullDisplay = true;

LOG_WITH_STREAM(RemoteLayerBuffers, stream << "GPU Process: prepareBuffersForDisplay - swapped from ["
<< inputData.bufferSet.front << ", " << inputData.bufferSet.back << ", " << inputData.bufferSet.secondaryBack << "] to ["
<< outputData.bufferSet.front << ", " << outputData.bufferSet.back << ", " << outputData.bufferSet.secondaryBack << "]");

outputData.displayRequirement = needsFullDisplay ? SwapBuffersDisplayRequirement::NeedsFullDisplay : SwapBuffersDisplayRequirement::NeedsNormalDisplay;
}
#endif

void RemoteRenderingBackend::markSurfacesVolatile(MarkSurfacesAsVolatileRequestIdentifier requestIdentifier, const Vector<RenderingResourceIdentifier>& identifiers)
void RemoteRenderingBackend::markSurfacesVolatile(MarkSurfacesAsVolatileRequestIdentifier requestIdentifier, const Vector<std::pair<RemoteImageBufferSetIdentifier, OptionSet<BufferInSetType>>>& identifiers)
{
assertIsCurrent(workQueue());
LOG_WITH_STREAM(RemoteLayerBuffers, stream << "GPU Process: RemoteRenderingBackend::markSurfacesVolatile " << identifiers);

auto makeVolatile = [](ImageBuffer& imageBuffer) {
imageBuffer.releaseGraphicsContext();
return imageBuffer.setVolatile();
};
Vector<std::pair<RemoteImageBufferSetIdentifier, OptionSet<BufferInSetType>>> markedBufferSets;
bool allSucceeded = true;

Vector<RenderingResourceIdentifier> markedVolatileBufferIdentifiers;
for (auto identifier : identifiers) {
if (auto target = imageBuffer(identifier)) {
if (makeVolatile(*target))
markedVolatileBufferIdentifiers.append(identifier);
} else
LOG_WITH_STREAM(RemoteLayerBuffers, stream << " failed to find ImageBuffer for identifier " << identifier);
}
RefPtr<RemoteImageBufferSet> remoteImageBufferSet = m_remoteImageBufferSets.get(identifier.first);

LOG_WITH_STREAM(RemoteLayerBuffers, stream << "GPU Process: markSurfacesVolatile - surfaces marked volatile " << markedVolatileBufferIdentifiers);
MESSAGE_CHECK(remoteImageBufferSet, "BufferSet is being marked volatile before being created"_s);

OptionSet<BufferInSetType> volatileBuffers;
if (!remoteImageBufferSet->makeBuffersVolatile(identifier.second, volatileBuffers))
allSucceeded = false;

if (!volatileBuffers.isEmpty())
markedBufferSets.append(std::make_pair(identifier.first, volatileBuffers));
}

bool didMarkAllLayerAsVolatile = identifiers.size() == markedVolatileBufferIdentifiers.size();
send(Messages::RemoteRenderingBackendProxy::DidMarkLayersAsVolatile(requestIdentifier, markedVolatileBufferIdentifiers, didMarkAllLayerAsVolatile), m_renderingBackendIdentifier);
LOG_WITH_STREAM(RemoteLayerBuffers, stream << "GPU Process: markSurfacesVolatile - surfaces marked volatile " << markedBufferSets);
send(Messages::RemoteRenderingBackendProxy::DidMarkLayersAsVolatile(requestIdentifier, WTFMove(markedBufferSets), allSucceeded), m_renderingBackendIdentifier);
}

void RemoteRenderingBackend::finalizeRenderingUpdate(RenderingUpdateID renderingUpdateID)
Expand Down
29 changes: 21 additions & 8 deletions Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,14 @@

#if ENABLE(GPU_PROCESS)

#include "BufferIdentifierSet.h"
#include "Connection.h"
#include "IPCEvent.h"
#include "ImageBufferBackendHandle.h"
#include "MarkSurfacesAsVolatileRequestIdentifier.h"
#include "MessageReceiver.h"
#include "MessageSender.h"
#include "RemoteImageBufferSetIdentifier.h"
#include "RemoteRenderingBackendCreationParameters.h"
#include "RemoteResourceCache.h"
#include "RemoteSerializedImageBufferIdentifier.h"
Expand Down Expand Up @@ -70,12 +73,14 @@ struct FaceDetectorOptions;

namespace WebKit {


class GPUConnectionToWebProcess;
class RemoteDisplayListRecorder;
class RemoteImageBuffer;
class RemoteImageBufferSet;
struct BufferIdentifierSet;
struct PrepareBackingStoreBuffersInputData;
struct PrepareBackingStoreBuffersOutputData;
struct ImageBufferSetPrepareBufferForDisplayInputData;
struct ImageBufferSetPrepareBufferForDisplayOutputData;
struct RemoteRenderingBackendCreationParameters;
enum class SwapBuffersDisplayRequirement : uint8_t;

Expand Down Expand Up @@ -116,8 +121,11 @@ class RemoteRenderingBackend : private IPC::MessageSender, public IPC::StreamMes
RefPtr<WebCore::ImageBuffer> imageBuffer(WebCore::RenderingResourceIdentifier);
RefPtr<WebCore::ImageBuffer> takeImageBuffer(WebCore::RenderingResourceIdentifier);

RefPtr<WebCore::ImageBuffer> allocateImageBuffer(const WebCore::FloatSize& logicalSize, WebCore::RenderingMode, WebCore::RenderingPurpose, float resolutionScale, const WebCore::DestinationColorSpace&, WebCore::PixelFormat, WebCore::RenderingResourceIdentifier);

void terminateWebProcess(ASCIILiteral message);
private:
friend class RemoteImageBufferSet;
RemoteRenderingBackend(GPUConnectionToWebProcess&, RemoteRenderingBackendCreationParameters&&, Ref<IPC::StreamServerConnection>&&);
void startListeningForIPC();
void workQueueInitialize();
Expand All @@ -143,15 +151,14 @@ class RemoteRenderingBackend : private IPC::MessageSender, public IPC::StreamMes
void releaseAllImageResources();
void releaseRenderingResource(WebCore::RenderingResourceIdentifier);
void finalizeRenderingUpdate(RenderingUpdateID);
void markSurfacesVolatile(MarkSurfacesAsVolatileRequestIdentifier, const Vector<WebCore::RenderingResourceIdentifier>&);
void markSurfacesVolatile(MarkSurfacesAsVolatileRequestIdentifier, const Vector<std::pair<RemoteImageBufferSetIdentifier, OptionSet<BufferInSetType>>>&);
void createRemoteImageBufferSet(WebKit::RemoteImageBufferSetIdentifier, WebCore::RenderingResourceIdentifier displayListIdentifier);
void releaseRemoteImageBufferSet(WebKit::RemoteImageBufferSetIdentifier);

#if PLATFORM(COCOA)
void prepareBuffersForDisplay(Vector<PrepareBackingStoreBuffersInputData> swapBuffersInput, CompletionHandler<void(Vector<PrepareBackingStoreBuffersOutputData>&&)>&&);
void prepareImageBufferSetsForDisplay(Vector<ImageBufferSetPrepareBufferForDisplayInputData> swapBuffersInput, CompletionHandler<void(Vector<ImageBufferSetPrepareBufferForDisplayOutputData>&&)>&&);
#endif

#if PLATFORM(COCOA)
void prepareLayerBuffersForDisplay(const PrepareBackingStoreBuffersInputData&, PrepareBackingStoreBuffersOutputData&);
#endif

void createRemoteBarcodeDetector(ShapeDetectionIdentifier, const WebCore::ShapeDetection::BarcodeDetectorOptions&);
void releaseRemoteBarcodeDetector(ShapeDetectionIdentifier);
void getRemoteBarcodeDetectorSupportedFormats(CompletionHandler<void(Vector<WebCore::ShapeDetection::BarcodeFormat>&&)>&&);
Expand All @@ -163,6 +170,9 @@ class RemoteRenderingBackend : private IPC::MessageSender, public IPC::StreamMes
void didFailCreateImageBuffer(WebCore::RenderingResourceIdentifier) WTF_REQUIRES_CAPABILITY(workQueue());
void didCreateImageBuffer(Ref<WebCore::ImageBuffer>) WTF_REQUIRES_CAPABILITY(workQueue());

void createDisplayListRecorder(RefPtr<WebCore::ImageBuffer>, WebCore::RenderingResourceIdentifier);
void releaseDisplayListRecorder(WebCore::RenderingResourceIdentifier);

Ref<IPC::StreamConnectionWorkQueue> m_workQueue;
Ref<IPC::StreamServerConnection> m_streamConnection;
RemoteResourceCache m_remoteResourceCache;
Expand All @@ -176,9 +186,12 @@ class RemoteRenderingBackend : private IPC::MessageSender, public IPC::StreamMes

HashMap<WebCore::RenderingResourceIdentifier, IPC::ScopedActiveMessageReceiveQueue<RemoteDisplayListRecorder>> m_remoteDisplayLists WTF_GUARDED_BY_CAPABILITY(workQueue());
HashMap<WebCore::RenderingResourceIdentifier, IPC::ScopedActiveMessageReceiveQueue<RemoteImageBuffer>> m_remoteImageBuffers WTF_GUARDED_BY_CAPABILITY(workQueue());
HashMap<WebKit::RemoteImageBufferSetIdentifier, IPC::ScopedActiveMessageReceiveQueue<RemoteImageBufferSet>> m_remoteImageBufferSets WTF_GUARDED_BY_CAPABILITY(workQueue());
Ref<ShapeDetection::ObjectHeap> m_shapeDetectionObjectHeap;
};

bool isSmallLayerBacking(const WebCore::ImageBufferParameters&);

} // namespace WebKit

#endif // ENABLE(GPU_PROCESS)
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,14 @@ messages -> RemoteRenderingBackend NotRefCounted Stream {
ReleaseAllImageResources()
ReleaseRenderingResource(WebCore::RenderingResourceIdentifier renderingResourceIdentifier)

CreateRemoteImageBufferSet(WebKit::RemoteImageBufferSetIdentifier bufferSetIdentifier, WebCore::RenderingResourceIdentifier displayListIdentifier)
ReleaseRemoteImageBufferSet(WebKit::RemoteImageBufferSetIdentifier bufferSetIdentifier)

#if PLATFORM(COCOA)
PrepareBuffersForDisplay(Vector<WebKit::PrepareBackingStoreBuffersInputData> swapBuffersInput) -> (Vector<WebKit::PrepareBackingStoreBuffersOutputData> swapBuffersOutput) Synchronous NotStreamEncodableReply
PrepareImageBufferSetsForDisplay(Vector<WebKit::ImageBufferSetPrepareBufferForDisplayInputData> swapBuffersInput) -> (Vector<WebKit::ImageBufferSetPrepareBufferForDisplayOutputData> swapBuffersOutput) NotStreamEncodableReply ReplyCanDispatchOutOfOrder
#endif

MarkSurfacesVolatile(WebKit::MarkSurfacesAsVolatileRequestIdentifier requestIdentifier, Vector<WebCore::RenderingResourceIdentifier> renderingResourceIdentifiers)
MarkSurfacesVolatile(WebKit::MarkSurfacesAsVolatileRequestIdentifier requestIdentifier, Vector<std::pair<WebKit::RemoteImageBufferSetIdentifier, OptionSet<WebKit::BufferInSetType>>> renderingResourceIdentifiers)
FinalizeRenderingUpdate(WebKit::RenderingUpdateID renderingUpdateID)

MoveToSerializedBuffer(WebCore::RenderingResourceIdentifier sourceImageBuffer)
Expand Down
7 changes: 7 additions & 0 deletions Source/WebKit/Platform/IPC/StreamClientConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class StreamClientConnection final : public ThreadSafeRefCounted<StreamClientCon

template<typename T, typename U, typename V>
Error waitForAndDispatchImmediately(ObjectIdentifierGeneric<U, V> destinationID, Timeout, OptionSet<WaitForOption> = { });
template<typename> Error waitForAsyncReplyAndDispatchImmediately(AsyncReplyID, Timeout);

StreamClientConnectionBuffer& bufferForTesting();
Connection& connectionForTesting();
Expand Down Expand Up @@ -224,6 +225,12 @@ Error StreamClientConnection::waitForAndDispatchImmediately(ObjectIdentifierGene
return m_connection->waitForAndDispatchImmediately<T>(destinationID, timeout, waitForOptions);
}

template<typename T>
Error StreamClientConnection::waitForAsyncReplyAndDispatchImmediately(AsyncReplyID replyID, Timeout timeout)
{
return m_connection->waitForAsyncReplyAndDispatchImmediately<T>(replyID, timeout);
}

template<typename T>
std::optional<StreamClientConnection::SendSyncResult<T>> StreamClientConnection::trySendSyncStream(T& message, Timeout timeout, std::span<uint8_t>& span)
{
Expand Down
7 changes: 5 additions & 2 deletions Source/WebKit/Scripts/webkit/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ def serialized_identifiers():
'WebKit::RemoteAudioDestinationIdentifier',
'WebKit::RemoteAudioHardwareListenerIdentifier',
'WebKit::RemoteAudioSessionIdentifier',
'WebKit::RemoteImageBufferSetIdentifier',
'WebKit::RemoteCDMIdentifier',
'WebKit::RemoteCDMInstanceIdentifier',
'WebKit::RemoteCDMInstanceSessionIdentifier',
Expand Down Expand Up @@ -672,6 +673,7 @@ def class_template_headers(template_string):
'Ref': {'headers': ['<wtf/Ref.h>'], 'argument_coder_headers': ['"ArgumentCoders.h"']},
'RefPtr': {'headers': ['<wtf/RefCounted.h>'], 'argument_coder_headers': ['"ArgumentCoders.h"']},
'RetainPtr': {'headers': ['<wtf/RetainPtr.h>'], 'argument_coder_headers': ['"ArgumentCodersCF.h"']},
'WebCore::ProcessQualified': {'headers': ['<WebCore/ProcessQualified.h>'], 'argument_coder_headers': ['"ArgumentCoders.h"']},
}

match = re.match('(?P<template_name>.+?)<(?P<parameter_string>.+)>', template_string)
Expand Down Expand Up @@ -950,6 +952,7 @@ def headers_for_type(type):
'WebKit::AppPrivacyReportTestingData': ['"AppPrivacyReport.h"'],
'WebKit::AuthenticationChallengeIdentifier': ['"IdentifierTypes.h"'],
'WebKit::BackForwardListItemState': ['"SessionState.h"'],
'WebKit::BufferInSetType': ['"BufferIdentifierSet.h"'],
'WebKit::CallDownloadDidStart': ['"DownloadManager.h"'],
'WebKit::ConsumerSharedCARingBuffer::Handle': ['"SharedCARingBuffer.h"'],
'WebKit::ContentWorldIdentifier': ['"ContentWorldShared.h"'],
Expand All @@ -965,8 +968,8 @@ def headers_for_type(type):
'WebKit::PageState': ['"SessionState.h"'],
'WebKit::PaymentSetupConfiguration': ['"PaymentSetupConfigurationWebKit.h"'],
'WebKit::PaymentSetupFeatures': ['"ApplePayPaymentSetupFeaturesWebKit.h"'],
'WebKit::PrepareBackingStoreBuffersInputData': ['"PrepareBackingStoreBuffersData.h"'],
'WebKit::PrepareBackingStoreBuffersOutputData': ['"PrepareBackingStoreBuffersData.h"'],
'WebKit::ImageBufferSetPrepareBufferForDisplayInputData': ['"PrepareBackingStoreBuffersData.h"'],
'WebKit::ImageBufferSetPrepareBufferForDisplayOutputData': ['"PrepareBackingStoreBuffersData.h"'],
'WebKit::RemoteVideoFrameReadReference': ['"RemoteVideoFrameIdentifier.h"'],
'WebKit::RemoteVideoFrameWriteReference': ['"RemoteVideoFrameIdentifier.h"'],
'WebKit::RespectSelectionAnchor': ['"GestureTypes.h"'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
#if ENABLE(GPU_PROCESS) && ENABLE(ENCRYPTED_MEDIA)
#include "RemoteCDMInstanceSessionIdentifier.h"
#endif
#include "RemoteImageBufferSetIdentifier.h"
#if ENABLE(GPU_PROCESS) && ENABLE(LEGACY_ENCRYPTED_MEDIA)
#include "RemoteLegacyCDMIdentifier.h"
#endif
Expand Down Expand Up @@ -501,6 +502,7 @@ Vector<ASCIILiteral> serializedIdentifiers()
#if ENABLE(GPU_PROCESS) && USE(AUDIO_SESSION)
static_assert(sizeof(uint64_t) == sizeof(WebKit::RemoteAudioSessionIdentifier));
#endif
static_assert(sizeof(uint64_t) == sizeof(WebKit::RemoteImageBufferSetIdentifier));
#if ENABLE(GPU_PROCESS) && ENABLE(ENCRYPTED_MEDIA)
static_assert(sizeof(uint64_t) == sizeof(WebKit::RemoteCDMIdentifier));
#endif
Expand Down Expand Up @@ -607,6 +609,7 @@ Vector<ASCIILiteral> serializedIdentifiers()
#if ENABLE(GPU_PROCESS) && USE(AUDIO_SESSION)
"WebKit::RemoteAudioSessionIdentifier"_s,
#endif
"WebKit::RemoteImageBufferSetIdentifier"_s,
#if ENABLE(GPU_PROCESS) && ENABLE(ENCRYPTED_MEDIA)
"WebKit::RemoteCDMIdentifier"_s,
#endif
Expand Down
35 changes: 35 additions & 0 deletions Source/WebKit/Shared/RemoteImageBufferSetIdentifier.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2023 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.
*/

#pragma once

#include <wtf/ObjectIdentifier.h>

namespace WebKit {

struct RemoteImageBufferSetIdentifierType;
using RemoteImageBufferSetIdentifier = ObjectIdentifier<RemoteImageBufferSetIdentifierType>;

}
59 changes: 22 additions & 37 deletions Source/WebKit/Shared/RemoteLayerTree/RemoteLayerBackingStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#pragma once

#include "BufferAndBackendInfo.h"
#include "BufferIdentifierSet.h"
#include "ImageBufferBackendHandle.h"
#include <WebCore/FloatRect.h>
#include <WebCore/ImageBuffer.h>
Expand All @@ -51,6 +52,7 @@ namespace WebKit {
class PlatformCALayerRemote;
class RemoteLayerBackingStoreCollection;
class RemoteLayerTreeNode;
class RemoteLayerTreeHost;
enum class SwapBuffersDisplayRequirement : uint8_t;

enum class BackingStoreNeedsDisplayReason : uint8_t {
Expand Down Expand Up @@ -95,7 +97,7 @@ class RemoteLayerBackingStore : public CanMakeWeakPtr<RemoteLayerBackingStore> {
friend bool operator==(const Parameters&, const Parameters&) = default;
};

void ensureBackingStore(const Parameters&);
virtual void ensureBackingStore(const Parameters&);

void setNeedsDisplay(const WebCore::IntRect);
void setNeedsDisplay();
Expand All @@ -107,7 +109,11 @@ class RemoteLayerBackingStore : public CanMakeWeakPtr<RemoteLayerBackingStore> {
bool needsDisplay() const;

bool performDelegatedLayerDisplay();

void paintContents();
virtual void createContextAndPaintContents() = 0;

virtual Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>> createFlushers() = 0;

WebCore::FloatSize size() const { return m_parameters.size; }
float scale() const { return m_parameters.scale; }
Expand All @@ -117,22 +123,19 @@ class RemoteLayerBackingStore : public CanMakeWeakPtr<RemoteLayerBackingStore> {
Type type() const { return m_parameters.type; }
bool isOpaque() const { return m_parameters.isOpaque; }
unsigned bytesPerPixel() const;
bool supportsPartialRepaint() const;
bool drawingRequiresClearedPixels() const;

PlatformCALayerRemote* layer() const { return m_layer; }

void encode(IPC::Encoder&) const;

void enumerateRectsBeingDrawn(WebCore::GraphicsContext&, void (^)(WebCore::FloatRect));

bool hasFrontBuffer() const
{
return m_contentsBufferHandle || !!m_frontBuffer.imageBuffer;
}
virtual bool hasFrontBuffer() const = 0;
virtual bool frontBufferMayBeVolatile() const = 0;

bool hasNoBuffers() const
{
return !m_frontBuffer.imageBuffer && !m_backBuffer.imageBuffer && !m_secondaryBackBuffer.imageBuffer && !m_contentsBufferHandle;
}
virtual void encodeBufferAndBackendInfos(IPC::Encoder&) const = 0;

Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>> takePendingFlushers();

Expand All @@ -142,35 +145,25 @@ class RemoteLayerBackingStore : public CanMakeWeakPtr<RemoteLayerBackingStore> {
SecondaryBack
};

RefPtr<WebCore::ImageBuffer> bufferForType(BufferType) const;

const WebCore::Region& dirtyRegion() { return m_dirtyRegion; }
bool hasEmptyDirtyRegion() const { return m_dirtyRegion.isEmpty() || m_parameters.size.isEmpty(); }
bool supportsPartialRepaint() const;

MonotonicTime lastDisplayTime() const { return m_lastDisplayTime; }

void clearBackingStore();
virtual void clearBackingStore() = 0;

protected:
virtual RefPtr<WebCore::ImageBuffer> allocateBuffer() const = 0;
virtual std::optional<ImageBufferBackendHandle> frontBufferHandle() const = 0;
#if ENABLE(RE_DYNAMIC_CONTENT_SCALING)
virtual std::optional<ImageBufferBackendHandle> displayListHandle() const { return std::nullopt; }
#endif

virtual void dump(WTF::TextStream&) const = 0;

protected:
RemoteLayerBackingStoreCollection* backingStoreCollection() const;

void drawInContext(WebCore::GraphicsContext&);

struct Buffer {
RefPtr<WebCore::ImageBuffer> imageBuffer;
bool isCleared { false };

explicit operator bool() const
{
return !!imageBuffer;
}

void discard();
};

void ensureFrontBuffer();
void dirtyRepaintCounterIfNecessary();

WebCore::IntRect layerBounds() const;
Expand All @@ -181,21 +174,13 @@ class RemoteLayerBackingStore : public CanMakeWeakPtr<RemoteLayerBackingStore> {

WebCore::Region m_dirtyRegion;

Buffer m_frontBuffer;
Buffer m_backBuffer;
Buffer m_secondaryBackBuffer;

std::optional<WebCore::IntRect> m_previouslyPaintedRect;

// FIXME: This should be removed and m_bufferHandle should be used to ref the buffer once ShareableBitmap::Handle
// can be encoded multiple times. http://webkit.org/b/234169
std::optional<MachSendRight> m_contentsBufferHandle;
std::optional<WebCore::RenderingResourceIdentifier> m_contentsRenderingResourceIdentifier;

#if ENABLE(RE_DYNAMIC_CONTENT_SCALING)
RefPtr<WebCore::ImageBuffer> m_displayListBuffer;
#endif

Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>> m_frontBufferFlushers;

WebCore::RepaintRectList m_paintingRects;
Expand Down Expand Up @@ -234,6 +219,7 @@ class RemoteLayerBackingStoreProperties {
std::optional<BufferAndBackendInfo> m_frontBufferInfo;
std::optional<BufferAndBackendInfo> m_backBufferInfo;
std::optional<BufferAndBackendInfo> m_secondaryBackBufferInfo;
std::optional<WebCore::RenderingResourceIdentifier> m_contentsRenderingResourceIdentifier;

std::optional<WebCore::IntRect> m_paintedRect;

Expand All @@ -245,7 +231,6 @@ class RemoteLayerBackingStoreProperties {
RemoteLayerBackingStore::Type m_type;
};

WTF::TextStream& operator<<(WTF::TextStream&, SwapBuffersDisplayRequirement);
WTF::TextStream& operator<<(WTF::TextStream&, BackingStoreNeedsDisplayReason);
WTF::TextStream& operator<<(WTF::TextStream&, const RemoteLayerBackingStore&);
WTF::TextStream& operator<<(WTF::TextStream&, const RemoteLayerBackingStoreProperties&);
Expand Down
214 changes: 46 additions & 168 deletions Source/WebKit/Shared/RemoteLayerTree/RemoteLayerBackingStore.mm
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,23 @@

#import "ArgumentCoders.h"
#import "DynamicContentScalingImageBufferBackend.h"
#import "GPUProcess.h"
#import "ImageBufferBackendHandleSharing.h"
#import "Logging.h"
#import "PlatformCALayerRemote.h"
#import "RemoteLayerBackingStoreCollection.h"
#import "RemoteLayerTreeContext.h"
#import "RemoteLayerTreeDrawingAreaProxy.h"
#import "RemoteLayerTreeHost.h"
#import "RemoteLayerTreeLayers.h"
#import "RemoteLayerTreeNode.h"
#import "ShareableBitmap.h"
#import "SwapBuffersDisplayRequirement.h"
#import "WebCoreArgumentCoders.h"
#import "WebPageProxy.h"
#import "WebProcess.h"
#import "WebProcessPool.h"
#import "WebProcessProxy.h"
#import <QuartzCore/QuartzCore.h>
#import <WebCore/BifurcatedGraphicsContext.h>
#import <WebCore/DynamicContentScalingTypes.h>
Expand All @@ -52,10 +58,10 @@
#import <pal/spi/cocoa/QuartzCoreSPI.h>
#import <wtf/FastMalloc.h>
#import <wtf/Noncopyable.h>
#import <wtf/Scope.h>
#import <wtf/cocoa/TypeCastsCocoa.h>
#import <wtf/text/TextStream.h>


namespace WebKit {

using namespace WebCore;
Expand Down Expand Up @@ -99,8 +105,6 @@ void flush() final

RemoteLayerBackingStore::~RemoteLayerBackingStore()
{
clearBackingStore();

if (!m_layer)
return;

Expand All @@ -122,27 +126,9 @@ void flush() final
return;

m_parameters = parameters;

if (m_frontBuffer) {
// If we have a valid backing store, we need to ensure that it gets completely
// repainted the next time display() is called.
setNeedsDisplay();
}

clearBackingStore();
}

void RemoteLayerBackingStore::clearBackingStore()
{
m_frontBuffer.discard();
m_backBuffer.discard();
m_secondaryBackBuffer.discard();
m_contentsBufferHandle = std::nullopt;
#if ENABLE(RE_DYNAMIC_CONTENT_SCALING)
m_displayListBuffer = nullptr;
#endif
}

#if !LOG_DISABLED
static bool hasValue(const ImageBufferBackendHandle& backendHandle)
{
Expand All @@ -164,13 +150,8 @@ static bool hasValue(const ImageBufferBackendHandle& backendHandle)

void RemoteLayerBackingStore::encode(IPC::Encoder& encoder) const
{
auto handleFromBuffer = [](ImageBuffer& buffer) -> std::optional<ImageBufferBackendHandle> {
auto* sharing = buffer.toBackendSharing();
if (is<ImageBufferBackendHandleSharing>(sharing))
return downcast<ImageBufferBackendHandleSharing>(*sharing).takeBackendHandle();

return std::nullopt;
};
if (auto* collection = backingStoreCollection())
collection->backingStoreWillBeEncoded(*this);

encoder << m_parameters.isOpaque;
encoder << m_parameters.type;
Expand All @@ -181,8 +162,8 @@ static bool hasValue(const ImageBufferBackendHandle& backendHandle)
if (m_contentsBufferHandle) {
ASSERT(m_parameters.type == Type::IOSurface);
handle = MachSendRight { *m_contentsBufferHandle };
} else if (RefPtr protectedBuffer = m_frontBuffer.imageBuffer)
handle = handleFromBuffer(*protectedBuffer);
} else
handle = frontBufferHandle();

// It would be nice to ASSERT(handle && hasValue(*handle)) here, but when we hit the timeout in RemoteImageBufferProxy::ensureBackendCreated(), we don't have a handle.
#if !LOG_DISABLED
Expand All @@ -192,27 +173,12 @@ static bool hasValue(const ImageBufferBackendHandle& backendHandle)

encoder << WTFMove(handle);

auto encodeBuffer = [&](const Buffer& buffer) {
if (buffer.imageBuffer) {
encoder << std::optional { BufferAndBackendInfo::fromImageBuffer(*buffer.imageBuffer) };
return;
}

encoder << std::optional<BufferAndBackendInfo>();
};

encodeBuffer(m_frontBuffer);
encodeBuffer(m_backBuffer);
encodeBuffer(m_secondaryBackBuffer);

encodeBufferAndBackendInfos(encoder);
encoder << m_contentsRenderingResourceIdentifier;
encoder << m_previouslyPaintedRect;

#if ENABLE(RE_DYNAMIC_CONTENT_SCALING)
std::optional<ImageBufferBackendHandle> displayListHandle;
if (m_displayListBuffer)
displayListHandle = handleFromBuffer(*m_displayListBuffer);

encoder << WTFMove(displayListHandle);
encoder << displayListHandle();
#endif
}

Expand All @@ -236,6 +202,9 @@ static bool hasValue(const ImageBufferBackendHandle& backendHandle)
if (!decoder.decode(result.m_secondaryBackBufferInfo))
return false;

if (!decoder.decode(result.m_contentsRenderingResourceIdentifier))
return false;

if (!decoder.decode(result.m_paintedRect))
return false;

Expand Down Expand Up @@ -326,18 +295,31 @@ static bool hasValue(const ImageBufferBackendHandle& backendHandle)
#if ENABLE(RE_DYNAMIC_CONTENT_SCALING)
// FIXME: Find a way to support partial repaint for backing store that
// includes a display list without allowing unbounded memory growth.
return m_parameters.includeDisplayList == IncludeDisplayList::No;
#else
return true;
if (m_parameters.includeDisplayList == IncludeDisplayList::Yes)
return false;
#endif

const unsigned maxSmallLayerBackingArea = 64u * 64u;
if (ImageBuffer::calculateBackendSize(m_parameters.size, m_parameters.scale).area() <= maxSmallLayerBackingArea)
return false;
return true;

}

bool RemoteLayerBackingStore::drawingRequiresClearedPixels() const
{
return !m_parameters.isOpaque && !m_layer->owner()->platformCALayerShouldPaintUsingCompositeCopy();
}

void RemoteLayerBackingStore::setDelegatedContents(const WebCore::PlatformCALayerDelegatedContents& contents)
{
m_contentsBufferHandle = MachSendRight { contents.surface };
if (contents.finishedFence)
m_frontBufferFlushers.append(DelegatedContentsFenceFlusher::create(Ref { *contents.finishedFence }));
m_contentsRenderingResourceIdentifier = contents.surfaceIdentifier;
if (contents.surfaceIdentifier)
m_contentsRenderingResourceIdentifier = *contents.surfaceIdentifier;
else
m_contentsRenderingResourceIdentifier = std::nullopt;
m_dirtyRegion = { };
m_paintingRects.clear();
}
Expand All @@ -359,11 +341,10 @@ static bool hasValue(const ImageBufferBackendHandle& backendHandle)
if (size().isEmpty())
return BackingStoreNeedsDisplayReason::None;

auto frontBuffer = bufferForType(RemoteLayerBackingStore::BufferType::Front);
if (!frontBuffer)
if (!hasFrontBuffer())
return BackingStoreNeedsDisplayReason::NoFrontBuffer;

if (frontBuffer->volatilityState() == WebCore::VolatilityState::Volatile)
if (frontBufferMayBeVolatile())
return BackingStoreNeedsDisplayReason::FrontBufferIsVolatile;

return hasEmptyDirtyRegion() ? BackingStoreNeedsDisplayReason::None : BackingStoreNeedsDisplayReason::HasDirtyRegion;
Expand Down Expand Up @@ -394,65 +375,18 @@ static bool hasValue(const ImageBufferBackendHandle& backendHandle)
}
}

void RemoteLayerBackingStore::ensureFrontBuffer()
{
if (m_frontBuffer.imageBuffer)
return;

m_frontBuffer.imageBuffer = allocateBuffer();
m_frontBuffer.isCleared = true;

#if ENABLE(RE_DYNAMIC_CONTENT_SCALING)
if (!m_displayListBuffer && m_parameters.includeDisplayList == IncludeDisplayList::Yes) {
ImageBufferCreationContext creationContext;
if (type() == RemoteLayerBackingStore::Type::IOSurface)
m_displayListBuffer = ImageBuffer::create<DynamicContentScalingAcceleratedImageBufferBackend>(m_parameters.size, m_parameters.scale, colorSpace(), pixelFormat(), RenderingPurpose::DOM, WTFMove(creationContext));
else
m_displayListBuffer = ImageBuffer::create<DynamicContentScalingImageBufferBackend>(m_parameters.size, m_parameters.scale, colorSpace(), pixelFormat(), RenderingPurpose::DOM, WTFMove(creationContext));
}
#endif
}


void RemoteLayerBackingStore::paintContents()
{
if (!m_frontBuffer.imageBuffer) {
ASSERT(m_layer->owner()->platformCALayerDelegatesDisplay(m_layer));
return;
}

LOG_WITH_STREAM(RemoteLayerBuffers, stream << "RemoteLayerBackingStore " << m_layer->layerID() << " paintContents() - has dirty region " << !hasEmptyDirtyRegion());
if (hasEmptyDirtyRegion())
return;

m_lastDisplayTime = MonotonicTime::now();

#if ENABLE(RE_DYNAMIC_CONTENT_SCALING)
if (m_parameters.includeDisplayList == IncludeDisplayList::Yes) {
auto& displayListContext = m_displayListBuffer->context();

BifurcatedGraphicsContext context(m_frontBuffer.imageBuffer->context(), displayListContext);
drawInContext(context);
return;
}
#endif

GraphicsContext& context = m_frontBuffer.imageBuffer->context();
drawInContext(context);
}

void RemoteLayerBackingStore::drawInContext(GraphicsContext& context)
{
auto markFrontBufferNotCleared = makeScopeExit([&]() {
m_frontBuffer.isCleared = false;
});
GraphicsContextStateSaver stateSaver(context);

// If we have less than webLayerMaxRectsToPaint rects to paint and they cover less
// than webLayerWastedSpaceThreshold of the total dirty area, we'll repaint each rect separately.
// Otherwise, repaint the entire bounding box of the dirty region.
IntRect dirtyBounds = m_dirtyRegion.bounds();

auto dirtyRects = m_dirtyRegion.rects();
if (dirtyRects.size() > PlatformCALayer::webLayerMaxRectsToPaint || m_dirtyRegion.totalArea() > PlatformCALayer::webLayerWastedSpaceThreshold * dirtyBounds.width() * dirtyBounds.height()) {
dirtyRects.clear();
Expand All @@ -468,34 +402,17 @@ static bool hasValue(const ImageBufferBackendHandle& backendHandle)
m_paintingRects.append(scaledRect);
}

IntRect layerBounds = this->layerBounds();
if (RefPtr imageBuffer = m_backBuffer.imageBuffer; !m_dirtyRegion.contains(layerBounds) && imageBuffer) {
if (!m_previouslyPaintedRect)
context.drawImageBuffer(*imageBuffer, { 0, 0 }, { CompositeOperator::Copy });
else {
Region copyRegion(*m_previouslyPaintedRect);
copyRegion.subtract(m_dirtyRegion);
IntRect copyRect = copyRegion.bounds();
if (!copyRect.isEmpty())
context.drawImageBuffer(*imageBuffer, copyRect, copyRect, { CompositeOperator::Copy });
}
}

if (m_paintingRects.size() == 1)
context.clip(m_paintingRects[0]);
else {
Path clipPath;
for (auto rect : m_paintingRects)
clipPath.addRect(rect);
context.clipPath(clipPath);
}
createContextAndPaintContents();
}

if (!m_parameters.isOpaque && !m_frontBuffer.isCleared && !m_layer->owner()->platformCALayerShouldPaintUsingCompositeCopy())
context.clearRect(layerBounds);
void RemoteLayerBackingStore::drawInContext(GraphicsContext& context)
{
GraphicsContextStateSaver stateSaver(context);
IntRect dirtyBounds = m_dirtyRegion.bounds();

#ifndef NDEBUG
if (m_parameters.isOpaque)
context.fillRect(layerBounds, SRGBA<uint8_t> { 255, 47, 146 });
context.fillRect(this->layerBounds(), SRGBA<uint8_t> { 255, 47, 146 });
#endif

OptionSet<WebCore::GraphicsLayerPaintBehavior> paintBehavior;
Expand Down Expand Up @@ -537,14 +454,8 @@ static bool hasValue(const ImageBufferBackendHandle& backendHandle)

m_layer->owner()->platformCALayerLayerDidDisplay(m_layer);

m_frontBuffer.imageBuffer->flushDrawingContextAsync();
m_previouslyPaintedRect = dirtyBounds;

m_frontBufferFlushers.append(m_frontBuffer.imageBuffer->createFlusher());
#if ENABLE(RE_DYNAMIC_CONTENT_SCALING)
if (m_parameters.includeDisplayList == IncludeDisplayList::Yes)
m_frontBufferFlushers.append(m_displayListBuffer->createFlusher());
#endif
m_frontBufferFlushers.appendVector(createFlushers());
}

void RemoteLayerBackingStore::enumerateRectsBeingDrawn(GraphicsContext& context, void (^block)(FloatRect))
Expand Down Expand Up @@ -598,7 +509,7 @@ static bool hasValue(const ImageBufferBackendHandle& backendHandle)

void RemoteLayerBackingStoreProperties::applyBackingStoreToLayer(CALayer *layer, LayerContentsType contentsType, std::optional<WebCore::RenderingResourceIdentifier> asyncContentsIdentifier, bool replayDynamicContentScalingDisplayListsIntoBackingStore)
{
if (asyncContentsIdentifier && m_frontBufferInfo && *asyncContentsIdentifier >= m_frontBufferInfo->resourceIdentifier)
if (asyncContentsIdentifier && m_contentsRenderingResourceIdentifier && *asyncContentsIdentifier >= m_contentsRenderingResourceIdentifier)
return;

layer.contentsOpaque = m_isOpaque;
Expand Down Expand Up @@ -696,31 +607,9 @@ static bool hasValue(const ImageBufferBackendHandle& backendHandle)
return std::exchange(m_frontBufferFlushers, { });
}

RefPtr<ImageBuffer> RemoteLayerBackingStore::bufferForType(BufferType bufferType) const
{
switch (bufferType) {
case BufferType::Front:
return m_frontBuffer.imageBuffer;
case BufferType::Back:
return m_backBuffer.imageBuffer;
case BufferType::SecondaryBack:
return m_secondaryBackBuffer.imageBuffer;
}
return nullptr;
}

void RemoteLayerBackingStore::Buffer::discard()
{
imageBuffer = nullptr;
}

TextStream& operator<<(TextStream& ts, const RemoteLayerBackingStore& backingStore)
{
ts.dumpProperty("front buffer", backingStore.bufferForType(RemoteLayerBackingStore::BufferType::Front));
ts.dumpProperty("back buffer", backingStore.bufferForType(RemoteLayerBackingStore::BufferType::Back));
ts.dumpProperty("secondaryBack buffer", backingStore.bufferForType(RemoteLayerBackingStore::BufferType::SecondaryBack));
ts.dumpProperty("is opaque", backingStore.isOpaque());

backingStore.dump(ts);
return ts;
}

Expand All @@ -730,17 +619,6 @@ static bool hasValue(const ImageBufferBackendHandle& backendHandle)
return ts;
}

TextStream& operator<<(TextStream& ts, SwapBuffersDisplayRequirement displayRequirement)
{
switch (displayRequirement) {
case SwapBuffersDisplayRequirement::NeedsFullDisplay: ts << "full display"; break;
case SwapBuffersDisplayRequirement::NeedsNormalDisplay: ts << "normal display"; break;
case SwapBuffersDisplayRequirement::NeedsNoDisplay: ts << "no display"; break;
}

return ts;
}

TextStream& operator<<(TextStream& ts, BackingStoreNeedsDisplayReason reason)
{
switch (reason) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class RemoteLayerWithRemoteRenderingBackingStore;
class RemoteLayerWithInProcessRenderingBackingStore;
class RemoteLayerTreeContext;
class RemoteLayerTreeTransaction;
class RemoteImageBufferSetProxy;

enum class SwapBuffersDisplayRequirement : uint8_t;

Expand All @@ -55,8 +56,9 @@ class RemoteLayerBackingStoreCollection : public CanMakeWeakPtr<RemoteLayerBacki
RemoteLayerBackingStoreCollection(RemoteLayerTreeContext&);
virtual ~RemoteLayerBackingStoreCollection();

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

// Return value indicates whether the backing store needs to be included in the transaction.
bool backingStoreWillBeDisplayed(RemoteLayerBackingStore&);
Expand All @@ -65,7 +67,7 @@ class RemoteLayerBackingStoreCollection : public CanMakeWeakPtr<RemoteLayerBacki
std::unique_ptr<RemoteLayerBackingStore> createRemoteLayerBackingStore(PlatformCALayerRemote*);

virtual void prepareBackingStoresForDisplay(RemoteLayerTreeTransaction&);
bool paintReachableBackingStoreContents();
virtual bool paintReachableBackingStoreContents();

void willFlushLayers();
void willBuildTransaction();
Expand All @@ -90,9 +92,9 @@ class RemoteLayerBackingStoreCollection : public CanMakeWeakPtr<RemoteLayerBacki
virtual void markBackingStoreVolatileAfterReachabilityChange(RemoteLayerBackingStore&);
virtual void markAllBackingStoreVolatileFromTimer();

bool collectRemoteRenderingBackingStoreBufferIdentifiersToMarkVolatile(RemoteLayerWithRemoteRenderingBackingStore&, OptionSet<VolatilityMarkingBehavior>, MonotonicTime now, Vector<WebCore::RenderingResourceIdentifier>&);
bool collectRemoteRenderingBackingStoreBufferIdentifiersToMarkVolatile(RemoteLayerWithRemoteRenderingBackingStore&, OptionSet<VolatilityMarkingBehavior>, MonotonicTime now, Vector<std::pair<Ref<RemoteImageBufferSetProxy>, OptionSet<BufferInSetType>>>&);

bool collectAllRemoteRenderingBufferIdentifiersToMarkVolatile(OptionSet<VolatilityMarkingBehavior> liveBackingStoreMarkingBehavior, OptionSet<VolatilityMarkingBehavior> unparentedBackingStoreMarkingBehavior, Vector<WebCore::RenderingResourceIdentifier>&);
bool collectAllRemoteRenderingBufferIdentifiersToMarkVolatile(OptionSet<VolatilityMarkingBehavior> liveBackingStoreMarkingBehavior, OptionSet<VolatilityMarkingBehavior> unparentedBackingStoreMarkingBehavior, Vector<std::pair<Ref<RemoteImageBufferSetProxy>, OptionSet<BufferInSetType>>>&);


private:
Expand All @@ -103,7 +105,7 @@ class RemoteLayerBackingStoreCollection : public CanMakeWeakPtr<RemoteLayerBacki
void volatilityTimerFired();

protected:
void sendMarkBuffersVolatile(Vector<WebCore::RenderingResourceIdentifier>&&, CompletionHandler<void(bool)>&&);
void sendMarkBuffersVolatile(Vector<std::pair<Ref<RemoteImageBufferSetProxy>, OptionSet<BufferInSetType>>>&&, CompletionHandler<void(bool)>&&);

static constexpr auto volatileBackingStoreAgeThreshold = 1_s;
static constexpr auto volatileSecondaryBackingStoreAgeThreshold = 200_ms;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#import "ImageBufferShareableMappedIOSurfaceBackend.h"
#import "Logging.h"
#import "PlatformCALayerRemote.h"
#import "RemoteImageBufferSetProxy.h"
#import "RemoteLayerBackingStore.h"
#import "RemoteLayerTreeContext.h"
#import "RemoteLayerWithInProcessRenderingBackingStore.h"
Expand Down Expand Up @@ -60,7 +61,7 @@
Vector<WeakPtr<RemoteLayerWithRemoteRenderingBackingStore>> backingStoreList;
backingStoreList.reserveInitialCapacity(m_backingStoresNeedingDisplay.computeSize());

Vector<WeakPtr<RemoteLayerWithRemoteRenderingBackingStore>> backingStoresWithNoBuffers;
auto& remoteRenderingBackend = layerTreeContext().ensureRemoteRenderingBackendProxy();

for (auto& backingStore : m_backingStoresNeedingDisplay) {
backingStore.layer()->properties().notePropertiesChanged(LayerChange::BackingStoreChanged);
Expand All @@ -70,19 +71,21 @@
if (remoteBackingStore->performDelegatedLayerDisplay())
continue;

if (remoteBackingStore->hasNoBuffers()) {
backingStoresWithNoBuffers.append(*remoteBackingStore);
auto bufferSet = remoteBackingStore->protectedBufferSet();
if (!bufferSet)
continue;
}

if (!remoteBackingStore->hasFrontBuffer() || !remoteBackingStore->supportsPartialRepaint())
remoteBackingStore->setNeedsDisplay();

remoteBackingStore->clearBackingStore();

prepareBuffersData.append({
{
remoteBackingStore->bufferForType(RemoteLayerBackingStore::BufferType::Front),
remoteBackingStore->bufferForType(RemoteLayerBackingStore::BufferType::Back),
remoteBackingStore->bufferForType(RemoteLayerBackingStore::BufferType::SecondaryBack)
},
bufferSet,
remoteBackingStore->dirtyRegion(),
remoteBackingStore->supportsPartialRepaint(),
remoteBackingStore->hasEmptyDirtyRegion(),
remoteBackingStore->drawingRequiresClearedPixels(),
});

backingStoreList.append(*remoteBackingStore);
Expand All @@ -91,20 +94,17 @@
}

if (prepareBuffersData.size()) {
auto& remoteRenderingBackend = layerTreeContext().ensureRemoteRenderingBackendProxy();
auto swapResult = remoteRenderingBackend.prepareBuffersForDisplay(WTFMove(prepareBuffersData));

RELEASE_ASSERT(swapResult.size() == backingStoreList.size());
for (unsigned i = 0; i < swapResult.size(); ++i) {
auto& backingStoreSwapResult = swapResult[i];
auto& backingStore = backingStoreList[i];
backingStore->applySwappedBuffers(WTFMove(backingStoreSwapResult.buffers.front), WTFMove(backingStoreSwapResult.buffers.back), WTFMove(backingStoreSwapResult.buffers.secondaryBack), backingStoreSwapResult.displayRequirement);
}
}

for (auto& backingStore : backingStoresWithNoBuffers) {
backingStore->applySwappedBuffers(nullptr, nullptr, nullptr, SwapBuffersDisplayRequirement::NeedsFullDisplay);
LOG_WITH_STREAM(RemoteLayerBuffers, stream << "RemoteLayerBackingStoreCollection::prepareBackingStoresForDisplay - allocated first buffers for layer " << backingStore->layer()->layerID() << " backing store " << *backingStore);
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 (backingStoreSwapResult.displayRequirement == SwapBuffersDisplayRequirement::NeedsFullDisplay)
backingStore->setNeedsDisplay();
backingStore->setBufferCacheIdentifiers(WTFMove(backingStoreSwapResult.cacheIdentifiers));
backingStore->setBackendHandle(WTFMove(backingStoreSwapResult.backendHandle));
}
});
}
}

Expand Down Expand Up @@ -272,7 +272,7 @@
void RemoteLayerBackingStoreCollection::markBackingStoreVolatileAfterReachabilityChange(RemoteLayerBackingStore& backingStore)
{
if (auto* remoteBackingStore = dynamicDowncast<RemoteLayerWithRemoteRenderingBackingStore>(&backingStore)) {
Vector<WebCore::RenderingResourceIdentifier> identifiers;
Vector<std::pair<Ref<RemoteImageBufferSetProxy>, OptionSet<BufferInSetType>>> identifiers;
collectRemoteRenderingBackingStoreBufferIdentifiersToMarkVolatile(*remoteBackingStore, { }, { }, identifiers);

if (identifiers.isEmpty())
Expand Down Expand Up @@ -311,7 +311,7 @@
{
bool successfullyMadeBackingStoreVolatile = markAllBackingStoreVolatile(VolatilityMarkingBehavior::IgnoreReachability, VolatilityMarkingBehavior::IgnoreReachability);

Vector<WebCore::RenderingResourceIdentifier> identifiers;
Vector<std::pair<Ref<RemoteImageBufferSetProxy>, OptionSet<BufferInSetType>>> identifiers;
bool collectedAllRemoteRenderingBuffers = collectAllRemoteRenderingBufferIdentifiersToMarkVolatile(VolatilityMarkingBehavior::IgnoreReachability, VolatilityMarkingBehavior::IgnoreReachability, identifiers);

LOG_WITH_STREAM(RemoteLayerBuffers, stream << "RemoteLayerBackingStoreCollection::tryMarkAllBackingStoreVolatile pid " << getpid() << " - live " << m_liveBackingStore.computeSize() << ", unparented " << m_unparentedBackingStore.computeSize() << " " << identifiers);
Expand All @@ -332,7 +332,7 @@
bool successfullyMadeBackingStoreVolatile = markAllBackingStoreVolatile(VolatilityMarkingBehavior::ConsiderTimeSinceLastDisplay, { });
LOG_WITH_STREAM(RemoteLayerBuffers, stream << "RemoteLayerBackingStoreCollection::markAllBackingStoreVolatileFromTimer() - live " << m_liveBackingStore.computeSize() << ", unparented " << m_unparentedBackingStore.computeSize() << "; successfullyMadeBackingStoreVolatile " << successfullyMadeBackingStoreVolatile);

Vector<WebCore::RenderingResourceIdentifier> identifiers;
Vector<std::pair<Ref<RemoteImageBufferSetProxy>, OptionSet<BufferInSetType>>> identifiers;
bool collectedAllRemoteRenderingBuffers = collectAllRemoteRenderingBufferIdentifiersToMarkVolatile(VolatilityMarkingBehavior::ConsiderTimeSinceLastDisplay, { }, identifiers);

LOG_WITH_STREAM(RemoteLayerBuffers, stream << "RemoteLayerBackingStoreCollection::markAllBackingStoreVolatileFromTimer pid " << getpid() << " - live " << m_liveBackingStore.computeSize() << ", unparented " << m_unparentedBackingStore.computeSize() << ", " << identifiers.size() << " buffers to set volatile: " << identifiers);
Expand Down Expand Up @@ -379,46 +379,34 @@
}
}

bool RemoteLayerBackingStoreCollection::collectRemoteRenderingBackingStoreBufferIdentifiersToMarkVolatile(RemoteLayerWithRemoteRenderingBackingStore& backingStore, OptionSet<VolatilityMarkingBehavior> markingBehavior, MonotonicTime now, Vector<WebCore::RenderingResourceIdentifier>& identifiers)
bool RemoteLayerBackingStoreCollection::collectRemoteRenderingBackingStoreBufferIdentifiersToMarkVolatile(RemoteLayerWithRemoteRenderingBackingStore& backingStore, OptionSet<VolatilityMarkingBehavior> markingBehavior, MonotonicTime now, Vector<std::pair<Ref<RemoteImageBufferSetProxy>, OptionSet<BufferInSetType>>>& identifiers)
{
ASSERT(!m_inLayerFlush);

auto collectBuffer = [&](RemoteLayerBackingStore::BufferType bufferType) {
auto buffer = backingStore.bufferForType(bufferType);
if (!buffer)
return;

if (buffer->volatilityState() != WebCore::VolatilityState::NonVolatile)
return;

// Clearing the backend handle in the Web Content process is necessary to have the surface in-use count drop to zero.
auto* sharing = buffer->toBackendSharing();
if (is<ImageBufferBackendHandleSharing>(sharing))
downcast<ImageBufferBackendHandleSharing>(*sharing).clearBackendHandle();

identifiers.append(buffer->renderingResourceIdentifier());
};
auto bufferSet = backingStore.protectedBufferSet();
if (!bufferSet)
return true;

if (markingBehavior.contains(VolatilityMarkingBehavior::ConsiderTimeSinceLastDisplay)) {
auto timeSinceLastDisplay = now - backingStore.lastDisplayTime();
if (timeSinceLastDisplay < volatileBackingStoreAgeThreshold) {
if (timeSinceLastDisplay >= volatileSecondaryBackingStoreAgeThreshold)
collectBuffer(RemoteLayerBackingStore::BufferType::SecondaryBack);

if (timeSinceLastDisplay >= volatileSecondaryBackingStoreAgeThreshold && !bufferSet->confirmedVolatility().contains(BufferInSetType::SecondaryBack))
identifiers.append(std::make_pair(Ref { *bufferSet }, BufferInSetType::SecondaryBack));
return false;
}
}

collectBuffer(RemoteLayerBackingStore::BufferType::SecondaryBack);
collectBuffer(RemoteLayerBackingStore::BufferType::Back);
OptionSet<BufferInSetType> bufferTypes { BufferInSetType::Back, BufferInSetType::SecondaryBack };

if (!m_reachableBackingStoreInLatestFlush.contains(backingStore) || markingBehavior.contains(VolatilityMarkingBehavior::IgnoreReachability))
collectBuffer(RemoteLayerBackingStore::BufferType::Front);
bufferTypes.add(BufferInSetType::Front);

if (!(bufferTypes - bufferSet->confirmedVolatility()).isEmpty())
identifiers.append(std::make_pair(Ref { *bufferSet }, bufferTypes));

return true;
}

bool RemoteLayerBackingStoreCollection::collectAllRemoteRenderingBufferIdentifiersToMarkVolatile(OptionSet<VolatilityMarkingBehavior> liveBackingStoreMarkingBehavior, OptionSet<VolatilityMarkingBehavior> unparentedBackingStoreMarkingBehavior, Vector<WebCore::RenderingResourceIdentifier>& identifiers)
bool RemoteLayerBackingStoreCollection::collectAllRemoteRenderingBufferIdentifiersToMarkVolatile(OptionSet<VolatilityMarkingBehavior> liveBackingStoreMarkingBehavior, OptionSet<VolatilityMarkingBehavior> unparentedBackingStoreMarkingBehavior, Vector<std::pair<Ref<RemoteImageBufferSetProxy>, OptionSet<BufferInSetType>>>& identifiers)
{
bool completed = true;
auto now = MonotonicTime::now();
Expand All @@ -437,7 +425,7 @@
}


void RemoteLayerBackingStoreCollection::sendMarkBuffersVolatile(Vector<WebCore::RenderingResourceIdentifier>&& identifiers, CompletionHandler<void(bool)>&& completionHandler)
void RemoteLayerBackingStoreCollection::sendMarkBuffersVolatile(Vector<std::pair<Ref<RemoteImageBufferSetProxy>, OptionSet<BufferInSetType>>>&& identifiers, CompletionHandler<void(bool)>&& completionHandler)
{
auto& remoteRenderingBackend = m_layerTreeContext.ensureRemoteRenderingBackendProxy();

Expand All @@ -447,5 +435,10 @@
});
}

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


} // namespace WebKit
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,55 @@ class RemoteLayerWithInProcessRenderingBackingStore : public RemoteLayerBackingS
bool isRemoteLayerWithInProcessRenderingBackingStore() const final { return true; }

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

RefPtr<WebCore::ImageBuffer> allocateBuffer() const final;
void clearBackingStore() final;

bool setBufferVolatile(BufferType);

std::optional<ImageBufferBackendHandle> frontBufferHandle() const final;
#if ENABLE(RE_DYNAMIC_CONTENT_SCALING)
std::optional<ImageBufferBackendHandle> displayListHandle() const final;
#endif
void encodeBufferAndBackendInfos(IPC::Encoder&) const final;

void dump(WTF::TextStream&) const final;

private:
RefPtr<WebCore::ImageBuffer> allocateBuffer() const;
SwapBuffersDisplayRequirement prepareBuffers();
WebCore::SetNonVolatileResult swapToValidFrontBuffer();

void ensureFrontBuffer();
bool hasFrontBuffer() const final;
bool frontBufferMayBeVolatile() const final;

struct Buffer {
RefPtr<WebCore::ImageBuffer> imageBuffer;
bool isCleared { false };

explicit operator bool() const
{
return !!imageBuffer;
}

void discard();
};

// Returns true if it was able to fulfill the request. This can fail when trying to mark an in-use surface as volatile.
bool setBufferVolatile(Buffer&);

WebCore::SetNonVolatileResult setBufferNonVolatile(Buffer&);
WebCore::SetNonVolatileResult setFrontBufferNonVolatile();

Buffer m_frontBuffer;
Buffer m_backBuffer;
Buffer m_secondaryBackBuffer;

#if ENABLE(RE_DYNAMIC_CONTENT_SCALING)
RefPtr<WebCore::ImageBuffer> m_displayListBuffer;
#endif
};

} // namespace WebKit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,139 @@
#import "RemoteLayerTreeContext.h"
#import "SwapBuffersDisplayRequirement.h"
#import <WebCore/IOSurfacePool.h>
#import <WebCore/PlatformCALayerClient.h>
#import <wtf/Scope.h>

namespace WebKit {

using namespace WebCore;

void RemoteLayerWithInProcessRenderingBackingStore::Buffer::discard()
{
imageBuffer = nullptr;
}

bool RemoteLayerWithInProcessRenderingBackingStore::hasFrontBuffer() const
{
return m_contentsBufferHandle || !!m_frontBuffer.imageBuffer;
}

bool RemoteLayerWithInProcessRenderingBackingStore::frontBufferMayBeVolatile() const
{
if (!m_frontBuffer)
return false;
return m_frontBuffer.imageBuffer->volatilityState() == WebCore::VolatilityState::Volatile;
}


void RemoteLayerWithInProcessRenderingBackingStore::clearBackingStore()
{
m_frontBuffer.discard();
m_backBuffer.discard();
m_secondaryBackBuffer.discard();
m_contentsBufferHandle = std::nullopt;
#if ENABLE(RE_DYNAMIC_CONTENT_SCALING)
m_displayListBuffer = nullptr;
#endif
}

static std::optional<ImageBufferBackendHandle> handleFromBuffer(ImageBuffer& buffer)
{
auto* sharing = buffer.toBackendSharing();
if (is<ImageBufferBackendHandleSharing>(sharing))
return downcast<ImageBufferBackendHandleSharing>(*sharing).takeBackendHandle();

return std::nullopt;
}

std::optional<ImageBufferBackendHandle> RemoteLayerWithInProcessRenderingBackingStore::frontBufferHandle() const
{
if (RefPtr protectedBuffer = m_frontBuffer.imageBuffer)
return handleFromBuffer(*protectedBuffer);
return std::nullopt;
}

#if ENABLE(RE_DYNAMIC_CONTENT_SCALING)
std::optional<ImageBufferBackendHandle> RemoteLayerWithInProcessRenderingBackingStore::displayListHandle() const
{
if (m_displayListBuffer)
return handleFromBuffer(*m_displayListBuffer);
return std::nullopt;
}
#endif

void RemoteLayerWithInProcessRenderingBackingStore::createContextAndPaintContents()
{
if (!m_frontBuffer.imageBuffer) {
ASSERT(m_layer->owner()->platformCALayerDelegatesDisplay(m_layer));
return;
}

auto markFrontBufferNotCleared = makeScopeExit([&]() {
m_frontBuffer.isCleared = false;
});

auto clipAndDrawInContext = [&](GraphicsContext& context) {
if (m_paintingRects.size() == 1)
context.clip(m_paintingRects[0]);
else {
Path clipPath;
for (auto rect : m_paintingRects)
clipPath.addRect(rect);
context.clipPath(clipPath);
}

if (drawingRequiresClearedPixels() && !m_frontBuffer.isCleared)
context.clearRect(layerBounds());

drawInContext(context);
};

#if ENABLE(RE_DYNAMIC_CONTENT_SCALING)
if (m_parameters.includeDisplayList == IncludeDisplayList::Yes) {
auto& displayListContext = m_displayListBuffer->context();

BifurcatedGraphicsContext context(m_frontBuffer.imageBuffer->context(), displayListContext);
clipAndDrawInContext(context);
return;
}
#endif

GraphicsContext& context = m_frontBuffer.imageBuffer->context();

// We never need to copy forward when using display list drawing, since we don't do partial repaint.
// FIXME: Copy forward logic is duplicated in RemoteImageBufferSet, find a good place to share.
if (RefPtr imageBuffer = m_backBuffer.imageBuffer; !m_dirtyRegion.contains(layerBounds()) && imageBuffer) {
if (!m_previouslyPaintedRect)
context.drawImageBuffer(*imageBuffer, { 0, 0 }, { CompositeOperator::Copy });
else {
Region copyRegion(*m_previouslyPaintedRect);
copyRegion.subtract(m_dirtyRegion);
IntRect copyRect = copyRegion.bounds();
if (!copyRect.isEmpty())
context.drawImageBuffer(*imageBuffer, copyRect, copyRect, { CompositeOperator::Copy });
}
}

clipAndDrawInContext(context);
}

Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>> RemoteLayerWithInProcessRenderingBackingStore::createFlushers()
{
Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>> flushers;

m_frontBuffer.imageBuffer->flushDrawingContextAsync();
flushers.append(m_frontBuffer.imageBuffer->createFlusher());

#if ENABLE(RE_DYNAMIC_CONTENT_SCALING)
if (m_parameters.includeDisplayList == IncludeDisplayList::Yes)
flushers.append(m_displayListBuffer->createFlusher());
#endif

return flushers;
}


SwapBuffersDisplayRequirement RemoteLayerWithInProcessRenderingBackingStore::prepareBuffers()
{
m_contentsBufferHandle = std::nullopt;
Expand Down Expand Up @@ -124,6 +252,25 @@
}
}

void RemoteLayerWithInProcessRenderingBackingStore::ensureFrontBuffer()
{
if (m_frontBuffer.imageBuffer)
return;

m_frontBuffer.imageBuffer = allocateBuffer();
m_frontBuffer.isCleared = true;

#if ENABLE(RE_DYNAMIC_CONTENT_SCALING)
if (!m_displayListBuffer && m_parameters.includeDisplayList == IncludeDisplayList::Yes) {
ImageBufferCreationContext creationContext;
if (type() == RemoteLayerBackingStore::Type::IOSurface)
m_displayListBuffer = ImageBuffer::create<DynamicContentScalingAcceleratedImageBufferBackend>(m_parameters.size, m_parameters.scale, colorSpace(), pixelFormat(), RenderingPurpose::DOM, WTFMove(creationContext));
else
m_displayListBuffer = ImageBuffer::create<DynamicContentScalingImageBufferBackend>(m_parameters.size, m_parameters.scale, colorSpace(), pixelFormat(), RenderingPurpose::DOM, WTFMove(creationContext));
}
#endif
}

void RemoteLayerWithInProcessRenderingBackingStore::prepareToDisplay()
{
ASSERT(!m_frontBufferFlushers.size());
Expand Down Expand Up @@ -179,4 +326,28 @@
return setBufferNonVolatile(m_frontBuffer);
}

void RemoteLayerWithInProcessRenderingBackingStore::encodeBufferAndBackendInfos(IPC::Encoder& encoder) const
{
auto encodeBuffer = [&](const Buffer& buffer) {
if (buffer.imageBuffer) {
encoder << std::optional { BufferAndBackendInfo::fromImageBuffer(*buffer.imageBuffer) };
return;
}

encoder << std::optional<BufferAndBackendInfo>();
};

encodeBuffer(m_frontBuffer);
encodeBuffer(m_backBuffer);
encodeBuffer(m_secondaryBackBuffer);
}

void RemoteLayerWithInProcessRenderingBackingStore::dump(WTF::TextStream& ts) const
{
ts.dumpProperty("front buffer", m_frontBuffer.imageBuffer);
ts.dumpProperty("back buffer", m_backBuffer.imageBuffer);
ts.dumpProperty("secondaryBack buffer", m_secondaryBackBuffer.imageBuffer);
ts.dumpProperty("is opaque", isOpaque());
}

} // namespace WebKit
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,42 @@

namespace WebKit {

class RemoteDisplayListRecorderProxy;

class RemoteLayerWithRemoteRenderingBackingStore : public RemoteLayerBackingStore {
public:
using RemoteLayerBackingStore::RemoteLayerBackingStore;
RemoteLayerWithRemoteRenderingBackingStore(PlatformCALayerRemote*);

bool isRemoteLayerWithRemoteRenderingBackingStore() const final { return true; }

void applySwappedBuffers(RefPtr<WebCore::ImageBuffer>&& front, RefPtr<WebCore::ImageBuffer>&& back, RefPtr<WebCore::ImageBuffer>&& secondaryBack, SwapBuffersDisplayRequirement);
void clearBackingStore() final;
void createContextAndPaintContents() final;

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

Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>> createFlushers() final;
std::optional<ImageBufferBackendHandle> frontBufferHandle() const final { return std::exchange(const_cast<RemoteLayerWithRemoteRenderingBackingStore*>(this)->m_backendHandle, std::nullopt); }
void encodeBufferAndBackendInfos(IPC::Encoder&) const final;

void ensureBackingStore(const Parameters&) final;
bool hasFrontBuffer() const final;
bool frontBufferMayBeVolatile() const final;

void setBufferCacheIdentifiers(BufferIdentifierSet&& identifiers)
{
m_bufferCacheIdentifiers = WTFMove(identifiers);
}
void setBackendHandle(std::optional<ImageBufferBackendHandle>&& backendHandle)
{
m_backendHandle = WTFMove(backendHandle);
}

RefPtr<WebCore::ImageBuffer> allocateBuffer() const final;
void dump(WTF::TextStream&) const final;
private:
RefPtr<RemoteImageBufferSetProxy> m_bufferSet;
BufferIdentifierSet m_bufferCacheIdentifiers;
std::optional<ImageBufferBackendHandle> m_backendHandle;
bool m_cleared { true };
};

} // namespace WebKit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,49 +26,101 @@
#import "config.h"
#import "RemoteLayerWithRemoteRenderingBackingStore.h"

#import "RemoteImageBufferSetProxy.h"
#import "RemoteLayerBackingStoreCollection.h"
#import "RemoteLayerTreeContext.h"
#import "RemoteRenderingBackendProxy.h"
#import "SwapBuffersDisplayRequirement.h"
#import <WebCore/PlatformCALayerClient.h>

namespace WebKit {

using namespace WebCore;

// Called after buffer swapping in the GPU process.
void RemoteLayerWithRemoteRenderingBackingStore::applySwappedBuffers(RefPtr<ImageBuffer>&& front, RefPtr<ImageBuffer>&& back, RefPtr<ImageBuffer>&& secondaryBack, SwapBuffersDisplayRequirement displayRequirement)
RemoteLayerWithRemoteRenderingBackingStore::RemoteLayerWithRemoteRenderingBackingStore(PlatformCALayerRemote* layer)
: RemoteLayerBackingStore(layer)
{
auto* collection = backingStoreCollection();
if (!collection) {
ASSERT_NOT_REACHED();
return;
}

m_bufferSet = collection->layerTreeContext().ensureRemoteRenderingBackendProxy().createRemoteImageBufferSet();
}

bool RemoteLayerWithRemoteRenderingBackingStore::hasFrontBuffer() const
{
return m_contentsBufferHandle || !m_cleared;
}

bool RemoteLayerWithRemoteRenderingBackingStore::frontBufferMayBeVolatile() const
{
if (!m_bufferSet)
return false;
return m_bufferSet->requestedVolatility().contains(BufferInSetType::Front);
}

void RemoteLayerWithRemoteRenderingBackingStore::clearBackingStore()
{
m_contentsBufferHandle = std::nullopt;
m_cleared = true;
}

if (front != m_backBuffer.imageBuffer || back != m_frontBuffer.imageBuffer || displayRequirement != SwapBuffersDisplayRequirement::NeedsNormalDisplay)
m_previouslyPaintedRect = std::nullopt;
Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>> RemoteLayerWithRemoteRenderingBackingStore::createFlushers()
{
if (!m_bufferSet)
return { };
return Vector<std::unique_ptr<WebCore::ThreadSafeImageBufferFlusher>>::from(m_bufferSet->flushFrontBufferAsync());
}

m_frontBuffer.imageBuffer = WTFMove(front);
m_backBuffer.imageBuffer = WTFMove(back);
m_secondaryBackBuffer.imageBuffer = WTFMove(secondaryBack);
void RemoteLayerWithRemoteRenderingBackingStore::createContextAndPaintContents()
{
auto bufferSet = protectedBufferSet();
if (!bufferSet)
return;

if (displayRequirement == SwapBuffersDisplayRequirement::NeedsNoDisplay)
if (!bufferSet->hasContext()) {
ASSERT(m_layer->owner()->platformCALayerDelegatesDisplay(m_layer));
return;
}

if (displayRequirement == SwapBuffersDisplayRequirement::NeedsFullDisplay)
setNeedsDisplay();
drawInContext(bufferSet->context());
m_cleared = false;
}

void RemoteLayerWithRemoteRenderingBackingStore::ensureBackingStore(const Parameters& parameters)
{
if (m_parameters == parameters)
return;

dirtyRepaintCounterIfNecessary();
ensureFrontBuffer();
m_parameters = parameters;
clearBackingStore();
if (m_bufferSet)
m_bufferSet->setConfiguration(size(), scale(), colorSpace(), pixelFormat(), type() == RemoteLayerBackingStore::Type::IOSurface ? RenderingMode::Accelerated : RenderingMode::Unaccelerated);
}

RefPtr<WebCore::ImageBuffer> RemoteLayerWithRemoteRenderingBackingStore::allocateBuffer() const
void RemoteLayerWithRemoteRenderingBackingStore::encodeBufferAndBackendInfos(IPC::Encoder& encoder) const
{
auto* collection = backingStoreCollection();
if (!collection) {
ASSERT_NOT_REACHED();
return nullptr;
}
auto encodeBuffer = [&](const std::optional<WebCore::RenderingResourceIdentifier>& bufferIdentifier) {
if (bufferIdentifier) {
encoder << std::optional { BufferAndBackendInfo { *bufferIdentifier, m_bufferSet->generation() } };
return;
}

OptionSet<WebCore::ImageBufferOptions> options;
if (type() == RemoteLayerBackingStore::Type::IOSurface)
options.add(WebCore::ImageBufferOptions::Accelerated);
return collection->layerTreeContext().ensureRemoteRenderingBackendProxy().createImageBuffer(size(), WebCore::RenderingPurpose::LayerBacking, scale(), colorSpace(), pixelFormat(), options);
encoder << std::optional<BufferAndBackendInfo>();
};

encodeBuffer(m_bufferCacheIdentifiers.front);
encodeBuffer(m_bufferCacheIdentifiers.back);
encodeBuffer(m_bufferCacheIdentifiers.secondaryBack);
}

void RemoteLayerWithRemoteRenderingBackingStore::dump(WTF::TextStream& ts) const
{
ts.dumpProperty("buffer set", m_bufferSet);
ts.dumpProperty("cache identifiers", m_bufferCacheIdentifiers);
ts.dumpProperty("is opaque", isOpaque());
}

} // namespace WebKit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@

#pragma once

namespace WTF {
class TextStream;
}

namespace WebKit {

enum class SwapBuffersDisplayRequirement : uint8_t {
Expand All @@ -33,4 +37,6 @@ enum class SwapBuffersDisplayRequirement : uint8_t {
NeedsNoDisplay
};

WTF::TextStream& operator<<(WTF::TextStream&, SwapBuffersDisplayRequirement);

} // namespace WebKit
1 change: 1 addition & 0 deletions Source/WebKit/Shared/WTFArgumentCoders.serialization.in
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ template: struct WebKit::NetworkResourceLoadIdentifierType
template: struct WebKit::PDFPluginIdentifierType
template: struct WebKit::PageGroupIdentifierType
template: struct WebKit::RemoteAudioDestinationIdentifierType
template: struct WebKit::RemoteImageBufferSetIdentifierType
template: struct WebKit::TapIdentifierType
template: struct WebKit::TextCheckerRequestType
template: struct WebKit::UserContentControllerIdentifierType
Expand Down
6 changes: 3 additions & 3 deletions Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in
Original file line number Diff line number Diff line change
Expand Up @@ -5544,17 +5544,17 @@ struct WebCore::InteractionRegion {
OptionSet<WebCore::InteractionRegion::CornerMask> maskedCorners;
};

[Nested] struct WebCore::Region::Span {
[Nested, AdditionalEncoder=StreamConnectionEncoder] struct WebCore::Region::Span {
int y;
size_t segmentIndex;
};

[Nested] class WebCore::Region::Shape {
[Nested, AdditionalEncoder=StreamConnectionEncoder] class WebCore::Region::Shape {
Vector<int, 32> m_segments;
Vector<WebCore::Region::Span, 16> m_spans;
};

class WebCore::Region {
[AdditionalEncoder=StreamConnectionEncoder] class WebCore::Region {
WebCore::IntRect bounds();
std::unique_ptr<WebCore::Region::Shape> copyShape();
}
Expand Down
2 changes: 2 additions & 0 deletions Source/WebKit/Sources.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ GPUProcess/graphics/ImageBufferShareableAllocator.cpp
GPUProcess/graphics/RemoteDisplayListRecorder.cpp
GPUProcess/graphics/RemoteGraphicsContextGL.cpp
GPUProcess/graphics/RemoteImageBuffer.cpp
GPUProcess/graphics/RemoteImageBufferSet.cpp
GPUProcess/graphics/RemoteRenderingBackend.cpp
GPUProcess/graphics/RemoteResourceCache.cpp
GPUProcess/graphics/ScopedRenderingResourcesRequest.cpp
Expand Down Expand Up @@ -718,6 +719,7 @@ WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.cpp
WebProcess/GPU/graphics/RemoteDisplayListRecorderProxy.cpp
WebProcess/GPU/graphics/RemoteImageBufferProxy.cpp
WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp
WebProcess/GPU/graphics/RemoteImageBufferSetProxy.cpp
WebProcess/GPU/graphics/RemoteResourceCacheProxy.cpp
WebProcess/GPU/media/AudioTrackPrivateRemote.cpp
WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp
Expand Down
1 change: 1 addition & 0 deletions Source/WebKit/SourcesCocoa.txt
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,7 @@ RemoteMediaSessionCoordinatorMessageReceiver.cpp
RemoteMediaSessionCoordinatorProxyMessageReceiver.cpp
RemoteImageBufferMessageReceiver.cpp
RemoteImageBufferProxyMessageReceiver.cpp
RemoteImageBufferSetMessageReceiver.cpp
RemoteRenderingBackendMessageReceiver.cpp
RemoteRenderingBackendProxyMessageReceiver.cpp
RemoteSampleBufferDisplayLayerManagerMessageReceiver.cpp
Expand Down
28 changes: 22 additions & 6 deletions Source/WebKit/WebKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1054,7 +1054,6 @@
461E1BF2279A0116006AF53B /* WebSharedWorkerContextManagerConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 461E1BEF279A010F006AF53B /* WebSharedWorkerContextManagerConnection.h */; };
462CD80C28204DFA00F0EA04 /* MarkSurfacesAsVolatileRequestIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 462CD80B28204DF100F0EA04 /* MarkSurfacesAsVolatileRequestIdentifier.h */; };
46301002298477B100715DB1 /* WKWebGeolocationPolicyDecider.h in Headers */ = {isa = PBXBuildFile; fileRef = 463010012984778C00715DB1 /* WKWebGeolocationPolicyDecider.h */; };
463A074B2AFD8C7200CA8DBE /* BufferAndBackendInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 463A074A2AFD8C6600CA8DBE /* BufferAndBackendInfo.h */; };
463FD4801EB9459600A2982C /* WKProcessTerminationReason.h in Headers */ = {isa = PBXBuildFile; fileRef = 463FD47F1EB9458400A2982C /* WKProcessTerminationReason.h */; settings = {ATTRIBUTES = (Private, ); }; };
463FD4821EB94EC000A2982C /* ProcessTerminationReason.h in Headers */ = {isa = PBXBuildFile; fileRef = 463FD4811EB94EAD00A2982C /* ProcessTerminationReason.h */; };
4656F7BD27ACAA8D00CB3D7C /* WebSharedWorker.h in Headers */ = {isa = PBXBuildFile; fileRef = 4656F7BC27ACAA8100CB3D7C /* WebSharedWorker.h */; };
Expand Down Expand Up @@ -1893,8 +1892,10 @@
A5EC6AD42151BD7B00677D17 /* WebPageDebuggable.h in Headers */ = {isa = PBXBuildFile; fileRef = A5EC6AD32151BD6900677D17 /* WebPageDebuggable.h */; };
A5EFD38C16B0E88C00B2F0E8 /* WKPageVisibilityTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = A5EFD38B16B0E88C00B2F0E8 /* WKPageVisibilityTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
A73E66BD2AB107C3005FC327 /* IPCEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = A73E66BC2AB107BB005FC327 /* IPCEvent.h */; };
A78A5FE42B0EB39E005036D3 /* RemoteImageBufferSetIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = A78A5FE32B0EB39E005036D3 /* RemoteImageBufferSetIdentifier.h */; };
A7A3D555289395E2008D683D /* WebWorkerClient.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A3D553289395E2008D683D /* WebWorkerClient.h */; };
A7D792D81767CCA300881CBE /* ActivityAssertion.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D792D41767CB0900881CBE /* ActivityAssertion.h */; };
A7E69BCC2B2117A100D43D3F /* BufferAndBackendInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = A7E69BCB2B21179600D43D3F /* BufferAndBackendInfo.h */; };
A7F35F5C2B194C0800E43D98 /* RemoteLayerWithRemoteRenderingBackingStore.h in Headers */ = {isa = PBXBuildFile; fileRef = A7F35F5B2B194C0800E43D98 /* RemoteLayerWithRemoteRenderingBackingStore.h */; };
A7F35F5F2B1959C000E43D98 /* RemoteLayerWithInProcessRenderingBackingStore.h in Headers */ = {isa = PBXBuildFile; fileRef = A7F35F5E2B1959B300E43D98 /* RemoteLayerWithInProcessRenderingBackingStore.h */; };
AAB145E6223F931200E489D8 /* PrefetchCache.h in Headers */ = {isa = PBXBuildFile; fileRef = AAB145E4223F931200E489D8 /* PrefetchCache.h */; };
Expand Down Expand Up @@ -5036,8 +5037,6 @@
463236852314833F00A48FA7 /* UIRemoteObjectRegistry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UIRemoteObjectRegistry.h; sourceTree = "<group>"; };
463236862314833F00A48FA7 /* UIRemoteObjectRegistry.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = UIRemoteObjectRegistry.cpp; sourceTree = "<group>"; };
463473B623561D2A00BE1A84 /* WebBackForwardCacheEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebBackForwardCacheEntry.cpp; sourceTree = "<group>"; };
463A07492AFD8C6600CA8DBE /* BufferAndBackendInfo.serialization.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = BufferAndBackendInfo.serialization.in; sourceTree = "<group>"; };
463A074A2AFD8C6600CA8DBE /* BufferAndBackendInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BufferAndBackendInfo.h; sourceTree = "<group>"; };
463FD47F1EB9458400A2982C /* WKProcessTerminationReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKProcessTerminationReason.h; sourceTree = "<group>"; };
463FD4811EB94EAD00A2982C /* ProcessTerminationReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessTerminationReason.h; sourceTree = "<group>"; };
46411E3D2AFDA94400CC00E4 /* WebCompiledContentRuleListData.serialization.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = WebCompiledContentRuleListData.serialization.in; sourceTree = "<group>"; };
Expand Down Expand Up @@ -6773,11 +6772,20 @@
A72D5D7F1236CBA800A88B15 /* APISerializedScriptValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APISerializedScriptValue.h; sourceTree = "<group>"; };
A73E66BC2AB107BB005FC327 /* IPCEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IPCEvent.h; sourceTree = "<group>"; };
A73E66BE2AB10958005FC327 /* IPCEventDarwin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IPCEventDarwin.cpp; sourceTree = "<group>"; };
A78A5FE32B0EB39E005036D3 /* RemoteImageBufferSetIdentifier.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteImageBufferSetIdentifier.h; sourceTree = "<group>"; };
A78A5FE52B0EE4C3005036D3 /* RemoteImageBufferSetProxy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RemoteImageBufferSetProxy.cpp; sourceTree = "<group>"; };
A78A5FE62B0EE4C3005036D3 /* RemoteImageBufferSetProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteImageBufferSetProxy.h; sourceTree = "<group>"; };
A78A5FE92B0EE849005036D3 /* RemoteImageBufferSet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteImageBufferSet.h; sourceTree = "<group>"; };
A78A5FEA2B0EE939005036D3 /* RemoteImageBufferSet.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RemoteImageBufferSet.cpp; sourceTree = "<group>"; };
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>"; };
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>"; };
A7E1503B2B1D6F500000E921 /* RemoteImageBufferSet.messages.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = RemoteImageBufferSet.messages.in; sourceTree = "<group>"; };
A7E69BCB2B21179600D43D3F /* BufferAndBackendInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BufferAndBackendInfo.h; sourceTree = "<group>"; };
A7E69BCD2B21196700D43D3F /* BufferAndBackendInfo.serialization.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = BufferAndBackendInfo.serialization.in; sourceTree = "<group>"; };
A7E93CEB192531AA00A1DC48 /* AuxiliaryProcessIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AuxiliaryProcessIOS.mm; path = ios/AuxiliaryProcessIOS.mm; sourceTree = "<group>"; };
A7F35F5A2B194BF100E43D98 /* RemoteLayerWithRemoteRenderingBackingStore.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RemoteLayerWithRemoteRenderingBackingStore.mm; sourceTree = "<group>"; };
A7F35F5B2B194C0800E43D98 /* RemoteLayerWithRemoteRenderingBackingStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteLayerWithRemoteRenderingBackingStore.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -8626,6 +8634,7 @@
517B5F94275EBA62002DC22D /* PushMessageForTesting.h */,
514899722AB4BCFC00943741 /* PushMessageForTesting.serialization.in */,
9B1229D023FF2A5E008CA751 /* RemoteAudioDestinationIdentifier.h */,
A78A5FE32B0EB39E005036D3 /* RemoteImageBufferSetIdentifier.h */,
5C80B3DB23690D8D0086E6DE /* RemoteWorkerInitializationData.h */,
F488B90F2ACFC67A00792C16 /* RemoteWorkerInitializationData.serialization.in */,
4691CB9A27B2DD1800B29AAF /* RemoteWorkerType.h */,
Expand Down Expand Up @@ -9894,8 +9903,8 @@
2D2E04761F5BEC4F00BB25ED /* RemoteLayerTree */ = {
isa = PBXGroup;
children = (
463A074A2AFD8C6600CA8DBE /* BufferAndBackendInfo.h */,
463A07492AFD8C6600CA8DBE /* BufferAndBackendInfo.serialization.in */,
A7E69BCB2B21179600D43D3F /* BufferAndBackendInfo.h */,
A7E69BCD2B21196700D43D3F /* BufferAndBackendInfo.serialization.in */,
2D478B90288F333500F3B73A /* DynamicContentScalingDisplayList.cpp */,
2D478B8F288F333500F3B73A /* DynamicContentScalingDisplayList.h */,
BCE579A42634836700F5C5E9 /* DynamicContentScalingImageBufferBackend.h */,
Expand Down Expand Up @@ -11751,6 +11760,8 @@
72440D3A287CF58900FADBC4 /* RemoteImageBufferProxy.cpp */,
727A7F492408AEE6004D2931 /* RemoteImageBufferProxy.h */,
7BE66B942A388C200059B6F2 /* RemoteImageBufferProxy.messages.in */,
A78A5FE52B0EE4C3005036D3 /* RemoteImageBufferSetProxy.cpp */,
A78A5FE62B0EE4C3005036D3 /* RemoteImageBufferSetProxy.h */,
5506409D2407160900AAE045 /* RemoteRenderingBackendProxy.cpp */,
5506409E2407160900AAE045 /* RemoteRenderingBackendProxy.h */,
550640A0240719E100AAE045 /* RemoteRenderingBackendProxy.messages.in */,
Expand Down Expand Up @@ -11781,6 +11792,10 @@
86F4FE1E2A98B9AE007378EE /* RemoteGraphicsContextGLInitializationState.serialization.in */,
72440D33287CCC0500FADBC4 /* RemoteImageBuffer.cpp */,
55AD09422408A02E00DE4D2F /* RemoteImageBuffer.h */,
A7E1503A2B1D6F030000E921 /* RemoteImageBuffer.messages.in */,
A78A5FEA2B0EE939005036D3 /* RemoteImageBufferSet.cpp */,
A78A5FE92B0EE849005036D3 /* RemoteImageBufferSet.h */,
A7E1503B2B1D6F500000E921 /* RemoteImageBufferSet.messages.in */,
72A87BBB287678A700289098 /* RemoteRenderingBackend.cpp */,
550640A324071A6100AAE045 /* RemoteRenderingBackend.h */,
550640A424071C2100AAE045 /* RemoteRenderingBackend.messages.in */,
Expand Down Expand Up @@ -15226,7 +15241,7 @@
E170876C16D6CA6900F99226 /* BlobRegistryProxy.h in Headers */,
4F601432155C5AA2001FBDE0 /* BlockingResponseMap.h in Headers */,
1A5705111BE410E600874AF1 /* BlockSPI.h in Headers */,
463A074B2AFD8C7200CA8DBE /* BufferAndBackendInfo.h in Headers */,
A7E69BCC2B2117A100D43D3F /* BufferAndBackendInfo.h in Headers */,
BC3065FA1259344E00E71278 /* CacheModel.h in Headers */,
935BF7FC2936BF1A00B41326 /* CacheStorageCache.h in Headers */,
934CF817294B884C00304F7D /* CacheStorageDiskStore.h in Headers */,
Expand Down Expand Up @@ -15625,6 +15640,7 @@
CDAC20CA23FC2F750021DEE3 /* RemoteCDMInstanceSession.h in Headers */,
CDAC20C923FC2F750021DEE3 /* RemoteCDMInstanceSessionIdentifier.h in Headers */,
F451C0FE2703B263002BA03B /* RemoteDisplayListRecorderProxy.h in Headers */,
A78A5FE42B0EB39E005036D3 /* RemoteImageBufferSetIdentifier.h in Headers */,
2D47B56D1810714E003A3AEE /* RemoteLayerBackingStore.h in Headers */,
2DDF731518E95060004F5A66 /* RemoteLayerBackingStoreCollection.h in Headers */,
1AB16AEA164B3A8800290D62 /* RemoteLayerTreeContext.h in Headers */,
Expand Down
37 changes: 37 additions & 0 deletions Source/WebKit/WebProcess/GPU/graphics/BufferIdentifierSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#if ENABLE(GPU_PROCESS)

#include <WebCore/ProcessQualified.h>
#include <WebCore/RenderingResourceIdentifier.h>

namespace WebKit {
Expand All @@ -37,6 +38,42 @@ struct BufferIdentifierSet {
std::optional<WebCore::RenderingResourceIdentifier> secondaryBack;
};

inline TextStream& operator<<(TextStream& ts, const BufferIdentifierSet& set)
{
auto dumpBuffer = [&](const char* name, const std::optional<WebCore::RenderingResourceIdentifier>& bufferInfo) {
ts.startGroup();
ts << name << " ";
if (bufferInfo)
ts << *bufferInfo;
else
ts << "none";
ts.endGroup();
};
dumpBuffer("front buffer", set.front);
dumpBuffer("back buffer", set.back);
dumpBuffer("secondaryBack buffer", set.secondaryBack);

return ts;
}

enum class BufferInSetType : uint8_t {
Front = 1 << 0,
Back = 1 << 1,
SecondaryBack = 1 << 2,
};

inline TextStream& operator<<(TextStream& ts, BufferInSetType bufferType)
{
if (bufferType == BufferInSetType::Front)
ts << "Front";
else if (bufferType == BufferInSetType::Back)
ts << "Back";
else
ts << "SecondaryBack";

return ts;
}

} // namespace WebKit

#endif // ENABLE(GPU_PROCESS)
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,10 @@
std::optional<WebCore::RenderingResourceIdentifier> secondaryBack;
};

[AdditionalEncoder=StreamConnectionEncoder, OptionSet] enum class WebKit::BufferInSetType : uint8_t {
Front,
Back,
SecondaryBack,
};

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -25,30 +25,38 @@

#include "config.h"

#if ENABLE(GPU_PROCESS) && PLATFORM(COCOA)
#if ENABLE(GPU_PROCESS)
#include "PrepareBackingStoreBuffersData.h"

#include "BufferIdentifierSet.h"
#include "RemoteLayerBackingStore.h"
#include <wtf/text/TextStream.h>

namespace WebKit {

static TextStream& operator<<(TextStream& ts, const BufferIdentifierSet& identifierSet)
TextStream& operator<<(TextStream& ts, const ImageBufferSetPrepareBufferForDisplayInputData& inputData)
{
ts << "front: " << identifierSet.front << " back: " << identifierSet.back << " secondaryBack: " << identifierSet.secondaryBack;
ts << "remoteImageBufferSet: " << inputData.remoteBufferSet;
ts << " dirtyRegion: " << inputData.dirtyRegion;
ts << " supportsPartialRepaint: " << inputData.supportsPartialRepaint;
ts << " hasEmptyDirtyRegion: " << inputData.hasEmptyDirtyRegion;
ts << " requiresClearedPixels: " << inputData.requiresClearedPixels;
return ts;
}

TextStream& operator<<(TextStream& ts, const PrepareBackingStoreBuffersInputData& inputData)
TextStream& operator<<(TextStream& ts, const ImageBufferSetPrepareBufferForDisplayOutputData& outputData)
{
ts << inputData.bufferSet << ", supportsPartialRepaint: " << inputData.supportsPartialRepaint << " hasEmptyDirtyRegion: " << inputData.hasEmptyDirtyRegion;
ts << "displayRequirement: " << outputData.displayRequirement;
ts << "bufferCacheIdentifiers: " << outputData.bufferCacheIdentifiers;
return ts;
}

TextStream& operator<<(TextStream& ts, const PrepareBackingStoreBuffersOutputData& outputData)
TextStream& operator<<(TextStream& ts, SwapBuffersDisplayRequirement displayRequirement)
{
ts << outputData.bufferSet << ", has front buffer handle: " << !!outputData.frontBufferHandle << " displayRequirement: " << outputData.displayRequirement;
switch (displayRequirement) {
case SwapBuffersDisplayRequirement::NeedsFullDisplay: ts << "full display"; break;
case SwapBuffersDisplayRequirement::NeedsNormalDisplay: ts << "normal display"; break;
case SwapBuffersDisplayRequirement::NeedsNoDisplay: ts << "no display"; break;
}

return ts;
}

Expand Down
Loading