Bug 1690619 - Keep track of where the request to rendering something comes from. r=gfx-reviewers,mstange

This patch adds plumbing to keep track of why we request frames to be rendered.
This information is then displayed in gecko profile markers on the renderer thread as well as in profiler HUD counters (See "Render reasons" in profiler.rs).

Differential Revision: https://phabricator.services.mozilla.com/D127274
This commit is contained in:
Nicolas Silva 2021-10-05 12:54:39 +00:00
Родитель aef746fa2f
Коммит cb6ac0df62
45 изменённых файлов: 392 добавлений и 187 удалений

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

@ -21,7 +21,7 @@ class CompositorController {
/**
* Ask the compositor to schedule a new composite.
*/
virtual void ScheduleRenderOnCompositorThread() = 0;
virtual void ScheduleRenderOnCompositorThread(wr::RenderReasons aReasons) = 0;
protected:
virtual ~CompositorController() = default;

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

@ -723,7 +723,8 @@ void APZCTreeManager::SampleForWebRender(const Maybe<VsyncId>& aVsyncId,
bool activeAnimations = AdvanceAnimationsInternal(lock, aSampleTime);
if (activeAnimations && controller) {
controller->ScheduleRenderOnCompositorThread();
controller->ScheduleRenderOnCompositorThread(
wr::RenderReasons::ANIMATED_PROPERTY);
}
nsTArray<wr::WrTransformProperty> transforms;

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

@ -4168,7 +4168,8 @@ const ScreenMargin AsyncPanZoomController::CalculatePendingDisplayPort(
void AsyncPanZoomController::ScheduleComposite() {
if (mCompositorController) {
mCompositorController->ScheduleRenderOnCompositorThread();
mCompositorController->ScheduleRenderOnCompositorThread(
wr::RenderReasons::APZ);
}
}

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

@ -52,7 +52,7 @@ static bool ScheduleComposition(CompositableHost* aCompositable) {
if (!cp) {
return false;
}
cp->ScheduleComposition();
cp->ScheduleComposition(wr::RenderReasons::ASYNC_IMAGE);
return true;
}

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

@ -395,11 +395,12 @@ bool CompositorBridgeChild::SendAdoptChild(const LayersId& id) {
return PCompositorBridgeChild::SendAdoptChild(id);
}
bool CompositorBridgeChild::SendFlushRendering() {
bool CompositorBridgeChild::SendFlushRendering(
const wr::RenderReasons& aReasons) {
if (!mCanSend) {
return false;
}
return PCompositorBridgeChild::SendFlushRendering();
return PCompositorBridgeChild::SendFlushRendering(aReasons);
}
bool CompositorBridgeChild::SendStartFrameTimeRecording(

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

@ -126,7 +126,7 @@ class CompositorBridgeChild final : public PCompositorBridgeChild,
bool SendResume();
bool SendResumeAsync();
bool SendAdoptChild(const LayersId& id);
bool SendFlushRendering();
bool SendFlushRendering(const wr::RenderReasons& aReasons);
bool SendStartFrameTimeRecording(const int32_t& bufferSize,
uint32_t* startIndex);
bool SendStopFrameTimeRecording(const uint32_t& startIndex,

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

@ -505,31 +505,34 @@ CompositorBridgeParent::RecvWaitOnTransactionProcessed() {
return IPC_OK();
}
mozilla::ipc::IPCResult CompositorBridgeParent::RecvFlushRendering() {
mozilla::ipc::IPCResult CompositorBridgeParent::RecvFlushRendering(
const wr::RenderReasons& aReasons) {
if (mWrBridge) {
mWrBridge->FlushRendering();
mWrBridge->FlushRendering(aReasons);
return IPC_OK();
}
if (mCompositorScheduler->NeedsComposite()) {
CancelCurrentCompositeTask();
ForceComposeToTarget(nullptr);
ForceComposeToTarget(aReasons, nullptr, nullptr);
}
return IPC_OK();
}
mozilla::ipc::IPCResult CompositorBridgeParent::RecvFlushRenderingAsync() {
mozilla::ipc::IPCResult CompositorBridgeParent::RecvFlushRenderingAsync(
const wr::RenderReasons& aReasons) {
if (mWrBridge) {
mWrBridge->FlushRendering(false);
mWrBridge->FlushRendering(aReasons, false);
return IPC_OK();
}
return RecvFlushRendering();
return RecvFlushRendering(aReasons);
}
mozilla::ipc::IPCResult CompositorBridgeParent::RecvForcePresent() {
mozilla::ipc::IPCResult CompositorBridgeParent::RecvForcePresent(
const wr::RenderReasons& aReasons) {
if (mWrBridge) {
mWrBridge->ScheduleForcedGenerateFrame();
mWrBridge->ScheduleForcedGenerateFrame(aReasons);
}
return IPC_OK();
}
@ -576,11 +579,12 @@ void CompositorBridgeParent::ActorDestroy(ActorDestroyReason why) {
&CompositorBridgeParent::DeferredDestroy));
}
void CompositorBridgeParent::ScheduleRenderOnCompositorThread() {
void CompositorBridgeParent::ScheduleRenderOnCompositorThread(
wr::RenderReasons aReasons) {
MOZ_ASSERT(CompositorThread());
CompositorThread()->Dispatch(
NewRunnableMethod("layers::CompositorBridgeParent::ScheduleComposition",
this, &CompositorBridgeParent::ScheduleComposition));
CompositorThread()->Dispatch(NewRunnableMethod<wr::RenderReasons>(
"layers::CompositorBridgeParent::ScheduleComposition", this,
&CompositorBridgeParent::ScheduleComposition, aReasons));
}
void CompositorBridgeParent::PauseComposition() {
@ -631,17 +635,18 @@ void CompositorBridgeParent::ResumeComposition() {
mPaused = false;
Invalidate();
mCompositorScheduler->ForceComposeToTarget(nullptr, nullptr);
mCompositorScheduler->ForceComposeToTarget(wr::RenderReasons::WIDGET, nullptr,
nullptr);
// if anyone's waiting to make sure that composition really got resumed, tell
// them
lock.NotifyAll();
}
void CompositorBridgeParent::ForceComposition() {
void CompositorBridgeParent::ForceComposition(wr::RenderReasons aReasons) {
// Cancel the orientation changed state to force composition
mForceCompositionTask = nullptr;
ScheduleRenderOnCompositorThread();
ScheduleRenderOnCompositorThread(aReasons);
}
void CompositorBridgeParent::CancelCurrentCompositeTask() {
@ -673,30 +678,31 @@ void CompositorBridgeParent::NotifyShadowTreeTransaction(
bool aScheduleComposite, uint32_t aPaintSequenceNumber,
bool aIsRepeatTransaction, bool aHitTestUpdate) {
if (aScheduleComposite) {
ScheduleComposition();
ScheduleComposition(wr::RenderReasons::OTHER);
}
}
void CompositorBridgeParent::ScheduleComposition() {
void CompositorBridgeParent::ScheduleComposition(wr::RenderReasons aReasons) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
if (mPaused) {
return;
}
if (mWrBridge) {
mWrBridge->ScheduleGenerateFrame();
mWrBridge->ScheduleGenerateFrame(aReasons);
} else {
mCompositorScheduler->ScheduleComposition();
mCompositorScheduler->ScheduleComposition(aReasons);
}
}
void CompositorBridgeParent::ForceComposeToTarget(DrawTarget* aTarget,
void CompositorBridgeParent::ForceComposeToTarget(wr::RenderReasons aReasons,
DrawTarget* aTarget,
const gfx::IntRect* aRect) {
AUTO_PROFILER_LABEL("CompositorBridgeParent::ForceComposeToTarget", GRAPHICS);
AutoRestore<bool> override(mOverrideComposeReadiness);
mOverrideComposeReadiness = true;
mCompositorScheduler->ForceComposeToTarget(aTarget, aRect);
mCompositorScheduler->ForceComposeToTarget(aReasons, aTarget, aRect);
}
PAPZCTreeManagerParent* CompositorBridgeParent::AllocPAPZCTreeManagerParent(
@ -837,7 +843,7 @@ bool CompositorBridgeParent::SetTestSampleTime(const LayersId& aId,
}
if (mWrBridge) {
mWrBridge->FlushRendering();
mWrBridge->FlushRendering(wr::RenderReasons::TESTING);
return true;
}
@ -950,7 +956,7 @@ void CompositorBridgeParent::SetFixedLayerMargins(ScreenIntCoord aTop,
}
Invalidate();
ScheduleComposition();
ScheduleComposition(wr::RenderReasons::RESIZE);
}
CompositorBridgeParent* CompositorBridgeParent::GetCompositorBridgeParent(
@ -1003,7 +1009,7 @@ void CompositorBridgeParent::NotifyVsync(const VsyncEvent& aVsync,
/* static */
void CompositorBridgeParent::ScheduleForcedComposition(
const LayersId& aLayersId) {
const LayersId& aLayersId, wr::RenderReasons aReasons) {
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
@ -1019,9 +1025,9 @@ void CompositorBridgeParent::ScheduleForcedComposition(
}
if (cbp->mWrBridge) {
cbp->mWrBridge->ScheduleForcedGenerateFrame();
cbp->mWrBridge->ScheduleForcedGenerateFrame(aReasons);
} else if (cbp->CanComposite()) {
cbp->mCompositorScheduler->ScheduleComposition();
cbp->mCompositorScheduler->ScheduleComposition(aReasons);
}
}
@ -1090,7 +1096,6 @@ mozilla::ipc::IPCResult CompositorBridgeParent::RecvAdoptChild(
const LayersId& child) {
RefPtr<APZUpdater> oldApzUpdater;
APZCTreeManagerParent* parent;
bool scheduleComposition = false;
bool apzEnablementChanged = false;
RefPtr<WebRenderBridgeParent> childWrBridge;
@ -1142,10 +1147,6 @@ mozilla::ipc::IPCResult CompositorBridgeParent::RecvAdoptChild(
parent = sIndirectLayerTrees[child].mApzcTreeManagerParent;
}
if (scheduleComposition) {
ScheduleComposition();
}
if (childWrBridge) {
MOZ_ASSERT(mWrBridge);
RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI();
@ -1643,7 +1644,7 @@ void CompositorBridgeParent::NotifyDidSceneBuild(
if (mWrBridge) {
mWrBridge->NotifyDidSceneBuild(aInfo);
} else {
mCompositorScheduler->ScheduleComposition();
mCompositorScheduler->ScheduleComposition(wr::RenderReasons::SCENE);
}
}

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

@ -178,7 +178,8 @@ class CompositorBridgeParentBase : public PCompositorBridgeParent,
MOZ_CRASH("Should only be called on ContentCompositorBridgeParent.");
}
virtual void ForceComposeToTarget(gfx::DrawTarget* aTarget,
virtual void ForceComposeToTarget(wr::RenderReasons aReasons,
gfx::DrawTarget* aTarget,
const gfx::IntRect* aRect = nullptr) {
MOZ_CRASH();
}
@ -219,8 +220,10 @@ class CompositorBridgeParentBase : public PCompositorBridgeParent,
PCompositorWidgetParent* aActor) = 0;
virtual mozilla::ipc::IPCResult RecvAdoptChild(const LayersId& id) = 0;
virtual mozilla::ipc::IPCResult RecvFlushRenderingAsync() = 0;
virtual mozilla::ipc::IPCResult RecvForcePresent() = 0;
virtual mozilla::ipc::IPCResult RecvFlushRenderingAsync(
const wr::RenderReasons& aReasons) = 0;
virtual mozilla::ipc::IPCResult RecvForcePresent(
const wr::RenderReasons& aReasons) = 0;
virtual mozilla::ipc::IPCResult RecvBeginRecording(
const TimeStamp& aRecordingStart, BeginRecordingResolver&& aResolve) = 0;
virtual mozilla::ipc::IPCResult RecvEndRecordingToDisk(
@ -241,7 +244,8 @@ class CompositorBridgeParentBase : public PCompositorBridgeParent,
CompositorOptions* compositorOptions) = 0;
virtual mozilla::ipc::IPCResult RecvNotifyChildRecreated(
const LayersId& id, CompositorOptions* compositorOptions) = 0;
virtual mozilla::ipc::IPCResult RecvFlushRendering() = 0;
virtual mozilla::ipc::IPCResult RecvFlushRendering(
const wr::RenderReasons& aReasons) = 0;
virtual mozilla::ipc::IPCResult RecvWaitOnTransactionProcessed() = 0;
virtual mozilla::ipc::IPCResult RecvStartFrameTimeRecording(
const int32_t& bufferSize, uint32_t* startIndex) = 0;
@ -308,10 +312,13 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
mozilla::ipc::IPCResult RecvNotifyChildRecreated(
const LayersId& child, CompositorOptions* aOptions) override;
mozilla::ipc::IPCResult RecvAdoptChild(const LayersId& child) override;
mozilla::ipc::IPCResult RecvFlushRendering() override;
mozilla::ipc::IPCResult RecvFlushRenderingAsync() override;
mozilla::ipc::IPCResult RecvFlushRendering(
const wr::RenderReasons& aReasons) override;
mozilla::ipc::IPCResult RecvFlushRenderingAsync(
const wr::RenderReasons& aReasons) override;
mozilla::ipc::IPCResult RecvWaitOnTransactionProcessed() override;
mozilla::ipc::IPCResult RecvForcePresent() override;
mozilla::ipc::IPCResult RecvForcePresent(
const wr::RenderReasons& aReasons) override;
mozilla::ipc::IPCResult RecvStartFrameTimeRecording(
const int32_t& aBufferSize, uint32_t* aOutStartIndex) override;
@ -408,9 +415,9 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
void AsyncRender();
// Can be called from any thread
void ScheduleRenderOnCompositorThread() override;
void ScheduleRenderOnCompositorThread(wr::RenderReasons aReasons) override;
void ScheduleComposition();
void ScheduleComposition(wr::RenderReasons aReasons);
void NotifyShadowTreeTransaction(LayersId aId, bool aIsFirstPaint,
const FocusTarget& aFocusTarget,
@ -426,7 +433,8 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
void ScheduleRotationOnCompositorThread(const TargetConfig& aTargetConfig,
bool aIsFirstPaint);
static void ScheduleForcedComposition(const LayersId& aLayersId);
static void ScheduleForcedComposition(const LayersId& aLayersId,
wr::RenderReasons aReasons);
/**
* Returns the unique layer tree identifier that corresponds to the root
@ -526,7 +534,8 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
widget::CompositorWidget* GetWidget() { return mWidget; }
virtual void ForceComposeToTarget(
gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr) override;
wr::RenderReasons aReasons, gfx::DrawTarget* aTarget,
const gfx::IntRect* aRect = nullptr) override;
PAPZCTreeManagerParent* AllocPAPZCTreeManagerParent(
const LayersId& aLayersId) override;
@ -648,7 +657,7 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
bool IsPaused() { return mPaused; }
protected:
void ForceComposition();
void ForceComposition(wr::RenderReasons aReasons);
void CancelCurrentCompositeTask();
/**

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

@ -69,10 +69,12 @@ CompositorVsyncScheduler::CompositorVsyncScheduler(
mLastVsyncTime(TimeStamp::Now()),
mLastVsyncOutputTime(TimeStamp::Now()),
mIsObservingVsync(false),
mRendersDelayedByVsyncReasons(wr::RenderReasons::NONE),
mVsyncNotificationsSkipped(0),
mWidget(aWidget),
mCurrentCompositeTaskMonitor("CurrentCompositeTaskMonitor"),
mCurrentCompositeTask(nullptr),
mCurrentCompositeTaskReasons(wr::RenderReasons::NONE),
mCurrentVRTaskMonitor("CurrentVRTaskMonitor"),
mCurrentVRTask(nullptr) {
mVsyncObserver = new Observer(this);
@ -108,13 +110,15 @@ void CompositorVsyncScheduler::Destroy() {
CancelCurrentVRTask();
}
void CompositorVsyncScheduler::PostCompositeTask(
const VsyncEvent& aVsyncEvent) {
void CompositorVsyncScheduler::PostCompositeTask(const VsyncEvent& aVsyncEvent,
wr::RenderReasons aReasons) {
MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
mCurrentCompositeTaskReasons = mCurrentCompositeTaskReasons | aReasons;
if (mCurrentCompositeTask == nullptr && CompositorThread()) {
RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod<VsyncEvent>(
"layers::CompositorVsyncScheduler::Composite", this,
&CompositorVsyncScheduler::Composite, aVsyncEvent);
RefPtr<CancelableRunnable> task =
NewCancelableRunnableMethod<VsyncEvent, wr::RenderReasons>(
"layers::CompositorVsyncScheduler::Composite", this,
&CompositorVsyncScheduler::Composite, aVsyncEvent, aReasons);
mCurrentCompositeTask = task;
CompositorThread()->Dispatch(task.forget());
}
@ -131,7 +135,7 @@ void CompositorVsyncScheduler::PostVRTask(TimeStamp aTimestamp) {
}
}
void CompositorVsyncScheduler::ScheduleComposition() {
void CompositorVsyncScheduler::ScheduleComposition(wr::RenderReasons aReasons) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
if (!mVsyncObserver) {
// Destroy was already called on this object.
@ -146,7 +150,7 @@ void CompositorVsyncScheduler::ScheduleComposition() {
if (mAsapScheduling) {
// Used only for performance testing purposes, and when recording/replaying
// to ensure that graphics are up to date.
PostCompositeTask(vsyncEvent);
PostCompositeTask(vsyncEvent, aReasons);
} else {
if (!mCompositeRequestedAt) {
mCompositeRequestedAt = TimeStamp::Now();
@ -157,7 +161,9 @@ void CompositorVsyncScheduler::ScheduleComposition() {
// through the main thread of the UI process. It's possible that
// we're blocking there waiting on a composite, so schedule an initial
// one now to get things started.
PostCompositeTask(vsyncEvent);
PostCompositeTask(vsyncEvent, aReasons);
} else {
mRendersDelayedByVsyncReasons = aReasons;
}
}
}
@ -188,10 +194,10 @@ bool CompositorVsyncScheduler::NotifyVsync(const VsyncEvent& aVsync) {
#if defined(MOZ_WIDGET_ANDROID)
gfx::VRManager* vm = gfx::VRManager::Get();
if (!vm->IsPresenting()) {
PostCompositeTask(aVsync);
PostCompositeTask(aVsync, wr::RenderReasons::VSYNC);
}
#else
PostCompositeTask(aVsync);
PostCompositeTask(aVsync, wr::RenderReasons::VSYNC);
#endif // defined(MOZ_WIDGET_ANDROID)
PostVRTask(aVsync.mTime);
@ -208,22 +214,31 @@ void CompositorVsyncScheduler::CancelCurrentVRTask() {
}
}
void CompositorVsyncScheduler::CancelCurrentCompositeTask() {
wr::RenderReasons CompositorVsyncScheduler::CancelCurrentCompositeTask() {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread() ||
NS_IsMainThread());
MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
wr::RenderReasons canceledTaskRenderReasons = mCurrentCompositeTaskReasons;
mCurrentCompositeTaskReasons = wr::RenderReasons::NONE;
if (mCurrentCompositeTask) {
mCurrentCompositeTask->Cancel();
mCurrentCompositeTask = nullptr;
}
return canceledTaskRenderReasons;
}
void CompositorVsyncScheduler::Composite(const VsyncEvent& aVsyncEvent) {
void CompositorVsyncScheduler::Composite(const VsyncEvent& aVsyncEvent,
wr::RenderReasons aReasons) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
MOZ_ASSERT(mVsyncSchedulerOwner);
{ // scope lock
MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
aReasons =
aReasons | mCurrentCompositeTaskReasons | mRendersDelayedByVsyncReasons;
mCurrentCompositeTaskReasons = wr::RenderReasons::NONE;
mRendersDelayedByVsyncReasons = wr::RenderReasons::NONE;
mCurrentCompositeTask = nullptr;
}
@ -253,7 +268,8 @@ void CompositorVsyncScheduler::Composite(const VsyncEvent& aVsyncEvent) {
mLastComposeTime = SampleTime::FromVsync(aVsyncEvent.mTime);
// Tell the owner to do a composite
mVsyncSchedulerOwner->CompositeToTarget(aVsyncEvent.mId, nullptr, nullptr);
mVsyncSchedulerOwner->CompositeToTarget(aVsyncEvent.mId, aReasons, nullptr,
nullptr);
mVsyncNotificationsSkipped = 0;
@ -267,7 +283,8 @@ void CompositorVsyncScheduler::Composite(const VsyncEvent& aVsyncEvent) {
}
}
void CompositorVsyncScheduler::ForceComposeToTarget(gfx::DrawTarget* aTarget,
void CompositorVsyncScheduler::ForceComposeToTarget(wr::RenderReasons aReasons,
gfx::DrawTarget* aTarget,
const IntRect* aRect) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
@ -289,7 +306,7 @@ void CompositorVsyncScheduler::ForceComposeToTarget(gfx::DrawTarget* aTarget,
mLastComposeTime = SampleTime::FromNow();
MOZ_ASSERT(mVsyncSchedulerOwner);
mVsyncSchedulerOwner->CompositeToTarget(VsyncId(), aTarget, aRect);
mVsyncSchedulerOwner->CompositeToTarget(VsyncId(), aReasons, aTarget, aRect);
}
bool CompositorVsyncScheduler::NeedsComposite() {
@ -300,8 +317,8 @@ bool CompositorVsyncScheduler::NeedsComposite() {
bool CompositorVsyncScheduler::FlushPendingComposite() {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
if (mCompositeRequestedAt) {
CancelCurrentCompositeTask();
ForceComposeToTarget(nullptr, nullptr);
wr::RenderReasons reasons = CancelCurrentCompositeTask();
ForceComposeToTarget(reasons, nullptr, nullptr);
return true;
}
return false;

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

@ -15,6 +15,7 @@
#include "mozilla/TimeStamp.h" // for TimeStamp
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/layers/SampleTime.h"
#include "mozilla/webrender/webrender_ffi.h"
#include "mozilla/VsyncDispatcher.h"
#include "mozilla/widget/CompositorWidget.h"
#include "nsISupportsImpl.h"
@ -60,12 +61,14 @@ class CompositorVsyncScheduler {
* composition soon (likely at the next vsync). This must be called on the
* compositor thread.
*/
void ScheduleComposition();
void ScheduleComposition(wr::RenderReasons aReasons);
/**
* Cancel any composite task that has been scheduled but hasn't run yet.
*
* Returns the render reasons of the canceled task if any.
*/
void CancelCurrentCompositeTask();
wr::RenderReasons CancelCurrentCompositeTask();
/**
* Check if a composite is pending. This is generally true between a call
@ -77,7 +80,8 @@ class CompositorVsyncScheduler {
* Force a composite to happen right away, without waiting for the next vsync.
* This must be called on the compositor thread.
*/
void ForceComposeToTarget(gfx::DrawTarget* aTarget,
void ForceComposeToTarget(wr::RenderReasons aReasons,
gfx::DrawTarget* aTarget,
const gfx::IntRect* aRect);
/**
@ -113,7 +117,8 @@ class CompositorVsyncScheduler {
// Post a task to run Composite() on the compositor thread, if there isn't
// such a task already queued. Can be called from any thread.
void PostCompositeTask(const VsyncEvent& aVsyncEvent);
void PostCompositeTask(const VsyncEvent& aVsyncEvent,
wr::RenderReasons aReasons);
// Post a task to run DispatchVREvents() on the VR thread, if there isn't
// such a task already queued. Can be called from any thread.
@ -126,7 +131,7 @@ class CompositorVsyncScheduler {
// This gets run at vsync time and "does" a composite (which really means
// update internal state and call the owner to do the composite).
void Composite(const VsyncEvent& aVsyncEvent);
void Composite(const VsyncEvent& aVsyncEvent, wr::RenderReasons aReasons);
void ObserveVsync();
void UnobserveVsync();
@ -155,6 +160,8 @@ class CompositorVsyncScheduler {
bool mAsapScheduling;
bool mIsObservingVsync;
// Accessed on the compositor thread.
wr::RenderReasons mRendersDelayedByVsyncReasons;
TimeStamp mCompositeRequestedAt;
int32_t mVsyncNotificationsSkipped;
widget::CompositorWidget* mWidget;
@ -162,6 +169,8 @@ class CompositorVsyncScheduler {
mozilla::Monitor mCurrentCompositeTaskMonitor;
RefPtr<CancelableRunnable> mCurrentCompositeTask;
// Accessed on multiple threads, guarded by mCurrentCompositeTaskMonitor.
wr::RenderReasons mCurrentCompositeTaskReasons;
mozilla::Monitor mCurrentVRTaskMonitor;
RefPtr<CancelableRunnable> mCurrentVRTask;

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

@ -8,6 +8,7 @@
#define mozilla_layers_CompositorVsyncSchedulerOwner_h
#include "mozilla/VsyncDispatcher.h"
#include "mozilla/webrender/webrender_ffi.h"
namespace mozilla {
@ -21,7 +22,8 @@ class CompositorVsyncSchedulerOwner {
public:
virtual bool IsPendingComposite() = 0;
virtual void FinishPendingComposite() = 0;
virtual void CompositeToTarget(VsyncId aId, gfx::DrawTarget* aTarget,
virtual void CompositeToTarget(VsyncId aId, wr::RenderReasons aReasons,
gfx::DrawTarget* aTarget,
const gfx::IntRect* aRect = nullptr) = 0;
virtual TimeDuration GetVsyncInterval() const = 0;
};

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

@ -61,11 +61,17 @@ class ContentCompositorBridgeParent final : public CompositorBridgeParentBase {
mozilla::ipc::IPCResult RecvAdoptChild(const LayersId& child) override {
return IPC_FAIL_NO_REASON(this);
}
mozilla::ipc::IPCResult RecvFlushRendering() override { return IPC_OK(); }
mozilla::ipc::IPCResult RecvFlushRenderingAsync() override {
mozilla::ipc::IPCResult RecvFlushRendering(
const wr::RenderReasons&) override {
return IPC_OK();
}
mozilla::ipc::IPCResult RecvFlushRenderingAsync(
const wr::RenderReasons&) override {
return IPC_OK();
}
mozilla::ipc::IPCResult RecvForcePresent(const wr::RenderReasons&) override {
return IPC_OK();
}
mozilla::ipc::IPCResult RecvForcePresent() override { return IPC_OK(); }
mozilla::ipc::IPCResult RecvWaitOnTransactionProcessed() override {
return IPC_OK();
}

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

@ -39,6 +39,7 @@ using mozilla::layers::TextureFlags from "mozilla/layers/CompositorTypes.h";
using mozilla::layers::CompositorOptions from "mozilla/layers/CompositorOptions.h";
using mozilla::wr::PipelineId from "mozilla/webrender/WebRenderTypes.h";
using mozilla::wr::IdNamespace from "mozilla/webrender/WebRenderTypes.h";
using mozilla::wr::RenderReasons from "mozilla/webrender/webrender_ffi.h";
using base::ProcessId from "base/process.h";
using mozilla::wr::MaybeExternalImageId from "mozilla/webrender/WebRenderTypes.h";
using mozilla::layers::LayersObserverEpoch from "mozilla/layers/LayersTypes.h";
@ -176,18 +177,18 @@ parent:
// Make sure any pending composites are started immediately and
// block until they are completed.
sync FlushRendering();
sync FlushRendering(RenderReasons aReasons);
// Same as FlushRendering, but asynchronous, since not all platforms require
// synchronous repaints on resize.
async FlushRenderingAsync();
async FlushRenderingAsync(RenderReasons aReasons);
// Make sure any pending composites have been received.
sync WaitOnTransactionProcessed();
// Force an additional frame presentation to be executed. This is used to
// work around a windows presentation bug (See Bug 1232042)
async ForcePresent();
async ForcePresent(RenderReasons aReasons);
sync StartFrameTimeRecording(int32_t bufferSize)
returns (uint32_t startIndex);

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

@ -22,6 +22,7 @@ using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h
using mozilla::layers::CompositionPayload from "mozilla/layers/LayersTypes.h";
using mozilla::layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
using mozilla::wr::BuiltDisplayListDescriptor from "mozilla/webrender/webrender_ffi.h";
using mozilla::wr::RenderReasons from "mozilla/webrender/webrender_ffi.h";
using mozilla::wr::IdNamespace from "mozilla/webrender/WebRenderTypes.h";
using mozilla::wr::MaybeIdNamespace from "mozilla/webrender/WebRenderTypes.h";
using mozilla::wr::ExternalImageKeyPair from "mozilla/webrender/WebRenderTypes.h";
@ -70,7 +71,7 @@ parent:
// Invalidate rendered frame
async InvalidateRenderedFrame();
// Schedule a composite if one isn't already scheduled.
async ScheduleComposite();
async ScheduleComposite(RenderReasons aReasons);
// Save the frame capture to disk
async Capture();

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

@ -95,7 +95,7 @@ UiCompositorControllerParent::RecvInvalidateAndRender() {
mRootLayerTreeId);
if (parent) {
parent->Invalidate();
parent->ScheduleComposition();
parent->ScheduleComposition(wr::RenderReasons::OTHER);
}
return IPC_OK();
}
@ -141,7 +141,7 @@ UiCompositorControllerParent::RecvRequestScreenPixels() {
if (state && state->mWrBridge) {
state->mWrBridge->RequestScreenPixels(this);
state->mWrBridge->ScheduleForcedGenerateFrame();
state->mWrBridge->ScheduleForcedGenerateFrame(wr::RenderReasons::OTHER);
}
#endif // defined(MOZ_WIDGET_ANDROID)

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

@ -338,6 +338,7 @@ WebRenderBridgeParent::WebRenderBridgeParent(
mScreenPixelsTarget(nullptr),
#endif
mBlobTileSize(256),
mSkippedCompositeReasons(wr::RenderReasons::NONE),
mDestroyed(false),
mReceivedDisplayList(false),
mIsFirstPaint(true),
@ -963,7 +964,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvUpdateResources(
// There are resource updates, then we update Epoch of transaction.
txn.UpdateEpoch(mPipelineId, mWrEpoch);
mAsyncImageManager->SetWillGenerateFrame();
ScheduleGenerateFrame();
ScheduleGenerateFrame(wr::RenderReasons::RESOURCE_UPDATE);
} else {
// If TransactionBuilder does not have resource updates nor display list,
// ScheduleGenerateFrame is not triggered via SceneBuilder and there is no
@ -1413,6 +1414,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEmptyTransaction(
UpdateAPZFocusState(aFocusTarget);
bool scheduleAnyComposite = false;
wr::RenderReasons renderReasons = wr::RenderReasons::NONE;
if (aTransactionData) {
bool scheduleComposite = false;
@ -1425,6 +1427,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEmptyTransaction(
return IPC_FAIL(this, "Failed to process empty transaction update.");
}
scheduleAnyComposite = scheduleAnyComposite || scheduleComposite;
renderReasons |= wr::RenderReasons::RESOURCE_UPDATE;
}
// If we are going to kick off a new composite as a result of this
@ -1446,7 +1449,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEmptyTransaction(
/* aUseForTelemetry */ scheduleAnyComposite);
if (scheduleAnyComposite) {
ScheduleGenerateFrame();
ScheduleGenerateFrame(renderReasons);
} else if (sendDidComposite) {
// The only thing in the pending transaction id queue should be the entry
// we just added, and now we're going to pretend we rendered it
@ -1537,7 +1540,7 @@ bool WebRenderBridgeParent::ProcessWebRenderParentCommands(
case WebRenderParentCommand::TOpUpdatedAsyncImagePipeline: {
const OpUpdatedAsyncImagePipeline& op =
cmd.get_OpUpdatedAsyncImagePipeline();
aTxn.InvalidateRenderedFrame();
aTxn.InvalidateRenderedFrame(wr::RenderReasons::ASYNC_IMAGE);
mAsyncImageManager->ApplyAsyncImageForPipeline(op.pipelineId(), aTxn,
txnForImageBridge);
break;
@ -1602,10 +1605,10 @@ void WebRenderBridgeParent::FlushSceneBuilds() {
// shouldn't be calling this function all that much in production so this
// is probably fine. If it becomes an issue we can add more state tracking
// machinery to optimize it away.
ScheduleGenerateFrame();
ScheduleGenerateFrame(wr::RenderReasons::FLUSH);
}
void WebRenderBridgeParent::FlushFrameGeneration() {
void WebRenderBridgeParent::FlushFrameGeneration(wr::RenderReasons aReasons) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
MOZ_ASSERT(IsRootWebRenderBridgeParent()); // This function is only useful on
// the root WRBP
@ -1616,7 +1619,7 @@ void WebRenderBridgeParent::FlushFrameGeneration() {
mCompositorScheduler->CancelCurrentCompositeTask();
// Update timestamp of scheduler for APZ and animation.
mCompositorScheduler->UpdateLastComposeTime();
MaybeGenerateFrame(VsyncId(), /* aForceGenerateFrame */ true);
MaybeGenerateFrame(VsyncId(), /* aForceGenerateFrame */ true, aReasons);
}
}
@ -1637,7 +1640,7 @@ void WebRenderBridgeParent::DisableNativeCompositor() {
// Disable WebRender's native compositor usage
mApi->EnableNativeCompositor(false);
// Ensure we generate and render a frame immediately.
ScheduleForcedGenerateFrame();
ScheduleForcedGenerateFrame(wr::RenderReasons::CONFIG_CHANGE);
mDisablingNativeCompositor = true;
}
@ -1782,7 +1785,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvGetSnapshot(
MOZ_ASSERT((uint32_t)(size.width * 4) == stride);
FlushSceneBuilds();
FlushFrameGeneration();
FlushFrameGeneration(wr::RenderReasons::SNAPSHOT);
mApi->Readback(start, size, bufferTexture->GetFormat(),
Range<uint8_t>(buffer, buffer_size), aNeedsYFlip);
@ -1923,7 +1926,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvClearCachedResources() {
mApi->SendTransaction(txn);
// Schedule generate frame to clean up Pipeline
ScheduleGenerateFrame();
ScheduleGenerateFrame(wr::RenderReasons::CLEAR_RESOURCES);
ClearAnimationResources();
@ -1985,11 +1988,12 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvInvalidateRenderedFrame() {
wr::AsUint64(mPipelineId), wr::AsUint64(mApi->GetId()),
IsRootWebRenderBridgeParent());
InvalidateRenderedFrame();
InvalidateRenderedFrame(wr::RenderReasons::WIDGET);
return IPC_OK();
}
mozilla::ipc::IPCResult WebRenderBridgeParent::RecvScheduleComposite() {
mozilla::ipc::IPCResult WebRenderBridgeParent::RecvScheduleComposite(
const wr::RenderReasons& aReasons) {
LOG("WebRenderBridgeParent::RecvScheduleComposite() PipelineId %" PRIx64
" Id %" PRIx64 " root %d",
wr::AsUint64(mPipelineId), wr::AsUint64(mApi->GetId()),
@ -1997,27 +2001,29 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvScheduleComposite() {
// Caller of LayerManager::ScheduleComposite() expects that it trigger
// composite. Then we do not want to skip generate frame.
ScheduleForcedGenerateFrame();
ScheduleForcedGenerateFrame(aReasons);
return IPC_OK();
}
void WebRenderBridgeParent::InvalidateRenderedFrame() {
void WebRenderBridgeParent::InvalidateRenderedFrame(
wr::RenderReasons aReasons) {
if (mDestroyed) {
return;
}
wr::TransactionBuilder fastTxn(mApi, /* aUseSceneBuilderThread */ false);
fastTxn.InvalidateRenderedFrame();
fastTxn.InvalidateRenderedFrame(aReasons);
mApi->SendTransaction(fastTxn);
}
void WebRenderBridgeParent::ScheduleForcedGenerateFrame() {
void WebRenderBridgeParent::ScheduleForcedGenerateFrame(
wr::RenderReasons aReasons) {
if (mDestroyed) {
return;
}
InvalidateRenderedFrame();
ScheduleGenerateFrame();
InvalidateRenderedFrame(aReasons);
ScheduleGenerateFrame(aReasons);
}
mozilla::ipc::IPCResult WebRenderBridgeParent::RecvCapture() {
@ -2050,7 +2056,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSyncWithCompositor() {
FlushSceneBuilds();
if (RefPtr<WebRenderBridgeParent> root = GetRootWebRenderBridgeParent()) {
root->FlushFrameGeneration();
root->FlushFrameGeneration(wr::RenderReasons::CONTENT_SYNC);
}
FlushFramePresentation();
// Finally, we force the AsyncImagePipelineManager to handle all the
@ -2194,12 +2200,14 @@ void WebRenderBridgeParent::CompositeIfNeeded() {
if (mSkippedComposite) {
mSkippedComposite = false;
if (mCompositorScheduler) {
mCompositorScheduler->ScheduleComposition();
mCompositorScheduler->ScheduleComposition(mSkippedCompositeReasons);
}
mSkippedCompositeReasons = wr::RenderReasons::NONE;
}
}
void WebRenderBridgeParent::CompositeToTarget(VsyncId aId,
wr::RenderReasons aReasons,
gfx::DrawTarget* aTarget,
const gfx::IntRect* aRect) {
// This function should only get called in the root WRBP
@ -2235,6 +2243,7 @@ void WebRenderBridgeParent::CompositeToTarget(VsyncId aId,
wr::RenderThread::Get()->TooManyPendingFrames(mApi->GetId())) {
// Render thread is busy, try next time.
mSkippedComposite = true;
mSkippedCompositeReasons = mSkippedCompositeReasons | aReasons;
ResetPreviousSampleTime();
// Record that we skipped presenting a frame for
@ -2251,7 +2260,7 @@ void WebRenderBridgeParent::CompositeToTarget(VsyncId aId,
}
mCompositionOpportunityId = mCompositionOpportunityId.Next();
MaybeGenerateFrame(aId, /* aForceGenerateFrame */ false);
MaybeGenerateFrame(aId, /* aForceGenerateFrame */ false, aReasons);
}
TimeDuration WebRenderBridgeParent::GetVsyncInterval() const {
@ -2264,7 +2273,8 @@ TimeDuration WebRenderBridgeParent::GetVsyncInterval() const {
}
void WebRenderBridgeParent::MaybeGenerateFrame(VsyncId aId,
bool aForceGenerateFrame) {
bool aForceGenerateFrame,
wr::RenderReasons aReasons) {
// This function should only get called in the root WRBP
MOZ_ASSERT(IsRootWebRenderBridgeParent());
LOG("WebRenderBridgeParent::MaybeGenerateFrame() PipelineId %" PRIx64
@ -2304,7 +2314,7 @@ void WebRenderBridgeParent::MaybeGenerateFrame(VsyncId aId,
// Trigger another CompositeToTarget() call because there might be another
// frame that we want to generate after this one.
// It will check if we actually want to generate the frame or not.
mCompositorScheduler->ScheduleComposition();
mCompositorScheduler->ScheduleComposition(aReasons);
}
bool generateFrame = mAsyncImageManager->GetAndResetWillGenerateFrame() ||
@ -2321,7 +2331,7 @@ void WebRenderBridgeParent::MaybeGenerateFrame(VsyncId aId,
if (RefPtr<OMTASampler> sampler = GetOMTASampler()) {
if (sampler->HasAnimations()) {
ScheduleGenerateFrame();
ScheduleGenerateFrame(wr::RenderReasons::ANIMATED_PROPERTY);
}
}
@ -2336,7 +2346,7 @@ void WebRenderBridgeParent::MaybeGenerateFrame(VsyncId aId,
#endif
MOZ_ASSERT(generateFrame);
fastTxn.GenerateFrame(aId);
fastTxn.GenerateFrame(aId, aReasons);
mApi->SendTransaction(fastTxn);
#if defined(MOZ_WIDGET_ANDROID)
@ -2352,7 +2362,7 @@ void WebRenderBridgeParent::MaybeGenerateFrame(VsyncId aId,
mDisablingNativeCompositor = false;
// Ensure we generate and render a frame immediately.
ScheduleForcedGenerateFrame();
ScheduleForcedGenerateFrame(aReasons);
}
}
@ -2406,7 +2416,7 @@ void WebRenderBridgeParent::NotifyDidSceneBuild(
mMostRecentComposite >= lastVsync ||
((TimeStamp::Now() - lastVsync).ToMilliseconds() >
StaticPrefs::gfx_webrender_late_scenebuild_threshold())) {
mCompositorScheduler->ScheduleComposition();
mCompositorScheduler->ScheduleComposition(wr::RenderReasons::SCENE);
return;
}
@ -2425,13 +2435,14 @@ void WebRenderBridgeParent::NotifyDidSceneBuild(
// we did all of display list building and scene building within the
// threshold), then don't do an early composite.
if (startId == lastVsyncId) {
mCompositorScheduler->ScheduleComposition();
mCompositorScheduler->ScheduleComposition(wr::RenderReasons::SCENE);
return;
}
}
}
CompositeToTarget(mCompositorScheduler->GetLastVsyncId(), nullptr, nullptr);
CompositeToTarget(mCompositorScheduler->GetLastVsyncId(),
wr::RenderReasons::SCENE, nullptr, nullptr);
}
static Telemetry::HistogramID GetHistogramId(const bool aIsLargePaint,
@ -2555,14 +2566,15 @@ LayersId WebRenderBridgeParent::GetLayersId() const {
return wr::AsLayersId(mPipelineId);
}
void WebRenderBridgeParent::ScheduleGenerateFrame() {
void WebRenderBridgeParent::ScheduleGenerateFrame(wr::RenderReasons aReasons) {
if (mCompositorScheduler) {
mAsyncImageManager->SetWillGenerateFrame();
mCompositorScheduler->ScheduleComposition();
mCompositorScheduler->ScheduleComposition(aReasons);
}
}
void WebRenderBridgeParent::FlushRendering(bool aWaitForPresent) {
void WebRenderBridgeParent::FlushRendering(wr::RenderReasons aReasons,
bool aWaitForPresent) {
if (mDestroyed) {
return;
}
@ -2570,7 +2582,7 @@ void WebRenderBridgeParent::FlushRendering(bool aWaitForPresent) {
// This gets called during e.g. window resizes, so we need to flush the
// scene (which has the display list at the new window size).
FlushSceneBuilds();
FlushFrameGeneration();
FlushFrameGeneration(aReasons);
if (aWaitForPresent) {
FlushFramePresentation();
}
@ -2616,7 +2628,7 @@ bool WebRenderBridgeParent::Resume() {
}
// Ensure we generate and render a frame immediately.
ScheduleForcedGenerateFrame();
ScheduleForcedGenerateFrame(wr::RenderReasons::WIDGET);
return true;
}
@ -2633,7 +2645,7 @@ void WebRenderBridgeParent::ClearResources() {
wr::Epoch wrEpoch = GetNextWrEpoch();
mReceivedDisplayList = false;
// Schedule generate frame to clean up Pipeline
ScheduleGenerateFrame();
ScheduleGenerateFrame(wr::RenderReasons::CLEAR_RESOURCES);
// WrFontKeys and WrImageKeys are deleted during WebRenderAPI destruction.
for (const auto& entry : mTextureHosts) {

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

@ -143,7 +143,8 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
mozilla::ipc::IPCResult RecvClearCachedResources() override;
mozilla::ipc::IPCResult RecvInvalidateRenderedFrame() override;
mozilla::ipc::IPCResult RecvScheduleComposite() override;
mozilla::ipc::IPCResult RecvScheduleComposite(
const wr::RenderReasons& aReasons) override;
mozilla::ipc::IPCResult RecvCapture() override;
mozilla::ipc::IPCResult RecvStartCaptureSequence(
const nsCString& path, const uint32_t& aFlags) override;
@ -182,7 +183,8 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
// CompositorVsyncSchedulerOwner
bool IsPendingComposite() override { return false; }
void FinishPendingComposite() override {}
void CompositeToTarget(VsyncId aId, gfx::DrawTarget* aTarget,
void CompositeToTarget(VsyncId aId, wr::RenderReasons aReasons,
gfx::DrawTarget* aTarget,
const gfx::IntRect* aRect = nullptr) override;
TimeDuration GetVsyncInterval() const override;
@ -240,7 +242,7 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
return aFontKey.mNamespace == mIdNamespace;
}
void FlushRendering(bool aWaitForPresent = true);
void FlushRendering(wr::RenderReasons aReasons, bool aWaitForPresent = true);
/**
* Schedule generating WebRender frame definitely at next composite timing.
@ -253,7 +255,7 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
* Call CompositorVsyncScheduler::ScheduleComposition() directly, if we just
* want to trigger AsyncImagePipelines update checks.
*/
void ScheduleGenerateFrame();
void ScheduleGenerateFrame(wr::RenderReasons aReason);
/**
* Invalidate rendered frame.
@ -261,7 +263,7 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
* WebRender could skip frame rendering if there is no update.
* This function is used to force invalidating even when there is no update.
*/
void InvalidateRenderedFrame();
void InvalidateRenderedFrame(wr::RenderReasons aReasons);
/**
* Schedule forced frame rendering at next composite timing.
@ -269,7 +271,7 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
* WebRender could skip frame rendering if there is no update.
* This function is used to force rendering even when there is no update.
*/
void ScheduleForcedGenerateFrame();
void ScheduleForcedGenerateFrame(wr::RenderReasons aReasons);
void NotifyDidSceneBuild(RefPtr<const wr::WebRenderPipelineInfo> aInfo);
@ -412,10 +414,11 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
void RollbackWrEpoch();
void FlushSceneBuilds();
void FlushFrameGeneration();
void FlushFrameGeneration(wr::RenderReasons aReasons);
void FlushFramePresentation();
void MaybeGenerateFrame(VsyncId aId, bool aForceGenerateFrame);
void MaybeGenerateFrame(VsyncId aId, bool aForceGenerateFrame,
wr::RenderReasons aReasons);
VsyncId GetVsyncIdForEpoch(const wr::Epoch& aEpoch) {
for (auto& id : mPendingTransactionIds) {
@ -504,6 +507,7 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
#endif
uint32_t mBoolParameterBits;
uint16_t mBlobTileSize;
wr::RenderReasons mSkippedCompositeReasons;
bool mDestroyed;
bool mReceivedDisplayList;
bool mIsFirstPaint;

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

@ -69,7 +69,8 @@ void WebRenderImageHost::UseTextureHost(
for (const auto& it : mWrBridges) {
RefPtr<WebRenderBridgeParent> wrBridge = it.second->WrBridge();
if (wrBridge && wrBridge->CompositorScheduler()) {
wrBridge->CompositorScheduler()->ScheduleComposition();
wrBridge->CompositorScheduler()->ScheduleComposition(
wr::RenderReasons::ASYNC_IMAGE);
}
}
}

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

@ -685,7 +685,7 @@ void WebRenderLayerManager::RemoveDidCompositeObserver(
mDidCompositeObservers.RemoveElement(aObserver);
}
void WebRenderLayerManager::FlushRendering() {
void WebRenderLayerManager::FlushRendering(wr::RenderReasons aReasons) {
CompositorBridgeChild* cBridge = GetCompositorBridgeChild();
if (!cBridge) {
return;
@ -696,15 +696,19 @@ void WebRenderLayerManager::FlushRendering() {
// might happen.
bool resizing = mWidget && mWidget->IsResizingNativeWidget().valueOr(true);
if (resizing) {
aReasons = aReasons | wr::RenderReasons::RESIZE;
}
// Limit async FlushRendering to !resizing and Win DComp.
// XXX relax the limitation
if (WrBridge()->GetCompositorUseDComp() && !resizing) {
cBridge->SendFlushRenderingAsync();
cBridge->SendFlushRenderingAsync(aReasons);
} else if (mWidget->SynchronouslyRepaintOnResize() ||
StaticPrefs::layers_force_synchronous_resize()) {
cBridge->SendFlushRendering();
cBridge->SendFlushRendering(aReasons);
} else {
cBridge->SendFlushRenderingAsync();
cBridge->SendFlushRenderingAsync(aReasons);
}
}
@ -731,8 +735,8 @@ void WebRenderLayerManager::SendInvalidRegion(const nsIntRegion& aRegion) {
}
}
void WebRenderLayerManager::ScheduleComposite() {
WrBridge()->SendScheduleComposite();
void WebRenderLayerManager::ScheduleComposite(wr::RenderReasons aReasons) {
WrBridge()->SendScheduleComposite(aReasons);
}
already_AddRefed<PersistentBufferProvider>

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

@ -110,12 +110,12 @@ class WebRenderLayerManager final : public WindowRenderer {
void AddDidCompositeObserver(DidCompositeObserver* aObserver);
void RemoveDidCompositeObserver(DidCompositeObserver* aObserver);
void FlushRendering() override;
void FlushRendering(wr::RenderReasons aReasons) override;
void WaitOnTransactionProcessed() override;
void SendInvalidRegion(const nsIntRegion& aRegion);
void ScheduleComposite();
void ScheduleComposite(wr::RenderReasons aReasons);
void SetNeedsComposite(bool aNeedsComposite) {
mNeedsComposite = aNeedsComposite;

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

@ -145,6 +145,10 @@ template <>
struct ParamTraits<mozilla::wr::ExternalImageKeyPair>
: public PlainOldDataSerializer<mozilla::wr::ExternalImageKeyPair> {};
template <>
struct ParamTraits<mozilla::wr::RenderReasons>
: public PlainOldDataSerializer<mozilla::wr::RenderReasons> {};
} // namespace IPC
#endif // GFX_WEBRENDERMESSAGEUTILS_H

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

@ -1234,17 +1234,19 @@ void wr_notifier_external_event(mozilla::wr::WrWindowId aWindowId,
std::move(evt));
}
static void NotifyScheduleRender(mozilla::wr::WrWindowId aWindowId) {
static void NotifyScheduleRender(mozilla::wr::WrWindowId aWindowId,
wr::RenderReasons aReasons) {
RefPtr<mozilla::layers::CompositorBridgeParent> cbp = mozilla::layers::
CompositorBridgeParent::GetCompositorBridgeParentFromWindowId(aWindowId);
if (cbp) {
cbp->ScheduleComposition();
cbp->ScheduleComposition(aReasons);
}
}
void wr_schedule_render(mozilla::wr::WrWindowId aWindowId) {
void wr_schedule_render(mozilla::wr::WrWindowId aWindowId,
wr::RenderReasons aReasons) {
layers::CompositorThread()->Dispatch(NewRunnableFunction(
"NotifyScheduleRender", &NotifyScheduleRender, aWindowId));
"NotifyScheduleRender", &NotifyScheduleRender, aWindowId, aReasons));
}
static void NotifyDidSceneBuild(

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

@ -276,12 +276,13 @@ void TransactionBuilder::ClearDisplayList(Epoch aEpoch,
wr_transaction_clear_display_list(mTxn, aEpoch, aPipelineId);
}
void TransactionBuilder::GenerateFrame(const VsyncId& aVsyncId) {
wr_transaction_generate_frame(mTxn, aVsyncId.mId);
void TransactionBuilder::GenerateFrame(const VsyncId& aVsyncId,
wr::RenderReasons aReasons) {
wr_transaction_generate_frame(mTxn, aVsyncId.mId, aReasons);
}
void TransactionBuilder::InvalidateRenderedFrame() {
wr_transaction_invalidate_rendered_frame(mTxn);
void TransactionBuilder::InvalidateRenderedFrame(wr::RenderReasons aReasons) {
wr_transaction_invalidate_rendered_frame(mTxn, aReasons);
}
bool TransactionBuilder::IsEmpty() const {

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

@ -119,9 +119,9 @@ class TransactionBuilder final {
void ClearDisplayList(Epoch aEpoch, wr::WrPipelineId aPipeline);
void GenerateFrame(const VsyncId& aVsyncId);
void GenerateFrame(const VsyncId& aVsyncId, wr::RenderReasons aReasons);
void InvalidateRenderedFrame();
void InvalidateRenderedFrame(wr::RenderReasons aReasons);
void SetDocumentView(const LayoutDeviceIntRect& aDocRect);

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

@ -530,7 +530,7 @@ extern "C" {
fn wr_notifier_new_frame_ready(window_id: WrWindowId);
fn wr_notifier_nop_frame_done(window_id: WrWindowId);
fn wr_notifier_external_event(window_id: WrWindowId, raw_event: usize);
fn wr_schedule_render(window_id: WrWindowId);
fn wr_schedule_render(window_id: WrWindowId, reasons: RenderReasons);
// NOTE: This moves away from pipeline_info.
fn wr_finished_scene_build(window_id: WrWindowId, pipeline_info: &mut WrPipelineInfo);
@ -986,7 +986,7 @@ impl SceneBuilderHooks for APZCallbacks {
}
fn post_resource_update(&self, _document_ids: &Vec<DocumentId>) {
unsafe { wr_schedule_render(self.window_id) }
unsafe { wr_schedule_render(self.window_id, RenderReasons::POST_RESOURCE_UPDATES_HOOK) }
unsafe {
gecko_profiler_end_marker(b"SceneBuilding\0".as_ptr() as *const c_char);
}
@ -1872,13 +1872,13 @@ pub extern "C" fn wr_transaction_set_document_view(txn: &mut Transaction, doc_re
}
#[no_mangle]
pub extern "C" fn wr_transaction_generate_frame(txn: &mut Transaction, id: u64) {
txn.generate_frame(id);
pub extern "C" fn wr_transaction_generate_frame(txn: &mut Transaction, id: u64, reasons: RenderReasons) {
txn.generate_frame(id, reasons);
}
#[no_mangle]
pub extern "C" fn wr_transaction_invalidate_rendered_frame(txn: &mut Transaction) {
txn.invalidate_rendered_frame();
pub extern "C" fn wr_transaction_invalidate_rendered_frame(txn: &mut Transaction, reasons: RenderReasons) {
txn.invalidate_rendered_frame(reasons);
}
fn wr_animation_properties_into_vec<T>(

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

@ -487,7 +487,7 @@ fn main() {
);
}
txn.generate_frame(0);
txn.generate_frame(0, RenderReasons::empty());
api.send_transaction(document_id, txn);
// Tick the compositor (in this sample, we don't block on UI events)
@ -534,7 +534,7 @@ fn main() {
}
}
txn.generate_frame(0);
txn.generate_frame(0, RenderReasons::empty());
api.send_transaction(document_id, txn);
current_epoch.0 += 1;
time += 0.001;

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

@ -200,7 +200,7 @@ impl Example for App {
colors: vec![],
},
);
txn.generate_frame(0);
txn.generate_frame(0, RenderReasons::empty());
api.send_transaction(document_id, txn);
}
_ => (),

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

@ -214,7 +214,7 @@ pub fn main_wrapper<E: Example>(
builder.end(),
);
txn.set_root_pipeline(pipeline_id);
txn.generate_frame(0);
txn.generate_frame(0, RenderReasons::empty());
api.send_transaction(document_id, txn);
println!("Entering event loop");
@ -303,7 +303,7 @@ pub fn main_wrapper<E: Example>(
layout_size,
builder.end(),
);
txn.generate_frame(0);
txn.generate_frame(0, RenderReasons::empty());
}
api.send_transaction(document_id, txn);

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

@ -124,7 +124,7 @@ impl Example for App {
doc.content_rect.size(),
builder.end(),
);
txn.generate_frame(0);
txn.generate_frame(0, RenderReasons::empty());
api.send_transaction(doc.id, txn);
}
}

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

@ -104,7 +104,7 @@ impl Example for App {
&DirtyRect::All,
);
let mut txn = Transaction::new();
txn.generate_frame(0);
txn.generate_frame(0, RenderReasons::empty());
api.send_transaction(document_id, txn);
}
_ => {}

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

@ -284,7 +284,7 @@ impl Window {
builder.end(),
);
txn.set_root_pipeline(self.pipeline_id);
txn.generate_frame(0);
txn.generate_frame(0, RenderReasons::empty());
api.send_transaction(self.document_id, txn);
renderer.update();

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

@ -190,7 +190,7 @@ impl Example for App {
ExternalScrollId(EXT_SCROLL_ID_CONTENT, PipelineId::dummy()),
ScrollClamping::ToContentBounds,
);
txn.generate_frame(0);
txn.generate_frame(0, RenderReasons::empty());
}
}
winit::WindowEvent::CursorMoved { position: LogicalPosition { x, y }, .. } => {
@ -211,7 +211,7 @@ impl Example for App {
ScrollClamping::ToContentBounds,
);
txn.generate_frame(0);
txn.generate_frame(0, RenderReasons::empty());
}
winit::WindowEvent::MouseInput { .. } => {
let results = api.hit_test(

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

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{ColorF, DocumentId, ExternalImageId, PrimitiveFlags, Parameter};
use api::{ColorF, DocumentId, ExternalImageId, PrimitiveFlags, Parameter, RenderReasons};
use api::{ImageFormat, NotificationRequest, Shadow, FilterOp, ImageBufferKind};
use api::units::*;
use api;
@ -653,6 +653,7 @@ pub struct RenderedDocument {
pub frame: Frame,
pub is_new_scene: bool,
pub profile: TransactionProfile,
pub render_reasons: RenderReasons,
pub frame_stats: Option<FullFrameStats>
}

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

@ -93,6 +93,8 @@ static PROFILER_PRESETS: &'static[(&'static str, &'static str)] = &[
(&"Interners", "Interned primitives,Interned clips,Interned pictures,Interned text runs,Interned normal borders,Interned image borders,Interned images,Interned YUV images,Interned line decorations,Interned linear gradients,Interned radial gradients,Interned conic gradients,Interned filter data,Interned backdrops"),
// Gpu sampler queries (need the pref gfx.webrender.debug.gpu-sampler-queries).
(&"GPU samplers", &"Alpha targets samplers,Transparent pass samplers,Opaque pass samplers,Total samplers"),
(&"Render reasons", &"Reason scene, Reason animated propert, Reason resource update, Reason async image, Reason clear resources, Reason APZ, Reason resize, Reason widget, Reason cache flush, Reason snapshot, Reason resource hook, Reason config change, Reason content sync, Reason flush, Reason vsync, Reason testing, Reason other"),
];
fn find_preset(name: &str) -> Option<&'static str> {
@ -231,7 +233,26 @@ pub const DEPTH_TARGETS_MEM: usize = 100;
pub const SHADER_BUILD_TIME: usize = 101;
pub const NUM_PROFILER_EVENTS: usize = 102;
pub const RENDER_REASON_FIRST: usize = 102;
pub const RENDER_REASON_SCENE: usize = 102;
pub const RENDER_REASON_ANIMATED_PROPERTY: usize = 103;
pub const RENDER_REASON_RESOURCE_UPDATE: usize = 104;
pub const RENDER_REASON_ASYNC_IMAGE: usize = 105;
pub const RENDER_REASON_CLEAR_RESOURCES: usize = 106;
pub const RENDER_REASON_APZ: usize = 107;
pub const RENDER_REASON_RESIZE: usize = 108;
pub const RENDER_REASON_WIDGET: usize = 109;
pub const RENDER_REASON_TEXTURE_CACHE_FLUSH: usize = 110;
pub const RENDER_REASON_SNAPSHOT: usize = 111;
pub const RENDER_REASON_POST_RESOURCE_UPDATE_HOOKS: usize = 112;
pub const RENDER_REASON_CONFIG_CHANGE: usize = 113;
pub const RENDER_REASON_CONTENT_SYNC: usize = 114;
pub const RENDER_REASON_FLUSH: usize = 115;
pub const RENDER_REASON_TESTING: usize = 116;
pub const RENDER_REASON_OTHER: usize = 117;
pub const RENDER_REASON_VSYNC: usize = 118;
pub const NUM_PROFILER_EVENTS: usize = 119;
pub struct Profiler {
counters: Vec<Counter>,
@ -386,6 +407,25 @@ impl Profiler {
float("Depth targets mem", "MB", DEPTH_TARGETS_MEM, Expected::none()),
float("Shader build time", "ms", SHADER_BUILD_TIME, Expected::none()),
// We use the expected range to highlight render reasons that are happening.
float("Reason scene", "", RENDER_REASON_SCENE, expected(0.0..0.01)),
float("Reason animated propert", "", RENDER_REASON_ANIMATED_PROPERTY, expected(0.0..0.01)),
float("Reason resource update", "", RENDER_REASON_RESOURCE_UPDATE, expected(0.0..0.01)),
float("Reason async image", "", RENDER_REASON_ASYNC_IMAGE, expected(0.0..0.01)),
float("Reason clear resources", "", RENDER_REASON_CLEAR_RESOURCES, expected(0.0..0.01)),
float("Reason APZ", "", RENDER_REASON_APZ, expected(0.0..0.01)),
float("Reason resize", "", RENDER_REASON_RESIZE, expected(0.0..0.01)),
float("Reason widget", "", RENDER_REASON_WIDGET, expected(0.0..0.01)),
float("Reason texture cache flush", "", RENDER_REASON_TEXTURE_CACHE_FLUSH, expected(0.0..0.01)),
float("Reason snapshot", "", RENDER_REASON_SNAPSHOT, expected(0.0..0.01)),
float("Reason resource hook", "", RENDER_REASON_POST_RESOURCE_UPDATE_HOOKS, expected(0.0..0.01)),
float("Reason config change", "", RENDER_REASON_CONFIG_CHANGE, expected(0.0..0.01)),
float("Reason content sync", "", RENDER_REASON_CONTENT_SYNC, expected(0.0..0.01)),
float("Reason flush", "", RENDER_REASON_FLUSH, expected(0.0..0.01)),
float("Reason testing", "", RENDER_REASON_TESTING, expected(0.0..0.01)),
float("Reason other", "", RENDER_REASON_OTHER, expected(0.0..0.01)),
float("On vsync", "", RENDER_REASON_VSYNC, expected(0.0..0.01)),
];
let mut counters = Vec::with_capacity(profile_counters.len());

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

@ -21,7 +21,7 @@ use crate::api::{DocumentId, PipelineId, PropertyBindingId, PropertyBindingKey,
use crate::api::{HitTestResult, HitTesterRequest, ApiHitTester, PropertyValue, DynamicProperties};
use crate::api::{ScrollClamping, TileSize, NotificationRequest, DebugFlags};
use crate::api::{GlyphDimensionRequest, GlyphIndexRequest, GlyphIndex, GlyphDimensions};
use crate::api::{FontInstanceOptions, FontInstancePlatformOptions, FontVariation};
use crate::api::{FontInstanceOptions, FontInstancePlatformOptions, FontVariation, RenderReasons};
use crate::api::DEFAULT_TILE_SIZE;
use crate::api::units::*;
use crate::api_resources::ApiResources;
@ -174,6 +174,9 @@ pub struct Transaction {
pub invalidate_rendered_frame: bool,
low_priority: bool,
///
pub render_reasons: RenderReasons,
}
impl Transaction {
@ -188,6 +191,7 @@ impl Transaction {
generate_frame: GenerateFrame::No,
invalidate_rendered_frame: false,
low_priority: false,
render_reasons: RenderReasons::empty(),
}
}
@ -358,8 +362,9 @@ impl Transaction {
/// as to when happened.
///
/// [notifier]: trait.RenderNotifier.html#tymethod.new_frame_ready
pub fn generate_frame(&mut self, id: u64) {
pub fn generate_frame(&mut self, id: u64, reasons: RenderReasons) {
self.generate_frame = GenerateFrame::Yes{ id };
self.render_reasons |= reasons;
}
/// Invalidate rendered frame. It ensure that frame will be rendered during
@ -368,8 +373,9 @@ impl Transaction {
/// But there are cases that needs to force rendering.
/// - Content of image is updated by reusing same ExternalImageId.
/// - Platform requests it if pixels become stale (like wakeup from standby).
pub fn invalidate_rendered_frame(&mut self) {
pub fn invalidate_rendered_frame(&mut self, reasons: RenderReasons) {
self.invalidate_rendered_frame = true;
self.render_reasons |= reasons
}
/// Reset the list of animated property bindings that should be used to resolve
@ -412,6 +418,7 @@ impl Transaction {
blob_requests: Vec::new(),
rasterized_blobs: Vec::new(),
profile: TransactionProfile::new(),
render_reasons: self.render_reasons,
})
}
@ -597,6 +604,8 @@ pub struct TransactionMsg {
pub rasterized_blobs: Vec<(BlobImageRequest, BlobImageResult)>,
/// Collect various data along the rendering pipeline to display it in the embedded profiler.
pub profile: TransactionProfile,
/// Keep track of who asks rendering to happen.
pub render_reasons: RenderReasons,
}
impl fmt::Debug for TransactionMsg {
@ -1219,6 +1228,7 @@ impl RenderApi {
blob_requests: Vec::new(),
rasterized_blobs: Vec::new(),
profile: TransactionProfile::new(),
render_reasons: RenderReasons::empty(),
})
}

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

@ -12,7 +12,7 @@ use api::{DebugFlags, BlobImageHandler, Parameter, BoolParameter};
use api::{DocumentId, ExternalScrollId, HitTestResult};
use api::{IdNamespace, PipelineId, RenderNotifier, ScrollClamping};
use api::{NotificationRequest, Checkpoint, QualitySettings};
use api::{PrimitiveKeyKind};
use api::{PrimitiveKeyKind, RenderReasons};
use api::units::*;
use api::channel::{single_msg_channel, Sender, Receiver};
#[cfg(any(feature = "capture", feature = "replay"))]
@ -436,7 +436,8 @@ impl Document {
debug_flags: DebugFlags,
tile_cache_logger: &mut TileCacheLogger,
tile_caches: &mut FastHashMap<SliceId, Box<TileCacheInstance>>,
frame_stats: Option<FullFrameStats>
frame_stats: Option<FullFrameStats>,
render_reasons: RenderReasons,
) -> RenderedDocument {
let frame_build_start_time = precise_time_ns();
@ -487,7 +488,8 @@ impl Document {
frame,
is_new_scene,
profile: self.profile.take_and_reset(),
frame_stats: frame_stats
frame_stats: frame_stats,
render_reasons,
}
}
@ -862,6 +864,7 @@ impl RenderBackend {
txn.frame_ops.take(),
txn.notifications.take(),
txn.render_frame,
RenderReasons::SCENE,
None,
txn.invalidate_rendered_frame,
frame_counter,
@ -1204,6 +1207,7 @@ impl RenderBackend {
txn.frame_ops.take(),
txn.notifications.take(),
txn.generate_frame.as_bool(),
txn.render_reasons,
txn.generate_frame.id(),
txn.invalidate_rendered_frame,
frame_counter,
@ -1241,6 +1245,7 @@ impl RenderBackend {
Vec::default(),
Vec::default(),
false,
RenderReasons::empty(),
None,
false,
frame_counter,
@ -1261,6 +1266,7 @@ impl RenderBackend {
mut frame_ops: Vec<FrameMsg>,
mut notifications: Vec<NotificationRequest>,
mut render_frame: bool,
render_reasons: RenderReasons,
generated_frame_id: Option<u64>,
invalidate_rendered_frame: bool,
frame_counter: &mut u32,
@ -1352,7 +1358,8 @@ impl RenderBackend {
self.debug_flags,
&mut self.tile_cache_logger,
&mut self.tile_caches,
frame_stats
frame_stats,
render_reasons,
);
debug!("generated frame for document {:?} with {} passes",
@ -1544,6 +1551,7 @@ impl RenderBackend {
&mut self.tile_cache_logger,
&mut self.tile_caches,
None,
RenderReasons::empty(),
);
// After we rendered the frames, there are pending updates to both
// GPU cache and resources. Instead of serializing them, we are going to make sure
@ -1814,7 +1822,13 @@ impl RenderBackend {
let msg_publish = ResultMsg::PublishDocument(
id,
RenderedDocument { frame, is_new_scene: true, profile: TransactionProfile::new(), frame_stats: None },
RenderedDocument {
frame,
is_new_scene: true,
profile: TransactionProfile::new(),
render_reasons: RenderReasons::empty(),
frame_stats: None,
},
self.resource_cache.pending_updates(),
);
self.result_tx.send(msg_publish).unwrap();

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

@ -35,7 +35,7 @@
//! calling `DrawTarget::to_framebuffer_rect`
use api::{BlobImageHandler, ColorF, ColorU, MixBlendMode};
use api::{DocumentId, Epoch, ExternalImageHandler};
use api::{DocumentId, Epoch, ExternalImageHandler, RenderReasons};
use api::CrashAnnotator;
#[cfg(feature = "replay")]
use api::ExternalImageId;
@ -1502,6 +1502,7 @@ impl Renderer {
doc.profile.merge(&mut prev_doc.profile);
if prev_doc.frame.must_be_drawn() {
prev_doc.render_reasons |= RenderReasons::TEXTURE_CACHE_FLUSH;
self.render_impl(
document_id,
&mut prev_doc,
@ -2092,6 +2093,31 @@ impl Renderer {
self.profiler.update_frame_stats(stats);
}
// Turn the render reasons bitflags into something we can see in the profiler.
// For now this is just a binary yes/no for each bit, which means that when looking
// at "Render reasons" in the profiler HUD the average view indicates the proportion
// of frames that had the bit set over a half second window whereas max shows whether
// the bit as been set at least once during that time window.
// We could implement better ways to visualize this information.
let add_markers = thread_is_being_profiled();
for i in 0..RenderReasons::NUM_BITS {
let counter = profiler::RENDER_REASON_FIRST + i as usize;
let mut val = 0.0;
let reason_bit = RenderReasons::from_bits_truncate(1 << i);
if active_doc.render_reasons.contains(reason_bit) {
val = 1.0;
if add_markers {
let event_str = format!("Render reason {:?}", reason_bit);
if let Ok(event_str) = std::ffi::CString::new(&event_str[..]) {
add_event_marker(event_str.as_c_str());
}
}
}
self.profile.set(counter, val);
}
active_doc.render_reasons = RenderReasons::empty();
self.texture_resolver.update_profile(&mut self.profile);
// Note: this clears the values in self.profile.

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

@ -524,6 +524,42 @@ pub enum BoolParameter {
DrawCallsForTextureCopy = 3,
}
bitflags! {
/// Flags to track why we are rendering.
#[repr(C)]
#[derive(Default, Deserialize, MallocSizeOf, Serialize)]
pub struct RenderReasons: u32 {
/// Equivalent of empty() for the C++ side.
const NONE = 0;
const SCENE = 1 << 0;
const ANIMATED_PROPERTY = 1 << 1;
const RESOURCE_UPDATE = 1 << 2;
const ASYNC_IMAGE = 1 << 3;
const CLEAR_RESOURCES = 1 << 4;
const APZ = 1 << 5;
/// Window resize
const RESIZE = 1 << 6;
/// Various widget-related reasons
const WIDGET = 1 << 7;
/// See Frame::must_be_drawn
const TEXTURE_CACHE_FLUSH = 1 << 8;
const SNAPSHOT = 1 << 9;
const POST_RESOURCE_UPDATES_HOOK = 1 << 10;
const CONFIG_CHANGE = 1 << 11;
const CONTENT_SYNC = 1 << 12;
const FLUSH = 1 << 13;
const TESTING = 1 << 14;
const OTHER = 1 << 15;
/// Vsync isn't actually "why" we render but it can be useful
/// to see which frames were driven by the vsync scheduler so
/// we store a bit for it.
const VSYNC = 1 << 16;
}
}
impl RenderReasons {
pub const NUM_BITS: u32 = 17;
}
bitflags! {
/// Flags to enable/disable various builtin debugging tools.

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

@ -106,7 +106,7 @@ impl<'a> RawtestHarness<'a> {
);
epoch.0 += 1;
txn.generate_frame(0);
txn.generate_frame(0, RenderReasons::TESTING);
self.wrench.api.send_transaction(self.wrench.document_id, txn);
}
@ -1252,7 +1252,7 @@ impl<'a> RawtestHarness<'a> {
layout_size,
builder.end(),
);
txn.generate_frame(0);
txn.generate_frame(0, RenderReasons::TESTING);
self.wrench.api.send_transaction(self.wrench.document_id, txn);
@ -1287,7 +1287,7 @@ impl<'a> RawtestHarness<'a> {
// 6. rebuild the scene and compare again
let mut txn = Transaction::new();
txn.set_root_pipeline(captured.root_pipeline_id.unwrap());
txn.generate_frame(0);
txn.generate_frame(0, RenderReasons::TESTING);
self.wrench.api.send_transaction(captured.document_id, txn);
let pixels2 = self.render_and_get_pixels(window_rect);
self.compare_pixels(pixels0, pixels2, window_rect.size());
@ -1319,7 +1319,7 @@ impl<'a> RawtestHarness<'a> {
layout_size,
builder.end(),
);
txn.generate_frame(0);
txn.generate_frame(0, RenderReasons::TESTING);
self.wrench.api.send_transaction(doc_id, txn);
// Ensure we get a notification from rendering the above, even though

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

@ -580,7 +580,7 @@ impl Wrench {
txn.scroll_node_with_id(*offset, *id, ScrollClamping::NoClamping);
}
txn.generate_frame(0);
txn.generate_frame(0, RenderReasons::TESTING);
self.api.send_transaction(self.document_id, txn);
}
@ -601,7 +601,7 @@ impl Wrench {
pub fn refresh(&mut self) {
self.begin_frame();
let mut txn = Transaction::new();
txn.generate_frame(0);
txn.generate_frame(0, RenderReasons::TESTING);
self.api.send_transaction(self.document_id, txn);
}

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

@ -7,6 +7,7 @@
#ifndef MOZILLA_PAINTING_WINDOWRENDERER_H
#define MOZILLA_PAINTING_WINDOWRENDERER_H
#include "mozilla/webrender/webrender_ffi.h"
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/dom/Animation.h" // for Animation
#include "mozilla/layers/ScrollableLayerGuid.h" // for ScrollableLayerGuid, ScrollableLayerGuid::ViewID
@ -164,7 +165,7 @@ class WindowRenderer : public FrameRecorder {
* Note: This may sychronously wait on a remote compositor
* to complete rendering.
*/
virtual void FlushRendering() {}
virtual void FlushRendering(wr::RenderReasons aReasons) {}
/**
* Make sure that the previous transaction has been

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

@ -311,7 +311,7 @@ void nsViewManager::Refresh(nsView* aView,
#endif
WindowRenderer* renderer = widget->GetWindowRenderer();
if (!renderer->NeedsWidgetInvalidation()) {
renderer->FlushRendering();
renderer->FlushRendering(wr::RenderReasons::WIDGET);
} else {
presShell->SyncPaintFallback(aView);
}

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

@ -3591,7 +3591,7 @@ gboolean nsWindow::OnExposeEvent(cairo_t* cr) {
}
if (knowsCompositor && layerManager && layerManager->NeedsComposite()) {
layerManager->ScheduleComposite();
layerManager->ScheduleComposite(wr::RenderReasons::WIDGET);
layerManager->SetNeedsComposite(false);
}
@ -3863,7 +3863,7 @@ gboolean nsWindow::OnConfigureEvent(GtkWidget* aWidget,
// frame, and its contents might be incorrect. See bug 1280653 comment 7
// and comment 10. Specifically we must ensure we recomposite the frame
// as soon as possible to avoid the corrupted frame being displayed.
GetWindowRenderer()->FlushRendering();
GetWindowRenderer()->FlushRendering(wr::RenderReasons::WIDGET);
return FALSE;
}
@ -6042,7 +6042,7 @@ void nsWindow::ResumeCompositorHiddenWindow() {
mCompositorState = COMPOSITOR_ENABLED;
remoteRenderer->SendResumeAsync();
}
remoteRenderer->SendForcePresent();
remoteRenderer->SendForcePresent(wr::RenderReasons::WIDGET);
}
}
@ -6158,7 +6158,7 @@ void nsWindow::ResumeCompositor() {
if (remoteRenderer) {
mCompositorState = COMPOSITOR_ENABLED;
remoteRenderer->SendResumeAsync();
remoteRenderer->SendForcePresent();
remoteRenderer->SendForcePresent(wr::RenderReasons::WIDGET);
}
}

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

@ -206,7 +206,7 @@ void CompositorWidgetParent::UpdateCompositorWnd(const HWND aCompositorWnd,
// Schedule composition after ::SetParent() call in parent
// process.
layers::CompositorBridgeParent::ScheduleForcedComposition(
self->mRootLayerTreeID.ref());
self->mRootLayerTreeID.ref(), wr::RenderReasons::WIDGET);
}
},
[self](const mozilla::ipc::ResponseRejectReason&) {});

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

@ -127,7 +127,7 @@ nsIWidgetListener* nsWindow::GetPaintListener() {
void nsWindow::ForcePresent() {
if (mResizeState != RESIZING) {
if (CompositorBridgeChild* remoteRenderer = GetRemoteRenderer()) {
remoteRenderer->SendForcePresent();
remoteRenderer->SendForcePresent(wr::RenderReasons::WIDGET);
}
}
}
@ -190,7 +190,7 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel) {
!mBounds.IsEqualEdges(mLastPaintBounds)) {
// Do an early async composite so that we at least have something on the
// screen in the right place, even if the content is out of date.
layerManager->ScheduleComposite();
layerManager->ScheduleComposite(wr::RenderReasons::WIDGET);
}
mLastPaintBounds = mBounds;
@ -256,7 +256,7 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel) {
}
if (knowsCompositor && layerManager && layerManager->NeedsComposite()) {
layerManager->ScheduleComposite();
layerManager->ScheduleComposite(wr::RenderReasons::WIDGET);
layerManager->SetNeedsComposite(false);
}