mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-29 18:40:41 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1152509. Use Mask with alpha to avoid allocating a surface. r=bas (ddab7594e3)
- Bug 1155881 follow-up: Make gfxAndroidPlatform::SupportsApzTouchInput const (a31194495e)
- Bug 1193481 - Prefer "Firefox Emoji" font for emoji characters in GetCommonFallbackFonts on B2G. r=jdaggett (e94e0eb718)
- Bug 1139253. Reuse the same thread for the software vsync thread. r=kats (fe7f6849bf)
- Bug 1147390. Enable / disable vsync on the vsync thread only. r=kats (fd485f8ec4)
- Bug 1146691 - Create tests to check that the RefreshDriverVsyncObservers get vsync notifications. r=kats (7a8527b378)
- Bug 1197201. Delete hardware vsync and vsync compositor prefs. r=kats (e8f0ef3258)
- Bug 1175530 - Log using gfxDebugOnce when enabling vsync compositor. r=mchang (81a48aebae)
- Bug 1196308 - Delete Software Compositor Scheduler. r=sotaro (d0e9620ddb)
- Don't run the compositor:created notification from within unsafer callers. (bug 1201684, r=mattwoodrow) (83d585749a)
- Bug 1160216 - Add a preference to force software vsync and set software vsync rate. r=kats (850d3ce7ab)
- Bug 1132966 - use relaxed Atomic integers for tracking graphics surface memory usage; r=njn (aca764781f)
- bug 1180012 remove unused GetPrefFonts() r=jdaggett (80a5a99f7f)
- Bug 1139726 - Assert gfxPlatform::Init is called on the main thread. r=kats (dd1ad58304)
- Bug 1208945 - Rename Color::{To,From}ARGB() so they aren't easily confused with {To,From}ABGR(). r=Bas. (8e83d44741)
- Bug 1199885 - Part 1: Add MouseInput InputData. r=kats (67764c13a6)
This commit is contained in:
+6
-2
@@ -246,7 +246,9 @@ public:
|
||||
return newColor;
|
||||
}
|
||||
|
||||
static Color FromARGB(uint32_t aColor)
|
||||
// The "Unusual" prefix is to avoid unintentionally using this function when
|
||||
// FromABGR(), which is much more common, is needed.
|
||||
static Color UnusualFromARGB(uint32_t aColor)
|
||||
{
|
||||
Color newColor(((aColor >> 16) & 0xff) * (1.0f / 255.0f),
|
||||
((aColor >> 8) & 0xff) * (1.0f / 255.0f),
|
||||
@@ -262,7 +264,9 @@ public:
|
||||
uint32_t(b * 255.0f) << 16 | uint32_t(a * 255.0f) << 24;
|
||||
}
|
||||
|
||||
uint32_t ToARGB() const
|
||||
// The "Unusual" prefix is to avoid unintentionally using this function when
|
||||
// ToABGR(), which is much more common, is needed.
|
||||
uint32_t UnusualToARGB() const
|
||||
{
|
||||
return uint32_t(b * 255.0f) | uint32_t(g * 255.0f) << 8 |
|
||||
uint32_t(r * 255.0f) << 16 | uint32_t(a * 255.0f) << 24;
|
||||
|
||||
@@ -44,13 +44,8 @@ PaintWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer)
|
||||
{
|
||||
AutoMoz2DMaskData mask;
|
||||
if (GetMaskData(aMaskLayer, Point(), &mask)) {
|
||||
if (aOpacity < 1.0) {
|
||||
aContext->PushGroup(gfxContentType::COLOR_ALPHA);
|
||||
aContext->Paint(aOpacity);
|
||||
aContext->PopGroupToSource();
|
||||
}
|
||||
aContext->SetMatrix(ThebesMatrix(mask.GetTransform()));
|
||||
aContext->Mask(mask.GetSurface());
|
||||
aContext->Mask(mask.GetSurface(), aOpacity);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -221,81 +221,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.
|
||||
@@ -303,68 +236,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")
|
||||
@@ -395,11 +273,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)
|
||||
@@ -411,6 +290,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()
|
||||
@@ -430,13 +314,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
|
||||
@@ -485,14 +388,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;
|
||||
}
|
||||
|
||||
@@ -501,7 +397,10 @@ CompositorVsyncScheduler::CancelCurrentCompositeTask()
|
||||
{
|
||||
MOZ_ASSERT(CompositorParent::IsInCompositorThread() || NS_IsMainThread());
|
||||
MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
|
||||
CompositorScheduler::CancelCurrentCompositeTask();
|
||||
if (mCurrentCompositeTask) {
|
||||
mCurrentCompositeTask->Cancel();
|
||||
mCurrentCompositeTask = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -515,7 +414,7 @@ CompositorVsyncScheduler::Composite(TimeStamp aVsyncTimestamp)
|
||||
|
||||
DispatchTouchEvents(aVsyncTimestamp);
|
||||
|
||||
if (mNeedsComposite) {
|
||||
if (mNeedsComposite || mAsapScheduling) {
|
||||
mNeedsComposite = false;
|
||||
mLastCompose = aVsyncTimestamp;
|
||||
ComposeToTarget(nullptr);
|
||||
@@ -546,7 +445,8 @@ void
|
||||
CompositorVsyncScheduler::ForceComposeToTarget(gfx::DrawTarget* aTarget, const IntRect* aRect)
|
||||
{
|
||||
OnForceComposeToTarget();
|
||||
CompositorScheduler::ForceComposeToTarget(aTarget, aRect);
|
||||
mLastCompose = TimeStamp::Now();
|
||||
ComposeToTarget(aTarget, aRect);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -610,22 +510,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,
|
||||
@@ -672,12 +577,8 @@ CompositorParent::CompositorParent(nsIWidget* aWidget,
|
||||
mApzcTreeManager = new APZCTreeManager();
|
||||
}
|
||||
|
||||
if (UseVsyncComposition()) {
|
||||
NS_WARNING("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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -59,6 +59,12 @@ public:
|
||||
return mDidGetVsyncNotification;
|
||||
}
|
||||
|
||||
void ResetVsyncNotification()
|
||||
{
|
||||
MonitorAutoLock lock(mVsyncMonitor);
|
||||
mDidGetVsyncNotification = false;
|
||||
}
|
||||
|
||||
private:
|
||||
bool mDidGetVsyncNotification;
|
||||
|
||||
@@ -72,9 +78,8 @@ protected:
|
||||
{
|
||||
gfxPlatform::GetPlatform();
|
||||
gfxPrefs::GetSingleton();
|
||||
if (gfxPrefs::HardwareVsyncEnabled() ) {
|
||||
mVsyncSource = gfxPlatform::GetPlatform()->GetHardwareVsync();
|
||||
}
|
||||
mVsyncSource = gfxPlatform::GetPlatform()->GetHardwareVsync();
|
||||
MOZ_RELEASE_ASSERT(mVsyncSource);
|
||||
}
|
||||
|
||||
virtual ~VsyncTester()
|
||||
@@ -105,10 +110,6 @@ FlushMainThreadLoop()
|
||||
// Tests that we can enable/disable vsync notifications
|
||||
TEST_F(VsyncTester, EnableVsync)
|
||||
{
|
||||
if (!gfxPrefs::HardwareVsyncEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
VsyncSource::Display& globalDisplay = mVsyncSource->GetGlobalDisplay();
|
||||
globalDisplay.DisableVsync();
|
||||
ASSERT_FALSE(globalDisplay.IsVsyncEnabled());
|
||||
@@ -123,10 +124,6 @@ TEST_F(VsyncTester, EnableVsync)
|
||||
// Test that if we have vsync enabled, the display should get vsync notifications
|
||||
TEST_F(VsyncTester, CompositorGetVsyncNotifications)
|
||||
{
|
||||
if (!gfxPrefs::HardwareVsyncEnabled() || !gfxPrefs::VsyncAlignedCompositor()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CompositorVsyncDispatcher::SetThreadAssertionsEnabled(false);
|
||||
|
||||
VsyncSource::Display& globalDisplay = mVsyncSource->GetGlobalDisplay();
|
||||
@@ -146,3 +143,63 @@ TEST_F(VsyncTester, CompositorGetVsyncNotifications)
|
||||
vsyncDispatcher = nullptr;
|
||||
testVsyncObserver = nullptr;
|
||||
}
|
||||
|
||||
// Test that if we have vsync enabled, the parent refresh driver should get notifications
|
||||
TEST_F(VsyncTester, ParentRefreshDriverGetVsyncNotifications)
|
||||
{
|
||||
if (!gfxPrefs::VsyncAlignedRefreshDriver()) {
|
||||
return;
|
||||
}
|
||||
|
||||
VsyncSource::Display& globalDisplay = mVsyncSource->GetGlobalDisplay();
|
||||
globalDisplay.DisableVsync();
|
||||
ASSERT_FALSE(globalDisplay.IsVsyncEnabled());
|
||||
|
||||
nsRefPtr<RefreshTimerVsyncDispatcher> vsyncDispatcher = globalDisplay.GetRefreshTimerVsyncDispatcher();
|
||||
ASSERT_TRUE(vsyncDispatcher != nullptr);
|
||||
|
||||
nsRefPtr<TestVsyncObserver> testVsyncObserver = new TestVsyncObserver();
|
||||
vsyncDispatcher->SetParentRefreshTimer(testVsyncObserver);
|
||||
ASSERT_TRUE(globalDisplay.IsVsyncEnabled());
|
||||
|
||||
testVsyncObserver->WaitForVsyncNotification();
|
||||
ASSERT_TRUE(testVsyncObserver->DidGetVsyncNotification());
|
||||
vsyncDispatcher->SetParentRefreshTimer(nullptr);
|
||||
|
||||
testVsyncObserver->ResetVsyncNotification();
|
||||
testVsyncObserver->WaitForVsyncNotification();
|
||||
ASSERT_FALSE(testVsyncObserver->DidGetVsyncNotification());
|
||||
|
||||
vsyncDispatcher = nullptr;
|
||||
testVsyncObserver = nullptr;
|
||||
}
|
||||
|
||||
// Test that child refresh vsync observers get vsync notifications
|
||||
TEST_F(VsyncTester, ChildRefreshDriverGetVsyncNotifications)
|
||||
{
|
||||
if (!gfxPrefs::VsyncAlignedRefreshDriver()) {
|
||||
return;
|
||||
}
|
||||
|
||||
VsyncSource::Display& globalDisplay = mVsyncSource->GetGlobalDisplay();
|
||||
globalDisplay.DisableVsync();
|
||||
ASSERT_FALSE(globalDisplay.IsVsyncEnabled());
|
||||
|
||||
nsRefPtr<RefreshTimerVsyncDispatcher> vsyncDispatcher = globalDisplay.GetRefreshTimerVsyncDispatcher();
|
||||
ASSERT_TRUE(vsyncDispatcher != nullptr);
|
||||
|
||||
nsRefPtr<TestVsyncObserver> testVsyncObserver = new TestVsyncObserver();
|
||||
vsyncDispatcher->AddChildRefreshTimer(testVsyncObserver);
|
||||
ASSERT_TRUE(globalDisplay.IsVsyncEnabled());
|
||||
|
||||
testVsyncObserver->WaitForVsyncNotification();
|
||||
ASSERT_TRUE(testVsyncObserver->DidGetVsyncNotification());
|
||||
|
||||
vsyncDispatcher->RemoveChildRefreshTimer(testVsyncObserver);
|
||||
testVsyncObserver->ResetVsyncNotification();
|
||||
testVsyncObserver->WaitForVsyncNotification();
|
||||
ASSERT_FALSE(testVsyncObserver->DidGetVsyncNotification());
|
||||
|
||||
vsyncDispatcher = nullptr;
|
||||
testVsyncObserver = nullptr;
|
||||
}
|
||||
|
||||
@@ -6,77 +6,81 @@
|
||||
|
||||
#include "SoftwareVsyncSource.h"
|
||||
#include "base/task.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
SoftwareVsyncSource::SoftwareVsyncSource()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mGlobalDisplay = new SoftwareDisplay();
|
||||
}
|
||||
|
||||
SoftwareVsyncSource::~SoftwareVsyncSource()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// Ensure we disable vsync on the main thread here
|
||||
mGlobalDisplay->DisableVsync();
|
||||
mGlobalDisplay->Shutdown();
|
||||
mGlobalDisplay = nullptr;
|
||||
}
|
||||
|
||||
SoftwareDisplay::SoftwareDisplay()
|
||||
: mVsyncEnabled(false)
|
||||
, mCurrentTaskMonitor("SoftwareVsyncCurrentTaskMonitor")
|
||||
: mCurrentVsyncTask(nullptr)
|
||||
, mVsyncEnabled(false)
|
||||
{
|
||||
// Mimic 60 fps
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
const double rate = 1000 / 60.0;
|
||||
const double rate = 1000.0 / (double) gfxPlatform::GetSoftwareVsyncRate();
|
||||
mVsyncRate = mozilla::TimeDuration::FromMilliseconds(rate);
|
||||
mVsyncThread = new base::Thread("SoftwareVsyncThread");
|
||||
MOZ_RELEASE_ASSERT(mVsyncThread->Start(), "Could not start software vsync thread");
|
||||
}
|
||||
|
||||
SoftwareDisplay::~SoftwareDisplay() {}
|
||||
|
||||
void
|
||||
SoftwareDisplay::EnableVsync()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (IsVsyncEnabled()) {
|
||||
MOZ_ASSERT(mVsyncThread->IsRunning());
|
||||
if (NS_IsMainThread()) {
|
||||
if (mVsyncEnabled) {
|
||||
return;
|
||||
}
|
||||
mVsyncEnabled = true;
|
||||
|
||||
mVsyncThread->message_loop()->PostTask(FROM_HERE,
|
||||
NewRunnableMethod(this, &SoftwareDisplay::EnableVsync));
|
||||
return;
|
||||
}
|
||||
|
||||
{ // scope lock
|
||||
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);
|
||||
}
|
||||
MOZ_ASSERT(IsInSoftwareVsyncThread());
|
||||
NotifyVsync(mozilla::TimeStamp::Now());
|
||||
}
|
||||
|
||||
void
|
||||
SoftwareDisplay::DisableVsync()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!IsVsyncEnabled()) {
|
||||
MOZ_ASSERT(mVsyncThread->IsRunning());
|
||||
if (NS_IsMainThread()) {
|
||||
if (!mVsyncEnabled) {
|
||||
return;
|
||||
}
|
||||
mVsyncEnabled = false;
|
||||
|
||||
mVsyncThread->message_loop()->PostTask(FROM_HERE,
|
||||
NewRunnableMethod(this, &SoftwareDisplay::DisableVsync));
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mVsyncThread->IsRunning());
|
||||
{ // scope lock
|
||||
mozilla::MonitorAutoLock lock(mCurrentTaskMonitor);
|
||||
mVsyncEnabled = false;
|
||||
if (mCurrentVsyncTask) {
|
||||
mCurrentVsyncTask->Cancel();
|
||||
mCurrentVsyncTask = nullptr;
|
||||
}
|
||||
MOZ_ASSERT(IsInSoftwareVsyncThread());
|
||||
if (mCurrentVsyncTask) {
|
||||
mCurrentVsyncTask->Cancel();
|
||||
mCurrentVsyncTask = nullptr;
|
||||
}
|
||||
mVsyncThread->Stop();
|
||||
}
|
||||
|
||||
bool
|
||||
SoftwareDisplay::IsVsyncEnabled()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mozilla::MonitorAutoLock lock(mCurrentTaskMonitor);
|
||||
return mVsyncEnabled;
|
||||
}
|
||||
|
||||
@@ -118,12 +122,6 @@ SoftwareDisplay::ScheduleNextVsync(mozilla::TimeStamp aVsyncTimestamp)
|
||||
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);
|
||||
@@ -133,8 +131,11 @@ SoftwareDisplay::ScheduleNextVsync(mozilla::TimeStamp aVsyncTimestamp)
|
||||
delay.ToMilliseconds());
|
||||
}
|
||||
|
||||
SoftwareDisplay::~SoftwareDisplay()
|
||||
void
|
||||
SoftwareDisplay::Shutdown()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
DisableVsync();
|
||||
mVsyncThread->Stop();
|
||||
delete mVsyncThread;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ public:
|
||||
bool IsInSoftwareVsyncThread();
|
||||
virtual void NotifyVsync(mozilla::TimeStamp aVsyncTimestamp) override;
|
||||
void ScheduleNextVsync(mozilla::TimeStamp aVsyncTimestamp);
|
||||
void Shutdown();
|
||||
|
||||
protected:
|
||||
~SoftwareDisplay();
|
||||
@@ -36,10 +37,8 @@ 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;
|
||||
CancelableTask* mCurrentVsyncTask; // only access on vsync thread
|
||||
bool mVsyncEnabled; // Only access on main thread
|
||||
}; // SoftwareDisplay
|
||||
|
||||
// Fallback option to use a software timer to mimic vsync. Useful for gtests
|
||||
|
||||
@@ -564,13 +564,25 @@ PR_STATIC_ASSERT(uint32_t(CAIRO_SURFACE_TYPE_SKIA) ==
|
||||
|
||||
/* Surface size memory reporting */
|
||||
|
||||
static int64_t gSurfaceMemoryUsed[size_t(gfxSurfaceType::Max)] = { 0 };
|
||||
|
||||
class SurfaceMemoryReporter final : public nsIMemoryReporter
|
||||
{
|
||||
~SurfaceMemoryReporter() {}
|
||||
|
||||
// We can touch this array on several different threads, and we don't
|
||||
// want to introduce memory barriers when recording the memory used. To
|
||||
// assure dynamic race checkers like TSan that this is OK, we use
|
||||
// relaxed memory ordering here.
|
||||
static Atomic<size_t, Relaxed> sSurfaceMemoryUsed[size_t(gfxSurfaceType::Max)];
|
||||
|
||||
public:
|
||||
static void AdjustUsedMemory(gfxSurfaceType aType, int32_t aBytes)
|
||||
{
|
||||
// A read-modify-write operation like += would require a memory barrier
|
||||
// here, which would defeat the purpose of using relaxed memory
|
||||
// ordering. So separate out the read and write operations.
|
||||
sSurfaceMemoryUsed[size_t(aType)] = sSurfaceMemoryUsed[size_t(aType)] + aBytes;
|
||||
};
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD CollectReports(nsIMemoryReporterCallback *aCb,
|
||||
@@ -578,7 +590,7 @@ public:
|
||||
{
|
||||
const size_t len = ArrayLength(sSurfaceMemoryReporterAttrs);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
int64_t amount = gSurfaceMemoryUsed[i];
|
||||
int64_t amount = sSurfaceMemoryUsed[i];
|
||||
|
||||
if (amount != 0) {
|
||||
const char *path = sSurfaceMemoryReporterAttrs[i].path;
|
||||
@@ -589,7 +601,7 @@ public:
|
||||
|
||||
nsresult rv = aCb->Callback(EmptyCString(), nsCString(path),
|
||||
KIND_OTHER, UNITS_BYTES,
|
||||
gSurfaceMemoryUsed[i],
|
||||
amount,
|
||||
nsCString(desc), aClosure);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
@@ -599,6 +611,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
Atomic<size_t, Relaxed> SurfaceMemoryReporter::sSurfaceMemoryUsed[size_t(gfxSurfaceType::Max)];
|
||||
|
||||
NS_IMPL_ISUPPORTS(SurfaceMemoryReporter, nsIMemoryReporter)
|
||||
|
||||
void
|
||||
@@ -616,7 +630,7 @@ gfxASurface::RecordMemoryUsedForSurfaceType(gfxSurfaceType aType,
|
||||
registered = true;
|
||||
}
|
||||
|
||||
gSurfaceMemoryUsed[size_t(aType)] += aBytes;
|
||||
SurfaceMemoryReporter::AdjustUsedMemory(aType, aBytes);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -175,13 +175,30 @@ gfxAndroidPlatform::GetCommonFallbackFonts(uint32_t aCh, uint32_t aNextCh,
|
||||
{
|
||||
static const char kDroidSansJapanese[] = "Droid Sans Japanese";
|
||||
static const char kMotoyaLMaru[] = "MotoyaLMaru";
|
||||
static const char kNotoColorEmoji[] = "Noto Color Emoji";
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
static const char kFirefoxEmoji[] = "Firefox Emoji";
|
||||
#endif
|
||||
|
||||
if (aNextCh == 0xfe0fu) {
|
||||
// if char is followed by VS16, try for a color emoji glyph
|
||||
aFontList.AppendElement("Noto Color Emoji");
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
aFontList.AppendElement(kFirefoxEmoji);
|
||||
#endif
|
||||
aFontList.AppendElement(kNotoColorEmoji);
|
||||
}
|
||||
|
||||
if (IS_IN_BMP(aCh)) {
|
||||
if (!IS_IN_BMP(aCh)) {
|
||||
uint32_t p = aCh >> 16;
|
||||
if (p == 1) { // try color emoji font, unless VS15 (text style) present
|
||||
if (aNextCh != 0xfe0fu && aNextCh != 0xfe0eu) {
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
aFontList.AppendElement(kFirefoxEmoji);
|
||||
#endif
|
||||
aFontList.AppendElement(kNotoColorEmoji);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// try language-specific "Droid Sans *" and "Noto Sans *" fonts for
|
||||
// certain blocks, as most devices probably have these
|
||||
uint8_t block = (aCh >> 8) & 0xff;
|
||||
|
||||
@@ -92,7 +92,7 @@ public:
|
||||
virtual bool IsInGonkEmulator() const { return mIsInGonkEmulator; }
|
||||
#endif
|
||||
|
||||
virtual bool SupportsApzTouchInput() override {
|
||||
virtual bool SupportsApzTouchInput() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -817,17 +817,17 @@ gfxContext::Mask(gfxASurface *surface, const gfxPoint& offset)
|
||||
|
||||
gfxPoint pt = surface->GetDeviceOffset();
|
||||
|
||||
Mask(sourceSurf, Point(offset.x - pt.x, offset.y - pt.y));
|
||||
Mask(sourceSurf, 1.0f, Point(offset.x - pt.x, offset.y - pt.y));
|
||||
}
|
||||
|
||||
void
|
||||
gfxContext::Mask(SourceSurface *surface, const Point& offset)
|
||||
gfxContext::Mask(SourceSurface *surface, float alpha, const Point& offset)
|
||||
{
|
||||
// We clip here to bind to the mask surface bounds, see above.
|
||||
mDT->MaskSurface(PatternFromState(this),
|
||||
surface,
|
||||
offset,
|
||||
DrawOptions(1.0f, CurrentState().op, CurrentState().aaMode));
|
||||
DrawOptions(alpha, CurrentState().op, CurrentState().aaMode));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -322,7 +322,7 @@ public:
|
||||
*/
|
||||
void Mask(gfxASurface *surface, const gfxPoint& offset = gfxPoint(0.0, 0.0));
|
||||
|
||||
void Mask(mozilla::gfx::SourceSurface *surface, const mozilla::gfx::Point& offset = mozilla::gfx::Point());
|
||||
void Mask(mozilla::gfx::SourceSurface *surface, float alpha = 1.0f, const mozilla::gfx::Point& offset = mozilla::gfx::Point());
|
||||
|
||||
/**
|
||||
** Line Properties
|
||||
|
||||
+44
-59
@@ -464,6 +464,7 @@ void RecordingPrefChanged(const char *aPrefName, void *aClosure)
|
||||
void
|
||||
gfxPlatform::Init()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
if (gEverInitialized) {
|
||||
NS_RUNTIMEABORT("Already started???");
|
||||
}
|
||||
@@ -591,8 +592,12 @@ gfxPlatform::Init()
|
||||
|
||||
RegisterStrongMemoryReporter(new GfxMemoryImageReporter());
|
||||
|
||||
if (XRE_IsParentProcess() && gfxPrefs::HardwareVsyncEnabled()) {
|
||||
gPlatform->mVsyncSource = gPlatform->CreateHardwareVsyncSource();
|
||||
if (XRE_IsParentProcess()) {
|
||||
if (gfxPlatform::ForceSoftwareVsync()) {
|
||||
gPlatform->mVsyncSource = (gPlatform)->gfxPlatform::CreateHardwareVsyncSource();
|
||||
} else {
|
||||
gPlatform->mVsyncSource = gPlatform->CreateHardwareVsyncSource();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1359,58 +1364,6 @@ gfxPlatform::MakePlatformFont(const nsAString& aFontName,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void
|
||||
AppendGenericFontFromPref(nsString& aFonts, nsIAtom *aLangGroup, const char *aGenericName)
|
||||
{
|
||||
NS_ENSURE_TRUE_VOID(Preferences::GetRootBranch());
|
||||
|
||||
nsAutoCString prefName, langGroupString;
|
||||
|
||||
aLangGroup->ToUTF8String(langGroupString);
|
||||
|
||||
nsAutoCString genericDotLang;
|
||||
if (aGenericName) {
|
||||
genericDotLang.Assign(aGenericName);
|
||||
} else {
|
||||
prefName.AssignLiteral("font.default.");
|
||||
prefName.Append(langGroupString);
|
||||
genericDotLang = Preferences::GetCString(prefName.get());
|
||||
}
|
||||
|
||||
genericDotLang.Append('.');
|
||||
genericDotLang.Append(langGroupString);
|
||||
|
||||
// fetch font.name.xxx value
|
||||
prefName.AssignLiteral("font.name.");
|
||||
prefName.Append(genericDotLang);
|
||||
nsAdoptingString nameValue = Preferences::GetString(prefName.get());
|
||||
if (nameValue) {
|
||||
if (!aFonts.IsEmpty())
|
||||
aFonts.AppendLiteral(", ");
|
||||
aFonts += nameValue;
|
||||
}
|
||||
|
||||
// fetch font.name-list.xxx value
|
||||
prefName.AssignLiteral("font.name-list.");
|
||||
prefName.Append(genericDotLang);
|
||||
nsAdoptingString nameListValue = Preferences::GetString(prefName.get());
|
||||
if (nameListValue && !nameListValue.Equals(nameValue)) {
|
||||
if (!aFonts.IsEmpty())
|
||||
aFonts.AppendLiteral(", ");
|
||||
aFonts += nameListValue;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatform::GetPrefFonts(nsIAtom *aLanguage, nsString& aFonts, bool aAppendUnicode)
|
||||
{
|
||||
aFonts.Truncate();
|
||||
|
||||
AppendGenericFontFromPref(aFonts, aLanguage, nullptr);
|
||||
if (aAppendUnicode)
|
||||
AppendGenericFontFromPref(aFonts, nsGkAtoms::Unicode, nullptr);
|
||||
}
|
||||
|
||||
bool gfxPlatform::ForEachPrefFont(eFontPrefLang aLangArray[], uint32_t aLangArrayLen, PrefFontCallback aCallback,
|
||||
void *aClosure)
|
||||
{
|
||||
@@ -1863,12 +1816,12 @@ gfxPlatform::TransformPixel(const Color& in, Color& out, qcms_transform *transfo
|
||||
out = Color::FromABGR(packed);
|
||||
#else
|
||||
/* ARGB puts the bytes in |ARGB| order on big endian */
|
||||
uint32_t packed = in.ToARGB();
|
||||
uint32_t packed = in.UnusualToARGB();
|
||||
/* add one to move past the alpha byte */
|
||||
qcms_transform_data(transform,
|
||||
(uint8_t *)&packed + 1, (uint8_t *)&packed + 1,
|
||||
1);
|
||||
out = Color::FromARGB(packed);
|
||||
out = Color::UnusualFromARGB(packed);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2401,6 +2354,13 @@ gfxPlatform::UsesOffMainThreadCompositing()
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* The preference "layout.frame_rate" has 3 meanings depending on the value:
|
||||
*
|
||||
* -1 = Auto (default), use hardware vsync or software vsync @ 60 hz if hw vsync fails.
|
||||
* 0 = ASAP mode - used during talos testing.
|
||||
* X = Software vsync at a rate of X times per second.
|
||||
*/
|
||||
already_AddRefed<mozilla::gfx::VsyncSource>
|
||||
gfxPlatform::CreateHardwareVsyncSource()
|
||||
{
|
||||
@@ -2420,6 +2380,29 @@ gfxPlatform::IsInLayoutAsapMode()
|
||||
return Preferences::GetInt("layout.frame_rate", -1) == 0;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
gfxPlatform::ForceSoftwareVsync()
|
||||
{
|
||||
return Preferences::GetInt("layout.frame_rate", -1) > 0;
|
||||
}
|
||||
|
||||
/* static */ int
|
||||
gfxPlatform::GetSoftwareVsyncRate()
|
||||
{
|
||||
int preferenceRate = Preferences::GetInt("layout.frame_rate",
|
||||
gfxPlatform::GetDefaultFrameRate());
|
||||
if (preferenceRate <= 0) {
|
||||
return gfxPlatform::GetDefaultFrameRate();
|
||||
}
|
||||
return preferenceRate;
|
||||
}
|
||||
|
||||
/* static */ int
|
||||
gfxPlatform::GetDefaultFrameRate()
|
||||
{
|
||||
return 60;
|
||||
}
|
||||
|
||||
static nsString
|
||||
DetectBadApzWheelInputPrefs()
|
||||
{
|
||||
@@ -2557,9 +2540,11 @@ gfxPlatform::NotifyCompositorCreated(LayersBackend aBackend)
|
||||
mCompositorBackend = aBackend;
|
||||
|
||||
// Notify that we created a compositor, so telemetry can update.
|
||||
if (nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService()) {
|
||||
obsvc->NotifyObservers(nullptr, "compositor:created", nullptr);
|
||||
}
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction([] {
|
||||
if (nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService()) {
|
||||
obsvc->NotifyObservers(nullptr, "compositor:created", nullptr);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -427,8 +427,6 @@ public:
|
||||
|
||||
virtual bool DidRenderingDeviceReset(DeviceResetReason* aResetReason = nullptr) { return false; }
|
||||
|
||||
void GetPrefFonts(nsIAtom *aLanguage, nsString& array, bool aAppendUnicode = true);
|
||||
|
||||
// in some situations, need to make decisions about ambiguous characters, may need to look at multiple pref langs
|
||||
void GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang);
|
||||
|
||||
@@ -610,6 +608,21 @@ public:
|
||||
*/
|
||||
static bool IsInLayoutAsapMode();
|
||||
|
||||
/**
|
||||
* Returns the software vsync rate to use.
|
||||
*/
|
||||
static int GetSoftwareVsyncRate();
|
||||
|
||||
/**
|
||||
* Returns whether or not a custom vsync rate is set.
|
||||
*/
|
||||
static bool ForceSoftwareVsync();
|
||||
|
||||
/**
|
||||
* Returns the default frame rate for the refresh driver / software vsync.
|
||||
*/
|
||||
static int GetDefaultFrameRate();
|
||||
|
||||
/**
|
||||
* Used to test which input types are handled via APZ.
|
||||
*/
|
||||
|
||||
@@ -263,12 +263,10 @@ private:
|
||||
DECL_GFX_PREF(Once, "gfx.vr.mirror-textures", VRMirrorTextures, bool, false);
|
||||
|
||||
DECL_GFX_PREF(Live, "gfx.vsync.collect-scroll-transforms", CollectScrollTransforms, bool, false);
|
||||
DECL_GFX_PREF(Once, "gfx.vsync.compositor", VsyncAlignedCompositor, bool, false);
|
||||
// On b2g, in really bad cases, I've seen up to 80 ms delays between touch events and the main thread
|
||||
// processing them. So 80 ms / 16 = 5 vsync events. Double it up just to be on the safe side, so 10.
|
||||
DECL_GFX_PREF(Once, "gfx.vsync.compositor.unobserve-count", CompositorUnobserveCount, int32_t, 10);
|
||||
// Use vsync events generated by hardware
|
||||
DECL_GFX_PREF(Once, "gfx.vsync.hw-vsync.enabled", HardwareVsyncEnabled, bool, false);
|
||||
DECL_GFX_PREF(Once, "gfx.vsync.refreshdriver", VsyncAlignedRefreshDriver, bool, false);
|
||||
DECL_GFX_PREF(Once, "gfx.work-around-driver-bugs", WorkAroundDriverBugs, bool, true);
|
||||
DECL_GFX_PREF(Once, "gfx.screen-mirroring.enabled", ScreenMirroringEnabled, bool, false);
|
||||
|
||||
@@ -77,7 +77,6 @@ using namespace mozilla::layout;
|
||||
static PRLogModuleInfo *gLog = nullptr;
|
||||
#define LOG(...) MOZ_LOG(gLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
#define DEFAULT_FRAME_RATE 60
|
||||
#define DEFAULT_THROTTLED_FRAME_RATE 1
|
||||
#define DEFAULT_RECOMPUTE_VISIBILITY_INTERVAL_MS 1000
|
||||
// after 10 minutes, stop firing off inactive timers
|
||||
@@ -856,7 +855,6 @@ CreateVsyncRefreshTimer()
|
||||
gfxPrefs::GetSingleton();
|
||||
|
||||
if (!gfxPrefs::VsyncAlignedRefreshDriver()
|
||||
|| !gfxPrefs::HardwareVsyncEnabled()
|
||||
|| gfxPlatform::IsInLayoutAsapMode()) {
|
||||
return;
|
||||
}
|
||||
@@ -933,7 +931,7 @@ nsRefreshDriver::Shutdown()
|
||||
/* static */ int32_t
|
||||
nsRefreshDriver::DefaultInterval()
|
||||
{
|
||||
return NSToIntRound(1000.0 / DEFAULT_FRAME_RATE);
|
||||
return NSToIntRound(1000.0 / gfxPlatform::GetDefaultFrameRate());
|
||||
}
|
||||
|
||||
// Compute the interval to use for the refresh driver timer, in milliseconds.
|
||||
@@ -949,7 +947,7 @@ nsRefreshDriver::GetRegularTimerInterval(bool *outIsDefault) const
|
||||
{
|
||||
int32_t rate = Preferences::GetInt("layout.frame_rate", -1);
|
||||
if (rate < 0) {
|
||||
rate = DEFAULT_FRAME_RATE;
|
||||
rate = gfxPlatform::GetDefaultFrameRate();
|
||||
if (outIsDefault) {
|
||||
*outIsDefault = true;
|
||||
}
|
||||
|
||||
@@ -5262,8 +5262,6 @@ pref("dom.audiochannel.mutedByDefault", false);
|
||||
// Hardware vsync supported on windows, os x, and b2g.
|
||||
// Linux and fennec will use software vsync.
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN) || defined(XP_LINUX)
|
||||
pref("gfx.vsync.hw-vsync.enabled", false);
|
||||
pref("gfx.vsync.compositor", true);
|
||||
pref("gfx.vsync.refreshdriver", true);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -28,6 +28,49 @@ already_AddRefed<Touch> SingleTouchData::ToNewDOMTouch() const
|
||||
return touch.forget();
|
||||
}
|
||||
|
||||
MouseInput::MouseInput(const WidgetMouseEventBase& aMouseEvent)
|
||||
: InputData(MOUSE_INPUT, aMouseEvent.time, aMouseEvent.timeStamp,
|
||||
aMouseEvent.modifiers)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Can only copy from WidgetTouchEvent on main thread");
|
||||
|
||||
mButtonType = NONE;
|
||||
|
||||
switch (aMouseEvent.button) {
|
||||
case WidgetMouseEventBase::eLeftButton:
|
||||
mButtonType = MouseInput::LEFT_BUTTON;
|
||||
break;
|
||||
case WidgetMouseEventBase::eMiddleButton:
|
||||
mButtonType = MouseInput::MIDDLE_BUTTON;
|
||||
break;
|
||||
case WidgetMouseEventBase::eRightButton:
|
||||
mButtonType = MouseInput::RIGHT_BUTTON;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (aMouseEvent.mMessage) {
|
||||
case eMouseMove:
|
||||
mType = MOUSE_MOVE;
|
||||
break;
|
||||
case eMouseUp:
|
||||
mType = MOUSE_UP;
|
||||
break;
|
||||
case eMouseDown:
|
||||
mType = MOUSE_DOWN;
|
||||
break;
|
||||
case eDragStart:
|
||||
mType = MOUSE_DRAG_START;
|
||||
break;
|
||||
case eDragEnd:
|
||||
mType = MOUSE_DRAG_END;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Mouse event type not supported");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MultiTouchInput::MultiTouchInput(const WidgetTouchEvent& aTouchEvent)
|
||||
: InputData(MULTITOUCH_INPUT, aTouchEvent.time, aTouchEvent.timeStamp,
|
||||
aTouchEvent.modifiers)
|
||||
|
||||
@@ -30,6 +30,7 @@ class Matrix4x4;
|
||||
enum InputType
|
||||
{
|
||||
MULTITOUCH_INPUT,
|
||||
MOUSE_INPUT,
|
||||
PANGESTURE_INPUT,
|
||||
PINCHGESTURE_INPUT,
|
||||
TAPGESTURE_INPUT,
|
||||
@@ -37,6 +38,7 @@ enum InputType
|
||||
};
|
||||
|
||||
class MultiTouchInput;
|
||||
class MouseInput;
|
||||
class PanGestureInput;
|
||||
class PinchGestureInput;
|
||||
class TapGestureInput;
|
||||
@@ -76,6 +78,7 @@ public:
|
||||
Modifiers modifiers;
|
||||
|
||||
INPUTDATA_AS_CHILD_TYPE(MultiTouchInput, MULTITOUCH_INPUT)
|
||||
INPUTDATA_AS_CHILD_TYPE(MouseInput, MOUSE_INPUT)
|
||||
INPUTDATA_AS_CHILD_TYPE(PanGestureInput, PANGESTURE_INPUT)
|
||||
INPUTDATA_AS_CHILD_TYPE(PinchGestureInput, PINCHGESTURE_INPUT)
|
||||
INPUTDATA_AS_CHILD_TYPE(TapGestureInput, TAPGESTURE_INPUT)
|
||||
@@ -245,6 +248,47 @@ public:
|
||||
nsTArray<SingleTouchData> mTouches;
|
||||
};
|
||||
|
||||
class MouseInput : public InputData
|
||||
{
|
||||
public:
|
||||
enum MouseType
|
||||
{
|
||||
MOUSE_MOVE,
|
||||
MOUSE_DOWN,
|
||||
MOUSE_UP,
|
||||
MOUSE_DRAG_START,
|
||||
MOUSE_DRAG_END,
|
||||
};
|
||||
|
||||
enum ButtonType
|
||||
{
|
||||
LEFT_BUTTON,
|
||||
MIDDLE_BUTTON,
|
||||
RIGHT_BUTTON,
|
||||
NONE
|
||||
};
|
||||
|
||||
MouseInput(MouseType aType, ButtonType aButtonType, uint32_t aTime,
|
||||
TimeStamp aTimeStamp, Modifiers aModifiers)
|
||||
: InputData(MOUSE_INPUT, aTime, aTimeStamp, aModifiers)
|
||||
, mType(aType)
|
||||
, mButtonType(aButtonType)
|
||||
{}
|
||||
|
||||
MouseInput()
|
||||
: InputData(MOUSE_INPUT)
|
||||
{}
|
||||
|
||||
explicit MouseInput(const WidgetMouseEventBase& aMouseEvent);
|
||||
|
||||
bool IsLeftButton() const { return mButtonType == LEFT_BUTTON; }
|
||||
|
||||
MouseType mType;
|
||||
ButtonType mButtonType;
|
||||
ScreenPoint mOrigin;
|
||||
ParentLayerPoint mLocalOrigin;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encapsulation class for pan events, can be used off-main-thread.
|
||||
* These events are currently only used for scrolling on desktop.
|
||||
|
||||
@@ -154,8 +154,7 @@ HwcComposer2D::RegisterHwcEventCallback()
|
||||
&HookVsync, // 2nd: void (*vsync)(...)
|
||||
&HookHotplug // 3rd: void (*hotplug)(...)
|
||||
};
|
||||
mHasHWVsync = mHal->RegisterHwcEventCallback(cHWCProcs) &&
|
||||
gfxPrefs::HardwareVsyncEnabled();
|
||||
mHasHWVsync = mHal->RegisterHwcEventCallback(cHWCProcs);
|
||||
return mHasHWVsync;
|
||||
}
|
||||
|
||||
|
||||
@@ -563,10 +563,7 @@ nsScreenManagerGonk::Initialize()
|
||||
void
|
||||
nsScreenManagerGonk::DisplayEnabled(bool aEnabled)
|
||||
{
|
||||
if (gfxPrefs::HardwareVsyncEnabled()) {
|
||||
VsyncControl(aEnabled);
|
||||
}
|
||||
|
||||
VsyncControl(aEnabled);
|
||||
NS_DispatchToMainThread(aEnabled ? mScreenOnEvent : mScreenOffEvent);
|
||||
}
|
||||
|
||||
@@ -635,8 +632,6 @@ nsScreenManagerGonk::GetSystemDefaultScale(float *aDefaultScale)
|
||||
void
|
||||
nsScreenManagerGonk::VsyncControl(bool aEnabled)
|
||||
{
|
||||
MOZ_ASSERT(gfxPrefs::HardwareVsyncEnabled());
|
||||
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_DispatchToMainThread(
|
||||
NS_NewRunnableMethodWithArgs<bool>(this,
|
||||
|
||||
@@ -1050,13 +1050,11 @@ nsBaseWidget::GetDocument() const
|
||||
|
||||
void nsBaseWidget::CreateCompositorVsyncDispatcher()
|
||||
{
|
||||
if (gfxPrefs::HardwareVsyncEnabled()) {
|
||||
// Parent directly listens to the vsync source whereas
|
||||
// child process communicate via IPC
|
||||
// Should be called AFTER gfxPlatform is initialized
|
||||
if (XRE_IsParentProcess()) {
|
||||
mCompositorVsyncDispatcher = new CompositorVsyncDispatcher();
|
||||
}
|
||||
// Parent directly listens to the vsync source whereas
|
||||
// child process communicate via IPC
|
||||
// Should be called AFTER gfxPlatform is initialized
|
||||
if (XRE_IsParentProcess()) {
|
||||
mCompositorVsyncDispatcher = new CompositorVsyncDispatcher();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user