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");
item.className = "urlbarView-row";
item.setAttribute("resultIndex", resultIndex);
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");
content.className = "urlbarView-row-inner";
item.appendChild(content);
let actionIcon = this._createElement("span");
actionIcon.className = "urlbarView-action-icon";
content.appendChild(actionIcon);
let typeIcon = this._createElement("span");
typeIcon.className = "urlbarView-type-icon";
content.appendChild(typeIcon);
let favicon = this._createElement("img");
favicon.className = "urlbarView-favicon";

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

@ -68,7 +68,7 @@
color: var(--autocomplete-popup-highlight-color);
}
.urlbarView-action-icon,
.urlbarView-type-icon,
.urlbarView-favicon {
display: inline-block;
vertical-align: middle;
@ -82,7 +82,11 @@
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);
}

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

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

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

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

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

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

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

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

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

@ -30,7 +30,7 @@ class VsyncBridgeChild final : public PVsyncBridgeChild {
void DeallocPVsyncBridgeChild() 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;
@ -40,7 +40,8 @@ class VsyncBridgeChild final : public PVsyncBridgeChild {
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;

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

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

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

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

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

@ -79,39 +79,51 @@ struct LayersId {
};
};
struct TransactionId {
uint64_t mId;
template <typename T>
struct BaseTransactionId {
uint64_t 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;
}
// Allow explicit cast to a uint64_t for now
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;
}
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;
}
bool operator==(const TransactionId& aOther) const {
bool operator==(const BaseTransactionId<T>& aOther) const {
return mId == aOther.mId;
}
};
class TransactionIdType {};
typedef BaseTransactionId<TransactionIdType> TransactionId;
struct LayersObserverEpoch {
uint64_t mId;

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

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

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

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

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

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

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

@ -41,6 +41,7 @@
#include "nsISupportsImpl.h"
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
#include "mozilla/layers/UiCompositorControllerParent.h"
#include "mozilla/VsyncDispatcher.h"
class MessageLoop;
class nsIWidget;
@ -146,9 +147,6 @@ class CompositorBridgeParentBase : public PCompositorBridgeParent,
LayersObserverEpoch aEpoch,
bool aActive) = 0;
virtual void DidComposite(LayersId aId, TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd) = 0;
// HostIPCAllocator
base::ProcessId GetChildProcessId() override;
void NotifyNotUsed(PTextureParent* aTexture,
@ -313,6 +311,7 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
void NotifyWebRenderContextPurge();
void NotifyPipelineRendered(const wr::PipelineId& aPipelineId,
const wr::Epoch& aEpoch,
const VsyncId& aCompositeStartId,
TimeStamp& aCompositeStart,
TimeStamp& aRenderStart, TimeStamp& aCompositeEnd,
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.
*/
static void NotifyVsync(const TimeStamp& aTimeStamp,
const LayersId& aLayersId);
static void NotifyVsync(const VsyncEvent& aVsync, const LayersId& aLayersId);
/**
* Set aController as the pan/zoom callback for the subtree referred
@ -595,7 +593,7 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
// CompositorVsyncSchedulerOwner
bool IsPendingComposite() override;
void FinishPendingComposite() override;
void CompositeToTarget(gfx::DrawTarget* aTarget,
void CompositeToTarget(VsyncId aId, gfx::DrawTarget* aTarget,
const gfx::IntRect* aRect = nullptr) override;
bool InitializeAdvancedLayers(const nsTArray<LayersBackend>& aBackendHints,
@ -628,11 +626,10 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
*/
bool CanComposite();
void DidComposite(LayersId aId, TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd) override;
void DidComposite(TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd);
void DidComposite(const VsyncId& aId, TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd);
void NotifyDidComposite(TransactionId aTransactionId,
void NotifyDidComposite(TransactionId aTransactionId, VsyncId aId,
TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd);
// 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); }
bool CompositorVsyncScheduler::Observer::NotifyVsync(
TimeStamp aVsyncTimestamp) {
bool CompositorVsyncScheduler::Observer::NotifyVsync(const VsyncEvent& aVsync) {
MutexAutoLock lock(mMutex);
if (!mOwner) {
return false;
}
return mOwner->NotifyVsync(aVsyncTimestamp);
return mOwner->NotifyVsync(aVsync);
}
void CompositorVsyncScheduler::Observer::Destroy() {
@ -107,12 +106,13 @@ void CompositorVsyncScheduler::Destroy() {
}
void CompositorVsyncScheduler::PostCompositeTask(
TimeStamp aCompositeTimestamp) {
VsyncId aId, TimeStamp aCompositeTimestamp) {
MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
if (mCurrentCompositeTask == nullptr && CompositorThreadHolder::Loop()) {
RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod<TimeStamp>(
"layers::CompositorVsyncScheduler::Composite", this,
&CompositorVsyncScheduler::Composite, aCompositeTimestamp);
RefPtr<CancelableRunnable> task =
NewCancelableRunnableMethod<VsyncId, TimeStamp>(
"layers::CompositorVsyncScheduler::Composite", this,
&CompositorVsyncScheduler::Composite, aId, aCompositeTimestamp);
mCurrentCompositeTask = task;
ScheduleTask(task.forget());
}
@ -139,7 +139,7 @@ void CompositorVsyncScheduler::ScheduleComposition() {
if (mAsapScheduling) {
// Used only for performance testing purposes, and when recording/replaying
// to ensure that graphics are up to date.
PostCompositeTask(TimeStamp::Now());
PostCompositeTask(VsyncId(), TimeStamp::Now());
#ifdef MOZ_WIDGET_ANDROID
} else if (mIsObservingVsync && mCompositeRequestedAt &&
(TimeStamp::Now() - mCompositeRequestedAt) >=
@ -150,7 +150,7 @@ void CompositorVsyncScheduler::ScheduleComposition() {
// 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
// content can actually block the main thread in this process.
PostCompositeTask(TimeStamp::Now());
PostCompositeTask(VsyncId(), TimeStamp::Now());
#endif
} else {
if (!mCompositeRequestedAt) {
@ -162,12 +162,12 @@ void CompositorVsyncScheduler::ScheduleComposition() {
// through the main thread of the UI process. It's possible that
// we're blocking there waiting on a composite, so schedule an initial
// one now to get things started.
PostCompositeTask(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
// the same as the compositor thread.
MOZ_ASSERT_IF(XRE_IsParentProcess(),
@ -175,8 +175,8 @@ bool CompositorVsyncScheduler::NotifyVsync(TimeStamp aVsyncTimestamp) {
MOZ_ASSERT_IF(XRE_GetProcessType() == GeckoProcessType_GPU,
CompositorThreadHolder::IsInCompositorThread());
MOZ_ASSERT(!NS_IsMainThread());
PostCompositeTask(aVsyncTimestamp);
PostVRTask(aVsyncTimestamp);
PostCompositeTask(aVsync.mId, aVsync.mTime);
PostVRTask(aVsync.mTime);
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(mVsyncSchedulerOwner);
@ -221,7 +222,7 @@ void CompositorVsyncScheduler::Composite(TimeStamp aVsyncTimestamp) {
mLastCompose = aVsyncTimestamp;
// Tell the owner to do a composite
mVsyncSchedulerOwner->CompositeToTarget(nullptr, nullptr);
mVsyncSchedulerOwner->CompositeToTarget(aId, nullptr, nullptr);
mVsyncNotificationsSkipped = 0;
@ -257,7 +258,7 @@ void CompositorVsyncScheduler::ForceComposeToTarget(gfx::DrawTarget* aTarget,
mLastCompose = TimeStamp::Now();
MOZ_ASSERT(mVsyncSchedulerOwner);
mVsyncSchedulerOwner->CompositeToTarget(aTarget, aRect);
mVsyncSchedulerOwner->CompositeToTarget(VsyncId(), aTarget, aRect);
}
bool CompositorVsyncScheduler::NeedsComposite() {

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

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

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

@ -7,6 +7,8 @@
#ifndef mozilla_layers_CompositorVsyncSchedulerOwner_h
#define mozilla_layers_CompositorVsyncSchedulerOwner_h
#include "mozilla/VsyncDispatcher.h"
namespace mozilla {
namespace gfx {
@ -19,7 +21,7 @@ class CompositorVsyncSchedulerOwner {
public:
virtual bool IsPendingComposite() = 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;
virtual TimeDuration GetVsyncInterval() const = 0;
};

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

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

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

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

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

@ -39,6 +39,8 @@
#include "mozilla/layers/TextureHost.h"
#include "mozilla/layers/AsyncCompositionManager.h"
using mozilla::Telemetry::LABELS_CONTENT_FRAME_TIME_REASON;
namespace mozilla {
namespace layers {
@ -884,12 +886,49 @@ bool LayerTransactionParent::IsSameProcess() const {
}
TransactionId LayerTransactionParent::FlushTransactionId(
TimeStamp& aCompositeEnd) {
const VsyncId& aId, TimeStamp& aCompositeEnd) {
if (mId.IsValid() && mPendingTransaction.IsValid() && !mVsyncRate.IsZero()) {
double latencyMs = (aCompositeEnd - mTxnStartTime).ToMilliseconds();
double latencyNorm = latencyMs / mVsyncRate.ToMilliseconds();
int32_t fracLatencyNorm = lround(latencyNorm * 100.0);
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)

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

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

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

@ -24,6 +24,7 @@
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/RefCountedShmem.h"
#include "mozilla/layers/RepaintRequest.h"
#include "VsyncSource.h"
#include "mozilla/Move.h"
#include <stdint.h>
@ -38,9 +39,28 @@ template <>
struct ParamTraits<mozilla::layers::LayersId>
: public PlainOldDataSerializer<mozilla::layers::LayersId> {};
template <typename T>
struct ParamTraits<mozilla::layers::BaseTransactionId<T>>
: public PlainOldDataSerializer<mozilla::layers::BaseTransactionId<T>> {};
template <>
struct ParamTraits<mozilla::layers::TransactionId>
: public PlainOldDataSerializer<mozilla::layers::TransactionId> {};
struct ParamTraits<mozilla::VsyncId>
: 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 <>
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 mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h";
using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
using mozilla::VsyncId from "mozilla/VsyncDispatcher.h";
namespace mozilla {
namespace layers {
@ -554,6 +555,7 @@ struct TransactionInfo
bool scheduleComposite;
uint32_t paintSequenceNumber;
bool isRepeatTransaction;
VsyncId vsyncId;
TimeStamp refreshStart;
TimeStamp transactionStart;
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::LayersObserverEpoch from "mozilla/layers/LayersTypes.h";
using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
using mozilla::VsyncId from "mozilla/VsyncDispatcher.h";
namespace mozilla {
namespace layers {
@ -48,11 +49,11 @@ parent:
LayoutSize aContentSize, ByteBuf aDL, BuiltDisplayListDescriptor aDLDesc,
WebRenderScrollData aScrollData,
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,
WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, TransactionId transactionId,
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 UpdateResources(OpUpdateResource[] aResourceUpdates, RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems);
async ParentCommands(WebRenderParentCommand[] commands);

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

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

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

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

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

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

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

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

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

@ -35,6 +35,8 @@
#include "mozilla/webrender/RenderThread.h"
#include "mozilla/widget/CompositorWidget.h"
using mozilla::Telemetry::LABELS_CONTENT_FRAME_TIME_REASON;
#ifdef MOZ_GECKO_PROFILER
#include "ProfilerMarkerPayload.h"
#endif
@ -854,9 +856,9 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
nsTArray<OpUpdateResource>&& aResourceUpdates,
nsTArray<RefCountedShmem>&& aSmallShmems,
nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace,
const bool& aContainsSVGGroup, const TimeStamp& aRefreshStartTime,
const TimeStamp& aTxnStartTime, const nsCString& aTxnURL,
const TimeStamp& aFwdTime) {
const bool& aContainsSVGGroup, const VsyncId& aVsyncId,
const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime,
const nsCString& aTxnURL, const TimeStamp& aFwdTime) {
if (mDestroyed) {
for (const auto& op : aToDestroy) {
DestroyActor(op);
@ -945,7 +947,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
mChildLayersObserverEpoch, true);
}
HoldPendingTransactionId(wrEpoch, aTransactionId, aContainsSVGGroup,
HoldPendingTransactionId(wrEpoch, aTransactionId, aContainsSVGGroup, aVsyncId,
aRefreshStartTime, aTxnStartTime, aTxnURL, aFwdTime,
mIsFirstPaint);
mIsFirstPaint = false;
@ -955,7 +957,8 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
// though DisplayList was not pushed to webrender.
if (CompositorBridgeParent* cbp = GetRootCompositorBridgeParent()) {
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<RefCountedShmem>&& aSmallShmems,
nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace,
const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime,
const nsCString& aTxnURL, const TimeStamp& aFwdTime) {
const VsyncId& aVsyncId, const TimeStamp& aRefreshStartTime,
const TimeStamp& aTxnStartTime, const nsCString& aTxnURL,
const TimeStamp& aFwdTime) {
if (mDestroyed) {
for (const auto& op : aToDestroy) {
DestroyActor(op);
@ -1058,8 +1062,8 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEmptyTransaction(
// Only register a value for CONTENT_FRAME_TIME telemetry if we actually drew
// something. It is for consistency with disabling WebRender.
HoldPendingTransactionId(mWrEpoch, aTransactionId, false, aRefreshStartTime,
aTxnStartTime, aTxnURL, aFwdTime,
HoldPendingTransactionId(mWrEpoch, aTransactionId, false, aVsyncId,
aRefreshStartTime, aTxnStartTime, aTxnURL, aFwdTime,
/* aIsFirstPaint */ false,
/* aUseForTelemetry */ scheduleComposite);
@ -1075,7 +1079,8 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEmptyTransaction(
MOZ_ASSERT(mPendingTransactionIds.size() == 1);
if (CompositorBridgeParent* cbp = GetRootCompositorBridgeParent()) {
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();
// Update timestamp of scheduler for APZ and animation.
mCompositorScheduler->UpdateLastComposeTime();
MaybeGenerateFrame(/* aForceGenerateFrame */ true);
MaybeGenerateFrame(VsyncId(), /* aForceGenerateFrame */ true);
}
}
@ -1642,11 +1647,12 @@ bool WebRenderBridgeParent::SampleAnimations(
void WebRenderBridgeParent::CompositeIfNeeded() {
if (mSkippedComposite) {
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) {
// This function should only get called in the root WRBP
MOZ_ASSERT(IsRootWebRenderBridgeParent());
@ -1677,7 +1683,7 @@ void WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget,
}
return;
}
MaybeGenerateFrame(/* aForceGenerateFrame */ false);
MaybeGenerateFrame(aId, /* aForceGenerateFrame */ false);
}
TimeDuration WebRenderBridgeParent::GetVsyncInterval() const {
@ -1689,7 +1695,8 @@ TimeDuration WebRenderBridgeParent::GetVsyncInterval() const {
return TimeDuration();
}
void WebRenderBridgeParent::MaybeGenerateFrame(bool aForceGenerateFrame) {
void WebRenderBridgeParent::MaybeGenerateFrame(VsyncId aId,
bool aForceGenerateFrame) {
// This function should only get called in the root WRBP
MOZ_ASSERT(IsRootWebRenderBridgeParent());
@ -1737,7 +1744,7 @@ void WebRenderBridgeParent::MaybeGenerateFrame(bool aForceGenerateFrame) {
SetAPZSampleTime();
wr::RenderThread::Get()->IncPendingFrameCount(mApi->GetId(), start);
wr::RenderThread::Get()->IncPendingFrameCount(mApi->GetId(), aId, start);
#if defined(ENABLE_FRAME_LATENCY_LOG)
auto startTime = TimeStamp::Now();
@ -1751,13 +1758,13 @@ void WebRenderBridgeParent::MaybeGenerateFrame(bool aForceGenerateFrame) {
void WebRenderBridgeParent::HoldPendingTransactionId(
const wr::Epoch& aWrEpoch, TransactionId aTransactionId,
bool aContainsSVGGroup, const TimeStamp& aRefreshStartTime,
const TimeStamp& aTxnStartTime, const nsCString& aTxnURL,
const TimeStamp& aFwdTime, const bool aIsFirstPaint,
const bool aUseForTelemetry) {
bool aContainsSVGGroup, const VsyncId& aVsyncId,
const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime,
const nsCString& aTxnURL, const TimeStamp& aFwdTime,
const bool aIsFirstPaint, const bool aUseForTelemetry) {
MOZ_ASSERT(aTransactionId > LastPendingTransactionId());
mPendingTransactionIds.push_back(PendingTransactionId(
aWrEpoch, aTransactionId, aContainsSVGGroup, aRefreshStartTime,
aWrEpoch, aTransactionId, aContainsSVGGroup, aVsyncId, aRefreshStartTime,
aTxnStartTime, aTxnURL, aFwdTime, aIsFirstPaint, aUseForTelemetry));
}
@ -1780,10 +1787,10 @@ void WebRenderBridgeParent::NotifySceneBuiltForEpoch(
}
TransactionId WebRenderBridgeParent::FlushTransactionIdsForEpoch(
const wr::Epoch& aEpoch, const TimeStamp& aCompositeStartTime,
const TimeStamp& aRenderStartTime, const TimeStamp& aEndTime,
UiCompositorControllerParent* aUiController, wr::RendererStats* aStats,
nsTArray<FrameStats>* aOutputStats) {
const wr::Epoch& aEpoch, const VsyncId& aCompositeStartId,
const TimeStamp& aCompositeStartTime, const TimeStamp& aRenderStartTime,
const TimeStamp& aEndTime, UiCompositorControllerParent* aUiController,
wr::RendererStats* aStats, nsTArray<FrameStats>* aOutputStats) {
TransactionId id{0};
while (!mPendingTransactionIds.empty()) {
const auto& transactionId = mPendingTransactionIds.front();
@ -1820,6 +1827,50 @@ TransactionId WebRenderBridgeParent::FlushTransactionIdsForEpoch(
}
#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) {
aOutputStats->AppendElement(FrameStats(
transactionId.mId, aCompositeStartTime, aRenderStartTime, aEndTime,

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

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

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

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

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

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

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

@ -55,11 +55,14 @@ void VsyncSource::Display::NotifyVsync(TimeStamp aVsyncTimestamp) {
// Called on the vsync thread
MutexAutoLock lock(mDispatcherLock);
mVsyncId = mVsyncId.Next();
VsyncEvent event(mVsyncId, aVsyncTimestamp);
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() {

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

@ -11,12 +11,21 @@
#include "mozilla/Mutex.h"
#include "mozilla/TimeStamp.h"
#include "nsISupportsImpl.h"
#include "mozilla/layers/LayersTypes.h"
namespace mozilla {
class RefreshTimerVsyncDispatcher;
class CompositorVsyncDispatcher;
class VsyncIdType {};
typedef layers::BaseTransactionId<VsyncIdType> VsyncId;
namespace layout {
class PVsyncChild;
}
namespace gfx {
class PVsyncBridgeParent;
// Controls how and when to enable/disable vsync. Lives as long as the
// gfxPlatform does on the parent process
@ -66,6 +75,7 @@ class VsyncSource {
bool mRefreshTimerNeedsVsync;
nsTArray<RefPtr<CompositorVsyncDispatcher>> mCompositorVsyncDispatchers;
RefPtr<RefreshTimerVsyncDispatcher> mRefreshTimerVsyncDispatcher;
VsyncId mVsyncId;
};
void AddCompositorVsyncDispatcher(
@ -82,6 +92,27 @@ class VsyncSource {
};
} // 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
#endif /* GFX_VSYNCSOURCE_H */

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

@ -2557,6 +2557,11 @@ void gfxPlatform::InitCompositorAccelerationPrefs() {
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
// WebRender for qualifying hardware. The Normandy pref rollout code sets
// 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
// override all the other enabling prefs (gfx.webrender.enabled,
// gfx.webrender.all, and gfx.webrender.all.qualified).
if (gfxPrefs::WebRenderForceDisabled()) {
if (gfxPrefs::WebRenderForceDisabled() || WebRenderEnvvarDisabled()) {
featureWebRender.UserDisable(
"User force-disabled WR",
NS_LITERAL_CSTRING("FEATURE_FAILURE_USER_FORCE_DISABLED"));

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

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

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

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

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

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

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

@ -1 +1 @@
74b9312fc0305ecaf06322b0f2f466da96e0a64c
34d58890821d2e606285f21cd6f4befd46c83d47

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

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

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

@ -1507,6 +1507,8 @@ impl ToDebugString for SpecificDisplayItem {
SpecificDisplayItem::StickyFrame(..) => String::from("sticky_frame"),
SpecificDisplayItem::Text(..) => String::from("text"),
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,
PushShadow(Shadow),
PopAllShadows,
PushCacheMarker(CacheMarkerDisplayItem),
PopCacheMarker,
}
/// This is a "complete" version of the DI specifics,
@ -159,6 +161,8 @@ pub enum CompletelySpecificDisplayItem {
SetGradientStops(Vec<GradientStop>),
PushShadow(Shadow),
PopAllShadows,
PushCacheMarker(CacheMarkerDisplayItem),
PopCacheMarker,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
@ -517,6 +521,12 @@ pub struct PushReferenceFrameDisplayListItem {
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)]
pub struct ReferenceFrame {
pub transform: Option<PropertyBinding<LayoutTransform>>,

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

@ -14,7 +14,7 @@ use std::marker::PhantomData;
use std::ops::Range;
use std::{io, mem, ptr, slice};
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 {ColorF, ComplexClipRegion, DisplayItem, ExtendMode, ExternalScrollId, FilterOp};
use {FontInstanceKey, GlyphInstance, GlyphOptions, RasterSpace, Gradient, GradientBuilder};
@ -502,6 +502,8 @@ impl Serialize for BuiltDisplayList {
),
SpecificDisplayItem::PushShadow(v) => PushShadow(v),
SpecificDisplayItem::PopAllShadows => PopAllShadows,
SpecificDisplayItem::PushCacheMarker(m) => PushCacheMarker(m),
SpecificDisplayItem::PopCacheMarker => PopCacheMarker,
},
clip_and_scroll: display_item.clip_and_scroll,
info: display_item.info,
@ -588,6 +590,8 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
},
PushShadow(specific_item) => SpecificDisplayItem::PushShadow(specific_item),
PopAllShadows => SpecificDisplayItem::PopAllShadows,
PushCacheMarker(marker) => SpecificDisplayItem::PushCacheMarker(marker),
PopCacheMarker => SpecificDisplayItem::PopCacheMarker,
},
clip_and_scroll: complete.clip_and_scroll,
info: complete.info,
@ -1261,6 +1265,19 @@ impl DisplayListBuilder {
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) {
self.push_new_empty_item(&SpecificDisplayItem::PopReferenceFrame);
}

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

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

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

@ -460,14 +460,18 @@ TraceLoggerEventPayload* TraceLoggerThreadState::getOrCreateEventPayload(
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) {
return nullptr;
}
if (!textIdPayloads.putNew(textId, payload)) {
if (!textIdPayloads.putNew(nextTextId, payload)) {
js_delete(payload);
return nullptr;
}
@ -976,33 +980,72 @@ void TraceLoggerThread::log(uint32_t id) {
entry.textId = id;
}
void TraceLoggerThreadState::clear() {
LockGuard<Mutex> guard(lock);
for (TraceLoggerThread* logger : threadLoggers) {
logger->clear();
}
bool TraceLoggerThreadState::remapDictionaryEntries(
mozilla::Vector<UniqueChars, 0, SystemAllocPolicy>* newDictionary,
uint32_t* newNextDictionaryId) {
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
// that still hold a pointer to a payload. Restarting the profiler may add
// this event to the new events array and so we need to maintain it's
// existence.
// that still hold a pointer to a payload. Restarting the profiler may reuse
// the exact same event as a previous session if it's still alive so we need
// to maintain it's existence.
for (TextIdToPayloadMap::Enum e(textIdPayloads); !e.empty(); e.popFront()) {
if (e.front().value()->uses() == 0) {
js_delete(e.front().value());
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.
for (auto range = dictionaryData.all(); !range.empty(); range.popFront()) {
range.front().reset();
return true;
}
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();
payloadDictionary.clearAndCompact();
nextTextId = TraceLogger_Last;
nextDictionaryId = 0;
for (TraceLoggerThread* logger : threadLoggers) {
logger->clear();
}
}
void TraceLoggerThread::clear() {

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

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

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

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

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

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

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

@ -7,6 +7,7 @@ include protocol PBackground;
include "mozilla/layers/LayersMessageUtils.h";
using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
using mozilla::VsyncEvent from "mozilla/VsyncDispatcher.h";
namespace mozilla {
namespace layout {
@ -22,7 +23,7 @@ async protocol PVsync
child:
// 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.
async VsyncRate(float aVsyncRate);

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

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

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

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

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

@ -42,18 +42,18 @@ VsyncParent::~VsyncParent() {
// 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.
MOZ_ASSERT(!IsOnBackgroundThread());
nsCOMPtr<nsIRunnable> vsyncEvent = NewRunnableMethod<TimeStamp>(
nsCOMPtr<nsIRunnable> vsyncEvent = NewRunnableMethod<VsyncEvent>(
"layout::VsyncParent::DispatchVsyncEvent", this,
&VsyncParent::DispatchVsyncEvent, aTimeStamp);
&VsyncParent::DispatchVsyncEvent, aVsync);
MOZ_ALWAYS_SUCCEEDS(
mBackgroundThread->Dispatch(vsyncEvent, NS_DISPATCH_NORMAL));
return true;
}
void VsyncParent::DispatchVsyncEvent(TimeStamp aTimeStamp) {
void VsyncParent::DispatchVsyncEvent(const VsyncEvent& aVsync) {
AssertIsOnBackgroundThread();
// 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
// notification.
if (mObservingVsync && !mDestroyed) {
Unused << SendNotify(aTimeStamp);
Unused << SendNotify(aVsync);
}
}

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

@ -34,14 +34,14 @@ class VsyncParent final : public PVsyncParent, public VsyncObserver {
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 RecvObserve() override;
virtual mozilla::ipc::IPCResult RecvUnobserve() override;
virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override;
void DispatchVsyncEvent(TimeStamp aTimeStamp);
void DispatchVsyncEvent(const VsyncEvent& aVsync);
bool mObservingVsync;
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':
LOCAL_INCLUDES += ['/media/libdav1d/config/aarch64/']
EXPORTS.dav1d += ['config/aarch64/config.h']
else:
LOCAL_INCLUDES += ['/media/libdav1d/config/other/']
EXPORTS.dav1d += ['config/other/config.h']
EXPORTS.dav1d += [
'version.h',

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

@ -573,12 +573,6 @@ VCMEncodedFrame* VCMJitterBuffer::ExtractAndSetDecode(uint32_t timestamp) {
if ((*frame).IsSessionComplete())
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;
}

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

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

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

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

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

@ -955,6 +955,11 @@ def enable_webrender(config, tests):
if test.get('webrender'):
test['mozharness'].setdefault('extra-options', [])\
.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

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

@ -51,6 +51,12 @@ class AWSY(TestingMixin, MercurialScript, TooltoolMixin, CodeCoverageMixin):
"default": False,
"help": "Tries to enable the WebRender compositor.",
}],
[["--disable-webrender"],
{"action": "store_true",
"dest": "disable_webrender",
"default": False,
"help": "Force-disables the WebRender compositor.",
}],
[["--base"],
{"action": "store_true",
"dest": "test_about_blank",
@ -232,6 +238,11 @@ class AWSY(TestingMixin, MercurialScript, TooltoolMixin, CodeCoverageMixin):
env['MOZ_WEBRENDER'] = '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']
if not os.path.isdir(env['MOZ_UPLOAD_DIR']):
self.mkdir_p(env['MOZ_UPLOAD_DIR'])

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

@ -140,10 +140,13 @@ button > .button-box {
.study-name {
font-weight: bold;
margin-bottom: 0.3em;
white-space: pre;
}
.study-header {
margin-bottom: .3em;
}
.study-header > * {
margin-right: 5px;
}
@ -153,7 +156,13 @@ button > .button-box {
}
.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 {

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

@ -13211,6 +13211,15 @@
"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"
},
"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": {
"record_in_processes": ["main", "content"],
"alert_emails": ["gfx-telemetry-alerts@mozilla.com", "mwoodrow@mozilla.com"],

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

@ -414,9 +414,12 @@ void SetVsyncObserver(VsyncObserver* aObserver) {
gVsyncObserver = aObserver;
}
static void NotifyVsyncObserver() {
void NotifyVsyncObserver() {
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
}
void CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp) {
void CompositorVsyncDispatcher::NotifyVsync(const VsyncEvent& aVsync) {
// In vsync thread
layers::CompositorBridgeParent::PostInsertVsyncProfilerMarker(
aVsyncTimestamp);
layers::CompositorBridgeParent::PostInsertVsyncProfilerMarker(aVsync.mTime);
MutexAutoLock lock(mCompositorObserverLock);
if (mCompositorVsyncObserver) {
mCompositorVsyncObserver->NotifyVsync(aVsyncTimestamp);
mCompositorVsyncObserver->NotifyVsync(aVsync);
}
}
@ -101,15 +100,15 @@ RefreshTimerVsyncDispatcher::~RefreshTimerVsyncDispatcher() {
MOZ_ASSERT(NS_IsMainThread());
}
void RefreshTimerVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp) {
void RefreshTimerVsyncDispatcher::NotifyVsync(const VsyncEvent& aVsync) {
MutexAutoLock lock(mRefreshTimersLock);
for (size_t i = 0; i < mChildRefreshTimers.Length(); i++) {
mChildRefreshTimers[i]->NotifyVsync(aVsyncTimestamp);
mChildRefreshTimers[i]->NotifyVsync(aVsync);
}
if (mParentRefreshTimer) {
mParentRefreshTimer->NotifyVsync(aVsyncTimestamp);
mParentRefreshTimer->NotifyVsync(aVsync);
}
}

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

@ -11,6 +11,7 @@
#include "nsISupportsImpl.h"
#include "nsTArray.h"
#include "mozilla/RefPtr.h"
#include "VsyncSource.h"
namespace mozilla {
@ -23,7 +24,7 @@ class VsyncObserver {
// 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
// thread model before handling the real task.
virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) = 0;
virtual bool NotifyVsync(const VsyncEvent& aVsync) = 0;
protected:
VsyncObserver() {}
@ -49,7 +50,7 @@ class CompositorVsyncDispatcher final {
CompositorVsyncDispatcher();
// 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
void SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
@ -72,7 +73,7 @@ class RefreshTimerVsyncDispatcher final {
RefreshTimerVsyncDispatcher();
// Please check CompositorVsyncDispatcher::NotifyVsync().
void NotifyVsync(TimeStamp aVsyncTimestamp);
void NotifyVsync(const VsyncEvent& aVsync);
// Set chrome process's RefreshTimer to this dispatcher.
// This function can be called from any thread.