Bug 1441308 - Always send parent commands when sending mDestroyedActors r=kats,sotaro

If we try to send them separately as we were before, we can run into
cases where we try to destroy the actors and then send the OpRemoveTexture,
which crashes.

Differential Revision: https://phabricator.services.mozilla.com/D23987

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Doug Thayer 2019-03-22 18:29:04 +00:00
Родитель 3f608fab0a
Коммит a794a12c8c
6 изменённых файлов: 61 добавлений и 46 удалений

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

@ -21,12 +21,12 @@ struct RenderRootDisplayListData {
gfx::IntRect mRect; gfx::IntRect mRect;
nsTArray<WebRenderParentCommand> mCommands; nsTArray<WebRenderParentCommand> mCommands;
wr::LayoutSize mContentSize; wr::LayoutSize mContentSize;
mozilla::ipc::ByteBuf mDL; Maybe<mozilla::ipc::ByteBuf> mDL;
wr::BuiltDisplayListDescriptor mDLDesc; wr::BuiltDisplayListDescriptor mDLDesc;
nsTArray<OpUpdateResource> mResourceUpdates; nsTArray<OpUpdateResource> mResourceUpdates;
nsTArray<RefCountedShmem> mSmallShmems; nsTArray<RefCountedShmem> mSmallShmems;
nsTArray<mozilla::ipc::Shmem> mLargeShmems; nsTArray<mozilla::ipc::Shmem> mLargeShmems;
WebRenderScrollData mScrollData; Maybe<WebRenderScrollData> mScrollData;
}; };
struct RenderRootUpdates { struct RenderRootUpdates {
@ -65,5 +65,4 @@ struct IPDLParamTraits<mozilla::layers::RenderRootUpdates> {
} // namespace ipc } // namespace ipc
} // namespace mozilla } // namespace mozilla
#endif /* GFX_RENDERROOTTYPES_H */ #endif /* GFX_RENDERROOTTYPES_H */

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

@ -66,6 +66,9 @@ class WebRenderBridgeChild final : public PWebRenderBridgeChild,
void AddWebRenderParentCommand(const WebRenderParentCommand& aCmd, void AddWebRenderParentCommand(const WebRenderParentCommand& aCmd,
wr::RenderRoot aRenderRoot); wr::RenderRoot aRenderRoot);
bool HasWebRenderParentCommands(wr::RenderRoot aRenderRoot) {
return !mParentCommands[aRenderRoot].IsEmpty();
}
void UpdateResources(wr::IpcResourceUpdateQueue& aResources, void UpdateResources(wr::IpcResourceUpdateQueue& aResources,
wr::RenderRoot aRenderRoot); wr::RenderRoot aRenderRoot);

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

@ -896,25 +896,13 @@ void WebRenderBridgeParent::SetAPZSampleTime() {
bool WebRenderBridgeParent::SetDisplayList( bool WebRenderBridgeParent::SetDisplayList(
wr::RenderRoot aRenderRoot, const gfx::IntRect& aRect, wr::RenderRoot aRenderRoot, const gfx::IntRect& aRect,
const nsTArray<WebRenderParentCommand>& aCommands,
const wr::LayoutSize& aContentSize, ipc::ByteBuf&& aDL, const wr::LayoutSize& aContentSize, ipc::ByteBuf&& aDL,
const wr::BuiltDisplayListDescriptor& aDLDesc, const wr::BuiltDisplayListDescriptor& aDLDesc,
const nsTArray<OpUpdateResource>& aResourceUpdates, const nsTArray<OpUpdateResource>& aResourceUpdates,
const nsTArray<RefCountedShmem>& aSmallShmems, const nsTArray<RefCountedShmem>& aSmallShmems,
const nsTArray<ipc::Shmem>& aLargeShmems, const TimeStamp& aTxnStartTime, const nsTArray<ipc::Shmem>& aLargeShmems, const TimeStamp& aTxnStartTime,
wr::TransactionBuilder& aTxn, Maybe<wr::AutoTransactionSender>& aTxnSender, wr::TransactionBuilder& aTxn, wr::Epoch aWrEpoch, bool aValidTransaction,
wr::Epoch aWrEpoch, bool aValidTransaction, bool aObserveLayersUpdate) { bool aObserveLayersUpdate) {
wr::WebRenderAPI* api = Api(aRenderRoot);
aTxn.SetLowPriority(!IsRootWebRenderBridgeParent());
if (aValidTransaction) {
aTxnSender.emplace(api, &aTxn);
}
if (NS_WARN_IF(
!ProcessWebRenderParentCommands(aCommands, aTxn, aRenderRoot))) {
return false;
}
if (NS_WARN_IF(!UpdateResources(aResourceUpdates, aSmallShmems, aLargeShmems, if (NS_WARN_IF(!UpdateResources(aResourceUpdates, aSmallShmems, aLargeShmems,
aTxn))) { aTxn))) {
return false; return false;
@ -954,7 +942,7 @@ bool WebRenderBridgeParent::SetDisplayList(
MakeUnique<SceneBuiltNotification>(this, aWrEpoch, aTxnStartTime)); MakeUnique<SceneBuiltNotification>(this, aWrEpoch, aTxnStartTime));
} }
api->SendTransaction(aTxn); Api(aRenderRoot)->SendTransaction(aTxn);
// We will schedule generating a frame after the scene // We will schedule generating a frame after the scene
// build is done, so we don't need to do it here. // build is done, so we don't need to do it here.
@ -1006,16 +994,26 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
mReceivedDisplayList = true; mReceivedDisplayList = true;
bool observeLayersUpdate = ShouldParentObserveEpoch(); bool observeLayersUpdate = ShouldParentObserveEpoch();
// The IsFirstPaint() flag should be the same for all the scrolldata across // The IsFirstPaint() flag should be the same for all the non-empty
// all the renderroot display lists in a given transaction. We assert this // scrolldata across all the renderroot display lists in a given
// below. So we can read the flag from any one of them. // transaction. We assert this below. So we can read the flag from any one
if (aDisplayLists[0].mScrollData.IsFirstPaint()) { // of them.
mIsFirstPaint = true; Maybe<size_t> firstScrollDataIndex;
}
for (size_t i = 1; i < aDisplayLists.Length(); i++) { for (size_t i = 1; i < aDisplayLists.Length(); i++) {
// Ensure the flag is the same on all of them. auto& scrollData = aDisplayLists[i].mScrollData;
MOZ_RELEASE_ASSERT(aDisplayLists[i].mScrollData.IsFirstPaint() == if (scrollData) {
aDisplayLists[0].mScrollData.IsFirstPaint()); if (firstScrollDataIndex.isNothing()) {
firstScrollDataIndex = Some(i);
if (scrollData && scrollData->IsFirstPaint()) {
mIsFirstPaint = true;
}
} else {
auto firstNonEmpty = aDisplayLists[*firstScrollDataIndex].mScrollData;
// Ensure the flag is the same on all of them.
MOZ_RELEASE_ASSERT(scrollData->IsFirstPaint() ==
firstNonEmpty->IsFirstPaint());
}
}
} }
// aScrollData is moved into this function but that is not reflected by the // aScrollData is moved into this function but that is not reflected by the
@ -1026,8 +1024,10 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
// sent to WebRender, so that the UpdateHitTestingTree call is guaranteed to // sent to WebRender, so that the UpdateHitTestingTree call is guaranteed to
// be in the updater queue at the time that the scene swap completes. // be in the updater queue at the time that the scene swap completes.
for (auto& displayList : aDisplayLists) { for (auto& displayList : aDisplayLists) {
UpdateAPZScrollData(wrEpoch, std::move(displayList.mScrollData), if (displayList.mScrollData) {
displayList.mRenderRoot); UpdateAPZScrollData(wrEpoch, std::move(displayList.mScrollData.ref()),
displayList.mRenderRoot);
}
} }
bool validTransaction = aIdNamespace == mIdNamespace; bool validTransaction = aIdNamespace == mIdNamespace;
@ -1037,13 +1037,25 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
for (auto& displayList : aDisplayLists) { for (auto& displayList : aDisplayLists) {
MOZ_ASSERT(displayList.mRenderRoot == wr::RenderRoot::Default || MOZ_ASSERT(displayList.mRenderRoot == wr::RenderRoot::Default ||
IsRootWebRenderBridgeParent()); IsRootWebRenderBridgeParent());
if (!SetDisplayList( auto renderRoot = displayList.mRenderRoot;
displayList.mRenderRoot, displayList.mRect, displayList.mCommands, auto& txn = txns[renderRoot];
displayList.mContentSize, std::move(displayList.mDL),
displayList.mDLDesc, displayList.mResourceUpdates, txn.SetLowPriority(!IsRootWebRenderBridgeParent());
displayList.mSmallShmems, displayList.mLargeShmems, aTxnStartTime, if (validTransaction) {
txns[displayList.mRenderRoot], senders[displayList.mRenderRoot], senders[renderRoot].emplace(Api(renderRoot), &txn);
wrEpoch, validTransaction, observeLayersUpdate)) { }
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"); return IPC_FAIL(this, "Failed call to SetDisplayList");
} }
} }

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

@ -296,17 +296,14 @@ class WebRenderBridgeParent final
} }
bool SetDisplayList(wr::RenderRoot aRenderRoot, const gfx::IntRect& aRect, bool SetDisplayList(wr::RenderRoot aRenderRoot, const gfx::IntRect& aRect,
const nsTArray<WebRenderParentCommand>& aCommands,
const wr::LayoutSize& aContentSize, ipc::ByteBuf&& aDL, const wr::LayoutSize& aContentSize, ipc::ByteBuf&& aDL,
const wr::BuiltDisplayListDescriptor& aDLDesc, const wr::BuiltDisplayListDescriptor& aDLDesc,
const nsTArray<OpUpdateResource>& aResourceUpdates, const nsTArray<OpUpdateResource>& aResourceUpdates,
const nsTArray<RefCountedShmem>& aSmallShmems, const nsTArray<RefCountedShmem>& aSmallShmems,
const nsTArray<ipc::Shmem>& aLargeShmems, const nsTArray<ipc::Shmem>& aLargeShmems,
const TimeStamp& aTxnStartTime, const TimeStamp& aTxnStartTime,
wr::TransactionBuilder& aTxn, wr::TransactionBuilder& aTxn, wr::Epoch aWrEpoch,
Maybe<wr::AutoTransactionSender>& aTxnSender, bool aValidTransaction, bool aObserveLayersUpdate);
wr::Epoch aWrEpoch, bool aValidTransaction,
bool aObserveLayersUpdate);
void UpdateAPZFocusState(const FocusTarget& aFocus); void UpdateAPZFocusState(const FocusTarget& aFocus);
void UpdateAPZScrollData(const wr::Epoch& aEpoch, WebRenderScrollData&& aData, void UpdateAPZScrollData(const wr::Epoch& aEpoch, WebRenderScrollData&& aData,

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

@ -238,7 +238,8 @@ bool WebRenderLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags) {
for (auto& stateManager : mStateManagers) { for (auto& stateManager : mStateManagers) {
auto renderRoot = stateManager.GetRenderRoot(); auto renderRoot = stateManager.GetRenderRoot();
if (stateManager.mAsyncResourceUpdates || if (stateManager.mAsyncResourceUpdates ||
!mPendingScrollUpdates[renderRoot].empty()) { !mPendingScrollUpdates[renderRoot].empty() ||
WrBridge()->HasWebRenderParentCommands(renderRoot)) {
auto updates = renderRootUpdates.AppendElement(); auto updates = renderRootUpdates.AppendElement();
updates->mRenderRoot = renderRoot; updates->mRenderRoot = renderRoot;
if (stateManager.mAsyncResourceUpdates) { if (stateManager.mAsyncResourceUpdates) {
@ -418,12 +419,15 @@ void WebRenderLayerManager::EndTransactionWithoutLayer(
auto renderRootDL = renderRootDLs.AppendElement(); auto renderRootDL = renderRootDLs.AppendElement();
renderRootDL->mRenderRoot = renderRoot; renderRootDL->mRenderRoot = renderRoot;
builder.Finalize(*renderRootDL); builder.Finalize(*renderRootDL);
mLastDisplayListSizes[renderRoot] = renderRootDL->mDL.mCapacity; mLastDisplayListSizes[renderRoot] = renderRootDL->mDL->mCapacity;
resourceUpdates.SubQueue(renderRoot) resourceUpdates.SubQueue(renderRoot)
.Flush(renderRootDL->mResourceUpdates, renderRootDL->mSmallShmems, .Flush(renderRootDL->mResourceUpdates, renderRootDL->mSmallShmems,
renderRootDL->mLargeShmems); renderRootDL->mLargeShmems);
renderRootDL->mRect = RoundedToInt(rects[renderRoot]).ToUnknownRect(); renderRootDL->mRect = RoundedToInt(rects[renderRoot]).ToUnknownRect();
renderRootDL->mScrollData = std::move(mScrollDatas[renderRoot]); renderRootDL->mScrollData.emplace(std::move(mScrollDatas[renderRoot]));
} else if (WrBridge()->HasWebRenderParentCommands(renderRoot)) {
auto renderRootDL = renderRootDLs.AppendElement();
renderRootDL->mRenderRoot = renderRoot;
} }
} }

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

@ -730,8 +730,8 @@ void DisplayListBuilder::Finalize(
wr_api_finalize_builder(SubBuilder(aOutTransaction.mRenderRoot).mWrState, wr_api_finalize_builder(SubBuilder(aOutTransaction.mRenderRoot).mWrState,
&aOutTransaction.mContentSize, &aOutTransaction.mContentSize,
&aOutTransaction.mDLDesc, &dl.inner); &aOutTransaction.mDLDesc, &dl.inner);
aOutTransaction.mDL = aOutTransaction.mDL.emplace(dl.inner.data, dl.inner.length,
ipc::ByteBuf(dl.inner.data, dl.inner.length, dl.inner.capacity); dl.inner.capacity);
dl.inner.capacity = 0; dl.inner.capacity = 0;
dl.inner.data = nullptr; dl.inner.data = nullptr;
} }