Bug 1868928 - Handle ApplyAsyncImageForPipeline() for AsyncImagePipeline of sync WebRenderImageHost after waiting RemoteTextures ready at WebRenderAPI r=gfx-reviewers,lsalzman

This is preparation for Bug 1868927.

By deferring ApplyAsyncImageForPipeline() for TextureHost in AsyncImagePipeline of synchronous WebRenderImageHost, ApplyAsyncImageForPipeline() can be called after the RemoteTextureHostWrapper is in the ready state.

Differential Revision: https://phabricator.services.mozilla.com/D197320
This commit is contained in:
sotaro 2024-01-05 21:45:54 +00:00
Родитель fd4f8e4eee
Коммит cfd47236fe
10 изменённых файлов: 305 добавлений и 86 удалений

Просмотреть файл

@ -353,17 +353,17 @@ void RemoteTextureMap::PushTexture(
owner->mWaitingTextureDataHolders.push_back(std::move(textureData));
if (!owner->mIsSyncMode) {
{
renderingReadyCallbacks =
GetRenderingReadyCallbacks(lock, owner, aTextureId);
// Update mAsyncRemoteTextureHost for async mode.
// Update mRemoteTextureHost.
// This happens when PushTexture() with RemoteTextureId is called after
// GetRemoteTextureForDisplayList() with the RemoteTextureId.
const auto key = std::pair(aForPid, aTextureId);
auto it = mRemoteTextureHostWrapperHolders.find(key);
if (it != mRemoteTextureHostWrapperHolders.end()) {
MOZ_ASSERT(!it->second->mAsyncRemoteTextureHost);
it->second->mAsyncRemoteTextureHost = aTextureHost;
MOZ_ASSERT(!it->second->mRemoteTextureHost);
it->second->mRemoteTextureHost = aTextureHost;
}
}
@ -971,18 +971,17 @@ bool RemoteTextureMap::GetRemoteTextureForDisplayList(
gfxCriticalNoteOnce << "remote texture does not exist";
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
}
}
// Update mAsyncRemoteTextureHost for async mode
if (textureId == owner->mLatestTextureId) {
const auto key = std::pair(forPid, textureId);
auto it = mRemoteTextureHostWrapperHolders.find(key);
if (it != mRemoteTextureHostWrapperHolders.end() &&
!it->second->mAsyncRemoteTextureHost) {
it->second->mAsyncRemoteTextureHost = owner->mLatestTextureHost;
} else {
MOZ_ASSERT(it->second->mAsyncRemoteTextureHost ==
owner->mLatestTextureHost);
}
// Update mRemoteTextureHost
if (textureId == owner->mLatestTextureId) {
const auto key = std::pair(forPid, textureId);
auto it = mRemoteTextureHostWrapperHolders.find(key);
if (it != mRemoteTextureHostWrapperHolders.end() &&
!it->second->mRemoteTextureHost) {
it->second->mRemoteTextureHost = owner->mLatestTextureHost;
} else {
MOZ_ASSERT(it->second->mRemoteTextureHost == owner->mLatestTextureHost);
}
}
@ -1009,7 +1008,7 @@ wr::MaybeExternalImageId RemoteTextureMap::GetExternalImageIdOfRemoteTexture(
return Nothing();
}
TextureHost* remoteTexture = it->second->mAsyncRemoteTextureHost;
TextureHost* remoteTexture = it->second->mRemoteTextureHost;
auto* owner = GetTextureOwner(lock, aOwnerId, aForPid);
if (!owner) {
@ -1109,8 +1108,8 @@ void RemoteTextureMap::UnregisterRemoteTextureHostWrapper(
return;
}
releasingTextures.emplace_back(it->second->mRemoteTextureHostWrapper);
if (it->second->mAsyncRemoteTextureHost) {
releasingTextures.emplace_back(it->second->mAsyncRemoteTextureHost);
if (it->second->mRemoteTextureHost) {
releasingTextures.emplace_back(it->second->mRemoteTextureHost);
}
mRemoteTextureHostWrapperHolders.erase(it);
@ -1208,10 +1207,10 @@ bool RemoteTextureMap::CheckRemoteTextureReady(
return true;
}
if (it->second->mAsyncRemoteTextureHost) {
if (it->second->mRemoteTextureHost) {
return true;
}
MOZ_ASSERT(!it->second->mAsyncRemoteTextureHost);
MOZ_ASSERT(!it->second->mRemoteTextureHost);
// Check if RemoteTextureId is as expected.
if (!owner->mRenderingReadyCallbackHolders.empty()) {
@ -1247,7 +1246,7 @@ bool RemoteTextureMap::WaitRemoteTextureReady(const RemoteTextureInfo& aInfo) {
}
const TimeDuration timeout = TimeDuration::FromMilliseconds(1000);
TextureHost* remoteTexture = it->second->mAsyncRemoteTextureHost;
TextureHost* remoteTexture = it->second->mRemoteTextureHost;
while (!remoteTexture) {
CVStatus status = mMonitor.Wait(timeout);
@ -1264,7 +1263,7 @@ bool RemoteTextureMap::WaitRemoteTextureReady(const RemoteTextureInfo& aInfo) {
return false;
}
remoteTexture = it->second->mAsyncRemoteTextureHost;
remoteTexture = it->second->mRemoteTextureHost;
if (!remoteTexture) {
auto* owner = GetTextureOwner(lock, aInfo.mOwnerId, aInfo.mForPid);
// When owner is alreay unregistered, remote texture will not be pushed.

Просмотреть файл

@ -378,7 +378,7 @@ class RemoteTextureMap {
// Hold compositable ref of remote texture of the RemoteTextureId in async
// mode. It is for keeping the texture alive during its rendering by
// WebRender.
CompositableTextureHostRef mAsyncRemoteTextureHost;
CompositableTextureHostRef mRemoteTextureHost;
bool mReadyCheckSuppressed = false;
};

Просмотреть файл

@ -210,6 +210,7 @@ EXPORTS.mozilla.layers += [
"TreeTraversal.h",
"UpdateImageHelper.h",
"wr/AsyncImagePipelineManager.h",
"wr/AsyncImagePipelineOp.h",
"wr/ClipManager.h",
"wr/DisplayItemCache.h",
"wr/HitTestInfoManager.h",
@ -418,6 +419,7 @@ UNIFIED_SOURCES += [
"TextureSourceProvider.cpp",
"TextureWrapperImage.cpp",
"wr/AsyncImagePipelineManager.cpp",
"wr/AsyncImagePipelineOp.cpp",
"wr/ClipManager.cpp",
"wr/DisplayItemCache.cpp",
"wr/HitTestInfoManager.cpp",

Просмотреть файл

@ -12,6 +12,7 @@
#include "CompositableHost.h"
#include "gfxEnv.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/layers/AsyncImagePipelineOp.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/RemoteTextureHostWrapper.h"
#include "mozilla/layers/SharedSurfacesParent.h"
@ -476,7 +477,9 @@ void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
const wr::PipelineId& aPipelineId, wr::TransactionBuilder& aTxn,
wr::TransactionBuilder& aTxnForImageBridge, RemoteTextureInfoList* aList) {
wr::TransactionBuilder& aTxnForImageBridge,
AsyncImagePipelineOps* aPendingOps,
RemoteTextureInfoList* aPendingRemoteTextures) {
AsyncImagePipeline* pipeline =
mAsyncImagePipelines.Get(wr::AsUint64(aPipelineId));
if (!pipeline) {
@ -486,7 +489,7 @@ void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
// ready event of RemoteTexture that uses ImageBridge do not need to be
// checked here.
if (pipeline->mImageHost->GetAsyncRef()) {
aList = nullptr;
aPendingRemoteTextures = nullptr;
}
wr::TransactionBuilder fastTxn(mApi, /* aUseSceneBuilderThread */ false);
@ -512,16 +515,38 @@ void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
auto* wrapper = texture ? texture->AsRemoteTextureHostWrapper() : nullptr;
// Store pending remote texture that is used for waiting at WebRenderAPI.
if (aList && texture && wrapper && texture != pipeline->mCurrentTexture &&
texture->NumSubTextures() != 0 && wrapper->IsReadyForRendering()) {
aList->mList.emplace(wrapper->mTextureId, wrapper->mOwnerId,
wrapper->mForPid);
if (aPendingRemoteTextures && texture &&
texture != pipeline->mCurrentTexture && texture->NumSubTextures() != 0 &&
wrapper && wrapper->IsReadyForRendering()) {
aPendingRemoteTextures->mList.emplace(wrapper->mTextureId,
wrapper->mOwnerId, wrapper->mForPid);
}
if (aPendingOps && !pipeline->mImageHost->GetAsyncRef()) {
aPendingOps->mList.emplace(AsyncImagePipelineOp::ApplyAsyncImageForPipeline(
this, aPipelineId, texture));
return;
}
ApplyAsyncImageForPipeline(epoch, aPipelineId, pipeline, texture,
sceneBuilderTxn, maybeFastTxn);
}
void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
const wr::PipelineId& aPipelineId, TextureHost* aTexture,
wr::TransactionBuilder& aTxn) {
AsyncImagePipeline* pipeline =
mAsyncImagePipelines.Get(wr::AsUint64(aPipelineId));
if (!pipeline) {
return;
}
MOZ_ASSERT(!pipeline->mImageHost->GetAsyncRef());
wr::Epoch epoch = GetNextImageEpoch();
ApplyAsyncImageForPipeline(epoch, aPipelineId, pipeline, aTexture, aTxn,
aTxn);
}
void AsyncImagePipelineManager::SetEmptyDisplayList(
const wr::PipelineId& aPipelineId, wr::TransactionBuilder& aTxn,
wr::TransactionBuilder& aTxnForImageBridge) {

Просмотреть файл

@ -109,10 +109,15 @@ class AsyncImagePipelineManager final {
const wr::MixBlendMode& aMixBlendMode);
void ApplyAsyncImagesOfImageBridge(wr::TransactionBuilder& aSceneBuilderTxn,
wr::TransactionBuilder& aFastTxn);
void ApplyAsyncImageForPipeline(
const wr::PipelineId& aPipelineId, wr::TransactionBuilder& aTxn,
wr::TransactionBuilder& aTxnForImageBridge,
AsyncImagePipelineOps* aPendingOps,
RemoteTextureInfoList* aPendingRemoteTextures);
void ApplyAsyncImageForPipeline(const wr::PipelineId& aPipelineId,
wr::TransactionBuilder& aTxn,
wr::TransactionBuilder& aTxnForImageBridge,
RemoteTextureInfoList* aList);
TextureHost* aTexture,
wr::TransactionBuilder& aTxn);
void SetEmptyDisplayList(const wr::PipelineId& aPipelineId,
wr::TransactionBuilder& aTxn,

Просмотреть файл

@ -0,0 +1,30 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "AsyncImagePipelineOp.h"
#include "mozilla/layers/AsyncImagePipelineManager.h"
namespace mozilla {
namespace layers {
void AsyncImagePipelineOps::HandleOps(wr::TransactionBuilder& aTxn) {
MOZ_ASSERT(!mList.empty());
while (!mList.empty()) {
auto& frontOp = mList.front();
auto* manager = frontOp.mAsyncImageManager;
const auto& pipelineId = frontOp.mPipelineId;
const auto& textureHost = frontOp.mTextureHost;
manager->ApplyAsyncImageForPipeline(pipelineId, textureHost, aTxn);
mList.pop();
}
}
} // namespace layers
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,73 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef MOZILLA_GFX_AsyncImagePipelineOp_H
#define MOZILLA_GFX_AsyncImagePipelineOp_H
#include <queue>
#include "mozilla/layers/TextureHost.h"
#include "mozilla/webrender/webrender_ffi.h"
#include "Units.h"
namespace mozilla {
namespace wr {
struct Transaction;
} // namespace wr
namespace layers {
class AsyncImagePipelineManager;
class TextureHost;
class AsyncImagePipelineOp {
public:
enum class Tag {
ApplyAsyncImageForPipeline,
};
const Tag mTag;
AsyncImagePipelineManager* const mAsyncImageManager;
const wr::PipelineId mPipelineId;
const CompositableTextureHostRef mTextureHost;
private:
AsyncImagePipelineOp(const Tag aTag,
AsyncImagePipelineManager* aAsyncImageManager,
const wr::PipelineId& aPipelineId,
TextureHost* aTextureHost)
: mTag(aTag),
mAsyncImageManager(aAsyncImageManager),
mPipelineId(aPipelineId),
mTextureHost(aTextureHost) {
MOZ_ASSERT(mTag == Tag::ApplyAsyncImageForPipeline);
}
public:
static AsyncImagePipelineOp ApplyAsyncImageForPipeline(
AsyncImagePipelineManager* aAsyncImageManager,
const wr::PipelineId& aPipelineId, TextureHost* aTextureHost) {
return AsyncImagePipelineOp(Tag::ApplyAsyncImageForPipeline,
aAsyncImageManager, aPipelineId, aTextureHost);
}
};
struct AsyncImagePipelineOps {
explicit AsyncImagePipelineOps(wr::Transaction* aTransaction)
: mTransaction(aTransaction) {}
void HandleOps(wr::TransactionBuilder& aTxn);
wr::Transaction* const mTransaction;
std::queue<AsyncImagePipelineOp> mList;
};
} // namespace layers
} // namespace mozilla
#endif // MOZILLA_GFX_AsyncImagePipelineOp_H

Просмотреть файл

@ -1459,23 +1459,31 @@ bool WebRenderBridgeParent::ProcessWebRenderParentCommands(
case WebRenderParentCommand::TOpUpdateAsyncImagePipeline: {
const OpUpdateAsyncImagePipeline& op =
cmd.get_OpUpdateAsyncImagePipeline();
auto* pendingOps = mApi->GetPendingAsyncImagePipelineOps(aTxn);
auto* pendingRemotetextures = mApi->GetPendingRemoteTextureInfoList();
mAsyncImageManager->UpdateAsyncImagePipeline(
op.pipelineId(), op.scBounds(), op.rotation(), op.filter(),
op.mixBlendMode());
auto* list = mApi->GetPendingRemoteTextureInfoList();
MOZ_ASSERT_IF(IsRootWebRenderBridgeParent(), !list);
mAsyncImageManager->ApplyAsyncImageForPipeline(op.pipelineId(), aTxn,
txnForImageBridge, list);
MOZ_ASSERT_IF(IsRootWebRenderBridgeParent(), !pendingRemotetextures);
mAsyncImageManager->ApplyAsyncImageForPipeline(
op.pipelineId(), aTxn, txnForImageBridge, pendingOps,
pendingRemotetextures);
break;
}
case WebRenderParentCommand::TOpUpdatedAsyncImagePipeline: {
const OpUpdatedAsyncImagePipeline& op =
cmd.get_OpUpdatedAsyncImagePipeline();
aTxn.InvalidateRenderedFrame(wr::RenderReasons::ASYNC_IMAGE);
auto* list = mApi->GetPendingRemoteTextureInfoList();
MOZ_ASSERT_IF(IsRootWebRenderBridgeParent(), !list);
mAsyncImageManager->ApplyAsyncImageForPipeline(op.pipelineId(), aTxn,
txnForImageBridge, list);
auto* pendingOps = mApi->GetPendingAsyncImagePipelineOps(aTxn);
auto* pendingRemotetextures = mApi->GetPendingRemoteTextureInfoList();
MOZ_ASSERT_IF(IsRootWebRenderBridgeParent(), !pendingRemotetextures);
mAsyncImageManager->ApplyAsyncImageForPipeline(
op.pipelineId(), aTxn, txnForImageBridge, pendingOps,
pendingRemotetextures);
break;
}
case WebRenderParentCommand::TCompositableOperation: {

Просмотреть файл

@ -217,11 +217,24 @@ class RemoveRenderer : public RendererEvent {
TransactionBuilder::TransactionBuilder(WebRenderAPI* aApi,
bool aUseSceneBuilderThread)
: mUseSceneBuilderThread(aUseSceneBuilderThread),
mApiBackend(aApi->GetBackendType()) {
mApiBackend(aApi->GetBackendType()),
mOwnsData(true) {
mTxn = wr_transaction_new(mUseSceneBuilderThread);
}
TransactionBuilder::~TransactionBuilder() { wr_transaction_delete(mTxn); }
TransactionBuilder::TransactionBuilder(WebRenderAPI* aApi, Transaction* aTxn,
bool aUseSceneBuilderThread,
bool aOwnsData)
: mTxn(aTxn),
mUseSceneBuilderThread(aUseSceneBuilderThread),
mApiBackend(aApi->GetBackendType()),
mOwnsData(aOwnsData) {}
TransactionBuilder::~TransactionBuilder() {
if (mOwnsData) {
wr_transaction_delete(mTxn);
}
}
void TransactionBuilder::SetLowPriority(bool aIsLowPriority) {
wr_transaction_set_low_priority(mTxn, aIsLowPriority);
@ -460,9 +473,17 @@ void WebRenderAPI::SendTransaction(TransactionBuilder& aTxn) {
std::move(mPendingRemoteTextureInfoList)));
}
if (mPendingAsyncImagePipelineOps &&
!mPendingAsyncImagePipelineOps->mList.empty()) {
mPendingWrTransactionEvents.emplace(
WrTransactionEvent::PendingAsyncImagePipelineOps(
std::move(mPendingAsyncImagePipelineOps), this, aTxn.Raw(),
aTxn.UseSceneBuilderThread()));
}
if (!mPendingWrTransactionEvents.empty()) {
mPendingWrTransactionEvents.emplace(WrTransactionEvent::Transaction(
aTxn.Take(), aTxn.UseSceneBuilderThread()));
this, aTxn.Take(), aTxn.UseSceneBuilderThread()));
HandleWrTransactionEvents(RemoteTextureWaitType::AsyncWait);
} else {
wr_api_send_transaction(mDocHandle, aTxn.Raw(),
@ -476,30 +497,40 @@ layers::RemoteTextureInfoList* WebRenderAPI::GetPendingRemoteTextureInfoList() {
return nullptr;
}
if (!gfx::gfxVars::UseCanvasRenderThread() ||
!StaticPrefs::webgl_out_of_process_async_present() ||
gfx::gfxVars::WebglOopAsyncPresentForceSync()) {
return nullptr;
}
// async remote texture is enabled
MOZ_ASSERT(gfx::gfxVars::UseCanvasRenderThread());
MOZ_ASSERT(StaticPrefs::webgl_out_of_process_async_present());
MOZ_ASSERT(!gfx::gfxVars::WebglOopAsyncPresentForceSync());
if (!mPendingRemoteTextureInfoList) {
mPendingRemoteTextureInfoList = MakeUnique<layers::RemoteTextureInfoList>();
}
return mPendingRemoteTextureInfoList.get();
}
layers::AsyncImagePipelineOps* WebRenderAPI::GetPendingAsyncImagePipelineOps(
TransactionBuilder& aTxn) {
if (!mRootApi) {
// root api does not support async wait RemoteTexture.
return nullptr;
}
if (!mPendingAsyncImagePipelineOps ||
mPendingAsyncImagePipelineOps->mTransaction != aTxn.Raw()) {
if (mPendingAsyncImagePipelineOps &&
!mPendingAsyncImagePipelineOps->mList.empty()) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
gfxCriticalNoteOnce << "Invalid AsyncImagePipelineOps";
}
mPendingAsyncImagePipelineOps =
MakeUnique<layers::AsyncImagePipelineOps>(aTxn.Raw());
} else {
MOZ_RELEASE_ASSERT(mPendingAsyncImagePipelineOps->mTransaction ==
aTxn.Raw());
}
return mPendingAsyncImagePipelineOps.get();
}
bool WebRenderAPI::CheckIsRemoteTextureReady(
layers::RemoteTextureInfoList* aList, const TimeStamp& aTimeStamp) {
MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread());
MOZ_ASSERT(aList);
MOZ_ASSERT(gfx::gfxVars::UseCanvasRenderThread());
MOZ_ASSERT(StaticPrefs::webgl_out_of_process_async_present());
MOZ_ASSERT(!gfx::gfxVars::WebglOopAsyncPresentForceSync());
RefPtr<WebRenderAPI> self = this;
auto callback = [self](const layers::RemoteTextureInfo&) {
@ -541,9 +572,6 @@ void WebRenderAPI::WaitRemoteTextureReady(
layers::RemoteTextureInfoList* aList) {
MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread());
MOZ_ASSERT(aList);
MOZ_ASSERT(gfx::gfxVars::UseCanvasRenderThread());
MOZ_ASSERT(StaticPrefs::webgl_out_of_process_async_present());
MOZ_ASSERT(!gfx::gfxVars::WebglOopAsyncPresentForceSync());
while (!aList->mList.empty()) {
auto& front = aList->mList.front();
@ -567,10 +595,10 @@ void WebRenderAPI::HandleWrTransactionEvents(RemoteTextureWaitType aType) {
auto& front = events.front();
switch (front.mTag) {
case WrTransactionEvent::Tag::Transaction:
wr_api_send_transaction(mDocHandle, front.Transaction(),
wr_api_send_transaction(mDocHandle, front.RawTransaction(),
front.UseSceneBuilderThread());
break;
case WrTransactionEvent::Tag::PendingRemoteTextures:
case WrTransactionEvent::Tag::PendingRemoteTextures: {
bool isReady = true;
if (aType == RemoteTextureWaitType::AsyncWait) {
isReady = CheckIsRemoteTextureReady(front.RemoteTextureInfoList(),
@ -587,10 +615,18 @@ void WebRenderAPI::HandleWrTransactionEvents(RemoteTextureWaitType aType) {
list->mList.pop();
}
}
if (!isReady) {
if (!isReady && (aType != RemoteTextureWaitType::FlushWithoutWait)) {
return;
}
break;
}
case WrTransactionEvent::Tag::PendingAsyncImagePipelineOps: {
auto* list = front.AsyncImagePipelineOps();
TransactionBuilder& txn = *front.GetTransactionBuilder();
list->HandleOps(txn);
break;
}
}
events.pop();
}
@ -891,6 +927,10 @@ RefPtr<WebRenderAPI::EndRecordingPromise> WebRenderAPI::EndRecording() {
void TransactionBuilder::Clear() { wr_resource_updates_clear(mTxn); }
Transaction* TransactionBuilder::Take() {
if (!mOwnsData) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return nullptr;
}
Transaction* txn = mTxn;
mTxn = wr_transaction_new(mUseSceneBuilderThread);
return txn;

Просмотреть файл

@ -15,6 +15,7 @@
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/gfx/CompositorHitTestInfo.h"
#include "mozilla/layers/AsyncImagePipelineOp.h"
#include "mozilla/layers/IpcResourceUpdateQueue.h"
#include "mozilla/layers/RemoteTextureMap.h"
#include "mozilla/layers/ScrollableLayerGuid.h"
@ -105,6 +106,9 @@ class TransactionBuilder final {
explicit TransactionBuilder(WebRenderAPI* aApi,
bool aUseSceneBuilderThread = true);
TransactionBuilder(WebRenderAPI* aApi, Transaction* aTxn,
bool aUseSceneBuilderThread, bool aOwnsData);
~TransactionBuilder();
void SetLowPriority(bool aIsLowPriority);
@ -206,9 +210,10 @@ class TransactionBuilder final {
Transaction* Raw() { return mTxn; }
protected:
Transaction* mTxn;
bool mUseSceneBuilderThread;
layers::WebRenderBackend mApiBackend;
Transaction* mTxn;
bool mOwnsData;
};
class TransactionWrapper final {
@ -309,6 +314,8 @@ class WebRenderAPI final {
RefPtr<EndRecordingPromise> EndRecording();
layers::RemoteTextureInfoList* GetPendingRemoteTextureInfoList();
layers::AsyncImagePipelineOps* GetPendingAsyncImagePipelineOps(
TransactionBuilder& aTxn);
void FlushPendingWrTransactionEventsWithoutWait();
void FlushPendingWrTransactionEventsWithWait();
@ -347,27 +354,14 @@ class WebRenderAPI final {
enum class Tag {
Transaction,
PendingRemoteTextures,
PendingAsyncImagePipelineOps,
};
const Tag mTag;
const TimeStamp mTimeStamp;
struct TransactionWrapper {
TransactionWrapper(wr::Transaction* aTxn, bool aUseSceneBuilderThread)
: mTxn(aTxn), mUseSceneBuilderThread(aUseSceneBuilderThread) {}
~TransactionWrapper() {
if (mTxn) {
wr_transaction_delete(mTxn);
}
}
wr::Transaction* mTxn;
const bool mUseSceneBuilderThread;
};
private:
WrTransactionEvent(const Tag aTag,
UniquePtr<TransactionWrapper>&& aTransaction)
UniquePtr<TransactionBuilder>&& aTransaction)
: mTag(aTag),
mTimeStamp(TimeStamp::Now()),
mTransaction(std::move(aTransaction)) {
@ -381,15 +375,28 @@ class WebRenderAPI final {
mPendingRemoteTextures(std::move(aPendingRemoteTextures)) {
MOZ_ASSERT(mTag == Tag::PendingRemoteTextures);
}
WrTransactionEvent(const Tag aTag,
UniquePtr<layers::AsyncImagePipelineOps>&&
aPendingAsyncImagePipelineOps,
UniquePtr<TransactionBuilder>&& aTransaction)
: mTag(aTag),
mTimeStamp(TimeStamp::Now()),
mPendingAsyncImagePipelineOps(
std::move(aPendingAsyncImagePipelineOps)),
mTransaction(std::move(aTransaction)) {
MOZ_ASSERT(mTag == Tag::PendingAsyncImagePipelineOps);
}
UniquePtr<TransactionWrapper> mTransaction;
UniquePtr<layers::RemoteTextureInfoList> mPendingRemoteTextures;
UniquePtr<layers::AsyncImagePipelineOps> mPendingAsyncImagePipelineOps;
UniquePtr<TransactionBuilder> mTransaction;
public:
static WrTransactionEvent Transaction(wr::Transaction* aTxn,
static WrTransactionEvent Transaction(WebRenderAPI* aApi,
wr::Transaction* aTxn,
bool aUseSceneBuilderThread) {
auto transaction =
MakeUnique<TransactionWrapper>(aTxn, aUseSceneBuilderThread);
auto transaction = MakeUnique<TransactionBuilder>(
aApi, aTxn, aUseSceneBuilderThread, /* aOwnsData */ true);
return WrTransactionEvent(Tag::Transaction, std::move(transaction));
}
@ -399,17 +406,37 @@ class WebRenderAPI final {
std::move(aPendingRemoteTextures));
}
wr::Transaction* Transaction() {
static WrTransactionEvent PendingAsyncImagePipelineOps(
UniquePtr<layers::AsyncImagePipelineOps>&&
aPendingAsyncImagePipelineOps,
WebRenderAPI* aApi, wr::Transaction* aTxn,
bool aUseSceneBuilderThread) {
auto transaction = MakeUnique<TransactionBuilder>(
aApi, aTxn, aUseSceneBuilderThread, /* aOwnsData */ false);
return WrTransactionEvent(Tag::PendingAsyncImagePipelineOps,
std::move(aPendingAsyncImagePipelineOps),
std::move(transaction));
}
wr::Transaction* RawTransaction() {
if (mTag == Tag::Transaction) {
return mTransaction->mTxn;
return mTransaction->Raw();
}
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return nullptr;
}
TransactionBuilder* GetTransactionBuilder() {
if (mTag == Tag::PendingAsyncImagePipelineOps) {
return mTransaction.get();
}
MOZ_CRASH("Should not be called");
return nullptr;
}
bool UseSceneBuilderThread() {
if (mTag == Tag::Transaction) {
return mTransaction->mUseSceneBuilderThread;
return mTransaction->UseSceneBuilderThread();
}
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return true;
@ -423,6 +450,15 @@ class WebRenderAPI final {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return nullptr;
}
layers::AsyncImagePipelineOps* AsyncImagePipelineOps() {
if (mTag == Tag::PendingAsyncImagePipelineOps) {
MOZ_ASSERT(mPendingAsyncImagePipelineOps);
return mPendingAsyncImagePipelineOps.get();
}
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return nullptr;
}
};
wr::DocumentHandle* mDocHandle;
@ -439,6 +475,7 @@ class WebRenderAPI final {
bool mRendererDestroyed;
UniquePtr<layers::RemoteTextureInfoList> mPendingRemoteTextureInfoList;
UniquePtr<layers::AsyncImagePipelineOps> mPendingAsyncImagePipelineOps;
std::queue<WrTransactionEvent> mPendingWrTransactionEvents;
// We maintain alive the root api to know when to shut the render backend