mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1102631 - Create a software vsync timer. r=kats
This commit is contained in:
parent
483f9be18f
commit
4b9c7c9fe3
116
gfx/thebes/SoftwareVsyncSource.cpp
Normal file
116
gfx/thebes/SoftwareVsyncSource.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "SoftwareVsyncSource.h"
|
||||
#include "base/task.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
SoftwareVsyncSource::SoftwareVsyncSource()
|
||||
{
|
||||
mGlobalDisplay = new SoftwareDisplay();
|
||||
}
|
||||
|
||||
SoftwareVsyncSource::~SoftwareVsyncSource()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// Ensure we disable vsync on the main thread here
|
||||
mGlobalDisplay->DisableVsync();
|
||||
mGlobalDisplay = nullptr;
|
||||
}
|
||||
|
||||
SoftwareDisplay::SoftwareDisplay()
|
||||
: mCurrentTaskMonitor("SoftwareVsyncCurrentTaskMonitor")
|
||||
{
|
||||
// Mimic 60 fps
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
const double rate = 1000 / 60.0;
|
||||
mVsyncRate = mozilla::TimeDuration::FromMilliseconds(rate);
|
||||
mVsyncThread = new base::Thread("SoftwareVsyncThread");
|
||||
EnableVsync();
|
||||
}
|
||||
|
||||
void
|
||||
SoftwareDisplay::EnableVsync()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mozilla::MonitorAutoLock lock(mCurrentTaskMonitor);
|
||||
mVsyncEnabled = true;
|
||||
MOZ_ASSERT(!mVsyncThread->IsRunning());
|
||||
MOZ_RELEASE_ASSERT(mVsyncThread->Start(), "Could not start software vsync thread");
|
||||
mCurrentVsyncTask = NewRunnableMethod(this,
|
||||
&SoftwareDisplay::NotifyVsync,
|
||||
mozilla::TimeStamp::Now());
|
||||
mVsyncThread->message_loop()->PostTask(FROM_HERE, mCurrentVsyncTask);
|
||||
}
|
||||
|
||||
void
|
||||
SoftwareDisplay::DisableVsync()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mVsyncThread->IsRunning());
|
||||
{ // Scope lock
|
||||
mozilla::MonitorAutoLock lock(mCurrentTaskMonitor);
|
||||
mVsyncEnabled = false;
|
||||
if (mCurrentVsyncTask) {
|
||||
mCurrentVsyncTask->Cancel();
|
||||
mCurrentVsyncTask = nullptr;
|
||||
}
|
||||
}
|
||||
mVsyncThread->Stop();
|
||||
}
|
||||
|
||||
bool
|
||||
SoftwareDisplay::IsVsyncEnabled()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mozilla::MonitorAutoLock lock(mCurrentTaskMonitor);
|
||||
return mVsyncEnabled;
|
||||
}
|
||||
|
||||
bool
|
||||
SoftwareDisplay::IsInSoftwareVsyncThread()
|
||||
{
|
||||
return mVsyncThread->thread_id() == PlatformThread::CurrentId();
|
||||
}
|
||||
|
||||
void
|
||||
SoftwareDisplay::NotifyVsync(mozilla::TimeStamp aVsyncTimestamp)
|
||||
{
|
||||
MOZ_ASSERT(IsInSoftwareVsyncThread());
|
||||
Display::NotifyVsync(aVsyncTimestamp);
|
||||
ScheduleNextVsync(aVsyncTimestamp);
|
||||
}
|
||||
|
||||
void
|
||||
SoftwareDisplay::ScheduleNextVsync(mozilla::TimeStamp aVsyncTimestamp)
|
||||
{
|
||||
MOZ_ASSERT(IsInSoftwareVsyncThread());
|
||||
mozilla::TimeStamp nextVsync = aVsyncTimestamp + mVsyncRate;
|
||||
mozilla::TimeDuration delay = nextVsync - mozilla::TimeStamp::Now();
|
||||
if (delay.ToMilliseconds() < 0) {
|
||||
delay = mozilla::TimeDuration::FromMilliseconds(0);
|
||||
}
|
||||
|
||||
mozilla::MonitorAutoLock lock(mCurrentTaskMonitor);
|
||||
// We could've disabled vsync between this posted task and when it actually
|
||||
// executes
|
||||
if (!mVsyncEnabled) {
|
||||
return;
|
||||
}
|
||||
mCurrentVsyncTask = NewRunnableMethod(this,
|
||||
&SoftwareDisplay::NotifyVsync,
|
||||
nextVsync);
|
||||
|
||||
mVsyncThread->message_loop()->PostDelayedTask(FROM_HERE,
|
||||
mCurrentVsyncTask,
|
||||
delay.ToMilliseconds());
|
||||
}
|
||||
|
||||
SoftwareDisplay::~SoftwareDisplay()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
delete mVsyncThread;
|
||||
}
|
64
gfx/thebes/SoftwareVsyncSource.h
Normal file
64
gfx/thebes/SoftwareVsyncSource.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#ifndef GFX_SOFTWARE_VSYNC_SOURCE_H
|
||||
#define GFX_SOFTWARE_VSYNC_SOURCE_H
|
||||
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "base/thread.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "VsyncSource.h"
|
||||
|
||||
class CancelableTask;
|
||||
|
||||
class SoftwareDisplay MOZ_FINAL : public mozilla::gfx::VsyncSource::Display
|
||||
{
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SoftwareDisplay)
|
||||
|
||||
public:
|
||||
SoftwareDisplay();
|
||||
virtual void EnableVsync() MOZ_OVERRIDE;
|
||||
virtual void DisableVsync() MOZ_OVERRIDE;
|
||||
virtual bool IsVsyncEnabled() MOZ_OVERRIDE;
|
||||
bool IsInSoftwareVsyncThread();
|
||||
virtual void NotifyVsync(mozilla::TimeStamp aVsyncTimestamp) MOZ_OVERRIDE;
|
||||
void ScheduleNextVsync(mozilla::TimeStamp aVsyncTimestamp);
|
||||
|
||||
protected:
|
||||
~SoftwareDisplay();
|
||||
|
||||
private:
|
||||
mozilla::TimeDuration mVsyncRate;
|
||||
// Use a chromium thread because nsITimers* fire on the main thread
|
||||
base::Thread* mVsyncThread;
|
||||
bool mVsyncEnabled;
|
||||
CancelableTask* mCurrentVsyncTask;
|
||||
// Locks against both mCurrentVsyncTask and mVsyncEnabled
|
||||
mozilla::Monitor mCurrentTaskMonitor;
|
||||
}; // SoftwareDisplay
|
||||
|
||||
// Fallback option to use a software timer to mimic vsync. Useful for gtests
|
||||
// To mimic a hardware vsync thread, we create a dedicated software timer
|
||||
// vsync thread.
|
||||
class SoftwareVsyncSource : public mozilla::gfx::VsyncSource
|
||||
{
|
||||
public:
|
||||
SoftwareVsyncSource();
|
||||
~SoftwareVsyncSource();
|
||||
|
||||
virtual Display& GetGlobalDisplay() MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(mGlobalDisplay != nullptr);
|
||||
return *mGlobalDisplay;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<SoftwareDisplay> mGlobalDisplay;
|
||||
};
|
||||
|
||||
#endif /* GFX_SOFTWARE_VSYNC_SOURCE_H */
|
@ -35,7 +35,7 @@ VsyncSource::FindDisplay(CompositorVsyncDispatcher* aCompositorVsyncDispatcher)
|
||||
void
|
||||
VsyncSource::Display::NotifyVsync(TimeStamp aVsyncTimestamp)
|
||||
{
|
||||
// Called on the hardware vsync thread
|
||||
// Called on the vsync thread
|
||||
for (size_t i = 0; i < mCompositorVsyncDispatchers.Length(); i++) {
|
||||
mCompositorVsyncDispatchers[i]->NotifyVsync(aVsyncTimestamp);
|
||||
}
|
||||
|
@ -3,6 +3,9 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GFX_VSYNCSOURCE_H
|
||||
#define GFX_VSYNCSOURCE_H
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
@ -26,8 +29,8 @@ public:
|
||||
virtual ~Display();
|
||||
void AddCompositorVsyncDispatcher(mozilla::CompositorVsyncDispatcher* aCompositorVsyncDispatcher);
|
||||
void RemoveCompositorVsyncDispatcher(mozilla::CompositorVsyncDispatcher* aCompositorVsyncDispatcher);
|
||||
// Notified when this display's vsync occurs, on the hardware vsync thread
|
||||
void NotifyVsync(mozilla::TimeStamp aVsyncTimestamp);
|
||||
// Notified when this display's vsync occurs, on the vsync thread
|
||||
virtual void NotifyVsync(mozilla::TimeStamp aVsyncTimestamp);
|
||||
|
||||
// These should all only be called on the main thread
|
||||
virtual void EnableVsync() = 0;
|
||||
@ -48,3 +51,5 @@ protected:
|
||||
}; // VsyncSource
|
||||
} // gfx
|
||||
} // mozilla
|
||||
|
||||
#endif /* GFX_VSYNCSOURCE_H */
|
||||
|
@ -105,6 +105,7 @@ class mozilla::gl::SkiaGLGlue : public GenericAtomicRefCounted {
|
||||
#include "nsIGfxInfo.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "VsyncSource.h"
|
||||
#include "SoftwareVsyncSource.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
@ -2283,3 +2284,11 @@ gfxPlatform::UsesOffMainThreadCompositing()
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::gfx::VsyncSource>
|
||||
gfxPlatform::CreateHardwareVsyncSource()
|
||||
{
|
||||
NS_WARNING("Hardware Vsync support not yet implemented. Falling back to software timers\n");
|
||||
nsRefPtr<mozilla::gfx::VsyncSource> softwareVsync = new SoftwareVsyncSource();
|
||||
return softwareVsync.forget();
|
||||
}
|
||||
|
@ -604,10 +604,7 @@ protected:
|
||||
/**
|
||||
* Initialized hardware vsync based on each platform.
|
||||
*/
|
||||
virtual already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource() {
|
||||
NS_WARNING("Hardware vsync not supported on platform yet");
|
||||
return nullptr;
|
||||
}
|
||||
virtual already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource();
|
||||
|
||||
/**
|
||||
* Helper method, creates a draw target for a specific Azure backend.
|
||||
|
@ -52,6 +52,7 @@ EXPORTS += [
|
||||
'gfxVR.h',
|
||||
'GraphicsFilter.h',
|
||||
'RoundedRect.h',
|
||||
'SoftwareVsyncSource.h',
|
||||
'VsyncSource.h',
|
||||
]
|
||||
|
||||
@ -245,6 +246,7 @@ UNIFIED_SOURCES += [
|
||||
'gfxUtils.cpp',
|
||||
'gfxVR.cpp',
|
||||
'nsUnicodeRange.cpp',
|
||||
'SoftwareVsyncSource.cpp',
|
||||
'VsyncSource.cpp',
|
||||
]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user