From cfd47236fe48c90dc92a7f47c81ed147f64c6452 Mon Sep 17 00:00:00 2001 From: sotaro Date: Fri, 5 Jan 2024 21:45:54 +0000 Subject: [PATCH] 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 --- gfx/layers/RemoteTextureMap.cpp | 43 +++++------ gfx/layers/RemoteTextureMap.h | 2 +- gfx/layers/moz.build | 2 + gfx/layers/wr/AsyncImagePipelineManager.cpp | 37 +++++++-- gfx/layers/wr/AsyncImagePipelineManager.h | 11 ++- gfx/layers/wr/AsyncImagePipelineOp.cpp | 30 +++++++ gfx/layers/wr/AsyncImagePipelineOp.h | 73 +++++++++++++++++ gfx/layers/wr/WebRenderBridgeParent.cpp | 24 ++++-- gfx/webrender_bindings/WebRenderAPI.cpp | 86 +++++++++++++++------ gfx/webrender_bindings/WebRenderAPI.h | 83 ++++++++++++++------ 10 files changed, 305 insertions(+), 86 deletions(-) create mode 100644 gfx/layers/wr/AsyncImagePipelineOp.cpp create mode 100644 gfx/layers/wr/AsyncImagePipelineOp.h diff --git a/gfx/layers/RemoteTextureMap.cpp b/gfx/layers/RemoteTextureMap.cpp index 4416b74c5e7d..47a14a090472 100644 --- a/gfx/layers/RemoteTextureMap.cpp +++ b/gfx/layers/RemoteTextureMap.cpp @@ -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. diff --git a/gfx/layers/RemoteTextureMap.h b/gfx/layers/RemoteTextureMap.h index 6ab6a88d35df..5a5673e15435 100644 --- a/gfx/layers/RemoteTextureMap.h +++ b/gfx/layers/RemoteTextureMap.h @@ -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; }; diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index 78a945189d2f..8cf8f01fd2c9 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -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", diff --git a/gfx/layers/wr/AsyncImagePipelineManager.cpp b/gfx/layers/wr/AsyncImagePipelineManager.cpp index 1b29cbf08c68..e32b00071600 100644 --- a/gfx/layers/wr/AsyncImagePipelineManager.cpp +++ b/gfx/layers/wr/AsyncImagePipelineManager.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) { diff --git a/gfx/layers/wr/AsyncImagePipelineManager.h b/gfx/layers/wr/AsyncImagePipelineManager.h index 7f797ebc4d94..7f8e68ae4125 100644 --- a/gfx/layers/wr/AsyncImagePipelineManager.h +++ b/gfx/layers/wr/AsyncImagePipelineManager.h @@ -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, diff --git a/gfx/layers/wr/AsyncImagePipelineOp.cpp b/gfx/layers/wr/AsyncImagePipelineOp.cpp new file mode 100644 index 000000000000..a6642be46117 --- /dev/null +++ b/gfx/layers/wr/AsyncImagePipelineOp.cpp @@ -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 diff --git a/gfx/layers/wr/AsyncImagePipelineOp.h b/gfx/layers/wr/AsyncImagePipelineOp.h new file mode 100644 index 000000000000..140679e7945f --- /dev/null +++ b/gfx/layers/wr/AsyncImagePipelineOp.h @@ -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 + +#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 mList; +}; + +} // namespace layers +} // namespace mozilla + +#endif // MOZILLA_GFX_AsyncImagePipelineOp_H diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp index 3dddf12c9ee6..5f3d1b082651 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -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: { diff --git a/gfx/webrender_bindings/WebRenderAPI.cpp b/gfx/webrender_bindings/WebRenderAPI.cpp index b21ade46f328..c7265f36bb92 100644 --- a/gfx/webrender_bindings/WebRenderAPI.cpp +++ b/gfx/webrender_bindings/WebRenderAPI.cpp @@ -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(); } 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(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 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::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; diff --git a/gfx/webrender_bindings/WebRenderAPI.h b/gfx/webrender_bindings/WebRenderAPI.h index 226877831427..85b60dab7ca5 100644 --- a/gfx/webrender_bindings/WebRenderAPI.h +++ b/gfx/webrender_bindings/WebRenderAPI.h @@ -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 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&& aTransaction) + UniquePtr&& 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&& + aPendingAsyncImagePipelineOps, + UniquePtr&& aTransaction) + : mTag(aTag), + mTimeStamp(TimeStamp::Now()), + mPendingAsyncImagePipelineOps( + std::move(aPendingAsyncImagePipelineOps)), + mTransaction(std::move(aTransaction)) { + MOZ_ASSERT(mTag == Tag::PendingAsyncImagePipelineOps); + } - UniquePtr mTransaction; UniquePtr mPendingRemoteTextures; + UniquePtr mPendingAsyncImagePipelineOps; + UniquePtr mTransaction; public: - static WrTransactionEvent Transaction(wr::Transaction* aTxn, + static WrTransactionEvent Transaction(WebRenderAPI* aApi, + wr::Transaction* aTxn, bool aUseSceneBuilderThread) { - auto transaction = - MakeUnique(aTxn, aUseSceneBuilderThread); + auto transaction = MakeUnique( + 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&& + aPendingAsyncImagePipelineOps, + WebRenderAPI* aApi, wr::Transaction* aTxn, + bool aUseSceneBuilderThread) { + auto transaction = MakeUnique( + 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 mPendingRemoteTextureInfoList; + UniquePtr mPendingAsyncImagePipelineOps; std::queue mPendingWrTransactionEvents; // We maintain alive the root api to know when to shut the render backend