tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestVsync.cpp (5136B)


      1 /* vim:set ts=2 sw=2 sts=2 et: */
      2 /* Any copyright is dedicated to the Public Domain.
      3 * http://creativecommons.org/publicdomain/zero/1.0/
      4 */
      5 
      6 #include "gmock/gmock.h"
      7 #include "gtest/gtest.h"
      8 #include "gfxPlatform.h"
      9 
     10 #include "MainThreadUtils.h"
     11 #include "nsIThread.h"
     12 #include "mozilla/RefPtr.h"
     13 #include "SoftwareVsyncSource.h"
     14 #include "VsyncSource.h"
     15 #include "mozilla/gtest/MozAssertions.h"
     16 #include "mozilla/Monitor.h"
     17 #include "mozilla/TimeStamp.h"
     18 #include "mozilla/VsyncDispatcher.h"
     19 
     20 using namespace mozilla;
     21 using namespace mozilla::gfx;
     22 using namespace mozilla::layers;
     23 using ::testing::_;
     24 
     25 // Timeout for vsync events to occur in milliseconds
     26 // Windows 8.1 has intermittents at 50 ms. Raise limit to 5 vsync intervals.
     27 const int kVsyncTimeoutMS = 80;
     28 
     29 class TestVsyncObserver : public VsyncObserver {
     30  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestVsyncObserver, override)
     31 
     32 public:
     33  TestVsyncObserver()
     34      : mDidGetVsyncNotification(false), mVsyncMonitor("VsyncMonitor") {}
     35 
     36  virtual void NotifyVsync(const VsyncEvent& aVsync) override {
     37    MonitorAutoLock lock(mVsyncMonitor);
     38    mDidGetVsyncNotification = true;
     39    mVsyncMonitor.Notify();
     40  }
     41 
     42  void WaitForVsyncNotification() {
     43    MOZ_ASSERT(NS_IsMainThread());
     44    if (DidGetVsyncNotification()) {
     45      return;
     46    }
     47 
     48    {  // scope lock
     49      MonitorAutoLock lock(mVsyncMonitor);
     50      lock.Wait(TimeDuration::FromMilliseconds(kVsyncTimeoutMS));
     51    }
     52  }
     53 
     54  bool DidGetVsyncNotification() {
     55    MonitorAutoLock lock(mVsyncMonitor);
     56    return mDidGetVsyncNotification;
     57  }
     58 
     59  void ResetVsyncNotification() {
     60    MonitorAutoLock lock(mVsyncMonitor);
     61    mDidGetVsyncNotification = false;
     62  }
     63 
     64 private:
     65  ~TestVsyncObserver() = default;
     66 
     67  bool mDidGetVsyncNotification;
     68 
     69 private:
     70  Monitor mVsyncMonitor MOZ_UNANNOTATED;
     71 };
     72 
     73 class VsyncTester : public ::testing::Test {
     74 protected:
     75  explicit VsyncTester() {
     76    gfxPlatform::GetPlatform();
     77    mVsyncDispatcher = gfxPlatform::GetPlatform()->GetGlobalVsyncDispatcher();
     78    mVsyncSource = mVsyncDispatcher->GetCurrentVsyncSource();
     79    MOZ_RELEASE_ASSERT(mVsyncSource, "GFX: Vsync source not found.");
     80  }
     81 
     82  virtual ~VsyncTester() { mVsyncSource = nullptr; }
     83 
     84  RefPtr<VsyncDispatcher> mVsyncDispatcher;
     85  RefPtr<VsyncSource> mVsyncSource;
     86 };
     87 
     88 static void FlushMainThreadLoop() {
     89  // Some tasks are pushed onto the main thread when adding vsync observers
     90  // This function will ensure all tasks are executed on the main thread
     91  // before returning.
     92  nsCOMPtr<nsIThread> mainThread;
     93  nsresult rv = NS_GetMainThread(getter_AddRefs(mainThread));
     94  ASSERT_NS_SUCCEEDED(rv);
     95 
     96  rv = NS_OK;
     97  bool processed = true;
     98  while (processed && NS_SUCCEEDED(rv)) {
     99    rv = mainThread->ProcessNextEvent(false, &processed);
    100  }
    101 }
    102 
    103 // Tests that we can enable/disable vsync notifications
    104 TEST_F(VsyncTester, EnableVsync) {
    105  mVsyncSource->DisableVsync();
    106  ASSERT_FALSE(mVsyncSource->IsVsyncEnabled());
    107 
    108  mVsyncSource->EnableVsync();
    109  ASSERT_TRUE(mVsyncSource->IsVsyncEnabled());
    110 
    111  mVsyncSource->DisableVsync();
    112  ASSERT_FALSE(mVsyncSource->IsVsyncEnabled());
    113 }
    114 
    115 // Test that if we have vsync enabled, the source should get vsync
    116 // notifications
    117 TEST_F(VsyncTester, CompositorGetVsyncNotifications) {
    118  mVsyncSource->DisableVsync();
    119  ASSERT_FALSE(mVsyncSource->IsVsyncEnabled());
    120 
    121  RefPtr<CompositorVsyncDispatcher> vsyncDispatcher =
    122      new CompositorVsyncDispatcher(mVsyncDispatcher);
    123  RefPtr<TestVsyncObserver> testVsyncObserver = new TestVsyncObserver();
    124 
    125  vsyncDispatcher->SetCompositorVsyncObserver(testVsyncObserver);
    126  FlushMainThreadLoop();
    127  ASSERT_TRUE(mVsyncSource->IsVsyncEnabled());
    128 
    129  testVsyncObserver->WaitForVsyncNotification();
    130  ASSERT_TRUE(testVsyncObserver->DidGetVsyncNotification());
    131 
    132  vsyncDispatcher->SetCompositorVsyncObserver(nullptr);
    133  FlushMainThreadLoop();
    134 
    135  vsyncDispatcher = nullptr;
    136  testVsyncObserver = nullptr;
    137  ASSERT_FALSE(mVsyncSource->IsVsyncEnabled());
    138 }
    139 
    140 // Test that child refresh vsync observers get vsync notifications
    141 TEST_F(VsyncTester, ChildRefreshDriverGetVsyncNotifications) {
    142  mVsyncSource->DisableVsync();
    143  ASSERT_FALSE(mVsyncSource->IsVsyncEnabled());
    144 
    145  ASSERT_TRUE(mVsyncDispatcher != nullptr);
    146 
    147  RefPtr<TestVsyncObserver> testVsyncObserver = new TestVsyncObserver();
    148  mVsyncDispatcher->AddVsyncObserver(testVsyncObserver);
    149  ASSERT_TRUE(mVsyncSource->IsVsyncEnabled());
    150 
    151  testVsyncObserver->WaitForVsyncNotification();
    152  ASSERT_TRUE(testVsyncObserver->DidGetVsyncNotification());
    153 
    154  mVsyncDispatcher->RemoveVsyncObserver(testVsyncObserver);
    155  testVsyncObserver->ResetVsyncNotification();
    156  testVsyncObserver->WaitForVsyncNotification();
    157  ASSERT_FALSE(testVsyncObserver->DidGetVsyncNotification());
    158 
    159  testVsyncObserver = nullptr;
    160 
    161  mVsyncSource->DisableVsync();
    162  ASSERT_FALSE(mVsyncSource->IsVsyncEnabled());
    163 }
    164 
    165 // Test that we can read the vsync rate
    166 TEST_F(VsyncTester, VsyncSourceHasVsyncRate) {
    167  TimeDuration vsyncRate = mVsyncSource->GetVsyncRate();
    168  ASSERT_NE(vsyncRate, TimeDuration::Forever());
    169  ASSERT_GT(vsyncRate.ToMilliseconds(), 0);
    170 
    171  mVsyncSource->DisableVsync();
    172  ASSERT_FALSE(mVsyncSource->IsVsyncEnabled());
    173 }