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:
Alexis Beingessner 2019-07-24 14:10:56 +00:00
Родитель 57498bb3b4
Коммит bb09834391
17 изменённых файлов: 554 добавлений и 177 удалений

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

@ -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

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

@ -8,7 +8,6 @@
#define GFX_FRAMEMETRICS_H
#include <stdint.h> // for uint8_t, uint32_t, uint64_t
#include <map>
#include "Units.h" // for CSSRect, CSSPixel, etc
#include "mozilla/DefineEnum.h" // for MOZ_DEFINE_ENUM
#include "mozilla/HashFunctions.h" // for HashGeneric
@ -21,6 +20,7 @@
#include "mozilla/layers/ScrollableLayerGuid.h" // for ScrollableLayerGuid
#include "mozilla/StaticPtr.h" // for StaticAutoPtr
#include "mozilla/TimeStamp.h" // for TimeStamp
#include "nsDataHashtable.h" // for nsDataHashtable
#include "nsString.h"
#include "mozilla/ServoStyleConsts.h"
#include "PLDHashTable.h" // for PLDHashNumber
@ -1099,7 +1099,7 @@ struct ScrollMetadata {
// Please add new fields above this comment.
};
typedef std::map<ScrollableLayerGuid::ViewID, ScrollUpdateInfo>
typedef nsDataHashtable<ScrollableLayerGuid::ViewIDHashKey, ScrollUpdateInfo>
ScrollUpdatesMap;
} // namespace layers

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

@ -2241,7 +2241,7 @@ bool LayerManager::SetPendingScrollUpdateForNextTransaction(
wr::RenderRoot renderRoot = (GetBackendType() == LayersBackend::LAYERS_WR)
? aRenderRoot
: wr::RenderRoot::Default;
mPendingScrollUpdates[renderRoot][aScrollId] = aUpdateInfo;
mPendingScrollUpdates[renderRoot].Put(aScrollId, aUpdateInfo);
return true;
}
@ -2250,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.Data()) : Nothing();
}
std::unordered_set<ScrollableLayerGuid::ViewID>
@ -2262,10 +2259,10 @@ 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.Key());
}
updates.clear();
updates.Clear();
}
return scrollIds;
}

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

@ -27,6 +27,7 @@ namespace layers {
struct ScrollableLayerGuid {
// We use IDs to identify frames across processes.
typedef uint64_t ViewID;
typedef nsUint64HashKey ViewIDHashKey;
static const ViewID NULL_SCROLL_ID; // This container layer does not scroll.
static const ViewID START_SCROLL_ID = 2; // This is the ID that scrolling
// subframes will begin at.

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

@ -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,
@ -231,7 +233,7 @@ void APZUpdater::UpdateScrollOffsets(WRRootId aRootLayerTreeId,
RunOnUpdaterThread(UpdaterQueueSelector(aOriginatingWrRootId),
NS_NewRunnableFunction(
"APZUpdater::UpdateScrollOffsets",
[=, updates = std::move(aUpdates)]() {
[=, updates = std::move(aUpdates)]() mutable {
self->mScrollData[aOriginatingWrRootId].ApplyUpdates(
updates, aPaintSequenceNumber);
auto root = self->mScrollData.find(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) &&
@ -43,6 +47,41 @@ bool IPDLParamTraits<mozilla::layers::RenderRootDisplayListData>::Read(
return false;
}
void WriteScrollUpdates(IPC::Message* aMsg, IProtocol* aActor,
layers::ScrollUpdatesMap& aParam) {
// ICK: we need to manually serialize this map because
// nsDataHashTable doesn't support it (and other maps cause other issues)
WriteIPDLParam(aMsg, aActor, aParam.Count());
for (auto it = aParam.Iter(); !it.Done(); it.Next()) {
WriteIPDLParam(aMsg, aActor, it.Key());
WriteIPDLParam(aMsg, aActor, it.Data());
}
}
bool ReadScrollUpdates(const IPC::Message* aMsg, PickleIterator* aIter,
IProtocol* aActor, layers::ScrollUpdatesMap* aResult) {
// Manually deserialize mScrollUpdates as a stream of K,V pairs
uint32_t count;
if (!ReadIPDLParam(aMsg, aIter, aActor, &count)) {
return false;
}
layers::ScrollUpdatesMap map(count);
for (size_t i = 0; i < count; ++i) {
layers::ScrollableLayerGuid::ViewID key;
layers::ScrollUpdateInfo data;
if (!ReadIPDLParam(aMsg, aIter, aActor, &key) ||
!ReadIPDLParam(aMsg, aIter, aActor, &data)) {
return false;
}
map.Put(key, data);
}
MOZ_RELEASE_ASSERT(map.Count() == count);
*aResult = std::move(map);
return true;
}
void IPDLParamTraits<mozilla::layers::RenderRootUpdates>::Write(
IPC::Message* aMsg, IProtocol* aActor, paramType&& aParam) {
WriteIPDLParam(aMsg, aActor, aParam.mRenderRoot);
@ -50,7 +89,8 @@ void IPDLParamTraits<mozilla::layers::RenderRootUpdates>::Write(
WriteIPDLParam(aMsg, aActor, aParam.mResourceUpdates);
WriteIPDLParam(aMsg, aActor, aParam.mSmallShmems);
WriteIPDLParam(aMsg, aActor, std::move(aParam.mLargeShmems));
WriteIPDLParam(aMsg, aActor, aParam.mScrollUpdates);
WriteScrollUpdates(aMsg, aActor, aParam.mScrollUpdates);
WriteIPDLParam(aMsg, aActor, aParam.mPaintSequenceNumber);
}
bool IPDLParamTraits<mozilla::layers::RenderRootUpdates>::Read(
@ -61,7 +101,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)) {
ReadScrollUpdates(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_AtStartup()));
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_AtStartup()) {
mRenderRoot = wr::RenderRoot::Content;
if (IsRootWebRenderBridgeParent() ||
!StaticPrefs::gfx_webrender_split_render_roots_AtStartup()) {
mRenderRoot = Some(wr::RenderRoot::Default);
}
for (auto& api : aApis) {
@ -339,19 +338,196 @@ 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_AtStartup() &&
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 entry = mPipelineDeferredUpdates.Lookup(wr::AsUint64(aPipelineId))) {
RefPtr<WebRenderBridgeParent> self = this;
for (auto& variant : entry.Data()) {
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) {});
}
entry.Remove();
}
}
/* 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);
root->mPipelineDeferredUpdates.LookupForAdd(key)
.OrInsert([]() { return nsTArray<RenderRootDeferredData>(); })
.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 entry = mPipelineRenderRoots.LookupForAdd(key);
if (!entry) {
entry.OrInsert([=]() { return aRenderRoot; });
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 entry = mPipelineDeferredUpdates.Lookup(key)) {
wrbp->HandleDeferredPipelineData(entry.Data(), aTxnStartTime);
entry.Remove();
for (auto it = wrbp->mChildPipelines.Iter(); !it.Done(); it.Next()) {
if (!MaybeHandleDeferredPipelineDataForPipeline(
aRenderRoot, wr::AsPipelineId(it.Get()->GetKey()),
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_AtStartup()) {
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 +542,16 @@ 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?)");
}
if (auto p = root->mPipelineRenderRoots.Lookup(wr::AsUint64(mPipelineId))) {
mRenderRoot.emplace(p.Data());
}
}
return IPC_OK();
}
@ -736,7 +922,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 +1029,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 +1164,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 +1223,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 +1249,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 +1264,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 +1272,50 @@ 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);
root->mPipelineRenderRoots.Put(id, *mRenderRoot);
mChildPipelines.PutEntry(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 +1354,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());
@ -1112,9 +1362,9 @@ bool WebRenderBridgeParent::ProcessEmptyTransactionUpdates(
MOZ_ASSERT(aUpdates.mRenderRoot == wr::RenderRoot::Default ||
IsRootWebRenderBridgeParent());
if (!aUpdates.mScrollUpdates.empty()) {
if (!aUpdates.mScrollUpdates.IsEmpty()) {
UpdateAPZScrollOffsets(std::move(aUpdates.mScrollUpdates),
aPaintSequenceNumber, aUpdates.mRenderRoot);
aUpdates.mPaintSequenceNumber, aUpdates.mRenderRoot);
}
// Update WrEpoch for UpdateResources() and ProcessWebRenderParentCommands().
@ -1169,14 +1419,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 +1435,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 +1452,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 +1631,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 +1671,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 +1726,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 +1864,22 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvClearCachedResources() {
if (renderRoot == wr::RenderRoot::Default ||
(IsRootWebRenderBridgeParent() &&
StaticPrefs::gfx_webrender_split_render_roots_AtStartup())) {
// 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 +1969,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 +2057,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 +2066,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 +2076,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 +2166,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;
@ -2015,11 +2282,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);
@ -2169,7 +2436,7 @@ TransactionId WebRenderBridgeParent::FlushTransactionIdsForEpoch(
transactionId.mSkippedComposites, transactionId.mTxnURL));
wr::RenderThread::Get()->NotifySlowFrame(
Api(wr::RenderRoot::Default)->GetId());
mApis[wr::RenderRoot::Default]->GetId());
}
}
@ -2259,7 +2526,7 @@ void WebRenderBridgeParent::Pause() {
return;
}
Api(wr::RenderRoot::Default)->Pause();
mApis[wr::RenderRoot::Default]->Pause();
#endif
mPaused = true;
}
@ -2271,7 +2538,7 @@ bool WebRenderBridgeParent::Resume() {
return false;
}
if (!Api(wr::RenderRoot::Default)->Resume()) {
if (!mApis[wr::RenderRoot::Default]->Resume()) {
return false;
}
#endif
@ -2409,10 +2676,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,25 @@ 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.
nsDataHashtable<nsUint64HashKey, 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.
nsTHashtable<nsUint64HashKey> 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.
nsDataHashtable<nsUint64HashKey, nsTArray<RenderRootDeferredData>>
mPipelineDeferredUpdates;
RefPtr<AsyncImagePipelineManager> mAsyncImageManager;
RefPtr<CompositorVsyncScheduler> mCompositorScheduler;
RefPtr<CompositorAnimationStorage> mAnimStorage;
@ -496,7 +549,7 @@ class WebRenderBridgeParent final
Mutex mRenderRootRectMutex;
wr::NonDefaultRenderRootArray<ScreenRect> mRenderRootRects;
wr::RenderRoot mRenderRoot;
Maybe<wr::RenderRoot> mRenderRoot;
bool mPaused;
bool mDestroyed;
bool mReceivedDisplayList;

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

@ -209,7 +209,7 @@ bool WebRenderLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags) {
!mWebRenderCommandBuilder.NeedsEmptyTransaction()) {
bool haveScrollUpdates = false;
for (auto renderRoot : wr::kRenderRoots) {
if (!mPendingScrollUpdates[renderRoot].empty()) {
if (!mPendingScrollUpdates[renderRoot].IsEmpty()) {
haveScrollUpdates = true;
break;
}
@ -251,25 +251,26 @@ bool WebRenderLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags) {
for (auto& stateManager : mStateManagers) {
auto renderRoot = stateManager.GetRenderRoot();
if (stateManager.mAsyncResourceUpdates ||
!mPendingScrollUpdates[renderRoot].empty() ||
!mPendingScrollUpdates[renderRoot].IsEmpty() ||
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.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; }
@ -210,12 +211,11 @@ uint32_t WebRenderScrollData::GetPaintSequenceNumber() const {
return mPaintSequenceNumber;
}
void WebRenderScrollData::ApplyUpdates(const ScrollUpdatesMap& aUpdates,
void WebRenderScrollData::ApplyUpdates(ScrollUpdatesMap& aUpdates,
uint32_t aPaintSequenceNumber) {
for (const auto& update : aUpdates) {
if (Maybe<size_t> index = HasMetadataFor(update.first)) {
mScrollMetadatas[*index].GetMetrics().UpdatePendingScrollInfo(
update.second);
for (auto it = aUpdates.Iter(); !it.Done(); it.Next()) {
if (Maybe<size_t> index = HasMetadataFor(it.Key())) {
mScrollMetadatas[*index].GetMetrics().UpdatePendingScrollInfo(it.Data());
}
}
mPaintSequenceNumber = aPaintSequenceNumber;
@ -234,7 +234,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"
@ -199,8 +200,7 @@ class WebRenderScrollData final {
void SetPaintSequenceNumber(uint32_t aPaintSequenceNumber);
uint32_t GetPaintSequenceNumber() const;
void ApplyUpdates(const ScrollUpdatesMap& aUpdates,
uint32_t aPaintSequenceNumber);
void ApplyUpdates(ScrollUpdatesMap& aUpdates, uint32_t aPaintSequenceNumber);
friend struct IPC::ParamTraits<WebRenderScrollData>;
@ -223,7 +223,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;