Bug 1805209 - Use RemoteTexture for WebGPU r=gfx-reviewers,lsalzman

WebGPU uses CompositableInProcessManager to push TextureHost directly from WebGPUParent to WebRender. But CompositableInProcessManager plumbing has a problem and caused Bug 1805209.

gecko already has a similar mechanism, called RemoteTextureMap. It is used in oop WebGL. If WebGPU uses RemoteTextureMap instead of CompositableInProcessManager, both WebGPU and oop WebGL use same mechanism.

WebGPUParent pushes a new texture to RemoteTextureMap. The RemoteTextureMap notifies the pushed texture to WebRenderImageHost.

Before the change, only one TextureHost is used for one swap chain. With the change, multiple TextureHosts are used for one swap chain with recycling.

The changes are followings.

- Use RemoteTextureMap instead of CompositableInProcessManager.
- Use RemoteTextureOwnerId instead of CompositableHandle.
- Use WebRenderCanvasData instead of WebRenderInProcessImageData.
- Add remote texture pushed callback functionality to RemoteTextureMap. With it, RemoteTextureMap notifies a new pushed remote texture to WebRenderImageHost.
- Remove CompositableInProcessManager.

Differential Revision: https://phabricator.services.mozilla.com/D164890
This commit is contained in:
sotaro 2022-12-23 20:41:02 +00:00
parent 8f1aac156b
commit 954c16acec
49 changed files with 560 additions and 559 deletions

View file

@ -45,19 +45,10 @@ RefPtr<layers::ImageContainer> OffscreenCanvasDisplayHelper::GetImageContainer()
return mImageContainer;
}
layers::CompositableHandle OffscreenCanvasDisplayHelper::GetCompositableHandle()
const {
MutexAutoLock lock(mMutex);
return mData.mHandle;
}
void OffscreenCanvasDisplayHelper::UpdateContext(
CanvasContextType aType, const Maybe<int32_t>& aChildId) {
RefPtr<layers::ImageContainer> imageContainer;
if (aType != CanvasContextType::WebGPU) {
imageContainer = MakeRefPtr<layers::ImageContainer>(
layers::ImageContainer::ASYNCHRONOUS);
}
RefPtr<layers::ImageContainer> imageContainer =
MakeRefPtr<layers::ImageContainer>(layers::ImageContainer::ASYNCHRONOUS);
MutexAutoLock lock(mMutex);
@ -94,7 +85,7 @@ bool OffscreenCanvasDisplayHelper::CommitFrameToCompositor(
MaybeQueueInvalidateElement();
}
if (mData.mHandle) {
if (mData.mOwnerId.isSome()) {
// No need to update the ImageContainer as the presentation itself is
// handled in the compositor process.
return true;
@ -279,14 +270,14 @@ OffscreenCanvasDisplayHelper::GetSurfaceSnapshot() {
Maybe<int32_t> childId;
HTMLCanvasElement* canvasElement;
RefPtr<gfx::SourceSurface> surface;
layers::CompositableHandle handle;
Maybe<layers::RemoteTextureOwnerId> ownerId;
{
MutexAutoLock lock(mMutex);
hasAlpha = !mData.mIsOpaque;
isAlphaPremult = mData.mIsAlphaPremult;
originPos = mData.mOriginPos;
handle = mData.mHandle;
ownerId = mData.mOwnerId;
managerId = mContextManagerId;
childId = mContextChildId;
canvasElement = mCanvasElement;
@ -340,7 +331,7 @@ OffscreenCanvasDisplayHelper::GetSurfaceSnapshot() {
// We don't have a usable surface, and the context lives in the compositor
// process.
return gfx::CanvasManagerChild::Get()->GetSnapshot(
managerId.value(), childId.value(), handle,
managerId.value(), childId.value(), ownerId,
hasAlpha ? gfx::SurfaceFormat::R8G8B8A8 : gfx::SurfaceFormat::R8G8B8X8,
hasAlpha && !isAlphaPremult, originPos == gl::OriginPos::BottomLeft);
}

View file

@ -27,7 +27,7 @@ struct OffscreenCanvasDisplayData final {
bool mIsOpaque = true;
bool mIsAlphaPremult = true;
mozilla::gl::OriginPos mOriginPos = gl::OriginPos::TopLeft;
mozilla::layers::CompositableHandle mHandle;
Maybe<layers::RemoteTextureOwnerId> mOwnerId;
};
class OffscreenCanvasDisplayHelper final {
@ -41,8 +41,6 @@ class OffscreenCanvasDisplayHelper final {
RefPtr<layers::ImageContainer> GetImageContainer() const;
layers::CompositableHandle GetCompositableHandle() const;
void UpdateContext(CanvasContextType aType, const Maybe<int32_t>& aChildId);
bool CommitFrameToCompositor(nsICanvasRenderingContextInternal* aContext,

View file

@ -9,7 +9,6 @@ include protocol PCanvasManager;
include "mozilla/layers/LayersMessageUtils.h";
[MoveOnly] using class mozilla::ipc::BigBuffer from "mozilla/ipc/BigBuffer.h";
using mozilla::layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
using mozilla::layers::SurfaceDescriptor from "mozilla/layers/LayersTypes.h";
using std::string from "string";
using mozilla::uvec2 from "mozilla/dom/WebGLIpdl.h";

View file

@ -1122,7 +1122,9 @@ bool WebGLContext::PushRemoteTexture(WebGLFramebuffer* fb,
};
swapChain.SetDestroyedCallback(destroyedCallback);
mRemoteTextureOwner->RegisterTextureOwner(ownerId);
mRemoteTextureOwner->RegisterTextureOwner(
ownerId,
/* aIsSyncMode */ gfx::gfxVars::WebglOopAsyncPresentForceSync());
}
MOZ_ASSERT(fb || surf);

View file

@ -40,7 +40,6 @@ class PresShell;
class WebGLFramebufferJS;
namespace layers {
class CanvasRenderer;
class CompositableHandle;
class Layer;
class Image;
class LayerManager;

View file

@ -1360,11 +1360,4 @@ webgpu::CanvasContext* HTMLCanvasElement::GetWebGPUContext() {
return static_cast<webgpu::CanvasContext*>(GetCurrentContext());
}
CompositableHandle HTMLCanvasElement::GetCompositableHandle() const {
if (mOffscreenDisplay) {
return mOffscreenDisplay->GetCompositableHandle();
}
return CompositableHandle();
}
} // namespace mozilla::dom

View file

@ -343,8 +343,6 @@ class HTMLCanvasElement final : public nsGenericHTMLElement,
layers::ImageContainer* GetImageContainer() const { return mImageContainer; }
layers::CompositableHandle GetCompositableHandle() const;
protected:
bool mResetLayer;
bool mMaybeModified; // we fetched the context, so we may have written to the

View file

@ -11,10 +11,10 @@
#include "mozilla/dom/HTMLCanvasElement.h"
#include "mozilla/gfx/CanvasManagerChild.h"
#include "mozilla/layers/CanvasRenderer.h"
#include "mozilla/layers/CompositableInProcessManager.h"
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/LayersSurfaces.h"
#include "mozilla/layers/RenderRootStateManager.h"
#include "mozilla/layers/WebRenderCanvasRenderer.h"
#include "ipc/WebGPUChild.h"
namespace mozilla::webgpu {
@ -65,9 +65,9 @@ void CanvasContext::Configure(const dom::GPUCanvasConfiguration& aDesc) {
}
gfx::IntSize actualSize(mWidth, mHeight);
mHandle = layers::CompositableInProcessManager::GetNextHandle();
mTexture =
aDesc.mDevice->InitSwapChain(aDesc, mHandle, mGfxFormat, &actualSize);
mRemoteTextureOwnerId = Some(layers::RemoteTextureOwnerId::GetNext());
mTexture = aDesc.mDevice->InitSwapChain(aDesc, *mRemoteTextureOwnerId,
mGfxFormat, &actualSize);
if (!mTexture) {
Unconfigure();
return;
@ -77,25 +77,14 @@ void CanvasContext::Configure(const dom::GPUCanvasConfiguration& aDesc) {
mBridge = aDesc.mDevice->GetBridge();
mGfxSize = actualSize;
// Force a new frame to be built, which will execute the
// `CanvasContextType::WebGPU` switch case in `CreateWebRenderCommands` and
// populate the WR user data.
if (mCanvasElement) {
mCanvasElement->InvalidateCanvas();
} else if (mOffscreenCanvas) {
dom::OffscreenCanvasDisplayData data;
data.mSize = {mWidth, mHeight};
data.mIsOpaque = false;
data.mHandle = mHandle;
mOffscreenCanvas->UpdateDisplayData(data);
}
ForceNewFrame();
}
void CanvasContext::Unconfigure() {
if (mBridge && mBridge->IsOpen() && mHandle) {
mBridge->SendSwapChainDestroy(mHandle);
if (mBridge && mBridge->IsOpen() && mRemoteTextureOwnerId.isSome()) {
mBridge->SendSwapChainDestroy(*mRemoteTextureOwnerId);
}
mHandle = layers::CompositableHandle();
mRemoteTextureOwnerId = Nothing();
mBridge = nullptr;
mTexture = nullptr;
mGfxFormat = gfx::SurfaceFormat::UNKNOWN;
@ -126,16 +115,37 @@ void CanvasContext::MaybeQueueSwapChainPresent() {
void CanvasContext::SwapChainPresent() {
mPendingSwapChainPresent = false;
if (mBridge && mBridge->IsOpen() && mHandle && mTexture) {
mBridge->SwapChainPresent(mHandle, mTexture->mId);
if (!mBridge || !mBridge->IsOpen() || mRemoteTextureOwnerId.isNothing() ||
!mTexture) {
return;
}
mLastRemoteTextureId = Some(layers::RemoteTextureId::GetNext());
mBridge->SwapChainPresent(mTexture->mId, *mLastRemoteTextureId,
*mRemoteTextureOwnerId);
}
bool CanvasContext::UpdateWebRenderCanvasData(
mozilla::nsDisplayListBuilder* aBuilder, WebRenderCanvasData* aCanvasData) {
auto* renderer = aCanvasData->GetCanvasRenderer();
if (renderer && mRemoteTextureOwnerId.isSome() &&
renderer->GetRemoteTextureOwnerIdOfPushCallback() ==
mRemoteTextureOwnerId) {
return true;
}
renderer = aCanvasData->CreateCanvasRenderer();
if (!InitializeCanvasRenderer(aBuilder, renderer)) {
// Clear CanvasRenderer of WebRenderCanvasData
aCanvasData->ClearCanvasRenderer();
return false;
}
return true;
}
bool CanvasContext::InitializeCanvasRenderer(
nsDisplayListBuilder* aBuilder, layers::CanvasRenderer* aRenderer) {
// This path is only used for rendering when we use the fallback Paint path,
// used by reftest-snapshot, printing and Firefox Screenshot.
if (!mHandle) {
if (mRemoteTextureOwnerId.isNothing()) {
return false;
}
@ -143,6 +153,7 @@ bool CanvasContext::InitializeCanvasRenderer(
data.mContext = this;
data.mSize = mGfxSize;
data.mIsOpaque = false;
data.mRemoteTextureOwnerIdOfPushCallback = mRemoteTextureOwnerId;
aRenderer->Initialize(data);
aRenderer->SetDirty();
@ -187,12 +198,33 @@ already_AddRefed<mozilla::gfx::SourceSurface> CanvasContext::GetSurfaceSnapshot(
return nullptr;
}
if (!mBridge || !mBridge->IsOpen() || !mHandle) {
if (!mBridge || !mBridge->IsOpen() || mRemoteTextureOwnerId.isNothing()) {
return nullptr;
}
return cm->GetSnapshot(cm->Id(), mBridge->Id(), mHandle, mGfxFormat,
/* aPremultiply */ false, /* aYFlip */ false);
MOZ_ASSERT(mRemoteTextureOwnerId.isSome());
return cm->GetSnapshot(cm->Id(), mBridge->Id(), mRemoteTextureOwnerId,
mGfxFormat, /* aPremultiply */ false,
/* aYFlip */ false);
}
void CanvasContext::ForceNewFrame() {
if (!mCanvasElement && !mOffscreenCanvas) {
return;
}
// Force a new frame to be built, which will execute the
// `CanvasContextType::WebGPU` switch case in `CreateWebRenderCommands` and
// populate the WR user data.
if (mCanvasElement) {
mCanvasElement->InvalidateCanvas();
} else if (mOffscreenCanvas) {
dom::OffscreenCanvasDisplayData data;
data.mSize = {mWidth, mHeight};
data.mIsOpaque = false;
data.mOwnerId = mRemoteTextureOwnerId;
mOffscreenCanvas->UpdateDisplayData(data);
}
}
} // namespace mozilla::webgpu

View file

@ -38,8 +38,6 @@ class CanvasContext final : public nsICanvasRenderingContextInternal,
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
layers::CompositableHandle mHandle;
public: // nsICanvasRenderingContextInternal
int32_t GetWidth() override { return mWidth; }
int32_t GetHeight() override { return mHeight; }
@ -54,6 +52,9 @@ class CanvasContext final : public nsICanvasRenderingContextInternal,
return NS_OK;
}
bool UpdateWebRenderCanvasData(mozilla::nsDisplayListBuilder* aBuilder,
WebRenderCanvasData* aCanvasData) override;
bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
layers::CanvasRenderer* aRenderer) override;
mozilla::UniquePtr<uint8_t[]> GetImageBuffer(int32_t* aFormat) override;
@ -87,6 +88,7 @@ class CanvasContext final : public nsICanvasRenderingContextInternal,
RefPtr<Texture> GetCurrentTexture(ErrorResult& aRv);
void MaybeQueueSwapChainPresent();
void SwapChainPresent();
void ForceNewFrame();
private:
uint32_t mWidth = 0, mHeight = 0;
@ -96,6 +98,9 @@ class CanvasContext final : public nsICanvasRenderingContextInternal,
RefPtr<Texture> mTexture;
gfx::SurfaceFormat mGfxFormat = gfx::SurfaceFormat::R8G8B8A8;
gfx::IntSize mGfxSize;
Maybe<layers::RemoteTextureId> mLastRemoteTextureId;
Maybe<layers::RemoteTextureOwnerId> mRemoteTextureOwnerId;
};
} // namespace webgpu

View file

@ -300,7 +300,7 @@ already_AddRefed<dom::Promise> Device::CreateRenderPipelineAsync(
already_AddRefed<Texture> Device::InitSwapChain(
const dom::GPUCanvasConfiguration& aDesc,
const layers::CompositableHandle& aHandle, gfx::SurfaceFormat aFormat,
const layers::RemoteTextureOwnerId aOwnerId, gfx::SurfaceFormat aFormat,
gfx::IntSize* aCanvasSize) {
if (!mBridge->CanSend()) {
return nullptr;
@ -327,7 +327,7 @@ already_AddRefed<Texture> Device::InitSwapChain(
const layers::RGBDescriptor rgbDesc(size, aFormat);
// buffer count doesn't matter much, will be created on demand
const size_t maxBufferCount = 10;
mBridge->DeviceCreateSwapChain(mId, rgbDesc, maxBufferCount, aHandle);
mBridge->DeviceCreateSwapChain(mId, rgbDesc, maxBufferCount, aOwnerId);
dom::GPUTextureDescriptor desc;
desc.mDimension = dom::GPUTextureDimension::_2d;

View file

@ -53,9 +53,6 @@ namespace ipc {
enum class ResponseRejectReason;
class Shmem;
} // namespace ipc
namespace layers {
class CompositableHandle;
} // namespace layers
namespace webgpu {
namespace ffi {
@ -102,7 +99,7 @@ class Device final : public DOMEventTargetHelper, public SupportsWeakPtr {
const ipc::Shmem& aShmem);
already_AddRefed<Texture> InitSwapChain(
const dom::GPUCanvasConfiguration& aDesc,
const layers::CompositableHandle& aHandle, gfx::SurfaceFormat aFormat,
const layers::RemoteTextureOwnerId aOwnerId, gfx::SurfaceFormat aFormat,
gfx::IntSize* aDefaultSize);
bool CheckNewWarning(const nsACString& aMessage);

View file

@ -6,7 +6,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
using layers::RGBDescriptor from "mozilla/layers/LayersSurfaces.h";
using layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
using layers::RemoteTextureId from "mozilla/layers/LayersTypes.h";
using layers::RemoteTextureOwnerId from "mozilla/layers/LayersTypes.h";
using RawId from "mozilla/webgpu/WebGPUTypes.h";
using dom::GPURequestAdapterOptions from "mozilla/dom/WebGPUBinding.h";
using dom::GPUCommandBufferDescriptor from "mozilla/dom/WebGPUBinding.h";
@ -71,9 +72,9 @@ parent:
async ComputePipelineDestroy(RawId selfId);
async RenderPipelineDestroy(RawId selfId);
async ImplicitLayoutDestroy(RawId implicitPlId, RawId[] implicitBglIds);
async DeviceCreateSwapChain(RawId selfId, RawId queueId, RGBDescriptor desc, RawId[] bufferIds, CompositableHandle handle);
async SwapChainPresent(CompositableHandle handle, RawId textureId, RawId commandEncoderId);
async SwapChainDestroy(CompositableHandle handle);
async DeviceCreateSwapChain(RawId selfId, RawId queueId, RGBDescriptor desc, RawId[] bufferIds, RemoteTextureOwnerId ownerId);
async SwapChainPresent(RawId textureId, RawId commandEncoderId, RemoteTextureId remoteTextureId, RemoteTextureOwnerId remoteTextureOwnerId);
async SwapChainDestroy(RemoteTextureOwnerId ownerId);
async DevicePushErrorScope(RawId selfId);
async DevicePopErrorScope(RawId selfId) returns (MaybeScopedError maybeError);

View file

@ -1013,22 +1013,23 @@ ipc::IPCResult WebGPUChild::RecvDropAction(const ipc::ByteBuf& aByteBuf) {
void WebGPUChild::DeviceCreateSwapChain(
RawId aSelfId, const RGBDescriptor& aRgbDesc, size_t maxBufferCount,
const layers::CompositableHandle& aHandle) {
const layers::RemoteTextureOwnerId& aOwnerId) {
RawId queueId = aSelfId; // TODO: multiple queues
nsTArray<RawId> bufferIds(maxBufferCount);
for (size_t i = 0; i < maxBufferCount; ++i) {
bufferIds.AppendElement(
ffi::wgpu_client_make_buffer_id(mClient.get(), aSelfId));
}
SendDeviceCreateSwapChain(aSelfId, queueId, aRgbDesc, bufferIds, aHandle);
SendDeviceCreateSwapChain(aSelfId, queueId, aRgbDesc, bufferIds, aOwnerId);
}
void WebGPUChild::SwapChainPresent(const layers::CompositableHandle& aHandle,
RawId aTextureId) {
void WebGPUChild::SwapChainPresent(RawId aTextureId,
const RemoteTextureId& aRemoteTextureId,
const RemoteTextureOwnerId& aOwnerId) {
// Hack: the function expects `DeviceId`, but it only uses it for `backend()`
// selection.
RawId encoderId = ffi::wgpu_client_make_encoder_id(mClient.get(), aTextureId);
SendSwapChainPresent(aHandle, aTextureId, encoderId);
SendSwapChainPresent(aTextureId, encoderId, aRemoteTextureId, aOwnerId);
}
void WebGPUChild::RegisterDevice(Device* const aDevice) {

View file

@ -19,7 +19,6 @@ namespace dom {
struct GPURequestAdapterOptions;
} // namespace dom
namespace layers {
class CompositableHandle;
class CompositorBridgeChild;
} // namespace layers
namespace webgpu {
@ -105,9 +104,10 @@ class WebGPUChild final : public PWebGPUChild, public SupportsWeakPtr {
void DeviceCreateSwapChain(RawId aSelfId, const RGBDescriptor& aRgbDesc,
size_t maxBufferCount,
const layers::CompositableHandle& aHandle);
void SwapChainPresent(const layers::CompositableHandle& aHandle,
RawId aTextureId);
const layers::RemoteTextureOwnerId& aOwnerId);
void SwapChainPresent(RawId aTextureId,
const RemoteTextureId& aRemoteTextureId,
const RemoteTextureOwnerId& aOwnerId);
void RegisterDevice(Device* const aDevice);
void UnregisterDevice(RawId aId);

View file

@ -6,9 +6,9 @@
#include "WebGPUParent.h"
#include "mozilla/PodOperations.h"
#include "mozilla/webgpu/ffi/wgpu.h"
#include "mozilla/layers/CompositableInProcessManager.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/RemoteTextureMap.h"
#include "mozilla/layers/TextureHost.h"
#include "mozilla/layers/WebRenderImageHost.h"
#include "mozilla/layers/WebRenderTextureHost.h"
@ -68,11 +68,8 @@ class PresentationData {
public:
RawId mDeviceId = 0;
RawId mQueueId = 0;
RefPtr<layers::WebRenderImageHost> mImageHost;
RefPtr<layers::MemoryTextureHost> mTextureHost;
layers::RGBDescriptor mDesc;
uint32_t mSourcePitch = 0;
uint32_t mTargetPitch = 0;
uint32_t mRowCount = 0;
int32_t mNextFrameID = 1;
std::vector<RawId> mUnassignedBufferIds;
std::vector<RawId> mAvailableBufferIds;
@ -80,17 +77,12 @@ class PresentationData {
Mutex mBuffersLock MOZ_UNANNOTATED;
PresentationData(RawId aDeviceId, RawId aQueueId,
already_AddRefed<layers::WebRenderImageHost> aImageHost,
already_AddRefed<layers::MemoryTextureHost> aTextureHost,
uint32_t aSourcePitch, uint32_t aTargetPitch, uint32_t aRows,
const layers::RGBDescriptor& aDesc, uint32_t aSourcePitch,
const nsTArray<RawId>& aBufferIds)
: mDeviceId(aDeviceId),
mQueueId(aQueueId),
mImageHost(aImageHost),
mTextureHost(aTextureHost),
mDesc(aDesc),
mSourcePitch(aSourcePitch),
mTargetPitch(aTargetPitch),
mRowCount(aRows),
mBuffersLock("WebGPU presentation buffers") {
MOZ_COUNT_CTOR(PresentationData);
@ -682,7 +674,8 @@ ipc::IPCResult WebGPUParent::RecvImplicitLayoutDestroy(
ipc::IPCResult WebGPUParent::RecvDeviceCreateSwapChain(
RawId aDeviceId, RawId aQueueId, const RGBDescriptor& aDesc,
const nsTArray<RawId>& aBufferIds, const CompositableHandle& aHandle) {
const nsTArray<RawId>& aBufferIds,
const layers::RemoteTextureOwnerId& aOwnerId) {
switch (aDesc.format()) {
case gfx::SurfaceFormat::R8G8B8A8:
case gfx::SurfaceFormat::B8G8R8A8:
@ -703,12 +696,6 @@ ipc::IPCResult WebGPUParent::RecvDeviceCreateSwapChain(
const uint32_t bufferStride =
bufferStrideWithMask.value() & ~kBufferAlignmentMask;
// GetRGBStride does its own size validation and returns 0 if invalid.
const auto textureStride = layers::ImageDataSerializer::GetRGBStride(aDesc);
if (textureStride <= 0) {
MOZ_ASSERT_UNREACHABLE("Invalid texture stride!");
return IPC_OK();
}
const auto rows = CheckedInt<uint32_t>(aDesc.size().height);
if (!rows.isValid()) {
@ -716,38 +703,16 @@ ipc::IPCResult WebGPUParent::RecvDeviceCreateSwapChain(
return IPC_OK();
}
const auto wholeBufferSize = rows * bufferStride;
const auto wholeTextureSize = rows * textureStride;
if (!wholeBufferSize.isValid() || !wholeTextureSize.isValid()) {
MOZ_ASSERT_UNREACHABLE("Invalid total buffer/texture size!");
return IPC_OK();
if (!mRemoteTextureOwner) {
mRemoteTextureOwner =
MakeRefPtr<layers::RemoteTextureOwnerClient>(OtherPid());
}
// RemoteTextureMap::GetRemoteTextureForDisplayList() works synchronously.
mRemoteTextureOwner->RegisterTextureOwner(aOwnerId, /* aIsSyncMode */ true);
auto* textureHostData = new (fallible) uint8_t[wholeTextureSize.value()];
if (NS_WARN_IF(!textureHostData)) {
ReportError(
aDeviceId,
"Error in Device::create_swapchain: failed to allocate texture buffer"_ns);
return IPC_OK();
}
layers::TextureInfo texInfo(layers::CompositableType::IMAGE);
layers::TextureFlags texFlags = layers::TextureFlags::NO_FLAGS;
wr::ExternalImageId externalId =
layers::CompositableInProcessManager::GetNextExternalImageId();
RefPtr<layers::WebRenderImageHost> imageHost =
layers::CompositableInProcessManager::Add(aHandle, OtherPid(), texInfo);
auto textureHost =
MakeRefPtr<layers::MemoryTextureHost>(textureHostData, aDesc, texFlags);
textureHost->DisableExternalTextures();
textureHost->EnsureRenderTexture(Some(externalId));
auto data = MakeRefPtr<PresentationData>(
aDeviceId, aQueueId, imageHost.forget(), textureHost.forget(),
bufferStride, textureStride, rows.value(), aBufferIds);
if (!mCanvasMap.insert({aHandle.Value(), data}).second) {
auto data = MakeRefPtr<PresentationData>(aDeviceId, aQueueId, aDesc,
bufferStride, aBufferIds);
if (!mCanvasMap.emplace(aOwnerId, data).second) {
NS_ERROR("External image is already registered as WebGPU canvas!");
}
return IPC_OK();
@ -789,13 +754,28 @@ ipc::IPCResult WebGPUParent::RecvDeviceCreateShaderModule(
}
struct PresentRequest {
PresentRequest(const ffi::WGPUGlobal* aContext,
RefPtr<PresentationData>& aData,
RefPtr<layers::RemoteTextureOwnerClient>& aRemoteTextureOwner,
const layers::RemoteTextureId aTextureId,
const layers::RemoteTextureOwnerId aOwnerId)
: mContext(aContext),
mData(aData),
mRemoteTextureOwner(aRemoteTextureOwner),
mTextureId(aTextureId),
mOwnerId(aOwnerId) {}
const ffi::WGPUGlobal* mContext;
RefPtr<PresentationData> mData;
RefPtr<layers::RemoteTextureOwnerClient> mRemoteTextureOwner;
const layers::RemoteTextureId mTextureId;
const layers::RemoteTextureOwnerId mOwnerId;
};
static void PresentCallback(ffi::WGPUBufferMapAsyncStatus status,
uint8_t* userdata) {
auto* req = reinterpret_cast<PresentRequest*>(userdata);
UniquePtr<PresentRequest> req(reinterpret_cast<PresentRequest*>(userdata));
PresentationData* data = req->mData.get();
// get the buffer ID
RawId bufferId;
@ -810,44 +790,29 @@ static void PresentCallback(ffi::WGPUBufferMapAsyncStatus status,
("PresentCallback for buffer %" PRIu64 " status=%d\n", bufferId, status));
// copy the data
if (status == ffi::WGPUBufferMapAsyncStatus_Success) {
const auto bufferSize = data->mRowCount * data->mSourcePitch;
const auto bufferSize = data->mDesc.size().height * data->mSourcePitch;
const auto mapped = ffi::wgpu_server_buffer_get_mapped_range(
req->mContext, bufferId, 0, bufferSize);
MOZ_ASSERT(mapped.length >= bufferSize);
if (data->mTextureHost) {
auto textureData =
req->mRemoteTextureOwner->CreateOrRecycleBufferTextureData(
req->mOwnerId, data->mDesc.size(), data->mDesc.format());
if (!textureData) {
gfxCriticalNoteOnce << "Failed to allocate BufferTextureData";
return;
}
layers::MappedTextureData mappedData;
if (textureData && textureData->BorrowMappedData(mappedData)) {
uint8_t* src = mapped.ptr;
uint8_t* dst = data->mTextureHost->GetBuffer();
for (uint32_t row = 0; row < data->mRowCount; ++row) {
memcpy(dst, src, data->mTargetPitch);
dst += data->mTargetPitch;
uint8_t* dst = mappedData.data;
for (auto row = 0; row < data->mDesc.size().height; ++row) {
memcpy(dst, src, mappedData.stride);
dst += mappedData.stride;
src += data->mSourcePitch;
}
layers::CompositorThread()->Dispatch(NS_NewRunnableFunction(
"webgpu::WebGPUParent::PresentCallback",
[imageHost = data->mImageHost, texture = data->mTextureHost,
frameID = data->mNextFrameID++]() {
AutoTArray<layers::CompositableHost::TimedTexture, 1> textures;
layers::CompositableHost::TimedTexture* timedTexture =
textures.AppendElement();
// TODO(aosmond): We recreate the WebRenderTextureHost object each
// time so that the pipeline actually updates, as it checks if the
// texture is the same as before issuing the transaction update to
// WR. We really ought to be cycling between a front and buffer back
// here to avoid a race uploading the texture and doing the copy in
// PresentCallback.
timedTexture->mTexture = new layers::WebRenderTextureHost(
layers::TextureFlags::BORROWED_EXTERNAL_ID, texture,
texture->GetMaybeExternalImageId().ref());
timedTexture->mTimeStamp = TimeStamp();
timedTexture->mPictureRect =
gfx::IntRect(gfx::IntPoint(0, 0), texture->GetSize());
timedTexture->mFrameID = frameID;
timedTexture->mProducerID = 0;
imageHost->UseTextureHost(textures);
}));
req->mRemoteTextureOwner->PushTexture(req->mTextureId, req->mOwnerId,
std::move(textureData),
/* aSharedSurface */ nullptr);
} else {
NS_WARNING("WebGPU present skipped: the swapchain is resized!");
}
@ -862,53 +827,48 @@ static void PresentCallback(ffi::WGPUBufferMapAsyncStatus status,
// TODO: better handle errors
NS_WARNING("WebGPU frame mapping failed!");
}
// free yourself
delete req;
}
ipc::IPCResult WebGPUParent::GetFrontBufferSnapshot(
IProtocol* aProtocol, const CompositableHandle& aHandle,
IProtocol* aProtocol, const layers::RemoteTextureOwnerId& aOwnerId,
Maybe<Shmem>& aShmem, gfx::IntSize& aSize) {
const auto& lookup = mCanvasMap.find(aHandle.Value());
if (lookup == mCanvasMap.end()) {
const auto& lookup = mCanvasMap.find(aOwnerId);
if (lookup == mCanvasMap.end() || !mRemoteTextureOwner) {
return IPC_OK();
}
RefPtr<PresentationData> data = lookup->second.get();
aSize = data->mTextureHost->GetSize();
uint32_t stride =
aSize.width * BytesPerPixel(data->mTextureHost->GetFormat());
uint32_t len = data->mRowCount * stride;
aSize = data->mDesc.size();
uint32_t stride = layers::ImageDataSerializer::ComputeRGBStride(
data->mDesc.format(), aSize.width);
uint32_t len = data->mDesc.size().height * stride;
Shmem shmem;
if (!AllocShmem(len, &shmem)) {
return IPC_OK();
}
uint8_t* dst = shmem.get<uint8_t>();
uint8_t* src = data->mTextureHost->GetBuffer();
for (uint32_t row = 0; row < data->mRowCount; ++row) {
memcpy(dst, src, stride);
src += data->mTargetPitch;
dst += stride;
}
mRemoteTextureOwner->GetLatestBufferSnapshot(aOwnerId, shmem, aSize);
aShmem.emplace(std::move(shmem));
return IPC_OK();
}
ipc::IPCResult WebGPUParent::RecvSwapChainPresent(
const CompositableHandle& aHandle, RawId aTextureId,
RawId aCommandEncoderId) {
RawId aTextureId, RawId aCommandEncoderId,
const layers::RemoteTextureId& aRemoteTextureId,
const layers::RemoteTextureOwnerId& aOwnerId) {
// step 0: get the data associated with the swapchain
const auto& lookup = mCanvasMap.find(aHandle.Value());
if (lookup == mCanvasMap.end()) {
const auto& lookup = mCanvasMap.find(aOwnerId);
if (lookup == mCanvasMap.end() || !mRemoteTextureOwner ||
!mRemoteTextureOwner->IsRegistered(aOwnerId)) {
NS_WARNING("WebGPU presenting on a destroyed swap chain!");
return IPC_OK();
}
RefPtr<PresentationData> data = lookup->second.get();
RawId bufferId = 0;
const auto& size = data->mTextureHost->GetSize();
const auto bufferSize = data->mRowCount * data->mSourcePitch;
const auto& size = data->mDesc.size();
const auto bufferSize = data->mDesc.size().height * data->mSourcePitch;
// step 1: find an available staging buffer, or create one
{
@ -1001,13 +961,11 @@ ipc::IPCResult WebGPUParent::RecvSwapChainPresent(
// texture,
// we can just give it the contents of the last mapped buffer instead of the
// copy.
auto* const presentRequest = new PresentRequest{
mContext.get(),
data,
};
auto presentRequest = MakeUnique<PresentRequest>(
mContext.get(), data, mRemoteTextureOwner, aRemoteTextureId, aOwnerId);
ffi::WGPUBufferMapCallbackC callback = {
&PresentCallback, reinterpret_cast<uint8_t*>(presentRequest)};
&PresentCallback, reinterpret_cast<uint8_t*>(presentRequest.release())};
ffi::wgpu_server_buffer_map(mContext.get(), bufferId, 0, bufferSize,
ffi::WGPUHostMap_Read, callback);
@ -1015,8 +973,11 @@ ipc::IPCResult WebGPUParent::RecvSwapChainPresent(
}
ipc::IPCResult WebGPUParent::RecvSwapChainDestroy(
const CompositableHandle& aHandle) {
const auto& lookup = mCanvasMap.find(aHandle.Value());
const layers::RemoteTextureOwnerId& aOwnerId) {
if (mRemoteTextureOwner) {
mRemoteTextureOwner->UnregisterTextureOwner(aOwnerId);
}
const auto& lookup = mCanvasMap.find(aOwnerId);
MOZ_ASSERT(lookup != mCanvasMap.end());
if (lookup == mCanvasMap.end()) {
NS_WARNING("WebGPU presenting on a destroyed swap chain!");
@ -1025,8 +986,6 @@ ipc::IPCResult WebGPUParent::RecvSwapChainDestroy(
RefPtr<PresentationData> data = lookup->second.get();
mCanvasMap.erase(lookup);
data->mTextureHost = nullptr;
layers::CompositableInProcessManager::Release(aHandle, OtherPid());
MutexAutoLock lock(data->mBuffersLock);
ipc::ByteBuf dropByteBuf;
@ -1047,11 +1006,11 @@ ipc::IPCResult WebGPUParent::RecvSwapChainDestroy(
void WebGPUParent::ActorDestroy(ActorDestroyReason aWhy) {
mTimer.Stop();
for (const auto& p : mCanvasMap) {
const CompositableHandle handle(p.first);
layers::CompositableInProcessManager::Release(handle, OtherPid());
}
mCanvasMap.clear();
if (mRemoteTextureOwner) {
mRemoteTextureOwner->UnregisterAllTextureOwners();
mRemoteTextureOwner = nullptr;
}
ffi::wgpu_server_poll_all_devices(mContext.get(), true);
mContext = nullptr;
}

View file

@ -13,7 +13,14 @@
#include "WebGPUTypes.h"
#include "base/timer.h"
namespace mozilla::webgpu {
namespace mozilla {
namespace layers {
class RemoteTextureOwnerClient;
} // namespace layers
namespace webgpu {
class ErrorBuffer;
class PresentationData;
@ -68,18 +75,20 @@ class WebGPUParent final : public PWebGPUParent {
ipc::IPCResult RecvRenderPipelineDestroy(RawId aPipelineId);
ipc::IPCResult RecvImplicitLayoutDestroy(
RawId aImplicitPlId, const nsTArray<RawId>& aImplicitBglIds);
ipc::IPCResult RecvDeviceCreateSwapChain(RawId aDeviceId, RawId aQueueId,
const layers::RGBDescriptor& aDesc,
const nsTArray<RawId>& aBufferIds,
const CompositableHandle& aHandle);
ipc::IPCResult RecvDeviceCreateSwapChain(
RawId aDeviceId, RawId aQueueId, const layers::RGBDescriptor& aDesc,
const nsTArray<RawId>& aBufferIds,
const layers::RemoteTextureOwnerId& aOwnerId);
ipc::IPCResult RecvDeviceCreateShaderModule(
RawId aDeviceId, RawId aModuleId, const nsString& aLabel,
const nsCString& aCode, DeviceCreateShaderModuleResolver&& aOutMessage);
ipc::IPCResult RecvSwapChainPresent(const CompositableHandle& aHandle,
RawId aTextureId,
RawId aCommandEncoderId);
ipc::IPCResult RecvSwapChainDestroy(const CompositableHandle& aHandle);
ipc::IPCResult RecvSwapChainPresent(
RawId aTextureId, RawId aCommandEncoderId,
const layers::RemoteTextureId& aRemoteTextureId,
const layers::RemoteTextureOwnerId& aOwnerId);
ipc::IPCResult RecvSwapChainDestroy(
const layers::RemoteTextureOwnerId& aOwnerId);
ipc::IPCResult RecvDeviceAction(RawId aDeviceId,
const ipc::ByteBuf& aByteBuf);
@ -100,10 +109,9 @@ class WebGPUParent final : public PWebGPUParent {
RawId aDeviceId, DevicePopErrorScopeResolver&& aResolver);
ipc::IPCResult RecvGenerateError(RawId aDeviceId, const nsCString& message);
ipc::IPCResult GetFrontBufferSnapshot(IProtocol* aProtocol,
const CompositableHandle& aHandle,
Maybe<Shmem>& aShmem,
gfx::IntSize& aSize);
ipc::IPCResult GetFrontBufferSnapshot(
IProtocol* aProtocol, const layers::RemoteTextureOwnerId& aOwnerId,
Maybe<Shmem>& aShmem, gfx::IntSize& aSize);
void ActorDestroy(ActorDestroyReason aWhy) override;
@ -133,11 +141,17 @@ class WebGPUParent final : public PWebGPUParent {
/// regardless of their state.
std::unordered_map<uint64_t, BufferMapData> mSharedMemoryMap;
/// Associated presentation data for each swapchain.
std::unordered_map<uint64_t, RefPtr<PresentationData>> mCanvasMap;
std::unordered_map<layers::RemoteTextureOwnerId, RefPtr<PresentationData>,
layers::RemoteTextureOwnerId::HashFn>
mCanvasMap;
RefPtr<layers::RemoteTextureOwnerClient> mRemoteTextureOwner;
/// Associated stack of error scopes for each device.
std::unordered_map<uint64_t, ErrorScopeStack> mErrorScopeMap;
};
} // namespace mozilla::webgpu
} // namespace webgpu
} // namespace mozilla
#endif // WEBGPU_PARENT_H_

View file

@ -145,14 +145,14 @@ RefPtr<webgpu::WebGPUChild> CanvasManagerChild::GetWebGPUChild() {
already_AddRefed<DataSourceSurface> CanvasManagerChild::GetSnapshot(
uint32_t aManagerId, int32_t aProtocolId,
const layers::CompositableHandle& aHandle, SurfaceFormat aFormat,
const Maybe<RemoteTextureOwnerId>& aOwnerId, SurfaceFormat aFormat,
bool aPremultiply, bool aYFlip) {
if (!CanSend()) {
return nullptr;
}
webgl::FrontBufferSnapshotIpc res;
if (!SendGetSnapshot(aManagerId, aProtocolId, aHandle, &res)) {
if (!SendGetSnapshot(aManagerId, aProtocolId, aOwnerId, &res)) {
return nullptr;
}

View file

@ -32,7 +32,7 @@ class CanvasManagerChild final : public PCanvasManagerChild {
uint32_t Id() const { return mId; }
already_AddRefed<DataSourceSurface> GetSnapshot(
uint32_t aManagerId, int32_t aProtocolId,
const layers::CompositableHandle& aHandle, SurfaceFormat aFormat,
const Maybe<RemoteTextureOwnerId>& aOwnerId, SurfaceFormat aFormat,
bool aPremultiply, bool aYFlip);
void ActorDestroy(ActorDestroyReason aReason) override;

View file

@ -122,7 +122,8 @@ mozilla::ipc::IPCResult CanvasManagerParent::RecvInitialize(
mozilla::ipc::IPCResult CanvasManagerParent::RecvGetSnapshot(
const uint32_t& aManagerId, const int32_t& aProtocolId,
const CompositableHandle& aHandle, webgl::FrontBufferSnapshotIpc* aResult) {
const Maybe<RemoteTextureOwnerId>& aOwnerId,
webgl::FrontBufferSnapshotIpc* aResult) {
if (!aManagerId) {
return IPC_FAIL(this, "invalid id");
}
@ -157,8 +158,11 @@ mozilla::ipc::IPCResult CanvasManagerParent::RecvGetSnapshot(
RefPtr<webgpu::WebGPUParent> webgpu =
static_cast<webgpu::WebGPUParent*>(actor);
IntSize size;
if (aOwnerId.isNothing()) {
return IPC_FAIL(this, "invalid OwnerId");
}
mozilla::ipc::IPCResult rv =
webgpu->GetFrontBufferSnapshot(this, aHandle, buffer.shmem, size);
webgpu->GetFrontBufferSnapshot(this, *aOwnerId, buffer.shmem, size);
if (!rv) {
return rv;
}

View file

@ -30,7 +30,7 @@ class CanvasManagerParent final : public PCanvasManagerParent {
mozilla::ipc::IPCResult RecvInitialize(const uint32_t& aId);
mozilla::ipc::IPCResult RecvGetSnapshot(
const uint32_t& aManagerId, const int32_t& aProtocolId,
const CompositableHandle& aHandle,
const Maybe<RemoteTextureOwnerId>& aOwnerId,
webgl::FrontBufferSnapshotIpc* aResult);
private:

View file

@ -9,7 +9,7 @@ include "mozilla/layers/LayersMessageUtils.h";
include protocol PWebGL;
include protocol PWebGPU;
using mozilla::layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
using layers::RemoteTextureOwnerId from "mozilla/layers/LayersTypes.h";
using mozilla::webgl::FrontBufferSnapshotIpc from "mozilla/dom/WebGLIpdl.h";
namespace mozilla {
@ -41,7 +41,7 @@ parent:
// intended to be used by the main thread in the content process to block
// reading without having to block on the worker thread that owns the context
// instance.
sync GetSnapshot(uint32_t aManagerId, int32_t aProtocolId, CompositableHandle aHandle) returns (FrontBufferSnapshotIpc ret);
sync GetSnapshot(uint32_t aManagerId, int32_t aProtocolId, RemoteTextureOwnerId? ownerId) returns (FrontBufferSnapshotIpc ret);
};
} // gfx

View file

@ -17,9 +17,10 @@
#include "mozilla/Preferences.h" // for Preferences
#include "mozilla/RefPtr.h" // for RefPtr
#include "mozilla/gfx/2D.h" // for DrawTarget
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "mozilla/WeakPtr.h" // for WeakPtr
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
#include "mozilla/Maybe.h"
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "mozilla/WeakPtr.h" // for WeakPtr
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
#include "nsICanvasRenderingContextInternal.h"
namespace mozilla {
@ -46,6 +47,9 @@ struct CanvasRendererData final {
gl::OriginPos mOriginPos = gl::OriginPos::TopLeft;
// Used in remote texture push callback
Maybe<RemoteTextureOwnerId> mRemoteTextureOwnerIdOfPushCallback = Nothing();
nsICanvasRenderingContextInternal* GetContext() const {
return mContext.get();
}
@ -122,6 +126,9 @@ class CanvasRenderer : public RefCounted<CanvasRenderer> {
const gfx::IntSize& GetSize() const { return mData.mSize; }
bool IsOpaque() const { return mData.mIsOpaque; }
bool YIsDown() const { return mData.mOriginPos == gl::OriginPos::TopLeft; }
Maybe<RemoteTextureOwnerId> GetRemoteTextureOwnerIdOfPushCallback() {
return mData.mRemoteTextureOwnerIdOfPushCallback;
}
void SetDirty() { mDirty = true; }
void ResetDirty() { mDirty = false; }

View file

@ -326,7 +326,6 @@ class CompositableHandle final {
enum class CompositableHandleOwner : uint8_t {
WebRenderBridge,
ImageBridge,
InProcessManager,
};
struct RemoteTextureId {

View file

@ -8,10 +8,12 @@
#include <vector>
#include "CompositableHost.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/layers/AsyncImagePipelineManager.h"
#include "mozilla/layers/BufferTexture.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/RemoteTextureHostWrapper.h"
#include "mozilla/layers/WebRenderTextureHost.h"
#include "mozilla/StaticPrefs_webgl.h"
@ -36,10 +38,10 @@ bool RemoteTextureOwnerClient::IsRegistered(
}
void RemoteTextureOwnerClient::RegisterTextureOwner(
const RemoteTextureOwnerId aOwnerId) {
const RemoteTextureOwnerId aOwnerId, bool aIsSyncMode) {
MOZ_ASSERT(mOwnerIds.find(aOwnerId) == mOwnerIds.end());
mOwnerIds.emplace(aOwnerId);
RemoteTextureMap::Get()->RegisterTextureOwner(aOwnerId, mForPid);
RemoteTextureMap::Get()->RegisterTextureOwner(aOwnerId, mForPid, aIsSyncMode);
}
void RemoteTextureOwnerClient::UnregisterTextureOwner(
@ -68,6 +70,14 @@ void RemoteTextureOwnerClient::PushTexture(
std::move(aTextureData), aSharedSurface);
}
void RemoteTextureOwnerClient::GetLatestBufferSnapshot(
const RemoteTextureOwnerId aOwnerId, const ipc::Shmem& aDestShmem,
const gfx::IntSize& aSize) {
MOZ_ASSERT(IsRegistered(aOwnerId));
RemoteTextureMap::Get()->GetLatestBufferSnapshot(aOwnerId, mForPid,
aDestShmem, aSize);
}
UniquePtr<TextureData>
RemoteTextureOwnerClient::CreateOrRecycleBufferTextureData(
const RemoteTextureOwnerId aOwnerId, gfx::IntSize aSize,
@ -133,6 +143,19 @@ void RemoteTextureMap::PushTexture(
return;
}
const auto key = std::pair(aForPid, aOwnerId);
auto it = mRemoteTexturePushListeners.find(key);
// Notify a new texture if callback is requested
if (it != mRemoteTexturePushListeners.end()) {
RefPtr<CompositableHost> compositableHost = it->second;
RefPtr<Runnable> runnable = NS_NewRunnableFunction(
"RemoteTextureMap::PushTexture::Runnable",
[compositableHost, aTextureId, aOwnerId, aForPid]() {
compositableHost->NotifyPushTexture(aTextureId, aOwnerId, aForPid);
});
CompositorThread()->Dispatch(runnable.forget());
}
auto textureData = MakeUnique<TextureDataHolder>(
aTextureId, textureHost, std::move(aTextureData), aSharedSurface);
@ -140,7 +163,7 @@ void RemoteTextureMap::PushTexture(
owner->mWaitingTextureDataHolders.push_back(std::move(textureData));
if (!gfx::gfxVars::WebglOopAsyncPresentForceSync()) {
if (!owner->mIsSyncMode) {
// Update mAsyncRemoteTextureHost for async mode.
// This happens when PushTexture() with RemoteTextureId is called after
// GetRemoteTextureForDisplayList() with the RemoteTextureId.
@ -183,8 +206,77 @@ void RemoteTextureMap::PushTexture(
}
}
void RemoteTextureMap::GetLatestBufferSnapshot(
const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid,
const ipc::Shmem& aDestShmem, const gfx::IntSize& aSize) {
// The compositable ref of remote texture should be updated in mMonitor lock.
CompositableTextureHostRef textureHostRef;
RefPtr<TextureHost> releasingTexture; // Release outside the monitor
{
MonitorAutoLock lock(mMonitor);
auto* owner = GetTextureOwner(lock, aOwnerId, aForPid);
if (!owner) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return;
}
// Get latest TextureHost of remote Texture.
if (owner->mWaitingTextureDataHolders.empty() &&
!owner->mLatestTextureHost) {
return;
}
TextureHost* textureHost =
!owner->mWaitingTextureDataHolders.empty()
? owner->mWaitingTextureDataHolders.back()->mTextureHost
: owner->mLatestTextureHost;
if (!textureHost->AsBufferTextureHost()) {
// Only BufferTextureHost is supported for now.
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return;
}
if (textureHost->GetSize() != aSize) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return;
}
if (textureHost->GetFormat() != gfx::SurfaceFormat::R8G8B8A8 &&
textureHost->GetFormat() != gfx::SurfaceFormat::B8G8R8A8) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return;
}
// Increment compositable ref to prevent that TextureHost is removed during
// memcpy.
textureHostRef = textureHost;
}
if (!textureHostRef) {
return;
}
auto* bufferTextureHost = textureHostRef->AsBufferTextureHost();
if (bufferTextureHost) {
uint32_t stride = ImageDataSerializer::ComputeRGBStride(
bufferTextureHost->GetFormat(), aSize.width);
uint32_t bufferSize = stride * aSize.height;
uint8_t* dst = aDestShmem.get<uint8_t>();
uint8_t* src = bufferTextureHost->GetBuffer();
MOZ_ASSERT(bufferSize <= aDestShmem.Size<uint8_t>());
memcpy(dst, src, bufferSize);
}
{
MonitorAutoLock lock(mMonitor);
// Release compositable ref in mMonitor lock, but release RefPtr outside the
// monitor
releasingTexture = textureHostRef;
textureHostRef = nullptr;
}
}
void RemoteTextureMap::RegisterTextureOwner(const RemoteTextureOwnerId aOwnerId,
const base::ProcessId aForPid) {
const base::ProcessId aForPid,
bool aIsSyncMode) {
MonitorAutoLock lock(mMonitor);
const auto key = std::pair(aForPid, aOwnerId);
@ -194,6 +286,8 @@ void RemoteTextureMap::RegisterTextureOwner(const RemoteTextureOwnerId aOwnerId,
return;
}
auto owner = MakeUnique<TextureOwner>();
owner->mIsSyncMode = aIsSyncMode;
mTextureOwners.emplace(key, std::move(owner));
}
@ -367,7 +461,7 @@ void RemoteTextureMap::GetRemoteTextureForDisplayList(
UpdateTexture(lock, owner, textureId);
if (gfx::gfxVars::WebglOopAsyncPresentForceSync()) {
if (owner->mIsSyncMode) {
// remote texture sync ipc
if (textureId == owner->mLatestTextureId) {
MOZ_ASSERT(owner->mLatestTextureHost);
@ -412,8 +506,8 @@ void RemoteTextureMap::GetRemoteTextureForDisplayList(
}
if (textureHost) {
aTextureHostWrapper->SetRemoteTextureHostForDisplayList(lock,
textureHost);
aTextureHostWrapper->SetRemoteTextureHostForDisplayList(
lock, textureHost, owner->mIsSyncMode);
aTextureHostWrapper->ApplyTextureFlagsToRemoteTexture();
}
}
@ -483,7 +577,7 @@ void RemoteTextureMap::ReleaseRemoteTextureHostForDisplayList(
MonitorAutoLock lock(mMonitor);
releasingTexture =
aTextureHostWrapper->GetRemoteTextureHostForDisplayList(lock);
aTextureHostWrapper->SetRemoteTextureHostForDisplayList(lock, nullptr);
aTextureHostWrapper->ClearRemoteTextureHostForDisplayList(lock);
}
}
@ -535,6 +629,74 @@ void RemoteTextureMap::UnregisterRemoteTextureHostWrapper(
}
}
void RemoteTextureMap::RegisterRemoteTexturePushListener(
const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid,
CompositableHost* aListener) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
RefPtr<CompositableHost>
releasingCompositableHost; // Release outside the monitor
{
MonitorAutoLock lock(mMonitor);
const auto key = std::pair(aForPid, aOwnerId);
auto it = mRemoteTexturePushListeners.find(key);
// Remove obsoleted CompositableHost.
if (it != mRemoteTexturePushListeners.end()) {
releasingCompositableHost = std::move(it->second);
mRemoteTexturePushListeners.erase(it);
}
mRemoteTexturePushListeners.emplace(key, aListener);
auto* owner = GetTextureOwner(lock, aOwnerId, aForPid);
if (!owner) {
return;
}
if (owner->mWaitingTextureDataHolders.empty() &&
!owner->mLatestTextureHost) {
return;
}
// Get latest RemoteTextureId.
auto textureId = !owner->mWaitingTextureDataHolders.empty()
? owner->mWaitingTextureDataHolders.back()->mTextureId
: owner->mLatestTextureId;
// Notify the RemoteTextureId to callback
RefPtr<CompositableHost> compositableHost = aListener;
RefPtr<Runnable> runnable = NS_NewRunnableFunction(
"RemoteTextureMap::RegisterRemoteTexturePushListener::Runnable",
[compositableHost, textureId, aOwnerId, aForPid]() {
compositableHost->NotifyPushTexture(textureId, aOwnerId, aForPid);
});
CompositorThread()->Dispatch(runnable.forget());
}
}
void RemoteTextureMap::UnregisterRemoteTexturePushListener(
const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid,
CompositableHost* aListener) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
RefPtr<CompositableHost>
releasingCompositableHost; // Release outside the monitor
{
MonitorAutoLock lock(mMonitor);
const auto key = std::pair(aForPid, aOwnerId);
auto it = mRemoteTexturePushListeners.find(key);
if (it == mRemoteTexturePushListeners.end()) {
return;
}
if (aListener != it->second) {
// aListener was alredy obsoleted.
return;
}
releasingCompositableHost = std::move(it->second);
mRemoteTexturePushListeners.erase(it);
}
}
UniquePtr<TextureData> RemoteTextureMap::GetRecycledBufferTextureData(
const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid,
gfx::IntSize aSize, gfx::SurfaceFormat aFormat) {

View file

@ -36,6 +36,7 @@ class SharedSurface;
namespace layers {
class CompositableHost;
class RemoteTextureHostWrapper;
class TextureData;
class TextureHost;
@ -50,13 +51,17 @@ class RemoteTextureOwnerClient final {
explicit RemoteTextureOwnerClient(const base::ProcessId aForPid);
bool IsRegistered(const RemoteTextureOwnerId aOwnerId);
void RegisterTextureOwner(const RemoteTextureOwnerId aOwnerId);
void RegisterTextureOwner(const RemoteTextureOwnerId aOwnerId,
bool aIsSyncMode);
void UnregisterTextureOwner(const RemoteTextureOwnerId aOwnerId);
void UnregisterAllTextureOwners();
void PushTexture(const RemoteTextureId aTextureId,
const RemoteTextureOwnerId aOwnerId,
UniquePtr<TextureData>&& aTextureData,
const std::shared_ptr<gl::SharedSurface>& aSharedSurface);
void GetLatestBufferSnapshot(const RemoteTextureOwnerId aOwnerId,
const ipc::Shmem& aDestShmem,
const gfx::IntSize& aSize);
UniquePtr<TextureData> CreateOrRecycleBufferTextureData(
const RemoteTextureOwnerId aOwnerId, gfx::IntSize aSize,
gfx::SurfaceFormat aFormat);
@ -95,8 +100,16 @@ class RemoteTextureMap {
const base::ProcessId aForPid,
UniquePtr<TextureData>&& aTextureData,
const std::shared_ptr<gl::SharedSurface>& aSharedSurface);
void GetLatestBufferSnapshot(const RemoteTextureOwnerId aOwnerId,
const base::ProcessId aForPid,
const ipc::Shmem& aDestShmem,
const gfx::IntSize& aSize);
// aIsSyncMode defines if RemoteTextureMap::GetRemoteTextureForDisplayList()
// works synchronously.
void RegisterTextureOwner(const RemoteTextureOwnerId aOwnerId,
const base::ProcessId aForPid);
const base::ProcessId aForPid, bool aIsSyncMode);
void UnregisterTextureOwner(const RemoteTextureOwnerId aOwnerIds,
const base::ProcessId aForPid);
void UnregisterTextureOwners(
@ -129,6 +142,14 @@ class RemoteTextureMap {
const RemoteTextureOwnerId aOwnerId,
const base::ProcessId aForPid);
void RegisterRemoteTexturePushListener(const RemoteTextureOwnerId aOwnerId,
const base::ProcessId aForPid,
CompositableHost* aListener);
void UnregisterRemoteTexturePushListener(const RemoteTextureOwnerId aOwnerId,
const base::ProcessId aForPid,
CompositableHost* aListener);
UniquePtr<TextureData> GetRecycledBufferTextureData(
const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid,
gfx::IntSize aSize, gfx::SurfaceFormat aFormat);
@ -157,6 +178,7 @@ class RemoteTextureMap {
};
struct TextureOwner {
bool mIsSyncMode = true;
// Holds TextureDataHolders that wait to be used for building wr display
// list.
std::deque<UniquePtr<TextureDataHolder>> mWaitingTextureDataHolders;
@ -204,6 +226,10 @@ class RemoteTextureMap {
UniquePtr<RemoteTextureHostWrapperHolder>>
mRemoteTextureHostWrapperHolders;
std::map<std::pair<base::ProcessId, RemoteTextureOwnerId>,
RefPtr<CompositableHost>>
mRemoteTexturePushListeners;
static StaticAutoPtr<RemoteTextureMap> sInstance;
};

View file

@ -129,6 +129,16 @@ void ShareableCanvasRenderer::UpdateCompositableClient() {
flags |= TextureFlags::IS_OPAQUE;
}
// With remote texture push callback, a new pushed remote texture is notifiled
// from RemoteTextureMap to WebRenderImageHost.
if (mData.mRemoteTextureOwnerIdOfPushCallback) {
GetForwarder()->EnableRemoteTexturePushCallback(
mCanvasClient, *mData.mRemoteTextureOwnerIdOfPushCallback, mData.mSize,
flags);
EnsurePipeline();
return;
}
// -
const auto fnGetExistingTc =

View file

@ -13,12 +13,12 @@
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/Attributes.h" // for override
#include "mozilla/RefPtr.h" // for RefPtr, RefCounted, etc
//#include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4
// #include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4
#include "mozilla/gfx/Polygon.h" // for Polygon
#include "mozilla/gfx/Rect.h" // for Rect
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc
//#include "mozilla/layers/LayersTypes.h" // for LayerRenderState, etc
// #include "mozilla/layers/LayersTypes.h" // for LayerRenderState, etc
#include "mozilla/layers/LayersMessages.h"
#include "mozilla/layers/TextureHost.h" // for TextureHost
#include "nsCOMPtr.h" // for already_AddRefed
@ -93,6 +93,15 @@ class CompositableHost {
const TextureFlags aFlags) = 0;
virtual void RemoveTextureHost(TextureHost* aTexture);
// Enable remote texture push callback
virtual void EnableRemoteTexturePushCallback(
const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid,
const gfx::IntSize aSize, const TextureFlags aFlags) = 0;
// Called from RemoteTextureMap when a new remote texture is pushed
virtual void NotifyPushTexture(const RemoteTextureId aTextureId,
const RemoteTextureOwnerId aOwnerId,
const base::ProcessId aForPid) = 0;
uint64_t GetCompositorBridgeID() const { return mCompositorBridgeID; }
const AsyncCompositableRef& GetAsyncRef() const { return mAsyncRef; }

View file

@ -96,8 +96,9 @@ void RemoteTextureHostWrapper::CreateRenderTexture(
MOZ_ASSERT(mRemoteTextureForDisplayList);
MOZ_ASSERT(mRemoteTextureForDisplayList->mExternalImageId.isSome());
if (gfx::gfxVars::WebglOopAsyncPresentForceSync()) {
if (mIsSyncMode) {
// sync mode
// mRemoteTextureForDisplayList is also used for WebRender rendering.
auto wrappedId = mRemoteTextureForDisplayList->mExternalImageId.ref();
RefPtr<wr::RenderTextureHost> texture =
new wr::RenderTextureHostWrapper(wrappedId);
@ -105,6 +106,9 @@ void RemoteTextureHostWrapper::CreateRenderTexture(
texture.forget());
} else {
// async mode
// mRemoteTextureForDisplayList could be previous remote texture's
// TextureHost that is compatible to the mTextureId's TextureHost.
// mRemoteTextureForDisplayList might not be used WebRender rendering.
RefPtr<wr::RenderTextureHost> texture =
new wr::RenderTextureHostWrapper(mTextureId, mOwnerId, mForPid);
wr::RenderThread::Get()->RegisterExternalImage(mExternalImageId.ref(),
@ -203,9 +207,17 @@ TextureHost* RemoteTextureHostWrapper::GetRemoteTextureHostForDisplayList(
}
void RemoteTextureHostWrapper::SetRemoteTextureHostForDisplayList(
const MonitorAutoLock& aProofOfLock, TextureHost* aTextureHost) {
const MonitorAutoLock& aProofOfLock, TextureHost* aTextureHost,
bool aIsSyncMode) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
mRemoteTextureForDisplayList = aTextureHost;
mIsSyncMode = aIsSyncMode;
}
void RemoteTextureHostWrapper::ClearRemoteTextureHostForDisplayList(
const MonitorAutoLock& aProofOfLoc) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
mRemoteTextureForDisplayList = nullptr;
}
bool RemoteTextureHostWrapper::IsWrappingSurfaceTextureHost() {

View file

@ -97,7 +97,10 @@ class RemoteTextureHostWrapper : public TextureHost {
const MonitorAutoLock& aProofOfLock);
// Called only by RemoteTextureMap
void SetRemoteTextureHostForDisplayList(const MonitorAutoLock& aProofOfLock,
TextureHost* aTextureHost);
TextureHost* aTextureHost,
bool aIsSyncMode);
void ClearRemoteTextureHostForDisplayList(
const MonitorAutoLock& aProofOfLock);
// Updated by RemoteTextureMap
//
@ -107,6 +110,8 @@ class RemoteTextureHostWrapper : public TextureHost {
// compatible to the mTextureId's TextureHost.
CompositableTextureHostRef mRemoteTextureForDisplayList;
bool mIsSyncMode = true;
friend class RemoteTextureMap;
};

View file

@ -88,8 +88,9 @@ class CompositableForwarder : public KnowsCompositor {
const gfx::IntSize aSize,
const TextureFlags aFlags) = 0;
virtual void EnableAsyncCompositable(CompositableClient* aCompositable,
bool aEnable) = 0;
virtual void EnableRemoteTexturePushCallback(
CompositableClient* aCompositable, const RemoteTextureOwnerId aOwnerId,
const gfx::IntSize aSize, const TextureFlags aFlags) = 0;
virtual void UpdateFwdTransactionId() = 0;
virtual uint64_t GetFwdTransactionId() = 0;

View file

@ -1,76 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "CompositableInProcessManager.h"
#include "mozilla/layers/CompositorThread.h"
namespace mozilla::layers {
std::map<std::pair<base::ProcessId, uint64_t>, RefPtr<WebRenderImageHost>>
CompositableInProcessManager::sCompositables;
StaticMutex CompositableInProcessManager::sMutex;
uint32_t CompositableInProcessManager::sNamespace(0);
Atomic<uint32_t> CompositableInProcessManager::sNextResourceId(1);
Atomic<uint64_t> CompositableInProcessManager::sNextHandle(1);
/* static */ void CompositableInProcessManager::Initialize(
uint32_t aNamespace) {
MOZ_ASSERT(NS_IsMainThread());
sNamespace = aNamespace;
}
/* static */ void CompositableInProcessManager::Shutdown() {
MOZ_ASSERT(NS_IsMainThread());
StaticMutexAutoLock lock(sMutex);
sCompositables.clear();
}
/* static */ RefPtr<WebRenderImageHost> CompositableInProcessManager::Add(
const CompositableHandle& aHandle, base::ProcessId aForPid,
const TextureInfo& aTextureInfo) {
MOZ_RELEASE_ASSERT(aHandle.Value());
StaticMutexAutoLock lock(sMutex);
const auto key = std::pair(aForPid, aHandle.Value());
if (sCompositables.find(key) != sCompositables.end()) {
MOZ_ASSERT_UNREACHABLE("Duplicate handle!");
return nullptr;
}
auto host = MakeRefPtr<WebRenderImageHost>(aTextureInfo);
sCompositables[key] = host;
host->SetAsyncRef(AsyncCompositableRef(aForPid, aHandle));
return host;
}
/* static */ RefPtr<WebRenderImageHost> CompositableInProcessManager::Find(
const CompositableHandle& aHandle, base::ProcessId aForPid) {
StaticMutexAutoLock lock(sMutex);
const auto key = std::pair(aForPid, aHandle.Value());
const auto i = sCompositables.find(key);
if (NS_WARN_IF(i == sCompositables.end())) {
return nullptr;
}
return i->second;
}
/* static */ void CompositableInProcessManager::Release(
const CompositableHandle& aHandle, base::ProcessId aForPid) {
StaticMutexAutoLock lock(sMutex);
const auto key = std::pair(aForPid, aHandle.Value());
const auto i = sCompositables.find(key);
if (NS_WARN_IF(i == sCompositables.end())) {
return;
}
sCompositables.erase(i);
}
} // namespace mozilla::layers

View file

@ -1,69 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/WebRenderImageHost.h"
#include "mozilla/webrender/WebRenderTypes.h"
#include "mozilla/Atomics.h"
#include "mozilla/Mutex.h"
#include <map>
#include <utility>
namespace mozilla::layers {
/**
* CompostaibleInProcessManager is responsible for tracking textures that the
* content process knows nothing about, beyond the CompositableHandle itself
* for the purpose of binding to an AsyncImagePipeline in the display list.
*
* Hence the compositor process is responsible for creating and updating the
* WebRenderImageHost object. This will allow frames to be composited without
* interacting with the content process.
*/
class CompositableInProcessManager final {
public:
static void Initialize(uint32_t aNamespace);
static void Shutdown();
static RefPtr<WebRenderImageHost> Add(const CompositableHandle& aHandle,
base::ProcessId aForPid,
const TextureInfo& aTextureInfo);
static RefPtr<WebRenderImageHost> Find(const CompositableHandle& aHandle,
base::ProcessId aForPid);
static void Release(const CompositableHandle& aHandle,
base::ProcessId aForPid);
static CompositableHandle GetNextHandle() {
return CompositableHandle(sNextHandle++);
}
static uint32_t GetNextResourceId() {
uint32_t resourceId = sNextResourceId++;
MOZ_RELEASE_ASSERT(resourceId != 0);
return resourceId;
}
static wr::ExternalImageId GetNextExternalImageId() {
return wr::ToExternalImageId(GetShiftedNamespace() | GetNextResourceId());
}
private:
static uint64_t GetShiftedNamespace() {
MOZ_ASSERT(sNamespace != 0);
return static_cast<uint64_t>(sNamespace) << 32;
}
static std::map<std::pair<base::ProcessId, uint64_t>,
RefPtr<WebRenderImageHost>>
sCompositables;
static StaticMutex sMutex MOZ_UNANNOTATED;
static uint32_t sNamespace;
static Atomic<uint32_t> sNextResourceId;
static Atomic<uint64_t> sNextHandle;
};
} // namespace mozilla::layers

View file

@ -92,15 +92,14 @@ bool CompositableParentManager::ReceiveCompositableUpdate(
op.textureFlags());
break;
}
case CompositableOperationDetail::TOpEnableAsyncCompositable: {
const OpEnableAsyncCompositable& op =
aDetail.get_OpEnableAsyncCompositable();
if (op.enable()) {
aCompositable->SetAsyncRef(
AsyncCompositableRef(GetChildProcessId(), aHandle));
} else {
aCompositable->SetAsyncRef(AsyncCompositableRef());
}
case CompositableOperationDetail::TOpEnableRemoteTexturePushCallback: {
const OpEnableRemoteTexturePushCallback& op =
aDetail.get_OpEnableRemoteTexturePushCallback();
aCompositable->SetAsyncRef(
AsyncCompositableRef(GetChildProcessId(), aHandle));
aCompositable->EnableRemoteTexturePushCallback(
op.ownerId(), GetChildProcessId(), op.size(), op.textureFlags());
break;
}
case CompositableOperationDetail::TOpDeliverAcquireFence: {

View file

@ -145,9 +145,16 @@ void ImageBridgeChild::UseRemoteTexture(CompositableClient* aCompositable,
OpUseRemoteTexture(aTextureId, aOwnerId, aSize, aFlags)));
}
void ImageBridgeChild::EnableAsyncCompositable(
CompositableClient* aCompositable, bool aEnable) {
// On ImageBridge, Compositable is always async.
void ImageBridgeChild::EnableRemoteTexturePushCallback(
CompositableClient* aCompositable, const RemoteTextureOwnerId aOwnerId,
const gfx::IntSize aSize, const TextureFlags aFlags) {
MOZ_ASSERT(aCompositable);
MOZ_ASSERT(aCompositable->GetIPCHandle());
MOZ_ASSERT(aCompositable->IsConnected());
mTxn->AddNoSwapEdit(CompositableOperation(
aCompositable->GetIPCHandle(),
OpEnableRemoteTexturePushCallback(aOwnerId, aSize, aFlags)));
}
void ImageBridgeChild::HoldUntilCompositableRefReleasedIfNecessary(

View file

@ -251,8 +251,10 @@ class ImageBridgeChild final : public PImageBridgeChild,
const gfx::IntSize aSize,
const TextureFlags aFlags) override;
void EnableAsyncCompositable(CompositableClient* aCompositable,
bool aEnable) override;
void EnableRemoteTexturePushCallback(CompositableClient* aCompositable,
const RemoteTextureOwnerId aOwnerId,
const gfx::IntSize aSize,
const TextureFlags aFlags) override;
void ReleaseCompositable(const CompositableHandle& aHandle) override;

View file

@ -208,7 +208,7 @@ struct ParamTraits<mozilla::layers::CompositableHandleOwner>
: public ContiguousEnumSerializerInclusive<
mozilla::layers::CompositableHandleOwner,
mozilla::layers::CompositableHandleOwner::WebRenderBridge,
mozilla::layers::CompositableHandleOwner::InProcessManager> {};
mozilla::layers::CompositableHandleOwner::ImageBridge> {};
template <>
struct ParamTraits<mozilla::layers::RemoteTextureId> {

View file

@ -295,8 +295,10 @@ struct OpUseRemoteTexture {
TextureFlags textureFlags;
};
struct OpEnableAsyncCompositable {
bool enable;
struct OpEnableRemoteTexturePushCallback {
RemoteTextureOwnerId ownerId;
IntSize size;
TextureFlags textureFlags;
};
struct OpNotifyNotUsed {
@ -323,7 +325,7 @@ union CompositableOperationDetail {
OpUseRemoteTexture;
OpEnableAsyncCompositable;
OpEnableRemoteTexturePushCallback;
OpDeliverAcquireFence;
};

View file

@ -149,7 +149,6 @@ EXPORTS.mozilla.layers += [
"ipc/CanvasThread.h",
"ipc/CanvasTranslator.h",
"ipc/CompositableForwarder.h",
"ipc/CompositableInProcessManager.h",
"ipc/CompositableTransactionParent.h",
"ipc/CompositorBridgeChild.h",
"ipc/CompositorBridgeParent.h",
@ -370,7 +369,6 @@ UNIFIED_SOURCES += [
"ipc/CanvasThread.cpp",
"ipc/CanvasTranslator.cpp",
"ipc/CompositableForwarder.cpp",
"ipc/CompositableInProcessManager.cpp",
"ipc/CompositableTransactionParent.cpp",
"ipc/CompositorBench.cpp",
"ipc/CompositorBridgeChild.cpp",

View file

@ -462,10 +462,12 @@ void WebRenderBridgeChild::UseRemoteTexture(CompositableClient* aCompositable,
OpUseRemoteTexture(aTextureId, aOwnerId, aSize, aFlags)));
}
void WebRenderBridgeChild::EnableAsyncCompositable(
CompositableClient* aCompositable, bool aEnable) {
void WebRenderBridgeChild::EnableRemoteTexturePushCallback(
CompositableClient* aCompositable, const RemoteTextureOwnerId aOwnerId,
const gfx::IntSize aSize, const TextureFlags aFlags) {
AddWebRenderParentCommand(CompositableOperation(
aCompositable->GetIPCHandle(), OpEnableAsyncCompositable(aEnable)));
aCompositable->GetIPCHandle(),
OpEnableRemoteTexturePushCallback(aOwnerId, aSize, aFlags)));
}
void WebRenderBridgeChild::UpdateFwdTransactionId() {

View file

@ -205,8 +205,10 @@ class WebRenderBridgeChild final : public PWebRenderBridgeChild,
const RemoteTextureOwnerId aOwnerId,
const gfx::IntSize aSize,
const TextureFlags aFlags) override;
void EnableAsyncCompositable(CompositableClient* aCompositable,
bool aEnable) override;
void EnableRemoteTexturePushCallback(CompositableClient* aCompositable,
const RemoteTextureOwnerId aOwnerId,
const gfx::IntSize aSize,
const TextureFlags aFlags) override;
void UpdateFwdTransactionId() override;
uint64_t GetFwdTransactionId() override;
bool InForwarderThread() override;

View file

@ -24,7 +24,6 @@
#include "mozilla/layers/AnimationHelper.h"
#include "mozilla/layers/APZSampler.h"
#include "mozilla/layers/APZUpdater.h"
#include "mozilla/layers/CompositableInProcessManager.h"
#include "mozilla/layers/Compositor.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorAnimationStorage.h"
@ -1771,9 +1770,6 @@ void WebRenderBridgeParent::AddPipelineIdForCompositable(
host = imageBridge->FindCompositable(aHandle);
break;
}
case CompositableHandleOwner::InProcessManager:
host = CompositableInProcessManager::Find(aHandle, OtherPid());
break;
}
if (!host) {

View file

@ -2262,24 +2262,6 @@ bool WebRenderCommandBuilder::PushImageProvider(
return true;
}
void WebRenderCommandBuilder::PushInProcessImage(
nsDisplayItem* aItem, const CompositableHandle& aHandle,
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
const LayoutDeviceRect& aAsyncImageBounds) {
RefPtr<WebRenderInProcessImageData> imageData =
CreateOrRecycleWebRenderUserData<WebRenderInProcessImageData>(aItem);
MOZ_ASSERT(imageData);
auto rendering = wr::ToImageRendering(aItem->Frame()->UsedImageRendering());
LayoutDeviceRect scBounds(LayoutDevicePoint(0, 0), aAsyncImageBounds.Size());
imageData->CreateWebRenderCommands(aBuilder, aHandle, aSc, aAsyncImageBounds,
scBounds, VideoInfo::Rotation::kDegree_0,
rendering, wr::MixBlendMode::Normal,
!aItem->BackfaceIsHidden());
}
static void PaintItemByDrawTarget(nsDisplayItem* aItem, gfx::DrawTarget* aDT,
const LayoutDevicePoint& aOffset,
const IntRect& visibleRect,

View file

@ -92,13 +92,6 @@ class WebRenderCommandBuilder final {
const LayoutDeviceRect& aRect,
const LayoutDeviceRect& aClip);
void PushInProcessImage(nsDisplayItem* aItem,
const CompositableHandle& aHandle,
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
const LayoutDeviceRect& aAsyncImageBounds);
Maybe<wr::ImageMask> BuildWrMaskImage(
nsDisplayMasksAndClipPaths* aMaskItem, wr::DisplayListBuilder& aBuilder,
wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc,

View file

@ -40,6 +40,14 @@ WebRenderImageHost::~WebRenderImageHost() {
}
void WebRenderImageHost::OnReleased() {
if (mRemoteTextureOwnerIdOfPushCallback) {
RemoteTextureMap::Get()->UnregisterRemoteTexturePushListener(
*mRemoteTextureOwnerIdOfPushCallback, mForPidOfPushCallback, this);
mRemoteTextureOwnerIdOfPushCallback = Nothing();
mSizeOfPushCallback = gfx::IntSize();
mFlagsOfPushCallback = TextureFlags::NO_FLAGS;
}
if (mRemoteTextureHost) {
mRemoteTextureHost = nullptr;
}
@ -138,6 +146,40 @@ void WebRenderImageHost::UseRemoteTexture(const RemoteTextureId aTextureId,
}
}
void WebRenderImageHost::EnableRemoteTexturePushCallback(
const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid,
const gfx::IntSize aSize, const TextureFlags aFlags) {
if (!GetAsyncRef()) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return;
}
if (mRemoteTextureOwnerIdOfPushCallback.isSome()) {
RemoteTextureMap::Get()->UnregisterRemoteTexturePushListener(aOwnerId,
aForPid, this);
}
RemoteTextureMap::Get()->RegisterRemoteTexturePushListener(aOwnerId, aForPid,
this);
mRemoteTextureOwnerIdOfPushCallback = Some(aOwnerId);
mForPidOfPushCallback = aForPid;
mSizeOfPushCallback = aSize;
mFlagsOfPushCallback = aFlags;
}
void WebRenderImageHost::NotifyPushTexture(const RemoteTextureId aTextureId,
const RemoteTextureOwnerId aOwnerId,
const base::ProcessId aForPid) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
if (mRemoteTextureOwnerIdOfPushCallback != Some(aOwnerId)) {
// RemoteTextureOwnerId is already obsoleted
return;
}
UseRemoteTexture(aTextureId, aOwnerId, aForPid, mSizeOfPushCallback,
mFlagsOfPushCallback);
}
void WebRenderImageHost::CleanupResources() {
ClearImages();
SetCurrentTextureHost(nullptr);

View file

@ -35,6 +35,15 @@ class WebRenderImageHost : public CompositableHost, public ImageComposite {
const TextureFlags aFlags) override;
void RemoveTextureHost(TextureHost* aTexture) override;
void EnableRemoteTexturePushCallback(const RemoteTextureOwnerId aOwnerId,
const base::ProcessId aForPid,
const gfx::IntSize aSize,
const TextureFlags aFlags) override;
void NotifyPushTexture(const RemoteTextureId aTextureId,
const RemoteTextureOwnerId aOwnerId,
const base::ProcessId aForPid) override;
void Dump(std::stringstream& aStream, const char* aPrefix = "",
bool aDumpHtml = false) override;
@ -73,6 +82,11 @@ class WebRenderImageHost : public CompositableHost, public ImageComposite {
CompositableTextureHostRef mCurrentTextureHost;
CompositableTextureHostRef mRemoteTextureHost;
Maybe<RemoteTextureOwnerId> mRemoteTextureOwnerIdOfPushCallback;
base::ProcessId mForPidOfPushCallback;
gfx::IntSize mSizeOfPushCallback;
TextureFlags mFlagsOfPushCallback = TextureFlags::NO_FLAGS;
};
} // namespace layers

View file

@ -287,60 +287,6 @@ bool WebRenderImageProviderData::Invalidate(ImageProviderId aProviderId) const {
return NS_SUCCEEDED(rv) && mKey.ref() == key;
}
WebRenderInProcessImageData::WebRenderInProcessImageData(
RenderRootStateManager* aManager, nsDisplayItem* aItem)
: WebRenderUserData(aManager, aItem) {}
WebRenderInProcessImageData::WebRenderInProcessImageData(
RenderRootStateManager* aManager, uint32_t aDisplayItemKey,
nsIFrame* aFrame)
: WebRenderUserData(aManager, aDisplayItemKey, aFrame) {}
WebRenderInProcessImageData::~WebRenderInProcessImageData() {
if (mPipelineId) {
mManager->RemovePipelineIdForCompositable(mPipelineId.ref());
}
}
void WebRenderInProcessImageData::CreateWebRenderCommands(
mozilla::wr::DisplayListBuilder& aBuilder,
const CompositableHandle& aHandle, const StackingContextHelper& aSc,
const LayoutDeviceRect& aBounds, const LayoutDeviceRect& aSCBounds,
VideoInfo::Rotation aRotation, const wr::ImageRendering& aFilter,
const wr::MixBlendMode& aMixBlendMode, bool aIsBackfaceVisible) {
MOZ_ASSERT(aHandle);
if (mPipelineId.isSome() && !(mHandle == aHandle)) {
// In this case, we need to remove the existed pipeline and create new one
// because the CompositableHandle has changed.
WrBridge()->RemovePipelineIdForCompositable(mPipelineId.ref());
mPipelineId.reset();
}
if (!mPipelineId) {
// Alloc in process image pipeline id.
mPipelineId =
Some(WrBridge()->GetCompositorBridgeChild()->GetNextPipelineId());
WrBridge()->AddPipelineIdForCompositable(
mPipelineId.ref(), aHandle, CompositableHandleOwner::InProcessManager);
mHandle = aHandle;
}
// Push IFrame for in process image pipeline.
//
// We don't push a stacking context for this in process image pipeline here.
// Instead, we do it inside the iframe that hosts the image. As a result,
// a bunch of the calculations normally done as part of that stacking
// context need to be done manually and pushed over to the parent side,
// where it will be done when we build the display list for the iframe.
// That happens in AsyncImagePipelineManager.
aBuilder.PushIFrame(aBounds, aIsBackfaceVisible, mPipelineId.ref(),
/*ignoreMissingPipelines*/ false);
WrBridge()->AddWebRenderParentCommand(OpUpdateAsyncImagePipeline(
mPipelineId.value(), aSCBounds, aRotation, aFilter, aMixBlendMode));
}
WebRenderFallbackData::WebRenderFallbackData(RenderRootStateManager* aManager,
nsDisplayItem* aItem)
: WebRenderUserData(aManager, aItem), mOpacity(1.0f), mInvalid(false) {}

View file

@ -49,7 +49,6 @@ class WebRenderCanvasRenderer;
class WebRenderCanvasRendererAsync;
class WebRenderImageData;
class WebRenderImageProviderData;
class WebRenderInProcessImageData;
class WebRenderFallbackData;
class RenderRootStateManager;
class WebRenderGroupData;
@ -84,9 +83,6 @@ class WebRenderUserData {
virtual WebRenderImageData* AsImageData() { return nullptr; }
virtual WebRenderImageProviderData* AsImageProviderData() { return nullptr; }
virtual WebRenderInProcessImageData* AsInProcessImageData() {
return nullptr;
}
virtual WebRenderFallbackData* AsFallbackData() { return nullptr; }
virtual WebRenderCanvasData* AsCanvasData() { return nullptr; }
virtual WebRenderGroupData* AsGroupData() { return nullptr; }
@ -213,30 +209,6 @@ class WebRenderImageProviderData final : public WebRenderUserData {
image::ImgDrawResult mDrawResult = image::ImgDrawResult::NOT_READY;
};
class WebRenderInProcessImageData final : public WebRenderUserData {
public:
WebRenderInProcessImageData(RenderRootStateManager* aManager,
nsDisplayItem* aItem);
WebRenderInProcessImageData(RenderRootStateManager* aManager,
uint32_t aDisplayItemKey, nsIFrame* aFrame);
~WebRenderInProcessImageData() override;
WebRenderInProcessImageData* AsInProcessImageData() override { return this; }
UserDataType GetType() override { return UserDataType::eInProcessImage; }
static UserDataType Type() { return UserDataType::eInProcessImage; }
void CreateWebRenderCommands(
mozilla::wr::DisplayListBuilder& aBuilder,
const CompositableHandle& aHandle, const StackingContextHelper& aSc,
const LayoutDeviceRect& aBounds, const LayoutDeviceRect& aSCBounds,
VideoInfo::Rotation aRotation, const wr::ImageRendering& aFilter,
const wr::MixBlendMode& aMixBlendMode, bool aIsBackfaceVisible);
protected:
Maybe<wr::PipelineId> mPipelineId;
CompositableHandle mHandle = CompositableHandle();
};
/// Used for fallback rendering.
///
/// In most cases this uses blob images but it can also render on the content

View file

@ -18,7 +18,6 @@
#include "mozilla/gfx/GPUParent.h"
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/glean/GleanMetrics.h"
#include "mozilla/layers/CompositableInProcessManager.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorManagerParent.h"
@ -131,7 +130,6 @@ void RenderThread::Start(uint32_t aNamespace) {
#ifdef XP_WIN
widget::WinCompositorWindowThread::Start();
#endif
layers::CompositableInProcessManager::Initialize(aNamespace);
layers::SharedSurfacesParent::Initialize();
RefPtr<Runnable> runnable = WrapRunnable(
@ -159,7 +157,6 @@ void RenderThread::ShutDown() {
oldThread->Shutdown();
layers::SharedSurfacesParent::Shutdown();
layers::CompositableInProcessManager::Shutdown();
#ifdef XP_WIN
if (widget::WinCompositorWindowThread::Get()) {

View file

@ -124,25 +124,20 @@ class nsDisplayCanvas final : public nsPaintedDisplayItem {
RefPtr<ImageContainer> container = element->GetImageContainer();
if (container) {
MOZ_ASSERT(container->IsAsync());
aManager->CommandBuilder().PushImage(this, container, aBuilder,
aResources, aSc, bounds, bounds);
return true;
}
CompositableHandle handle = element->GetCompositableHandle();
if (handle) {
aManager->CommandBuilder().PushInProcessImage(this, handle, aBuilder,
aResources, aSc, bounds);
return true;
}
return true;
}
switch (element->GetCurrentContextType()) {
case CanvasContextType::Canvas2D:
case CanvasContextType::WebGL1:
case CanvasContextType::WebGL2: {
case CanvasContextType::WebGL2:
case CanvasContextType::WebGPU: {
bool isRecycled;
RefPtr<WebRenderCanvasData> canvasData =
aManager->CommandBuilder()
@ -194,33 +189,6 @@ class nsDisplayCanvas final : public nsPaintedDisplayItem {
mixBlendMode));
break;
}
case CanvasContextType::WebGPU: {
nsHTMLCanvasFrame* canvasFrame =
static_cast<nsHTMLCanvasFrame*>(mFrame);
HTMLCanvasElement* canvasElement =
static_cast<HTMLCanvasElement*>(canvasFrame->GetContent());
webgpu::CanvasContext* canvasContext =
canvasElement->GetWebGPUContext();
if (!canvasContext || !canvasContext->mHandle) {
return true;
}
nsIntSize canvasSizeInPx = canvasFrame->GetCanvasSize();
IntrinsicSize intrinsicSize =
IntrinsicSizeFromCanvasSize(canvasSizeInPx);
AspectRatio intrinsicRatio =
IntrinsicRatioFromCanvasSize(canvasSizeInPx);
nsRect area =
mFrame->GetContentRectRelativeToSelf() + ToReferenceFrame();
nsRect dest = nsLayoutUtils::ComputeObjectDestRect(
area, intrinsicSize, intrinsicRatio, mFrame->StylePosition());
LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
dest, mFrame->PresContext()->AppUnitsPerDevPixel());
aManager->CommandBuilder().PushInProcessImage(
this, canvasContext->mHandle, aBuilder, aResources, aSc, bounds);
break;
}
case CanvasContextType::ImageBitmap: {
nsHTMLCanvasFrame* canvasFrame =
static_cast<nsHTMLCanvasFrame*>(mFrame);