Merge mozilla-central to mozilla-inbound. a=merge

This commit is contained in:
Daniel Varga 2018-12-08 11:50:00 +02:00
Родитель 43432ff2a6 9abd7f512c
Коммит 5d3de7487c
65 изменённых файлов: 640 добавлений и 282 удалений

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

@ -197,17 +197,20 @@ class UrlbarView {
let item = this._createElement("div"); let item = this._createElement("div");
item.className = "urlbarView-row"; item.className = "urlbarView-row";
item.setAttribute("resultIndex", resultIndex); item.setAttribute("resultIndex", resultIndex);
if (result.type == UrlbarUtils.MATCH_TYPE.TAB_SWITCH) { if (result.type == UrlbarUtils.MATCH_TYPE.TAB_SWITCH) {
item.setAttribute("action", "switch-to-tab"); item.setAttribute("type", "switchtab");
} else if (result.source == UrlbarUtils.MATCH_SOURCE.BOOKMARKS) {
item.setAttribute("type", "bookmark");
} }
let content = this._createElement("span"); let content = this._createElement("span");
content.className = "urlbarView-row-inner"; content.className = "urlbarView-row-inner";
item.appendChild(content); item.appendChild(content);
let actionIcon = this._createElement("span"); let typeIcon = this._createElement("span");
actionIcon.className = "urlbarView-action-icon"; typeIcon.className = "urlbarView-type-icon";
content.appendChild(actionIcon); content.appendChild(typeIcon);
let favicon = this._createElement("img"); let favicon = this._createElement("img");
favicon.className = "urlbarView-favicon"; favicon.className = "urlbarView-favicon";

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

@ -68,7 +68,7 @@
color: var(--autocomplete-popup-highlight-color); color: var(--autocomplete-popup-highlight-color);
} }
.urlbarView-action-icon, .urlbarView-type-icon,
.urlbarView-favicon { .urlbarView-favicon {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
@ -82,7 +82,11 @@
fill-opacity: 0.6; fill-opacity: 0.6;
} }
.urlbarView-row[action=switch-to-tab] > .urlbarView-row-inner > .urlbarView-action-icon { .urlbarView-row[type=bookmark] > .urlbarView-row-inner > .urlbarView-type-icon {
background-image: url(chrome://browser/skin/bookmark.svg);
}
.urlbarView-row[type=switchtab] > .urlbarView-row-inner > .urlbarView-type-icon {
background-image: url(chrome://browser/skin/tab.svg); background-image: url(chrome://browser/skin/tab.svg);
} }

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

@ -18,12 +18,12 @@ CompositorWidgetVsyncObserver::CompositorWidgetVsyncObserver(
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
} }
bool CompositorWidgetVsyncObserver::NotifyVsync(TimeStamp aTimeStamp) { bool CompositorWidgetVsyncObserver::NotifyVsync(const VsyncEvent& aVsync) {
// Vsync notifications should only arrive on the vsync thread. // Vsync notifications should only arrive on the vsync thread.
MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(!NS_IsMainThread());
mVsyncBridge->NotifyVsync(aTimeStamp, mRootLayerTreeId); mVsyncBridge->NotifyVsync(aVsync, mRootLayerTreeId);
return true; return true;
} }

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

@ -24,7 +24,7 @@ class CompositorWidgetVsyncObserver : public VsyncObserver {
CompositorWidgetVsyncObserver(RefPtr<VsyncBridgeChild> aVsyncBridge, CompositorWidgetVsyncObserver(RefPtr<VsyncBridgeChild> aVsyncBridge,
const layers::LayersId& aRootLayerTreeId); const layers::LayersId& aRootLayerTreeId);
bool NotifyVsync(TimeStamp aVsyncTimestamp) override; bool NotifyVsync(const VsyncEvent& aVsync) override;
private: private:
RefPtr<VsyncBridgeChild> mVsyncBridge; RefPtr<VsyncBridgeChild> mVsyncBridge;

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

@ -5,6 +5,7 @@
using class mozilla::TimeStamp from "mozilla/TimeStamp.h"; using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h"; using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h";
using mozilla::VsyncEvent from "mozilla/VsyncDispatcher.h";
namespace mozilla { namespace mozilla {
namespace gfx { namespace gfx {
@ -16,7 +17,7 @@ namespace gfx {
sync protocol PVsyncBridge sync protocol PVsyncBridge
{ {
parent: parent:
async NotifyVsync(TimeStamp vsyncTimeStamp, LayersId layersId); async NotifyVsync(VsyncEvent vsync, LayersId layersId);
}; };
} // namespace gfx } // namespace gfx

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

@ -46,21 +46,21 @@ void VsyncBridgeChild::Open(Endpoint<PVsyncBridgeChild>&& aEndpoint) {
class NotifyVsyncTask : public Runnable { class NotifyVsyncTask : public Runnable {
public: public:
NotifyVsyncTask(RefPtr<VsyncBridgeChild> aVsyncBridge, TimeStamp aTimeStamp, NotifyVsyncTask(RefPtr<VsyncBridgeChild> aVsyncBridge,
const layers::LayersId& aLayersId) const VsyncEvent& aVsync, const layers::LayersId& aLayersId)
: Runnable("gfx::NotifyVsyncTask"), : Runnable("gfx::NotifyVsyncTask"),
mVsyncBridge(aVsyncBridge), mVsyncBridge(aVsyncBridge),
mTimeStamp(aTimeStamp), mVsync(aVsync),
mLayersId(aLayersId) {} mLayersId(aLayersId) {}
NS_IMETHOD Run() override { NS_IMETHOD Run() override {
mVsyncBridge->NotifyVsyncImpl(mTimeStamp, mLayersId); mVsyncBridge->NotifyVsyncImpl(mVsync, mLayersId);
return NS_OK; return NS_OK;
} }
private: private:
RefPtr<VsyncBridgeChild> mVsyncBridge; RefPtr<VsyncBridgeChild> mVsyncBridge;
TimeStamp mTimeStamp; VsyncEvent mVsync;
layers::LayersId mLayersId; layers::LayersId mLayersId;
}; };
@ -68,17 +68,16 @@ bool VsyncBridgeChild::IsOnVsyncIOThread() const {
return MessageLoop::current() == mLoop; return MessageLoop::current() == mLoop;
} }
void VsyncBridgeChild::NotifyVsync(TimeStamp aTimeStamp, void VsyncBridgeChild::NotifyVsync(const VsyncEvent& aVsync,
const layers::LayersId& aLayersId) { const layers::LayersId& aLayersId) {
// This should be on the Vsync thread (not the Vsync I/O thread). // This should be on the Vsync thread (not the Vsync I/O thread).
MOZ_ASSERT(!IsOnVsyncIOThread()); MOZ_ASSERT(!IsOnVsyncIOThread());
RefPtr<NotifyVsyncTask> task = RefPtr<NotifyVsyncTask> task = new NotifyVsyncTask(this, aVsync, aLayersId);
new NotifyVsyncTask(this, aTimeStamp, aLayersId);
mLoop->PostTask(task.forget()); mLoop->PostTask(task.forget());
} }
void VsyncBridgeChild::NotifyVsyncImpl(TimeStamp aTimeStamp, void VsyncBridgeChild::NotifyVsyncImpl(const VsyncEvent& aVsync,
const layers::LayersId& aLayersId) { const layers::LayersId& aLayersId) {
// This should be on the Vsync I/O thread. // This should be on the Vsync I/O thread.
MOZ_ASSERT(IsOnVsyncIOThread()); MOZ_ASSERT(IsOnVsyncIOThread());
@ -86,7 +85,7 @@ void VsyncBridgeChild::NotifyVsyncImpl(TimeStamp aTimeStamp,
if (!mProcessToken) { if (!mProcessToken) {
return; return;
} }
SendNotifyVsync(aTimeStamp, aLayersId); SendNotifyVsync(aVsync, aLayersId);
} }
void VsyncBridgeChild::Close() { void VsyncBridgeChild::Close() {

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

@ -30,7 +30,7 @@ class VsyncBridgeChild final : public PVsyncBridgeChild {
void DeallocPVsyncBridgeChild() override; void DeallocPVsyncBridgeChild() override;
void ProcessingError(Result aCode, const char* aReason) override; void ProcessingError(Result aCode, const char* aReason) override;
void NotifyVsync(TimeStamp aTimeStamp, const layers::LayersId& aLayersId); void NotifyVsync(const VsyncEvent& aVsync, const layers::LayersId& aLayersId);
virtual void HandleFatalError(const char* aMsg) const override; virtual void HandleFatalError(const char* aMsg) const override;
@ -40,7 +40,8 @@ class VsyncBridgeChild final : public PVsyncBridgeChild {
void Open(Endpoint<PVsyncBridgeChild>&& aEndpoint); void Open(Endpoint<PVsyncBridgeChild>&& aEndpoint);
void NotifyVsyncImpl(TimeStamp aTimeStamp, const layers::LayersId& aLayersId); void NotifyVsyncImpl(const VsyncEvent& aVsync,
const layers::LayersId& aLayersId);
bool IsOnVsyncIOThread() const; bool IsOnVsyncIOThread() const;

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

@ -42,8 +42,8 @@ void VsyncBridgeParent::Open(Endpoint<PVsyncBridgeParent>&& aEndpoint) {
} }
mozilla::ipc::IPCResult VsyncBridgeParent::RecvNotifyVsync( mozilla::ipc::IPCResult VsyncBridgeParent::RecvNotifyVsync(
const TimeStamp& aTimeStamp, const LayersId& aLayersId) { const VsyncEvent& aVsync, const LayersId& aLayersId) {
CompositorBridgeParent::NotifyVsync(aTimeStamp, aLayersId); CompositorBridgeParent::NotifyVsync(aVsync, aLayersId);
return IPC_OK(); return IPC_OK();
} }

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

@ -23,7 +23,7 @@ class VsyncBridgeParent final : public PVsyncBridgeParent {
static RefPtr<VsyncBridgeParent> Start( static RefPtr<VsyncBridgeParent> Start(
Endpoint<PVsyncBridgeParent>&& aEndpoint); Endpoint<PVsyncBridgeParent>&& aEndpoint);
mozilla::ipc::IPCResult RecvNotifyVsync(const TimeStamp& vsyncTimeStamp, mozilla::ipc::IPCResult RecvNotifyVsync(const VsyncEvent& aVsync,
const LayersId& aLayersId) override; const LayersId& aLayersId) override;
void ActorDestroy(ActorDestroyReason aWhy) override; void ActorDestroy(ActorDestroyReason aWhy) override;
void DeallocPVsyncBridgeParent() override; void DeallocPVsyncBridgeParent() override;

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

@ -79,39 +79,51 @@ struct LayersId {
}; };
}; };
struct TransactionId { template <typename T>
uint64_t mId; struct BaseTransactionId {
uint64_t mId = 0;
bool IsValid() const { return mId != 0; } bool IsValid() const { return mId != 0; }
MOZ_MUST_USE TransactionId Next() const { return TransactionId{mId + 1}; } MOZ_MUST_USE BaseTransactionId<T> Next() const {
return BaseTransactionId<T>{mId + 1};
}
MOZ_MUST_USE TransactionId Prev() const { return TransactionId{mId - 1}; } MOZ_MUST_USE BaseTransactionId<T> Prev() const {
return BaseTransactionId<T>{mId - 1};
}
int64_t operator-(const TransactionId& aOther) const { int64_t operator-(const BaseTransactionId<T>& aOther) const {
return mId - aOther.mId; return mId - aOther.mId;
} }
// Allow explicit cast to a uint64_t for now // Allow explicit cast to a uint64_t for now
explicit operator uint64_t() const { return mId; } explicit operator uint64_t() const { return mId; }
bool operator<(const TransactionId& aOther) const { return mId < aOther.mId; } bool operator<(const BaseTransactionId<T>& aOther) const {
return mId < aOther.mId;
}
bool operator<=(const TransactionId& aOther) const { bool operator<=(const BaseTransactionId<T>& aOther) const {
return mId <= aOther.mId; return mId <= aOther.mId;
} }
bool operator>(const TransactionId& aOther) const { return mId > aOther.mId; } bool operator>(const BaseTransactionId<T>& aOther) const {
return mId > aOther.mId;
}
bool operator>=(const TransactionId& aOther) const { bool operator>=(const BaseTransactionId<T>& aOther) const {
return mId >= aOther.mId; return mId >= aOther.mId;
} }
bool operator==(const TransactionId& aOther) const { bool operator==(const BaseTransactionId<T>& aOther) const {
return mId == aOther.mId; return mId == aOther.mId;
} }
}; };
class TransactionIdType {};
typedef BaseTransactionId<TransactionIdType> TransactionId;
struct LayersObserverEpoch { struct LayersObserverEpoch {
uint64_t mId; uint64_t mId;

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

@ -10,6 +10,7 @@
#include "nsISupportsImpl.h" #include "nsISupportsImpl.h"
#include "mozilla/layers/LayersTypes.h" #include "mozilla/layers/LayersTypes.h"
#include "mozilla/TimeStamp.h" #include "mozilla/TimeStamp.h"
#include "mozilla/VsyncDispatcher.h"
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
@ -80,6 +81,8 @@ class TransactionIdAllocator {
* Get the start time of the current refresh tick. * Get the start time of the current refresh tick.
*/ */
virtual mozilla::TimeStamp GetTransactionStart() = 0; virtual mozilla::TimeStamp GetTransactionStart() = 0;
virtual VsyncId GetVsyncId() = 0;
}; };
} // namespace layers } // namespace layers

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

@ -681,6 +681,9 @@ void ClientLayerManager::ForwardTransaction(bool aScheduleComposite) {
mLatestTransactionId = mLatestTransactionId =
mTransactionIdAllocator->GetTransactionId(!mIsRepeatTransaction); mTransactionIdAllocator->GetTransactionId(!mIsRepeatTransaction);
TimeStamp refreshStart = mTransactionIdAllocator->GetTransactionStart(); TimeStamp refreshStart = mTransactionIdAllocator->GetTransactionStart();
if (!refreshStart) {
refreshStart = mTransactionStart;
}
if (gfxPrefs::AlwaysPaint() && XRE_IsContentProcess()) { if (gfxPrefs::AlwaysPaint() && XRE_IsContentProcess()) {
mForwarder->SendPaintTime(mLatestTransactionId, mLastPaintTime); mForwarder->SendPaintTime(mLatestTransactionId, mLastPaintTime);
@ -688,10 +691,11 @@ void ClientLayerManager::ForwardTransaction(bool aScheduleComposite) {
// forward this transaction's changeset to our LayerManagerComposite // forward this transaction's changeset to our LayerManagerComposite
bool sent = false; bool sent = false;
bool ok = mForwarder->EndTransaction(mRegionToClear, mLatestTransactionId, bool ok = mForwarder->EndTransaction(
aScheduleComposite, mPaintSequenceNumber, mRegionToClear, mLatestTransactionId, aScheduleComposite,
mIsRepeatTransaction, refreshStart, mPaintSequenceNumber, mIsRepeatTransaction,
mTransactionStart, mURL, &sent); mTransactionIdAllocator->GetVsyncId(), refreshStart, mTransactionStart,
mURL, &sent);
if (ok) { if (ok) {
if (sent) { if (sent) {
mNeedsComposite = false; mNeedsComposite = false;

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

@ -671,11 +671,12 @@ void CompositorBridgeParent::PauseComposition() {
TimeStamp now = TimeStamp::Now(); TimeStamp now = TimeStamp::Now();
if (mCompositor) { if (mCompositor) {
mCompositor->Pause(); mCompositor->Pause();
DidComposite(now, now); DidComposite(VsyncId(), now, now);
} else if (mWrBridge) { } else if (mWrBridge) {
mWrBridge->Pause(); mWrBridge->Pause();
NotifyPipelineRendered(mWrBridge->PipelineId(), NotifyPipelineRendered(mWrBridge->PipelineId(),
mWrBridge->GetCurrentEpoch(), now, now, now); mWrBridge->GetCurrentEpoch(), VsyncId(), now, now,
now);
} }
} }
@ -888,7 +889,7 @@ void CompositorBridgeParent::ScheduleComposition() {
}); });
} }
void CompositorBridgeParent::CompositeToTarget(DrawTarget* aTarget, void CompositorBridgeParent::CompositeToTarget(VsyncId aId, DrawTarget* aTarget,
const gfx::IntRect* aRect) { const gfx::IntRect* aRect) {
AUTO_PROFILER_TRACING("Paint", "Composite"); AUTO_PROFILER_TRACING("Paint", "Composite");
AUTO_PROFILER_LABEL("CompositorBridgeParent::CompositeToTarget", GRAPHICS); AUTO_PROFILER_LABEL("CompositorBridgeParent::CompositeToTarget", GRAPHICS);
@ -899,7 +900,7 @@ void CompositorBridgeParent::CompositeToTarget(DrawTarget* aTarget,
if (!CanComposite()) { if (!CanComposite()) {
TimeStamp end = TimeStamp::Now(); TimeStamp end = TimeStamp::Now();
DidComposite(start, end); DidComposite(aId, start, end);
return; return;
} }
@ -993,7 +994,7 @@ void CompositorBridgeParent::CompositeToTarget(DrawTarget* aTarget,
if (!aTarget) { if (!aTarget) {
TimeStamp end = TimeStamp::Now(); TimeStamp end = TimeStamp::Now();
DidComposite(start, end); DidComposite(aId, start, end);
} }
// We're not really taking advantage of the stored composite-again-time here. // We're not really taking advantage of the stored composite-again-time here.
@ -1246,7 +1247,7 @@ void CompositorBridgeParent::ShadowLayersUpdated(
ScheduleComposition(); ScheduleComposition();
if (mPaused) { if (mPaused) {
TimeStamp now = TimeStamp::Now(); TimeStamp now = TimeStamp::Now();
DidComposite(now, now); DidComposite(VsyncId(), now, now);
} }
} }
mLayerManager->NotifyShadowTreeTransaction(); mLayerManager->NotifyShadowTreeTransaction();
@ -1284,7 +1285,7 @@ bool CompositorBridgeParent::SetTestSampleTime(const LayersId& aId,
CancelCurrentCompositeTask(); CancelCurrentCompositeTask();
// Pretend we composited in case someone is wating for this event. // Pretend we composited in case someone is wating for this event.
TimeStamp now = TimeStamp::Now(); TimeStamp now = TimeStamp::Now();
DidComposite(now, now); DidComposite(VsyncId(), now, now);
} }
} }
@ -1314,7 +1315,7 @@ void CompositorBridgeParent::ApplyAsyncProperties(
CancelCurrentCompositeTask(); CancelCurrentCompositeTask();
// Pretend we composited in case someone is waiting for this event. // Pretend we composited in case someone is waiting for this event.
TimeStamp now = TimeStamp::Now(); TimeStamp now = TimeStamp::Now();
DidComposite(now, now); DidComposite(VsyncId(), now, now);
} }
} }
} }
@ -1572,7 +1573,7 @@ CompositorBridgeParent* CompositorBridgeParent::RemoveCompositor(uint64_t id) {
return retval; return retval;
} }
void CompositorBridgeParent::NotifyVsync(const TimeStamp& aTimeStamp, void CompositorBridgeParent::NotifyVsync(const VsyncEvent& aVsync,
const LayersId& aLayersId) { const LayersId& aLayersId) {
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU); MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
@ -1587,7 +1588,7 @@ void CompositorBridgeParent::NotifyVsync(const TimeStamp& aTimeStamp,
RefPtr<VsyncObserver> obs = cbp->mWidget->GetVsyncObserver(); RefPtr<VsyncObserver> obs = cbp->mWidget->GetVsyncObserver();
if (!obs) return; if (!obs) return;
obs->NotifyVsync(aTimeStamp); obs->NotifyVsync(aVsync);
} }
mozilla::ipc::IPCResult CompositorBridgeParent::RecvNotifyChildCreated( mozilla::ipc::IPCResult CompositorBridgeParent::RecvNotifyChildCreated(
@ -1684,8 +1685,8 @@ mozilla::ipc::IPCResult CompositorBridgeParent::RecvAdoptChild(
GetAnimationStorage(), mWrBridge->GetTextureFactoryIdentifier()); GetAnimationStorage(), mWrBridge->GetTextureFactoryIdentifier());
// Pretend we composited, since parent CompositorBridgeParent was replaced. // Pretend we composited, since parent CompositorBridgeParent was replaced.
TimeStamp now = TimeStamp::Now(); TimeStamp now = TimeStamp::Now();
NotifyPipelineRendered(childWrBridge->PipelineId(), newEpoch, now, now, NotifyPipelineRendered(childWrBridge->PipelineId(), newEpoch, VsyncId(),
now); now, now, now);
} }
if (oldApzUpdater) { if (oldApzUpdater) {
@ -1976,19 +1977,14 @@ CompositorBridgeParent::LayerTreeState::InProcessSharingController() const {
return mParent; return mParent;
} }
void CompositorBridgeParent::DidComposite(LayersId aId, void CompositorBridgeParent::DidComposite(const VsyncId& aId,
TimeStamp& aCompositeStart, TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd) { TimeStamp& aCompositeEnd) {
MOZ_ASSERT(aId == mRootLayerTreeID);
DidComposite(aCompositeStart, aCompositeEnd);
}
void CompositorBridgeParent::DidComposite(TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd) {
if (mWrBridge) { if (mWrBridge) {
MOZ_ASSERT(false); // This should never get called for a WR compositor MOZ_ASSERT(false); // This should never get called for a WR compositor
} else { } else {
NotifyDidComposite(mPendingTransaction, aCompositeStart, aCompositeEnd); NotifyDidComposite(mPendingTransaction, aId, aCompositeStart,
aCompositeEnd);
#if defined(ENABLE_FRAME_LATENCY_LOG) #if defined(ENABLE_FRAME_LATENCY_LOG)
if (mPendingTransaction.IsValid()) { if (mPendingTransaction.IsValid()) {
if (mRefreshStartTime) { if (mRefreshStartTime) {
@ -2017,8 +2013,9 @@ void CompositorBridgeParent::DidComposite(TimeStamp& aCompositeStart,
void CompositorBridgeParent::NotifyPipelineRendered( void CompositorBridgeParent::NotifyPipelineRendered(
const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch,
TimeStamp& aCompositeStart, TimeStamp& aRenderStart, const VsyncId& aCompositeStartId, TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd, wr::RendererStats* aStats) { TimeStamp& aRenderStart, TimeStamp& aCompositeEnd,
wr::RendererStats* aStats) {
if (!mWrBridge || !mAsyncImageManager) { if (!mWrBridge || !mAsyncImageManager) {
return; return;
} }
@ -2033,7 +2030,8 @@ void CompositorBridgeParent::NotifyPipelineRendered(
if (!mPaused) { if (!mPaused) {
TransactionId transactionId = mWrBridge->FlushTransactionIdsForEpoch( TransactionId transactionId = mWrBridge->FlushTransactionIdsForEpoch(
aEpoch, aCompositeStart, aRenderStart, aCompositeEnd, uiController); aEpoch, aCompositeStartId, aCompositeStart, aRenderStart,
aCompositeEnd, uiController);
Unused << SendDidComposite(LayersId{0}, transactionId, aCompositeStart, Unused << SendDidComposite(LayersId{0}, transactionId, aCompositeStart,
aCompositeEnd); aCompositeEnd);
@ -2052,8 +2050,8 @@ void CompositorBridgeParent::NotifyPipelineRendered(
wrBridge->RemoveEpochDataPriorTo(aEpoch); wrBridge->RemoveEpochDataPriorTo(aEpoch);
if (!mPaused) { if (!mPaused) {
TransactionId transactionId = wrBridge->FlushTransactionIdsForEpoch( TransactionId transactionId = wrBridge->FlushTransactionIdsForEpoch(
aEpoch, aCompositeStart, aRenderStart, aCompositeEnd, uiController, aEpoch, aCompositeStartId, aCompositeStart, aRenderStart,
aStats, &stats); aCompositeEnd, uiController, aStats, &stats);
Unused << wrBridge->GetCompositorBridge()->SendDidComposite( Unused << wrBridge->GetCompositorBridge()->SendDidComposite(
wrBridge->GetLayersId(), transactionId, aCompositeStart, wrBridge->GetLayersId(), transactionId, aCompositeStart,
aCompositeEnd); aCompositeEnd);
@ -2071,6 +2069,7 @@ CompositorBridgeParent::GetAsyncImagePipelineManager() const {
} }
void CompositorBridgeParent::NotifyDidComposite(TransactionId aTransactionId, void CompositorBridgeParent::NotifyDidComposite(TransactionId aTransactionId,
VsyncId aId,
TimeStamp& aCompositeStart, TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd) { TimeStamp& aCompositeEnd) {
MOZ_ASSERT( MOZ_ASSERT(
@ -2088,13 +2087,13 @@ void CompositorBridgeParent::NotifyDidComposite(TransactionId aTransactionId,
} }
MonitorAutoLock lock(*sIndirectLayerTreesLock); MonitorAutoLock lock(*sIndirectLayerTreesLock);
ForEachIndirectLayerTree( ForEachIndirectLayerTree([&](LayerTreeState* lts,
[&](LayerTreeState* lts, const LayersId& aLayersId) -> void { const LayersId& aLayersId) -> void {
if (lts->mCrossProcessParent && lts->mParent == this) { if (lts->mCrossProcessParent && lts->mParent == this) {
CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent; CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent;
cpcp->DidCompositeLocked(aLayersId, aCompositeStart, aCompositeEnd); cpcp->DidCompositeLocked(aLayersId, aId, aCompositeStart, aCompositeEnd);
} }
}); });
} }
void CompositorBridgeParent::InvalidateRemoteLayers() { void CompositorBridgeParent::InvalidateRemoteLayers() {

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

@ -41,6 +41,7 @@
#include "nsISupportsImpl.h" #include "nsISupportsImpl.h"
#include "ThreadSafeRefcountingWithMainThreadDestruction.h" #include "ThreadSafeRefcountingWithMainThreadDestruction.h"
#include "mozilla/layers/UiCompositorControllerParent.h" #include "mozilla/layers/UiCompositorControllerParent.h"
#include "mozilla/VsyncDispatcher.h"
class MessageLoop; class MessageLoop;
class nsIWidget; class nsIWidget;
@ -146,9 +147,6 @@ class CompositorBridgeParentBase : public PCompositorBridgeParent,
LayersObserverEpoch aEpoch, LayersObserverEpoch aEpoch,
bool aActive) = 0; bool aActive) = 0;
virtual void DidComposite(LayersId aId, TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd) = 0;
// HostIPCAllocator // HostIPCAllocator
base::ProcessId GetChildProcessId() override; base::ProcessId GetChildProcessId() override;
void NotifyNotUsed(PTextureParent* aTexture, void NotifyNotUsed(PTextureParent* aTexture,
@ -313,6 +311,7 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
void NotifyWebRenderContextPurge(); void NotifyWebRenderContextPurge();
void NotifyPipelineRendered(const wr::PipelineId& aPipelineId, void NotifyPipelineRendered(const wr::PipelineId& aPipelineId,
const wr::Epoch& aEpoch, const wr::Epoch& aEpoch,
const VsyncId& aCompositeStartId,
TimeStamp& aCompositeStart, TimeStamp& aCompositeStart,
TimeStamp& aRenderStart, TimeStamp& aCompositeEnd, TimeStamp& aRenderStart, TimeStamp& aCompositeEnd,
wr::RendererStats* aStats = nullptr); wr::RendererStats* aStats = nullptr);
@ -393,8 +392,7 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
/** /**
* Notify the compositor for the given layer tree that vsync has occurred. * Notify the compositor for the given layer tree that vsync has occurred.
*/ */
static void NotifyVsync(const TimeStamp& aTimeStamp, static void NotifyVsync(const VsyncEvent& aVsync, const LayersId& aLayersId);
const LayersId& aLayersId);
/** /**
* Set aController as the pan/zoom callback for the subtree referred * Set aController as the pan/zoom callback for the subtree referred
@ -595,7 +593,7 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
// CompositorVsyncSchedulerOwner // CompositorVsyncSchedulerOwner
bool IsPendingComposite() override; bool IsPendingComposite() override;
void FinishPendingComposite() override; void FinishPendingComposite() override;
void CompositeToTarget(gfx::DrawTarget* aTarget, void CompositeToTarget(VsyncId aId, gfx::DrawTarget* aTarget,
const gfx::IntRect* aRect = nullptr) override; const gfx::IntRect* aRect = nullptr) override;
bool InitializeAdvancedLayers(const nsTArray<LayersBackend>& aBackendHints, bool InitializeAdvancedLayers(const nsTArray<LayersBackend>& aBackendHints,
@ -628,11 +626,10 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
*/ */
bool CanComposite(); bool CanComposite();
void DidComposite(LayersId aId, TimeStamp& aCompositeStart, void DidComposite(const VsyncId& aId, TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd) override; TimeStamp& aCompositeEnd);
void DidComposite(TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd);
void NotifyDidComposite(TransactionId aTransactionId, void NotifyDidComposite(TransactionId aTransactionId, VsyncId aId,
TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd); TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd);
// The indirect layer tree lock must be held before calling this function. // The indirect layer tree lock must be held before calling this function.

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

@ -48,13 +48,12 @@ CompositorVsyncScheduler::Observer::Observer(CompositorVsyncScheduler* aOwner)
CompositorVsyncScheduler::Observer::~Observer() { MOZ_ASSERT(!mOwner); } CompositorVsyncScheduler::Observer::~Observer() { MOZ_ASSERT(!mOwner); }
bool CompositorVsyncScheduler::Observer::NotifyVsync( bool CompositorVsyncScheduler::Observer::NotifyVsync(const VsyncEvent& aVsync) {
TimeStamp aVsyncTimestamp) {
MutexAutoLock lock(mMutex); MutexAutoLock lock(mMutex);
if (!mOwner) { if (!mOwner) {
return false; return false;
} }
return mOwner->NotifyVsync(aVsyncTimestamp); return mOwner->NotifyVsync(aVsync);
} }
void CompositorVsyncScheduler::Observer::Destroy() { void CompositorVsyncScheduler::Observer::Destroy() {
@ -107,12 +106,13 @@ void CompositorVsyncScheduler::Destroy() {
} }
void CompositorVsyncScheduler::PostCompositeTask( void CompositorVsyncScheduler::PostCompositeTask(
TimeStamp aCompositeTimestamp) { VsyncId aId, TimeStamp aCompositeTimestamp) {
MonitorAutoLock lock(mCurrentCompositeTaskMonitor); MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
if (mCurrentCompositeTask == nullptr && CompositorThreadHolder::Loop()) { if (mCurrentCompositeTask == nullptr && CompositorThreadHolder::Loop()) {
RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod<TimeStamp>( RefPtr<CancelableRunnable> task =
"layers::CompositorVsyncScheduler::Composite", this, NewCancelableRunnableMethod<VsyncId, TimeStamp>(
&CompositorVsyncScheduler::Composite, aCompositeTimestamp); "layers::CompositorVsyncScheduler::Composite", this,
&CompositorVsyncScheduler::Composite, aId, aCompositeTimestamp);
mCurrentCompositeTask = task; mCurrentCompositeTask = task;
ScheduleTask(task.forget()); ScheduleTask(task.forget());
} }
@ -139,7 +139,7 @@ void CompositorVsyncScheduler::ScheduleComposition() {
if (mAsapScheduling) { if (mAsapScheduling) {
// Used only for performance testing purposes, and when recording/replaying // Used only for performance testing purposes, and when recording/replaying
// to ensure that graphics are up to date. // to ensure that graphics are up to date.
PostCompositeTask(TimeStamp::Now()); PostCompositeTask(VsyncId(), TimeStamp::Now());
#ifdef MOZ_WIDGET_ANDROID #ifdef MOZ_WIDGET_ANDROID
} else if (mIsObservingVsync && mCompositeRequestedAt && } else if (mIsObservingVsync && mCompositeRequestedAt &&
(TimeStamp::Now() - mCompositeRequestedAt) >= (TimeStamp::Now() - mCompositeRequestedAt) >=
@ -150,7 +150,7 @@ void CompositorVsyncScheduler::ScheduleComposition() {
// wait for the vsync. Note that this should only ever happen on Fennec // wait for the vsync. Note that this should only ever happen on Fennec
// because there content runs in the same process as the compositor, and so // because there content runs in the same process as the compositor, and so
// content can actually block the main thread in this process. // content can actually block the main thread in this process.
PostCompositeTask(TimeStamp::Now()); PostCompositeTask(VsyncId(), TimeStamp::Now());
#endif #endif
} else { } else {
if (!mCompositeRequestedAt) { if (!mCompositeRequestedAt) {
@ -162,12 +162,12 @@ void CompositorVsyncScheduler::ScheduleComposition() {
// through the main thread of the UI process. It's possible that // through the main thread of the UI process. It's possible that
// we're blocking there waiting on a composite, so schedule an initial // we're blocking there waiting on a composite, so schedule an initial
// one now to get things started. // one now to get things started.
PostCompositeTask(TimeStamp::Now()); PostCompositeTask(VsyncId(), TimeStamp::Now());
} }
} }
} }
bool CompositorVsyncScheduler::NotifyVsync(TimeStamp aVsyncTimestamp) { bool CompositorVsyncScheduler::NotifyVsync(const VsyncEvent& aVsync) {
// Called from the vsync dispatch thread. When in the GPU Process, that's // Called from the vsync dispatch thread. When in the GPU Process, that's
// the same as the compositor thread. // the same as the compositor thread.
MOZ_ASSERT_IF(XRE_IsParentProcess(), MOZ_ASSERT_IF(XRE_IsParentProcess(),
@ -175,8 +175,8 @@ bool CompositorVsyncScheduler::NotifyVsync(TimeStamp aVsyncTimestamp) {
MOZ_ASSERT_IF(XRE_GetProcessType() == GeckoProcessType_GPU, MOZ_ASSERT_IF(XRE_GetProcessType() == GeckoProcessType_GPU,
CompositorThreadHolder::IsInCompositorThread()); CompositorThreadHolder::IsInCompositorThread());
MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(!NS_IsMainThread());
PostCompositeTask(aVsyncTimestamp); PostCompositeTask(aVsync.mId, aVsync.mTime);
PostVRTask(aVsyncTimestamp); PostVRTask(aVsync.mTime);
return true; return true;
} }
@ -190,7 +190,8 @@ void CompositorVsyncScheduler::CancelCurrentCompositeTask() {
} }
} }
void CompositorVsyncScheduler::Composite(TimeStamp aVsyncTimestamp) { void CompositorVsyncScheduler::Composite(VsyncId aId,
TimeStamp aVsyncTimestamp) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
MOZ_ASSERT(mVsyncSchedulerOwner); MOZ_ASSERT(mVsyncSchedulerOwner);
@ -221,7 +222,7 @@ void CompositorVsyncScheduler::Composite(TimeStamp aVsyncTimestamp) {
mLastCompose = aVsyncTimestamp; mLastCompose = aVsyncTimestamp;
// Tell the owner to do a composite // Tell the owner to do a composite
mVsyncSchedulerOwner->CompositeToTarget(nullptr, nullptr); mVsyncSchedulerOwner->CompositeToTarget(aId, nullptr, nullptr);
mVsyncNotificationsSkipped = 0; mVsyncNotificationsSkipped = 0;
@ -257,7 +258,7 @@ void CompositorVsyncScheduler::ForceComposeToTarget(gfx::DrawTarget* aTarget,
mLastCompose = TimeStamp::Now(); mLastCompose = TimeStamp::Now();
MOZ_ASSERT(mVsyncSchedulerOwner); MOZ_ASSERT(mVsyncSchedulerOwner);
mVsyncSchedulerOwner->CompositeToTarget(aTarget, aRect); mVsyncSchedulerOwner->CompositeToTarget(VsyncId(), aTarget, aRect);
} }
bool CompositorVsyncScheduler::NeedsComposite() { bool CompositorVsyncScheduler::NeedsComposite() {

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

@ -48,7 +48,7 @@ class CompositorVsyncScheduler {
* Notify this class of a vsync. This will trigger a composite if one is * Notify this class of a vsync. This will trigger a composite if one is
* needed. This must be called from the vsync dispatch thread. * needed. This must be called from the vsync dispatch thread.
*/ */
bool NotifyVsync(TimeStamp aVsyncTimestamp); bool NotifyVsync(const VsyncEvent& aVsync);
/** /**
* Do cleanup. This must be called on the compositor thread. * Do cleanup. This must be called on the compositor thread.
@ -108,7 +108,7 @@ class CompositorVsyncScheduler {
// Post a task to run Composite() on the compositor thread, if there isn't // 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. // such a task already queued. Can be called from any thread.
void PostCompositeTask(TimeStamp aCompositeTimestamp); void PostCompositeTask(VsyncId aId, TimeStamp aCompositeTimestamp);
// Post a task to run DispatchVREvents() on the VR thread, if there isn't // 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. // such a task already queued. Can be called from any thread.
@ -116,7 +116,7 @@ class CompositorVsyncScheduler {
// This gets run at vsync time and "does" a composite (which really means // This gets run at vsync time and "does" a composite (which really means
// update internal state and call the owner to do the composite). // update internal state and call the owner to do the composite).
void Composite(TimeStamp aVsyncTimestamp); void Composite(VsyncId aId, TimeStamp aVsyncTimestamp);
void ObserveVsync(); void ObserveVsync();
void UnobserveVsync(); void UnobserveVsync();
@ -126,7 +126,7 @@ class CompositorVsyncScheduler {
class Observer final : public VsyncObserver { class Observer final : public VsyncObserver {
public: public:
explicit Observer(CompositorVsyncScheduler* aOwner); explicit Observer(CompositorVsyncScheduler* aOwner);
virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) override; virtual bool NotifyVsync(const VsyncEvent& aVsync) override;
void Destroy(); void Destroy();
private: private:

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

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

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

@ -389,22 +389,18 @@ void CrossProcessCompositorBridgeParent::ShadowLayersUpdated(
static_cast<uint32_t>( static_cast<uint32_t>(
(endTime - aInfo.transactionStart()).ToMilliseconds())); (endTime - aInfo.transactionStart()).ToMilliseconds()));
aLayerTree->SetPendingTransactionId(aInfo.id(), aInfo.refreshStart(), aLayerTree->SetPendingTransactionId(
aInfo.transactionStart(), aInfo.url(), aInfo.id(), aInfo.vsyncId(), aInfo.refreshStart(),
aInfo.fwdTime()); aInfo.transactionStart(), aInfo.url(), aInfo.fwdTime());
}
void CrossProcessCompositorBridgeParent::DidComposite(
LayersId aId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd) {
MonitorAutoLock lock(*sIndirectLayerTreesLock);
DidCompositeLocked(aId, aCompositeStart, aCompositeEnd);
} }
void CrossProcessCompositorBridgeParent::DidCompositeLocked( void CrossProcessCompositorBridgeParent::DidCompositeLocked(
LayersId aId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd) { LayersId aId, const VsyncId& aVsyncId, TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd) {
sIndirectLayerTreesLock->AssertCurrentThreadOwns(); sIndirectLayerTreesLock->AssertCurrentThreadOwns();
if (LayerTransactionParent* layerTree = sIndirectLayerTrees[aId].mLayerTree) { if (LayerTransactionParent* layerTree = sIndirectLayerTrees[aId].mLayerTree) {
TransactionId transactionId = layerTree->FlushTransactionId(aCompositeEnd); TransactionId transactionId =
layerTree->FlushTransactionId(aVsyncId, aCompositeEnd);
if (transactionId.IsValid()) { if (transactionId.IsValid()) {
Unused << SendDidComposite(aId, transactionId, aCompositeStart, Unused << SendDidComposite(aId, transactionId, aCompositeStart,
aCompositeEnd); aCompositeEnd);

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

@ -137,10 +137,8 @@ class CrossProcessCompositorBridgeParent final
// Use DidCompositeLocked if you already hold a lock on // Use DidCompositeLocked if you already hold a lock on
// sIndirectLayerTreesLock; Otherwise use DidComposite, which would request // sIndirectLayerTreesLock; Otherwise use DidComposite, which would request
// the lock automatically. // the lock automatically.
void DidCompositeLocked(LayersId aId, TimeStamp& aCompositeStart, void DidCompositeLocked(LayersId aId, const VsyncId& aVsyncId,
TimeStamp& aCompositeEnd); TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd);
void DidComposite(LayersId aId, TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd) override;
PTextureParent* AllocPTextureParent( PTextureParent* AllocPTextureParent(
const SurfaceDescriptor& aSharedData, const ReadLockDescriptor& aReadLock, const SurfaceDescriptor& aSharedData, const ReadLockDescriptor& aReadLock,

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

@ -39,6 +39,8 @@
#include "mozilla/layers/TextureHost.h" #include "mozilla/layers/TextureHost.h"
#include "mozilla/layers/AsyncCompositionManager.h" #include "mozilla/layers/AsyncCompositionManager.h"
using mozilla::Telemetry::LABELS_CONTENT_FRAME_TIME_REASON;
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
@ -884,12 +886,49 @@ bool LayerTransactionParent::IsSameProcess() const {
} }
TransactionId LayerTransactionParent::FlushTransactionId( TransactionId LayerTransactionParent::FlushTransactionId(
TimeStamp& aCompositeEnd) { const VsyncId& aId, TimeStamp& aCompositeEnd) {
if (mId.IsValid() && mPendingTransaction.IsValid() && !mVsyncRate.IsZero()) { if (mId.IsValid() && mPendingTransaction.IsValid() && !mVsyncRate.IsZero()) {
double latencyMs = (aCompositeEnd - mTxnStartTime).ToMilliseconds(); double latencyMs = (aCompositeEnd - mTxnStartTime).ToMilliseconds();
double latencyNorm = latencyMs / mVsyncRate.ToMilliseconds(); double latencyNorm = latencyMs / mVsyncRate.ToMilliseconds();
int32_t fracLatencyNorm = lround(latencyNorm * 100.0); int32_t fracLatencyNorm = lround(latencyNorm * 100.0);
Telemetry::Accumulate(Telemetry::CONTENT_FRAME_TIME, fracLatencyNorm); Telemetry::Accumulate(Telemetry::CONTENT_FRAME_TIME, fracLatencyNorm);
// Record CONTENT_FRAME_TIME_REASON. See
// WebRenderBridgeParent::FlushTransactionIdsForEpoch for more details.
//
// Note that deseralizing a layers update (RecvUpdate) can delay the receipt
// of the composite vsync message
// (CompositorBridgeParent::CompositeToTarget), since they're using the same
// thread. This can mean that compositing might start significantly late,
// but this code will still detect it as having successfully started on the
// right vsync (which is somewhat correct). We'd now have reduced time left
// in the vsync interval to finish compositing, so the chances of a missed
// frame increases. This is effectively including the RecvUpdate work as
// part of the 'compositing' phase for this metric, but it isn't included in
// COMPOSITE_TIME, and *is* included in CONTENT_FULL_PAINT_TIME.
latencyMs = (aCompositeEnd - mRefreshStartTime).ToMilliseconds();
latencyNorm = latencyMs / mVsyncRate.ToMilliseconds();
fracLatencyNorm = lround(latencyNorm * 100.0);
if (fracLatencyNorm < 200) {
// Success
Telemetry::AccumulateCategorical(
LABELS_CONTENT_FRAME_TIME_REASON::OnTime);
} else {
if (mTxnVsyncId == VsyncId() || aId == VsyncId() || mTxnVsyncId >= aId) {
// Vsync ids are nonsensical, possibly something got trigged from
// outside vsync?
Telemetry::AccumulateCategorical(
LABELS_CONTENT_FRAME_TIME_REASON::NoVsync);
} else if (aId - mTxnVsyncId > 1) {
// Composite started late (and maybe took too long as well)
Telemetry::AccumulateCategorical(
LABELS_CONTENT_FRAME_TIME_REASON::MissedComposite);
} else {
// Composite start on time, but must have taken too long.
Telemetry::AccumulateCategorical(
LABELS_CONTENT_FRAME_TIME_REASON::SlowComposite);
}
}
} }
#if defined(ENABLE_FRAME_LATENCY_LOG) #if defined(ENABLE_FRAME_LATENCY_LOG)

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

@ -72,18 +72,20 @@ class LayerTransactionParent final : public PLayerTransactionParent,
bool IsSameProcess() const override; bool IsSameProcess() const override;
const TransactionId& GetPendingTransactionId() { return mPendingTransaction; } const TransactionId& GetPendingTransactionId() { return mPendingTransaction; }
void SetPendingTransactionId(TransactionId aId, void SetPendingTransactionId(TransactionId aId, const VsyncId& aVsyncId,
const TimeStamp& aRefreshStartTime, const TimeStamp& aRefreshStartTime,
const TimeStamp& aTxnStartTime, const TimeStamp& aTxnStartTime,
const nsCString& aURL, const nsCString& aURL,
const TimeStamp& aFwdTime) { const TimeStamp& aFwdTime) {
mPendingTransaction = aId; mPendingTransaction = aId;
mTxnVsyncId = aVsyncId;
mRefreshStartTime = aRefreshStartTime; mRefreshStartTime = aRefreshStartTime;
mTxnStartTime = aTxnStartTime; mTxnStartTime = aTxnStartTime;
mTxnURL = aURL; mTxnURL = aURL;
mFwdTime = aFwdTime; mFwdTime = aFwdTime;
} }
TransactionId FlushTransactionId(TimeStamp& aCompositeEnd); TransactionId FlushTransactionId(const VsyncId& aId,
TimeStamp& aCompositeEnd);
// CompositableParentManager // CompositableParentManager
void SendAsyncMessage( void SendAsyncMessage(
@ -202,6 +204,7 @@ class LayerTransactionParent final : public PLayerTransactionParent,
TimeDuration mVsyncRate; TimeDuration mVsyncRate;
TransactionId mPendingTransaction; TransactionId mPendingTransaction;
VsyncId mTxnVsyncId;
TimeStamp mRefreshStartTime; TimeStamp mRefreshStartTime;
TimeStamp mTxnStartTime; TimeStamp mTxnStartTime;
TimeStamp mFwdTime; TimeStamp mFwdTime;

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

@ -24,6 +24,7 @@
#include "mozilla/layers/LayersTypes.h" #include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/RefCountedShmem.h" #include "mozilla/layers/RefCountedShmem.h"
#include "mozilla/layers/RepaintRequest.h" #include "mozilla/layers/RepaintRequest.h"
#include "VsyncSource.h"
#include "mozilla/Move.h" #include "mozilla/Move.h"
#include <stdint.h> #include <stdint.h>
@ -38,9 +39,28 @@ template <>
struct ParamTraits<mozilla::layers::LayersId> struct ParamTraits<mozilla::layers::LayersId>
: public PlainOldDataSerializer<mozilla::layers::LayersId> {}; : public PlainOldDataSerializer<mozilla::layers::LayersId> {};
template <typename T>
struct ParamTraits<mozilla::layers::BaseTransactionId<T>>
: public PlainOldDataSerializer<mozilla::layers::BaseTransactionId<T>> {};
template <> template <>
struct ParamTraits<mozilla::layers::TransactionId> struct ParamTraits<mozilla::VsyncId>
: public PlainOldDataSerializer<mozilla::layers::TransactionId> {}; : public PlainOldDataSerializer<mozilla::VsyncId> {};
template <>
struct ParamTraits<mozilla::VsyncEvent> {
typedef mozilla::VsyncEvent paramType;
static void Write(Message* msg, const paramType& param) {
WriteParam(msg, param.mId);
WriteParam(msg, param.mTime);
}
static bool Read(const Message* msg, PickleIterator* iter,
paramType* result) {
return ReadParam(msg, iter, &result->mId) &&
ReadParam(msg, iter, &result->mTime);
}
};
template <> template <>
struct ParamTraits<mozilla::layers::LayersObserverEpoch> struct ParamTraits<mozilla::layers::LayersObserverEpoch>

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

@ -52,6 +52,7 @@ using mozilla::CrossProcessSemaphoreHandle from "mozilla/ipc/CrossProcessSemapho
using struct mozilla::void_t from "ipc/IPCMessageUtils.h"; using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h"; using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h";
using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h"; using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
using mozilla::VsyncId from "mozilla/VsyncDispatcher.h";
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
@ -554,6 +555,7 @@ struct TransactionInfo
bool scheduleComposite; bool scheduleComposite;
uint32_t paintSequenceNumber; uint32_t paintSequenceNumber;
bool isRepeatTransaction; bool isRepeatTransaction;
VsyncId vsyncId;
TimeStamp refreshStart; TimeStamp refreshStart;
TimeStamp transactionStart; TimeStamp transactionStart;
nsCString url; nsCString url;

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

@ -28,6 +28,7 @@ using mozilla::layers::WebRenderScrollData from "mozilla/layers/WebRenderScrollD
using mozilla::layers::FocusTarget from "mozilla/layers/FocusTarget.h"; using mozilla::layers::FocusTarget from "mozilla/layers/FocusTarget.h";
using mozilla::layers::LayersObserverEpoch from "mozilla/layers/LayersTypes.h"; using mozilla::layers::LayersObserverEpoch from "mozilla/layers/LayersTypes.h";
using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h"; using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
using mozilla::VsyncId from "mozilla/VsyncDispatcher.h";
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
@ -48,11 +49,11 @@ parent:
LayoutSize aContentSize, ByteBuf aDL, BuiltDisplayListDescriptor aDLDesc, LayoutSize aContentSize, ByteBuf aDL, BuiltDisplayListDescriptor aDLDesc,
WebRenderScrollData aScrollData, WebRenderScrollData aScrollData,
OpUpdateResource[] aResourceUpdates, RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems, OpUpdateResource[] aResourceUpdates, RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems,
IdNamespace aIdNamespace, bool containsSVGGroup, TimeStamp refreshStartTime, TimeStamp txnStartTime, nsCString txnURL, TimeStamp fwdTime); IdNamespace aIdNamespace, bool containsSVGGroup, VsyncId vsyncId, TimeStamp refreshStartTime, TimeStamp txnStartTime, nsCString txnURL, TimeStamp fwdTime);
async EmptyTransaction(FocusTarget focusTarget, ScrollUpdatesMap scrollUpdates, uint32_t aPaintSequenceNumber, async EmptyTransaction(FocusTarget focusTarget, ScrollUpdatesMap scrollUpdates, uint32_t aPaintSequenceNumber,
WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, TransactionId transactionId, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, TransactionId transactionId,
OpUpdateResource[] aResourceUpdates, RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems, OpUpdateResource[] aResourceUpdates, RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems,
IdNamespace aIdNamespace, TimeStamp refreshStartTime, TimeStamp txnStartTime, nsCString txnURL, TimeStamp fwdTime); IdNamespace aIdNamespace, VsyncId vsyncId, TimeStamp refreshStartTime, TimeStamp txnStartTime, nsCString txnURL, TimeStamp fwdTime);
async SetFocusTarget(FocusTarget focusTarget); async SetFocusTarget(FocusTarget focusTarget);
async UpdateResources(OpUpdateResource[] aResourceUpdates, RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems); async UpdateResources(OpUpdateResource[] aResourceUpdates, RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems);
async ParentCommands(WebRenderParentCommand[] commands); async ParentCommands(WebRenderParentCommand[] commands);

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

@ -528,7 +528,8 @@ void ShadowLayerForwarder::SendPaintTime(TransactionId aId,
bool ShadowLayerForwarder::EndTransaction( bool ShadowLayerForwarder::EndTransaction(
const nsIntRegion& aRegionToClear, TransactionId aId, const nsIntRegion& aRegionToClear, TransactionId aId,
bool aScheduleComposite, uint32_t aPaintSequenceNumber, bool aScheduleComposite, uint32_t aPaintSequenceNumber,
bool aIsRepeatTransaction, const mozilla::TimeStamp& aRefreshStart, bool aIsRepeatTransaction, const mozilla::VsyncId& aVsyncId,
const mozilla::TimeStamp& aRefreshStart,
const mozilla::TimeStamp& aTransactionStart, const nsCString& aURL, const mozilla::TimeStamp& aTransactionStart, const nsCString& aURL,
bool* aSent) { bool* aSent) {
*aSent = false; *aSent = false;
@ -670,6 +671,7 @@ bool ShadowLayerForwarder::EndTransaction(
info.scheduleComposite() = aScheduleComposite; info.scheduleComposite() = aScheduleComposite;
info.paintSequenceNumber() = aPaintSequenceNumber; info.paintSequenceNumber() = aPaintSequenceNumber;
info.isRepeatTransaction() = aIsRepeatTransaction; info.isRepeatTransaction() = aIsRepeatTransaction;
info.vsyncId() = aVsyncId;
info.refreshStart() = aRefreshStart; info.refreshStart() = aRefreshStart;
info.transactionStart() = aTransactionStart; info.transactionStart() = aTransactionStart;
info.url() = aURL; info.url() = aURL;

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

@ -252,6 +252,7 @@ class ShadowLayerForwarder final : public LayersIPCActor,
bool EndTransaction(const nsIntRegion& aRegionToClear, TransactionId aId, bool EndTransaction(const nsIntRegion& aRegionToClear, TransactionId aId,
bool aScheduleComposite, uint32_t aPaintSequenceNumber, bool aScheduleComposite, uint32_t aPaintSequenceNumber,
bool aIsRepeatTransaction, bool aIsRepeatTransaction,
const mozilla::VsyncId& aVsyncId,
const mozilla::TimeStamp& aRefreshStart, const mozilla::TimeStamp& aRefreshStart,
const mozilla::TimeStamp& aTransactionStart, const mozilla::TimeStamp& aTransactionStart,
const nsCString& aURL, bool* aSent); const nsCString& aURL, bool* aSent);

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

@ -105,7 +105,8 @@ void WebRenderBridgeChild::EndTransaction(
const wr::LayoutSize& aContentSize, wr::BuiltDisplayList& aDL, const wr::LayoutSize& aContentSize, wr::BuiltDisplayList& aDL,
wr::IpcResourceUpdateQueue& aResources, const gfx::IntSize& aSize, wr::IpcResourceUpdateQueue& aResources, const gfx::IntSize& aSize,
TransactionId aTransactionId, const WebRenderScrollData& aScrollData, TransactionId aTransactionId, const WebRenderScrollData& aScrollData,
bool aContainsSVGGroup, const mozilla::TimeStamp& aRefreshStartTime, bool aContainsSVGGroup, const mozilla::VsyncId& aVsyncId,
const mozilla::TimeStamp& aRefreshStartTime,
const mozilla::TimeStamp& aTxnStartTime, const nsCString& aTxnURL) { const mozilla::TimeStamp& aTxnStartTime, const nsCString& aTxnURL) {
MOZ_ASSERT(!mDestroyed); MOZ_ASSERT(!mDestroyed);
MOZ_ASSERT(mIsInTransaction); MOZ_ASSERT(mIsInTransaction);
@ -121,11 +122,12 @@ void WebRenderBridgeChild::EndTransaction(
nsTArray<ipc::Shmem> largeShmems; nsTArray<ipc::Shmem> largeShmems;
aResources.Flush(resourceUpdates, smallShmems, largeShmems); aResources.Flush(resourceUpdates, smallShmems, largeShmems);
this->SendSetDisplayList( this->SendSetDisplayList(aSize, mParentCommands, mDestroyedActors,
aSize, mParentCommands, mDestroyedActors, GetFwdTransactionId(), GetFwdTransactionId(), aTransactionId, aContentSize,
aTransactionId, aContentSize, dlData, aDL.dl_desc, aScrollData, dlData, aDL.dl_desc, aScrollData, resourceUpdates,
resourceUpdates, smallShmems, largeShmems, mIdNamespace, smallShmems, largeShmems, mIdNamespace,
aContainsSVGGroup, aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime); aContainsSVGGroup, aVsyncId, aRefreshStartTime,
aTxnStartTime, aTxnURL, fwdTime);
mParentCommands.Clear(); mParentCommands.Clear();
mDestroyedActors.Clear(); mDestroyedActors.Clear();
@ -136,6 +138,7 @@ void WebRenderBridgeChild::EndEmptyTransaction(
const FocusTarget& aFocusTarget, const ScrollUpdatesMap& aUpdates, const FocusTarget& aFocusTarget, const ScrollUpdatesMap& aUpdates,
Maybe<wr::IpcResourceUpdateQueue>& aResources, Maybe<wr::IpcResourceUpdateQueue>& aResources,
uint32_t aPaintSequenceNumber, TransactionId aTransactionId, uint32_t aPaintSequenceNumber, TransactionId aTransactionId,
const mozilla::VsyncId& aVsyncId,
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);
@ -154,8 +157,8 @@ void WebRenderBridgeChild::EndEmptyTransaction(
this->SendEmptyTransaction( this->SendEmptyTransaction(
aFocusTarget, aUpdates, aPaintSequenceNumber, mParentCommands, aFocusTarget, aUpdates, aPaintSequenceNumber, mParentCommands,
mDestroyedActors, GetFwdTransactionId(), aTransactionId, resourceUpdates, mDestroyedActors, GetFwdTransactionId(), aTransactionId, resourceUpdates,
smallShmems, largeShmems, mIdNamespace, aRefreshStartTime, aTxnStartTime, smallShmems, largeShmems, mIdNamespace, aVsyncId, aRefreshStartTime,
aTxnURL, fwdTime); aTxnStartTime, aTxnURL, fwdTime);
mParentCommands.Clear(); mParentCommands.Clear();
mDestroyedActors.Clear(); mDestroyedActors.Clear();
mIsInTransaction = false; mIsInTransaction = false;

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

@ -66,17 +66,21 @@ class WebRenderBridgeChild final : public PWebRenderBridgeChild,
void UpdateResources(wr::IpcResourceUpdateQueue& aResources); void UpdateResources(wr::IpcResourceUpdateQueue& aResources);
void BeginTransaction(); void BeginTransaction();
void EndTransaction( void EndTransaction(const wr::LayoutSize& aContentSize,
const wr::LayoutSize& aContentSize, wr::BuiltDisplayList& dl, wr::BuiltDisplayList& dl,
wr::IpcResourceUpdateQueue& aResources, const gfx::IntSize& aSize, wr::IpcResourceUpdateQueue& aResources,
TransactionId aTransactionId, const WebRenderScrollData& aScrollData, const gfx::IntSize& aSize, TransactionId aTransactionId,
bool aContainsSVGroup, const mozilla::TimeStamp& aRefreshStartTime, const WebRenderScrollData& aScrollData,
const mozilla::TimeStamp& aTxnStartTime, const nsCString& aTxtURL); bool aContainsSVGroup, const mozilla::VsyncId& aVsyncId,
const mozilla::TimeStamp& aRefreshStartTime,
const mozilla::TimeStamp& aTxnStartTime,
const nsCString& aTxtURL);
void EndEmptyTransaction(const FocusTarget& aFocusTarget, void EndEmptyTransaction(const FocusTarget& aFocusTarget,
const ScrollUpdatesMap& aUpdates, const ScrollUpdatesMap& aUpdates,
Maybe<wr::IpcResourceUpdateQueue>& aResources, Maybe<wr::IpcResourceUpdateQueue>& aResources,
uint32_t aPaintSequenceNumber, uint32_t aPaintSequenceNumber,
TransactionId aTransactionId, TransactionId aTransactionId,
const mozilla::VsyncId& aVsyncId,
const mozilla::TimeStamp& aRefreshStartTime, const mozilla::TimeStamp& aRefreshStartTime,
const mozilla::TimeStamp& aTxnStartTime, const mozilla::TimeStamp& aTxnStartTime,
const nsCString& aTxtURL); const nsCString& aTxtURL);

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

@ -35,6 +35,8 @@
#include "mozilla/webrender/RenderThread.h" #include "mozilla/webrender/RenderThread.h"
#include "mozilla/widget/CompositorWidget.h" #include "mozilla/widget/CompositorWidget.h"
using mozilla::Telemetry::LABELS_CONTENT_FRAME_TIME_REASON;
#ifdef MOZ_GECKO_PROFILER #ifdef MOZ_GECKO_PROFILER
#include "ProfilerMarkerPayload.h" #include "ProfilerMarkerPayload.h"
#endif #endif
@ -854,9 +856,9 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
nsTArray<OpUpdateResource>&& aResourceUpdates, nsTArray<OpUpdateResource>&& aResourceUpdates,
nsTArray<RefCountedShmem>&& aSmallShmems, nsTArray<RefCountedShmem>&& aSmallShmems,
nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace, nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace,
const bool& aContainsSVGGroup, const TimeStamp& aRefreshStartTime, const bool& aContainsSVGGroup, const VsyncId& aVsyncId,
const TimeStamp& aTxnStartTime, const nsCString& aTxnURL, const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime,
const TimeStamp& aFwdTime) { const nsCString& aTxnURL, const TimeStamp& aFwdTime) {
if (mDestroyed) { if (mDestroyed) {
for (const auto& op : aToDestroy) { for (const auto& op : aToDestroy) {
DestroyActor(op); DestroyActor(op);
@ -945,7 +947,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
mChildLayersObserverEpoch, true); mChildLayersObserverEpoch, true);
} }
HoldPendingTransactionId(wrEpoch, aTransactionId, aContainsSVGGroup, HoldPendingTransactionId(wrEpoch, aTransactionId, aContainsSVGGroup, aVsyncId,
aRefreshStartTime, aTxnStartTime, aTxnURL, aFwdTime, aRefreshStartTime, aTxnStartTime, aTxnURL, aFwdTime,
mIsFirstPaint); mIsFirstPaint);
mIsFirstPaint = false; mIsFirstPaint = false;
@ -955,7 +957,8 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
// though DisplayList was not pushed to webrender. // though DisplayList was not pushed to webrender.
if (CompositorBridgeParent* cbp = GetRootCompositorBridgeParent()) { if (CompositorBridgeParent* cbp = GetRootCompositorBridgeParent()) {
TimeStamp now = TimeStamp::Now(); TimeStamp now = TimeStamp::Now();
cbp->NotifyPipelineRendered(mPipelineId, wrEpoch, now, now, now); cbp->NotifyPipelineRendered(mPipelineId, wrEpoch, VsyncId(), now, now,
now);
} }
} }
@ -973,8 +976,9 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEmptyTransaction(
nsTArray<OpUpdateResource>&& aResourceUpdates, nsTArray<OpUpdateResource>&& aResourceUpdates,
nsTArray<RefCountedShmem>&& aSmallShmems, nsTArray<RefCountedShmem>&& aSmallShmems,
nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace, nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace,
const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime, const VsyncId& aVsyncId, const TimeStamp& aRefreshStartTime,
const nsCString& aTxnURL, const TimeStamp& aFwdTime) { const TimeStamp& aTxnStartTime, const nsCString& aTxnURL,
const TimeStamp& aFwdTime) {
if (mDestroyed) { if (mDestroyed) {
for (const auto& op : aToDestroy) { for (const auto& op : aToDestroy) {
DestroyActor(op); DestroyActor(op);
@ -1058,8 +1062,8 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEmptyTransaction(
// Only register a value for CONTENT_FRAME_TIME telemetry if we actually drew // Only register a value for CONTENT_FRAME_TIME telemetry if we actually drew
// something. It is for consistency with disabling WebRender. // something. It is for consistency with disabling WebRender.
HoldPendingTransactionId(mWrEpoch, aTransactionId, false, aRefreshStartTime, HoldPendingTransactionId(mWrEpoch, aTransactionId, false, aVsyncId,
aTxnStartTime, aTxnURL, aFwdTime, aRefreshStartTime, aTxnStartTime, aTxnURL, aFwdTime,
/* aIsFirstPaint */ false, /* aIsFirstPaint */ false,
/* aUseForTelemetry */ scheduleComposite); /* aUseForTelemetry */ scheduleComposite);
@ -1075,7 +1079,8 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEmptyTransaction(
MOZ_ASSERT(mPendingTransactionIds.size() == 1); MOZ_ASSERT(mPendingTransactionIds.size() == 1);
if (CompositorBridgeParent* cbp = GetRootCompositorBridgeParent()) { if (CompositorBridgeParent* cbp = GetRootCompositorBridgeParent()) {
TimeStamp now = TimeStamp::Now(); TimeStamp now = TimeStamp::Now();
cbp->NotifyPipelineRendered(mPipelineId, mWrEpoch, now, now, now); cbp->NotifyPipelineRendered(mPipelineId, mWrEpoch, VsyncId(), now, now,
now);
} }
} }
@ -1217,7 +1222,7 @@ void WebRenderBridgeParent::FlushFrameGeneration() {
mCompositorScheduler->CancelCurrentCompositeTask(); mCompositorScheduler->CancelCurrentCompositeTask();
// Update timestamp of scheduler for APZ and animation. // Update timestamp of scheduler for APZ and animation.
mCompositorScheduler->UpdateLastComposeTime(); mCompositorScheduler->UpdateLastComposeTime();
MaybeGenerateFrame(/* aForceGenerateFrame */ true); MaybeGenerateFrame(VsyncId(), /* aForceGenerateFrame */ true);
} }
} }
@ -1642,11 +1647,12 @@ bool WebRenderBridgeParent::SampleAnimations(
void WebRenderBridgeParent::CompositeIfNeeded() { void WebRenderBridgeParent::CompositeIfNeeded() {
if (mSkippedComposite) { if (mSkippedComposite) {
mSkippedComposite = false; mSkippedComposite = false;
CompositeToTarget(nullptr, nullptr); CompositeToTarget(VsyncId(), nullptr, nullptr);
} }
} }
void WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget, void WebRenderBridgeParent::CompositeToTarget(VsyncId aId,
gfx::DrawTarget* aTarget,
const gfx::IntRect* aRect) { const gfx::IntRect* aRect) {
// This function should only get called in the root WRBP // This function should only get called in the root WRBP
MOZ_ASSERT(IsRootWebRenderBridgeParent()); MOZ_ASSERT(IsRootWebRenderBridgeParent());
@ -1677,7 +1683,7 @@ void WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget,
} }
return; return;
} }
MaybeGenerateFrame(/* aForceGenerateFrame */ false); MaybeGenerateFrame(aId, /* aForceGenerateFrame */ false);
} }
TimeDuration WebRenderBridgeParent::GetVsyncInterval() const { TimeDuration WebRenderBridgeParent::GetVsyncInterval() const {
@ -1689,7 +1695,8 @@ TimeDuration WebRenderBridgeParent::GetVsyncInterval() const {
return TimeDuration(); return TimeDuration();
} }
void WebRenderBridgeParent::MaybeGenerateFrame(bool aForceGenerateFrame) { void WebRenderBridgeParent::MaybeGenerateFrame(VsyncId aId,
bool aForceGenerateFrame) {
// This function should only get called in the root WRBP // This function should only get called in the root WRBP
MOZ_ASSERT(IsRootWebRenderBridgeParent()); MOZ_ASSERT(IsRootWebRenderBridgeParent());
@ -1737,7 +1744,7 @@ void WebRenderBridgeParent::MaybeGenerateFrame(bool aForceGenerateFrame) {
SetAPZSampleTime(); SetAPZSampleTime();
wr::RenderThread::Get()->IncPendingFrameCount(mApi->GetId(), start); wr::RenderThread::Get()->IncPendingFrameCount(mApi->GetId(), aId, start);
#if defined(ENABLE_FRAME_LATENCY_LOG) #if defined(ENABLE_FRAME_LATENCY_LOG)
auto startTime = TimeStamp::Now(); auto startTime = TimeStamp::Now();
@ -1751,13 +1758,13 @@ void WebRenderBridgeParent::MaybeGenerateFrame(bool aForceGenerateFrame) {
void WebRenderBridgeParent::HoldPendingTransactionId( void WebRenderBridgeParent::HoldPendingTransactionId(
const wr::Epoch& aWrEpoch, TransactionId aTransactionId, const wr::Epoch& aWrEpoch, TransactionId aTransactionId,
bool aContainsSVGGroup, const TimeStamp& aRefreshStartTime, bool aContainsSVGGroup, const VsyncId& aVsyncId,
const TimeStamp& aTxnStartTime, const nsCString& aTxnURL, const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime,
const TimeStamp& aFwdTime, const bool aIsFirstPaint, const nsCString& aTxnURL, const TimeStamp& aFwdTime,
const bool aUseForTelemetry) { const bool aIsFirstPaint, const bool aUseForTelemetry) {
MOZ_ASSERT(aTransactionId > LastPendingTransactionId()); MOZ_ASSERT(aTransactionId > LastPendingTransactionId());
mPendingTransactionIds.push_back(PendingTransactionId( mPendingTransactionIds.push_back(PendingTransactionId(
aWrEpoch, aTransactionId, aContainsSVGGroup, aRefreshStartTime, aWrEpoch, aTransactionId, aContainsSVGGroup, aVsyncId, aRefreshStartTime,
aTxnStartTime, aTxnURL, aFwdTime, aIsFirstPaint, aUseForTelemetry)); aTxnStartTime, aTxnURL, aFwdTime, aIsFirstPaint, aUseForTelemetry));
} }
@ -1780,10 +1787,10 @@ void WebRenderBridgeParent::NotifySceneBuiltForEpoch(
} }
TransactionId WebRenderBridgeParent::FlushTransactionIdsForEpoch( TransactionId WebRenderBridgeParent::FlushTransactionIdsForEpoch(
const wr::Epoch& aEpoch, const TimeStamp& aCompositeStartTime, const wr::Epoch& aEpoch, const VsyncId& aCompositeStartId,
const TimeStamp& aRenderStartTime, const TimeStamp& aEndTime, const TimeStamp& aCompositeStartTime, const TimeStamp& aRenderStartTime,
UiCompositorControllerParent* aUiController, wr::RendererStats* aStats, const TimeStamp& aEndTime, UiCompositorControllerParent* aUiController,
nsTArray<FrameStats>* aOutputStats) { wr::RendererStats* aStats, nsTArray<FrameStats>* aOutputStats) {
TransactionId id{0}; TransactionId id{0};
while (!mPendingTransactionIds.empty()) { while (!mPendingTransactionIds.empty()) {
const auto& transactionId = mPendingTransactionIds.front(); const auto& transactionId = mPendingTransactionIds.front();
@ -1820,6 +1827,50 @@ TransactionId WebRenderBridgeParent::FlushTransactionIdsForEpoch(
} }
#endif #endif
// Record CONTENT_FRAME_TIME_REASON.
//
// This uses the refresh start time (CONTENT_FRAME_TIME uses the start of
// display list building), since that includes layout/style time, and 200
// should correlate more closely with missing a vsync.
//
// Also of note is that when the root WebRenderBridgeParent decides to
// skip a composite (due to the Renderer being busy), that won't notify
// child WebRenderBridgeParents. That failure will show up as the
// composite starting late (since it did), but it's really a fault of a
// slow composite on the previous frame, not a slow
// CONTENT_FULL_PAINT_TIME. It would be nice to have a separate bucket for
// this category (scene was ready on the next vsync, but we chose not to
// composite), but I can't find a way to locate the right child
// WebRenderBridgeParents from the root. WebRender notifies us of the
// child pipelines contained within a render, after it finishes, but I
// can't see how to query what child pipeline would have been rendered,
// when we choose to not do it.
latencyMs = (aEndTime - transactionId.mRefreshStartTime).ToMilliseconds();
latencyNorm = latencyMs / mVsyncRate.ToMilliseconds();
fracLatencyNorm = lround(latencyNorm * 100.0);
if (fracLatencyNorm < 200) {
// Success
Telemetry::AccumulateCategorical(
LABELS_CONTENT_FRAME_TIME_REASON::OnTime);
} else {
if (transactionId.mVsyncId == VsyncId() ||
aCompositeStartId == VsyncId() ||
transactionId.mVsyncId >= aCompositeStartId) {
// Vsync ids are nonsensical, possibly something got trigged from
// outside vsync?
Telemetry::AccumulateCategorical(
LABELS_CONTENT_FRAME_TIME_REASON::NoVsync);
} else if (aCompositeStartId - transactionId.mVsyncId > 1) {
// Composite started late (and maybe took too long as well)
Telemetry::AccumulateCategorical(
LABELS_CONTENT_FRAME_TIME_REASON::MissedComposite);
} else {
// Composite start on time, but must have taken too long.
Telemetry::AccumulateCategorical(
LABELS_CONTENT_FRAME_TIME_REASON::SlowComposite);
}
}
if (fracLatencyNorm > 200) { if (fracLatencyNorm > 200) {
aOutputStats->AppendElement(FrameStats( aOutputStats->AppendElement(FrameStats(
transactionId.mId, aCompositeStartTime, aRenderStartTime, aEndTime, transactionId.mId, aCompositeStartTime, aRenderStartTime, aEndTime,

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

@ -102,9 +102,9 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
nsTArray<OpUpdateResource>&& aResourceUpdates, nsTArray<OpUpdateResource>&& aResourceUpdates,
nsTArray<RefCountedShmem>&& aSmallShmems, nsTArray<RefCountedShmem>&& aSmallShmems,
nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace, nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace,
const bool& aContainsSVGGroup, const TimeStamp& aRefreshStartTime, const bool& aContainsSVGGroup, const VsyncId& aVsyncId,
const TimeStamp& aTxnStartTime, const nsCString& aTxnURL, const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime,
const TimeStamp& aFwdTime) override; const nsCString& aTxnURL, const TimeStamp& aFwdTime) override;
mozilla::ipc::IPCResult RecvEmptyTransaction( mozilla::ipc::IPCResult RecvEmptyTransaction(
const FocusTarget& aFocusTarget, const ScrollUpdatesMap& aUpdates, const FocusTarget& aFocusTarget, const ScrollUpdatesMap& aUpdates,
const uint32_t& aPaintSequenceNumber, const uint32_t& aPaintSequenceNumber,
@ -114,8 +114,9 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
nsTArray<OpUpdateResource>&& aResourceUpdates, nsTArray<OpUpdateResource>&& aResourceUpdates,
nsTArray<RefCountedShmem>&& aSmallShmems, nsTArray<RefCountedShmem>&& aSmallShmems,
nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace, nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace,
const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime, const VsyncId& aVsyncId, const TimeStamp& aRefreshStartTime,
const nsCString& aTxnURL, const TimeStamp& aFwdTime) override; const TimeStamp& aTxnStartTime, const nsCString& aTxnURL,
const TimeStamp& aFwdTime) override;
mozilla::ipc::IPCResult RecvSetFocusTarget( mozilla::ipc::IPCResult RecvSetFocusTarget(
const FocusTarget& aFocusTarget) override; const FocusTarget& aFocusTarget) override;
mozilla::ipc::IPCResult RecvParentCommands( mozilla::ipc::IPCResult RecvParentCommands(
@ -158,7 +159,7 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
// CompositorVsyncSchedulerOwner // CompositorVsyncSchedulerOwner
bool IsPendingComposite() override { return false; } bool IsPendingComposite() override { return false; }
void FinishPendingComposite() override {} void FinishPendingComposite() override {}
void CompositeToTarget(gfx::DrawTarget* aTarget, void CompositeToTarget(VsyncId aId, gfx::DrawTarget* aTarget,
const gfx::IntRect* aRect = nullptr) override; const gfx::IntRect* aRect = nullptr) override;
TimeDuration GetVsyncInterval() const override; TimeDuration GetVsyncInterval() const override;
@ -174,15 +175,15 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
void HoldPendingTransactionId( void HoldPendingTransactionId(
const wr::Epoch& aWrEpoch, TransactionId aTransactionId, const wr::Epoch& aWrEpoch, TransactionId aTransactionId,
bool aContainsSVGGroup, const TimeStamp& aRefreshStartTime, bool aContainsSVGGroup, const VsyncId& aVsyncId,
const TimeStamp& aTxnStartTime, const nsCString& aTxnURL, const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime,
const TimeStamp& aFwdTime, const bool aIsFirstPaint, const nsCString& aTxnURL, const TimeStamp& aFwdTime,
const bool aUseForTelemetry = true); const bool aIsFirstPaint, const bool aUseForTelemetry = true);
TransactionId LastPendingTransactionId(); TransactionId LastPendingTransactionId();
TransactionId FlushTransactionIdsForEpoch( TransactionId FlushTransactionIdsForEpoch(
const wr::Epoch& aEpoch, const TimeStamp& aCompositeStartTime, const wr::Epoch& aEpoch, const VsyncId& aCompositeStartId,
const TimeStamp& aRenderStartTime, const TimeStamp& aEndTime, const TimeStamp& aCompositeStartTime, const TimeStamp& aRenderStartTime,
UiCompositorControllerParent* aUiController, const TimeStamp& aEndTime, UiCompositorControllerParent* aUiController,
wr::RendererStats* aStats = nullptr, wr::RendererStats* aStats = nullptr,
nsTArray<FrameStats>* aOutputStats = nullptr); nsTArray<FrameStats>* aOutputStats = nullptr);
void NotifySceneBuiltForEpoch(const wr::Epoch& aEpoch, void NotifySceneBuiltForEpoch(const wr::Epoch& aEpoch,
@ -315,18 +316,19 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
void FlushFrameGeneration(); void FlushFrameGeneration();
void FlushFramePresentation(); void FlushFramePresentation();
void MaybeGenerateFrame(bool aForceGenerateFrame); void MaybeGenerateFrame(VsyncId aId, bool aForceGenerateFrame);
private: private:
struct PendingTransactionId { struct PendingTransactionId {
PendingTransactionId(const wr::Epoch& aEpoch, TransactionId aId, PendingTransactionId(const wr::Epoch& aEpoch, TransactionId aId,
bool aContainsSVGGroup, bool aContainsSVGGroup, const VsyncId& aVsyncId,
const TimeStamp& aRefreshStartTime, const TimeStamp& aRefreshStartTime,
const TimeStamp& aTxnStartTime, const TimeStamp& aTxnStartTime,
const nsCString& aTxnURL, const TimeStamp& aFwdTime, const nsCString& aTxnURL, const TimeStamp& aFwdTime,
const bool aIsFirstPaint, const bool aUseForTelemetry) const bool aIsFirstPaint, const bool aUseForTelemetry)
: mEpoch(aEpoch), : mEpoch(aEpoch),
mId(aId), mId(aId),
mVsyncId(aVsyncId),
mRefreshStartTime(aRefreshStartTime), mRefreshStartTime(aRefreshStartTime),
mTxnStartTime(aTxnStartTime), mTxnStartTime(aTxnStartTime),
mTxnURL(aTxnURL), mTxnURL(aTxnURL),
@ -337,6 +339,7 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
mUseForTelemetry(aUseForTelemetry) {} mUseForTelemetry(aUseForTelemetry) {}
wr::Epoch mEpoch; wr::Epoch mEpoch;
TransactionId mId; TransactionId mId;
VsyncId mVsyncId;
TimeStamp mRefreshStartTime; TimeStamp mRefreshStartTime;
TimeStamp mTxnStartTime; TimeStamp mTxnStartTime;
nsCString mTxnURL; nsCString mTxnURL;

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

@ -232,8 +232,9 @@ bool WebRenderLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags) {
WrBridge()->EndEmptyTransaction(mFocusTarget, mPendingScrollUpdates, WrBridge()->EndEmptyTransaction(mFocusTarget, mPendingScrollUpdates,
mAsyncResourceUpdates, mPaintSequenceNumber, mAsyncResourceUpdates, mPaintSequenceNumber,
mLatestTransactionId, refreshStart, mLatestTransactionId,
mTransactionStart, mURL); mTransactionIdAllocator->GetVsyncId(),
refreshStart, mTransactionStart, mURL);
ClearPendingScrollInfoUpdate(); ClearPendingScrollInfoUpdate();
mTransactionStart = TimeStamp(); mTransactionStart = TimeStamp();
@ -363,8 +364,9 @@ void WebRenderLayerManager::EndTransactionWithoutLayer(
AUTO_PROFILER_TRACING("Paint", "ForwardDPTransaction"); AUTO_PROFILER_TRACING("Paint", "ForwardDPTransaction");
WrBridge()->EndTransaction(contentSize, dl, resourceUpdates, WrBridge()->EndTransaction(contentSize, dl, resourceUpdates,
size.ToUnknownSize(), mLatestTransactionId, size.ToUnknownSize(), mLatestTransactionId,
mScrollData, containsSVGGroup, refreshStart, mScrollData, containsSVGGroup,
mTransactionStart, mURL); mTransactionIdAllocator->GetVsyncId(),
refreshStart, mTransactionStart, mURL);
} }
mTransactionStart = TimeStamp(); mTransactionStart = TimeStamp();

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

@ -30,7 +30,7 @@ class TestVsyncObserver : public VsyncObserver {
TestVsyncObserver() TestVsyncObserver()
: mDidGetVsyncNotification(false), mVsyncMonitor("VsyncMonitor") {} : mDidGetVsyncNotification(false), mVsyncMonitor("VsyncMonitor") {}
virtual bool NotifyVsync(TimeStamp aVsyncTimeStamp) override { virtual bool NotifyVsync(const VsyncEvent& aVsync) override {
MonitorAutoLock lock(mVsyncMonitor); MonitorAutoLock lock(mVsyncMonitor);
mDidGetVsyncNotification = true; mDidGetVsyncNotification = true;
mVsyncMonitor.Notify(); mVsyncMonitor.Notify();

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

@ -55,11 +55,14 @@ void VsyncSource::Display::NotifyVsync(TimeStamp aVsyncTimestamp) {
// Called on the vsync thread // Called on the vsync thread
MutexAutoLock lock(mDispatcherLock); MutexAutoLock lock(mDispatcherLock);
mVsyncId = mVsyncId.Next();
VsyncEvent event(mVsyncId, aVsyncTimestamp);
for (size_t i = 0; i < mCompositorVsyncDispatchers.Length(); i++) { for (size_t i = 0; i < mCompositorVsyncDispatchers.Length(); i++) {
mCompositorVsyncDispatchers[i]->NotifyVsync(aVsyncTimestamp); mCompositorVsyncDispatchers[i]->NotifyVsync(event);
} }
mRefreshTimerVsyncDispatcher->NotifyVsync(aVsyncTimestamp); mRefreshTimerVsyncDispatcher->NotifyVsync(event);
} }
TimeDuration VsyncSource::Display::GetVsyncRate() { TimeDuration VsyncSource::Display::GetVsyncRate() {

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

@ -11,12 +11,21 @@
#include "mozilla/Mutex.h" #include "mozilla/Mutex.h"
#include "mozilla/TimeStamp.h" #include "mozilla/TimeStamp.h"
#include "nsISupportsImpl.h" #include "nsISupportsImpl.h"
#include "mozilla/layers/LayersTypes.h"
namespace mozilla { namespace mozilla {
class RefreshTimerVsyncDispatcher; class RefreshTimerVsyncDispatcher;
class CompositorVsyncDispatcher; class CompositorVsyncDispatcher;
class VsyncIdType {};
typedef layers::BaseTransactionId<VsyncIdType> VsyncId;
namespace layout {
class PVsyncChild;
}
namespace gfx { namespace gfx {
class PVsyncBridgeParent;
// Controls how and when to enable/disable vsync. Lives as long as the // Controls how and when to enable/disable vsync. Lives as long as the
// gfxPlatform does on the parent process // gfxPlatform does on the parent process
@ -66,6 +75,7 @@ class VsyncSource {
bool mRefreshTimerNeedsVsync; bool mRefreshTimerNeedsVsync;
nsTArray<RefPtr<CompositorVsyncDispatcher>> mCompositorVsyncDispatchers; nsTArray<RefPtr<CompositorVsyncDispatcher>> mCompositorVsyncDispatchers;
RefPtr<RefreshTimerVsyncDispatcher> mRefreshTimerVsyncDispatcher; RefPtr<RefreshTimerVsyncDispatcher> mRefreshTimerVsyncDispatcher;
VsyncId mVsyncId;
}; };
void AddCompositorVsyncDispatcher( void AddCompositorVsyncDispatcher(
@ -82,6 +92,27 @@ class VsyncSource {
}; };
} // namespace gfx } // namespace gfx
namespace recordreplay {
namespace child {
void NotifyVsyncObserver();
}
} // namespace recordreplay
struct VsyncEvent {
VsyncId mId;
TimeStamp mTime;
private:
VsyncEvent(const VsyncId& aId, const TimeStamp& aTime)
: mId(aId), mTime(aTime) {}
VsyncEvent() {}
friend class gfx::VsyncSource::Display;
friend class gfx::PVsyncBridgeParent;
friend class layout::PVsyncChild;
friend void recordreplay::child::NotifyVsyncObserver();
};
} // namespace mozilla } // namespace mozilla
#endif /* GFX_VSYNCSOURCE_H */ #endif /* GFX_VSYNCSOURCE_H */

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

@ -2557,6 +2557,11 @@ void gfxPlatform::InitCompositorAccelerationPrefs() {
return (env && *env == '1'); return (env && *env == '1');
} }
static bool WebRenderEnvvarDisabled() {
const char* env = PR_GetEnv("MOZ_WEBRENDER");
return (env && *env == '0');
}
// If the "gfx.webrender.all.qualified" pref is true we want to enable // If the "gfx.webrender.all.qualified" pref is true we want to enable
// WebRender for qualifying hardware. The Normandy pref rollout code sets // WebRender for qualifying hardware. The Normandy pref rollout code sets
// default values on rolled out prefs on every startup, but Gfx starts up // default values on rolled out prefs on every startup, but Gfx starts up
@ -2722,7 +2727,7 @@ void gfxPlatform::InitWebRenderConfig() {
// If the user set the pref to force-disable, let's do that. This will // If the user set the pref to force-disable, let's do that. This will
// override all the other enabling prefs (gfx.webrender.enabled, // override all the other enabling prefs (gfx.webrender.enabled,
// gfx.webrender.all, and gfx.webrender.all.qualified). // gfx.webrender.all, and gfx.webrender.all.qualified).
if (gfxPrefs::WebRenderForceDisabled()) { if (gfxPrefs::WebRenderForceDisabled() || WebRenderEnvvarDisabled()) {
featureWebRender.UserDisable( featureWebRender.UserDisable(
"User force-disabled WR", "User force-disabled WR",
NS_LITERAL_CSTRING("FEATURE_FAILURE_USER_FORCE_DISABLED")); NS_LITERAL_CSTRING("FEATURE_FAILURE_USER_FORCE_DISABLED"));

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

@ -244,6 +244,7 @@ void RenderThread::HandleFrame(wr::WindowId aWindowId, bool aRender) {
} }
TimeStamp startTime; TimeStamp startTime;
VsyncId startId;
bool hadSlowFrame; bool hadSlowFrame;
{ // scope lock { // scope lock
@ -253,11 +254,13 @@ void RenderThread::HandleFrame(wr::WindowId aWindowId, bool aRender) {
WindowInfo* info = it->second; WindowInfo* info = it->second;
MOZ_ASSERT(info->mPendingCount > 0); MOZ_ASSERT(info->mPendingCount > 0);
startTime = info->mStartTimes.front(); startTime = info->mStartTimes.front();
startId = info->mStartIds.front();
hadSlowFrame = info->mHadSlowFrame; hadSlowFrame = info->mHadSlowFrame;
info->mHadSlowFrame = false; info->mHadSlowFrame = false;
} }
UpdateAndRender(aWindowId, startTime, aRender, /* aReadbackSize */ Nothing(), UpdateAndRender(aWindowId, startId, startTime, aRender,
/* aReadbackSize */ Nothing(),
/* aReadbackBuffer */ Nothing(), hadSlowFrame); /* aReadbackBuffer */ Nothing(), hadSlowFrame);
FrameRenderingComplete(aWindowId); FrameRenderingComplete(aWindowId);
} }
@ -304,6 +307,7 @@ void RenderThread::RunEvent(wr::WindowId aWindowId,
static void NotifyDidRender(layers::CompositorBridgeParent* aBridge, static void NotifyDidRender(layers::CompositorBridgeParent* aBridge,
RefPtr<WebRenderPipelineInfo> aInfo, RefPtr<WebRenderPipelineInfo> aInfo,
VsyncId aCompositeStartId,
TimeStamp aCompositeStart, TimeStamp aRenderStart, TimeStamp aCompositeStart, TimeStamp aRenderStart,
TimeStamp aEnd, bool aRender, TimeStamp aEnd, bool aRender,
RendererStats aStats) { RendererStats aStats) {
@ -317,13 +321,9 @@ static void NotifyDidRender(layers::CompositorBridgeParent* aBridge,
auto info = aInfo->Raw(); auto info = aInfo->Raw();
for (uintptr_t i = 0; i < info.epochs.length; i++) { for (uintptr_t i = 0; i < info.epochs.length; i++) {
aBridge->NotifyPipelineRendered(info.epochs.data[i].pipeline_id, aBridge->NotifyPipelineRendered(
info.epochs.data[i].epoch, aCompositeStart, info.epochs.data[i].pipeline_id, info.epochs.data[i].epoch,
aRenderStart, aEnd, &aStats); aCompositeStartId, aCompositeStart, aRenderStart, aEnd, &aStats);
}
if (aBridge->GetWrBridge()) {
aBridge->GetWrBridge()->CompositeIfNeeded();
} }
} }
@ -336,6 +336,7 @@ static void NotifyDidStartRender(layers::CompositorBridgeParent* aBridge) {
} }
void RenderThread::UpdateAndRender(wr::WindowId aWindowId, void RenderThread::UpdateAndRender(wr::WindowId aWindowId,
const VsyncId& aStartId,
const TimeStamp& aStartTime, bool aRender, const TimeStamp& aStartTime, bool aRender,
const Maybe<gfx::IntSize>& aReadbackSize, const Maybe<gfx::IntSize>& aReadbackSize,
const Maybe<Range<uint8_t>>& aReadbackBuffer, const Maybe<Range<uint8_t>>& aReadbackBuffer,
@ -374,8 +375,8 @@ void RenderThread::UpdateAndRender(wr::WindowId aWindowId,
layers::CompositorThreadHolder::Loop()->PostTask( layers::CompositorThreadHolder::Loop()->PostTask(
NewRunnableFunction("NotifyDidRenderRunnable", &NotifyDidRender, NewRunnableFunction("NotifyDidRenderRunnable", &NotifyDidRender,
renderer->GetCompositorBridge(), info, aStartTime, renderer->GetCompositorBridge(), info, aStartId,
start, end, aRender, stats)); aStartTime, start, end, aRender, stats));
if (rendered) { if (rendered) {
// Wait for GPU after posting NotifyDidRender, since the wait is not // Wait for GPU after posting NotifyDidRender, since the wait is not
@ -463,6 +464,7 @@ void RenderThread::SetDestroyed(wr::WindowId aWindowId) {
} }
void RenderThread::IncPendingFrameCount(wr::WindowId aWindowId, void RenderThread::IncPendingFrameCount(wr::WindowId aWindowId,
const VsyncId& aStartId,
const TimeStamp& aStartTime) { const TimeStamp& aStartTime) {
MutexAutoLock lock(mFrameCountMapLock); MutexAutoLock lock(mFrameCountMapLock);
auto it = mWindowInfos.find(AsUint64(aWindowId)); auto it = mWindowInfos.find(AsUint64(aWindowId));
@ -472,6 +474,7 @@ void RenderThread::IncPendingFrameCount(wr::WindowId aWindowId,
} }
it->second->mPendingCount++; it->second->mPendingCount++;
it->second->mStartTimes.push(aStartTime); it->second->mStartTimes.push(aStartTime);
it->second->mStartIds.push(aStartId);
} }
void RenderThread::DecPendingFrameCount(wr::WindowId aWindowId) { void RenderThread::DecPendingFrameCount(wr::WindowId aWindowId) {
@ -495,6 +498,7 @@ void RenderThread::DecPendingFrameCount(wr::WindowId aWindowId) {
mozilla::Telemetry::AccumulateTimeDelta(mozilla::Telemetry::COMPOSITE_TIME, mozilla::Telemetry::AccumulateTimeDelta(mozilla::Telemetry::COMPOSITE_TIME,
info->mStartTimes.front()); info->mStartTimes.front());
info->mStartTimes.pop(); info->mStartTimes.pop();
info->mStartIds.pop();
} }
void RenderThread::IncRenderingFrameCount(wr::WindowId aWindowId) { void RenderThread::IncRenderingFrameCount(wr::WindowId aWindowId) {
@ -529,6 +533,7 @@ void RenderThread::FrameRenderingComplete(wr::WindowId aWindowId) {
mozilla::Telemetry::AccumulateTimeDelta(mozilla::Telemetry::COMPOSITE_TIME, mozilla::Telemetry::AccumulateTimeDelta(mozilla::Telemetry::COMPOSITE_TIME,
info->mStartTimes.front()); info->mStartTimes.front());
info->mStartTimes.pop(); info->mStartTimes.pop();
info->mStartIds.pop();
} }
void RenderThread::NotifySlowFrame(wr::WindowId aWindowId) { void RenderThread::NotifySlowFrame(wr::WindowId aWindowId) {

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

@ -21,6 +21,7 @@
#include "mozilla/webrender/WebRenderTypes.h" #include "mozilla/webrender/WebRenderTypes.h"
#include "mozilla/layers/SynchronousTask.h" #include "mozilla/layers/SynchronousTask.h"
#include "GLContext.h" #include "GLContext.h"
#include "mozilla/VsyncDispatcher.h"
#include <list> #include <list>
#include <queue> #include <queue>
@ -168,8 +169,9 @@ class RenderThread final {
void RunEvent(wr::WindowId aWindowId, UniquePtr<RendererEvent> aCallBack); void RunEvent(wr::WindowId aWindowId, UniquePtr<RendererEvent> aCallBack);
/// Can only be called from the render thread. /// Can only be called from the render thread.
void UpdateAndRender(wr::WindowId aWindowId, const TimeStamp& aStartTime, void UpdateAndRender(wr::WindowId aWindowId, const VsyncId& aStartId,
bool aRender, const Maybe<gfx::IntSize>& aReadbackSize, const TimeStamp& aStartTime, bool aRender,
const Maybe<gfx::IntSize>& aReadbackSize,
const Maybe<Range<uint8_t>>& aReadbackBuffer, const Maybe<Range<uint8_t>>& aReadbackBuffer,
bool aHadSlowFrame); bool aHadSlowFrame);
@ -200,7 +202,7 @@ class RenderThread final {
/// Can be called from any thread. /// Can be called from any thread.
bool TooManyPendingFrames(wr::WindowId aWindowId); bool TooManyPendingFrames(wr::WindowId aWindowId);
/// Can be called from any thread. /// Can be called from any thread.
void IncPendingFrameCount(wr::WindowId aWindowId, void IncPendingFrameCount(wr::WindowId aWindowId, const VsyncId& aStartId,
const TimeStamp& aStartTime); const TimeStamp& aStartTime);
/// Can be called from any thread. /// Can be called from any thread.
void DecPendingFrameCount(wr::WindowId aWindowId); void DecPendingFrameCount(wr::WindowId aWindowId);
@ -266,6 +268,7 @@ class RenderThread final {
// One entry in this queue for each pending frame, so the length // One entry in this queue for each pending frame, so the length
// should always equal mPendingCount // should always equal mPendingCount
std::queue<TimeStamp> mStartTimes; std::queue<TimeStamp> mStartTimes;
std::queue<VsyncId> mStartIds;
bool mHadSlowFrame = false; bool mHadSlowFrame = false;
}; };

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

@ -372,8 +372,9 @@ void WebRenderAPI::Readback(const TimeStamp& aStartTime, gfx::IntSize size,
~Readback() { MOZ_COUNT_DTOR(Readback); } ~Readback() { MOZ_COUNT_DTOR(Readback); }
virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override { virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
aRenderThread.UpdateAndRender(aWindowId, mStartTime, /* aRender */ true, aRenderThread.UpdateAndRender(aWindowId, VsyncId(), mStartTime,
Some(mSize), Some(mBuffer), false); /* aRender */ true, Some(mSize),
Some(mBuffer), false);
layers::AutoCompleteTask complete(mTask); layers::AutoCompleteTask complete(mTask);
} }

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

@ -1 +1 @@
74b9312fc0305ecaf06322b0f2f466da96e0a64c 34d58890821d2e606285f21cd6f4befd46c83d47

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

@ -981,6 +981,10 @@ impl<'a> DisplayListFlattener<'a> {
SpecificDisplayItem::PopAllShadows => { SpecificDisplayItem::PopAllShadows => {
self.pop_all_shadows(); self.pop_all_shadows();
} }
SpecificDisplayItem::PushCacheMarker(_marker) => {
}
SpecificDisplayItem::PopCacheMarker => {
}
} }
None None
} }

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

@ -1507,6 +1507,8 @@ impl ToDebugString for SpecificDisplayItem {
SpecificDisplayItem::StickyFrame(..) => String::from("sticky_frame"), SpecificDisplayItem::StickyFrame(..) => String::from("sticky_frame"),
SpecificDisplayItem::Text(..) => String::from("text"), SpecificDisplayItem::Text(..) => String::from("text"),
SpecificDisplayItem::YuvImage(..) => String::from("yuv_image"), SpecificDisplayItem::YuvImage(..) => String::from("yuv_image"),
SpecificDisplayItem::PushCacheMarker(..) => String::from("push_cache_marker"),
SpecificDisplayItem::PopCacheMarker => String::from("pop_cache_marker"),
} }
} }
} }

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

@ -128,6 +128,8 @@ pub enum SpecificDisplayItem {
SetGradientStops, SetGradientStops,
PushShadow(Shadow), PushShadow(Shadow),
PopAllShadows, PopAllShadows,
PushCacheMarker(CacheMarkerDisplayItem),
PopCacheMarker,
} }
/// This is a "complete" version of the DI specifics, /// This is a "complete" version of the DI specifics,
@ -159,6 +161,8 @@ pub enum CompletelySpecificDisplayItem {
SetGradientStops(Vec<GradientStop>), SetGradientStops(Vec<GradientStop>),
PushShadow(Shadow), PushShadow(Shadow),
PopAllShadows, PopAllShadows,
PushCacheMarker(CacheMarkerDisplayItem),
PopCacheMarker,
} }
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
@ -517,6 +521,12 @@ pub struct PushReferenceFrameDisplayListItem {
pub reference_frame: ReferenceFrame, pub reference_frame: ReferenceFrame,
} }
/// Provides a hint to WR that it should try to cache the items
/// within a cache marker context in an off-screen surface.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct CacheMarkerDisplayItem {
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct ReferenceFrame { pub struct ReferenceFrame {
pub transform: Option<PropertyBinding<LayoutTransform>>, pub transform: Option<PropertyBinding<LayoutTransform>>,

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

@ -14,7 +14,7 @@ use std::marker::PhantomData;
use std::ops::Range; use std::ops::Range;
use std::{io, mem, ptr, slice}; use std::{io, mem, ptr, slice};
use time::precise_time_ns; use time::precise_time_ns;
use {AlphaType, BorderDetails, BorderDisplayItem, BorderRadius, BoxShadowClipMode}; use {AlphaType, BorderDetails, BorderDisplayItem, BorderRadius, BoxShadowClipMode, CacheMarkerDisplayItem};
use {BoxShadowDisplayItem, ClipAndScrollInfo, ClipChainId, ClipChainItem, ClipDisplayItem, ClipId}; use {BoxShadowDisplayItem, ClipAndScrollInfo, ClipChainId, ClipChainItem, ClipDisplayItem, ClipId};
use {ColorF, ComplexClipRegion, DisplayItem, ExtendMode, ExternalScrollId, FilterOp}; use {ColorF, ComplexClipRegion, DisplayItem, ExtendMode, ExternalScrollId, FilterOp};
use {FontInstanceKey, GlyphInstance, GlyphOptions, RasterSpace, Gradient, GradientBuilder}; use {FontInstanceKey, GlyphInstance, GlyphOptions, RasterSpace, Gradient, GradientBuilder};
@ -502,6 +502,8 @@ impl Serialize for BuiltDisplayList {
), ),
SpecificDisplayItem::PushShadow(v) => PushShadow(v), SpecificDisplayItem::PushShadow(v) => PushShadow(v),
SpecificDisplayItem::PopAllShadows => PopAllShadows, SpecificDisplayItem::PopAllShadows => PopAllShadows,
SpecificDisplayItem::PushCacheMarker(m) => PushCacheMarker(m),
SpecificDisplayItem::PopCacheMarker => PopCacheMarker,
}, },
clip_and_scroll: display_item.clip_and_scroll, clip_and_scroll: display_item.clip_and_scroll,
info: display_item.info, info: display_item.info,
@ -588,6 +590,8 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
}, },
PushShadow(specific_item) => SpecificDisplayItem::PushShadow(specific_item), PushShadow(specific_item) => SpecificDisplayItem::PushShadow(specific_item),
PopAllShadows => SpecificDisplayItem::PopAllShadows, PopAllShadows => SpecificDisplayItem::PopAllShadows,
PushCacheMarker(marker) => SpecificDisplayItem::PushCacheMarker(marker),
PopCacheMarker => SpecificDisplayItem::PopCacheMarker,
}, },
clip_and_scroll: complete.clip_and_scroll, clip_and_scroll: complete.clip_and_scroll,
info: complete.info, info: complete.info,
@ -1261,6 +1265,19 @@ impl DisplayListBuilder {
id id
} }
pub fn push_cache_marker(&mut self) {
self.push_new_empty_item(&SpecificDisplayItem::PushCacheMarker(CacheMarkerDisplayItem {
// The display item itself is empty for now while we experiment with
// the API. In future it may contain extra information, such as details
// on whether the surface is known to be opaque and/or a background color
// hint that WR should clear the surface to.
}));
}
pub fn pop_cache_marker(&mut self) {
self.push_new_empty_item(&SpecificDisplayItem::PopCacheMarker);
}
pub fn pop_reference_frame(&mut self) { pub fn pop_reference_frame(&mut self) {
self.push_new_empty_item(&SpecificDisplayItem::PopReferenceFrame); self.push_new_empty_item(&SpecificDisplayItem::PopReferenceFrame);
} }

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

@ -1151,6 +1151,11 @@ impl YamlFrameWriter {
yaml_node(&mut v, "previously-applied-offset", Yaml::Array(applied)); yaml_node(&mut v, "previously-applied-offset", Yaml::Array(applied));
} }
PopCacheMarker => return,
PushCacheMarker(_) => {
str_node(&mut v, "type", "cache-marker");
}
PopStackingContext => return, PopStackingContext => return,
PopReferenceFrame => return, PopReferenceFrame => return,
SetGradientStops => panic!("dummy item yielded?"), SetGradientStops => panic!("dummy item yielded?"),

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

@ -460,14 +460,18 @@ TraceLoggerEventPayload* TraceLoggerThreadState::getOrCreateEventPayload(
nextDictionaryId++; nextDictionaryId++;
} }
uint32_t textId = nextTextId; // Look for a free entry, as some textId's may
// already be taken from previous profiling sessions.
while (textIdPayloads.has(nextTextId)) {
nextTextId++;
}
auto* payload = js_new<TraceLoggerEventPayload>(textId, dictId); auto* payload = js_new<TraceLoggerEventPayload>(nextTextId, dictId);
if (!payload) { if (!payload) {
return nullptr; return nullptr;
} }
if (!textIdPayloads.putNew(textId, payload)) { if (!textIdPayloads.putNew(nextTextId, payload)) {
js_delete(payload); js_delete(payload);
return nullptr; return nullptr;
} }
@ -976,33 +980,72 @@ void TraceLoggerThread::log(uint32_t id) {
entry.textId = id; entry.textId = id;
} }
void TraceLoggerThreadState::clear() { bool TraceLoggerThreadState::remapDictionaryEntries(
LockGuard<Mutex> guard(lock); mozilla::Vector<UniqueChars, 0, SystemAllocPolicy>* newDictionary,
for (TraceLoggerThread* logger : threadLoggers) { uint32_t* newNextDictionaryId) {
logger->clear(); MOZ_ASSERT(newNextDictionaryId != nullptr && newDictionary != nullptr);
}
typedef HashMap<uint32_t, uint32_t, DefaultHasher<uint32_t>,
SystemAllocPolicy>
DictionaryMap;
DictionaryMap dictionaryMap;
// Clear all payloads that are not currently used. There may be some events // Clear all payloads that are not currently used. There may be some events
// that still hold a pointer to a payload. Restarting the profiler may add // that still hold a pointer to a payload. Restarting the profiler may reuse
// this event to the new events array and so we need to maintain it's // the exact same event as a previous session if it's still alive so we need
// existence. // to maintain it's existence.
for (TextIdToPayloadMap::Enum e(textIdPayloads); !e.empty(); e.popFront()) { for (TextIdToPayloadMap::Enum e(textIdPayloads); !e.empty(); e.popFront()) {
if (e.front().value()->uses() == 0) { if (e.front().value()->uses() == 0) {
js_delete(e.front().value()); js_delete(e.front().value());
e.removeFront(); e.removeFront();
} else {
TraceLoggerEventPayload* payload = e.front().value();
uint32_t dictId = payload->dictionaryId();
if (dictionaryMap.has(dictId)) {
DictionaryMap::Ptr mapPointer = dictionaryMap.lookup(dictId);
MOZ_ASSERT(mapPointer);
payload->setDictionaryId(mapPointer->value());
} else {
if (!newDictionary->append(std::move(dictionaryData[dictId]))) {
return false;
}
payload->setDictionaryId(*newNextDictionaryId);
if (!dictionaryMap.putNew(dictId, *newNextDictionaryId)) {
return false;
}
(*newNextDictionaryId)++;
}
} }
} }
// Clear and free any data used for the string dictionary. return true;
for (auto range = dictionaryData.all(); !range.empty(); range.popFront()) { }
range.front().reset();
void TraceLoggerThreadState::clear() {
LockGuard<Mutex> guard(lock);
uint32_t newNextDictionaryId = 0;
mozilla::Vector<UniqueChars, 0, SystemAllocPolicy> newDictionary;
if (remapDictionaryEntries(&newDictionary, &newNextDictionaryId)) {
// Clear and free any data used for the string dictionary.
for (auto range = dictionaryData.all(); !range.empty(); range.popFront()) {
range.front().reset();
}
dictionaryData.clearAndFree();
dictionaryData = std::move(newDictionary);
payloadDictionary.clearAndCompact();
nextTextId = TraceLogger_Last;
nextDictionaryId = newNextDictionaryId;
} }
dictionaryData.clearAndFree(); for (TraceLoggerThread* logger : threadLoggers) {
payloadDictionary.clearAndCompact(); logger->clear();
}
nextTextId = TraceLogger_Last;
nextDictionaryId = 0;
} }
void TraceLoggerThread::clear() { void TraceLoggerThread::clear() {

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

@ -200,6 +200,7 @@ class TraceLoggerEventPayload {
mozilla::Maybe<uint32_t> column() { return col_; } mozilla::Maybe<uint32_t> column() { return col_; }
uint32_t textId() { return textId_; } uint32_t textId() { return textId_; }
uint32_t dictionaryId() { return dictionaryId_; } uint32_t dictionaryId() { return dictionaryId_; }
void setDictionaryId(uint32_t dictId) { dictionaryId_ = dictId; }
uint32_t uses() { return uses_; } uint32_t uses() { return uses_; }
// Payloads may have their use count change at any time, *except* the count // Payloads may have their use count change at any time, *except* the count
@ -426,6 +427,9 @@ class TraceLoggerThreadState {
void enableFrontendLogging(); void enableFrontendLogging();
void clear(); void clear();
bool remapDictionaryEntries(
mozilla::Vector<UniqueChars, 0, SystemAllocPolicy>* newDictionary,
uint32_t* newNextDictionaryId);
TraceLoggerThread* forCurrentThread(JSContext* cx); TraceLoggerThread* forCurrentThread(JSContext* cx);
void destroyLogger(TraceLoggerThread* logger); void destroyLogger(TraceLoggerThread* logger);

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

@ -285,10 +285,10 @@ class RefreshDriverTimer {
*/ */
void Tick() { void Tick() {
TimeStamp now = TimeStamp::Now(); TimeStamp now = TimeStamp::Now();
Tick(now); Tick(VsyncId(), now);
} }
void TickRefreshDrivers(TimeStamp aNow, void TickRefreshDrivers(VsyncId aId, TimeStamp aNow,
nsTArray<RefPtr<nsRefreshDriver>>& aDrivers) { nsTArray<RefPtr<nsRefreshDriver>>& aDrivers) {
if (aDrivers.IsEmpty()) { if (aDrivers.IsEmpty()) {
return; return;
@ -301,14 +301,14 @@ class RefreshDriverTimer {
continue; continue;
} }
TickDriver(driver, aNow); TickDriver(driver, aId, aNow);
} }
} }
/* /*
* Tick the refresh drivers based on the given timestamp. * Tick the refresh drivers based on the given timestamp.
*/ */
void Tick(TimeStamp now) { void Tick(VsyncId aId, TimeStamp now) {
ScheduleNextTick(now); ScheduleNextTick(now);
mLastFireTime = now; mLastFireTime = now;
@ -317,14 +317,14 @@ class RefreshDriverTimer {
// RD is short for RefreshDriver // RD is short for RefreshDriver
AUTO_PROFILER_TRACING("Paint", "RefreshDriverTick"); AUTO_PROFILER_TRACING("Paint", "RefreshDriverTick");
TickRefreshDrivers(now, mContentRefreshDrivers); TickRefreshDrivers(aId, now, mContentRefreshDrivers);
TickRefreshDrivers(now, mRootRefreshDrivers); TickRefreshDrivers(aId, now, mRootRefreshDrivers);
LOG("[%p] done.", this); LOG("[%p] done.", this);
} }
static void TickDriver(nsRefreshDriver* driver, TimeStamp now) { static void TickDriver(nsRefreshDriver* driver, VsyncId aId, TimeStamp now) {
driver->Tick(now); driver->Tick(aId, now);
} }
TimeStamp mLastFireTime; TimeStamp mLastFireTime;
@ -462,11 +462,12 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
public nsIRunnablePriority { public nsIRunnablePriority {
public: public:
ParentProcessVsyncNotifier(RefreshDriverVsyncObserver* aObserver, ParentProcessVsyncNotifier(RefreshDriverVsyncObserver* aObserver,
TimeStamp aVsyncTimestamp) VsyncId aId, TimeStamp aVsyncTimestamp)
: Runnable( : Runnable(
"VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::" "VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::"
"ParentProcessVsyncNotifier"), "ParentProcessVsyncNotifier"),
mObserver(aObserver), mObserver(aObserver),
mId(aId),
mVsyncTimestamp(aVsyncTimestamp) {} mVsyncTimestamp(aVsyncTimestamp) {}
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
@ -483,7 +484,7 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
} }
sHighPriorityEnabled = sHighPriorityPrefValue; sHighPriorityEnabled = sHighPriorityPrefValue;
mObserver->TickRefreshDriver(mVsyncTimestamp); mObserver->TickRefreshDriver(mId, mVsyncTimestamp);
return NS_OK; return NS_OK;
} }
@ -497,11 +498,12 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
private: private:
~ParentProcessVsyncNotifier() {} ~ParentProcessVsyncNotifier() {}
RefPtr<RefreshDriverVsyncObserver> mObserver; RefPtr<RefreshDriverVsyncObserver> mObserver;
VsyncId mId;
TimeStamp mVsyncTimestamp; TimeStamp mVsyncTimestamp;
static mozilla::Atomic<bool> sHighPriorityEnabled; static mozilla::Atomic<bool> sHighPriorityEnabled;
}; };
bool NotifyVsync(TimeStamp aVsyncTimestamp) override { bool NotifyVsync(const VsyncEvent& aVsync) override {
// IMPORTANT: All paths through this method MUST hold a strong ref on // IMPORTANT: All paths through this method MUST hold a strong ref on
// |this| for the duration of the TickRefreshDriver callback. // |this| for the duration of the TickRefreshDriver callback.
@ -512,7 +514,8 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
// if the main thread is blocked for long periods of time // if the main thread is blocked for long periods of time
{ // scope lock { // scope lock
MonitorAutoLock lock(mRefreshTickLock); MonitorAutoLock lock(mRefreshTickLock);
mRecentVsync = aVsyncTimestamp; mRecentVsync = aVsync.mTime;
mRecentVsyncId = aVsync.mId;
if (!mProcessedVsync) { if (!mProcessedVsync) {
return true; return true;
} }
@ -520,11 +523,12 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
} }
nsCOMPtr<nsIRunnable> vsyncEvent = nsCOMPtr<nsIRunnable> vsyncEvent =
new ParentProcessVsyncNotifier(this, aVsyncTimestamp); new ParentProcessVsyncNotifier(this, aVsync.mId, aVsync.mTime);
NS_DispatchToMainThread(vsyncEvent); NS_DispatchToMainThread(vsyncEvent);
} else { } else {
mRecentVsync = aVsyncTimestamp; mRecentVsync = aVsync.mTime;
if (!mBlockUntil.IsNull() && mBlockUntil > aVsyncTimestamp) { mRecentVsyncId = aVsync.mId;
if (!mBlockUntil.IsNull() && mBlockUntil > aVsync.mTime) {
if (mProcessedVsync) { if (mProcessedVsync) {
// Re-post vsync update as a normal priority runnable. This way // Re-post vsync update as a normal priority runnable. This way
// runnables already in normal priority queue get processed. // runnables already in normal priority queue get processed.
@ -539,7 +543,7 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
} }
RefPtr<RefreshDriverVsyncObserver> kungFuDeathGrip(this); RefPtr<RefreshDriverVsyncObserver> kungFuDeathGrip(this);
TickRefreshDriver(aVsyncTimestamp); TickRefreshDriver(aVsync.mId, aVsync.mTime);
} }
return true; return true;
@ -561,7 +565,7 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
mRecentVsync > mLastProcessedTickInChildProcess) { mRecentVsync > mLastProcessedTickInChildProcess) {
// mBlockUntil is for high priority vsync notifications only. // mBlockUntil is for high priority vsync notifications only.
mBlockUntil = TimeStamp(); mBlockUntil = TimeStamp();
TickRefreshDriver(mRecentVsync); TickRefreshDriver(mRecentVsyncId, mRecentVsync);
} }
mProcessedVsync = true; mProcessedVsync = true;
@ -615,7 +619,7 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
} }
} }
void TickRefreshDriver(TimeStamp aVsyncTimestamp) { void TickRefreshDriver(VsyncId aId, TimeStamp aVsyncTimestamp) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
RecordTelemetryProbes(aVsyncTimestamp); RecordTelemetryProbes(aVsyncTimestamp);
@ -639,7 +643,7 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
// before use. // before use.
if (mVsyncRefreshDriverTimer) { if (mVsyncRefreshDriverTimer) {
RefPtr<VsyncRefreshDriverTimer> timer = mVsyncRefreshDriverTimer; RefPtr<VsyncRefreshDriverTimer> timer = mVsyncRefreshDriverTimer;
timer->RunRefreshDrivers(aVsyncTimestamp); timer->RunRefreshDrivers(aId, aVsyncTimestamp);
// Note: mVsyncRefreshDriverTimer might be null now. // Note: mVsyncRefreshDriverTimer might be null now.
} }
@ -655,6 +659,7 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
VsyncRefreshDriverTimer* mVsyncRefreshDriverTimer; VsyncRefreshDriverTimer* mVsyncRefreshDriverTimer;
Monitor mRefreshTickLock; Monitor mRefreshTickLock;
TimeStamp mRecentVsync; TimeStamp mRecentVsync;
VsyncId mRecentVsyncId;
TimeStamp mLastChildTick; TimeStamp mLastChildTick;
TimeStamp mLastProcessedTickInChildProcess; TimeStamp mLastProcessedTickInChildProcess;
TimeStamp mBlockUntil; TimeStamp mBlockUntil;
@ -717,7 +722,9 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
// RefreshDriverVsyncObserver. // RefreshDriverVsyncObserver.
} }
void RunRefreshDrivers(TimeStamp aTimeStamp) { Tick(aTimeStamp); } void RunRefreshDrivers(VsyncId aId, TimeStamp aTimeStamp) {
Tick(aId, aTimeStamp);
}
RefPtr<RefreshDriverVsyncObserver> mVsyncObserver; RefPtr<RefreshDriverVsyncObserver> mVsyncObserver;
// Used for parent process. // Used for parent process.
@ -871,7 +878,7 @@ class InactiveRefreshDriverTimer final
if (index < drivers.Length() && if (index < drivers.Length() &&
!drivers[index]->IsTestControllingRefreshesEnabled()) { !drivers[index]->IsTestControllingRefreshesEnabled()) {
TickDriver(drivers[index], now); TickDriver(drivers[index], VsyncId(), now);
} }
mNextDriverIndex++; mNextDriverIndex++;
@ -1364,9 +1371,9 @@ void nsRefreshDriver::DoTick() {
"Shouldn't have a JSContext on the stack"); "Shouldn't have a JSContext on the stack");
if (mTestControllingRefreshes) { if (mTestControllingRefreshes) {
Tick(mMostRecentRefresh); Tick(VsyncId(), mMostRecentRefresh);
} else { } else {
Tick(TimeStamp::Now()); Tick(VsyncId(), TimeStamp::Now());
} }
} }
@ -1608,7 +1615,7 @@ void nsRefreshDriver::CancelIdleRunnable(nsIRunnable* aRunnable) {
} }
} }
void nsRefreshDriver::Tick(TimeStamp aNowTime) { void nsRefreshDriver::Tick(VsyncId aId, TimeStamp aNowTime) {
MOZ_ASSERT(!nsContentUtils::GetCurrentJSContext(), MOZ_ASSERT(!nsContentUtils::GetCurrentJSContext(),
"Shouldn't have a JSContext on the stack"); "Shouldn't have a JSContext on the stack");
@ -1675,6 +1682,7 @@ void nsRefreshDriver::Tick(TimeStamp aNowTime) {
AutoRestore<TimeStamp> restoreTickStart(mTickStart); AutoRestore<TimeStamp> restoreTickStart(mTickStart);
mTickStart = TimeStamp::Now(); mTickStart = TimeStamp::Now();
mTickVsyncId = aId;
gfxPlatform::GetPlatform()->SchedulePaintIfDeviceReset(); gfxPlatform::GetPlatform()->SchedulePaintIfDeviceReset();
@ -2052,6 +2060,8 @@ void nsRefreshDriver::ResetInitialTransactionId(
mozilla::TimeStamp nsRefreshDriver::GetTransactionStart() { return mTickStart; } mozilla::TimeStamp nsRefreshDriver::GetTransactionStart() { return mTickStart; }
VsyncId nsRefreshDriver::GetVsyncId() { return mTickVsyncId; }
void nsRefreshDriver::NotifyTransactionCompleted( void nsRefreshDriver::NotifyTransactionCompleted(
mozilla::layers::TransactionId aTransactionId) { mozilla::layers::TransactionId aTransactionId) {
if (aTransactionId > mCompletedTransaction) { if (aTransactionId > mCompletedTransaction) {

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

@ -25,6 +25,7 @@
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/layers/TransactionIdAllocator.h" #include "mozilla/layers/TransactionIdAllocator.h"
#include "mozilla/VsyncDispatcher.h"
class nsPresContext; class nsPresContext;
class nsIPresShell; class nsIPresShell;
@ -361,6 +362,7 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
void ClearPendingTransactions() override; void ClearPendingTransactions() override;
void ResetInitialTransactionId(TransactionId aTransactionId) override; void ResetInitialTransactionId(TransactionId aTransactionId) override;
mozilla::TimeStamp GetTransactionStart() override; mozilla::TimeStamp GetTransactionStart() override;
mozilla::VsyncId GetVsyncId() override;
bool IsWaitingForPaint(mozilla::TimeStamp aTime); bool IsWaitingForPaint(mozilla::TimeStamp aTime);
@ -414,7 +416,7 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
void DispatchAnimationEvents(); void DispatchAnimationEvents();
void RunFrameRequestCallbacks(mozilla::TimeStamp aNowTime); void RunFrameRequestCallbacks(mozilla::TimeStamp aNowTime);
void UpdateIntersectionObservations(); void UpdateIntersectionObservations();
void Tick(mozilla::TimeStamp aNowTime); void Tick(mozilla::VsyncId aId, mozilla::TimeStamp aNowTime);
enum EnsureTimerStartedFlags { enum EnsureTimerStartedFlags {
eNone = 0, eNone = 0,
@ -507,6 +509,7 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
uint64_t mWarningThreshold; uint64_t mWarningThreshold;
mozilla::TimeStamp mMostRecentRefresh; mozilla::TimeStamp mMostRecentRefresh;
mozilla::TimeStamp mTickStart; mozilla::TimeStamp mTickStart;
mozilla::VsyncId mTickVsyncId;
mozilla::TimeStamp mNextThrottledFrameRequestTick; mozilla::TimeStamp mNextThrottledFrameRequestTick;
mozilla::TimeStamp mNextRecomputeVisibilityTick; mozilla::TimeStamp mNextRecomputeVisibilityTick;

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

@ -7,6 +7,7 @@ include protocol PBackground;
include "mozilla/layers/LayersMessageUtils.h"; include "mozilla/layers/LayersMessageUtils.h";
using class mozilla::TimeStamp from "mozilla/TimeStamp.h"; using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
using mozilla::VsyncEvent from "mozilla/VsyncDispatcher.h";
namespace mozilla { namespace mozilla {
namespace layout { namespace layout {
@ -22,7 +23,7 @@ async protocol PVsync
child: child:
// Send vsync event from chrome to content process. // Send vsync event from chrome to content process.
prio(high) async Notify(TimeStamp aVsyncTimestamp) compress; prio(high) async Notify(VsyncEvent aVsync) compress;
// Send the vsync rate to the content process. // Send the vsync rate to the content process.
async VsyncRate(float aVsyncRate); async VsyncRate(float aVsyncRate);

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

@ -51,8 +51,7 @@ void VsyncChild::ActorDestroy(ActorDestroyReason aActorDestroyReason) {
} }
} }
mozilla::ipc::IPCResult VsyncChild::RecvNotify( mozilla::ipc::IPCResult VsyncChild::RecvNotify(const VsyncEvent& aVsync) {
const TimeStamp& aVsyncTimestamp) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mIsShutdown); MOZ_ASSERT(!mIsShutdown);
@ -63,7 +62,7 @@ mozilla::ipc::IPCResult VsyncChild::RecvNotify(
return IPC_OK(); return IPC_OK();
} }
mObserver->NotifyVsync(aVsyncTimestamp); mObserver->NotifyVsync(aVsync);
} }
return IPC_OK(); return IPC_OK();
} }

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

@ -52,8 +52,7 @@ class VsyncChild final : public PVsyncChild {
VsyncChild(); VsyncChild();
virtual ~VsyncChild(); virtual ~VsyncChild();
virtual mozilla::ipc::IPCResult RecvNotify( virtual mozilla::ipc::IPCResult RecvNotify(const VsyncEvent& aVsync) override;
const TimeStamp& aVsyncTimestamp) override;
virtual mozilla::ipc::IPCResult RecvVsyncRate( virtual mozilla::ipc::IPCResult RecvVsyncRate(
const float& aVsyncRate) override; const float& aVsyncRate) override;
virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override; virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override;

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

@ -42,18 +42,18 @@ VsyncParent::~VsyncParent() {
// VsyncParent is always released on the background thread. // VsyncParent is always released on the background thread.
} }
bool VsyncParent::NotifyVsync(TimeStamp aTimeStamp) { bool VsyncParent::NotifyVsync(const VsyncEvent& aVsync) {
// Called on hardware vsync thread. We should post to current ipc thread. // Called on hardware vsync thread. We should post to current ipc thread.
MOZ_ASSERT(!IsOnBackgroundThread()); MOZ_ASSERT(!IsOnBackgroundThread());
nsCOMPtr<nsIRunnable> vsyncEvent = NewRunnableMethod<TimeStamp>( nsCOMPtr<nsIRunnable> vsyncEvent = NewRunnableMethod<VsyncEvent>(
"layout::VsyncParent::DispatchVsyncEvent", this, "layout::VsyncParent::DispatchVsyncEvent", this,
&VsyncParent::DispatchVsyncEvent, aTimeStamp); &VsyncParent::DispatchVsyncEvent, aVsync);
MOZ_ALWAYS_SUCCEEDS( MOZ_ALWAYS_SUCCEEDS(
mBackgroundThread->Dispatch(vsyncEvent, NS_DISPATCH_NORMAL)); mBackgroundThread->Dispatch(vsyncEvent, NS_DISPATCH_NORMAL));
return true; return true;
} }
void VsyncParent::DispatchVsyncEvent(TimeStamp aTimeStamp) { void VsyncParent::DispatchVsyncEvent(const VsyncEvent& aVsync) {
AssertIsOnBackgroundThread(); AssertIsOnBackgroundThread();
// If we call NotifyVsync() when we handle ActorDestroy() message, we might // If we call NotifyVsync() when we handle ActorDestroy() message, we might
@ -62,7 +62,7 @@ void VsyncParent::DispatchVsyncEvent(TimeStamp aTimeStamp) {
// NotifyVsync(). We use mObservingVsync and mDestroyed flags to skip this // NotifyVsync(). We use mObservingVsync and mDestroyed flags to skip this
// notification. // notification.
if (mObservingVsync && !mDestroyed) { if (mObservingVsync && !mDestroyed) {
Unused << SendNotify(aTimeStamp); Unused << SendNotify(aVsync);
} }
} }

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

@ -34,14 +34,14 @@ class VsyncParent final : public PVsyncParent, public VsyncObserver {
VsyncParent(); VsyncParent();
virtual ~VsyncParent(); virtual ~VsyncParent();
virtual bool NotifyVsync(TimeStamp aTimeStamp) override; virtual bool NotifyVsync(const VsyncEvent& aVsync) override;
virtual mozilla::ipc::IPCResult RecvRequestVsyncRate() override; virtual mozilla::ipc::IPCResult RecvRequestVsyncRate() override;
virtual mozilla::ipc::IPCResult RecvObserve() override; virtual mozilla::ipc::IPCResult RecvObserve() override;
virtual mozilla::ipc::IPCResult RecvUnobserve() override; virtual mozilla::ipc::IPCResult RecvUnobserve() override;
virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override; virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override;
void DispatchVsyncEvent(TimeStamp aTimeStamp); void DispatchVsyncEvent(const VsyncEvent& aVsync);
bool mObservingVsync; bool mObservingVsync;
bool mDestroyed; bool mDestroyed;

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

@ -0,0 +1,27 @@
/*
* Autogenerated by the Meson build system.
* Do not edit, your changes will be lost.
*/
#pragma once
#define ARCH_AARCH64 0
#define ARCH_ARM 0
#define ARCH_X86 0
#define ARCH_X86_32 0
#define ARCH_X86_64 0
#define CONFIG_10BPC 1
#define CONFIG_8BPC 1
#define HAVE_ASM 0
#define HAVE_POSIX_MEMALIGN 1
#define HAVE_UNISTD_H 1

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

@ -33,6 +33,9 @@ elif CONFIG['CPU_ARCH'] == 'arm':
elif CONFIG['CPU_ARCH'] == 'aarch64': elif CONFIG['CPU_ARCH'] == 'aarch64':
LOCAL_INCLUDES += ['/media/libdav1d/config/aarch64/'] LOCAL_INCLUDES += ['/media/libdav1d/config/aarch64/']
EXPORTS.dav1d += ['config/aarch64/config.h'] EXPORTS.dav1d += ['config/aarch64/config.h']
else:
LOCAL_INCLUDES += ['/media/libdav1d/config/other/']
EXPORTS.dav1d += ['config/other/config.h']
EXPORTS.dav1d += [ EXPORTS.dav1d += [
'version.h', 'version.h',

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

@ -573,12 +573,6 @@ VCMEncodedFrame* VCMJitterBuffer::ExtractAndSetDecode(uint32_t timestamp) {
if ((*frame).IsSessionComplete()) if ((*frame).IsSessionComplete())
UpdateAveragePacketsPerFrame(frame->NumPackets()); UpdateAveragePacketsPerFrame(frame->NumPackets());
if (frame->Length() == 0) {
// Normally only if MakeDecodable() on an incomplete frame threw it all away
ReleaseFrame(frame);
return NULL;
}
return frame; return frame;
} }

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

@ -57,7 +57,7 @@ public class WifiScanner extends BroadcastReceiver {
/* ------- */ /* ------- */
public WifiScanner(Context c) { public WifiScanner(Context c) {
mContext = c; mContext = c.getApplicationContext();
} }
private boolean isWifiEnabled() { private boolean isWifiEnabled() {

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

@ -5,6 +5,7 @@ job-defaults:
virtualization: virtualization:
by-test-platform: by-test-platform:
windows10-64-qr/.*: virtual-with-gpu windows10-64-qr/.*: virtual-with-gpu
windows10-64/.*: virtual-with-gpu
default: virtual default: virtual
allow-software-gl-layers: false allow-software-gl-layers: false
mozharness: mozharness:

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

@ -955,6 +955,11 @@ def enable_webrender(config, tests):
if test.get('webrender'): if test.get('webrender'):
test['mozharness'].setdefault('extra-options', [])\ test['mozharness'].setdefault('extra-options', [])\
.append("--enable-webrender") .append("--enable-webrender")
# Explicitly disable WebRender on non-WR AWSY, since that job runs on
# virtual-with-gpu and thus is considered qualified hardware.
elif test['suite'] == 'awsy':
test['mozharness'].setdefault('extra-options', [])\
.append("--disable-webrender")
yield test yield test

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

@ -51,6 +51,12 @@ class AWSY(TestingMixin, MercurialScript, TooltoolMixin, CodeCoverageMixin):
"default": False, "default": False,
"help": "Tries to enable the WebRender compositor.", "help": "Tries to enable the WebRender compositor.",
}], }],
[["--disable-webrender"],
{"action": "store_true",
"dest": "disable_webrender",
"default": False,
"help": "Force-disables the WebRender compositor.",
}],
[["--base"], [["--base"],
{"action": "store_true", {"action": "store_true",
"dest": "test_about_blank", "dest": "test_about_blank",
@ -232,6 +238,11 @@ class AWSY(TestingMixin, MercurialScript, TooltoolMixin, CodeCoverageMixin):
env['MOZ_WEBRENDER'] = '1' env['MOZ_WEBRENDER'] = '1'
env['MOZ_ACCELERATED'] = '1' env['MOZ_ACCELERATED'] = '1'
# Allow explicitly disabling webrender, so that we don't run WR on non-QR
# test platforms just because they run on qualified hardware.
if self.config['disable_webrender']:
env['MOZ_WEBRENDER'] = '0'
env['MOZ_UPLOAD_DIR'] = dirs['abs_blob_upload_dir'] env['MOZ_UPLOAD_DIR'] = dirs['abs_blob_upload_dir']
if not os.path.isdir(env['MOZ_UPLOAD_DIR']): if not os.path.isdir(env['MOZ_UPLOAD_DIR']):
self.mkdir_p(env['MOZ_UPLOAD_DIR']) self.mkdir_p(env['MOZ_UPLOAD_DIR'])

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

@ -140,10 +140,13 @@ button > .button-box {
.study-name { .study-name {
font-weight: bold; font-weight: bold;
margin-bottom: 0.3em;
white-space: pre; white-space: pre;
} }
.study-header {
margin-bottom: .3em;
}
.study-header > * { .study-header > * {
margin-right: 5px; margin-right: 5px;
} }
@ -153,7 +156,13 @@ button > .button-box {
} }
.study-description code { .study-description code {
font: italic 1.0rem 'Fira Mono', 'mono', 'monospace'; background-color: var(--grey-20);
border-radius: 3px;
box-sizing: border-box;
color: var(--in-content-text-color);
font-size: 85%;
font-family: 'Fira Mono', 'mono', monospace;
padding: .2em .4em;
} }
.study-actions { .study-actions {

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

@ -13211,6 +13211,15 @@
"n_buckets": 50, "n_buckets": 50,
"description": "The time, in percentage of a vsync interval, spent from beginning a paint in the content process until that frame is presented in the compositor by WebRender, excluding time spent uploading any content" "description": "The time, in percentage of a vsync interval, spent from beginning a paint in the content process until that frame is presented in the compositor by WebRender, excluding time spent uploading any content"
}, },
"CONTENT_FRAME_TIME_REASON": {
"record_in_processes": ["main", "gpu"],
"alert_emails": ["gfx-telemetry-alerts@mozilla.com", "mwoodrow@mozilla.com"],
"bug_numbers": [1510853],
"expires_in_version": "73",
"kind": "categorical",
"description": "The reason that CONTENT_FRAME_TIME recorded a slow (>200) result, if any.",
"labels": ["OnTime", "NoVsync", "MissedComposite", "SlowComposite"]
},
"CONTENT_LARGE_PAINT_PHASE_WEIGHT": { "CONTENT_LARGE_PAINT_PHASE_WEIGHT": {
"record_in_processes": ["main", "content"], "record_in_processes": ["main", "content"],
"alert_emails": ["gfx-telemetry-alerts@mozilla.com", "mwoodrow@mozilla.com"], "alert_emails": ["gfx-telemetry-alerts@mozilla.com", "mwoodrow@mozilla.com"],

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

@ -414,9 +414,12 @@ void SetVsyncObserver(VsyncObserver* aObserver) {
gVsyncObserver = aObserver; gVsyncObserver = aObserver;
} }
static void NotifyVsyncObserver() { void NotifyVsyncObserver() {
if (gVsyncObserver) { if (gVsyncObserver) {
gVsyncObserver->NotifyVsync(TimeStamp::Now()); static VsyncId vsyncId;
vsyncId = vsyncId.Next();
VsyncEvent event(vsyncId, TimeStamp::Now());
gVsyncObserver->NotifyVsync(event);
} }
} }

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

@ -27,14 +27,13 @@ CompositorVsyncDispatcher::~CompositorVsyncDispatcher() {
// nsBaseWidget // nsBaseWidget
} }
void CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp) { void CompositorVsyncDispatcher::NotifyVsync(const VsyncEvent& aVsync) {
// In vsync thread // In vsync thread
layers::CompositorBridgeParent::PostInsertVsyncProfilerMarker( layers::CompositorBridgeParent::PostInsertVsyncProfilerMarker(aVsync.mTime);
aVsyncTimestamp);
MutexAutoLock lock(mCompositorObserverLock); MutexAutoLock lock(mCompositorObserverLock);
if (mCompositorVsyncObserver) { if (mCompositorVsyncObserver) {
mCompositorVsyncObserver->NotifyVsync(aVsyncTimestamp); mCompositorVsyncObserver->NotifyVsync(aVsync);
} }
} }
@ -101,15 +100,15 @@ RefreshTimerVsyncDispatcher::~RefreshTimerVsyncDispatcher() {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
} }
void RefreshTimerVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp) { void RefreshTimerVsyncDispatcher::NotifyVsync(const VsyncEvent& aVsync) {
MutexAutoLock lock(mRefreshTimersLock); MutexAutoLock lock(mRefreshTimersLock);
for (size_t i = 0; i < mChildRefreshTimers.Length(); i++) { for (size_t i = 0; i < mChildRefreshTimers.Length(); i++) {
mChildRefreshTimers[i]->NotifyVsync(aVsyncTimestamp); mChildRefreshTimers[i]->NotifyVsync(aVsync);
} }
if (mParentRefreshTimer) { if (mParentRefreshTimer) {
mParentRefreshTimer->NotifyVsync(aVsyncTimestamp); mParentRefreshTimer->NotifyVsync(aVsync);
} }
} }

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

@ -11,6 +11,7 @@
#include "nsISupportsImpl.h" #include "nsISupportsImpl.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "VsyncSource.h"
namespace mozilla { namespace mozilla {
@ -23,7 +24,7 @@ class VsyncObserver {
// thread from VsyncSource. But it might also be called on PVsync ipc thread // thread from VsyncSource. But it might also be called on PVsync ipc thread
// if this notification is cross process. Thus all observer should check the // if this notification is cross process. Thus all observer should check the
// thread model before handling the real task. // thread model before handling the real task.
virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) = 0; virtual bool NotifyVsync(const VsyncEvent& aVsync) = 0;
protected: protected:
VsyncObserver() {} VsyncObserver() {}
@ -49,7 +50,7 @@ class CompositorVsyncDispatcher final {
CompositorVsyncDispatcher(); CompositorVsyncDispatcher();
// Called on the vsync thread when a hardware vsync occurs // Called on the vsync thread when a hardware vsync occurs
void NotifyVsync(TimeStamp aVsyncTimestamp); void NotifyVsync(const VsyncEvent& aVsync);
// Compositor vsync observers must be added/removed on the compositor thread // Compositor vsync observers must be added/removed on the compositor thread
void SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver); void SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
@ -72,7 +73,7 @@ class RefreshTimerVsyncDispatcher final {
RefreshTimerVsyncDispatcher(); RefreshTimerVsyncDispatcher();
// Please check CompositorVsyncDispatcher::NotifyVsync(). // Please check CompositorVsyncDispatcher::NotifyVsync().
void NotifyVsync(TimeStamp aVsyncTimestamp); void NotifyVsync(const VsyncEvent& aVsync);
// Set chrome process's RefreshTimer to this dispatcher. // Set chrome process's RefreshTimer to this dispatcher.
// This function can be called from any thread. // This function can be called from any thread.