Bug 1955005 - Make the old state transaction render immediately and offscreen. r=emilio
The main goal of this patch is to ensure that we render the snapshots as soon as the transaction is received on the WebRender to prevent another transaction within the same vsync interval from replacing the old state's transaction before it has had a chance to produce the snapshots. In addition, we produce the snapshots by generating a frame that isn't presented to the window. This is to avoid potential vsync issues from trying to present multiple times in the same interval and avoids a fair amount of wasted work. Differential Revision: https://phabricator.services.mozilla.com/D242358
This commit is contained in:
@@ -53,7 +53,8 @@ parent:
|
|||||||
bool containsSVGGroup,
|
bool containsSVGGroup,
|
||||||
VsyncId vsyncId, TimeStamp vsyncStartTime,
|
VsyncId vsyncId, TimeStamp vsyncStartTime,
|
||||||
TimeStamp refreshStartTime, TimeStamp txnStartTime, nsCString txnURL, TimeStamp fwdTime,
|
TimeStamp refreshStartTime, TimeStamp txnStartTime, nsCString txnURL, TimeStamp fwdTime,
|
||||||
CompositionPayload[] payloads);
|
CompositionPayload[] payloads,
|
||||||
|
bool renderOffscreen);
|
||||||
async EmptyTransaction(FocusTarget focusTarget,
|
async EmptyTransaction(FocusTarget focusTarget,
|
||||||
MaybeTransactionData transationData,
|
MaybeTransactionData transationData,
|
||||||
OpDestroy[] toDestroy, uint64_t fwdTransactionId, TransactionId transactionId,
|
OpDestroy[] toDestroy, uint64_t fwdTransactionId, TransactionId transactionId,
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ void WebRenderBridgeChild::UpdateResources(
|
|||||||
bool WebRenderBridgeChild::EndTransaction(
|
bool WebRenderBridgeChild::EndTransaction(
|
||||||
DisplayListData&& aDisplayListData, TransactionId aTransactionId,
|
DisplayListData&& aDisplayListData, TransactionId aTransactionId,
|
||||||
bool aContainsSVGGroup, const mozilla::VsyncId& aVsyncId,
|
bool aContainsSVGGroup, const mozilla::VsyncId& aVsyncId,
|
||||||
const mozilla::TimeStamp& aVsyncStartTime,
|
bool aRenderOffscreen, const mozilla::TimeStamp& aVsyncStartTime,
|
||||||
const mozilla::TimeStamp& aRefreshStartTime,
|
const mozilla::TimeStamp& aRefreshStartTime,
|
||||||
const mozilla::TimeStamp& aTxnStartTime, const nsCString& aTxnURL) {
|
const mozilla::TimeStamp& aTxnStartTime, const nsCString& aTxnURL) {
|
||||||
MOZ_ASSERT(!mDestroyed);
|
MOZ_ASSERT(!mDestroyed);
|
||||||
@@ -126,7 +126,8 @@ bool WebRenderBridgeChild::EndTransaction(
|
|||||||
bool ret = this->SendSetDisplayList(
|
bool ret = this->SendSetDisplayList(
|
||||||
std::move(aDisplayListData), mDestroyedActors, GetFwdTransactionId(),
|
std::move(aDisplayListData), mDestroyedActors, GetFwdTransactionId(),
|
||||||
aTransactionId, aContainsSVGGroup, aVsyncId, aVsyncStartTime,
|
aTransactionId, aContainsSVGGroup, aVsyncId, aVsyncStartTime,
|
||||||
aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime, payloads);
|
aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime, payloads,
|
||||||
|
aRenderOffscreen);
|
||||||
|
|
||||||
// With multiple render roots, we may not have sent all of our
|
// With multiple render roots, we may not have sent all of our
|
||||||
// mParentCommands, so go ahead and go through our mParentCommands and ensure
|
// mParentCommands, so go ahead and go through our mParentCommands and ensure
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class WebRenderBridgeChild final : public PWebRenderBridgeChild,
|
|||||||
void BeginTransaction();
|
void BeginTransaction();
|
||||||
bool EndTransaction(DisplayListData&& aDisplayListData,
|
bool EndTransaction(DisplayListData&& aDisplayListData,
|
||||||
TransactionId aTransactionId, bool aContainsSVGroup,
|
TransactionId aTransactionId, bool aContainsSVGroup,
|
||||||
const mozilla::VsyncId& aVsyncId,
|
const mozilla::VsyncId& aVsyncId, bool aRenderOffscreen,
|
||||||
const mozilla::TimeStamp& aVsyncStartTime,
|
const mozilla::TimeStamp& aVsyncStartTime,
|
||||||
const mozilla::TimeStamp& aRefreshStartTime,
|
const mozilla::TimeStamp& aRefreshStartTime,
|
||||||
const mozilla::TimeStamp& aTxnStartTime,
|
const mozilla::TimeStamp& aTxnStartTime,
|
||||||
|
|||||||
@@ -1188,7 +1188,8 @@ bool WebRenderBridgeParent::SetDisplayList(
|
|||||||
|
|
||||||
bool WebRenderBridgeParent::ProcessDisplayListData(
|
bool WebRenderBridgeParent::ProcessDisplayListData(
|
||||||
DisplayListData& aDisplayList, wr::Epoch aWrEpoch,
|
DisplayListData& aDisplayList, wr::Epoch aWrEpoch,
|
||||||
const TimeStamp& aTxnStartTime, bool aValidTransaction) {
|
const TimeStamp& aTxnStartTime, bool aValidTransaction,
|
||||||
|
bool aRenderOffscreen, const VsyncId& aVsyncId) {
|
||||||
wr::TransactionBuilder txn(mApi, /* aUseSceneBuilderThread */ true,
|
wr::TransactionBuilder txn(mApi, /* aUseSceneBuilderThread */ true,
|
||||||
mRemoteTextureTxnScheduler, mFwdTransactionId);
|
mRemoteTextureTxnScheduler, mFwdTransactionId);
|
||||||
Maybe<wr::AutoTransactionSender> sender;
|
Maybe<wr::AutoTransactionSender> sender;
|
||||||
@@ -1215,6 +1216,13 @@ bool WebRenderBridgeParent::ProcessDisplayListData(
|
|||||||
UpdateAPZScrollData(aWrEpoch, std::move(aDisplayList.mScrollData.ref()));
|
UpdateAPZScrollData(aWrEpoch, std::move(aDisplayList.mScrollData.ref()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aRenderOffscreen) {
|
||||||
|
TimeStamp start = TimeStamp::Now();
|
||||||
|
txn.GenerateFrame(aVsyncId, false, wr::RenderReasons::SNAPSHOT);
|
||||||
|
wr::RenderThread::Get()->IncPendingFrameCount(mApi->GetId(), aVsyncId,
|
||||||
|
start);
|
||||||
|
}
|
||||||
|
|
||||||
txn.SetLowPriority(!IsRootWebRenderBridgeParent());
|
txn.SetLowPriority(!IsRootWebRenderBridgeParent());
|
||||||
sender.emplace(mApi, &txn);
|
sender.emplace(mApi, &txn);
|
||||||
bool success = true;
|
bool success = true;
|
||||||
@@ -1242,7 +1250,8 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
|
|||||||
const bool& aContainsSVGGroup, const VsyncId& aVsyncId,
|
const bool& aContainsSVGGroup, const VsyncId& aVsyncId,
|
||||||
const TimeStamp& aVsyncStartTime, const TimeStamp& aRefreshStartTime,
|
const TimeStamp& aVsyncStartTime, const TimeStamp& aRefreshStartTime,
|
||||||
const TimeStamp& aTxnStartTime, const nsACString& aTxnURL,
|
const TimeStamp& aTxnStartTime, const nsACString& aTxnURL,
|
||||||
const TimeStamp& aFwdTime, nsTArray<CompositionPayload>&& aPayloads) {
|
const TimeStamp& aFwdTime, nsTArray<CompositionPayload>&& aPayloads,
|
||||||
|
const bool& aRenderOffscreen) {
|
||||||
if (mDestroyed) {
|
if (mDestroyed) {
|
||||||
for (const auto& op : aToDestroy) {
|
for (const auto& op : aToDestroy) {
|
||||||
DestroyActor(op);
|
DestroyActor(op);
|
||||||
@@ -1282,8 +1291,9 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool validTransaction = aDisplayList.mIdNamespace == mIdNamespace;
|
bool validTransaction = aDisplayList.mIdNamespace == mIdNamespace;
|
||||||
bool success = ProcessDisplayListData(aDisplayList, wrEpoch, aTxnStartTime,
|
bool success =
|
||||||
validTransaction);
|
ProcessDisplayListData(aDisplayList, wrEpoch, aTxnStartTime,
|
||||||
|
validTransaction, aRenderOffscreen, aVsyncId);
|
||||||
|
|
||||||
if (!IsRootWebRenderBridgeParent()) {
|
if (!IsRootWebRenderBridgeParent()) {
|
||||||
aPayloads.AppendElement(
|
aPayloads.AppendElement(
|
||||||
|
|||||||
@@ -120,8 +120,8 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
|
|||||||
const bool& aContainsSVGGroup, const VsyncId& aVsyncId,
|
const bool& aContainsSVGGroup, const VsyncId& aVsyncId,
|
||||||
const TimeStamp& aVsyncStartTime, const TimeStamp& aRefreshStartTime,
|
const TimeStamp& aVsyncStartTime, const TimeStamp& aRefreshStartTime,
|
||||||
const TimeStamp& aTxnStartTime, const nsACString& aTxnURL,
|
const TimeStamp& aTxnStartTime, const nsACString& aTxnURL,
|
||||||
const TimeStamp& aFwdTime,
|
const TimeStamp& aFwdTime, nsTArray<CompositionPayload>&& aPayloads,
|
||||||
nsTArray<CompositionPayload>&& aPayloads) override;
|
const bool& aRenderOffscreen) override;
|
||||||
mozilla::ipc::IPCResult RecvEmptyTransaction(
|
mozilla::ipc::IPCResult RecvEmptyTransaction(
|
||||||
const FocusTarget& aFocusTarget,
|
const FocusTarget& aFocusTarget,
|
||||||
Maybe<TransactionData>&& aTransactionData,
|
Maybe<TransactionData>&& aTransactionData,
|
||||||
@@ -327,7 +327,8 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
|
|||||||
|
|
||||||
bool ProcessDisplayListData(DisplayListData& aDisplayList, wr::Epoch aWrEpoch,
|
bool ProcessDisplayListData(DisplayListData& aDisplayList, wr::Epoch aWrEpoch,
|
||||||
const TimeStamp& aTxnStartTime,
|
const TimeStamp& aTxnStartTime,
|
||||||
bool aValidTransaction);
|
bool aValidTransaction, bool aRenderOffscreen,
|
||||||
|
const VsyncId& aVsyncId);
|
||||||
|
|
||||||
bool SetDisplayList(const LayoutDeviceRect& aRect, ipc::ByteBuf&& aDLItems,
|
bool SetDisplayList(const LayoutDeviceRect& aRect, ipc::ByteBuf&& aDLItems,
|
||||||
ipc::ByteBuf&& aDLCache, ipc::ByteBuf&& aSpatialTreeDL,
|
ipc::ByteBuf&& aDLCache, ipc::ByteBuf&& aSpatialTreeDL,
|
||||||
|
|||||||
@@ -331,7 +331,7 @@ bool WebRenderLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags) {
|
|||||||
void WebRenderLayerManager::EndTransactionWithoutLayer(
|
void WebRenderLayerManager::EndTransactionWithoutLayer(
|
||||||
nsDisplayList* aDisplayList, nsDisplayListBuilder* aDisplayListBuilder,
|
nsDisplayList* aDisplayList, nsDisplayListBuilder* aDisplayListBuilder,
|
||||||
WrFiltersHolder&& aFilters, WebRenderBackgroundData* aBackground,
|
WrFiltersHolder&& aFilters, WebRenderBackgroundData* aBackground,
|
||||||
const double aGeckoDLBuildTime) {
|
const double aGeckoDLBuildTime, bool aRenderOffscreen) {
|
||||||
AUTO_PROFILER_TRACING_MARKER("Paint", "WrDisplayList", GRAPHICS);
|
AUTO_PROFILER_TRACING_MARKER("Paint", "WrDisplayList", GRAPHICS);
|
||||||
|
|
||||||
auto clearTarget = MakeScopeExit([&] { mTarget = nullptr; });
|
auto clearTarget = MakeScopeExit([&] { mTarget = nullptr; });
|
||||||
@@ -460,7 +460,7 @@ void WebRenderLayerManager::EndTransactionWithoutLayer(
|
|||||||
duration);
|
duration);
|
||||||
bool ret = WrBridge()->EndTransaction(
|
bool ret = WrBridge()->EndTransaction(
|
||||||
std::move(dlData), mLatestTransactionId, containsSVGGroup,
|
std::move(dlData), mLatestTransactionId, containsSVGGroup,
|
||||||
mTransactionIdAllocator->GetVsyncId(),
|
mTransactionIdAllocator->GetVsyncId(), aRenderOffscreen,
|
||||||
mTransactionIdAllocator->GetVsyncStart(), refreshStart,
|
mTransactionIdAllocator->GetVsyncStart(), refreshStart,
|
||||||
mTransactionStart, mURL);
|
mTransactionStart, mURL);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ class WebRenderLayerManager final : public WindowRenderer {
|
|||||||
nsDisplayListBuilder* aDisplayListBuilder,
|
nsDisplayListBuilder* aDisplayListBuilder,
|
||||||
WrFiltersHolder&& aFilters,
|
WrFiltersHolder&& aFilters,
|
||||||
WebRenderBackgroundData* aBackground,
|
WebRenderBackgroundData* aBackground,
|
||||||
const double aGeckoDLBuildTime);
|
const double aGeckoDLBuildTime,
|
||||||
|
bool aRenderOffscreen);
|
||||||
|
|
||||||
LayersBackend GetBackendType() override { return LayersBackend::LAYERS_WR; }
|
LayersBackend GetBackendType() override { return LayersBackend::LAYERS_WR; }
|
||||||
void GetBackendName(nsAString& name) override;
|
void GetBackendName(nsAString& name) override;
|
||||||
|
|||||||
@@ -6544,6 +6544,9 @@ void PresShell::PaintAndRequestComposite(nsView* aView, PaintFlags aFlags) {
|
|||||||
if (aFlags & PaintFlags::PaintSyncDecodeImages) {
|
if (aFlags & PaintFlags::PaintSyncDecodeImages) {
|
||||||
flags |= PaintInternalFlags::PaintSyncDecodeImages;
|
flags |= PaintInternalFlags::PaintSyncDecodeImages;
|
||||||
}
|
}
|
||||||
|
if (aFlags & PaintFlags::PaintCompositeOffscreen) {
|
||||||
|
flags |= PaintInternalFlags::PaintCompositeOffscreen;
|
||||||
|
}
|
||||||
PaintInternal(aView, flags);
|
PaintInternal(aView, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6634,6 +6637,9 @@ void PresShell::PaintInternal(nsView* aViewToPaint, PaintInternalFlags aFlags) {
|
|||||||
mIsFirstPaint = false;
|
mIsFirstPaint = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool offscreen =
|
||||||
|
bool(aFlags & PaintInternalFlags::PaintCompositeOffscreen);
|
||||||
|
|
||||||
if (!renderer->BeginTransaction(url)) {
|
if (!renderer->BeginTransaction(url)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -6673,6 +6679,9 @@ void PresShell::PaintInternal(nsView* aViewToPaint, PaintInternalFlags aFlags) {
|
|||||||
StaticPrefs::image_testing_decode_sync_enabled()) {
|
StaticPrefs::image_testing_decode_sync_enabled()) {
|
||||||
flags |= PaintFrameFlags::SyncDecodeImages;
|
flags |= PaintFrameFlags::SyncDecodeImages;
|
||||||
}
|
}
|
||||||
|
if (aFlags & PaintInternalFlags::PaintCompositeOffscreen) {
|
||||||
|
flags |= PaintFrameFlags::CompositeOffscreen;
|
||||||
|
}
|
||||||
if (renderer->GetBackendType() == layers::LayersBackend::LAYERS_WR) {
|
if (renderer->GetBackendType() == layers::LayersBackend::LAYERS_WR) {
|
||||||
flags |= PaintFrameFlags::ForWebRender;
|
flags |= PaintFrameFlags::ForWebRender;
|
||||||
}
|
}
|
||||||
@@ -6695,8 +6704,8 @@ void PresShell::PaintInternal(nsView* aViewToPaint, PaintInternalFlags aFlags) {
|
|||||||
WrFiltersHolder wrFilters;
|
WrFiltersHolder wrFilters;
|
||||||
|
|
||||||
layerManager->SetTransactionIdAllocator(presContext->RefreshDriver());
|
layerManager->SetTransactionIdAllocator(presContext->RefreshDriver());
|
||||||
layerManager->EndTransactionWithoutLayer(nullptr, nullptr,
|
layerManager->EndTransactionWithoutLayer(
|
||||||
std::move(wrFilters), &data, 0);
|
nullptr, nullptr, std::move(wrFilters), &data, 0, offscreen);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -192,6 +192,8 @@ enum class PaintFlags {
|
|||||||
None = 0,
|
None = 0,
|
||||||
/* Sync-decode images. */
|
/* Sync-decode images. */
|
||||||
PaintSyncDecodeImages = 1 << 1,
|
PaintSyncDecodeImages = 1 << 1,
|
||||||
|
/* Render without presenting to the window */
|
||||||
|
PaintCompositeOffscreen = 1 << 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(PaintFlags)
|
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(PaintFlags)
|
||||||
@@ -202,6 +204,8 @@ enum class PaintInternalFlags {
|
|||||||
PaintSyncDecodeImages = 1 << 1,
|
PaintSyncDecodeImages = 1 << 1,
|
||||||
/* Composite layers to the window. */
|
/* Composite layers to the window. */
|
||||||
PaintComposite = 1 << 2,
|
PaintComposite = 1 << 2,
|
||||||
|
/* Render without presenting to the window */
|
||||||
|
PaintCompositeOffscreen = 1 << 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(PaintInternalFlags)
|
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(PaintInternalFlags)
|
||||||
|
|||||||
@@ -3267,6 +3267,9 @@ void nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
|
|||||||
PrintHitTestInfoStats(list);
|
PrintHitTestInfoStats(list);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (aFlags & PaintFrameFlags::CompositeOffscreen) {
|
||||||
|
flags |= nsDisplayList::PAINT_COMPOSITE_OFFSCREEN;
|
||||||
|
}
|
||||||
|
|
||||||
TimeStamp paintStart = TimeStamp::Now();
|
TimeStamp paintStart = TimeStamp::Now();
|
||||||
list->PaintRoot(builder, aRenderingContext, flags, Some(geckoDLBuildTime));
|
list->PaintRoot(builder, aRenderingContext, flags, Some(geckoDLBuildTime));
|
||||||
|
|||||||
@@ -1124,6 +1124,7 @@ class nsLayoutUtils {
|
|||||||
ForWebRender = 0x100,
|
ForWebRender = 0x100,
|
||||||
UseHighQualityScaling = 0x200,
|
UseHighQualityScaling = 0x200,
|
||||||
ResetViewportScrolling = 0x400,
|
ResetViewportScrolling = 0x400,
|
||||||
|
CompositeOffscreen = 0x800,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2299,7 +2299,8 @@ void nsDisplayList::PaintRoot(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
|
|||||||
|
|
||||||
wrManager->EndTransactionWithoutLayer(this, aBuilder,
|
wrManager->EndTransactionWithoutLayer(this, aBuilder,
|
||||||
std::move(wrFilters), nullptr,
|
std::move(wrFilters), nullptr,
|
||||||
aDisplayListBuildTime.valueOr(0.0));
|
aDisplayListBuildTime.valueOr(0.0),
|
||||||
|
aFlags & PAINT_COMPOSITE_OFFSCREEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (presContext->RefreshDriver()->HasScheduleFlush()) {
|
if (presContext->RefreshDriver()->HasScheduleFlush()) {
|
||||||
|
|||||||
@@ -3259,7 +3259,8 @@ class nsDisplayList {
|
|||||||
PAINT_DEFAULT = 0,
|
PAINT_DEFAULT = 0,
|
||||||
PAINT_USE_WIDGET_LAYERS = 0x01,
|
PAINT_USE_WIDGET_LAYERS = 0x01,
|
||||||
PAINT_EXISTING_TRANSACTION = 0x04,
|
PAINT_EXISTING_TRANSACTION = 0x04,
|
||||||
PAINT_IDENTICAL_DISPLAY_LIST = 0x08
|
PAINT_IDENTICAL_DISPLAY_LIST = 0x08,
|
||||||
|
PAINT_COMPOSITE_OFFSCREEN = 0x10
|
||||||
};
|
};
|
||||||
void PaintRoot(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
|
void PaintRoot(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
|
||||||
uint32_t aFlags, Maybe<double> aDisplayListBuildTime);
|
uint32_t aFlags, Maybe<double> aDisplayListBuildTime);
|
||||||
|
|||||||
Reference in New Issue
Block a user