Bug 1196308 - Delete Software Compositor Scheduler. r=sotaro

This commit is contained in:
Mason Chang 2015-08-20 17:57:42 -07:00
parent 79c8a43d05
commit 2471ad297f
2 changed files with 97 additions and 227 deletions

View File

@ -224,81 +224,14 @@ static void SetThreadPriority()
hal::SetCurrentThreadPriority(hal::THREAD_PRIORITY_COMPOSITOR);
}
CompositorScheduler::CompositorScheduler(CompositorParent* aCompositorParent)
: mCompositorParent(aCompositorParent)
, mCurrentCompositeTask(nullptr)
{
}
CompositorScheduler::~CompositorScheduler()
{
MOZ_ASSERT(!mCompositorParent);
}
void
CompositorScheduler::CancelCurrentCompositeTask()
{
if (mCurrentCompositeTask) {
mCurrentCompositeTask->Cancel();
mCurrentCompositeTask = nullptr;
}
}
void
CompositorScheduler::ScheduleTask(CancelableTask* aTask, int aTime)
{
MOZ_ASSERT(CompositorParent::CompositorLoop());
MOZ_ASSERT(aTime >= 0);
CompositorParent::CompositorLoop()->PostDelayedTask(FROM_HERE, aTask, aTime);
}
void
CompositorScheduler::ResumeComposition()
{
mLastCompose = TimeStamp::Now();
ComposeToTarget(nullptr);
}
void
CompositorScheduler::ForceComposeToTarget(gfx::DrawTarget* aTarget, const IntRect* aRect)
{
mLastCompose = TimeStamp::Now();
ComposeToTarget(aTarget, aRect);
}
void
CompositorScheduler::ComposeToTarget(gfx::DrawTarget* aTarget, const IntRect* aRect)
{
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
MOZ_ASSERT(mCompositorParent);
mCompositorParent->CompositeToTarget(aTarget, aRect);
}
void
CompositorScheduler::Destroy()
{
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
CancelCurrentCompositeTask();
mCompositorParent = nullptr;
}
CompositorSoftwareTimerScheduler::CompositorSoftwareTimerScheduler(CompositorParent* aCompositorParent)
: CompositorScheduler(aCompositorParent)
{
}
CompositorSoftwareTimerScheduler::~CompositorSoftwareTimerScheduler()
{
MOZ_ASSERT(!mCurrentCompositeTask);
}
// Used when layout.frame_rate is -1. Needs to be kept in sync with
// DEFAULT_FRAME_RATE in nsRefreshDriver.cpp.
static const int32_t kDefaultFrameRate = 60;
#ifdef COMPOSITOR_PERFORMANCE_WARNING
static int32_t
CalculateCompositionFrameRate()
{
// Used when layout.frame_rate is -1. Needs to be kept in sync with
// DEFAULT_FRAME_RATE in nsRefreshDriver.cpp.
// TODO: This should actually return the vsync rate.
const int32_t defaultFrameRate = 60;
int32_t compositionFrameRatePref = gfxPrefs::LayersCompositionFrameRate();
if (compositionFrameRatePref < 0) {
// Use the same frame rate for composition as for layout.
@ -306,68 +239,13 @@ CalculateCompositionFrameRate()
if (layoutFrameRatePref < 0) {
// TODO: The main thread frame scheduling code consults the actual
// monitor refresh rate in this case. We should do the same.
return kDefaultFrameRate;
return defaultFrameRate;
}
return layoutFrameRatePref;
}
return compositionFrameRatePref;
}
void
CompositorSoftwareTimerScheduler::ScheduleComposition()
{
if (mCurrentCompositeTask) {
return;
}
bool initialComposition = mLastCompose.IsNull();
TimeDuration delta;
if (!initialComposition) {
delta = TimeStamp::Now() - mLastCompose;
}
int32_t rate = CalculateCompositionFrameRate();
// If rate == 0 (ASAP mode), minFrameDelta must be 0 so there's no delay.
TimeDuration minFrameDelta = TimeDuration::FromMilliseconds(
rate == 0 ? 0.0 : std::max(0.0, 1000.0 / rate));
mCurrentCompositeTask = NewRunnableMethod(this,
&CompositorSoftwareTimerScheduler::CallComposite);
if (!initialComposition && delta < minFrameDelta) {
TimeDuration delay = minFrameDelta - delta;
#ifdef COMPOSITOR_PERFORMANCE_WARNING
mExpectedComposeStartTime = TimeStamp::Now() + delay;
#endif
ScheduleTask(mCurrentCompositeTask, delay.ToMilliseconds());
} else {
#ifdef COMPOSITOR_PERFORMANCE_WARNING
mExpectedComposeStartTime = TimeStamp::Now();
#endif
ScheduleTask(mCurrentCompositeTask, 0);
}
}
bool
CompositorSoftwareTimerScheduler::NeedsComposite()
{
return mCurrentCompositeTask ? true : false;
}
void
CompositorSoftwareTimerScheduler::CallComposite()
{
Composite(TimeStamp::Now());
}
void
CompositorSoftwareTimerScheduler::Composite(TimeStamp aTimestamp)
{
mCurrentCompositeTask = nullptr;
mLastCompose = aTimestamp;
ComposeToTarget(nullptr);
}
CompositorVsyncScheduler::Observer::Observer(CompositorVsyncScheduler* aOwner)
: mMutex("CompositorVsyncScheduler.Observer.Mutex")
@ -398,11 +276,12 @@ CompositorVsyncScheduler::Observer::Destroy()
}
CompositorVsyncScheduler::CompositorVsyncScheduler(CompositorParent* aCompositorParent, nsIWidget* aWidget)
: CompositorScheduler(aCompositorParent)
: mCompositorParent(aCompositorParent)
, mLastCompose(TimeStamp::Now())
, mCurrentCompositeTask(nullptr)
, mNeedsComposite(false)
, mIsObservingVsync(false)
, mVsyncNotificationsSkipped(0)
, mCompositorParent(aCompositorParent)
, mCurrentCompositeTaskMonitor("CurrentCompositeTaskMonitor")
, mSetNeedsCompositeMonitor("SetNeedsCompositeMonitor")
, mSetNeedsCompositeTask(nullptr)
@ -414,6 +293,11 @@ CompositorVsyncScheduler::CompositorVsyncScheduler(CompositorParent* aCompositor
#ifdef MOZ_WIDGET_GONK
GeckoTouchDispatcher::GetInstance()->SetCompositorVsyncScheduler(this);
#endif
// mAsapScheduling is set on the main thread during init,
// but is only accessed after on the compositor thread.
mAsapScheduling = gfxPrefs::LayersCompositionFrameRate() == 0 ||
gfxPlatform::IsInLayoutAsapMode();
}
CompositorVsyncScheduler::~CompositorVsyncScheduler()
@ -433,13 +317,32 @@ CompositorVsyncScheduler::Destroy()
mVsyncObserver->Destroy();
mVsyncObserver = nullptr;
CancelCurrentSetNeedsCompositeTask();
CompositorScheduler::Destroy();
CancelCurrentCompositeTask();
}
void
CompositorVsyncScheduler::PostCompositeTask(TimeStamp aCompositeTimestamp)
{
// can be called from the compositor or vsync thread
MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
if (mCurrentCompositeTask == nullptr) {
mCurrentCompositeTask = NewRunnableMethod(this,
&CompositorVsyncScheduler::Composite,
aCompositeTimestamp);
ScheduleTask(mCurrentCompositeTask, 0);
}
}
void
CompositorVsyncScheduler::ScheduleComposition()
{
SetNeedsComposite(true);
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
if (mAsapScheduling) {
// Used only for performance testing purposes
PostCompositeTask(TimeStamp::Now());
} else {
SetNeedsComposite(true);
}
}
void
@ -488,14 +391,7 @@ CompositorVsyncScheduler::NotifyVsync(TimeStamp aVsyncTimestamp)
// Called from the vsync dispatch thread
MOZ_ASSERT(!CompositorParent::IsInCompositorThread());
MOZ_ASSERT(!NS_IsMainThread());
MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
if (mCurrentCompositeTask == nullptr) {
mCurrentCompositeTask = NewRunnableMethod(this,
&CompositorVsyncScheduler::Composite,
aVsyncTimestamp);
ScheduleTask(mCurrentCompositeTask, 0);
}
PostCompositeTask(aVsyncTimestamp);
return true;
}
@ -504,7 +400,10 @@ CompositorVsyncScheduler::CancelCurrentCompositeTask()
{
MOZ_ASSERT(CompositorParent::IsInCompositorThread() || NS_IsMainThread());
MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
CompositorScheduler::CancelCurrentCompositeTask();
if (mCurrentCompositeTask) {
mCurrentCompositeTask->Cancel();
mCurrentCompositeTask = nullptr;
}
}
void
@ -518,7 +417,7 @@ CompositorVsyncScheduler::Composite(TimeStamp aVsyncTimestamp)
DispatchTouchEvents(aVsyncTimestamp);
if (mNeedsComposite) {
if (mNeedsComposite || mAsapScheduling) {
mNeedsComposite = false;
mLastCompose = aVsyncTimestamp;
ComposeToTarget(nullptr);
@ -549,7 +448,8 @@ void
CompositorVsyncScheduler::ForceComposeToTarget(gfx::DrawTarget* aTarget, const IntRect* aRect)
{
OnForceComposeToTarget();
CompositorScheduler::ForceComposeToTarget(aTarget, aRect);
mLastCompose = TimeStamp::Now();
ComposeToTarget(aTarget, aRect);
}
bool
@ -613,22 +513,27 @@ MessageLoop* CompositorParent::CompositorLoop()
return CompositorThread() ? CompositorThread()->message_loop() : nullptr;
}
static bool
IsInCompositorAsapMode()
void
CompositorVsyncScheduler::ScheduleTask(CancelableTask* aTask, int aTime)
{
// Returns true if the compositor is allowed to be in ASAP mode
// and layout is not in ASAP mode
return gfxPrefs::LayersCompositionFrameRate() == 0 &&
!gfxPlatform::IsInLayoutAsapMode();
MOZ_ASSERT(CompositorParent::CompositorLoop());
MOZ_ASSERT(aTime >= 0);
CompositorParent::CompositorLoop()->PostDelayedTask(FROM_HERE, aTask, aTime);
}
static bool
UseVsyncComposition()
void
CompositorVsyncScheduler::ResumeComposition()
{
return gfxPrefs::VsyncAlignedCompositor()
&& gfxPrefs::HardwareVsyncEnabled()
&& !IsInCompositorAsapMode()
&& !gfxPlatform::IsInLayoutAsapMode();
mLastCompose = TimeStamp::Now();
ComposeToTarget(nullptr);
}
void
CompositorVsyncScheduler::ComposeToTarget(gfx::DrawTarget* aTarget, const IntRect* aRect)
{
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
MOZ_ASSERT(mCompositorParent);
mCompositorParent->CompositeToTarget(aTarget, aRect);
}
CompositorParent::CompositorParent(nsIWidget* aWidget,
@ -675,12 +580,8 @@ CompositorParent::CompositorParent(nsIWidget* aWidget,
mApzcTreeManager = new APZCTreeManager();
}
if (UseVsyncComposition()) {
gfxDebugOnce() << "Enabling vsync compositor";
mCompositorScheduler = new CompositorVsyncScheduler(this, aWidget);
} else {
mCompositorScheduler = new CompositorSoftwareTimerScheduler(this);
}
gfxDebugOnce() << "Enabling vsync compositor";
mCompositorScheduler = new CompositorVsyncScheduler(this, aWidget);
LayerScope::SetPixelScale(mWidget->GetDefaultScale().scale);
}

View File

@ -88,21 +88,31 @@ private:
friend class CompositorParent;
};
class CompositorScheduler
/**
* Manages the vsync (de)registration and tracking on behalf of the
* compositor when it need to paint.
* Turns vsync notifications into scheduled composites.
**/
class CompositorVsyncScheduler
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorScheduler)
explicit CompositorScheduler(CompositorParent* aCompositorParent);
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorVsyncScheduler)
virtual void ScheduleComposition() = 0;
virtual void CancelCurrentCompositeTask();
virtual bool NeedsComposite() = 0;
virtual void Composite(TimeStamp aTimestamp) = 0;
virtual void ScheduleTask(CancelableTask*, int);
virtual void ResumeComposition();
virtual void ForceComposeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect);
virtual void ComposeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr);
virtual void Destroy();
public:
explicit CompositorVsyncScheduler(CompositorParent* aCompositorParent, nsIWidget* aWidget);
bool NotifyVsync(TimeStamp aVsyncTimestamp);
void SetNeedsComposite(bool aSchedule);
void OnForceComposeToTarget();
void ScheduleTask(CancelableTask*, int);
void ResumeComposition();
void ComposeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr);
void PostCompositeTask(TimeStamp aCompositeTimestamp);
void Destroy();
void ScheduleComposition();
void CancelCurrentCompositeTask();
bool NeedsComposite();
void Composite(TimeStamp aVsyncTimestamp);
void ForceComposeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect);
const TimeStamp& GetLastComposeTime()
{
@ -115,56 +125,7 @@ public:
return mExpectedComposeStartTime;
}
#endif
protected:
virtual ~CompositorScheduler();
CompositorParent* mCompositorParent;
TimeStamp mLastCompose;
CancelableTask* mCurrentCompositeTask;
#ifdef COMPOSITOR_PERFORMANCE_WARNING
TimeStamp mExpectedComposeStartTime;
#endif
};
class CompositorSoftwareTimerScheduler final : public CompositorScheduler
{
public:
explicit CompositorSoftwareTimerScheduler(CompositorParent* aCompositorParent);
// from CompositorScheduler
virtual void ScheduleComposition() override;
virtual bool NeedsComposite() override;
virtual void Composite(TimeStamp aTimestamp) override;
void CallComposite();
private:
virtual ~CompositorSoftwareTimerScheduler();
};
/**
* Manages the vsync (de)registration and tracking on behalf of the
* compositor when it need to paint.
* Turns vsync notifications into scheduled composites.
**/
class CompositorVsyncScheduler final : public CompositorScheduler
{
public:
explicit CompositorVsyncScheduler(CompositorParent* aCompositorParent, nsIWidget* aWidget);
bool NotifyVsync(TimeStamp aVsyncTimestamp);
void SetNeedsComposite(bool aSchedule);
void OnForceComposeToTarget();
// from CompositorScheduler
virtual void ScheduleComposition() override;
virtual void CancelCurrentCompositeTask() override;
virtual bool NeedsComposite() override;
virtual void Composite(TimeStamp aVsyncTimestamp) override;
virtual void ForceComposeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect) override;
virtual void Destroy() override;
private:
virtual ~CompositorVsyncScheduler();
@ -188,10 +149,18 @@ private:
CompositorVsyncScheduler* mOwner;
};
CompositorParent* mCompositorParent;
TimeStamp mLastCompose;
CancelableTask* mCurrentCompositeTask;
#ifdef COMPOSITOR_PERFORMANCE_WARNING
TimeStamp mExpectedComposeStartTime;
#endif
bool mAsapScheduling;
bool mNeedsComposite;
bool mIsObservingVsync;
int32_t mVsyncNotificationsSkipped;
CompositorParent* mCompositorParent;
nsRefPtr<CompositorVsyncDispatcher> mCompositorVsyncDispatcher;
nsRefPtr<CompositorVsyncScheduler::Observer> mVsyncObserver;
@ -216,7 +185,7 @@ class CompositorParent final : public PCompositorParent,
public ShadowLayersManager
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorParent)
friend class CompositorScheduler;
friend class CompositorVsyncScheduler;
public:
explicit CompositorParent(nsIWidget* aWidget,
@ -498,7 +467,7 @@ protected:
nsRefPtr<APZCTreeManager> mApzcTreeManager;
nsRefPtr<CompositorThreadHolder> mCompositorThreadHolder;
nsRefPtr<CompositorScheduler> mCompositorScheduler;
nsRefPtr<CompositorVsyncScheduler> mCompositorScheduler;
DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
};