зеркало из 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");
|
let item = this._createElement("div");
|
||||||
item.className = "urlbarView-row";
|
item.className = "urlbarView-row";
|
||||||
item.setAttribute("resultIndex", resultIndex);
|
item.setAttribute("resultIndex", resultIndex);
|
||||||
|
|
||||||
if (result.type == UrlbarUtils.MATCH_TYPE.TAB_SWITCH) {
|
if (result.type == UrlbarUtils.MATCH_TYPE.TAB_SWITCH) {
|
||||||
item.setAttribute("action", "switch-to-tab");
|
item.setAttribute("type", "switchtab");
|
||||||
|
} else if (result.source == UrlbarUtils.MATCH_SOURCE.BOOKMARKS) {
|
||||||
|
item.setAttribute("type", "bookmark");
|
||||||
}
|
}
|
||||||
|
|
||||||
let content = this._createElement("span");
|
let content = this._createElement("span");
|
||||||
content.className = "urlbarView-row-inner";
|
content.className = "urlbarView-row-inner";
|
||||||
item.appendChild(content);
|
item.appendChild(content);
|
||||||
|
|
||||||
let actionIcon = this._createElement("span");
|
let typeIcon = this._createElement("span");
|
||||||
actionIcon.className = "urlbarView-action-icon";
|
typeIcon.className = "urlbarView-type-icon";
|
||||||
content.appendChild(actionIcon);
|
content.appendChild(typeIcon);
|
||||||
|
|
||||||
let favicon = this._createElement("img");
|
let favicon = this._createElement("img");
|
||||||
favicon.className = "urlbarView-favicon";
|
favicon.className = "urlbarView-favicon";
|
||||||
|
|
|
@ -68,7 +68,7 @@
|
||||||
color: var(--autocomplete-popup-highlight-color);
|
color: var(--autocomplete-popup-highlight-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.urlbarView-action-icon,
|
.urlbarView-type-icon,
|
||||||
.urlbarView-favicon {
|
.urlbarView-favicon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
@ -82,7 +82,11 @@
|
||||||
fill-opacity: 0.6;
|
fill-opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.urlbarView-row[action=switch-to-tab] > .urlbarView-row-inner > .urlbarView-action-icon {
|
.urlbarView-row[type=bookmark] > .urlbarView-row-inner > .urlbarView-type-icon {
|
||||||
|
background-image: url(chrome://browser/skin/bookmark.svg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.urlbarView-row[type=switchtab] > .urlbarView-row-inner > .urlbarView-type-icon {
|
||||||
background-image: url(chrome://browser/skin/tab.svg);
|
background-image: url(chrome://browser/skin/tab.svg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,12 +18,12 @@ CompositorWidgetVsyncObserver::CompositorWidgetVsyncObserver(
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CompositorWidgetVsyncObserver::NotifyVsync(TimeStamp aTimeStamp) {
|
bool CompositorWidgetVsyncObserver::NotifyVsync(const VsyncEvent& aVsync) {
|
||||||
// Vsync notifications should only arrive on the vsync thread.
|
// Vsync notifications should only arrive on the vsync thread.
|
||||||
MOZ_ASSERT(XRE_IsParentProcess());
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
MOZ_ASSERT(!NS_IsMainThread());
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
|
|
||||||
mVsyncBridge->NotifyVsync(aTimeStamp, mRootLayerTreeId);
|
mVsyncBridge->NotifyVsync(aVsync, mRootLayerTreeId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ class CompositorWidgetVsyncObserver : public VsyncObserver {
|
||||||
CompositorWidgetVsyncObserver(RefPtr<VsyncBridgeChild> aVsyncBridge,
|
CompositorWidgetVsyncObserver(RefPtr<VsyncBridgeChild> aVsyncBridge,
|
||||||
const layers::LayersId& aRootLayerTreeId);
|
const layers::LayersId& aRootLayerTreeId);
|
||||||
|
|
||||||
bool NotifyVsync(TimeStamp aVsyncTimestamp) override;
|
bool NotifyVsync(const VsyncEvent& aVsync) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RefPtr<VsyncBridgeChild> mVsyncBridge;
|
RefPtr<VsyncBridgeChild> mVsyncBridge;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
|
using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
|
||||||
using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h";
|
using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h";
|
||||||
|
using mozilla::VsyncEvent from "mozilla/VsyncDispatcher.h";
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace gfx {
|
namespace gfx {
|
||||||
|
@ -16,7 +17,7 @@ namespace gfx {
|
||||||
sync protocol PVsyncBridge
|
sync protocol PVsyncBridge
|
||||||
{
|
{
|
||||||
parent:
|
parent:
|
||||||
async NotifyVsync(TimeStamp vsyncTimeStamp, LayersId layersId);
|
async NotifyVsync(VsyncEvent vsync, LayersId layersId);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gfx
|
} // namespace gfx
|
||||||
|
|
|
@ -46,21 +46,21 @@ void VsyncBridgeChild::Open(Endpoint<PVsyncBridgeChild>&& aEndpoint) {
|
||||||
|
|
||||||
class NotifyVsyncTask : public Runnable {
|
class NotifyVsyncTask : public Runnable {
|
||||||
public:
|
public:
|
||||||
NotifyVsyncTask(RefPtr<VsyncBridgeChild> aVsyncBridge, TimeStamp aTimeStamp,
|
NotifyVsyncTask(RefPtr<VsyncBridgeChild> aVsyncBridge,
|
||||||
const layers::LayersId& aLayersId)
|
const VsyncEvent& aVsync, const layers::LayersId& aLayersId)
|
||||||
: Runnable("gfx::NotifyVsyncTask"),
|
: Runnable("gfx::NotifyVsyncTask"),
|
||||||
mVsyncBridge(aVsyncBridge),
|
mVsyncBridge(aVsyncBridge),
|
||||||
mTimeStamp(aTimeStamp),
|
mVsync(aVsync),
|
||||||
mLayersId(aLayersId) {}
|
mLayersId(aLayersId) {}
|
||||||
|
|
||||||
NS_IMETHOD Run() override {
|
NS_IMETHOD Run() override {
|
||||||
mVsyncBridge->NotifyVsyncImpl(mTimeStamp, mLayersId);
|
mVsyncBridge->NotifyVsyncImpl(mVsync, mLayersId);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RefPtr<VsyncBridgeChild> mVsyncBridge;
|
RefPtr<VsyncBridgeChild> mVsyncBridge;
|
||||||
TimeStamp mTimeStamp;
|
VsyncEvent mVsync;
|
||||||
layers::LayersId mLayersId;
|
layers::LayersId mLayersId;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -68,17 +68,16 @@ bool VsyncBridgeChild::IsOnVsyncIOThread() const {
|
||||||
return MessageLoop::current() == mLoop;
|
return MessageLoop::current() == mLoop;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VsyncBridgeChild::NotifyVsync(TimeStamp aTimeStamp,
|
void VsyncBridgeChild::NotifyVsync(const VsyncEvent& aVsync,
|
||||||
const layers::LayersId& aLayersId) {
|
const layers::LayersId& aLayersId) {
|
||||||
// This should be on the Vsync thread (not the Vsync I/O thread).
|
// This should be on the Vsync thread (not the Vsync I/O thread).
|
||||||
MOZ_ASSERT(!IsOnVsyncIOThread());
|
MOZ_ASSERT(!IsOnVsyncIOThread());
|
||||||
|
|
||||||
RefPtr<NotifyVsyncTask> task =
|
RefPtr<NotifyVsyncTask> task = new NotifyVsyncTask(this, aVsync, aLayersId);
|
||||||
new NotifyVsyncTask(this, aTimeStamp, aLayersId);
|
|
||||||
mLoop->PostTask(task.forget());
|
mLoop->PostTask(task.forget());
|
||||||
}
|
}
|
||||||
|
|
||||||
void VsyncBridgeChild::NotifyVsyncImpl(TimeStamp aTimeStamp,
|
void VsyncBridgeChild::NotifyVsyncImpl(const VsyncEvent& aVsync,
|
||||||
const layers::LayersId& aLayersId) {
|
const layers::LayersId& aLayersId) {
|
||||||
// This should be on the Vsync I/O thread.
|
// This should be on the Vsync I/O thread.
|
||||||
MOZ_ASSERT(IsOnVsyncIOThread());
|
MOZ_ASSERT(IsOnVsyncIOThread());
|
||||||
|
@ -86,7 +85,7 @@ void VsyncBridgeChild::NotifyVsyncImpl(TimeStamp aTimeStamp,
|
||||||
if (!mProcessToken) {
|
if (!mProcessToken) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SendNotifyVsync(aTimeStamp, aLayersId);
|
SendNotifyVsync(aVsync, aLayersId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VsyncBridgeChild::Close() {
|
void VsyncBridgeChild::Close() {
|
||||||
|
|
|
@ -30,7 +30,7 @@ class VsyncBridgeChild final : public PVsyncBridgeChild {
|
||||||
void DeallocPVsyncBridgeChild() override;
|
void DeallocPVsyncBridgeChild() override;
|
||||||
void ProcessingError(Result aCode, const char* aReason) override;
|
void ProcessingError(Result aCode, const char* aReason) override;
|
||||||
|
|
||||||
void NotifyVsync(TimeStamp aTimeStamp, const layers::LayersId& aLayersId);
|
void NotifyVsync(const VsyncEvent& aVsync, const layers::LayersId& aLayersId);
|
||||||
|
|
||||||
virtual void HandleFatalError(const char* aMsg) const override;
|
virtual void HandleFatalError(const char* aMsg) const override;
|
||||||
|
|
||||||
|
@ -40,7 +40,8 @@ class VsyncBridgeChild final : public PVsyncBridgeChild {
|
||||||
|
|
||||||
void Open(Endpoint<PVsyncBridgeChild>&& aEndpoint);
|
void Open(Endpoint<PVsyncBridgeChild>&& aEndpoint);
|
||||||
|
|
||||||
void NotifyVsyncImpl(TimeStamp aTimeStamp, const layers::LayersId& aLayersId);
|
void NotifyVsyncImpl(const VsyncEvent& aVsync,
|
||||||
|
const layers::LayersId& aLayersId);
|
||||||
|
|
||||||
bool IsOnVsyncIOThread() const;
|
bool IsOnVsyncIOThread() const;
|
||||||
|
|
||||||
|
|
|
@ -42,8 +42,8 @@ void VsyncBridgeParent::Open(Endpoint<PVsyncBridgeParent>&& aEndpoint) {
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult VsyncBridgeParent::RecvNotifyVsync(
|
mozilla::ipc::IPCResult VsyncBridgeParent::RecvNotifyVsync(
|
||||||
const TimeStamp& aTimeStamp, const LayersId& aLayersId) {
|
const VsyncEvent& aVsync, const LayersId& aLayersId) {
|
||||||
CompositorBridgeParent::NotifyVsync(aTimeStamp, aLayersId);
|
CompositorBridgeParent::NotifyVsync(aVsync, aLayersId);
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ class VsyncBridgeParent final : public PVsyncBridgeParent {
|
||||||
static RefPtr<VsyncBridgeParent> Start(
|
static RefPtr<VsyncBridgeParent> Start(
|
||||||
Endpoint<PVsyncBridgeParent>&& aEndpoint);
|
Endpoint<PVsyncBridgeParent>&& aEndpoint);
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvNotifyVsync(const TimeStamp& vsyncTimeStamp,
|
mozilla::ipc::IPCResult RecvNotifyVsync(const VsyncEvent& aVsync,
|
||||||
const LayersId& aLayersId) override;
|
const LayersId& aLayersId) override;
|
||||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||||
void DeallocPVsyncBridgeParent() override;
|
void DeallocPVsyncBridgeParent() override;
|
||||||
|
|
|
@ -79,39 +79,51 @@ struct LayersId {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TransactionId {
|
template <typename T>
|
||||||
uint64_t mId;
|
struct BaseTransactionId {
|
||||||
|
uint64_t mId = 0;
|
||||||
|
|
||||||
bool IsValid() const { return mId != 0; }
|
bool IsValid() const { return mId != 0; }
|
||||||
|
|
||||||
MOZ_MUST_USE TransactionId Next() const { return TransactionId{mId + 1}; }
|
MOZ_MUST_USE BaseTransactionId<T> Next() const {
|
||||||
|
return BaseTransactionId<T>{mId + 1};
|
||||||
|
}
|
||||||
|
|
||||||
MOZ_MUST_USE TransactionId Prev() const { return TransactionId{mId - 1}; }
|
MOZ_MUST_USE BaseTransactionId<T> Prev() const {
|
||||||
|
return BaseTransactionId<T>{mId - 1};
|
||||||
|
}
|
||||||
|
|
||||||
int64_t operator-(const TransactionId& aOther) const {
|
int64_t operator-(const BaseTransactionId<T>& aOther) const {
|
||||||
return mId - aOther.mId;
|
return mId - aOther.mId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow explicit cast to a uint64_t for now
|
// Allow explicit cast to a uint64_t for now
|
||||||
explicit operator uint64_t() const { return mId; }
|
explicit operator uint64_t() const { return mId; }
|
||||||
|
|
||||||
bool operator<(const TransactionId& aOther) const { return mId < aOther.mId; }
|
bool operator<(const BaseTransactionId<T>& aOther) const {
|
||||||
|
return mId < aOther.mId;
|
||||||
|
}
|
||||||
|
|
||||||
bool operator<=(const TransactionId& aOther) const {
|
bool operator<=(const BaseTransactionId<T>& aOther) const {
|
||||||
return mId <= aOther.mId;
|
return mId <= aOther.mId;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator>(const TransactionId& aOther) const { return mId > aOther.mId; }
|
bool operator>(const BaseTransactionId<T>& aOther) const {
|
||||||
|
return mId > aOther.mId;
|
||||||
|
}
|
||||||
|
|
||||||
bool operator>=(const TransactionId& aOther) const {
|
bool operator>=(const BaseTransactionId<T>& aOther) const {
|
||||||
return mId >= aOther.mId;
|
return mId >= aOther.mId;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const TransactionId& aOther) const {
|
bool operator==(const BaseTransactionId<T>& aOther) const {
|
||||||
return mId == aOther.mId;
|
return mId == aOther.mId;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TransactionIdType {};
|
||||||
|
typedef BaseTransactionId<TransactionIdType> TransactionId;
|
||||||
|
|
||||||
struct LayersObserverEpoch {
|
struct LayersObserverEpoch {
|
||||||
uint64_t mId;
|
uint64_t mId;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "nsISupportsImpl.h"
|
#include "nsISupportsImpl.h"
|
||||||
#include "mozilla/layers/LayersTypes.h"
|
#include "mozilla/layers/LayersTypes.h"
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
|
#include "mozilla/VsyncDispatcher.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
@ -80,6 +81,8 @@ class TransactionIdAllocator {
|
||||||
* Get the start time of the current refresh tick.
|
* Get the start time of the current refresh tick.
|
||||||
*/
|
*/
|
||||||
virtual mozilla::TimeStamp GetTransactionStart() = 0;
|
virtual mozilla::TimeStamp GetTransactionStart() = 0;
|
||||||
|
|
||||||
|
virtual VsyncId GetVsyncId() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace layers
|
} // namespace layers
|
||||||
|
|
|
@ -681,6 +681,9 @@ void ClientLayerManager::ForwardTransaction(bool aScheduleComposite) {
|
||||||
mLatestTransactionId =
|
mLatestTransactionId =
|
||||||
mTransactionIdAllocator->GetTransactionId(!mIsRepeatTransaction);
|
mTransactionIdAllocator->GetTransactionId(!mIsRepeatTransaction);
|
||||||
TimeStamp refreshStart = mTransactionIdAllocator->GetTransactionStart();
|
TimeStamp refreshStart = mTransactionIdAllocator->GetTransactionStart();
|
||||||
|
if (!refreshStart) {
|
||||||
|
refreshStart = mTransactionStart;
|
||||||
|
}
|
||||||
|
|
||||||
if (gfxPrefs::AlwaysPaint() && XRE_IsContentProcess()) {
|
if (gfxPrefs::AlwaysPaint() && XRE_IsContentProcess()) {
|
||||||
mForwarder->SendPaintTime(mLatestTransactionId, mLastPaintTime);
|
mForwarder->SendPaintTime(mLatestTransactionId, mLastPaintTime);
|
||||||
|
@ -688,10 +691,11 @@ void ClientLayerManager::ForwardTransaction(bool aScheduleComposite) {
|
||||||
|
|
||||||
// forward this transaction's changeset to our LayerManagerComposite
|
// forward this transaction's changeset to our LayerManagerComposite
|
||||||
bool sent = false;
|
bool sent = false;
|
||||||
bool ok = mForwarder->EndTransaction(mRegionToClear, mLatestTransactionId,
|
bool ok = mForwarder->EndTransaction(
|
||||||
aScheduleComposite, mPaintSequenceNumber,
|
mRegionToClear, mLatestTransactionId, aScheduleComposite,
|
||||||
mIsRepeatTransaction, refreshStart,
|
mPaintSequenceNumber, mIsRepeatTransaction,
|
||||||
mTransactionStart, mURL, &sent);
|
mTransactionIdAllocator->GetVsyncId(), refreshStart, mTransactionStart,
|
||||||
|
mURL, &sent);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
if (sent) {
|
if (sent) {
|
||||||
mNeedsComposite = false;
|
mNeedsComposite = false;
|
||||||
|
|
|
@ -671,11 +671,12 @@ void CompositorBridgeParent::PauseComposition() {
|
||||||
TimeStamp now = TimeStamp::Now();
|
TimeStamp now = TimeStamp::Now();
|
||||||
if (mCompositor) {
|
if (mCompositor) {
|
||||||
mCompositor->Pause();
|
mCompositor->Pause();
|
||||||
DidComposite(now, now);
|
DidComposite(VsyncId(), now, now);
|
||||||
} else if (mWrBridge) {
|
} else if (mWrBridge) {
|
||||||
mWrBridge->Pause();
|
mWrBridge->Pause();
|
||||||
NotifyPipelineRendered(mWrBridge->PipelineId(),
|
NotifyPipelineRendered(mWrBridge->PipelineId(),
|
||||||
mWrBridge->GetCurrentEpoch(), now, now, now);
|
mWrBridge->GetCurrentEpoch(), VsyncId(), now, now,
|
||||||
|
now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,7 +889,7 @@ void CompositorBridgeParent::ScheduleComposition() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompositorBridgeParent::CompositeToTarget(DrawTarget* aTarget,
|
void CompositorBridgeParent::CompositeToTarget(VsyncId aId, DrawTarget* aTarget,
|
||||||
const gfx::IntRect* aRect) {
|
const gfx::IntRect* aRect) {
|
||||||
AUTO_PROFILER_TRACING("Paint", "Composite");
|
AUTO_PROFILER_TRACING("Paint", "Composite");
|
||||||
AUTO_PROFILER_LABEL("CompositorBridgeParent::CompositeToTarget", GRAPHICS);
|
AUTO_PROFILER_LABEL("CompositorBridgeParent::CompositeToTarget", GRAPHICS);
|
||||||
|
@ -899,7 +900,7 @@ void CompositorBridgeParent::CompositeToTarget(DrawTarget* aTarget,
|
||||||
|
|
||||||
if (!CanComposite()) {
|
if (!CanComposite()) {
|
||||||
TimeStamp end = TimeStamp::Now();
|
TimeStamp end = TimeStamp::Now();
|
||||||
DidComposite(start, end);
|
DidComposite(aId, start, end);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -993,7 +994,7 @@ void CompositorBridgeParent::CompositeToTarget(DrawTarget* aTarget,
|
||||||
|
|
||||||
if (!aTarget) {
|
if (!aTarget) {
|
||||||
TimeStamp end = TimeStamp::Now();
|
TimeStamp end = TimeStamp::Now();
|
||||||
DidComposite(start, end);
|
DidComposite(aId, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're not really taking advantage of the stored composite-again-time here.
|
// We're not really taking advantage of the stored composite-again-time here.
|
||||||
|
@ -1246,7 +1247,7 @@ void CompositorBridgeParent::ShadowLayersUpdated(
|
||||||
ScheduleComposition();
|
ScheduleComposition();
|
||||||
if (mPaused) {
|
if (mPaused) {
|
||||||
TimeStamp now = TimeStamp::Now();
|
TimeStamp now = TimeStamp::Now();
|
||||||
DidComposite(now, now);
|
DidComposite(VsyncId(), now, now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mLayerManager->NotifyShadowTreeTransaction();
|
mLayerManager->NotifyShadowTreeTransaction();
|
||||||
|
@ -1284,7 +1285,7 @@ bool CompositorBridgeParent::SetTestSampleTime(const LayersId& aId,
|
||||||
CancelCurrentCompositeTask();
|
CancelCurrentCompositeTask();
|
||||||
// Pretend we composited in case someone is wating for this event.
|
// Pretend we composited in case someone is wating for this event.
|
||||||
TimeStamp now = TimeStamp::Now();
|
TimeStamp now = TimeStamp::Now();
|
||||||
DidComposite(now, now);
|
DidComposite(VsyncId(), now, now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1314,7 +1315,7 @@ void CompositorBridgeParent::ApplyAsyncProperties(
|
||||||
CancelCurrentCompositeTask();
|
CancelCurrentCompositeTask();
|
||||||
// Pretend we composited in case someone is waiting for this event.
|
// Pretend we composited in case someone is waiting for this event.
|
||||||
TimeStamp now = TimeStamp::Now();
|
TimeStamp now = TimeStamp::Now();
|
||||||
DidComposite(now, now);
|
DidComposite(VsyncId(), now, now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1572,7 +1573,7 @@ CompositorBridgeParent* CompositorBridgeParent::RemoveCompositor(uint64_t id) {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompositorBridgeParent::NotifyVsync(const TimeStamp& aTimeStamp,
|
void CompositorBridgeParent::NotifyVsync(const VsyncEvent& aVsync,
|
||||||
const LayersId& aLayersId) {
|
const LayersId& aLayersId) {
|
||||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
|
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
|
||||||
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
||||||
|
@ -1587,7 +1588,7 @@ void CompositorBridgeParent::NotifyVsync(const TimeStamp& aTimeStamp,
|
||||||
RefPtr<VsyncObserver> obs = cbp->mWidget->GetVsyncObserver();
|
RefPtr<VsyncObserver> obs = cbp->mWidget->GetVsyncObserver();
|
||||||
if (!obs) return;
|
if (!obs) return;
|
||||||
|
|
||||||
obs->NotifyVsync(aTimeStamp);
|
obs->NotifyVsync(aVsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult CompositorBridgeParent::RecvNotifyChildCreated(
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvNotifyChildCreated(
|
||||||
|
@ -1684,8 +1685,8 @@ mozilla::ipc::IPCResult CompositorBridgeParent::RecvAdoptChild(
|
||||||
GetAnimationStorage(), mWrBridge->GetTextureFactoryIdentifier());
|
GetAnimationStorage(), mWrBridge->GetTextureFactoryIdentifier());
|
||||||
// Pretend we composited, since parent CompositorBridgeParent was replaced.
|
// Pretend we composited, since parent CompositorBridgeParent was replaced.
|
||||||
TimeStamp now = TimeStamp::Now();
|
TimeStamp now = TimeStamp::Now();
|
||||||
NotifyPipelineRendered(childWrBridge->PipelineId(), newEpoch, now, now,
|
NotifyPipelineRendered(childWrBridge->PipelineId(), newEpoch, VsyncId(),
|
||||||
now);
|
now, now, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldApzUpdater) {
|
if (oldApzUpdater) {
|
||||||
|
@ -1976,19 +1977,14 @@ CompositorBridgeParent::LayerTreeState::InProcessSharingController() const {
|
||||||
return mParent;
|
return mParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompositorBridgeParent::DidComposite(LayersId aId,
|
void CompositorBridgeParent::DidComposite(const VsyncId& aId,
|
||||||
TimeStamp& aCompositeStart,
|
TimeStamp& aCompositeStart,
|
||||||
TimeStamp& aCompositeEnd) {
|
TimeStamp& aCompositeEnd) {
|
||||||
MOZ_ASSERT(aId == mRootLayerTreeID);
|
|
||||||
DidComposite(aCompositeStart, aCompositeEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CompositorBridgeParent::DidComposite(TimeStamp& aCompositeStart,
|
|
||||||
TimeStamp& aCompositeEnd) {
|
|
||||||
if (mWrBridge) {
|
if (mWrBridge) {
|
||||||
MOZ_ASSERT(false); // This should never get called for a WR compositor
|
MOZ_ASSERT(false); // This should never get called for a WR compositor
|
||||||
} else {
|
} else {
|
||||||
NotifyDidComposite(mPendingTransaction, aCompositeStart, aCompositeEnd);
|
NotifyDidComposite(mPendingTransaction, aId, aCompositeStart,
|
||||||
|
aCompositeEnd);
|
||||||
#if defined(ENABLE_FRAME_LATENCY_LOG)
|
#if defined(ENABLE_FRAME_LATENCY_LOG)
|
||||||
if (mPendingTransaction.IsValid()) {
|
if (mPendingTransaction.IsValid()) {
|
||||||
if (mRefreshStartTime) {
|
if (mRefreshStartTime) {
|
||||||
|
@ -2017,8 +2013,9 @@ void CompositorBridgeParent::DidComposite(TimeStamp& aCompositeStart,
|
||||||
|
|
||||||
void CompositorBridgeParent::NotifyPipelineRendered(
|
void CompositorBridgeParent::NotifyPipelineRendered(
|
||||||
const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch,
|
const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch,
|
||||||
TimeStamp& aCompositeStart, TimeStamp& aRenderStart,
|
const VsyncId& aCompositeStartId, TimeStamp& aCompositeStart,
|
||||||
TimeStamp& aCompositeEnd, wr::RendererStats* aStats) {
|
TimeStamp& aRenderStart, TimeStamp& aCompositeEnd,
|
||||||
|
wr::RendererStats* aStats) {
|
||||||
if (!mWrBridge || !mAsyncImageManager) {
|
if (!mWrBridge || !mAsyncImageManager) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2033,7 +2030,8 @@ void CompositorBridgeParent::NotifyPipelineRendered(
|
||||||
|
|
||||||
if (!mPaused) {
|
if (!mPaused) {
|
||||||
TransactionId transactionId = mWrBridge->FlushTransactionIdsForEpoch(
|
TransactionId transactionId = mWrBridge->FlushTransactionIdsForEpoch(
|
||||||
aEpoch, aCompositeStart, aRenderStart, aCompositeEnd, uiController);
|
aEpoch, aCompositeStartId, aCompositeStart, aRenderStart,
|
||||||
|
aCompositeEnd, uiController);
|
||||||
Unused << SendDidComposite(LayersId{0}, transactionId, aCompositeStart,
|
Unused << SendDidComposite(LayersId{0}, transactionId, aCompositeStart,
|
||||||
aCompositeEnd);
|
aCompositeEnd);
|
||||||
|
|
||||||
|
@ -2052,8 +2050,8 @@ void CompositorBridgeParent::NotifyPipelineRendered(
|
||||||
wrBridge->RemoveEpochDataPriorTo(aEpoch);
|
wrBridge->RemoveEpochDataPriorTo(aEpoch);
|
||||||
if (!mPaused) {
|
if (!mPaused) {
|
||||||
TransactionId transactionId = wrBridge->FlushTransactionIdsForEpoch(
|
TransactionId transactionId = wrBridge->FlushTransactionIdsForEpoch(
|
||||||
aEpoch, aCompositeStart, aRenderStart, aCompositeEnd, uiController,
|
aEpoch, aCompositeStartId, aCompositeStart, aRenderStart,
|
||||||
aStats, &stats);
|
aCompositeEnd, uiController, aStats, &stats);
|
||||||
Unused << wrBridge->GetCompositorBridge()->SendDidComposite(
|
Unused << wrBridge->GetCompositorBridge()->SendDidComposite(
|
||||||
wrBridge->GetLayersId(), transactionId, aCompositeStart,
|
wrBridge->GetLayersId(), transactionId, aCompositeStart,
|
||||||
aCompositeEnd);
|
aCompositeEnd);
|
||||||
|
@ -2071,6 +2069,7 @@ CompositorBridgeParent::GetAsyncImagePipelineManager() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompositorBridgeParent::NotifyDidComposite(TransactionId aTransactionId,
|
void CompositorBridgeParent::NotifyDidComposite(TransactionId aTransactionId,
|
||||||
|
VsyncId aId,
|
||||||
TimeStamp& aCompositeStart,
|
TimeStamp& aCompositeStart,
|
||||||
TimeStamp& aCompositeEnd) {
|
TimeStamp& aCompositeEnd) {
|
||||||
MOZ_ASSERT(
|
MOZ_ASSERT(
|
||||||
|
@ -2088,13 +2087,13 @@ void CompositorBridgeParent::NotifyDidComposite(TransactionId aTransactionId,
|
||||||
}
|
}
|
||||||
|
|
||||||
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
||||||
ForEachIndirectLayerTree(
|
ForEachIndirectLayerTree([&](LayerTreeState* lts,
|
||||||
[&](LayerTreeState* lts, const LayersId& aLayersId) -> void {
|
const LayersId& aLayersId) -> void {
|
||||||
if (lts->mCrossProcessParent && lts->mParent == this) {
|
if (lts->mCrossProcessParent && lts->mParent == this) {
|
||||||
CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent;
|
CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent;
|
||||||
cpcp->DidCompositeLocked(aLayersId, aCompositeStart, aCompositeEnd);
|
cpcp->DidCompositeLocked(aLayersId, aId, aCompositeStart, aCompositeEnd);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompositorBridgeParent::InvalidateRemoteLayers() {
|
void CompositorBridgeParent::InvalidateRemoteLayers() {
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "nsISupportsImpl.h"
|
#include "nsISupportsImpl.h"
|
||||||
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
|
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
|
||||||
#include "mozilla/layers/UiCompositorControllerParent.h"
|
#include "mozilla/layers/UiCompositorControllerParent.h"
|
||||||
|
#include "mozilla/VsyncDispatcher.h"
|
||||||
|
|
||||||
class MessageLoop;
|
class MessageLoop;
|
||||||
class nsIWidget;
|
class nsIWidget;
|
||||||
|
@ -146,9 +147,6 @@ class CompositorBridgeParentBase : public PCompositorBridgeParent,
|
||||||
LayersObserverEpoch aEpoch,
|
LayersObserverEpoch aEpoch,
|
||||||
bool aActive) = 0;
|
bool aActive) = 0;
|
||||||
|
|
||||||
virtual void DidComposite(LayersId aId, TimeStamp& aCompositeStart,
|
|
||||||
TimeStamp& aCompositeEnd) = 0;
|
|
||||||
|
|
||||||
// HostIPCAllocator
|
// HostIPCAllocator
|
||||||
base::ProcessId GetChildProcessId() override;
|
base::ProcessId GetChildProcessId() override;
|
||||||
void NotifyNotUsed(PTextureParent* aTexture,
|
void NotifyNotUsed(PTextureParent* aTexture,
|
||||||
|
@ -313,6 +311,7 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
|
||||||
void NotifyWebRenderContextPurge();
|
void NotifyWebRenderContextPurge();
|
||||||
void NotifyPipelineRendered(const wr::PipelineId& aPipelineId,
|
void NotifyPipelineRendered(const wr::PipelineId& aPipelineId,
|
||||||
const wr::Epoch& aEpoch,
|
const wr::Epoch& aEpoch,
|
||||||
|
const VsyncId& aCompositeStartId,
|
||||||
TimeStamp& aCompositeStart,
|
TimeStamp& aCompositeStart,
|
||||||
TimeStamp& aRenderStart, TimeStamp& aCompositeEnd,
|
TimeStamp& aRenderStart, TimeStamp& aCompositeEnd,
|
||||||
wr::RendererStats* aStats = nullptr);
|
wr::RendererStats* aStats = nullptr);
|
||||||
|
@ -393,8 +392,7 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
|
||||||
/**
|
/**
|
||||||
* Notify the compositor for the given layer tree that vsync has occurred.
|
* Notify the compositor for the given layer tree that vsync has occurred.
|
||||||
*/
|
*/
|
||||||
static void NotifyVsync(const TimeStamp& aTimeStamp,
|
static void NotifyVsync(const VsyncEvent& aVsync, const LayersId& aLayersId);
|
||||||
const LayersId& aLayersId);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set aController as the pan/zoom callback for the subtree referred
|
* Set aController as the pan/zoom callback for the subtree referred
|
||||||
|
@ -595,7 +593,7 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
|
||||||
// CompositorVsyncSchedulerOwner
|
// CompositorVsyncSchedulerOwner
|
||||||
bool IsPendingComposite() override;
|
bool IsPendingComposite() override;
|
||||||
void FinishPendingComposite() override;
|
void FinishPendingComposite() override;
|
||||||
void CompositeToTarget(gfx::DrawTarget* aTarget,
|
void CompositeToTarget(VsyncId aId, gfx::DrawTarget* aTarget,
|
||||||
const gfx::IntRect* aRect = nullptr) override;
|
const gfx::IntRect* aRect = nullptr) override;
|
||||||
|
|
||||||
bool InitializeAdvancedLayers(const nsTArray<LayersBackend>& aBackendHints,
|
bool InitializeAdvancedLayers(const nsTArray<LayersBackend>& aBackendHints,
|
||||||
|
@ -628,11 +626,10 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
|
||||||
*/
|
*/
|
||||||
bool CanComposite();
|
bool CanComposite();
|
||||||
|
|
||||||
void DidComposite(LayersId aId, TimeStamp& aCompositeStart,
|
void DidComposite(const VsyncId& aId, TimeStamp& aCompositeStart,
|
||||||
TimeStamp& aCompositeEnd) override;
|
TimeStamp& aCompositeEnd);
|
||||||
void DidComposite(TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd);
|
|
||||||
|
|
||||||
void NotifyDidComposite(TransactionId aTransactionId,
|
void NotifyDidComposite(TransactionId aTransactionId, VsyncId aId,
|
||||||
TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd);
|
TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd);
|
||||||
|
|
||||||
// The indirect layer tree lock must be held before calling this function.
|
// The indirect layer tree lock must be held before calling this function.
|
||||||
|
|
|
@ -48,13 +48,12 @@ CompositorVsyncScheduler::Observer::Observer(CompositorVsyncScheduler* aOwner)
|
||||||
|
|
||||||
CompositorVsyncScheduler::Observer::~Observer() { MOZ_ASSERT(!mOwner); }
|
CompositorVsyncScheduler::Observer::~Observer() { MOZ_ASSERT(!mOwner); }
|
||||||
|
|
||||||
bool CompositorVsyncScheduler::Observer::NotifyVsync(
|
bool CompositorVsyncScheduler::Observer::NotifyVsync(const VsyncEvent& aVsync) {
|
||||||
TimeStamp aVsyncTimestamp) {
|
|
||||||
MutexAutoLock lock(mMutex);
|
MutexAutoLock lock(mMutex);
|
||||||
if (!mOwner) {
|
if (!mOwner) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return mOwner->NotifyVsync(aVsyncTimestamp);
|
return mOwner->NotifyVsync(aVsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompositorVsyncScheduler::Observer::Destroy() {
|
void CompositorVsyncScheduler::Observer::Destroy() {
|
||||||
|
@ -107,12 +106,13 @@ void CompositorVsyncScheduler::Destroy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompositorVsyncScheduler::PostCompositeTask(
|
void CompositorVsyncScheduler::PostCompositeTask(
|
||||||
TimeStamp aCompositeTimestamp) {
|
VsyncId aId, TimeStamp aCompositeTimestamp) {
|
||||||
MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
|
MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
|
||||||
if (mCurrentCompositeTask == nullptr && CompositorThreadHolder::Loop()) {
|
if (mCurrentCompositeTask == nullptr && CompositorThreadHolder::Loop()) {
|
||||||
RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod<TimeStamp>(
|
RefPtr<CancelableRunnable> task =
|
||||||
"layers::CompositorVsyncScheduler::Composite", this,
|
NewCancelableRunnableMethod<VsyncId, TimeStamp>(
|
||||||
&CompositorVsyncScheduler::Composite, aCompositeTimestamp);
|
"layers::CompositorVsyncScheduler::Composite", this,
|
||||||
|
&CompositorVsyncScheduler::Composite, aId, aCompositeTimestamp);
|
||||||
mCurrentCompositeTask = task;
|
mCurrentCompositeTask = task;
|
||||||
ScheduleTask(task.forget());
|
ScheduleTask(task.forget());
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ void CompositorVsyncScheduler::ScheduleComposition() {
|
||||||
if (mAsapScheduling) {
|
if (mAsapScheduling) {
|
||||||
// Used only for performance testing purposes, and when recording/replaying
|
// Used only for performance testing purposes, and when recording/replaying
|
||||||
// to ensure that graphics are up to date.
|
// to ensure that graphics are up to date.
|
||||||
PostCompositeTask(TimeStamp::Now());
|
PostCompositeTask(VsyncId(), TimeStamp::Now());
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
} else if (mIsObservingVsync && mCompositeRequestedAt &&
|
} else if (mIsObservingVsync && mCompositeRequestedAt &&
|
||||||
(TimeStamp::Now() - mCompositeRequestedAt) >=
|
(TimeStamp::Now() - mCompositeRequestedAt) >=
|
||||||
|
@ -150,7 +150,7 @@ void CompositorVsyncScheduler::ScheduleComposition() {
|
||||||
// wait for the vsync. Note that this should only ever happen on Fennec
|
// wait for the vsync. Note that this should only ever happen on Fennec
|
||||||
// because there content runs in the same process as the compositor, and so
|
// because there content runs in the same process as the compositor, and so
|
||||||
// content can actually block the main thread in this process.
|
// content can actually block the main thread in this process.
|
||||||
PostCompositeTask(TimeStamp::Now());
|
PostCompositeTask(VsyncId(), TimeStamp::Now());
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if (!mCompositeRequestedAt) {
|
if (!mCompositeRequestedAt) {
|
||||||
|
@ -162,12 +162,12 @@ void CompositorVsyncScheduler::ScheduleComposition() {
|
||||||
// through the main thread of the UI process. It's possible that
|
// through the main thread of the UI process. It's possible that
|
||||||
// we're blocking there waiting on a composite, so schedule an initial
|
// we're blocking there waiting on a composite, so schedule an initial
|
||||||
// one now to get things started.
|
// one now to get things started.
|
||||||
PostCompositeTask(TimeStamp::Now());
|
PostCompositeTask(VsyncId(), TimeStamp::Now());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CompositorVsyncScheduler::NotifyVsync(TimeStamp aVsyncTimestamp) {
|
bool CompositorVsyncScheduler::NotifyVsync(const VsyncEvent& aVsync) {
|
||||||
// Called from the vsync dispatch thread. When in the GPU Process, that's
|
// Called from the vsync dispatch thread. When in the GPU Process, that's
|
||||||
// the same as the compositor thread.
|
// the same as the compositor thread.
|
||||||
MOZ_ASSERT_IF(XRE_IsParentProcess(),
|
MOZ_ASSERT_IF(XRE_IsParentProcess(),
|
||||||
|
@ -175,8 +175,8 @@ bool CompositorVsyncScheduler::NotifyVsync(TimeStamp aVsyncTimestamp) {
|
||||||
MOZ_ASSERT_IF(XRE_GetProcessType() == GeckoProcessType_GPU,
|
MOZ_ASSERT_IF(XRE_GetProcessType() == GeckoProcessType_GPU,
|
||||||
CompositorThreadHolder::IsInCompositorThread());
|
CompositorThreadHolder::IsInCompositorThread());
|
||||||
MOZ_ASSERT(!NS_IsMainThread());
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
PostCompositeTask(aVsyncTimestamp);
|
PostCompositeTask(aVsync.mId, aVsync.mTime);
|
||||||
PostVRTask(aVsyncTimestamp);
|
PostVRTask(aVsync.mTime);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +190,8 @@ void CompositorVsyncScheduler::CancelCurrentCompositeTask() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompositorVsyncScheduler::Composite(TimeStamp aVsyncTimestamp) {
|
void CompositorVsyncScheduler::Composite(VsyncId aId,
|
||||||
|
TimeStamp aVsyncTimestamp) {
|
||||||
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
||||||
MOZ_ASSERT(mVsyncSchedulerOwner);
|
MOZ_ASSERT(mVsyncSchedulerOwner);
|
||||||
|
|
||||||
|
@ -221,7 +222,7 @@ void CompositorVsyncScheduler::Composite(TimeStamp aVsyncTimestamp) {
|
||||||
mLastCompose = aVsyncTimestamp;
|
mLastCompose = aVsyncTimestamp;
|
||||||
|
|
||||||
// Tell the owner to do a composite
|
// Tell the owner to do a composite
|
||||||
mVsyncSchedulerOwner->CompositeToTarget(nullptr, nullptr);
|
mVsyncSchedulerOwner->CompositeToTarget(aId, nullptr, nullptr);
|
||||||
|
|
||||||
mVsyncNotificationsSkipped = 0;
|
mVsyncNotificationsSkipped = 0;
|
||||||
|
|
||||||
|
@ -257,7 +258,7 @@ void CompositorVsyncScheduler::ForceComposeToTarget(gfx::DrawTarget* aTarget,
|
||||||
|
|
||||||
mLastCompose = TimeStamp::Now();
|
mLastCompose = TimeStamp::Now();
|
||||||
MOZ_ASSERT(mVsyncSchedulerOwner);
|
MOZ_ASSERT(mVsyncSchedulerOwner);
|
||||||
mVsyncSchedulerOwner->CompositeToTarget(aTarget, aRect);
|
mVsyncSchedulerOwner->CompositeToTarget(VsyncId(), aTarget, aRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CompositorVsyncScheduler::NeedsComposite() {
|
bool CompositorVsyncScheduler::NeedsComposite() {
|
||||||
|
|
|
@ -48,7 +48,7 @@ class CompositorVsyncScheduler {
|
||||||
* Notify this class of a vsync. This will trigger a composite if one is
|
* Notify this class of a vsync. This will trigger a composite if one is
|
||||||
* needed. This must be called from the vsync dispatch thread.
|
* needed. This must be called from the vsync dispatch thread.
|
||||||
*/
|
*/
|
||||||
bool NotifyVsync(TimeStamp aVsyncTimestamp);
|
bool NotifyVsync(const VsyncEvent& aVsync);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do cleanup. This must be called on the compositor thread.
|
* Do cleanup. This must be called on the compositor thread.
|
||||||
|
@ -108,7 +108,7 @@ class CompositorVsyncScheduler {
|
||||||
|
|
||||||
// Post a task to run Composite() on the compositor thread, if there isn't
|
// Post a task to run Composite() on the compositor thread, if there isn't
|
||||||
// such a task already queued. Can be called from any thread.
|
// such a task already queued. Can be called from any thread.
|
||||||
void PostCompositeTask(TimeStamp aCompositeTimestamp);
|
void PostCompositeTask(VsyncId aId, TimeStamp aCompositeTimestamp);
|
||||||
|
|
||||||
// Post a task to run DispatchVREvents() on the VR thread, if there isn't
|
// Post a task to run DispatchVREvents() on the VR thread, if there isn't
|
||||||
// such a task already queued. Can be called from any thread.
|
// such a task already queued. Can be called from any thread.
|
||||||
|
@ -116,7 +116,7 @@ class CompositorVsyncScheduler {
|
||||||
|
|
||||||
// This gets run at vsync time and "does" a composite (which really means
|
// This gets run at vsync time and "does" a composite (which really means
|
||||||
// update internal state and call the owner to do the composite).
|
// update internal state and call the owner to do the composite).
|
||||||
void Composite(TimeStamp aVsyncTimestamp);
|
void Composite(VsyncId aId, TimeStamp aVsyncTimestamp);
|
||||||
|
|
||||||
void ObserveVsync();
|
void ObserveVsync();
|
||||||
void UnobserveVsync();
|
void UnobserveVsync();
|
||||||
|
@ -126,7 +126,7 @@ class CompositorVsyncScheduler {
|
||||||
class Observer final : public VsyncObserver {
|
class Observer final : public VsyncObserver {
|
||||||
public:
|
public:
|
||||||
explicit Observer(CompositorVsyncScheduler* aOwner);
|
explicit Observer(CompositorVsyncScheduler* aOwner);
|
||||||
virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) override;
|
virtual bool NotifyVsync(const VsyncEvent& aVsync) override;
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#ifndef mozilla_layers_CompositorVsyncSchedulerOwner_h
|
#ifndef mozilla_layers_CompositorVsyncSchedulerOwner_h
|
||||||
#define mozilla_layers_CompositorVsyncSchedulerOwner_h
|
#define mozilla_layers_CompositorVsyncSchedulerOwner_h
|
||||||
|
|
||||||
|
#include "mozilla/VsyncDispatcher.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
namespace gfx {
|
namespace gfx {
|
||||||
|
@ -19,7 +21,7 @@ class CompositorVsyncSchedulerOwner {
|
||||||
public:
|
public:
|
||||||
virtual bool IsPendingComposite() = 0;
|
virtual bool IsPendingComposite() = 0;
|
||||||
virtual void FinishPendingComposite() = 0;
|
virtual void FinishPendingComposite() = 0;
|
||||||
virtual void CompositeToTarget(gfx::DrawTarget* aTarget,
|
virtual void CompositeToTarget(VsyncId aId, gfx::DrawTarget* aTarget,
|
||||||
const gfx::IntRect* aRect = nullptr) = 0;
|
const gfx::IntRect* aRect = nullptr) = 0;
|
||||||
virtual TimeDuration GetVsyncInterval() const = 0;
|
virtual TimeDuration GetVsyncInterval() const = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -389,22 +389,18 @@ void CrossProcessCompositorBridgeParent::ShadowLayersUpdated(
|
||||||
static_cast<uint32_t>(
|
static_cast<uint32_t>(
|
||||||
(endTime - aInfo.transactionStart()).ToMilliseconds()));
|
(endTime - aInfo.transactionStart()).ToMilliseconds()));
|
||||||
|
|
||||||
aLayerTree->SetPendingTransactionId(aInfo.id(), aInfo.refreshStart(),
|
aLayerTree->SetPendingTransactionId(
|
||||||
aInfo.transactionStart(), aInfo.url(),
|
aInfo.id(), aInfo.vsyncId(), aInfo.refreshStart(),
|
||||||
aInfo.fwdTime());
|
aInfo.transactionStart(), aInfo.url(), aInfo.fwdTime());
|
||||||
}
|
|
||||||
|
|
||||||
void CrossProcessCompositorBridgeParent::DidComposite(
|
|
||||||
LayersId aId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd) {
|
|
||||||
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
||||||
DidCompositeLocked(aId, aCompositeStart, aCompositeEnd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrossProcessCompositorBridgeParent::DidCompositeLocked(
|
void CrossProcessCompositorBridgeParent::DidCompositeLocked(
|
||||||
LayersId aId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd) {
|
LayersId aId, const VsyncId& aVsyncId, TimeStamp& aCompositeStart,
|
||||||
|
TimeStamp& aCompositeEnd) {
|
||||||
sIndirectLayerTreesLock->AssertCurrentThreadOwns();
|
sIndirectLayerTreesLock->AssertCurrentThreadOwns();
|
||||||
if (LayerTransactionParent* layerTree = sIndirectLayerTrees[aId].mLayerTree) {
|
if (LayerTransactionParent* layerTree = sIndirectLayerTrees[aId].mLayerTree) {
|
||||||
TransactionId transactionId = layerTree->FlushTransactionId(aCompositeEnd);
|
TransactionId transactionId =
|
||||||
|
layerTree->FlushTransactionId(aVsyncId, aCompositeEnd);
|
||||||
if (transactionId.IsValid()) {
|
if (transactionId.IsValid()) {
|
||||||
Unused << SendDidComposite(aId, transactionId, aCompositeStart,
|
Unused << SendDidComposite(aId, transactionId, aCompositeStart,
|
||||||
aCompositeEnd);
|
aCompositeEnd);
|
||||||
|
|
|
@ -137,10 +137,8 @@ class CrossProcessCompositorBridgeParent final
|
||||||
// Use DidCompositeLocked if you already hold a lock on
|
// Use DidCompositeLocked if you already hold a lock on
|
||||||
// sIndirectLayerTreesLock; Otherwise use DidComposite, which would request
|
// sIndirectLayerTreesLock; Otherwise use DidComposite, which would request
|
||||||
// the lock automatically.
|
// the lock automatically.
|
||||||
void DidCompositeLocked(LayersId aId, TimeStamp& aCompositeStart,
|
void DidCompositeLocked(LayersId aId, const VsyncId& aVsyncId,
|
||||||
TimeStamp& aCompositeEnd);
|
TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd);
|
||||||
void DidComposite(LayersId aId, TimeStamp& aCompositeStart,
|
|
||||||
TimeStamp& aCompositeEnd) override;
|
|
||||||
|
|
||||||
PTextureParent* AllocPTextureParent(
|
PTextureParent* AllocPTextureParent(
|
||||||
const SurfaceDescriptor& aSharedData, const ReadLockDescriptor& aReadLock,
|
const SurfaceDescriptor& aSharedData, const ReadLockDescriptor& aReadLock,
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
#include "mozilla/layers/TextureHost.h"
|
#include "mozilla/layers/TextureHost.h"
|
||||||
#include "mozilla/layers/AsyncCompositionManager.h"
|
#include "mozilla/layers/AsyncCompositionManager.h"
|
||||||
|
|
||||||
|
using mozilla::Telemetry::LABELS_CONTENT_FRAME_TIME_REASON;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
|
@ -884,12 +886,49 @@ bool LayerTransactionParent::IsSameProcess() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
TransactionId LayerTransactionParent::FlushTransactionId(
|
TransactionId LayerTransactionParent::FlushTransactionId(
|
||||||
TimeStamp& aCompositeEnd) {
|
const VsyncId& aId, TimeStamp& aCompositeEnd) {
|
||||||
if (mId.IsValid() && mPendingTransaction.IsValid() && !mVsyncRate.IsZero()) {
|
if (mId.IsValid() && mPendingTransaction.IsValid() && !mVsyncRate.IsZero()) {
|
||||||
double latencyMs = (aCompositeEnd - mTxnStartTime).ToMilliseconds();
|
double latencyMs = (aCompositeEnd - mTxnStartTime).ToMilliseconds();
|
||||||
double latencyNorm = latencyMs / mVsyncRate.ToMilliseconds();
|
double latencyNorm = latencyMs / mVsyncRate.ToMilliseconds();
|
||||||
int32_t fracLatencyNorm = lround(latencyNorm * 100.0);
|
int32_t fracLatencyNorm = lround(latencyNorm * 100.0);
|
||||||
Telemetry::Accumulate(Telemetry::CONTENT_FRAME_TIME, fracLatencyNorm);
|
Telemetry::Accumulate(Telemetry::CONTENT_FRAME_TIME, fracLatencyNorm);
|
||||||
|
|
||||||
|
// Record CONTENT_FRAME_TIME_REASON. See
|
||||||
|
// WebRenderBridgeParent::FlushTransactionIdsForEpoch for more details.
|
||||||
|
//
|
||||||
|
// Note that deseralizing a layers update (RecvUpdate) can delay the receipt
|
||||||
|
// of the composite vsync message
|
||||||
|
// (CompositorBridgeParent::CompositeToTarget), since they're using the same
|
||||||
|
// thread. This can mean that compositing might start significantly late,
|
||||||
|
// but this code will still detect it as having successfully started on the
|
||||||
|
// right vsync (which is somewhat correct). We'd now have reduced time left
|
||||||
|
// in the vsync interval to finish compositing, so the chances of a missed
|
||||||
|
// frame increases. This is effectively including the RecvUpdate work as
|
||||||
|
// part of the 'compositing' phase for this metric, but it isn't included in
|
||||||
|
// COMPOSITE_TIME, and *is* included in CONTENT_FULL_PAINT_TIME.
|
||||||
|
latencyMs = (aCompositeEnd - mRefreshStartTime).ToMilliseconds();
|
||||||
|
latencyNorm = latencyMs / mVsyncRate.ToMilliseconds();
|
||||||
|
fracLatencyNorm = lround(latencyNorm * 100.0);
|
||||||
|
if (fracLatencyNorm < 200) {
|
||||||
|
// Success
|
||||||
|
Telemetry::AccumulateCategorical(
|
||||||
|
LABELS_CONTENT_FRAME_TIME_REASON::OnTime);
|
||||||
|
} else {
|
||||||
|
if (mTxnVsyncId == VsyncId() || aId == VsyncId() || mTxnVsyncId >= aId) {
|
||||||
|
// Vsync ids are nonsensical, possibly something got trigged from
|
||||||
|
// outside vsync?
|
||||||
|
Telemetry::AccumulateCategorical(
|
||||||
|
LABELS_CONTENT_FRAME_TIME_REASON::NoVsync);
|
||||||
|
} else if (aId - mTxnVsyncId > 1) {
|
||||||
|
// Composite started late (and maybe took too long as well)
|
||||||
|
Telemetry::AccumulateCategorical(
|
||||||
|
LABELS_CONTENT_FRAME_TIME_REASON::MissedComposite);
|
||||||
|
} else {
|
||||||
|
// Composite start on time, but must have taken too long.
|
||||||
|
Telemetry::AccumulateCategorical(
|
||||||
|
LABELS_CONTENT_FRAME_TIME_REASON::SlowComposite);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(ENABLE_FRAME_LATENCY_LOG)
|
#if defined(ENABLE_FRAME_LATENCY_LOG)
|
||||||
|
|
|
@ -72,18 +72,20 @@ class LayerTransactionParent final : public PLayerTransactionParent,
|
||||||
bool IsSameProcess() const override;
|
bool IsSameProcess() const override;
|
||||||
|
|
||||||
const TransactionId& GetPendingTransactionId() { return mPendingTransaction; }
|
const TransactionId& GetPendingTransactionId() { return mPendingTransaction; }
|
||||||
void SetPendingTransactionId(TransactionId aId,
|
void SetPendingTransactionId(TransactionId aId, const VsyncId& aVsyncId,
|
||||||
const TimeStamp& aRefreshStartTime,
|
const TimeStamp& aRefreshStartTime,
|
||||||
const TimeStamp& aTxnStartTime,
|
const TimeStamp& aTxnStartTime,
|
||||||
const nsCString& aURL,
|
const nsCString& aURL,
|
||||||
const TimeStamp& aFwdTime) {
|
const TimeStamp& aFwdTime) {
|
||||||
mPendingTransaction = aId;
|
mPendingTransaction = aId;
|
||||||
|
mTxnVsyncId = aVsyncId;
|
||||||
mRefreshStartTime = aRefreshStartTime;
|
mRefreshStartTime = aRefreshStartTime;
|
||||||
mTxnStartTime = aTxnStartTime;
|
mTxnStartTime = aTxnStartTime;
|
||||||
mTxnURL = aURL;
|
mTxnURL = aURL;
|
||||||
mFwdTime = aFwdTime;
|
mFwdTime = aFwdTime;
|
||||||
}
|
}
|
||||||
TransactionId FlushTransactionId(TimeStamp& aCompositeEnd);
|
TransactionId FlushTransactionId(const VsyncId& aId,
|
||||||
|
TimeStamp& aCompositeEnd);
|
||||||
|
|
||||||
// CompositableParentManager
|
// CompositableParentManager
|
||||||
void SendAsyncMessage(
|
void SendAsyncMessage(
|
||||||
|
@ -202,6 +204,7 @@ class LayerTransactionParent final : public PLayerTransactionParent,
|
||||||
TimeDuration mVsyncRate;
|
TimeDuration mVsyncRate;
|
||||||
|
|
||||||
TransactionId mPendingTransaction;
|
TransactionId mPendingTransaction;
|
||||||
|
VsyncId mTxnVsyncId;
|
||||||
TimeStamp mRefreshStartTime;
|
TimeStamp mRefreshStartTime;
|
||||||
TimeStamp mTxnStartTime;
|
TimeStamp mTxnStartTime;
|
||||||
TimeStamp mFwdTime;
|
TimeStamp mFwdTime;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "mozilla/layers/LayersTypes.h"
|
#include "mozilla/layers/LayersTypes.h"
|
||||||
#include "mozilla/layers/RefCountedShmem.h"
|
#include "mozilla/layers/RefCountedShmem.h"
|
||||||
#include "mozilla/layers/RepaintRequest.h"
|
#include "mozilla/layers/RepaintRequest.h"
|
||||||
|
#include "VsyncSource.h"
|
||||||
#include "mozilla/Move.h"
|
#include "mozilla/Move.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -38,9 +39,28 @@ template <>
|
||||||
struct ParamTraits<mozilla::layers::LayersId>
|
struct ParamTraits<mozilla::layers::LayersId>
|
||||||
: public PlainOldDataSerializer<mozilla::layers::LayersId> {};
|
: public PlainOldDataSerializer<mozilla::layers::LayersId> {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct ParamTraits<mozilla::layers::BaseTransactionId<T>>
|
||||||
|
: public PlainOldDataSerializer<mozilla::layers::BaseTransactionId<T>> {};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct ParamTraits<mozilla::layers::TransactionId>
|
struct ParamTraits<mozilla::VsyncId>
|
||||||
: public PlainOldDataSerializer<mozilla::layers::TransactionId> {};
|
: public PlainOldDataSerializer<mozilla::VsyncId> {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ParamTraits<mozilla::VsyncEvent> {
|
||||||
|
typedef mozilla::VsyncEvent paramType;
|
||||||
|
|
||||||
|
static void Write(Message* msg, const paramType& param) {
|
||||||
|
WriteParam(msg, param.mId);
|
||||||
|
WriteParam(msg, param.mTime);
|
||||||
|
}
|
||||||
|
static bool Read(const Message* msg, PickleIterator* iter,
|
||||||
|
paramType* result) {
|
||||||
|
return ReadParam(msg, iter, &result->mId) &&
|
||||||
|
ReadParam(msg, iter, &result->mTime);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct ParamTraits<mozilla::layers::LayersObserverEpoch>
|
struct ParamTraits<mozilla::layers::LayersObserverEpoch>
|
||||||
|
|
|
@ -52,6 +52,7 @@ using mozilla::CrossProcessSemaphoreHandle from "mozilla/ipc/CrossProcessSemapho
|
||||||
using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
|
using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
|
||||||
using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h";
|
using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h";
|
||||||
using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
|
using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
|
||||||
|
using mozilla::VsyncId from "mozilla/VsyncDispatcher.h";
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
@ -554,6 +555,7 @@ struct TransactionInfo
|
||||||
bool scheduleComposite;
|
bool scheduleComposite;
|
||||||
uint32_t paintSequenceNumber;
|
uint32_t paintSequenceNumber;
|
||||||
bool isRepeatTransaction;
|
bool isRepeatTransaction;
|
||||||
|
VsyncId vsyncId;
|
||||||
TimeStamp refreshStart;
|
TimeStamp refreshStart;
|
||||||
TimeStamp transactionStart;
|
TimeStamp transactionStart;
|
||||||
nsCString url;
|
nsCString url;
|
||||||
|
|
|
@ -28,6 +28,7 @@ using mozilla::layers::WebRenderScrollData from "mozilla/layers/WebRenderScrollD
|
||||||
using mozilla::layers::FocusTarget from "mozilla/layers/FocusTarget.h";
|
using mozilla::layers::FocusTarget from "mozilla/layers/FocusTarget.h";
|
||||||
using mozilla::layers::LayersObserverEpoch from "mozilla/layers/LayersTypes.h";
|
using mozilla::layers::LayersObserverEpoch from "mozilla/layers/LayersTypes.h";
|
||||||
using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
|
using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
|
||||||
|
using mozilla::VsyncId from "mozilla/VsyncDispatcher.h";
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
@ -48,11 +49,11 @@ parent:
|
||||||
LayoutSize aContentSize, ByteBuf aDL, BuiltDisplayListDescriptor aDLDesc,
|
LayoutSize aContentSize, ByteBuf aDL, BuiltDisplayListDescriptor aDLDesc,
|
||||||
WebRenderScrollData aScrollData,
|
WebRenderScrollData aScrollData,
|
||||||
OpUpdateResource[] aResourceUpdates, RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems,
|
OpUpdateResource[] aResourceUpdates, RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems,
|
||||||
IdNamespace aIdNamespace, bool containsSVGGroup, TimeStamp refreshStartTime, TimeStamp txnStartTime, nsCString txnURL, TimeStamp fwdTime);
|
IdNamespace aIdNamespace, bool containsSVGGroup, VsyncId vsyncId, TimeStamp refreshStartTime, TimeStamp txnStartTime, nsCString txnURL, TimeStamp fwdTime);
|
||||||
async EmptyTransaction(FocusTarget focusTarget, ScrollUpdatesMap scrollUpdates, uint32_t aPaintSequenceNumber,
|
async EmptyTransaction(FocusTarget focusTarget, ScrollUpdatesMap scrollUpdates, uint32_t aPaintSequenceNumber,
|
||||||
WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, TransactionId transactionId,
|
WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, TransactionId transactionId,
|
||||||
OpUpdateResource[] aResourceUpdates, RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems,
|
OpUpdateResource[] aResourceUpdates, RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems,
|
||||||
IdNamespace aIdNamespace, TimeStamp refreshStartTime, TimeStamp txnStartTime, nsCString txnURL, TimeStamp fwdTime);
|
IdNamespace aIdNamespace, VsyncId vsyncId, TimeStamp refreshStartTime, TimeStamp txnStartTime, nsCString txnURL, TimeStamp fwdTime);
|
||||||
async SetFocusTarget(FocusTarget focusTarget);
|
async SetFocusTarget(FocusTarget focusTarget);
|
||||||
async UpdateResources(OpUpdateResource[] aResourceUpdates, RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems);
|
async UpdateResources(OpUpdateResource[] aResourceUpdates, RefCountedShmem[] aSmallShmems, Shmem[] aLargeShmems);
|
||||||
async ParentCommands(WebRenderParentCommand[] commands);
|
async ParentCommands(WebRenderParentCommand[] commands);
|
||||||
|
|
|
@ -528,7 +528,8 @@ void ShadowLayerForwarder::SendPaintTime(TransactionId aId,
|
||||||
bool ShadowLayerForwarder::EndTransaction(
|
bool ShadowLayerForwarder::EndTransaction(
|
||||||
const nsIntRegion& aRegionToClear, TransactionId aId,
|
const nsIntRegion& aRegionToClear, TransactionId aId,
|
||||||
bool aScheduleComposite, uint32_t aPaintSequenceNumber,
|
bool aScheduleComposite, uint32_t aPaintSequenceNumber,
|
||||||
bool aIsRepeatTransaction, const mozilla::TimeStamp& aRefreshStart,
|
bool aIsRepeatTransaction, const mozilla::VsyncId& aVsyncId,
|
||||||
|
const mozilla::TimeStamp& aRefreshStart,
|
||||||
const mozilla::TimeStamp& aTransactionStart, const nsCString& aURL,
|
const mozilla::TimeStamp& aTransactionStart, const nsCString& aURL,
|
||||||
bool* aSent) {
|
bool* aSent) {
|
||||||
*aSent = false;
|
*aSent = false;
|
||||||
|
@ -670,6 +671,7 @@ bool ShadowLayerForwarder::EndTransaction(
|
||||||
info.scheduleComposite() = aScheduleComposite;
|
info.scheduleComposite() = aScheduleComposite;
|
||||||
info.paintSequenceNumber() = aPaintSequenceNumber;
|
info.paintSequenceNumber() = aPaintSequenceNumber;
|
||||||
info.isRepeatTransaction() = aIsRepeatTransaction;
|
info.isRepeatTransaction() = aIsRepeatTransaction;
|
||||||
|
info.vsyncId() = aVsyncId;
|
||||||
info.refreshStart() = aRefreshStart;
|
info.refreshStart() = aRefreshStart;
|
||||||
info.transactionStart() = aTransactionStart;
|
info.transactionStart() = aTransactionStart;
|
||||||
info.url() = aURL;
|
info.url() = aURL;
|
||||||
|
|
|
@ -252,6 +252,7 @@ class ShadowLayerForwarder final : public LayersIPCActor,
|
||||||
bool EndTransaction(const nsIntRegion& aRegionToClear, TransactionId aId,
|
bool EndTransaction(const nsIntRegion& aRegionToClear, TransactionId aId,
|
||||||
bool aScheduleComposite, uint32_t aPaintSequenceNumber,
|
bool aScheduleComposite, uint32_t aPaintSequenceNumber,
|
||||||
bool aIsRepeatTransaction,
|
bool aIsRepeatTransaction,
|
||||||
|
const mozilla::VsyncId& aVsyncId,
|
||||||
const mozilla::TimeStamp& aRefreshStart,
|
const mozilla::TimeStamp& aRefreshStart,
|
||||||
const mozilla::TimeStamp& aTransactionStart,
|
const mozilla::TimeStamp& aTransactionStart,
|
||||||
const nsCString& aURL, bool* aSent);
|
const nsCString& aURL, bool* aSent);
|
||||||
|
|
|
@ -105,7 +105,8 @@ void WebRenderBridgeChild::EndTransaction(
|
||||||
const wr::LayoutSize& aContentSize, wr::BuiltDisplayList& aDL,
|
const wr::LayoutSize& aContentSize, wr::BuiltDisplayList& aDL,
|
||||||
wr::IpcResourceUpdateQueue& aResources, const gfx::IntSize& aSize,
|
wr::IpcResourceUpdateQueue& aResources, const gfx::IntSize& aSize,
|
||||||
TransactionId aTransactionId, const WebRenderScrollData& aScrollData,
|
TransactionId aTransactionId, const WebRenderScrollData& aScrollData,
|
||||||
bool aContainsSVGGroup, const mozilla::TimeStamp& aRefreshStartTime,
|
bool aContainsSVGGroup, const mozilla::VsyncId& aVsyncId,
|
||||||
|
const mozilla::TimeStamp& aRefreshStartTime,
|
||||||
const mozilla::TimeStamp& aTxnStartTime, const nsCString& aTxnURL) {
|
const mozilla::TimeStamp& aTxnStartTime, const nsCString& aTxnURL) {
|
||||||
MOZ_ASSERT(!mDestroyed);
|
MOZ_ASSERT(!mDestroyed);
|
||||||
MOZ_ASSERT(mIsInTransaction);
|
MOZ_ASSERT(mIsInTransaction);
|
||||||
|
@ -121,11 +122,12 @@ void WebRenderBridgeChild::EndTransaction(
|
||||||
nsTArray<ipc::Shmem> largeShmems;
|
nsTArray<ipc::Shmem> largeShmems;
|
||||||
aResources.Flush(resourceUpdates, smallShmems, largeShmems);
|
aResources.Flush(resourceUpdates, smallShmems, largeShmems);
|
||||||
|
|
||||||
this->SendSetDisplayList(
|
this->SendSetDisplayList(aSize, mParentCommands, mDestroyedActors,
|
||||||
aSize, mParentCommands, mDestroyedActors, GetFwdTransactionId(),
|
GetFwdTransactionId(), aTransactionId, aContentSize,
|
||||||
aTransactionId, aContentSize, dlData, aDL.dl_desc, aScrollData,
|
dlData, aDL.dl_desc, aScrollData, resourceUpdates,
|
||||||
resourceUpdates, smallShmems, largeShmems, mIdNamespace,
|
smallShmems, largeShmems, mIdNamespace,
|
||||||
aContainsSVGGroup, aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime);
|
aContainsSVGGroup, aVsyncId, aRefreshStartTime,
|
||||||
|
aTxnStartTime, aTxnURL, fwdTime);
|
||||||
|
|
||||||
mParentCommands.Clear();
|
mParentCommands.Clear();
|
||||||
mDestroyedActors.Clear();
|
mDestroyedActors.Clear();
|
||||||
|
@ -136,6 +138,7 @@ void WebRenderBridgeChild::EndEmptyTransaction(
|
||||||
const FocusTarget& aFocusTarget, const ScrollUpdatesMap& aUpdates,
|
const FocusTarget& aFocusTarget, const ScrollUpdatesMap& aUpdates,
|
||||||
Maybe<wr::IpcResourceUpdateQueue>& aResources,
|
Maybe<wr::IpcResourceUpdateQueue>& aResources,
|
||||||
uint32_t aPaintSequenceNumber, TransactionId aTransactionId,
|
uint32_t aPaintSequenceNumber, TransactionId aTransactionId,
|
||||||
|
const mozilla::VsyncId& aVsyncId,
|
||||||
const mozilla::TimeStamp& aRefreshStartTime,
|
const mozilla::TimeStamp& aRefreshStartTime,
|
||||||
const mozilla::TimeStamp& aTxnStartTime, const nsCString& aTxnURL) {
|
const mozilla::TimeStamp& aTxnStartTime, const nsCString& aTxnURL) {
|
||||||
MOZ_ASSERT(!mDestroyed);
|
MOZ_ASSERT(!mDestroyed);
|
||||||
|
@ -154,8 +157,8 @@ void WebRenderBridgeChild::EndEmptyTransaction(
|
||||||
this->SendEmptyTransaction(
|
this->SendEmptyTransaction(
|
||||||
aFocusTarget, aUpdates, aPaintSequenceNumber, mParentCommands,
|
aFocusTarget, aUpdates, aPaintSequenceNumber, mParentCommands,
|
||||||
mDestroyedActors, GetFwdTransactionId(), aTransactionId, resourceUpdates,
|
mDestroyedActors, GetFwdTransactionId(), aTransactionId, resourceUpdates,
|
||||||
smallShmems, largeShmems, mIdNamespace, aRefreshStartTime, aTxnStartTime,
|
smallShmems, largeShmems, mIdNamespace, aVsyncId, aRefreshStartTime,
|
||||||
aTxnURL, fwdTime);
|
aTxnStartTime, aTxnURL, fwdTime);
|
||||||
mParentCommands.Clear();
|
mParentCommands.Clear();
|
||||||
mDestroyedActors.Clear();
|
mDestroyedActors.Clear();
|
||||||
mIsInTransaction = false;
|
mIsInTransaction = false;
|
||||||
|
|
|
@ -66,17 +66,21 @@ class WebRenderBridgeChild final : public PWebRenderBridgeChild,
|
||||||
|
|
||||||
void UpdateResources(wr::IpcResourceUpdateQueue& aResources);
|
void UpdateResources(wr::IpcResourceUpdateQueue& aResources);
|
||||||
void BeginTransaction();
|
void BeginTransaction();
|
||||||
void EndTransaction(
|
void EndTransaction(const wr::LayoutSize& aContentSize,
|
||||||
const wr::LayoutSize& aContentSize, wr::BuiltDisplayList& dl,
|
wr::BuiltDisplayList& dl,
|
||||||
wr::IpcResourceUpdateQueue& aResources, const gfx::IntSize& aSize,
|
wr::IpcResourceUpdateQueue& aResources,
|
||||||
TransactionId aTransactionId, const WebRenderScrollData& aScrollData,
|
const gfx::IntSize& aSize, TransactionId aTransactionId,
|
||||||
bool aContainsSVGroup, const mozilla::TimeStamp& aRefreshStartTime,
|
const WebRenderScrollData& aScrollData,
|
||||||
const mozilla::TimeStamp& aTxnStartTime, const nsCString& aTxtURL);
|
bool aContainsSVGroup, const mozilla::VsyncId& aVsyncId,
|
||||||
|
const mozilla::TimeStamp& aRefreshStartTime,
|
||||||
|
const mozilla::TimeStamp& aTxnStartTime,
|
||||||
|
const nsCString& aTxtURL);
|
||||||
void EndEmptyTransaction(const FocusTarget& aFocusTarget,
|
void EndEmptyTransaction(const FocusTarget& aFocusTarget,
|
||||||
const ScrollUpdatesMap& aUpdates,
|
const ScrollUpdatesMap& aUpdates,
|
||||||
Maybe<wr::IpcResourceUpdateQueue>& aResources,
|
Maybe<wr::IpcResourceUpdateQueue>& aResources,
|
||||||
uint32_t aPaintSequenceNumber,
|
uint32_t aPaintSequenceNumber,
|
||||||
TransactionId aTransactionId,
|
TransactionId aTransactionId,
|
||||||
|
const mozilla::VsyncId& aVsyncId,
|
||||||
const mozilla::TimeStamp& aRefreshStartTime,
|
const mozilla::TimeStamp& aRefreshStartTime,
|
||||||
const mozilla::TimeStamp& aTxnStartTime,
|
const mozilla::TimeStamp& aTxnStartTime,
|
||||||
const nsCString& aTxtURL);
|
const nsCString& aTxtURL);
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
#include "mozilla/webrender/RenderThread.h"
|
#include "mozilla/webrender/RenderThread.h"
|
||||||
#include "mozilla/widget/CompositorWidget.h"
|
#include "mozilla/widget/CompositorWidget.h"
|
||||||
|
|
||||||
|
using mozilla::Telemetry::LABELS_CONTENT_FRAME_TIME_REASON;
|
||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
#include "ProfilerMarkerPayload.h"
|
#include "ProfilerMarkerPayload.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -854,9 +856,9 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
|
||||||
nsTArray<OpUpdateResource>&& aResourceUpdates,
|
nsTArray<OpUpdateResource>&& aResourceUpdates,
|
||||||
nsTArray<RefCountedShmem>&& aSmallShmems,
|
nsTArray<RefCountedShmem>&& aSmallShmems,
|
||||||
nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace,
|
nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace,
|
||||||
const bool& aContainsSVGGroup, const TimeStamp& aRefreshStartTime,
|
const bool& aContainsSVGGroup, const VsyncId& aVsyncId,
|
||||||
const TimeStamp& aTxnStartTime, const nsCString& aTxnURL,
|
const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime,
|
||||||
const TimeStamp& aFwdTime) {
|
const nsCString& aTxnURL, const TimeStamp& aFwdTime) {
|
||||||
if (mDestroyed) {
|
if (mDestroyed) {
|
||||||
for (const auto& op : aToDestroy) {
|
for (const auto& op : aToDestroy) {
|
||||||
DestroyActor(op);
|
DestroyActor(op);
|
||||||
|
@ -945,7 +947,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
|
||||||
mChildLayersObserverEpoch, true);
|
mChildLayersObserverEpoch, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
HoldPendingTransactionId(wrEpoch, aTransactionId, aContainsSVGGroup,
|
HoldPendingTransactionId(wrEpoch, aTransactionId, aContainsSVGGroup, aVsyncId,
|
||||||
aRefreshStartTime, aTxnStartTime, aTxnURL, aFwdTime,
|
aRefreshStartTime, aTxnStartTime, aTxnURL, aFwdTime,
|
||||||
mIsFirstPaint);
|
mIsFirstPaint);
|
||||||
mIsFirstPaint = false;
|
mIsFirstPaint = false;
|
||||||
|
@ -955,7 +957,8 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
|
||||||
// though DisplayList was not pushed to webrender.
|
// though DisplayList was not pushed to webrender.
|
||||||
if (CompositorBridgeParent* cbp = GetRootCompositorBridgeParent()) {
|
if (CompositorBridgeParent* cbp = GetRootCompositorBridgeParent()) {
|
||||||
TimeStamp now = TimeStamp::Now();
|
TimeStamp now = TimeStamp::Now();
|
||||||
cbp->NotifyPipelineRendered(mPipelineId, wrEpoch, now, now, now);
|
cbp->NotifyPipelineRendered(mPipelineId, wrEpoch, VsyncId(), now, now,
|
||||||
|
now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -973,8 +976,9 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEmptyTransaction(
|
||||||
nsTArray<OpUpdateResource>&& aResourceUpdates,
|
nsTArray<OpUpdateResource>&& aResourceUpdates,
|
||||||
nsTArray<RefCountedShmem>&& aSmallShmems,
|
nsTArray<RefCountedShmem>&& aSmallShmems,
|
||||||
nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace,
|
nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace,
|
||||||
const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime,
|
const VsyncId& aVsyncId, const TimeStamp& aRefreshStartTime,
|
||||||
const nsCString& aTxnURL, const TimeStamp& aFwdTime) {
|
const TimeStamp& aTxnStartTime, const nsCString& aTxnURL,
|
||||||
|
const TimeStamp& aFwdTime) {
|
||||||
if (mDestroyed) {
|
if (mDestroyed) {
|
||||||
for (const auto& op : aToDestroy) {
|
for (const auto& op : aToDestroy) {
|
||||||
DestroyActor(op);
|
DestroyActor(op);
|
||||||
|
@ -1058,8 +1062,8 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEmptyTransaction(
|
||||||
|
|
||||||
// Only register a value for CONTENT_FRAME_TIME telemetry if we actually drew
|
// Only register a value for CONTENT_FRAME_TIME telemetry if we actually drew
|
||||||
// something. It is for consistency with disabling WebRender.
|
// something. It is for consistency with disabling WebRender.
|
||||||
HoldPendingTransactionId(mWrEpoch, aTransactionId, false, aRefreshStartTime,
|
HoldPendingTransactionId(mWrEpoch, aTransactionId, false, aVsyncId,
|
||||||
aTxnStartTime, aTxnURL, aFwdTime,
|
aRefreshStartTime, aTxnStartTime, aTxnURL, aFwdTime,
|
||||||
/* aIsFirstPaint */ false,
|
/* aIsFirstPaint */ false,
|
||||||
/* aUseForTelemetry */ scheduleComposite);
|
/* aUseForTelemetry */ scheduleComposite);
|
||||||
|
|
||||||
|
@ -1075,7 +1079,8 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEmptyTransaction(
|
||||||
MOZ_ASSERT(mPendingTransactionIds.size() == 1);
|
MOZ_ASSERT(mPendingTransactionIds.size() == 1);
|
||||||
if (CompositorBridgeParent* cbp = GetRootCompositorBridgeParent()) {
|
if (CompositorBridgeParent* cbp = GetRootCompositorBridgeParent()) {
|
||||||
TimeStamp now = TimeStamp::Now();
|
TimeStamp now = TimeStamp::Now();
|
||||||
cbp->NotifyPipelineRendered(mPipelineId, mWrEpoch, now, now, now);
|
cbp->NotifyPipelineRendered(mPipelineId, mWrEpoch, VsyncId(), now, now,
|
||||||
|
now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1217,7 +1222,7 @@ void WebRenderBridgeParent::FlushFrameGeneration() {
|
||||||
mCompositorScheduler->CancelCurrentCompositeTask();
|
mCompositorScheduler->CancelCurrentCompositeTask();
|
||||||
// Update timestamp of scheduler for APZ and animation.
|
// Update timestamp of scheduler for APZ and animation.
|
||||||
mCompositorScheduler->UpdateLastComposeTime();
|
mCompositorScheduler->UpdateLastComposeTime();
|
||||||
MaybeGenerateFrame(/* aForceGenerateFrame */ true);
|
MaybeGenerateFrame(VsyncId(), /* aForceGenerateFrame */ true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1642,11 +1647,12 @@ bool WebRenderBridgeParent::SampleAnimations(
|
||||||
void WebRenderBridgeParent::CompositeIfNeeded() {
|
void WebRenderBridgeParent::CompositeIfNeeded() {
|
||||||
if (mSkippedComposite) {
|
if (mSkippedComposite) {
|
||||||
mSkippedComposite = false;
|
mSkippedComposite = false;
|
||||||
CompositeToTarget(nullptr, nullptr);
|
CompositeToTarget(VsyncId(), nullptr, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget,
|
void WebRenderBridgeParent::CompositeToTarget(VsyncId aId,
|
||||||
|
gfx::DrawTarget* aTarget,
|
||||||
const gfx::IntRect* aRect) {
|
const gfx::IntRect* aRect) {
|
||||||
// This function should only get called in the root WRBP
|
// This function should only get called in the root WRBP
|
||||||
MOZ_ASSERT(IsRootWebRenderBridgeParent());
|
MOZ_ASSERT(IsRootWebRenderBridgeParent());
|
||||||
|
@ -1677,7 +1683,7 @@ void WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget,
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MaybeGenerateFrame(/* aForceGenerateFrame */ false);
|
MaybeGenerateFrame(aId, /* aForceGenerateFrame */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeDuration WebRenderBridgeParent::GetVsyncInterval() const {
|
TimeDuration WebRenderBridgeParent::GetVsyncInterval() const {
|
||||||
|
@ -1689,7 +1695,8 @@ TimeDuration WebRenderBridgeParent::GetVsyncInterval() const {
|
||||||
return TimeDuration();
|
return TimeDuration();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRenderBridgeParent::MaybeGenerateFrame(bool aForceGenerateFrame) {
|
void WebRenderBridgeParent::MaybeGenerateFrame(VsyncId aId,
|
||||||
|
bool aForceGenerateFrame) {
|
||||||
// This function should only get called in the root WRBP
|
// This function should only get called in the root WRBP
|
||||||
MOZ_ASSERT(IsRootWebRenderBridgeParent());
|
MOZ_ASSERT(IsRootWebRenderBridgeParent());
|
||||||
|
|
||||||
|
@ -1737,7 +1744,7 @@ void WebRenderBridgeParent::MaybeGenerateFrame(bool aForceGenerateFrame) {
|
||||||
|
|
||||||
SetAPZSampleTime();
|
SetAPZSampleTime();
|
||||||
|
|
||||||
wr::RenderThread::Get()->IncPendingFrameCount(mApi->GetId(), start);
|
wr::RenderThread::Get()->IncPendingFrameCount(mApi->GetId(), aId, start);
|
||||||
|
|
||||||
#if defined(ENABLE_FRAME_LATENCY_LOG)
|
#if defined(ENABLE_FRAME_LATENCY_LOG)
|
||||||
auto startTime = TimeStamp::Now();
|
auto startTime = TimeStamp::Now();
|
||||||
|
@ -1751,13 +1758,13 @@ void WebRenderBridgeParent::MaybeGenerateFrame(bool aForceGenerateFrame) {
|
||||||
|
|
||||||
void WebRenderBridgeParent::HoldPendingTransactionId(
|
void WebRenderBridgeParent::HoldPendingTransactionId(
|
||||||
const wr::Epoch& aWrEpoch, TransactionId aTransactionId,
|
const wr::Epoch& aWrEpoch, TransactionId aTransactionId,
|
||||||
bool aContainsSVGGroup, const TimeStamp& aRefreshStartTime,
|
bool aContainsSVGGroup, const VsyncId& aVsyncId,
|
||||||
const TimeStamp& aTxnStartTime, const nsCString& aTxnURL,
|
const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime,
|
||||||
const TimeStamp& aFwdTime, const bool aIsFirstPaint,
|
const nsCString& aTxnURL, const TimeStamp& aFwdTime,
|
||||||
const bool aUseForTelemetry) {
|
const bool aIsFirstPaint, const bool aUseForTelemetry) {
|
||||||
MOZ_ASSERT(aTransactionId > LastPendingTransactionId());
|
MOZ_ASSERT(aTransactionId > LastPendingTransactionId());
|
||||||
mPendingTransactionIds.push_back(PendingTransactionId(
|
mPendingTransactionIds.push_back(PendingTransactionId(
|
||||||
aWrEpoch, aTransactionId, aContainsSVGGroup, aRefreshStartTime,
|
aWrEpoch, aTransactionId, aContainsSVGGroup, aVsyncId, aRefreshStartTime,
|
||||||
aTxnStartTime, aTxnURL, aFwdTime, aIsFirstPaint, aUseForTelemetry));
|
aTxnStartTime, aTxnURL, aFwdTime, aIsFirstPaint, aUseForTelemetry));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1780,10 +1787,10 @@ void WebRenderBridgeParent::NotifySceneBuiltForEpoch(
|
||||||
}
|
}
|
||||||
|
|
||||||
TransactionId WebRenderBridgeParent::FlushTransactionIdsForEpoch(
|
TransactionId WebRenderBridgeParent::FlushTransactionIdsForEpoch(
|
||||||
const wr::Epoch& aEpoch, const TimeStamp& aCompositeStartTime,
|
const wr::Epoch& aEpoch, const VsyncId& aCompositeStartId,
|
||||||
const TimeStamp& aRenderStartTime, const TimeStamp& aEndTime,
|
const TimeStamp& aCompositeStartTime, const TimeStamp& aRenderStartTime,
|
||||||
UiCompositorControllerParent* aUiController, wr::RendererStats* aStats,
|
const TimeStamp& aEndTime, UiCompositorControllerParent* aUiController,
|
||||||
nsTArray<FrameStats>* aOutputStats) {
|
wr::RendererStats* aStats, nsTArray<FrameStats>* aOutputStats) {
|
||||||
TransactionId id{0};
|
TransactionId id{0};
|
||||||
while (!mPendingTransactionIds.empty()) {
|
while (!mPendingTransactionIds.empty()) {
|
||||||
const auto& transactionId = mPendingTransactionIds.front();
|
const auto& transactionId = mPendingTransactionIds.front();
|
||||||
|
@ -1820,6 +1827,50 @@ TransactionId WebRenderBridgeParent::FlushTransactionIdsForEpoch(
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Record CONTENT_FRAME_TIME_REASON.
|
||||||
|
//
|
||||||
|
// This uses the refresh start time (CONTENT_FRAME_TIME uses the start of
|
||||||
|
// display list building), since that includes layout/style time, and 200
|
||||||
|
// should correlate more closely with missing a vsync.
|
||||||
|
//
|
||||||
|
// Also of note is that when the root WebRenderBridgeParent decides to
|
||||||
|
// skip a composite (due to the Renderer being busy), that won't notify
|
||||||
|
// child WebRenderBridgeParents. That failure will show up as the
|
||||||
|
// composite starting late (since it did), but it's really a fault of a
|
||||||
|
// slow composite on the previous frame, not a slow
|
||||||
|
// CONTENT_FULL_PAINT_TIME. It would be nice to have a separate bucket for
|
||||||
|
// this category (scene was ready on the next vsync, but we chose not to
|
||||||
|
// composite), but I can't find a way to locate the right child
|
||||||
|
// WebRenderBridgeParents from the root. WebRender notifies us of the
|
||||||
|
// child pipelines contained within a render, after it finishes, but I
|
||||||
|
// can't see how to query what child pipeline would have been rendered,
|
||||||
|
// when we choose to not do it.
|
||||||
|
latencyMs = (aEndTime - transactionId.mRefreshStartTime).ToMilliseconds();
|
||||||
|
latencyNorm = latencyMs / mVsyncRate.ToMilliseconds();
|
||||||
|
fracLatencyNorm = lround(latencyNorm * 100.0);
|
||||||
|
if (fracLatencyNorm < 200) {
|
||||||
|
// Success
|
||||||
|
Telemetry::AccumulateCategorical(
|
||||||
|
LABELS_CONTENT_FRAME_TIME_REASON::OnTime);
|
||||||
|
} else {
|
||||||
|
if (transactionId.mVsyncId == VsyncId() ||
|
||||||
|
aCompositeStartId == VsyncId() ||
|
||||||
|
transactionId.mVsyncId >= aCompositeStartId) {
|
||||||
|
// Vsync ids are nonsensical, possibly something got trigged from
|
||||||
|
// outside vsync?
|
||||||
|
Telemetry::AccumulateCategorical(
|
||||||
|
LABELS_CONTENT_FRAME_TIME_REASON::NoVsync);
|
||||||
|
} else if (aCompositeStartId - transactionId.mVsyncId > 1) {
|
||||||
|
// Composite started late (and maybe took too long as well)
|
||||||
|
Telemetry::AccumulateCategorical(
|
||||||
|
LABELS_CONTENT_FRAME_TIME_REASON::MissedComposite);
|
||||||
|
} else {
|
||||||
|
// Composite start on time, but must have taken too long.
|
||||||
|
Telemetry::AccumulateCategorical(
|
||||||
|
LABELS_CONTENT_FRAME_TIME_REASON::SlowComposite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (fracLatencyNorm > 200) {
|
if (fracLatencyNorm > 200) {
|
||||||
aOutputStats->AppendElement(FrameStats(
|
aOutputStats->AppendElement(FrameStats(
|
||||||
transactionId.mId, aCompositeStartTime, aRenderStartTime, aEndTime,
|
transactionId.mId, aCompositeStartTime, aRenderStartTime, aEndTime,
|
||||||
|
|
|
@ -102,9 +102,9 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
|
||||||
nsTArray<OpUpdateResource>&& aResourceUpdates,
|
nsTArray<OpUpdateResource>&& aResourceUpdates,
|
||||||
nsTArray<RefCountedShmem>&& aSmallShmems,
|
nsTArray<RefCountedShmem>&& aSmallShmems,
|
||||||
nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace,
|
nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace,
|
||||||
const bool& aContainsSVGGroup, const TimeStamp& aRefreshStartTime,
|
const bool& aContainsSVGGroup, const VsyncId& aVsyncId,
|
||||||
const TimeStamp& aTxnStartTime, const nsCString& aTxnURL,
|
const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime,
|
||||||
const TimeStamp& aFwdTime) override;
|
const nsCString& aTxnURL, const TimeStamp& aFwdTime) override;
|
||||||
mozilla::ipc::IPCResult RecvEmptyTransaction(
|
mozilla::ipc::IPCResult RecvEmptyTransaction(
|
||||||
const FocusTarget& aFocusTarget, const ScrollUpdatesMap& aUpdates,
|
const FocusTarget& aFocusTarget, const ScrollUpdatesMap& aUpdates,
|
||||||
const uint32_t& aPaintSequenceNumber,
|
const uint32_t& aPaintSequenceNumber,
|
||||||
|
@ -114,8 +114,9 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
|
||||||
nsTArray<OpUpdateResource>&& aResourceUpdates,
|
nsTArray<OpUpdateResource>&& aResourceUpdates,
|
||||||
nsTArray<RefCountedShmem>&& aSmallShmems,
|
nsTArray<RefCountedShmem>&& aSmallShmems,
|
||||||
nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace,
|
nsTArray<ipc::Shmem>&& aLargeShmems, const wr::IdNamespace& aIdNamespace,
|
||||||
const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime,
|
const VsyncId& aVsyncId, const TimeStamp& aRefreshStartTime,
|
||||||
const nsCString& aTxnURL, const TimeStamp& aFwdTime) override;
|
const TimeStamp& aTxnStartTime, const nsCString& aTxnURL,
|
||||||
|
const TimeStamp& aFwdTime) override;
|
||||||
mozilla::ipc::IPCResult RecvSetFocusTarget(
|
mozilla::ipc::IPCResult RecvSetFocusTarget(
|
||||||
const FocusTarget& aFocusTarget) override;
|
const FocusTarget& aFocusTarget) override;
|
||||||
mozilla::ipc::IPCResult RecvParentCommands(
|
mozilla::ipc::IPCResult RecvParentCommands(
|
||||||
|
@ -158,7 +159,7 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
|
||||||
// CompositorVsyncSchedulerOwner
|
// CompositorVsyncSchedulerOwner
|
||||||
bool IsPendingComposite() override { return false; }
|
bool IsPendingComposite() override { return false; }
|
||||||
void FinishPendingComposite() override {}
|
void FinishPendingComposite() override {}
|
||||||
void CompositeToTarget(gfx::DrawTarget* aTarget,
|
void CompositeToTarget(VsyncId aId, gfx::DrawTarget* aTarget,
|
||||||
const gfx::IntRect* aRect = nullptr) override;
|
const gfx::IntRect* aRect = nullptr) override;
|
||||||
TimeDuration GetVsyncInterval() const override;
|
TimeDuration GetVsyncInterval() const override;
|
||||||
|
|
||||||
|
@ -174,15 +175,15 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
|
||||||
|
|
||||||
void HoldPendingTransactionId(
|
void HoldPendingTransactionId(
|
||||||
const wr::Epoch& aWrEpoch, TransactionId aTransactionId,
|
const wr::Epoch& aWrEpoch, TransactionId aTransactionId,
|
||||||
bool aContainsSVGGroup, const TimeStamp& aRefreshStartTime,
|
bool aContainsSVGGroup, const VsyncId& aVsyncId,
|
||||||
const TimeStamp& aTxnStartTime, const nsCString& aTxnURL,
|
const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime,
|
||||||
const TimeStamp& aFwdTime, const bool aIsFirstPaint,
|
const nsCString& aTxnURL, const TimeStamp& aFwdTime,
|
||||||
const bool aUseForTelemetry = true);
|
const bool aIsFirstPaint, const bool aUseForTelemetry = true);
|
||||||
TransactionId LastPendingTransactionId();
|
TransactionId LastPendingTransactionId();
|
||||||
TransactionId FlushTransactionIdsForEpoch(
|
TransactionId FlushTransactionIdsForEpoch(
|
||||||
const wr::Epoch& aEpoch, const TimeStamp& aCompositeStartTime,
|
const wr::Epoch& aEpoch, const VsyncId& aCompositeStartId,
|
||||||
const TimeStamp& aRenderStartTime, const TimeStamp& aEndTime,
|
const TimeStamp& aCompositeStartTime, const TimeStamp& aRenderStartTime,
|
||||||
UiCompositorControllerParent* aUiController,
|
const TimeStamp& aEndTime, UiCompositorControllerParent* aUiController,
|
||||||
wr::RendererStats* aStats = nullptr,
|
wr::RendererStats* aStats = nullptr,
|
||||||
nsTArray<FrameStats>* aOutputStats = nullptr);
|
nsTArray<FrameStats>* aOutputStats = nullptr);
|
||||||
void NotifySceneBuiltForEpoch(const wr::Epoch& aEpoch,
|
void NotifySceneBuiltForEpoch(const wr::Epoch& aEpoch,
|
||||||
|
@ -315,18 +316,19 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
|
||||||
void FlushFrameGeneration();
|
void FlushFrameGeneration();
|
||||||
void FlushFramePresentation();
|
void FlushFramePresentation();
|
||||||
|
|
||||||
void MaybeGenerateFrame(bool aForceGenerateFrame);
|
void MaybeGenerateFrame(VsyncId aId, bool aForceGenerateFrame);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct PendingTransactionId {
|
struct PendingTransactionId {
|
||||||
PendingTransactionId(const wr::Epoch& aEpoch, TransactionId aId,
|
PendingTransactionId(const wr::Epoch& aEpoch, TransactionId aId,
|
||||||
bool aContainsSVGGroup,
|
bool aContainsSVGGroup, const VsyncId& aVsyncId,
|
||||||
const TimeStamp& aRefreshStartTime,
|
const TimeStamp& aRefreshStartTime,
|
||||||
const TimeStamp& aTxnStartTime,
|
const TimeStamp& aTxnStartTime,
|
||||||
const nsCString& aTxnURL, const TimeStamp& aFwdTime,
|
const nsCString& aTxnURL, const TimeStamp& aFwdTime,
|
||||||
const bool aIsFirstPaint, const bool aUseForTelemetry)
|
const bool aIsFirstPaint, const bool aUseForTelemetry)
|
||||||
: mEpoch(aEpoch),
|
: mEpoch(aEpoch),
|
||||||
mId(aId),
|
mId(aId),
|
||||||
|
mVsyncId(aVsyncId),
|
||||||
mRefreshStartTime(aRefreshStartTime),
|
mRefreshStartTime(aRefreshStartTime),
|
||||||
mTxnStartTime(aTxnStartTime),
|
mTxnStartTime(aTxnStartTime),
|
||||||
mTxnURL(aTxnURL),
|
mTxnURL(aTxnURL),
|
||||||
|
@ -337,6 +339,7 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
|
||||||
mUseForTelemetry(aUseForTelemetry) {}
|
mUseForTelemetry(aUseForTelemetry) {}
|
||||||
wr::Epoch mEpoch;
|
wr::Epoch mEpoch;
|
||||||
TransactionId mId;
|
TransactionId mId;
|
||||||
|
VsyncId mVsyncId;
|
||||||
TimeStamp mRefreshStartTime;
|
TimeStamp mRefreshStartTime;
|
||||||
TimeStamp mTxnStartTime;
|
TimeStamp mTxnStartTime;
|
||||||
nsCString mTxnURL;
|
nsCString mTxnURL;
|
||||||
|
|
|
@ -232,8 +232,9 @@ bool WebRenderLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags) {
|
||||||
|
|
||||||
WrBridge()->EndEmptyTransaction(mFocusTarget, mPendingScrollUpdates,
|
WrBridge()->EndEmptyTransaction(mFocusTarget, mPendingScrollUpdates,
|
||||||
mAsyncResourceUpdates, mPaintSequenceNumber,
|
mAsyncResourceUpdates, mPaintSequenceNumber,
|
||||||
mLatestTransactionId, refreshStart,
|
mLatestTransactionId,
|
||||||
mTransactionStart, mURL);
|
mTransactionIdAllocator->GetVsyncId(),
|
||||||
|
refreshStart, mTransactionStart, mURL);
|
||||||
ClearPendingScrollInfoUpdate();
|
ClearPendingScrollInfoUpdate();
|
||||||
|
|
||||||
mTransactionStart = TimeStamp();
|
mTransactionStart = TimeStamp();
|
||||||
|
@ -363,8 +364,9 @@ void WebRenderLayerManager::EndTransactionWithoutLayer(
|
||||||
AUTO_PROFILER_TRACING("Paint", "ForwardDPTransaction");
|
AUTO_PROFILER_TRACING("Paint", "ForwardDPTransaction");
|
||||||
WrBridge()->EndTransaction(contentSize, dl, resourceUpdates,
|
WrBridge()->EndTransaction(contentSize, dl, resourceUpdates,
|
||||||
size.ToUnknownSize(), mLatestTransactionId,
|
size.ToUnknownSize(), mLatestTransactionId,
|
||||||
mScrollData, containsSVGGroup, refreshStart,
|
mScrollData, containsSVGGroup,
|
||||||
mTransactionStart, mURL);
|
mTransactionIdAllocator->GetVsyncId(),
|
||||||
|
refreshStart, mTransactionStart, mURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
mTransactionStart = TimeStamp();
|
mTransactionStart = TimeStamp();
|
||||||
|
|
|
@ -30,7 +30,7 @@ class TestVsyncObserver : public VsyncObserver {
|
||||||
TestVsyncObserver()
|
TestVsyncObserver()
|
||||||
: mDidGetVsyncNotification(false), mVsyncMonitor("VsyncMonitor") {}
|
: mDidGetVsyncNotification(false), mVsyncMonitor("VsyncMonitor") {}
|
||||||
|
|
||||||
virtual bool NotifyVsync(TimeStamp aVsyncTimeStamp) override {
|
virtual bool NotifyVsync(const VsyncEvent& aVsync) override {
|
||||||
MonitorAutoLock lock(mVsyncMonitor);
|
MonitorAutoLock lock(mVsyncMonitor);
|
||||||
mDidGetVsyncNotification = true;
|
mDidGetVsyncNotification = true;
|
||||||
mVsyncMonitor.Notify();
|
mVsyncMonitor.Notify();
|
||||||
|
|
|
@ -55,11 +55,14 @@ void VsyncSource::Display::NotifyVsync(TimeStamp aVsyncTimestamp) {
|
||||||
// Called on the vsync thread
|
// Called on the vsync thread
|
||||||
MutexAutoLock lock(mDispatcherLock);
|
MutexAutoLock lock(mDispatcherLock);
|
||||||
|
|
||||||
|
mVsyncId = mVsyncId.Next();
|
||||||
|
VsyncEvent event(mVsyncId, aVsyncTimestamp);
|
||||||
|
|
||||||
for (size_t i = 0; i < mCompositorVsyncDispatchers.Length(); i++) {
|
for (size_t i = 0; i < mCompositorVsyncDispatchers.Length(); i++) {
|
||||||
mCompositorVsyncDispatchers[i]->NotifyVsync(aVsyncTimestamp);
|
mCompositorVsyncDispatchers[i]->NotifyVsync(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
mRefreshTimerVsyncDispatcher->NotifyVsync(aVsyncTimestamp);
|
mRefreshTimerVsyncDispatcher->NotifyVsync(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeDuration VsyncSource::Display::GetVsyncRate() {
|
TimeDuration VsyncSource::Display::GetVsyncRate() {
|
||||||
|
|
|
@ -11,12 +11,21 @@
|
||||||
#include "mozilla/Mutex.h"
|
#include "mozilla/Mutex.h"
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "nsISupportsImpl.h"
|
#include "nsISupportsImpl.h"
|
||||||
|
#include "mozilla/layers/LayersTypes.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
class RefreshTimerVsyncDispatcher;
|
class RefreshTimerVsyncDispatcher;
|
||||||
class CompositorVsyncDispatcher;
|
class CompositorVsyncDispatcher;
|
||||||
|
|
||||||
|
class VsyncIdType {};
|
||||||
|
typedef layers::BaseTransactionId<VsyncIdType> VsyncId;
|
||||||
|
|
||||||
|
namespace layout {
|
||||||
|
class PVsyncChild;
|
||||||
|
}
|
||||||
|
|
||||||
namespace gfx {
|
namespace gfx {
|
||||||
|
class PVsyncBridgeParent;
|
||||||
|
|
||||||
// Controls how and when to enable/disable vsync. Lives as long as the
|
// Controls how and when to enable/disable vsync. Lives as long as the
|
||||||
// gfxPlatform does on the parent process
|
// gfxPlatform does on the parent process
|
||||||
|
@ -66,6 +75,7 @@ class VsyncSource {
|
||||||
bool mRefreshTimerNeedsVsync;
|
bool mRefreshTimerNeedsVsync;
|
||||||
nsTArray<RefPtr<CompositorVsyncDispatcher>> mCompositorVsyncDispatchers;
|
nsTArray<RefPtr<CompositorVsyncDispatcher>> mCompositorVsyncDispatchers;
|
||||||
RefPtr<RefreshTimerVsyncDispatcher> mRefreshTimerVsyncDispatcher;
|
RefPtr<RefreshTimerVsyncDispatcher> mRefreshTimerVsyncDispatcher;
|
||||||
|
VsyncId mVsyncId;
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddCompositorVsyncDispatcher(
|
void AddCompositorVsyncDispatcher(
|
||||||
|
@ -82,6 +92,27 @@ class VsyncSource {
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gfx
|
} // namespace gfx
|
||||||
|
|
||||||
|
namespace recordreplay {
|
||||||
|
namespace child {
|
||||||
|
void NotifyVsyncObserver();
|
||||||
|
}
|
||||||
|
} // namespace recordreplay
|
||||||
|
|
||||||
|
struct VsyncEvent {
|
||||||
|
VsyncId mId;
|
||||||
|
TimeStamp mTime;
|
||||||
|
|
||||||
|
private:
|
||||||
|
VsyncEvent(const VsyncId& aId, const TimeStamp& aTime)
|
||||||
|
: mId(aId), mTime(aTime) {}
|
||||||
|
VsyncEvent() {}
|
||||||
|
friend class gfx::VsyncSource::Display;
|
||||||
|
friend class gfx::PVsyncBridgeParent;
|
||||||
|
friend class layout::PVsyncChild;
|
||||||
|
friend void recordreplay::child::NotifyVsyncObserver();
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
#endif /* GFX_VSYNCSOURCE_H */
|
#endif /* GFX_VSYNCSOURCE_H */
|
||||||
|
|
|
@ -2557,6 +2557,11 @@ void gfxPlatform::InitCompositorAccelerationPrefs() {
|
||||||
return (env && *env == '1');
|
return (env && *env == '1');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool WebRenderEnvvarDisabled() {
|
||||||
|
const char* env = PR_GetEnv("MOZ_WEBRENDER");
|
||||||
|
return (env && *env == '0');
|
||||||
|
}
|
||||||
|
|
||||||
// If the "gfx.webrender.all.qualified" pref is true we want to enable
|
// If the "gfx.webrender.all.qualified" pref is true we want to enable
|
||||||
// WebRender for qualifying hardware. The Normandy pref rollout code sets
|
// WebRender for qualifying hardware. The Normandy pref rollout code sets
|
||||||
// default values on rolled out prefs on every startup, but Gfx starts up
|
// default values on rolled out prefs on every startup, but Gfx starts up
|
||||||
|
@ -2722,7 +2727,7 @@ void gfxPlatform::InitWebRenderConfig() {
|
||||||
// If the user set the pref to force-disable, let's do that. This will
|
// If the user set the pref to force-disable, let's do that. This will
|
||||||
// override all the other enabling prefs (gfx.webrender.enabled,
|
// override all the other enabling prefs (gfx.webrender.enabled,
|
||||||
// gfx.webrender.all, and gfx.webrender.all.qualified).
|
// gfx.webrender.all, and gfx.webrender.all.qualified).
|
||||||
if (gfxPrefs::WebRenderForceDisabled()) {
|
if (gfxPrefs::WebRenderForceDisabled() || WebRenderEnvvarDisabled()) {
|
||||||
featureWebRender.UserDisable(
|
featureWebRender.UserDisable(
|
||||||
"User force-disabled WR",
|
"User force-disabled WR",
|
||||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_USER_FORCE_DISABLED"));
|
NS_LITERAL_CSTRING("FEATURE_FAILURE_USER_FORCE_DISABLED"));
|
||||||
|
|
|
@ -244,6 +244,7 @@ void RenderThread::HandleFrame(wr::WindowId aWindowId, bool aRender) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeStamp startTime;
|
TimeStamp startTime;
|
||||||
|
VsyncId startId;
|
||||||
|
|
||||||
bool hadSlowFrame;
|
bool hadSlowFrame;
|
||||||
{ // scope lock
|
{ // scope lock
|
||||||
|
@ -253,11 +254,13 @@ void RenderThread::HandleFrame(wr::WindowId aWindowId, bool aRender) {
|
||||||
WindowInfo* info = it->second;
|
WindowInfo* info = it->second;
|
||||||
MOZ_ASSERT(info->mPendingCount > 0);
|
MOZ_ASSERT(info->mPendingCount > 0);
|
||||||
startTime = info->mStartTimes.front();
|
startTime = info->mStartTimes.front();
|
||||||
|
startId = info->mStartIds.front();
|
||||||
hadSlowFrame = info->mHadSlowFrame;
|
hadSlowFrame = info->mHadSlowFrame;
|
||||||
info->mHadSlowFrame = false;
|
info->mHadSlowFrame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateAndRender(aWindowId, startTime, aRender, /* aReadbackSize */ Nothing(),
|
UpdateAndRender(aWindowId, startId, startTime, aRender,
|
||||||
|
/* aReadbackSize */ Nothing(),
|
||||||
/* aReadbackBuffer */ Nothing(), hadSlowFrame);
|
/* aReadbackBuffer */ Nothing(), hadSlowFrame);
|
||||||
FrameRenderingComplete(aWindowId);
|
FrameRenderingComplete(aWindowId);
|
||||||
}
|
}
|
||||||
|
@ -304,6 +307,7 @@ void RenderThread::RunEvent(wr::WindowId aWindowId,
|
||||||
|
|
||||||
static void NotifyDidRender(layers::CompositorBridgeParent* aBridge,
|
static void NotifyDidRender(layers::CompositorBridgeParent* aBridge,
|
||||||
RefPtr<WebRenderPipelineInfo> aInfo,
|
RefPtr<WebRenderPipelineInfo> aInfo,
|
||||||
|
VsyncId aCompositeStartId,
|
||||||
TimeStamp aCompositeStart, TimeStamp aRenderStart,
|
TimeStamp aCompositeStart, TimeStamp aRenderStart,
|
||||||
TimeStamp aEnd, bool aRender,
|
TimeStamp aEnd, bool aRender,
|
||||||
RendererStats aStats) {
|
RendererStats aStats) {
|
||||||
|
@ -317,13 +321,9 @@ static void NotifyDidRender(layers::CompositorBridgeParent* aBridge,
|
||||||
auto info = aInfo->Raw();
|
auto info = aInfo->Raw();
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < info.epochs.length; i++) {
|
for (uintptr_t i = 0; i < info.epochs.length; i++) {
|
||||||
aBridge->NotifyPipelineRendered(info.epochs.data[i].pipeline_id,
|
aBridge->NotifyPipelineRendered(
|
||||||
info.epochs.data[i].epoch, aCompositeStart,
|
info.epochs.data[i].pipeline_id, info.epochs.data[i].epoch,
|
||||||
aRenderStart, aEnd, &aStats);
|
aCompositeStartId, aCompositeStart, aRenderStart, aEnd, &aStats);
|
||||||
}
|
|
||||||
|
|
||||||
if (aBridge->GetWrBridge()) {
|
|
||||||
aBridge->GetWrBridge()->CompositeIfNeeded();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,6 +336,7 @@ static void NotifyDidStartRender(layers::CompositorBridgeParent* aBridge) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderThread::UpdateAndRender(wr::WindowId aWindowId,
|
void RenderThread::UpdateAndRender(wr::WindowId aWindowId,
|
||||||
|
const VsyncId& aStartId,
|
||||||
const TimeStamp& aStartTime, bool aRender,
|
const TimeStamp& aStartTime, bool aRender,
|
||||||
const Maybe<gfx::IntSize>& aReadbackSize,
|
const Maybe<gfx::IntSize>& aReadbackSize,
|
||||||
const Maybe<Range<uint8_t>>& aReadbackBuffer,
|
const Maybe<Range<uint8_t>>& aReadbackBuffer,
|
||||||
|
@ -374,8 +375,8 @@ void RenderThread::UpdateAndRender(wr::WindowId aWindowId,
|
||||||
|
|
||||||
layers::CompositorThreadHolder::Loop()->PostTask(
|
layers::CompositorThreadHolder::Loop()->PostTask(
|
||||||
NewRunnableFunction("NotifyDidRenderRunnable", &NotifyDidRender,
|
NewRunnableFunction("NotifyDidRenderRunnable", &NotifyDidRender,
|
||||||
renderer->GetCompositorBridge(), info, aStartTime,
|
renderer->GetCompositorBridge(), info, aStartId,
|
||||||
start, end, aRender, stats));
|
aStartTime, start, end, aRender, stats));
|
||||||
|
|
||||||
if (rendered) {
|
if (rendered) {
|
||||||
// Wait for GPU after posting NotifyDidRender, since the wait is not
|
// Wait for GPU after posting NotifyDidRender, since the wait is not
|
||||||
|
@ -463,6 +464,7 @@ void RenderThread::SetDestroyed(wr::WindowId aWindowId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderThread::IncPendingFrameCount(wr::WindowId aWindowId,
|
void RenderThread::IncPendingFrameCount(wr::WindowId aWindowId,
|
||||||
|
const VsyncId& aStartId,
|
||||||
const TimeStamp& aStartTime) {
|
const TimeStamp& aStartTime) {
|
||||||
MutexAutoLock lock(mFrameCountMapLock);
|
MutexAutoLock lock(mFrameCountMapLock);
|
||||||
auto it = mWindowInfos.find(AsUint64(aWindowId));
|
auto it = mWindowInfos.find(AsUint64(aWindowId));
|
||||||
|
@ -472,6 +474,7 @@ void RenderThread::IncPendingFrameCount(wr::WindowId aWindowId,
|
||||||
}
|
}
|
||||||
it->second->mPendingCount++;
|
it->second->mPendingCount++;
|
||||||
it->second->mStartTimes.push(aStartTime);
|
it->second->mStartTimes.push(aStartTime);
|
||||||
|
it->second->mStartIds.push(aStartId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderThread::DecPendingFrameCount(wr::WindowId aWindowId) {
|
void RenderThread::DecPendingFrameCount(wr::WindowId aWindowId) {
|
||||||
|
@ -495,6 +498,7 @@ void RenderThread::DecPendingFrameCount(wr::WindowId aWindowId) {
|
||||||
mozilla::Telemetry::AccumulateTimeDelta(mozilla::Telemetry::COMPOSITE_TIME,
|
mozilla::Telemetry::AccumulateTimeDelta(mozilla::Telemetry::COMPOSITE_TIME,
|
||||||
info->mStartTimes.front());
|
info->mStartTimes.front());
|
||||||
info->mStartTimes.pop();
|
info->mStartTimes.pop();
|
||||||
|
info->mStartIds.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderThread::IncRenderingFrameCount(wr::WindowId aWindowId) {
|
void RenderThread::IncRenderingFrameCount(wr::WindowId aWindowId) {
|
||||||
|
@ -529,6 +533,7 @@ void RenderThread::FrameRenderingComplete(wr::WindowId aWindowId) {
|
||||||
mozilla::Telemetry::AccumulateTimeDelta(mozilla::Telemetry::COMPOSITE_TIME,
|
mozilla::Telemetry::AccumulateTimeDelta(mozilla::Telemetry::COMPOSITE_TIME,
|
||||||
info->mStartTimes.front());
|
info->mStartTimes.front());
|
||||||
info->mStartTimes.pop();
|
info->mStartTimes.pop();
|
||||||
|
info->mStartIds.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderThread::NotifySlowFrame(wr::WindowId aWindowId) {
|
void RenderThread::NotifySlowFrame(wr::WindowId aWindowId) {
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "mozilla/webrender/WebRenderTypes.h"
|
#include "mozilla/webrender/WebRenderTypes.h"
|
||||||
#include "mozilla/layers/SynchronousTask.h"
|
#include "mozilla/layers/SynchronousTask.h"
|
||||||
#include "GLContext.h"
|
#include "GLContext.h"
|
||||||
|
#include "mozilla/VsyncDispatcher.h"
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
@ -168,8 +169,9 @@ class RenderThread final {
|
||||||
void RunEvent(wr::WindowId aWindowId, UniquePtr<RendererEvent> aCallBack);
|
void RunEvent(wr::WindowId aWindowId, UniquePtr<RendererEvent> aCallBack);
|
||||||
|
|
||||||
/// Can only be called from the render thread.
|
/// Can only be called from the render thread.
|
||||||
void UpdateAndRender(wr::WindowId aWindowId, const TimeStamp& aStartTime,
|
void UpdateAndRender(wr::WindowId aWindowId, const VsyncId& aStartId,
|
||||||
bool aRender, const Maybe<gfx::IntSize>& aReadbackSize,
|
const TimeStamp& aStartTime, bool aRender,
|
||||||
|
const Maybe<gfx::IntSize>& aReadbackSize,
|
||||||
const Maybe<Range<uint8_t>>& aReadbackBuffer,
|
const Maybe<Range<uint8_t>>& aReadbackBuffer,
|
||||||
bool aHadSlowFrame);
|
bool aHadSlowFrame);
|
||||||
|
|
||||||
|
@ -200,7 +202,7 @@ class RenderThread final {
|
||||||
/// Can be called from any thread.
|
/// Can be called from any thread.
|
||||||
bool TooManyPendingFrames(wr::WindowId aWindowId);
|
bool TooManyPendingFrames(wr::WindowId aWindowId);
|
||||||
/// Can be called from any thread.
|
/// Can be called from any thread.
|
||||||
void IncPendingFrameCount(wr::WindowId aWindowId,
|
void IncPendingFrameCount(wr::WindowId aWindowId, const VsyncId& aStartId,
|
||||||
const TimeStamp& aStartTime);
|
const TimeStamp& aStartTime);
|
||||||
/// Can be called from any thread.
|
/// Can be called from any thread.
|
||||||
void DecPendingFrameCount(wr::WindowId aWindowId);
|
void DecPendingFrameCount(wr::WindowId aWindowId);
|
||||||
|
@ -266,6 +268,7 @@ class RenderThread final {
|
||||||
// One entry in this queue for each pending frame, so the length
|
// One entry in this queue for each pending frame, so the length
|
||||||
// should always equal mPendingCount
|
// should always equal mPendingCount
|
||||||
std::queue<TimeStamp> mStartTimes;
|
std::queue<TimeStamp> mStartTimes;
|
||||||
|
std::queue<VsyncId> mStartIds;
|
||||||
bool mHadSlowFrame = false;
|
bool mHadSlowFrame = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -372,8 +372,9 @@ void WebRenderAPI::Readback(const TimeStamp& aStartTime, gfx::IntSize size,
|
||||||
~Readback() { MOZ_COUNT_DTOR(Readback); }
|
~Readback() { MOZ_COUNT_DTOR(Readback); }
|
||||||
|
|
||||||
virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
|
virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
|
||||||
aRenderThread.UpdateAndRender(aWindowId, mStartTime, /* aRender */ true,
|
aRenderThread.UpdateAndRender(aWindowId, VsyncId(), mStartTime,
|
||||||
Some(mSize), Some(mBuffer), false);
|
/* aRender */ true, Some(mSize),
|
||||||
|
Some(mBuffer), false);
|
||||||
layers::AutoCompleteTask complete(mTask);
|
layers::AutoCompleteTask complete(mTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
74b9312fc0305ecaf06322b0f2f466da96e0a64c
|
34d58890821d2e606285f21cd6f4befd46c83d47
|
||||||
|
|
|
@ -981,6 +981,10 @@ impl<'a> DisplayListFlattener<'a> {
|
||||||
SpecificDisplayItem::PopAllShadows => {
|
SpecificDisplayItem::PopAllShadows => {
|
||||||
self.pop_all_shadows();
|
self.pop_all_shadows();
|
||||||
}
|
}
|
||||||
|
SpecificDisplayItem::PushCacheMarker(_marker) => {
|
||||||
|
}
|
||||||
|
SpecificDisplayItem::PopCacheMarker => {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -1507,6 +1507,8 @@ impl ToDebugString for SpecificDisplayItem {
|
||||||
SpecificDisplayItem::StickyFrame(..) => String::from("sticky_frame"),
|
SpecificDisplayItem::StickyFrame(..) => String::from("sticky_frame"),
|
||||||
SpecificDisplayItem::Text(..) => String::from("text"),
|
SpecificDisplayItem::Text(..) => String::from("text"),
|
||||||
SpecificDisplayItem::YuvImage(..) => String::from("yuv_image"),
|
SpecificDisplayItem::YuvImage(..) => String::from("yuv_image"),
|
||||||
|
SpecificDisplayItem::PushCacheMarker(..) => String::from("push_cache_marker"),
|
||||||
|
SpecificDisplayItem::PopCacheMarker => String::from("pop_cache_marker"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,6 +128,8 @@ pub enum SpecificDisplayItem {
|
||||||
SetGradientStops,
|
SetGradientStops,
|
||||||
PushShadow(Shadow),
|
PushShadow(Shadow),
|
||||||
PopAllShadows,
|
PopAllShadows,
|
||||||
|
PushCacheMarker(CacheMarkerDisplayItem),
|
||||||
|
PopCacheMarker,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is a "complete" version of the DI specifics,
|
/// This is a "complete" version of the DI specifics,
|
||||||
|
@ -159,6 +161,8 @@ pub enum CompletelySpecificDisplayItem {
|
||||||
SetGradientStops(Vec<GradientStop>),
|
SetGradientStops(Vec<GradientStop>),
|
||||||
PushShadow(Shadow),
|
PushShadow(Shadow),
|
||||||
PopAllShadows,
|
PopAllShadows,
|
||||||
|
PushCacheMarker(CacheMarkerDisplayItem),
|
||||||
|
PopCacheMarker,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
|
@ -517,6 +521,12 @@ pub struct PushReferenceFrameDisplayListItem {
|
||||||
pub reference_frame: ReferenceFrame,
|
pub reference_frame: ReferenceFrame,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Provides a hint to WR that it should try to cache the items
|
||||||
|
/// within a cache marker context in an off-screen surface.
|
||||||
|
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
|
pub struct CacheMarkerDisplayItem {
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
pub struct ReferenceFrame {
|
pub struct ReferenceFrame {
|
||||||
pub transform: Option<PropertyBinding<LayoutTransform>>,
|
pub transform: Option<PropertyBinding<LayoutTransform>>,
|
||||||
|
|
|
@ -14,7 +14,7 @@ use std::marker::PhantomData;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::{io, mem, ptr, slice};
|
use std::{io, mem, ptr, slice};
|
||||||
use time::precise_time_ns;
|
use time::precise_time_ns;
|
||||||
use {AlphaType, BorderDetails, BorderDisplayItem, BorderRadius, BoxShadowClipMode};
|
use {AlphaType, BorderDetails, BorderDisplayItem, BorderRadius, BoxShadowClipMode, CacheMarkerDisplayItem};
|
||||||
use {BoxShadowDisplayItem, ClipAndScrollInfo, ClipChainId, ClipChainItem, ClipDisplayItem, ClipId};
|
use {BoxShadowDisplayItem, ClipAndScrollInfo, ClipChainId, ClipChainItem, ClipDisplayItem, ClipId};
|
||||||
use {ColorF, ComplexClipRegion, DisplayItem, ExtendMode, ExternalScrollId, FilterOp};
|
use {ColorF, ComplexClipRegion, DisplayItem, ExtendMode, ExternalScrollId, FilterOp};
|
||||||
use {FontInstanceKey, GlyphInstance, GlyphOptions, RasterSpace, Gradient, GradientBuilder};
|
use {FontInstanceKey, GlyphInstance, GlyphOptions, RasterSpace, Gradient, GradientBuilder};
|
||||||
|
@ -502,6 +502,8 @@ impl Serialize for BuiltDisplayList {
|
||||||
),
|
),
|
||||||
SpecificDisplayItem::PushShadow(v) => PushShadow(v),
|
SpecificDisplayItem::PushShadow(v) => PushShadow(v),
|
||||||
SpecificDisplayItem::PopAllShadows => PopAllShadows,
|
SpecificDisplayItem::PopAllShadows => PopAllShadows,
|
||||||
|
SpecificDisplayItem::PushCacheMarker(m) => PushCacheMarker(m),
|
||||||
|
SpecificDisplayItem::PopCacheMarker => PopCacheMarker,
|
||||||
},
|
},
|
||||||
clip_and_scroll: display_item.clip_and_scroll,
|
clip_and_scroll: display_item.clip_and_scroll,
|
||||||
info: display_item.info,
|
info: display_item.info,
|
||||||
|
@ -588,6 +590,8 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
|
||||||
},
|
},
|
||||||
PushShadow(specific_item) => SpecificDisplayItem::PushShadow(specific_item),
|
PushShadow(specific_item) => SpecificDisplayItem::PushShadow(specific_item),
|
||||||
PopAllShadows => SpecificDisplayItem::PopAllShadows,
|
PopAllShadows => SpecificDisplayItem::PopAllShadows,
|
||||||
|
PushCacheMarker(marker) => SpecificDisplayItem::PushCacheMarker(marker),
|
||||||
|
PopCacheMarker => SpecificDisplayItem::PopCacheMarker,
|
||||||
},
|
},
|
||||||
clip_and_scroll: complete.clip_and_scroll,
|
clip_and_scroll: complete.clip_and_scroll,
|
||||||
info: complete.info,
|
info: complete.info,
|
||||||
|
@ -1261,6 +1265,19 @@ impl DisplayListBuilder {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn push_cache_marker(&mut self) {
|
||||||
|
self.push_new_empty_item(&SpecificDisplayItem::PushCacheMarker(CacheMarkerDisplayItem {
|
||||||
|
// The display item itself is empty for now while we experiment with
|
||||||
|
// the API. In future it may contain extra information, such as details
|
||||||
|
// on whether the surface is known to be opaque and/or a background color
|
||||||
|
// hint that WR should clear the surface to.
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_cache_marker(&mut self) {
|
||||||
|
self.push_new_empty_item(&SpecificDisplayItem::PopCacheMarker);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pop_reference_frame(&mut self) {
|
pub fn pop_reference_frame(&mut self) {
|
||||||
self.push_new_empty_item(&SpecificDisplayItem::PopReferenceFrame);
|
self.push_new_empty_item(&SpecificDisplayItem::PopReferenceFrame);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1151,6 +1151,11 @@ impl YamlFrameWriter {
|
||||||
yaml_node(&mut v, "previously-applied-offset", Yaml::Array(applied));
|
yaml_node(&mut v, "previously-applied-offset", Yaml::Array(applied));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PopCacheMarker => return,
|
||||||
|
PushCacheMarker(_) => {
|
||||||
|
str_node(&mut v, "type", "cache-marker");
|
||||||
|
}
|
||||||
|
|
||||||
PopStackingContext => return,
|
PopStackingContext => return,
|
||||||
PopReferenceFrame => return,
|
PopReferenceFrame => return,
|
||||||
SetGradientStops => panic!("dummy item yielded?"),
|
SetGradientStops => panic!("dummy item yielded?"),
|
||||||
|
|
|
@ -460,14 +460,18 @@ TraceLoggerEventPayload* TraceLoggerThreadState::getOrCreateEventPayload(
|
||||||
nextDictionaryId++;
|
nextDictionaryId++;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t textId = nextTextId;
|
// Look for a free entry, as some textId's may
|
||||||
|
// already be taken from previous profiling sessions.
|
||||||
|
while (textIdPayloads.has(nextTextId)) {
|
||||||
|
nextTextId++;
|
||||||
|
}
|
||||||
|
|
||||||
auto* payload = js_new<TraceLoggerEventPayload>(textId, dictId);
|
auto* payload = js_new<TraceLoggerEventPayload>(nextTextId, dictId);
|
||||||
if (!payload) {
|
if (!payload) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!textIdPayloads.putNew(textId, payload)) {
|
if (!textIdPayloads.putNew(nextTextId, payload)) {
|
||||||
js_delete(payload);
|
js_delete(payload);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -976,33 +980,72 @@ void TraceLoggerThread::log(uint32_t id) {
|
||||||
entry.textId = id;
|
entry.textId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceLoggerThreadState::clear() {
|
bool TraceLoggerThreadState::remapDictionaryEntries(
|
||||||
LockGuard<Mutex> guard(lock);
|
mozilla::Vector<UniqueChars, 0, SystemAllocPolicy>* newDictionary,
|
||||||
for (TraceLoggerThread* logger : threadLoggers) {
|
uint32_t* newNextDictionaryId) {
|
||||||
logger->clear();
|
MOZ_ASSERT(newNextDictionaryId != nullptr && newDictionary != nullptr);
|
||||||
}
|
|
||||||
|
typedef HashMap<uint32_t, uint32_t, DefaultHasher<uint32_t>,
|
||||||
|
SystemAllocPolicy>
|
||||||
|
DictionaryMap;
|
||||||
|
DictionaryMap dictionaryMap;
|
||||||
|
|
||||||
// Clear all payloads that are not currently used. There may be some events
|
// Clear all payloads that are not currently used. There may be some events
|
||||||
// that still hold a pointer to a payload. Restarting the profiler may add
|
// that still hold a pointer to a payload. Restarting the profiler may reuse
|
||||||
// this event to the new events array and so we need to maintain it's
|
// the exact same event as a previous session if it's still alive so we need
|
||||||
// existence.
|
// to maintain it's existence.
|
||||||
for (TextIdToPayloadMap::Enum e(textIdPayloads); !e.empty(); e.popFront()) {
|
for (TextIdToPayloadMap::Enum e(textIdPayloads); !e.empty(); e.popFront()) {
|
||||||
if (e.front().value()->uses() == 0) {
|
if (e.front().value()->uses() == 0) {
|
||||||
js_delete(e.front().value());
|
js_delete(e.front().value());
|
||||||
e.removeFront();
|
e.removeFront();
|
||||||
|
} else {
|
||||||
|
TraceLoggerEventPayload* payload = e.front().value();
|
||||||
|
uint32_t dictId = payload->dictionaryId();
|
||||||
|
|
||||||
|
if (dictionaryMap.has(dictId)) {
|
||||||
|
DictionaryMap::Ptr mapPointer = dictionaryMap.lookup(dictId);
|
||||||
|
MOZ_ASSERT(mapPointer);
|
||||||
|
payload->setDictionaryId(mapPointer->value());
|
||||||
|
} else {
|
||||||
|
if (!newDictionary->append(std::move(dictionaryData[dictId]))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
payload->setDictionaryId(*newNextDictionaryId);
|
||||||
|
|
||||||
|
if (!dictionaryMap.putNew(dictId, *newNextDictionaryId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*newNextDictionaryId)++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear and free any data used for the string dictionary.
|
return true;
|
||||||
for (auto range = dictionaryData.all(); !range.empty(); range.popFront()) {
|
}
|
||||||
range.front().reset();
|
|
||||||
|
void TraceLoggerThreadState::clear() {
|
||||||
|
LockGuard<Mutex> guard(lock);
|
||||||
|
|
||||||
|
uint32_t newNextDictionaryId = 0;
|
||||||
|
mozilla::Vector<UniqueChars, 0, SystemAllocPolicy> newDictionary;
|
||||||
|
if (remapDictionaryEntries(&newDictionary, &newNextDictionaryId)) {
|
||||||
|
// Clear and free any data used for the string dictionary.
|
||||||
|
for (auto range = dictionaryData.all(); !range.empty(); range.popFront()) {
|
||||||
|
range.front().reset();
|
||||||
|
}
|
||||||
|
dictionaryData.clearAndFree();
|
||||||
|
dictionaryData = std::move(newDictionary);
|
||||||
|
|
||||||
|
payloadDictionary.clearAndCompact();
|
||||||
|
|
||||||
|
nextTextId = TraceLogger_Last;
|
||||||
|
nextDictionaryId = newNextDictionaryId;
|
||||||
}
|
}
|
||||||
|
|
||||||
dictionaryData.clearAndFree();
|
for (TraceLoggerThread* logger : threadLoggers) {
|
||||||
payloadDictionary.clearAndCompact();
|
logger->clear();
|
||||||
|
}
|
||||||
nextTextId = TraceLogger_Last;
|
|
||||||
nextDictionaryId = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceLoggerThread::clear() {
|
void TraceLoggerThread::clear() {
|
||||||
|
|
|
@ -200,6 +200,7 @@ class TraceLoggerEventPayload {
|
||||||
mozilla::Maybe<uint32_t> column() { return col_; }
|
mozilla::Maybe<uint32_t> column() { return col_; }
|
||||||
uint32_t textId() { return textId_; }
|
uint32_t textId() { return textId_; }
|
||||||
uint32_t dictionaryId() { return dictionaryId_; }
|
uint32_t dictionaryId() { return dictionaryId_; }
|
||||||
|
void setDictionaryId(uint32_t dictId) { dictionaryId_ = dictId; }
|
||||||
uint32_t uses() { return uses_; }
|
uint32_t uses() { return uses_; }
|
||||||
|
|
||||||
// Payloads may have their use count change at any time, *except* the count
|
// Payloads may have their use count change at any time, *except* the count
|
||||||
|
@ -426,6 +427,9 @@ class TraceLoggerThreadState {
|
||||||
void enableFrontendLogging();
|
void enableFrontendLogging();
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
bool remapDictionaryEntries(
|
||||||
|
mozilla::Vector<UniqueChars, 0, SystemAllocPolicy>* newDictionary,
|
||||||
|
uint32_t* newNextDictionaryId);
|
||||||
|
|
||||||
TraceLoggerThread* forCurrentThread(JSContext* cx);
|
TraceLoggerThread* forCurrentThread(JSContext* cx);
|
||||||
void destroyLogger(TraceLoggerThread* logger);
|
void destroyLogger(TraceLoggerThread* logger);
|
||||||
|
|
|
@ -285,10 +285,10 @@ class RefreshDriverTimer {
|
||||||
*/
|
*/
|
||||||
void Tick() {
|
void Tick() {
|
||||||
TimeStamp now = TimeStamp::Now();
|
TimeStamp now = TimeStamp::Now();
|
||||||
Tick(now);
|
Tick(VsyncId(), now);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TickRefreshDrivers(TimeStamp aNow,
|
void TickRefreshDrivers(VsyncId aId, TimeStamp aNow,
|
||||||
nsTArray<RefPtr<nsRefreshDriver>>& aDrivers) {
|
nsTArray<RefPtr<nsRefreshDriver>>& aDrivers) {
|
||||||
if (aDrivers.IsEmpty()) {
|
if (aDrivers.IsEmpty()) {
|
||||||
return;
|
return;
|
||||||
|
@ -301,14 +301,14 @@ class RefreshDriverTimer {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
TickDriver(driver, aNow);
|
TickDriver(driver, aId, aNow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tick the refresh drivers based on the given timestamp.
|
* Tick the refresh drivers based on the given timestamp.
|
||||||
*/
|
*/
|
||||||
void Tick(TimeStamp now) {
|
void Tick(VsyncId aId, TimeStamp now) {
|
||||||
ScheduleNextTick(now);
|
ScheduleNextTick(now);
|
||||||
|
|
||||||
mLastFireTime = now;
|
mLastFireTime = now;
|
||||||
|
@ -317,14 +317,14 @@ class RefreshDriverTimer {
|
||||||
// RD is short for RefreshDriver
|
// RD is short for RefreshDriver
|
||||||
AUTO_PROFILER_TRACING("Paint", "RefreshDriverTick");
|
AUTO_PROFILER_TRACING("Paint", "RefreshDriverTick");
|
||||||
|
|
||||||
TickRefreshDrivers(now, mContentRefreshDrivers);
|
TickRefreshDrivers(aId, now, mContentRefreshDrivers);
|
||||||
TickRefreshDrivers(now, mRootRefreshDrivers);
|
TickRefreshDrivers(aId, now, mRootRefreshDrivers);
|
||||||
|
|
||||||
LOG("[%p] done.", this);
|
LOG("[%p] done.", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TickDriver(nsRefreshDriver* driver, TimeStamp now) {
|
static void TickDriver(nsRefreshDriver* driver, VsyncId aId, TimeStamp now) {
|
||||||
driver->Tick(now);
|
driver->Tick(aId, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeStamp mLastFireTime;
|
TimeStamp mLastFireTime;
|
||||||
|
@ -462,11 +462,12 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
|
||||||
public nsIRunnablePriority {
|
public nsIRunnablePriority {
|
||||||
public:
|
public:
|
||||||
ParentProcessVsyncNotifier(RefreshDriverVsyncObserver* aObserver,
|
ParentProcessVsyncNotifier(RefreshDriverVsyncObserver* aObserver,
|
||||||
TimeStamp aVsyncTimestamp)
|
VsyncId aId, TimeStamp aVsyncTimestamp)
|
||||||
: Runnable(
|
: Runnable(
|
||||||
"VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::"
|
"VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::"
|
||||||
"ParentProcessVsyncNotifier"),
|
"ParentProcessVsyncNotifier"),
|
||||||
mObserver(aObserver),
|
mObserver(aObserver),
|
||||||
|
mId(aId),
|
||||||
mVsyncTimestamp(aVsyncTimestamp) {}
|
mVsyncTimestamp(aVsyncTimestamp) {}
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
@ -483,7 +484,7 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
|
||||||
}
|
}
|
||||||
sHighPriorityEnabled = sHighPriorityPrefValue;
|
sHighPriorityEnabled = sHighPriorityPrefValue;
|
||||||
|
|
||||||
mObserver->TickRefreshDriver(mVsyncTimestamp);
|
mObserver->TickRefreshDriver(mId, mVsyncTimestamp);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,11 +498,12 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
|
||||||
private:
|
private:
|
||||||
~ParentProcessVsyncNotifier() {}
|
~ParentProcessVsyncNotifier() {}
|
||||||
RefPtr<RefreshDriverVsyncObserver> mObserver;
|
RefPtr<RefreshDriverVsyncObserver> mObserver;
|
||||||
|
VsyncId mId;
|
||||||
TimeStamp mVsyncTimestamp;
|
TimeStamp mVsyncTimestamp;
|
||||||
static mozilla::Atomic<bool> sHighPriorityEnabled;
|
static mozilla::Atomic<bool> sHighPriorityEnabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool NotifyVsync(TimeStamp aVsyncTimestamp) override {
|
bool NotifyVsync(const VsyncEvent& aVsync) override {
|
||||||
// IMPORTANT: All paths through this method MUST hold a strong ref on
|
// IMPORTANT: All paths through this method MUST hold a strong ref on
|
||||||
// |this| for the duration of the TickRefreshDriver callback.
|
// |this| for the duration of the TickRefreshDriver callback.
|
||||||
|
|
||||||
|
@ -512,7 +514,8 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
|
||||||
// if the main thread is blocked for long periods of time
|
// if the main thread is blocked for long periods of time
|
||||||
{ // scope lock
|
{ // scope lock
|
||||||
MonitorAutoLock lock(mRefreshTickLock);
|
MonitorAutoLock lock(mRefreshTickLock);
|
||||||
mRecentVsync = aVsyncTimestamp;
|
mRecentVsync = aVsync.mTime;
|
||||||
|
mRecentVsyncId = aVsync.mId;
|
||||||
if (!mProcessedVsync) {
|
if (!mProcessedVsync) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -520,11 +523,12 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> vsyncEvent =
|
nsCOMPtr<nsIRunnable> vsyncEvent =
|
||||||
new ParentProcessVsyncNotifier(this, aVsyncTimestamp);
|
new ParentProcessVsyncNotifier(this, aVsync.mId, aVsync.mTime);
|
||||||
NS_DispatchToMainThread(vsyncEvent);
|
NS_DispatchToMainThread(vsyncEvent);
|
||||||
} else {
|
} else {
|
||||||
mRecentVsync = aVsyncTimestamp;
|
mRecentVsync = aVsync.mTime;
|
||||||
if (!mBlockUntil.IsNull() && mBlockUntil > aVsyncTimestamp) {
|
mRecentVsyncId = aVsync.mId;
|
||||||
|
if (!mBlockUntil.IsNull() && mBlockUntil > aVsync.mTime) {
|
||||||
if (mProcessedVsync) {
|
if (mProcessedVsync) {
|
||||||
// Re-post vsync update as a normal priority runnable. This way
|
// Re-post vsync update as a normal priority runnable. This way
|
||||||
// runnables already in normal priority queue get processed.
|
// runnables already in normal priority queue get processed.
|
||||||
|
@ -539,7 +543,7 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<RefreshDriverVsyncObserver> kungFuDeathGrip(this);
|
RefPtr<RefreshDriverVsyncObserver> kungFuDeathGrip(this);
|
||||||
TickRefreshDriver(aVsyncTimestamp);
|
TickRefreshDriver(aVsync.mId, aVsync.mTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -561,7 +565,7 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
|
||||||
mRecentVsync > mLastProcessedTickInChildProcess) {
|
mRecentVsync > mLastProcessedTickInChildProcess) {
|
||||||
// mBlockUntil is for high priority vsync notifications only.
|
// mBlockUntil is for high priority vsync notifications only.
|
||||||
mBlockUntil = TimeStamp();
|
mBlockUntil = TimeStamp();
|
||||||
TickRefreshDriver(mRecentVsync);
|
TickRefreshDriver(mRecentVsyncId, mRecentVsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
mProcessedVsync = true;
|
mProcessedVsync = true;
|
||||||
|
@ -615,7 +619,7 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TickRefreshDriver(TimeStamp aVsyncTimestamp) {
|
void TickRefreshDriver(VsyncId aId, TimeStamp aVsyncTimestamp) {
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
RecordTelemetryProbes(aVsyncTimestamp);
|
RecordTelemetryProbes(aVsyncTimestamp);
|
||||||
|
@ -639,7 +643,7 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
|
||||||
// before use.
|
// before use.
|
||||||
if (mVsyncRefreshDriverTimer) {
|
if (mVsyncRefreshDriverTimer) {
|
||||||
RefPtr<VsyncRefreshDriverTimer> timer = mVsyncRefreshDriverTimer;
|
RefPtr<VsyncRefreshDriverTimer> timer = mVsyncRefreshDriverTimer;
|
||||||
timer->RunRefreshDrivers(aVsyncTimestamp);
|
timer->RunRefreshDrivers(aId, aVsyncTimestamp);
|
||||||
// Note: mVsyncRefreshDriverTimer might be null now.
|
// Note: mVsyncRefreshDriverTimer might be null now.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -655,6 +659,7 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
|
||||||
VsyncRefreshDriverTimer* mVsyncRefreshDriverTimer;
|
VsyncRefreshDriverTimer* mVsyncRefreshDriverTimer;
|
||||||
Monitor mRefreshTickLock;
|
Monitor mRefreshTickLock;
|
||||||
TimeStamp mRecentVsync;
|
TimeStamp mRecentVsync;
|
||||||
|
VsyncId mRecentVsyncId;
|
||||||
TimeStamp mLastChildTick;
|
TimeStamp mLastChildTick;
|
||||||
TimeStamp mLastProcessedTickInChildProcess;
|
TimeStamp mLastProcessedTickInChildProcess;
|
||||||
TimeStamp mBlockUntil;
|
TimeStamp mBlockUntil;
|
||||||
|
@ -717,7 +722,9 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
|
||||||
// RefreshDriverVsyncObserver.
|
// RefreshDriverVsyncObserver.
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunRefreshDrivers(TimeStamp aTimeStamp) { Tick(aTimeStamp); }
|
void RunRefreshDrivers(VsyncId aId, TimeStamp aTimeStamp) {
|
||||||
|
Tick(aId, aTimeStamp);
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<RefreshDriverVsyncObserver> mVsyncObserver;
|
RefPtr<RefreshDriverVsyncObserver> mVsyncObserver;
|
||||||
// Used for parent process.
|
// Used for parent process.
|
||||||
|
@ -871,7 +878,7 @@ class InactiveRefreshDriverTimer final
|
||||||
|
|
||||||
if (index < drivers.Length() &&
|
if (index < drivers.Length() &&
|
||||||
!drivers[index]->IsTestControllingRefreshesEnabled()) {
|
!drivers[index]->IsTestControllingRefreshesEnabled()) {
|
||||||
TickDriver(drivers[index], now);
|
TickDriver(drivers[index], VsyncId(), now);
|
||||||
}
|
}
|
||||||
|
|
||||||
mNextDriverIndex++;
|
mNextDriverIndex++;
|
||||||
|
@ -1364,9 +1371,9 @@ void nsRefreshDriver::DoTick() {
|
||||||
"Shouldn't have a JSContext on the stack");
|
"Shouldn't have a JSContext on the stack");
|
||||||
|
|
||||||
if (mTestControllingRefreshes) {
|
if (mTestControllingRefreshes) {
|
||||||
Tick(mMostRecentRefresh);
|
Tick(VsyncId(), mMostRecentRefresh);
|
||||||
} else {
|
} else {
|
||||||
Tick(TimeStamp::Now());
|
Tick(VsyncId(), TimeStamp::Now());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1608,7 +1615,7 @@ void nsRefreshDriver::CancelIdleRunnable(nsIRunnable* aRunnable) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsRefreshDriver::Tick(TimeStamp aNowTime) {
|
void nsRefreshDriver::Tick(VsyncId aId, TimeStamp aNowTime) {
|
||||||
MOZ_ASSERT(!nsContentUtils::GetCurrentJSContext(),
|
MOZ_ASSERT(!nsContentUtils::GetCurrentJSContext(),
|
||||||
"Shouldn't have a JSContext on the stack");
|
"Shouldn't have a JSContext on the stack");
|
||||||
|
|
||||||
|
@ -1675,6 +1682,7 @@ void nsRefreshDriver::Tick(TimeStamp aNowTime) {
|
||||||
|
|
||||||
AutoRestore<TimeStamp> restoreTickStart(mTickStart);
|
AutoRestore<TimeStamp> restoreTickStart(mTickStart);
|
||||||
mTickStart = TimeStamp::Now();
|
mTickStart = TimeStamp::Now();
|
||||||
|
mTickVsyncId = aId;
|
||||||
|
|
||||||
gfxPlatform::GetPlatform()->SchedulePaintIfDeviceReset();
|
gfxPlatform::GetPlatform()->SchedulePaintIfDeviceReset();
|
||||||
|
|
||||||
|
@ -2052,6 +2060,8 @@ void nsRefreshDriver::ResetInitialTransactionId(
|
||||||
|
|
||||||
mozilla::TimeStamp nsRefreshDriver::GetTransactionStart() { return mTickStart; }
|
mozilla::TimeStamp nsRefreshDriver::GetTransactionStart() { return mTickStart; }
|
||||||
|
|
||||||
|
VsyncId nsRefreshDriver::GetVsyncId() { return mTickVsyncId; }
|
||||||
|
|
||||||
void nsRefreshDriver::NotifyTransactionCompleted(
|
void nsRefreshDriver::NotifyTransactionCompleted(
|
||||||
mozilla::layers::TransactionId aTransactionId) {
|
mozilla::layers::TransactionId aTransactionId) {
|
||||||
if (aTransactionId > mCompletedTransaction) {
|
if (aTransactionId > mCompletedTransaction) {
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/layers/TransactionIdAllocator.h"
|
#include "mozilla/layers/TransactionIdAllocator.h"
|
||||||
|
#include "mozilla/VsyncDispatcher.h"
|
||||||
|
|
||||||
class nsPresContext;
|
class nsPresContext;
|
||||||
class nsIPresShell;
|
class nsIPresShell;
|
||||||
|
@ -361,6 +362,7 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
|
||||||
void ClearPendingTransactions() override;
|
void ClearPendingTransactions() override;
|
||||||
void ResetInitialTransactionId(TransactionId aTransactionId) override;
|
void ResetInitialTransactionId(TransactionId aTransactionId) override;
|
||||||
mozilla::TimeStamp GetTransactionStart() override;
|
mozilla::TimeStamp GetTransactionStart() override;
|
||||||
|
mozilla::VsyncId GetVsyncId() override;
|
||||||
|
|
||||||
bool IsWaitingForPaint(mozilla::TimeStamp aTime);
|
bool IsWaitingForPaint(mozilla::TimeStamp aTime);
|
||||||
|
|
||||||
|
@ -414,7 +416,7 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
|
||||||
void DispatchAnimationEvents();
|
void DispatchAnimationEvents();
|
||||||
void RunFrameRequestCallbacks(mozilla::TimeStamp aNowTime);
|
void RunFrameRequestCallbacks(mozilla::TimeStamp aNowTime);
|
||||||
void UpdateIntersectionObservations();
|
void UpdateIntersectionObservations();
|
||||||
void Tick(mozilla::TimeStamp aNowTime);
|
void Tick(mozilla::VsyncId aId, mozilla::TimeStamp aNowTime);
|
||||||
|
|
||||||
enum EnsureTimerStartedFlags {
|
enum EnsureTimerStartedFlags {
|
||||||
eNone = 0,
|
eNone = 0,
|
||||||
|
@ -507,6 +509,7 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
|
||||||
uint64_t mWarningThreshold;
|
uint64_t mWarningThreshold;
|
||||||
mozilla::TimeStamp mMostRecentRefresh;
|
mozilla::TimeStamp mMostRecentRefresh;
|
||||||
mozilla::TimeStamp mTickStart;
|
mozilla::TimeStamp mTickStart;
|
||||||
|
mozilla::VsyncId mTickVsyncId;
|
||||||
mozilla::TimeStamp mNextThrottledFrameRequestTick;
|
mozilla::TimeStamp mNextThrottledFrameRequestTick;
|
||||||
mozilla::TimeStamp mNextRecomputeVisibilityTick;
|
mozilla::TimeStamp mNextRecomputeVisibilityTick;
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ include protocol PBackground;
|
||||||
include "mozilla/layers/LayersMessageUtils.h";
|
include "mozilla/layers/LayersMessageUtils.h";
|
||||||
|
|
||||||
using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
|
using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
|
||||||
|
using mozilla::VsyncEvent from "mozilla/VsyncDispatcher.h";
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layout {
|
namespace layout {
|
||||||
|
@ -22,7 +23,7 @@ async protocol PVsync
|
||||||
|
|
||||||
child:
|
child:
|
||||||
// Send vsync event from chrome to content process.
|
// Send vsync event from chrome to content process.
|
||||||
prio(high) async Notify(TimeStamp aVsyncTimestamp) compress;
|
prio(high) async Notify(VsyncEvent aVsync) compress;
|
||||||
|
|
||||||
// Send the vsync rate to the content process.
|
// Send the vsync rate to the content process.
|
||||||
async VsyncRate(float aVsyncRate);
|
async VsyncRate(float aVsyncRate);
|
||||||
|
|
|
@ -51,8 +51,7 @@ void VsyncChild::ActorDestroy(ActorDestroyReason aActorDestroyReason) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult VsyncChild::RecvNotify(
|
mozilla::ipc::IPCResult VsyncChild::RecvNotify(const VsyncEvent& aVsync) {
|
||||||
const TimeStamp& aVsyncTimestamp) {
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
MOZ_ASSERT(!mIsShutdown);
|
MOZ_ASSERT(!mIsShutdown);
|
||||||
|
|
||||||
|
@ -63,7 +62,7 @@ mozilla::ipc::IPCResult VsyncChild::RecvNotify(
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
mObserver->NotifyVsync(aVsyncTimestamp);
|
mObserver->NotifyVsync(aVsync);
|
||||||
}
|
}
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,8 +52,7 @@ class VsyncChild final : public PVsyncChild {
|
||||||
VsyncChild();
|
VsyncChild();
|
||||||
virtual ~VsyncChild();
|
virtual ~VsyncChild();
|
||||||
|
|
||||||
virtual mozilla::ipc::IPCResult RecvNotify(
|
virtual mozilla::ipc::IPCResult RecvNotify(const VsyncEvent& aVsync) override;
|
||||||
const TimeStamp& aVsyncTimestamp) override;
|
|
||||||
virtual mozilla::ipc::IPCResult RecvVsyncRate(
|
virtual mozilla::ipc::IPCResult RecvVsyncRate(
|
||||||
const float& aVsyncRate) override;
|
const float& aVsyncRate) override;
|
||||||
virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override;
|
virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override;
|
||||||
|
|
|
@ -42,18 +42,18 @@ VsyncParent::~VsyncParent() {
|
||||||
// VsyncParent is always released on the background thread.
|
// VsyncParent is always released on the background thread.
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VsyncParent::NotifyVsync(TimeStamp aTimeStamp) {
|
bool VsyncParent::NotifyVsync(const VsyncEvent& aVsync) {
|
||||||
// Called on hardware vsync thread. We should post to current ipc thread.
|
// Called on hardware vsync thread. We should post to current ipc thread.
|
||||||
MOZ_ASSERT(!IsOnBackgroundThread());
|
MOZ_ASSERT(!IsOnBackgroundThread());
|
||||||
nsCOMPtr<nsIRunnable> vsyncEvent = NewRunnableMethod<TimeStamp>(
|
nsCOMPtr<nsIRunnable> vsyncEvent = NewRunnableMethod<VsyncEvent>(
|
||||||
"layout::VsyncParent::DispatchVsyncEvent", this,
|
"layout::VsyncParent::DispatchVsyncEvent", this,
|
||||||
&VsyncParent::DispatchVsyncEvent, aTimeStamp);
|
&VsyncParent::DispatchVsyncEvent, aVsync);
|
||||||
MOZ_ALWAYS_SUCCEEDS(
|
MOZ_ALWAYS_SUCCEEDS(
|
||||||
mBackgroundThread->Dispatch(vsyncEvent, NS_DISPATCH_NORMAL));
|
mBackgroundThread->Dispatch(vsyncEvent, NS_DISPATCH_NORMAL));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VsyncParent::DispatchVsyncEvent(TimeStamp aTimeStamp) {
|
void VsyncParent::DispatchVsyncEvent(const VsyncEvent& aVsync) {
|
||||||
AssertIsOnBackgroundThread();
|
AssertIsOnBackgroundThread();
|
||||||
|
|
||||||
// If we call NotifyVsync() when we handle ActorDestroy() message, we might
|
// If we call NotifyVsync() when we handle ActorDestroy() message, we might
|
||||||
|
@ -62,7 +62,7 @@ void VsyncParent::DispatchVsyncEvent(TimeStamp aTimeStamp) {
|
||||||
// NotifyVsync(). We use mObservingVsync and mDestroyed flags to skip this
|
// NotifyVsync(). We use mObservingVsync and mDestroyed flags to skip this
|
||||||
// notification.
|
// notification.
|
||||||
if (mObservingVsync && !mDestroyed) {
|
if (mObservingVsync && !mDestroyed) {
|
||||||
Unused << SendNotify(aTimeStamp);
|
Unused << SendNotify(aVsync);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,14 +34,14 @@ class VsyncParent final : public PVsyncParent, public VsyncObserver {
|
||||||
VsyncParent();
|
VsyncParent();
|
||||||
virtual ~VsyncParent();
|
virtual ~VsyncParent();
|
||||||
|
|
||||||
virtual bool NotifyVsync(TimeStamp aTimeStamp) override;
|
virtual bool NotifyVsync(const VsyncEvent& aVsync) override;
|
||||||
virtual mozilla::ipc::IPCResult RecvRequestVsyncRate() override;
|
virtual mozilla::ipc::IPCResult RecvRequestVsyncRate() override;
|
||||||
|
|
||||||
virtual mozilla::ipc::IPCResult RecvObserve() override;
|
virtual mozilla::ipc::IPCResult RecvObserve() override;
|
||||||
virtual mozilla::ipc::IPCResult RecvUnobserve() override;
|
virtual mozilla::ipc::IPCResult RecvUnobserve() override;
|
||||||
virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override;
|
virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override;
|
||||||
|
|
||||||
void DispatchVsyncEvent(TimeStamp aTimeStamp);
|
void DispatchVsyncEvent(const VsyncEvent& aVsync);
|
||||||
|
|
||||||
bool mObservingVsync;
|
bool mObservingVsync;
|
||||||
bool mDestroyed;
|
bool mDestroyed;
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Autogenerated by the Meson build system.
|
||||||
|
* Do not edit, your changes will be lost.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define ARCH_AARCH64 0
|
||||||
|
|
||||||
|
#define ARCH_ARM 0
|
||||||
|
|
||||||
|
#define ARCH_X86 0
|
||||||
|
|
||||||
|
#define ARCH_X86_32 0
|
||||||
|
|
||||||
|
#define ARCH_X86_64 0
|
||||||
|
|
||||||
|
#define CONFIG_10BPC 1
|
||||||
|
|
||||||
|
#define CONFIG_8BPC 1
|
||||||
|
|
||||||
|
#define HAVE_ASM 0
|
||||||
|
|
||||||
|
#define HAVE_POSIX_MEMALIGN 1
|
||||||
|
|
||||||
|
#define HAVE_UNISTD_H 1
|
||||||
|
|
|
@ -33,6 +33,9 @@ elif CONFIG['CPU_ARCH'] == 'arm':
|
||||||
elif CONFIG['CPU_ARCH'] == 'aarch64':
|
elif CONFIG['CPU_ARCH'] == 'aarch64':
|
||||||
LOCAL_INCLUDES += ['/media/libdav1d/config/aarch64/']
|
LOCAL_INCLUDES += ['/media/libdav1d/config/aarch64/']
|
||||||
EXPORTS.dav1d += ['config/aarch64/config.h']
|
EXPORTS.dav1d += ['config/aarch64/config.h']
|
||||||
|
else:
|
||||||
|
LOCAL_INCLUDES += ['/media/libdav1d/config/other/']
|
||||||
|
EXPORTS.dav1d += ['config/other/config.h']
|
||||||
|
|
||||||
EXPORTS.dav1d += [
|
EXPORTS.dav1d += [
|
||||||
'version.h',
|
'version.h',
|
||||||
|
|
|
@ -573,12 +573,6 @@ VCMEncodedFrame* VCMJitterBuffer::ExtractAndSetDecode(uint32_t timestamp) {
|
||||||
if ((*frame).IsSessionComplete())
|
if ((*frame).IsSessionComplete())
|
||||||
UpdateAveragePacketsPerFrame(frame->NumPackets());
|
UpdateAveragePacketsPerFrame(frame->NumPackets());
|
||||||
|
|
||||||
if (frame->Length() == 0) {
|
|
||||||
// Normally only if MakeDecodable() on an incomplete frame threw it all away
|
|
||||||
ReleaseFrame(frame);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ public class WifiScanner extends BroadcastReceiver {
|
||||||
/* ------- */
|
/* ------- */
|
||||||
|
|
||||||
public WifiScanner(Context c) {
|
public WifiScanner(Context c) {
|
||||||
mContext = c;
|
mContext = c.getApplicationContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isWifiEnabled() {
|
private boolean isWifiEnabled() {
|
||||||
|
|
|
@ -5,6 +5,7 @@ job-defaults:
|
||||||
virtualization:
|
virtualization:
|
||||||
by-test-platform:
|
by-test-platform:
|
||||||
windows10-64-qr/.*: virtual-with-gpu
|
windows10-64-qr/.*: virtual-with-gpu
|
||||||
|
windows10-64/.*: virtual-with-gpu
|
||||||
default: virtual
|
default: virtual
|
||||||
allow-software-gl-layers: false
|
allow-software-gl-layers: false
|
||||||
mozharness:
|
mozharness:
|
||||||
|
|
|
@ -955,6 +955,11 @@ def enable_webrender(config, tests):
|
||||||
if test.get('webrender'):
|
if test.get('webrender'):
|
||||||
test['mozharness'].setdefault('extra-options', [])\
|
test['mozharness'].setdefault('extra-options', [])\
|
||||||
.append("--enable-webrender")
|
.append("--enable-webrender")
|
||||||
|
# Explicitly disable WebRender on non-WR AWSY, since that job runs on
|
||||||
|
# virtual-with-gpu and thus is considered qualified hardware.
|
||||||
|
elif test['suite'] == 'awsy':
|
||||||
|
test['mozharness'].setdefault('extra-options', [])\
|
||||||
|
.append("--disable-webrender")
|
||||||
|
|
||||||
yield test
|
yield test
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,12 @@ class AWSY(TestingMixin, MercurialScript, TooltoolMixin, CodeCoverageMixin):
|
||||||
"default": False,
|
"default": False,
|
||||||
"help": "Tries to enable the WebRender compositor.",
|
"help": "Tries to enable the WebRender compositor.",
|
||||||
}],
|
}],
|
||||||
|
[["--disable-webrender"],
|
||||||
|
{"action": "store_true",
|
||||||
|
"dest": "disable_webrender",
|
||||||
|
"default": False,
|
||||||
|
"help": "Force-disables the WebRender compositor.",
|
||||||
|
}],
|
||||||
[["--base"],
|
[["--base"],
|
||||||
{"action": "store_true",
|
{"action": "store_true",
|
||||||
"dest": "test_about_blank",
|
"dest": "test_about_blank",
|
||||||
|
@ -232,6 +238,11 @@ class AWSY(TestingMixin, MercurialScript, TooltoolMixin, CodeCoverageMixin):
|
||||||
env['MOZ_WEBRENDER'] = '1'
|
env['MOZ_WEBRENDER'] = '1'
|
||||||
env['MOZ_ACCELERATED'] = '1'
|
env['MOZ_ACCELERATED'] = '1'
|
||||||
|
|
||||||
|
# Allow explicitly disabling webrender, so that we don't run WR on non-QR
|
||||||
|
# test platforms just because they run on qualified hardware.
|
||||||
|
if self.config['disable_webrender']:
|
||||||
|
env['MOZ_WEBRENDER'] = '0'
|
||||||
|
|
||||||
env['MOZ_UPLOAD_DIR'] = dirs['abs_blob_upload_dir']
|
env['MOZ_UPLOAD_DIR'] = dirs['abs_blob_upload_dir']
|
||||||
if not os.path.isdir(env['MOZ_UPLOAD_DIR']):
|
if not os.path.isdir(env['MOZ_UPLOAD_DIR']):
|
||||||
self.mkdir_p(env['MOZ_UPLOAD_DIR'])
|
self.mkdir_p(env['MOZ_UPLOAD_DIR'])
|
||||||
|
|
|
@ -140,10 +140,13 @@ button > .button-box {
|
||||||
|
|
||||||
.study-name {
|
.study-name {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-bottom: 0.3em;
|
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.study-header {
|
||||||
|
margin-bottom: .3em;
|
||||||
|
}
|
||||||
|
|
||||||
.study-header > * {
|
.study-header > * {
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
@ -153,7 +156,13 @@ button > .button-box {
|
||||||
}
|
}
|
||||||
|
|
||||||
.study-description code {
|
.study-description code {
|
||||||
font: italic 1.0rem 'Fira Mono', 'mono', 'monospace';
|
background-color: var(--grey-20);
|
||||||
|
border-radius: 3px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: var(--in-content-text-color);
|
||||||
|
font-size: 85%;
|
||||||
|
font-family: 'Fira Mono', 'mono', monospace;
|
||||||
|
padding: .2em .4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.study-actions {
|
.study-actions {
|
||||||
|
|
|
@ -13211,6 +13211,15 @@
|
||||||
"n_buckets": 50,
|
"n_buckets": 50,
|
||||||
"description": "The time, in percentage of a vsync interval, spent from beginning a paint in the content process until that frame is presented in the compositor by WebRender, excluding time spent uploading any content"
|
"description": "The time, in percentage of a vsync interval, spent from beginning a paint in the content process until that frame is presented in the compositor by WebRender, excluding time spent uploading any content"
|
||||||
},
|
},
|
||||||
|
"CONTENT_FRAME_TIME_REASON": {
|
||||||
|
"record_in_processes": ["main", "gpu"],
|
||||||
|
"alert_emails": ["gfx-telemetry-alerts@mozilla.com", "mwoodrow@mozilla.com"],
|
||||||
|
"bug_numbers": [1510853],
|
||||||
|
"expires_in_version": "73",
|
||||||
|
"kind": "categorical",
|
||||||
|
"description": "The reason that CONTENT_FRAME_TIME recorded a slow (>200) result, if any.",
|
||||||
|
"labels": ["OnTime", "NoVsync", "MissedComposite", "SlowComposite"]
|
||||||
|
},
|
||||||
"CONTENT_LARGE_PAINT_PHASE_WEIGHT": {
|
"CONTENT_LARGE_PAINT_PHASE_WEIGHT": {
|
||||||
"record_in_processes": ["main", "content"],
|
"record_in_processes": ["main", "content"],
|
||||||
"alert_emails": ["gfx-telemetry-alerts@mozilla.com", "mwoodrow@mozilla.com"],
|
"alert_emails": ["gfx-telemetry-alerts@mozilla.com", "mwoodrow@mozilla.com"],
|
||||||
|
|
|
@ -414,9 +414,12 @@ void SetVsyncObserver(VsyncObserver* aObserver) {
|
||||||
gVsyncObserver = aObserver;
|
gVsyncObserver = aObserver;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void NotifyVsyncObserver() {
|
void NotifyVsyncObserver() {
|
||||||
if (gVsyncObserver) {
|
if (gVsyncObserver) {
|
||||||
gVsyncObserver->NotifyVsync(TimeStamp::Now());
|
static VsyncId vsyncId;
|
||||||
|
vsyncId = vsyncId.Next();
|
||||||
|
VsyncEvent event(vsyncId, TimeStamp::Now());
|
||||||
|
gVsyncObserver->NotifyVsync(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,14 +27,13 @@ CompositorVsyncDispatcher::~CompositorVsyncDispatcher() {
|
||||||
// nsBaseWidget
|
// nsBaseWidget
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp) {
|
void CompositorVsyncDispatcher::NotifyVsync(const VsyncEvent& aVsync) {
|
||||||
// In vsync thread
|
// In vsync thread
|
||||||
layers::CompositorBridgeParent::PostInsertVsyncProfilerMarker(
|
layers::CompositorBridgeParent::PostInsertVsyncProfilerMarker(aVsync.mTime);
|
||||||
aVsyncTimestamp);
|
|
||||||
|
|
||||||
MutexAutoLock lock(mCompositorObserverLock);
|
MutexAutoLock lock(mCompositorObserverLock);
|
||||||
if (mCompositorVsyncObserver) {
|
if (mCompositorVsyncObserver) {
|
||||||
mCompositorVsyncObserver->NotifyVsync(aVsyncTimestamp);
|
mCompositorVsyncObserver->NotifyVsync(aVsync);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,15 +100,15 @@ RefreshTimerVsyncDispatcher::~RefreshTimerVsyncDispatcher() {
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RefreshTimerVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp) {
|
void RefreshTimerVsyncDispatcher::NotifyVsync(const VsyncEvent& aVsync) {
|
||||||
MutexAutoLock lock(mRefreshTimersLock);
|
MutexAutoLock lock(mRefreshTimersLock);
|
||||||
|
|
||||||
for (size_t i = 0; i < mChildRefreshTimers.Length(); i++) {
|
for (size_t i = 0; i < mChildRefreshTimers.Length(); i++) {
|
||||||
mChildRefreshTimers[i]->NotifyVsync(aVsyncTimestamp);
|
mChildRefreshTimers[i]->NotifyVsync(aVsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mParentRefreshTimer) {
|
if (mParentRefreshTimer) {
|
||||||
mParentRefreshTimer->NotifyVsync(aVsyncTimestamp);
|
mParentRefreshTimer->NotifyVsync(aVsync);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "nsISupportsImpl.h"
|
#include "nsISupportsImpl.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "VsyncSource.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
@ -23,7 +24,7 @@ class VsyncObserver {
|
||||||
// thread from VsyncSource. But it might also be called on PVsync ipc thread
|
// thread from VsyncSource. But it might also be called on PVsync ipc thread
|
||||||
// if this notification is cross process. Thus all observer should check the
|
// if this notification is cross process. Thus all observer should check the
|
||||||
// thread model before handling the real task.
|
// thread model before handling the real task.
|
||||||
virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) = 0;
|
virtual bool NotifyVsync(const VsyncEvent& aVsync) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
VsyncObserver() {}
|
VsyncObserver() {}
|
||||||
|
@ -49,7 +50,7 @@ class CompositorVsyncDispatcher final {
|
||||||
CompositorVsyncDispatcher();
|
CompositorVsyncDispatcher();
|
||||||
|
|
||||||
// Called on the vsync thread when a hardware vsync occurs
|
// Called on the vsync thread when a hardware vsync occurs
|
||||||
void NotifyVsync(TimeStamp aVsyncTimestamp);
|
void NotifyVsync(const VsyncEvent& aVsync);
|
||||||
|
|
||||||
// Compositor vsync observers must be added/removed on the compositor thread
|
// Compositor vsync observers must be added/removed on the compositor thread
|
||||||
void SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
|
void SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
|
||||||
|
@ -72,7 +73,7 @@ class RefreshTimerVsyncDispatcher final {
|
||||||
RefreshTimerVsyncDispatcher();
|
RefreshTimerVsyncDispatcher();
|
||||||
|
|
||||||
// Please check CompositorVsyncDispatcher::NotifyVsync().
|
// Please check CompositorVsyncDispatcher::NotifyVsync().
|
||||||
void NotifyVsync(TimeStamp aVsyncTimestamp);
|
void NotifyVsync(const VsyncEvent& aVsync);
|
||||||
|
|
||||||
// Set chrome process's RefreshTimer to this dispatcher.
|
// Set chrome process's RefreshTimer to this dispatcher.
|
||||||
// This function can be called from any thread.
|
// This function can be called from any thread.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче