diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /gfx/tests/gtest/TestVsync.cpp | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gfx/tests/gtest/TestVsync.cpp')
-rw-r--r-- | gfx/tests/gtest/TestVsync.cpp | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/gfx/tests/gtest/TestVsync.cpp b/gfx/tests/gtest/TestVsync.cpp new file mode 100644 index 0000000000..7249e7d26c --- /dev/null +++ b/gfx/tests/gtest/TestVsync.cpp @@ -0,0 +1,173 @@ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "gfxPlatform.h" + +#include "MainThreadUtils.h" +#include "nsIThread.h" +#include "mozilla/RefPtr.h" +#include "SoftwareVsyncSource.h" +#include "VsyncSource.h" +#include "mozilla/gtest/MozAssertions.h" +#include "mozilla/Monitor.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/VsyncDispatcher.h" + +using namespace mozilla; +using namespace mozilla::gfx; +using namespace mozilla::layers; +using ::testing::_; + +// Timeout for vsync events to occur in milliseconds +// Windows 8.1 has intermittents at 50 ms. Raise limit to 5 vsync intervals. +const int kVsyncTimeoutMS = 80; + +class TestVsyncObserver : public VsyncObserver { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestVsyncObserver, override) + + public: + TestVsyncObserver() + : mDidGetVsyncNotification(false), mVsyncMonitor("VsyncMonitor") {} + + virtual void NotifyVsync(const VsyncEvent& aVsync) override { + MonitorAutoLock lock(mVsyncMonitor); + mDidGetVsyncNotification = true; + mVsyncMonitor.Notify(); + } + + void WaitForVsyncNotification() { + MOZ_ASSERT(NS_IsMainThread()); + if (DidGetVsyncNotification()) { + return; + } + + { // scope lock + MonitorAutoLock lock(mVsyncMonitor); + lock.Wait(TimeDuration::FromMilliseconds(kVsyncTimeoutMS)); + } + } + + bool DidGetVsyncNotification() { + MonitorAutoLock lock(mVsyncMonitor); + return mDidGetVsyncNotification; + } + + void ResetVsyncNotification() { + MonitorAutoLock lock(mVsyncMonitor); + mDidGetVsyncNotification = false; + } + + private: + ~TestVsyncObserver() = default; + + bool mDidGetVsyncNotification; + + private: + Monitor mVsyncMonitor MOZ_UNANNOTATED; +}; + +class VsyncTester : public ::testing::Test { + protected: + explicit VsyncTester() { + gfxPlatform::GetPlatform(); + mVsyncDispatcher = gfxPlatform::GetPlatform()->GetGlobalVsyncDispatcher(); + mVsyncSource = mVsyncDispatcher->GetCurrentVsyncSource(); + MOZ_RELEASE_ASSERT(mVsyncSource, "GFX: Vsync source not found."); + } + + virtual ~VsyncTester() { mVsyncSource = nullptr; } + + RefPtr<VsyncDispatcher> mVsyncDispatcher; + RefPtr<VsyncSource> mVsyncSource; +}; + +static void FlushMainThreadLoop() { + // Some tasks are pushed onto the main thread when adding vsync observers + // This function will ensure all tasks are executed on the main thread + // before returning. + nsCOMPtr<nsIThread> mainThread; + nsresult rv = NS_GetMainThread(getter_AddRefs(mainThread)); + ASSERT_NS_SUCCEEDED(rv); + + rv = NS_OK; + bool processed = true; + while (processed && NS_SUCCEEDED(rv)) { + rv = mainThread->ProcessNextEvent(false, &processed); + } +} + +// Tests that we can enable/disable vsync notifications +TEST_F(VsyncTester, EnableVsync) { + mVsyncSource->DisableVsync(); + ASSERT_FALSE(mVsyncSource->IsVsyncEnabled()); + + mVsyncSource->EnableVsync(); + ASSERT_TRUE(mVsyncSource->IsVsyncEnabled()); + + mVsyncSource->DisableVsync(); + ASSERT_FALSE(mVsyncSource->IsVsyncEnabled()); +} + +// Test that if we have vsync enabled, the source should get vsync +// notifications +TEST_F(VsyncTester, CompositorGetVsyncNotifications) { + mVsyncSource->DisableVsync(); + ASSERT_FALSE(mVsyncSource->IsVsyncEnabled()); + + RefPtr<CompositorVsyncDispatcher> vsyncDispatcher = + new CompositorVsyncDispatcher(mVsyncDispatcher); + RefPtr<TestVsyncObserver> testVsyncObserver = new TestVsyncObserver(); + + vsyncDispatcher->SetCompositorVsyncObserver(testVsyncObserver); + FlushMainThreadLoop(); + ASSERT_TRUE(mVsyncSource->IsVsyncEnabled()); + + testVsyncObserver->WaitForVsyncNotification(); + ASSERT_TRUE(testVsyncObserver->DidGetVsyncNotification()); + + vsyncDispatcher->SetCompositorVsyncObserver(nullptr); + FlushMainThreadLoop(); + + vsyncDispatcher = nullptr; + testVsyncObserver = nullptr; + ASSERT_FALSE(mVsyncSource->IsVsyncEnabled()); +} + +// Test that child refresh vsync observers get vsync notifications +TEST_F(VsyncTester, ChildRefreshDriverGetVsyncNotifications) { + mVsyncSource->DisableVsync(); + ASSERT_FALSE(mVsyncSource->IsVsyncEnabled()); + + ASSERT_TRUE(mVsyncDispatcher != nullptr); + + RefPtr<TestVsyncObserver> testVsyncObserver = new TestVsyncObserver(); + mVsyncDispatcher->AddVsyncObserver(testVsyncObserver); + ASSERT_TRUE(mVsyncSource->IsVsyncEnabled()); + + testVsyncObserver->WaitForVsyncNotification(); + ASSERT_TRUE(testVsyncObserver->DidGetVsyncNotification()); + + mVsyncDispatcher->RemoveVsyncObserver(testVsyncObserver); + testVsyncObserver->ResetVsyncNotification(); + testVsyncObserver->WaitForVsyncNotification(); + ASSERT_FALSE(testVsyncObserver->DidGetVsyncNotification()); + + testVsyncObserver = nullptr; + + mVsyncSource->DisableVsync(); + ASSERT_FALSE(mVsyncSource->IsVsyncEnabled()); +} + +// Test that we can read the vsync rate +TEST_F(VsyncTester, VsyncSourceHasVsyncRate) { + TimeDuration vsyncRate = mVsyncSource->GetVsyncRate(); + ASSERT_NE(vsyncRate, TimeDuration::Forever()); + ASSERT_GT(vsyncRate.ToMilliseconds(), 0); + + mVsyncSource->DisableVsync(); + ASSERT_FALSE(mVsyncSource->IsVsyncEnabled()); +} |