зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1547351
- Automatically set content process render root r=kats
This implements the idea of automatically setting a content proc's render root based on the render root enclosing the iframe that points to it. There was a bit of cleanup in here that was a bit tricky to extract from the core patch revolving around how we use the Api(...) helper. This was to avoid the situation where we use the Api(...) helper before our render root is initialized, when we don't actually have to. I.e., when we just want the root WebRenderAPI in all cases. An alternative to this approach could be to fully built out the WebRender transactions and just queue those up to be sent. However, transaction building has various side effects which are committed before the transaction is actually sent, so we would have to build out some scheme for deferring those as well. This seemed simpler. Patch primarily written by :dthayer Differential Revision: https://phabricator.services.mozilla.com/D37078 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
340a9acb9f
Коммит
81f39dd2b0
|
@ -293,7 +293,6 @@ class BasePopup {
|
|||
if (this.extension.remote) {
|
||||
browser.setAttribute("remote", "true");
|
||||
browser.setAttribute("remoteType", E10SUtils.EXTENSION_REMOTE_TYPE);
|
||||
browser.setAttribute("renderroot", "content");
|
||||
}
|
||||
|
||||
// We only need flex sizing for the sake of the slide-in sub-views of the
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "Units.h" // for CSSRect, CSSPixel, etc
|
||||
#include "mozilla/DefineEnum.h" // for MOZ_DEFINE_ENUM
|
||||
#include "mozilla/HashFunctions.h" // for HashGeneric
|
||||
#include "mozilla/HashTable.h" // for HashMap
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/gfx/BasePoint.h" // for BasePoint
|
||||
#include "mozilla/gfx/Rect.h" // for RoundedIn
|
||||
|
@ -1099,7 +1100,7 @@ struct ScrollMetadata {
|
|||
// Please add new fields above this comment.
|
||||
};
|
||||
|
||||
typedef std::map<ScrollableLayerGuid::ViewID, ScrollUpdateInfo>
|
||||
typedef HashMap<ScrollableLayerGuid::ViewID, ScrollUpdateInfo>
|
||||
ScrollUpdatesMap;
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -2240,7 +2240,8 @@ bool LayerManager::SetPendingScrollUpdateForNextTransaction(
|
|||
wr::RenderRoot renderRoot = (GetBackendType() == LayersBackend::LAYERS_WR)
|
||||
? aRenderRoot
|
||||
: wr::RenderRoot::Default;
|
||||
mPendingScrollUpdates[renderRoot][aScrollId] = aUpdateInfo;
|
||||
bool ok = mPendingScrollUpdates[renderRoot].put(aScrollId, aUpdateInfo);
|
||||
MOZ_RELEASE_ASSERT(ok);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2249,11 +2250,8 @@ Maybe<ScrollUpdateInfo> LayerManager::GetPendingScrollInfoUpdate(
|
|||
// This never gets called for WebRenderLayerManager, so we assume that all
|
||||
// pending scroll info updates are stored under the default RenderRoot.
|
||||
MOZ_ASSERT(GetBackendType() != LayersBackend::LAYERS_WR);
|
||||
auto it = mPendingScrollUpdates[wr::RenderRoot::Default].find(aScrollId);
|
||||
if (it != mPendingScrollUpdates[wr::RenderRoot::Default].end()) {
|
||||
return Some(it->second);
|
||||
}
|
||||
return Nothing();
|
||||
auto p = mPendingScrollUpdates[wr::RenderRoot::Default].lookup(aScrollId);
|
||||
return p ? Some(p->value()) : Nothing();
|
||||
}
|
||||
|
||||
std::unordered_set<ScrollableLayerGuid::ViewID>
|
||||
|
@ -2261,8 +2259,8 @@ LayerManager::ClearPendingScrollInfoUpdate() {
|
|||
std::unordered_set<ScrollableLayerGuid::ViewID> scrollIds;
|
||||
for (auto renderRoot : wr::kRenderRoots) {
|
||||
auto& updates = mPendingScrollUpdates[renderRoot];
|
||||
for (const auto& update : updates) {
|
||||
scrollIds.insert(update.first);
|
||||
for (auto it = updates.iter(); !it.done(); it.next()) {
|
||||
scrollIds.insert(it.get().key());
|
||||
}
|
||||
updates.clear();
|
||||
}
|
||||
|
|
|
@ -204,22 +204,24 @@ void APZUpdater::UpdateScrollDataAndTreeState(
|
|||
}
|
||||
self->mEpochData[aOriginatingWrRootId].mRequired = aEpoch;
|
||||
}));
|
||||
RunOnUpdaterThread(UpdaterQueueSelector(aOriginatingWrRootId),
|
||||
NS_NewRunnableFunction(
|
||||
"APZUpdater::UpdateHitTestingTree",
|
||||
[=, aScrollData = std::move(aScrollData)]() {
|
||||
self->mScrollData[aOriginatingWrRootId] =
|
||||
aScrollData;
|
||||
auto root = self->mScrollData.find(aRootLayerTreeId);
|
||||
if (root == self->mScrollData.end()) {
|
||||
return;
|
||||
}
|
||||
self->mApz->UpdateHitTestingTree(
|
||||
WebRenderScrollDataWrapper(
|
||||
*self, aRootLayerTreeId, &(root->second)),
|
||||
aScrollData.IsFirstPaint(), aOriginatingWrRootId,
|
||||
aScrollData.GetPaintSequenceNumber());
|
||||
}));
|
||||
RunOnUpdaterThread(
|
||||
UpdaterQueueSelector(aOriginatingWrRootId),
|
||||
NS_NewRunnableFunction(
|
||||
"APZUpdater::UpdateHitTestingTree",
|
||||
[=, aScrollData = std::move(aScrollData)]() mutable {
|
||||
auto isFirstPaint = aScrollData.IsFirstPaint();
|
||||
auto paintSequenceNumber = aScrollData.GetPaintSequenceNumber();
|
||||
|
||||
self->mScrollData[aOriginatingWrRootId] = std::move(aScrollData);
|
||||
auto root = self->mScrollData.find(aRootLayerTreeId);
|
||||
if (root == self->mScrollData.end()) {
|
||||
return;
|
||||
}
|
||||
self->mApz->UpdateHitTestingTree(
|
||||
WebRenderScrollDataWrapper(*self, aRootLayerTreeId,
|
||||
&(root->second)),
|
||||
isFirstPaint, aOriginatingWrRootId, paintSequenceNumber);
|
||||
}));
|
||||
}
|
||||
|
||||
void APZUpdater::UpdateScrollOffsets(WRRootId aRootLayerTreeId,
|
||||
|
|
|
@ -49,14 +49,13 @@ parent:
|
|||
async DeleteCompositorAnimations(uint64_t[] aIds);
|
||||
async SetDisplayList(RenderRootDisplayListData[] displayLists,
|
||||
OpDestroy[] toDestroy, uint64_t fwdTransactionId, TransactionId transactionId,
|
||||
IdNamespace aIdNamespace, bool containsSVGGroup,
|
||||
bool containsSVGGroup,
|
||||
VsyncId vsyncId, TimeStamp vsyncStartTime,
|
||||
TimeStamp refreshStartTime, TimeStamp txnStartTime, nsCString txnURL, TimeStamp fwdTime,
|
||||
CompositionPayload[] payloads);
|
||||
async EmptyTransaction(FocusTarget focusTarget, uint32_t aPaintSequenceNumber,
|
||||
async EmptyTransaction(FocusTarget focusTarget,
|
||||
RenderRootUpdates[] renderRootUpdates,
|
||||
OpDestroy[] toDestroy, uint64_t fwdTransactionId, TransactionId transactionId,
|
||||
IdNamespace aIdNamespace,
|
||||
VsyncId vsyncId, TimeStamp vsyncStartTime,
|
||||
TimeStamp refreshStartTime, TimeStamp txnStartTime,
|
||||
nsCString txnURL, TimeStamp fwdTime,
|
||||
|
|
|
@ -14,11 +14,13 @@ namespace ipc {
|
|||
void IPDLParamTraits<mozilla::layers::RenderRootDisplayListData>::Write(
|
||||
IPC::Message* aMsg, IProtocol* aActor, paramType&& aParam) {
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mRenderRoot);
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mIdNamespace);
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mRect);
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mCommands);
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mContentSize);
|
||||
WriteIPDLParam(aMsg, aActor, std::move(aParam.mDL));
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mDLDesc);
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mRemotePipelineIds);
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mResourceUpdates);
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mSmallShmems);
|
||||
WriteIPDLParam(aMsg, aActor, std::move(aParam.mLargeShmems));
|
||||
|
@ -29,11 +31,13 @@ bool IPDLParamTraits<mozilla::layers::RenderRootDisplayListData>::Read(
|
|||
const IPC::Message* aMsg, PickleIterator* aIter, IProtocol* aActor,
|
||||
paramType* aResult) {
|
||||
if (ReadIPDLParam(aMsg, aIter, aActor, &aResult->mRenderRoot) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mIdNamespace) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mRect) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mCommands) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mContentSize) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mDL) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mDLDesc) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mRemotePipelineIds) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mResourceUpdates) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mSmallShmems) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mLargeShmems) &&
|
||||
|
@ -51,6 +55,7 @@ void IPDLParamTraits<mozilla::layers::RenderRootUpdates>::Write(
|
|||
WriteIPDLParam(aMsg, aActor, aParam.mSmallShmems);
|
||||
WriteIPDLParam(aMsg, aActor, std::move(aParam.mLargeShmems));
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mScrollUpdates);
|
||||
WriteIPDLParam(aMsg, aActor, aParam.mPaintSequenceNumber);
|
||||
}
|
||||
|
||||
bool IPDLParamTraits<mozilla::layers::RenderRootUpdates>::Read(
|
||||
|
@ -61,7 +66,8 @@ bool IPDLParamTraits<mozilla::layers::RenderRootUpdates>::Read(
|
|||
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mResourceUpdates) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mSmallShmems) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mLargeShmems) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mScrollUpdates)) {
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mScrollUpdates) &&
|
||||
ReadIPDLParam(aMsg, aIter, aActor, &aResult->mPaintSequenceNumber)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/webrender/WebRenderTypes.h"
|
||||
#include "mozilla/layers/WebRenderMessages.h"
|
||||
#include "mozilla/layers/WebRenderScrollData.h"
|
||||
#include "mozilla/Variant.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -18,11 +19,13 @@ namespace layers {
|
|||
|
||||
struct RenderRootDisplayListData {
|
||||
wr::RenderRoot mRenderRoot;
|
||||
wr::IdNamespace mIdNamespace;
|
||||
LayoutDeviceRect mRect;
|
||||
nsTArray<WebRenderParentCommand> mCommands;
|
||||
wr::LayoutSize mContentSize;
|
||||
Maybe<mozilla::ipc::ByteBuf> mDL;
|
||||
wr::BuiltDisplayListDescriptor mDLDesc;
|
||||
nsTArray<wr::PipelineId> mRemotePipelineIds;
|
||||
nsTArray<OpUpdateResource> mResourceUpdates;
|
||||
nsTArray<RefCountedShmem> mSmallShmems;
|
||||
nsTArray<mozilla::ipc::Shmem> mLargeShmems;
|
||||
|
@ -36,8 +39,19 @@ struct RenderRootUpdates {
|
|||
nsTArray<RefCountedShmem> mSmallShmems;
|
||||
nsTArray<mozilla::ipc::Shmem> mLargeShmems;
|
||||
ScrollUpdatesMap mScrollUpdates;
|
||||
uint32_t mPaintSequenceNumber;
|
||||
};
|
||||
|
||||
struct ResourceUpdates {
|
||||
nsTArray<OpUpdateResource> mResourceUpdates;
|
||||
nsTArray<RefCountedShmem> mSmallShmems;
|
||||
nsTArray<mozilla::ipc::Shmem> mLargeShmems;
|
||||
};
|
||||
|
||||
typedef Variant<RenderRootDisplayListData, RenderRootUpdates, ResourceUpdates,
|
||||
FocusTarget>
|
||||
RenderRootDeferredData;
|
||||
|
||||
} // namespace layers
|
||||
|
||||
namespace ipc {
|
||||
|
|
|
@ -122,6 +122,7 @@ void WebRenderBridgeChild::EndTransaction(
|
|||
(XRE_IsParentProcess() &&
|
||||
StaticPrefs::gfx_webrender_split_render_roots()));
|
||||
renderRoot.mCommands = std::move(mParentCommands[renderRoot.mRenderRoot]);
|
||||
renderRoot.mIdNamespace = mIdNamespace;
|
||||
}
|
||||
|
||||
nsTArray<CompositionPayload> payloads;
|
||||
|
@ -129,11 +130,10 @@ void WebRenderBridgeChild::EndTransaction(
|
|||
mManager->TakeCompositionPayloads(payloads);
|
||||
}
|
||||
|
||||
this->SendSetDisplayList(std::move(aRenderRoots), mDestroyedActors,
|
||||
GetFwdTransactionId(), aTransactionId, mIdNamespace,
|
||||
aContainsSVGGroup, aVsyncId, aVsyncStartTime,
|
||||
aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime,
|
||||
payloads);
|
||||
this->SendSetDisplayList(
|
||||
std::move(aRenderRoots), mDestroyedActors, GetFwdTransactionId(),
|
||||
aTransactionId, aContainsSVGGroup, aVsyncId, aVsyncStartTime,
|
||||
aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime, payloads);
|
||||
|
||||
// With multiple render roots, we may not have sent all of our
|
||||
// mParentCommands, so go ahead and go through our mParentCommands and ensure
|
||||
|
@ -146,8 +146,8 @@ void WebRenderBridgeChild::EndTransaction(
|
|||
void WebRenderBridgeChild::EndEmptyTransaction(
|
||||
const FocusTarget& aFocusTarget,
|
||||
nsTArray<RenderRootUpdates>& aRenderRootUpdates,
|
||||
uint32_t aPaintSequenceNumber, TransactionId aTransactionId,
|
||||
const mozilla::VsyncId& aVsyncId, const mozilla::TimeStamp& aVsyncStartTime,
|
||||
TransactionId aTransactionId, const mozilla::VsyncId& aVsyncId,
|
||||
const mozilla::TimeStamp& aVsyncStartTime,
|
||||
const mozilla::TimeStamp& aRefreshStartTime,
|
||||
const mozilla::TimeStamp& aTxnStartTime, const nsCString& aTxnURL) {
|
||||
MOZ_ASSERT(!mDestroyed);
|
||||
|
@ -168,10 +168,9 @@ void WebRenderBridgeChild::EndEmptyTransaction(
|
|||
}
|
||||
|
||||
this->SendEmptyTransaction(
|
||||
aFocusTarget, aPaintSequenceNumber, std::move(aRenderRootUpdates),
|
||||
mDestroyedActors, GetFwdTransactionId(), aTransactionId, mIdNamespace,
|
||||
aVsyncId, aVsyncStartTime, aRefreshStartTime, aTxnStartTime, aTxnURL,
|
||||
fwdTime, payloads);
|
||||
aFocusTarget, std::move(aRenderRootUpdates), mDestroyedActors,
|
||||
GetFwdTransactionId(), aTransactionId, aVsyncId, aVsyncStartTime,
|
||||
aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime, payloads);
|
||||
|
||||
// With multiple render roots, we may not have sent all of our
|
||||
// mParentCommands, so go ahead and go through our mParentCommands and ensure
|
||||
|
|
|
@ -82,7 +82,6 @@ class WebRenderBridgeChild final : public PWebRenderBridgeChild,
|
|||
const nsCString& aTxtURL);
|
||||
void EndEmptyTransaction(const FocusTarget& aFocusTarget,
|
||||
nsTArray<RenderRootUpdates>& aRenderRootUpdates,
|
||||
uint32_t aPaintSequenceNumber,
|
||||
TransactionId aTransactionId,
|
||||
const mozilla::VsyncId& aVsyncId,
|
||||
const mozilla::TimeStamp& aVsyncStartTime,
|
||||
|
|
|
@ -306,7 +306,6 @@ WebRenderBridgeParent::WebRenderBridgeParent(
|
|||
mWrEpoch{0},
|
||||
mIdNamespace(aApis[0]->GetNamespace()),
|
||||
mRenderRootRectMutex("WebRenderBridgeParent::mRenderRootRectMutex"),
|
||||
mRenderRoot(wr::RenderRoot::Default),
|
||||
mPaused(false),
|
||||
mDestroyed(false),
|
||||
mReceivedDisplayList(false),
|
||||
|
@ -320,9 +319,9 @@ WebRenderBridgeParent::WebRenderBridgeParent(
|
|||
mCompositorScheduler = new CompositorVsyncScheduler(this, mWidget);
|
||||
}
|
||||
|
||||
if (!IsRootWebRenderBridgeParent() &&
|
||||
StaticPrefs::gfx_webrender_split_render_roots()) {
|
||||
mRenderRoot = wr::RenderRoot::Content;
|
||||
if (IsRootWebRenderBridgeParent() ||
|
||||
!StaticPrefs::gfx_webrender_split_render_roots()) {
|
||||
mRenderRoot = Some(wr::RenderRoot::Default);
|
||||
}
|
||||
|
||||
for (auto& api : aApis) {
|
||||
|
@ -339,19 +338,204 @@ WebRenderBridgeParent::WebRenderBridgeParent(const wr::PipelineId& aPipelineId)
|
|||
mWrEpoch{0},
|
||||
mIdNamespace{0},
|
||||
mRenderRootRectMutex("WebRenderBridgeParent::mRenderRootRectMutex"),
|
||||
mRenderRoot(wr::RenderRoot::Default),
|
||||
mPaused(false),
|
||||
mDestroyed(true),
|
||||
mReceivedDisplayList(false),
|
||||
mIsFirstPaint(false),
|
||||
mSkippedComposite(false) {}
|
||||
|
||||
WebRenderBridgeParent::~WebRenderBridgeParent() {
|
||||
if (RefPtr<WebRenderBridgeParent> root = GetRootWebRenderBridgeParent()) {
|
||||
root->RemoveDeferredPipeline(mPipelineId);
|
||||
}
|
||||
}
|
||||
|
||||
bool WebRenderBridgeParent::RenderRootIsValid(wr::RenderRoot aRenderRoot) {
|
||||
if (StaticPrefs::gfx_webrender_split_render_roots() &&
|
||||
IsRootWebRenderBridgeParent()) {
|
||||
return aRenderRoot <= wr::kHighestRenderRoot;
|
||||
} else {
|
||||
return aRenderRoot == wr::RenderRoot::Default;
|
||||
}
|
||||
}
|
||||
|
||||
void WebRenderBridgeParent::RemoveDeferredPipeline(wr::PipelineId aPipelineId) {
|
||||
MOZ_ASSERT(IsRootWebRenderBridgeParent());
|
||||
mPipelineRenderRoots.remove(wr::AsUint64(aPipelineId));
|
||||
if (auto p = mPipelineDeferredUpdates.lookup(wr::AsUint64(aPipelineId))) {
|
||||
RefPtr<WebRenderBridgeParent> self = this;
|
||||
for (auto& variant : p->value()) {
|
||||
variant.match(
|
||||
[=](RenderRootDisplayListData& x) {
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(self, x.mSmallShmems);
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(self, x.mLargeShmems);
|
||||
},
|
||||
[=](RenderRootUpdates& x) {
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(self, x.mSmallShmems);
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(self, x.mLargeShmems);
|
||||
},
|
||||
[=](ResourceUpdates& x) {
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(self, x.mSmallShmems);
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(self, x.mLargeShmems);
|
||||
},
|
||||
[=](FocusTarget& x) {});
|
||||
}
|
||||
mPipelineDeferredUpdates.remove(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* static */
|
||||
WebRenderBridgeParent* WebRenderBridgeParent::CreateDestroyed(
|
||||
const wr::PipelineId& aPipelineId) {
|
||||
return new WebRenderBridgeParent(aPipelineId);
|
||||
}
|
||||
|
||||
void WebRenderBridgeParent::PushDeferredPipelineData(
|
||||
RenderRootDeferredData&& aDeferredData) {
|
||||
MOZ_ASSERT(!IsRootWebRenderBridgeParent());
|
||||
if (RefPtr<WebRenderBridgeParent> root = GetRootWebRenderBridgeParent()) {
|
||||
uint64_t key = wr::AsUint64(mPipelineId);
|
||||
auto p = root->mPipelineDeferredUpdates.lookupForAdd(key);
|
||||
if (!p) {
|
||||
bool added = root->mPipelineDeferredUpdates.add(
|
||||
p, key, nsTArray<RenderRootDeferredData>());
|
||||
if (NS_WARN_IF(!added)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
p->value().AppendElement(std::move(aDeferredData));
|
||||
}
|
||||
}
|
||||
|
||||
bool WebRenderBridgeParent::HandleDeferredPipelineData(
|
||||
nsTArray<RenderRootDeferredData>& aDeferredData,
|
||||
const TimeStamp& aTxnStartTime) {
|
||||
MOZ_ASSERT(!IsRootWebRenderBridgeParent());
|
||||
for (auto& entry : aDeferredData) {
|
||||
bool success = entry.match(
|
||||
[&](RenderRootDisplayListData& data) {
|
||||
// We ensure this with RenderRootIsValid before calling
|
||||
// PushDeferredPipelineData:
|
||||
MOZ_ASSERT(data.mRenderRoot == wr::RenderRoot::Default);
|
||||
wr::Epoch wrEpoch = GetNextWrEpoch();
|
||||
bool validTransaction = data.mIdNamespace == mIdNamespace;
|
||||
|
||||
if (!ProcessRenderRootDisplayListData(data,
|
||||
wrEpoch,
|
||||
aTxnStartTime,
|
||||
validTransaction,
|
||||
false)){
|
||||
return false;
|
||||
}
|
||||
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(this, data.mSmallShmems);
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(this, data.mLargeShmems);
|
||||
return true;
|
||||
},
|
||||
[&](RenderRootUpdates& data) {
|
||||
// We ensure this with RenderRootIsValid before calling
|
||||
// PushDeferredPipelineData:
|
||||
MOZ_ASSERT(data.mRenderRoot == wr::RenderRoot::Default);
|
||||
bool scheduleComposite;
|
||||
if (!ProcessEmptyTransactionUpdates(data, &scheduleComposite)) {
|
||||
return false;
|
||||
}
|
||||
if (scheduleComposite) {
|
||||
ScheduleGenerateFrame(Nothing());
|
||||
}
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(this, data.mSmallShmems);
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(this, data.mLargeShmems);
|
||||
return true;
|
||||
},
|
||||
[&](ResourceUpdates& data) {
|
||||
wr::TransactionBuilder txn;
|
||||
txn.SetLowPriority(!IsRootWebRenderBridgeParent());
|
||||
|
||||
if (!UpdateResources(data.mResourceUpdates, data.mSmallShmems,
|
||||
data.mLargeShmems, txn)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Api(wr::RenderRoot::Default)->SendTransaction(txn);
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(this, data.mSmallShmems);
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(this, data.mLargeShmems);
|
||||
return true;
|
||||
},
|
||||
[&](FocusTarget& data) {
|
||||
UpdateAPZFocusState(data);
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
aDeferredData.Clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebRenderBridgeParent::MaybeHandleDeferredPipelineDataForPipeline(
|
||||
wr::RenderRoot aRenderRoot, wr::PipelineId aPipelineId,
|
||||
const TimeStamp& aTxnStartTime) {
|
||||
MOZ_ASSERT(IsRootWebRenderBridgeParent());
|
||||
|
||||
uint64_t key = wr::AsUint64(aPipelineId);
|
||||
auto p = mPipelineRenderRoots.lookupForAdd(key);
|
||||
if (!p) {
|
||||
if (!mPipelineRenderRoots.add(p, key, aRenderRoot)) {
|
||||
return false;
|
||||
}
|
||||
CompositorBridgeParent::LayerTreeState* lts =
|
||||
CompositorBridgeParent::GetIndirectShadowTree(
|
||||
wr::AsLayersId(aPipelineId));
|
||||
if (!lts) {
|
||||
return true;
|
||||
}
|
||||
RefPtr<WebRenderBridgeParent> wrbp = lts->mWrBridge;
|
||||
if (!wrbp) {
|
||||
return true;
|
||||
}
|
||||
MOZ_ASSERT(wrbp->mRenderRoot.refOr(aRenderRoot) == aRenderRoot);
|
||||
wrbp->mRenderRoot = Some(aRenderRoot);
|
||||
|
||||
if (auto p = mPipelineDeferredUpdates.lookup(key)) {
|
||||
wrbp->HandleDeferredPipelineData(p->value(), aTxnStartTime);
|
||||
mPipelineDeferredUpdates.remove(p);
|
||||
|
||||
for (auto iter = wrbp->mChildPipelines.iter(); !iter.done(); iter.next()) {
|
||||
if (!MaybeHandleDeferredPipelineDataForPipeline(
|
||||
aRenderRoot,
|
||||
wr::AsPipelineId(iter.get()),
|
||||
aTxnStartTime)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebRenderBridgeParent::MaybeHandleDeferredPipelineData(
|
||||
wr::RenderRoot aRenderRoot, const nsTArray<wr::PipelineId>& aPipelineIds,
|
||||
const TimeStamp& aTxnStartTime) {
|
||||
MOZ_ASSERT(IsRootWebRenderBridgeParent());
|
||||
if (!StaticPrefs::gfx_webrender_split_render_roots()) {
|
||||
return true;
|
||||
}
|
||||
for (wr::PipelineId pipelineId : aPipelineIds) {
|
||||
if (!MaybeHandleDeferredPipelineDataForPipeline(aRenderRoot, pipelineId,
|
||||
aTxnStartTime)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEnsureConnected(
|
||||
TextureFactoryIdentifier* aTextureFactoryIdentifier,
|
||||
MaybeIdNamespace* aMaybeIdNamespace) {
|
||||
|
@ -366,6 +550,17 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEnsureConnected(
|
|||
*aTextureFactoryIdentifier = GetTextureFactoryIdentifier();
|
||||
*aMaybeIdNamespace = Some(mIdNamespace);
|
||||
|
||||
if (!mRenderRoot) {
|
||||
RefPtr<WebRenderBridgeParent> root = GetRootWebRenderBridgeParent();
|
||||
if (!root) {
|
||||
return IPC_FAIL(this, "Root WRBP is missing (shutting down?)");
|
||||
}
|
||||
auto p = root->mPipelineRenderRoots.lookup(wr::AsUint64(mPipelineId));
|
||||
if (p) {
|
||||
mRenderRoot.emplace(p->value());
|
||||
}
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
@ -736,7 +931,18 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvUpdateResources(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
MOZ_RELEASE_ASSERT(aRenderRoot <= wr::kHighestRenderRoot);
|
||||
if (!RenderRootIsValid(aRenderRoot)) {
|
||||
return IPC_FAIL(this, "Received an invalid renderRoot");
|
||||
}
|
||||
|
||||
if (!mRenderRoot) {
|
||||
PushDeferredPipelineData(AsVariant(ResourceUpdates{
|
||||
std::move(aResourceUpdates),
|
||||
std::move(aSmallShmems),
|
||||
std::move(aLargeShmems),
|
||||
}));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
wr::TransactionBuilder txn;
|
||||
txn.SetLowPriority(!IsRootWebRenderBridgeParent());
|
||||
|
@ -832,13 +1038,18 @@ WebRenderBridgeParent::GetRootWebRenderBridgeParent() const {
|
|||
}
|
||||
|
||||
void WebRenderBridgeParent::UpdateAPZFocusState(const FocusTarget& aFocus) {
|
||||
if (!mRenderRoot) {
|
||||
PushDeferredPipelineData(AsVariant(aFocus));
|
||||
return;
|
||||
}
|
||||
|
||||
CompositorBridgeParent* cbp = GetRootCompositorBridgeParent();
|
||||
if (!cbp) {
|
||||
return;
|
||||
}
|
||||
LayersId rootLayersId = cbp->RootLayerTreeId();
|
||||
if (RefPtr<APZUpdater> apz = cbp->GetAPZUpdater()) {
|
||||
apz->UpdateFocusState(rootLayersId, WRRootId(GetLayersId(), mRenderRoot),
|
||||
apz->UpdateFocusState(rootLayersId, WRRootId(GetLayersId(), *mRenderRoot),
|
||||
aFocus);
|
||||
}
|
||||
}
|
||||
|
@ -962,14 +1173,57 @@ bool WebRenderBridgeParent::SetDisplayList(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool WebRenderBridgeParent::ProcessRenderRootDisplayListData(
|
||||
RenderRootDisplayListData& aDisplayList,
|
||||
wr::Epoch aWrEpoch,
|
||||
const TimeStamp& aTxnStartTime,
|
||||
bool aValidTransaction,
|
||||
bool aObserveLayersUpdate) {
|
||||
wr::TransactionBuilder txn;
|
||||
Maybe<wr::AutoTransactionSender> sender;
|
||||
|
||||
// Note that this needs to happen before the display list transaction is
|
||||
// sent to WebRender, so that the UpdateHitTestingTree call is guaranteed to
|
||||
// be in the updater queue at the time that the scene swap completes.
|
||||
if (aDisplayList.mScrollData) {
|
||||
UpdateAPZScrollData(aWrEpoch, std::move(aDisplayList.mScrollData.ref()),
|
||||
aDisplayList.mRenderRoot);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aDisplayList.mRenderRoot == wr::RenderRoot::Default ||
|
||||
IsRootWebRenderBridgeParent());
|
||||
auto renderRoot = aDisplayList.mRenderRoot;
|
||||
|
||||
txn.SetLowPriority(!IsRootWebRenderBridgeParent());
|
||||
if (aValidTransaction) {
|
||||
MOZ_ASSERT(aDisplayList.mIdNamespace == mIdNamespace);
|
||||
sender.emplace(Api(renderRoot), &txn);
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!ProcessWebRenderParentCommands(aDisplayList.mCommands, txn,
|
||||
renderRoot))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aDisplayList.mDL &&
|
||||
!SetDisplayList(renderRoot, aDisplayList.mRect, aDisplayList.mContentSize,
|
||||
std::move(aDisplayList.mDL.ref()), aDisplayList.mDLDesc,
|
||||
aDisplayList.mResourceUpdates, aDisplayList.mSmallShmems,
|
||||
aDisplayList.mLargeShmems, aTxnStartTime, txn, aWrEpoch,
|
||||
aValidTransaction, aObserveLayersUpdate)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
|
||||
nsTArray<RenderRootDisplayListData>&& aDisplayLists,
|
||||
nsTArray<OpDestroy>&& aToDestroy, const uint64_t& aFwdTransactionId,
|
||||
const TransactionId& aTransactionId, const wr::IdNamespace& aIdNamespace,
|
||||
const bool& aContainsSVGGroup, const VsyncId& aVsyncId,
|
||||
const TimeStamp& aVsyncStartTime, const TimeStamp& aRefreshStartTime,
|
||||
const TimeStamp& aTxnStartTime, const nsCString& aTxnURL,
|
||||
const TimeStamp& aFwdTime, nsTArray<CompositionPayload>&& aPayloads) {
|
||||
const TransactionId& aTransactionId, const bool& aContainsSVGGroup,
|
||||
const VsyncId& aVsyncId, const TimeStamp& aVsyncStartTime,
|
||||
const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime,
|
||||
const nsCString& aTxnURL, const TimeStamp& aFwdTime,
|
||||
nsTArray<CompositionPayload>&& aPayloads) {
|
||||
if (mDestroyed) {
|
||||
for (const auto& op : aToDestroy) {
|
||||
DestroyActor(op);
|
||||
|
@ -978,9 +1232,13 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
|
|||
}
|
||||
|
||||
// Guard against malicious content processes
|
||||
MOZ_RELEASE_ASSERT(aDisplayLists.Length() > 0);
|
||||
if (aDisplayLists.Length() == 0) {
|
||||
return IPC_FAIL(this, "Must send at least one RenderRootDisplayListData.");
|
||||
}
|
||||
for (auto& displayList : aDisplayLists) {
|
||||
MOZ_RELEASE_ASSERT(displayList.mRenderRoot <= wr::kHighestRenderRoot);
|
||||
if (!RenderRootIsValid(displayList.mRenderRoot)) {
|
||||
return IPC_FAIL(this, "Received an invalid renderRoot");
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsRootWebRenderBridgeParent()) {
|
||||
|
@ -1000,7 +1258,6 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
|
|||
mAsyncImageManager->SetCompositionTime(TimeStamp::Now());
|
||||
|
||||
mReceivedDisplayList = true;
|
||||
bool observeLayersUpdate = ShouldParentObserveEpoch();
|
||||
|
||||
// The IsFirstPaint() flag should be the same for all the non-empty
|
||||
// scrolldata across all the renderroot display lists in a given
|
||||
|
@ -1016,7 +1273,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
|
|||
mIsFirstPaint = true;
|
||||
}
|
||||
} else {
|
||||
auto firstNonEmpty = aDisplayLists[*firstScrollDataIndex].mScrollData;
|
||||
auto& firstNonEmpty = aDisplayLists[*firstScrollDataIndex].mScrollData;
|
||||
// Ensure the flag is the same on all of them.
|
||||
MOZ_RELEASE_ASSERT(scrollData->IsFirstPaint() ==
|
||||
firstNonEmpty->IsFirstPaint());
|
||||
|
@ -1024,47 +1281,52 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
|
|||
}
|
||||
}
|
||||
|
||||
// aScrollData is moved into this function but that is not reflected by the
|
||||
// function signature due to the way the IPDL generator works. We remove the
|
||||
// const so that we can move this structure all the way to the desired
|
||||
// destination.
|
||||
// Also note that this needs to happen before the display list transaction is
|
||||
// sent to WebRender, so that the UpdateHitTestingTree call is guaranteed to
|
||||
// be in the updater queue at the time that the scene swap completes.
|
||||
if (!mRenderRoot) {
|
||||
// Only non-root WRBPs will ever have an unresolved mRenderRoot
|
||||
MOZ_ASSERT(!IsRootWebRenderBridgeParent());
|
||||
if (aDisplayLists.Length() != 1) {
|
||||
return IPC_FAIL(this, "Well-behaved content processes must only send a DL for a single renderRoot");
|
||||
}
|
||||
PushDeferredPipelineData(AsVariant(std::move(aDisplayLists[0])));
|
||||
aDisplayLists.Clear();
|
||||
}
|
||||
|
||||
for (auto& displayList : aDisplayLists) {
|
||||
if (displayList.mScrollData) {
|
||||
UpdateAPZScrollData(wrEpoch, std::move(displayList.mScrollData.ref()),
|
||||
displayList.mRenderRoot);
|
||||
if (IsRootWebRenderBridgeParent()) {
|
||||
if (!MaybeHandleDeferredPipelineData(
|
||||
displayList.mRenderRoot,
|
||||
displayList.mRemotePipelineIds,
|
||||
aTxnStartTime)) {
|
||||
return IPC_FAIL(this, "Failed processing deferred pipeline data");
|
||||
}
|
||||
} else {
|
||||
RefPtr<WebRenderBridgeParent> root = GetRootWebRenderBridgeParent();
|
||||
if (!root) {
|
||||
return IPC_FAIL(this, "Root WRBP is missing (shutting down?)");
|
||||
}
|
||||
|
||||
for (auto pipelineId : displayList.mRemotePipelineIds) {
|
||||
auto id = wr::AsUint64(pipelineId);
|
||||
if (!root->mPipelineRenderRoots.put(id, *mRenderRoot) ||
|
||||
!mChildPipelines.put(id)) {
|
||||
return IPC_FAIL(this, "Failed to add child pipeline id.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool validTransaction = aIdNamespace == mIdNamespace;
|
||||
bool validTransaction = aDisplayLists.Length() > 0 &&
|
||||
aDisplayLists[0].mIdNamespace == mIdNamespace;
|
||||
bool observeLayersUpdate = ShouldParentObserveEpoch();
|
||||
|
||||
wr::RenderRootArray<wr::TransactionBuilder> txns;
|
||||
wr::RenderRootArray<Maybe<wr::AutoTransactionSender>> senders;
|
||||
for (auto& displayList : aDisplayLists) {
|
||||
MOZ_ASSERT(displayList.mRenderRoot == wr::RenderRoot::Default ||
|
||||
IsRootWebRenderBridgeParent());
|
||||
auto renderRoot = displayList.mRenderRoot;
|
||||
auto& txn = txns[renderRoot];
|
||||
|
||||
txn.SetLowPriority(!IsRootWebRenderBridgeParent());
|
||||
if (validTransaction) {
|
||||
senders[renderRoot].emplace(Api(renderRoot), &txn);
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!ProcessWebRenderParentCommands(displayList.mCommands, txn,
|
||||
renderRoot))) {
|
||||
return IPC_FAIL(this, "Invalid parent command found");
|
||||
}
|
||||
|
||||
if (displayList.mDL &&
|
||||
!SetDisplayList(renderRoot, displayList.mRect, displayList.mContentSize,
|
||||
std::move(displayList.mDL.ref()), displayList.mDLDesc,
|
||||
displayList.mResourceUpdates, displayList.mSmallShmems,
|
||||
displayList.mLargeShmems, aTxnStartTime, txn, wrEpoch,
|
||||
validTransaction, observeLayersUpdate)) {
|
||||
return IPC_FAIL(this, "Failed call to SetDisplayList");
|
||||
if (!ProcessRenderRootDisplayListData(
|
||||
displayList,
|
||||
wrEpoch,
|
||||
aTxnStartTime,
|
||||
validTransaction,
|
||||
observeLayersUpdate)) {
|
||||
return IPC_FAIL(this, "Failed to process RenderRootDisplayListData.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1103,8 +1365,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
|
|||
}
|
||||
|
||||
bool WebRenderBridgeParent::ProcessEmptyTransactionUpdates(
|
||||
RenderRootUpdates& aUpdates, uint32_t aPaintSequenceNumber,
|
||||
bool* aScheduleComposite) {
|
||||
RenderRootUpdates& aUpdates, bool* aScheduleComposite) {
|
||||
*aScheduleComposite = false;
|
||||
wr::TransactionBuilder txn;
|
||||
txn.SetLowPriority(!IsRootWebRenderBridgeParent());
|
||||
|
@ -1114,7 +1375,7 @@ bool WebRenderBridgeParent::ProcessEmptyTransactionUpdates(
|
|||
|
||||
if (!aUpdates.mScrollUpdates.empty()) {
|
||||
UpdateAPZScrollOffsets(std::move(aUpdates.mScrollUpdates),
|
||||
aPaintSequenceNumber, aUpdates.mRenderRoot);
|
||||
aUpdates.mPaintSequenceNumber, aUpdates.mRenderRoot);
|
||||
}
|
||||
|
||||
// Update WrEpoch for UpdateResources() and ProcessWebRenderParentCommands().
|
||||
|
@ -1169,14 +1430,13 @@ bool WebRenderBridgeParent::ProcessEmptyTransactionUpdates(
|
|||
}
|
||||
|
||||
mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEmptyTransaction(
|
||||
const FocusTarget& aFocusTarget, const uint32_t& aPaintSequenceNumber,
|
||||
const FocusTarget& aFocusTarget,
|
||||
nsTArray<RenderRootUpdates>&& aRenderRootUpdates,
|
||||
nsTArray<OpDestroy>&& aToDestroy, const uint64_t& aFwdTransactionId,
|
||||
const TransactionId& aTransactionId, const wr::IdNamespace& aIdNamespace,
|
||||
const VsyncId& aVsyncId, const TimeStamp& aVsyncStartTime,
|
||||
const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime,
|
||||
const nsCString& aTxnURL, const TimeStamp& aFwdTime,
|
||||
nsTArray<CompositionPayload>&& aPayloads) {
|
||||
const TransactionId& aTransactionId, const VsyncId& aVsyncId,
|
||||
const TimeStamp& aVsyncStartTime, const TimeStamp& aRefreshStartTime,
|
||||
const TimeStamp& aTxnStartTime, const nsCString& aTxnURL,
|
||||
const TimeStamp& aFwdTime, nsTArray<CompositionPayload>&& aPayloads) {
|
||||
if (mDestroyed) {
|
||||
for (const auto& op : aToDestroy) {
|
||||
DestroyActor(op);
|
||||
|
@ -1186,7 +1446,9 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEmptyTransaction(
|
|||
|
||||
// Guard against malicious content processes
|
||||
for (auto& update : aRenderRootUpdates) {
|
||||
MOZ_RELEASE_ASSERT(update.mRenderRoot <= wr::kHighestRenderRoot);
|
||||
if (!RenderRootIsValid(update.mRenderRoot)) {
|
||||
return IPC_FAIL(this, "Received an invalid renderRoot");
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsRootWebRenderBridgeParent()) {
|
||||
|
@ -1201,16 +1463,26 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEmptyTransaction(
|
|||
AutoWebRenderBridgeParentAsyncMessageSender autoAsyncMessageSender(
|
||||
this, &aToDestroy);
|
||||
|
||||
if (!mRenderRoot && aRenderRootUpdates.Length() > 0) {
|
||||
// Only non-root WRBPs will ever have an unresolved mRenderRoot
|
||||
MOZ_ASSERT(!IsRootWebRenderBridgeParent());
|
||||
if (aRenderRootUpdates.Length() != 1) {
|
||||
return IPC_FAIL(this, "Well-behaved content processes must only send a DL for a single renderRoot");
|
||||
}
|
||||
PushDeferredPipelineData(AsVariant(std::move(aRenderRootUpdates[0])));
|
||||
aRenderRootUpdates.Clear();
|
||||
}
|
||||
|
||||
UpdateAPZFocusState(aFocusTarget);
|
||||
|
||||
bool scheduleAnyComposite = false;
|
||||
|
||||
for (auto& update : aRenderRootUpdates) {
|
||||
MOZ_ASSERT(update.mRenderRoot == wr::RenderRoot::Default ||
|
||||
IsRootWebRenderBridgeParent());
|
||||
|
||||
bool scheduleComposite = false;
|
||||
if (!ProcessEmptyTransactionUpdates(update, aPaintSequenceNumber,
|
||||
&scheduleComposite)) {
|
||||
if (!ProcessEmptyTransactionUpdates(update, &scheduleComposite)) {
|
||||
return IPC_FAIL(this, "Failed to process empty transaction update.");
|
||||
}
|
||||
scheduleAnyComposite = scheduleAnyComposite || scheduleComposite;
|
||||
|
@ -1370,7 +1642,7 @@ void WebRenderBridgeParent::FlushSceneBuilds() {
|
|||
// to block until all the inflight transactions have been processed. This
|
||||
// flush message blocks until all previously sent scenes have been built
|
||||
// and received by the render backend thread.
|
||||
Api(wr::RenderRoot::Default)->FlushSceneBuilder();
|
||||
mApis[wr::RenderRoot::Default]->FlushSceneBuilder();
|
||||
// The post-swap hook for async-scene-building calls the
|
||||
// ScheduleRenderOnCompositorThread function from the scene builder thread,
|
||||
// which then triggers a call to ScheduleGenerateFrame() on the compositor
|
||||
|
@ -1410,7 +1682,7 @@ void WebRenderBridgeParent::FlushFramePresentation() {
|
|||
// this effectively blocks on the render backend and renderer threads,
|
||||
// following the same codepath that WebRender takes to render and composite
|
||||
// a frame.
|
||||
Api(wr::RenderRoot::Default)->WaitFlushed();
|
||||
mApis[wr::RenderRoot::Default]->WaitFlushed();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WebRenderBridgeParent::RecvGetSnapshot(
|
||||
|
@ -1465,9 +1737,9 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvGetSnapshot(
|
|||
|
||||
FlushSceneBuilds();
|
||||
FlushFrameGeneration();
|
||||
Api(wr::RenderRoot::Default)
|
||||
->Readback(start, size, bufferTexture->GetFormat(),
|
||||
Range<uint8_t>(buffer, buffer_size));
|
||||
mApis[wr::RenderRoot::Default]->Readback(start, size,
|
||||
bufferTexture->GetFormat(),
|
||||
Range<uint8_t>(buffer, buffer_size));
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
@ -1603,16 +1875,22 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvClearCachedResources() {
|
|||
if (renderRoot == wr::RenderRoot::Default ||
|
||||
(IsRootWebRenderBridgeParent() &&
|
||||
StaticPrefs::gfx_webrender_split_render_roots())) {
|
||||
// Clear resources
|
||||
wr::TransactionBuilder txn;
|
||||
txn.SetLowPriority(true);
|
||||
txn.ClearDisplayList(GetNextWrEpoch(), mPipelineId);
|
||||
txn.Notify(wr::Checkpoint::SceneBuilt,
|
||||
MakeUnique<ScheduleObserveLayersUpdate>(
|
||||
mCompositorBridge, GetLayersId(),
|
||||
mChildLayersObserverEpoch, false));
|
||||
|
||||
Api(renderRoot)->SendTransaction(txn);
|
||||
if (mRenderRoot) {
|
||||
// Clear resources
|
||||
wr::TransactionBuilder txn;
|
||||
txn.SetLowPriority(true);
|
||||
txn.ClearDisplayList(GetNextWrEpoch(), mPipelineId);
|
||||
txn.Notify(wr::Checkpoint::SceneBuilt,
|
||||
MakeUnique<ScheduleObserveLayersUpdate>(
|
||||
mCompositorBridge, GetLayersId(),
|
||||
mChildLayersObserverEpoch, false));
|
||||
Api(renderRoot)->SendTransaction(txn);
|
||||
} else {
|
||||
if (RefPtr<WebRenderBridgeParent> root =
|
||||
GetRootWebRenderBridgeParent()) {
|
||||
root->RemoveDeferredPipeline(mPipelineId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Schedule generate frame to clean up Pipeline
|
||||
|
@ -1702,7 +1980,7 @@ void WebRenderBridgeParent::ScheduleForcedGenerateFrame() {
|
|||
|
||||
mozilla::ipc::IPCResult WebRenderBridgeParent::RecvCapture() {
|
||||
if (!mDestroyed) {
|
||||
Api(wr::RenderRoot::Default)->Capture();
|
||||
mApis[wr::RenderRoot::Default]->Capture();
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
@ -1790,7 +2068,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetAsyncScrollOffset(
|
|||
return IPC_OK();
|
||||
}
|
||||
mCompositorBridge->SetTestAsyncScrollOffset(
|
||||
WRRootId(GetLayersId(), mRenderRoot), aScrollId, CSSPoint(aX, aY));
|
||||
WRRootId(GetLayersId(), *mRenderRoot), aScrollId, CSSPoint(aX, aY));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
@ -1799,7 +2077,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetAsyncZoom(
|
|||
if (mDestroyed) {
|
||||
return IPC_OK();
|
||||
}
|
||||
mCompositorBridge->SetTestAsyncZoom(WRRootId(GetLayersId(), mRenderRoot),
|
||||
mCompositorBridge->SetTestAsyncZoom(WRRootId(GetLayersId(), *mRenderRoot),
|
||||
aScrollId,
|
||||
LayerToParentLayerScale(aZoom));
|
||||
return IPC_OK();
|
||||
|
@ -1809,13 +2087,13 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvFlushApzRepaints() {
|
|||
if (mDestroyed) {
|
||||
return IPC_OK();
|
||||
}
|
||||
mCompositorBridge->FlushApzRepaints(WRRootId(GetLayersId(), mRenderRoot));
|
||||
mCompositorBridge->FlushApzRepaints(WRRootId(GetLayersId(), *mRenderRoot));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WebRenderBridgeParent::RecvGetAPZTestData(
|
||||
APZTestData* aOutData) {
|
||||
mCompositorBridge->GetAPZTestData(WRRootId(GetLayersId(), mRenderRoot),
|
||||
mCompositorBridge->GetAPZTestData(WRRootId(GetLayersId(), *mRenderRoot),
|
||||
aOutData);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
@ -1899,7 +2177,7 @@ void WebRenderBridgeParent::CompositeToTarget(VsyncId aId,
|
|||
}
|
||||
|
||||
if (mSkippedComposite || wr::RenderThread::Get()->TooManyPendingFrames(
|
||||
Api(wr::RenderRoot::Default)->GetId())) {
|
||||
mApis[wr::RenderRoot::Default]->GetId())) {
|
||||
// Render thread is busy, try next time.
|
||||
mSkippedComposite = true;
|
||||
mSkippedCompositeId = aId;
|
||||
|
@ -2006,11 +2284,11 @@ void WebRenderBridgeParent::MaybeGenerateFrame(VsyncId aId,
|
|||
SetAPZSampleTime();
|
||||
|
||||
wr::RenderThread::Get()->IncPendingFrameCount(
|
||||
Api(wr::RenderRoot::Default)->GetId(), aId, start, framesGenerated);
|
||||
mApis[wr::RenderRoot::Default]->GetId(), aId, start, framesGenerated);
|
||||
|
||||
#if defined(ENABLE_FRAME_LATENCY_LOG)
|
||||
auto startTime = TimeStamp::Now();
|
||||
Api(wr::RenderRoot::Default)->SetFrameStartTime(startTime);
|
||||
mApis[wr::RenderRoot::Default]->SetFrameStartTime(startTime);
|
||||
#endif
|
||||
|
||||
MOZ_ASSERT(framesGenerated > 0);
|
||||
|
@ -2160,7 +2438,7 @@ TransactionId WebRenderBridgeParent::FlushTransactionIdsForEpoch(
|
|||
transactionId.mSkippedComposites, transactionId.mTxnURL));
|
||||
|
||||
wr::RenderThread::Get()->NotifySlowFrame(
|
||||
Api(wr::RenderRoot::Default)->GetId());
|
||||
mApis[wr::RenderRoot::Default]->GetId());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2250,7 +2528,7 @@ void WebRenderBridgeParent::Pause() {
|
|||
return;
|
||||
}
|
||||
|
||||
Api(wr::RenderRoot::Default)->Pause();
|
||||
mApis[wr::RenderRoot::Default]->Pause();
|
||||
#endif
|
||||
mPaused = true;
|
||||
}
|
||||
|
@ -2262,7 +2540,7 @@ bool WebRenderBridgeParent::Resume() {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!Api(wr::RenderRoot::Default)->Resume()) {
|
||||
if (!mApis[wr::RenderRoot::Default]->Resume()) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
@ -2400,10 +2678,10 @@ TextureFactoryIdentifier WebRenderBridgeParent::GetTextureFactoryIdentifier() {
|
|||
|
||||
return TextureFactoryIdentifier(
|
||||
LayersBackend::LAYERS_WR, XRE_GetProcessType(),
|
||||
Api(wr::RenderRoot::Default)->GetMaxTextureSize(), false,
|
||||
Api(wr::RenderRoot::Default)->GetUseANGLE(),
|
||||
Api(wr::RenderRoot::Default)->GetUseDComp(), false, false, false,
|
||||
Api(wr::RenderRoot::Default)->GetSyncHandle());
|
||||
mApis[wr::RenderRoot::Default]->GetMaxTextureSize(), false,
|
||||
mApis[wr::RenderRoot::Default]->GetUseANGLE(),
|
||||
mApis[wr::RenderRoot::Default]->GetUseDComp(), false, false, false,
|
||||
mApis[wr::RenderRoot::Default]->GetSyncHandle());
|
||||
}
|
||||
|
||||
wr::Epoch WebRenderBridgeParent::GetNextWrEpoch() {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "mozilla/layers/PWebRenderBridgeParent.h"
|
||||
#include "mozilla/layers/UiCompositorControllerParent.h"
|
||||
#include "mozilla/layers/WebRenderCompositionRecorder.h"
|
||||
#include "mozilla/HashTable.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Result.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
@ -123,21 +124,20 @@ class WebRenderBridgeParent final
|
|||
mozilla::ipc::IPCResult RecvSetDisplayList(
|
||||
nsTArray<RenderRootDisplayListData>&& aDisplayLists,
|
||||
nsTArray<OpDestroy>&& aToDestroy, const uint64_t& aFwdTransactionId,
|
||||
const TransactionId& aTransactionId, const wr::IdNamespace& aIdNamespace,
|
||||
const bool& aContainsSVGGroup, const VsyncId& aVsyncId,
|
||||
const TimeStamp& aVsyncStartTime, const TimeStamp& aRefreshStartTime,
|
||||
const TimeStamp& aTxnStartTime, const nsCString& aTxnURL,
|
||||
const TimeStamp& aFwdTime,
|
||||
nsTArray<CompositionPayload>&& aPayloads) override;
|
||||
mozilla::ipc::IPCResult RecvEmptyTransaction(
|
||||
const FocusTarget& aFocusTarget, const uint32_t& aPaintSequenceNumber,
|
||||
nsTArray<RenderRootUpdates>&& aRenderRootUpdates,
|
||||
nsTArray<OpDestroy>&& aToDestroy, const uint64_t& aFwdTransactionId,
|
||||
const TransactionId& aTransactionId, const wr::IdNamespace& aIdNamespace,
|
||||
const TransactionId& aTransactionId, const bool& aContainsSVGGroup,
|
||||
const VsyncId& aVsyncId, const TimeStamp& aVsyncStartTime,
|
||||
const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime,
|
||||
const nsCString& aTxnURL, const TimeStamp& aFwdTime,
|
||||
nsTArray<CompositionPayload>&& aPayloads) override;
|
||||
mozilla::ipc::IPCResult RecvEmptyTransaction(
|
||||
const FocusTarget& aFocusTarget,
|
||||
nsTArray<RenderRootUpdates>&& aRenderRootUpdates,
|
||||
nsTArray<OpDestroy>&& aToDestroy, const uint64_t& aFwdTransactionId,
|
||||
const TransactionId& aTransactionId, const VsyncId& aVsyncId,
|
||||
const TimeStamp& aVsyncStartTime, const TimeStamp& aRefreshStartTime,
|
||||
const TimeStamp& aTxnStartTime, const nsCString& aTxnURL,
|
||||
const TimeStamp& aFwdTime,
|
||||
nsTArray<CompositionPayload>&& aPayloads) override;
|
||||
mozilla::ipc::IPCResult RecvSetFocusTarget(
|
||||
const FocusTarget& aFocusTarget) override;
|
||||
mozilla::ipc::IPCResult RecvParentCommands(
|
||||
|
@ -270,6 +270,29 @@ class WebRenderBridgeParent final
|
|||
*/
|
||||
void ForceIsFirstPaint() { mIsFirstPaint = true; }
|
||||
|
||||
void PushDeferredPipelineData(RenderRootDeferredData&& aDeferredData);
|
||||
|
||||
/**
|
||||
* If we attempt to process information for a particular pipeline before we
|
||||
* can determine what RenderRoot it belongs to, then we defer that data until
|
||||
* we can. This handles processing that deferred data.
|
||||
*/
|
||||
bool MaybeHandleDeferredPipelineData(
|
||||
wr::RenderRoot aRenderRoot, const nsTArray<wr::PipelineId>& aPipelineIds,
|
||||
const TimeStamp& aTxnStartTime);
|
||||
|
||||
/**
|
||||
* See MaybeHandleDeferredPipelineData - this is the implementation of that for
|
||||
* a single pipeline.
|
||||
*/
|
||||
bool MaybeHandleDeferredPipelineDataForPipeline(
|
||||
wr::RenderRoot aRenderRoot, wr::PipelineId aPipelineId,
|
||||
const TimeStamp& aTxnStartTime);
|
||||
|
||||
bool HandleDeferredPipelineData(
|
||||
nsTArray<RenderRootDeferredData>& aDeferredData,
|
||||
const TimeStamp& aTxnStartTime);
|
||||
|
||||
bool IsRootWebRenderBridgeParent() const;
|
||||
LayersId GetLayersId() const;
|
||||
WRRootId GetWRRootId() const;
|
||||
|
@ -281,14 +304,14 @@ class WebRenderBridgeParent final
|
|||
class ScheduleSharedSurfaceRelease;
|
||||
|
||||
explicit WebRenderBridgeParent(const wr::PipelineId& aPipelineId);
|
||||
virtual ~WebRenderBridgeParent() = default;
|
||||
virtual ~WebRenderBridgeParent();
|
||||
|
||||
wr::WebRenderAPI* Api(wr::RenderRoot aRenderRoot) {
|
||||
if (IsRootWebRenderBridgeParent()) {
|
||||
return mApis[aRenderRoot];
|
||||
} else {
|
||||
MOZ_ASSERT(aRenderRoot == wr::RenderRoot::Default);
|
||||
return mApis[mRenderRoot];
|
||||
return mApis[*mRenderRoot];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,14 +326,25 @@ class WebRenderBridgeParent final
|
|||
return aRenderRoot;
|
||||
} else {
|
||||
MOZ_ASSERT(aRenderRoot == wr::RenderRoot::Default);
|
||||
return mRenderRoot;
|
||||
return *mRenderRoot;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns whether a given render root is valid for this WRBP to receive as
|
||||
// input from the WRBC.
|
||||
bool RenderRootIsValid(wr::RenderRoot aRenderRoot);
|
||||
|
||||
void RemoveDeferredPipeline(wr::PipelineId aPipelineId);
|
||||
|
||||
bool ProcessEmptyTransactionUpdates(RenderRootUpdates& aUpdates,
|
||||
uint32_t aPaintSequenceNumber,
|
||||
bool* aScheduleComposite);
|
||||
|
||||
bool ProcessRenderRootDisplayListData(RenderRootDisplayListData& aDisplayList,
|
||||
wr::Epoch aWrEpoch,
|
||||
const TimeStamp& aTxnStartTime,
|
||||
bool aValidTransaction,
|
||||
bool aObserveLayersUpdate);
|
||||
|
||||
bool SetDisplayList(wr::RenderRoot aRenderRoot, const LayoutDeviceRect& aRect,
|
||||
const wr::LayoutSize& aContentSize, ipc::ByteBuf&& aDL,
|
||||
const wr::BuiltDisplayListDescriptor& aDLDesc,
|
||||
|
@ -462,6 +496,24 @@ class WebRenderBridgeParent final
|
|||
// need to be able to null these out in a thread-safe way from
|
||||
// ClearResources, and there's no way to do that with an nsTArray.
|
||||
wr::RenderRootArray<RefPtr<wr::WebRenderAPI>> mApis;
|
||||
// This is a map from pipeline id to render root, that tracks the render
|
||||
// roots of all subpipelines (including nested subpipelines, e.g. in the
|
||||
// Fission case) attached to this WebRenderBridgeParent. This is only
|
||||
// populated on the root WRBP. It is used to resolve the render root for the
|
||||
// subpipelines, since they may not know where they are attached in the
|
||||
// parent display list and therefore may not know their render root.
|
||||
HashMap<uint64_t, wr::RenderRoot> mPipelineRenderRoots;
|
||||
// This is a hashset of child pipelines for this WRBP. This allows us to
|
||||
// iterate through all the children of a non-root WRBP and add them to
|
||||
// the root's mPipelineRenderRoots, and potentially resolve any of their
|
||||
// deferred updates.
|
||||
HashSet<uint64_t> mChildPipelines;
|
||||
// This is a map from pipeline id to a list of deferred data. This is only
|
||||
// populated on the root WRBP. The data contained within is deferred because
|
||||
// the sub-WRBP that received it did not know which renderroot it belonged
|
||||
// to. Once that is resolved by the root WRBP getting the right display list
|
||||
// update, the deferred data is processed.
|
||||
HashMap<uint64_t, nsTArray<RenderRootDeferredData>> mPipelineDeferredUpdates;
|
||||
RefPtr<AsyncImagePipelineManager> mAsyncImageManager;
|
||||
RefPtr<CompositorVsyncScheduler> mCompositorScheduler;
|
||||
RefPtr<CompositorAnimationStorage> mAnimStorage;
|
||||
|
@ -496,7 +548,7 @@ class WebRenderBridgeParent final
|
|||
Mutex mRenderRootRectMutex;
|
||||
wr::NonDefaultRenderRootArray<ScreenRect> mRenderRootRects;
|
||||
|
||||
wr::RenderRoot mRenderRoot;
|
||||
Maybe<wr::RenderRoot> mRenderRoot;
|
||||
bool mPaused;
|
||||
bool mDestroyed;
|
||||
bool mReceivedDisplayList;
|
||||
|
|
|
@ -255,21 +255,22 @@ bool WebRenderLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags) {
|
|||
WrBridge()->HasWebRenderParentCommands(renderRoot)) {
|
||||
auto updates = renderRootUpdates.AppendElement();
|
||||
updates->mRenderRoot = renderRoot;
|
||||
updates->mPaintSequenceNumber = mPaintSequenceNumber;
|
||||
if (stateManager.mAsyncResourceUpdates) {
|
||||
stateManager.mAsyncResourceUpdates->Flush(updates->mResourceUpdates,
|
||||
updates->mSmallShmems,
|
||||
updates->mLargeShmems);
|
||||
}
|
||||
updates->mScrollUpdates = std::move(mPendingScrollUpdates[renderRoot]);
|
||||
for (const auto& entry : updates->mScrollUpdates) {
|
||||
nsLayoutUtils::NotifyPaintSkipTransaction(/*scroll id=*/entry.first);
|
||||
for (auto it = updates->mScrollUpdates.iter(); !it.done(); it.next()) {
|
||||
nsLayoutUtils::NotifyPaintSkipTransaction(/*scroll id=*/it.get().key());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<wr::IpcResourceUpdateQueue> nothing;
|
||||
WrBridge()->EndEmptyTransaction(mFocusTarget, renderRootUpdates,
|
||||
mPaintSequenceNumber, mLatestTransactionId,
|
||||
mLatestTransactionId,
|
||||
mTransactionIdAllocator->GetVsyncId(),
|
||||
mTransactionIdAllocator->GetVsyncStart(),
|
||||
refreshStart, mTransactionStart, mURL);
|
||||
|
|
|
@ -158,13 +158,14 @@ WebRenderLayerManager* WebRenderScrollData::GetManager() const {
|
|||
|
||||
size_t WebRenderScrollData::AddMetadata(const ScrollMetadata& aMetadata) {
|
||||
ScrollableLayerGuid::ViewID scrollId = aMetadata.GetMetrics().GetScrollId();
|
||||
auto insertResult = mScrollIdMap.insert(std::make_pair(scrollId, 0));
|
||||
if (insertResult.second) {
|
||||
// Insertion took place, therefore it's a scrollId we hadn't seen before
|
||||
insertResult.first->second = mScrollMetadatas.Length();
|
||||
auto p = mScrollIdMap.lookupForAdd(scrollId);
|
||||
if (!p) {
|
||||
// It's a scrollId we hadn't seen before
|
||||
bool ok = mScrollIdMap.add(p, scrollId, mScrollMetadatas.Length());
|
||||
MOZ_RELEASE_ASSERT(ok);
|
||||
mScrollMetadatas.AppendElement(aMetadata);
|
||||
} // else we didn't insert, because it already existed
|
||||
return insertResult.first->second;
|
||||
return p->value();
|
||||
}
|
||||
|
||||
size_t WebRenderScrollData::AddLayerData(
|
||||
|
@ -193,8 +194,8 @@ const ScrollMetadata& WebRenderScrollData::GetScrollMetadata(
|
|||
|
||||
Maybe<size_t> WebRenderScrollData::HasMetadataFor(
|
||||
const ScrollableLayerGuid::ViewID& aScrollId) const {
|
||||
auto it = mScrollIdMap.find(aScrollId);
|
||||
return (it == mScrollIdMap.end() ? Nothing() : Some(it->second));
|
||||
auto ptr = mScrollIdMap.lookup(aScrollId);
|
||||
return (ptr ? Some(ptr->value()) : Nothing());
|
||||
}
|
||||
|
||||
void WebRenderScrollData::SetIsFirstPaint() { mIsFirstPaint = true; }
|
||||
|
@ -212,10 +213,11 @@ uint32_t WebRenderScrollData::GetPaintSequenceNumber() const {
|
|||
|
||||
void WebRenderScrollData::ApplyUpdates(const ScrollUpdatesMap& aUpdates,
|
||||
uint32_t aPaintSequenceNumber) {
|
||||
for (const auto& update : aUpdates) {
|
||||
if (Maybe<size_t> index = HasMetadataFor(update.first)) {
|
||||
for (auto it = aUpdates.iter(); !it.done(); it.next()) {
|
||||
auto& entry = it.get();
|
||||
if (Maybe<size_t> index = HasMetadataFor(entry.key())) {
|
||||
mScrollMetadatas[*index].GetMetrics().UpdatePendingScrollInfo(
|
||||
update.second);
|
||||
entry.value());
|
||||
}
|
||||
}
|
||||
mPaintSequenceNumber = aPaintSequenceNumber;
|
||||
|
@ -234,7 +236,8 @@ bool WebRenderScrollData::RepopulateMap() {
|
|||
for (size_t i = 0; i < mScrollMetadatas.Length(); i++) {
|
||||
ScrollableLayerGuid::ViewID scrollId =
|
||||
mScrollMetadatas[i].GetMetrics().GetScrollId();
|
||||
mScrollIdMap.emplace(scrollId, i);
|
||||
bool ok = mScrollIdMap.putNew(scrollId, i);
|
||||
MOZ_RELEASE_ASSERT(ok);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "mozilla/layers/RenderRootBoundary.h"
|
||||
#include "mozilla/layers/WebRenderMessageUtils.h"
|
||||
#include "mozilla/webrender/WebRenderTypes.h"
|
||||
#include "mozilla/HashTable.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "nsTArrayForwardDeclare.h"
|
||||
|
||||
|
@ -223,7 +224,7 @@ class WebRenderScrollData final {
|
|||
// valid on both the child and parent.
|
||||
// The key into this map is the scrollId of a ScrollMetadata, and the value is
|
||||
// an index into the mScrollMetadatas array.
|
||||
std::map<ScrollableLayerGuid::ViewID, size_t> mScrollIdMap;
|
||||
HashMap<ScrollableLayerGuid::ViewID, size_t> mScrollIdMap;
|
||||
|
||||
// A list of all the unique ScrollMetadata objects from the layer tree. Each
|
||||
// ScrollMetadata in this list must have a unique scroll id.
|
||||
|
|
|
@ -816,6 +816,8 @@ void DisplayListBuilder::Finalize(
|
|||
&aOutTransaction.mDLDesc, &dl.inner);
|
||||
aOutTransaction.mDL.emplace(dl.inner.data, dl.inner.length,
|
||||
dl.inner.capacity);
|
||||
aOutTransaction.mRemotePipelineIds =
|
||||
std::move(SubBuilder(aOutTransaction.mRenderRoot).mRemotePipelineIds);
|
||||
dl.inner.capacity = 0;
|
||||
dl.inner.data = nullptr;
|
||||
}
|
||||
|
@ -1104,6 +1106,7 @@ void DisplayListBuilder::PushIFrame(const wr::LayoutRect& aBounds,
|
|||
bool aIsBackfaceVisible,
|
||||
PipelineId aPipeline,
|
||||
bool aIgnoreMissingPipeline) {
|
||||
mRemotePipelineIds.AppendElement(aPipeline);
|
||||
wr_dp_push_iframe(mWrState, aBounds, MergeClipLeaf(aBounds),
|
||||
aIsBackfaceVisible, &mCurrentSpaceAndClipChain, aPipeline,
|
||||
aIgnoreMissingPipeline);
|
||||
|
|
|
@ -638,6 +638,7 @@ class DisplayListBuilder final {
|
|||
wr::PipelineId mPipelineId;
|
||||
wr::LayoutSize mContentSize;
|
||||
|
||||
nsTArray<wr::PipelineId> mRemotePipelineIds;
|
||||
RenderRoot mRenderRoot;
|
||||
bool mSendSubBuilderDisplayList;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче