Bug 1055050 - Add visual warning if the transaction latency is > 100 ms. r=mwoodrow

--HG--
extra : rebase_source : 23140892b8e598c7073dd1b8c83fbddfa0bf52ee
This commit is contained in:
Benoit Girard 2014-08-28 15:24:26 -04:00
parent 643c02ae7c
commit d83f3e3d33
12 changed files with 110 additions and 10 deletions

View File

@ -7,6 +7,7 @@
#define GFX_TRANSACTION_ID_ALLOCATOR_H
#include "nsISupportsImpl.h"
#include "mozilla/TimeStamp.h"
namespace mozilla {
namespace layers {
@ -44,6 +45,11 @@ public:
* return ordering issues.
*/
virtual void RevokeTransactionId(uint64_t aTransactionId) = 0;
/**
* Get the start time of the current refresh tick.
*/
virtual mozilla::TimeStamp GetTransactionStart() = 0;
};
}

View File

@ -129,6 +129,7 @@ void
ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
{
mInTransaction = true;
mTransactionStart = TimeStamp::Now();
#ifdef MOZ_LAYERS_HAVE_LOG
MOZ_LAYERS_LOG(("[----- BeginTransaction"));
@ -184,7 +185,6 @@ ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
void
ClientLayerManager::BeginTransaction()
{
mInTransaction = true;
BeginTransactionWithTarget(nullptr);
}
@ -260,6 +260,9 @@ ClientLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
for (size_t i = 0; i < mTexturePools.Length(); i++) {
mTexturePools[i]->ReturnDeferredClients();
}
mInTransaction = false;
mTransactionStart = TimeStamp();
}
bool
@ -448,13 +451,19 @@ ClientLayerManager::ForwardTransaction(bool aScheduleComposite)
mPhase = PHASE_FORWARD;
mLatestTransactionId = mTransactionIdAllocator->GetTransactionId();
TimeStamp transactionStart;
if (!mTransactionIdAllocator->GetTransactionStart().IsNull()) {
transactionStart = mTransactionIdAllocator->GetTransactionStart();
} else {
transactionStart = mTransactionStart;
}
// forward this transaction's changeset to our LayerManagerComposite
bool sent;
AutoInfallibleTArray<EditReply, 10> replies;
if (mForwarder->EndTransaction(&replies, mRegionToClear,
mLatestTransactionId, aScheduleComposite, mPaintSequenceNumber,
mIsRepeatTransaction, &sent)) {
mIsRepeatTransaction, transactionStart, &sent)) {
for (nsTArray<EditReply>::size_type i = 0; i < replies.Length(); ++i) {
const EditReply& reply = replies[i];

View File

@ -300,6 +300,7 @@ private:
RefPtr<ShadowLayerForwarder> mForwarder;
nsAutoTArray<RefPtr<TextureClientPool>,2> mTexturePools;
nsAutoTArray<dom::OverfillCallback*,0> mOverfillCallbacks;
mozilla::TimeStamp mTransactionStart;
// indexed by gfx::SurfaceFormat
nsTArray<RefPtr<SimpleTextureClientPool> > mSimpleTilePools;

View File

@ -339,13 +339,53 @@ LayerManagerComposite::RenderDebugOverlay(const Rect& aBounds)
bool drawFrameCounter = gfxPrefs::DrawFrameCounter();
bool drawFrameColorBars = gfxPrefs::CompositorDrawColorBars();
TimeStamp now = TimeStamp::Now();
if (drawFps) {
if (!mFPS) {
mFPS = MakeUnique<FPSState>();
}
#ifdef ANDROID
// Draw a translation delay warning overlay
int width;
int border;
float alpha = 1;
if ((now - mWarnTime).ToMilliseconds() < 150) {
printf_stderr("Draw\n");
EffectChain effects;
// Black blorder
border = 4;
width = 6;
effects.mPrimaryEffect = new EffectSolidColor(gfx::Color(0, 0, 0, 1));
mCompositor->DrawQuad(gfx::Rect(border, border, aBounds.width - 2 * border, width),
aBounds, effects, alpha, gfx::Matrix4x4());
mCompositor->DrawQuad(gfx::Rect(border, aBounds.height - border - width, aBounds.width - 2 * border, width),
aBounds, effects, alpha, gfx::Matrix4x4());
mCompositor->DrawQuad(gfx::Rect(border, border + width, width, aBounds.height - 2 * border - width * 2),
aBounds, effects, alpha, gfx::Matrix4x4());
mCompositor->DrawQuad(gfx::Rect(aBounds.width - border - width, border + width, width, aBounds.height - 2 * border - 2 * width),
aBounds, effects, alpha, gfx::Matrix4x4());
// Content
border = 5;
width = 4;
effects.mPrimaryEffect = new EffectSolidColor(gfx::Color(1, 1.f - mWarningLevel, 0, 1));
mCompositor->DrawQuad(gfx::Rect(border, border, aBounds.width - 2 * border, width),
aBounds, effects, alpha, gfx::Matrix4x4());
mCompositor->DrawQuad(gfx::Rect(border, aBounds.height - border - width, aBounds.width - 2 * border, width),
aBounds, effects, alpha, gfx::Matrix4x4());
mCompositor->DrawQuad(gfx::Rect(border, border + width, width, aBounds.height - 2 * border - width * 2),
aBounds, effects, alpha, gfx::Matrix4x4());
mCompositor->DrawQuad(gfx::Rect(aBounds.width - border - width, border + width, width, aBounds.height - 2 * border - 2 * width),
aBounds, effects, alpha, gfx::Matrix4x4());
SetDebugOverlayWantsNextFrame(true);
}
#endif
float fillRatio = mCompositor->GetFillRatio();
mFPS->DrawFPS(TimeStamp::Now(), drawFrameColorBars ? 10 : 0, 0, unsigned(fillRatio), mCompositor);
mFPS->DrawFPS(now, drawFrameColorBars ? 10 : 0, 0, unsigned(fillRatio), mCompositor);
} else {
mFPS = nullptr;
}

View File

@ -239,6 +239,19 @@ public:
TextRenderer* GetTextRenderer() { return mTextRenderer; }
/**
* Add an on frame warning.
* @param severity ranges from 0 to 1. It's used to compute the warning color.
*/
void VisualFrameWarning(float severity) {
mozilla::TimeStamp now = TimeStamp::Now();
if (severity > mWarningLevel ||
mWarnTime + TimeDuration::FromMilliseconds(1500) < now) {
mWarnTime = now;
mWarningLevel = severity;
}
}
private:
/** Region we're clipping our current drawing to. */
nsIntRegion mClippingRegion;
@ -277,6 +290,8 @@ private:
bool aInvertEffect,
float aContrastEffect);
float mWarningLevel;
mozilla::TimeStamp mWarnTime;
RefPtr<Compositor> mCompositor;
UniquePtr<LayerProperties> mClonedLayerTreeProperties;

View File

@ -185,10 +185,12 @@ LayerTransactionParent::RecvUpdateNoSwap(const InfallibleTArray<Edit>& cset,
const bool& isFirstPaint,
const bool& scheduleComposite,
const uint32_t& paintSequenceNumber,
const bool& isRepeatTransaction)
const bool& isRepeatTransaction,
const mozilla::TimeStamp& aTransactionStart)
{
return RecvUpdate(cset, aTransactionId, targetConfig, isFirstPaint,
scheduleComposite, paintSequenceNumber, isRepeatTransaction, nullptr);
scheduleComposite, paintSequenceNumber, isRepeatTransaction,
aTransactionStart, nullptr);
}
bool
@ -199,6 +201,7 @@ LayerTransactionParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
const bool& scheduleComposite,
const uint32_t& paintSequenceNumber,
const bool& isRepeatTransaction,
const mozilla::TimeStamp& aTransactionStart,
InfallibleTArray<EditReply>* reply)
{
profiler_tracing("Paint", "Composite", TRACING_INTERVAL_START);
@ -569,6 +572,16 @@ LayerTransactionParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
}
#endif
TimeDuration latency = TimeStamp::Now() - aTransactionStart;
// Theshold is 200ms to trigger, 1000ms to hit red
if (latency > TimeDuration::FromMilliseconds(200)) {
float severity = (latency - TimeDuration::FromMilliseconds(200)).ToMilliseconds() / 800;
if (severity > 1.f) {
severity = 1.f;
}
mLayerManager->VisualFrameWarning(severity);
}
return true;
}

View File

@ -105,6 +105,7 @@ protected:
const bool& scheduleComposite,
const uint32_t& paintSequenceNumber,
const bool& isRepeatTransaction,
const mozilla::TimeStamp& aTransactionStart,
EditReplyArray* reply) MOZ_OVERRIDE;
virtual bool RecvUpdateNoSwap(const EditArray& cset,
@ -113,7 +114,8 @@ protected:
const bool& isFirstPaint,
const bool& scheduleComposite,
const uint32_t& paintSequenceNumber,
const bool& isRepeatTransaction) MOZ_OVERRIDE;
const bool& isRepeatTransaction,
const mozilla::TimeStamp& aTransactionStart) MOZ_OVERRIDE;
virtual bool RecvClearCachedResources() MOZ_OVERRIDE;
virtual bool RecvForceComposite() MOZ_OVERRIDE;

View File

@ -55,14 +55,14 @@ parent:
// for a particular document.
sync Update(Edit[] cset, uint64_t id, TargetConfig targetConfig, bool isFirstPaint,
bool scheduleComposite, uint32_t paintSequenceNumber,
bool isRepeatTransaction)
bool isRepeatTransaction, TimeStamp transactionStart)
returns (EditReply[] reply);
// We don't need to send a sync transaction if
// no transaction operate require a swap.
async UpdateNoSwap(Edit[] cset, uint64_t id, TargetConfig targetConfig, bool isFirstPaint,
bool scheduleComposite, uint32_t paintSequenceNumber,
bool isRepeatTransaction);
bool isRepeatTransaction, TimeStamp transactionStart);
// Testing APIs

