зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound. a=merge
This commit is contained in:
Коммит
5d3de7487c
|
@ -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.
|
||||
|
|
Загрузка…
Ссылка в новой задаче