View File

@ -529,6 +529,7 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies,
bool aScheduleComposite,
uint32_t aPaintSequenceNumber,
bool aIsRepeatTransaction,
const mozilla::TimeStamp& aTransactionStart,
bool* aSent)
{
*aSent = false;
@ -653,7 +654,8 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies,
!mShadowManager->IPCOpen() ||
!mShadowManager->SendUpdate(cset, aId, targetConfig, mIsFirstPaint,
aScheduleComposite, aPaintSequenceNumber,
aIsRepeatTransaction, aReplies)) {
aIsRepeatTransaction, aTransactionStart,
aReplies)) {
MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!"));
return false;
}
@ -666,7 +668,7 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies,
!mShadowManager->IPCOpen() ||
!mShadowManager->SendUpdateNoSwap(cset, aId, targetConfig, mIsFirstPaint,
aScheduleComposite, aPaintSequenceNumber,
aIsRepeatTransaction)) {
aIsRepeatTransaction, aTransactionStart)) {
MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!"));
return false;
}

View File

@ -306,6 +306,7 @@ public:
bool aScheduleComposite,
uint32_t aPaintSequenceNumber,
bool aIsRepeatTransaction,
const mozilla::TimeStamp& aTransactionStart,
bool* aSent);
/**

View File

@ -1108,6 +1108,9 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
AutoRestore<bool> restoreInRefresh(mInRefresh);
mInRefresh = true;
AutoRestore<TimeStamp> restoreTickStart(mTickStart);
mTickStart = TimeStamp::Now();
/*
* The timer holds a reference to |this| while calling |Notify|.
* However, implementations of |WillRefresh| are permitted to destroy
@ -1432,6 +1435,12 @@ nsRefreshDriver::RevokeTransactionId(uint64_t aTransactionId)
mPendingTransaction--;
}
mozilla::TimeStamp
nsRefreshDriver::GetTransactionStart()
{
return mTickStart;
}
void
nsRefreshDriver::NotifyTransactionCompleted(uint64_t aTransactionId)
{

View File

@ -275,6 +275,7 @@ public:
virtual uint64_t GetTransactionId() MOZ_OVERRIDE;
void NotifyTransactionCompleted(uint64_t aTransactionId) MOZ_OVERRIDE;
void RevokeTransactionId(uint64_t aTransactionId) MOZ_OVERRIDE;
mozilla::TimeStamp GetTransactionStart() MOZ_OVERRIDE;
bool IsWaitingForPaint(mozilla::TimeStamp aTime);
@ -360,6 +361,7 @@ private:
int64_t mMostRecentRefreshEpochTime;
mozilla::TimeStamp mMostRecentRefresh;
mozilla::TimeStamp mMostRecentTick;
mozilla::TimeStamp mTickStart;
// separate arrays for each flush type we support
ObserverArray mObservers[3];