Bug 1324592 - Use nsITimer to trigger DirectInput polling instead of DelayedDispatch. r=qdot
authorChih-Yi Leu <cleu@mozilla.com>
Thu, 29 Dec 2016 15:00:00 -0500
changeset 327763 ee66c0cbd0585a7a1618f2a5718ca0e0de5ccb3a
parent 327762 31ffcb82ced81bb75faa800d2b7e883a3761a03b
child 327764 949122733877f55beb3245d7490040ee52d24c03
push id85268
push userryanvm@gmail.com
push dateMon, 02 Jan 2017 03:34:20 +0000
treeherdermozilla-inbound@949122733877 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersqdot
bugs1324592
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1324592 - Use nsITimer to trigger DirectInput polling instead of DelayedDispatch. r=qdot
dom/gamepad/windows/WindowsGamepad.cpp
--- a/dom/gamepad/windows/WindowsGamepad.cpp
+++ b/dom/gamepad/windows/WindowsGamepad.cpp
@@ -324,30 +324,59 @@ public:
   decltype(HidP_GetUsages) *mHidP_GetUsages;
   decltype(HidP_GetUsageValue) *mHidP_GetUsageValue;
   decltype(HidP_GetScaledUsageValue) *mHidP_GetScaledUsageValue;
 
 private:
   HMODULE mModule;
 };
 
+HWND sHWnd = nullptr;
+
+static void
+DirectInputMessageLoopOnceCallback(nsITimer *aTimer, void* aClosure)
+{
+  MOZ_ASSERT(NS_GetCurrentThread() == gMonitorThread);
+  MSG msg;
+  while (PeekMessageW(&msg, sHWnd, 0, 0, PM_REMOVE) > 0) {
+    TranslateMessage(&msg);
+    DispatchMessage(&msg);
+  }
+  aTimer->Cancel();
+  if (!sIsShutdown) {
+    aTimer->InitWithFuncCallback(DirectInputMessageLoopOnceCallback,
+                                 nullptr, kWindowsGamepadPollInterval,
+                                 nsITimer::TYPE_ONE_SHOT);
+  }
+}
+
 class WindowsGamepadService
 {
  public:
   WindowsGamepadService()
   {
+    mDirectInputTimer = do_CreateInstance("@mozilla.org/timer;1");
     mXInputTimer = do_CreateInstance("@mozilla.org/timer;1");
     mDeviceChangeTimer = do_CreateInstance("@mozilla.org/timer;1");
   }
   virtual ~WindowsGamepadService()
   {
     Cleanup();
   }
 
   void DevicesChanged(bool aIsStablizing);
+
+  void StartMessageLoop()
+  {
+    MOZ_ASSERT(mDirectInputTimer);
+    mDirectInputTimer->InitWithFuncCallback(DirectInputMessageLoopOnceCallback,
+                                            nullptr, kWindowsGamepadPollInterval,
+                                            nsITimer::TYPE_ONE_SHOT);
+  }
+
   void Startup();
   void Shutdown();
   // Parse gamepad input from a WM_INPUT message.
   bool HandleRawInput(HRAWINPUT handle);
 
   static void XInputMessageLoopOnceCallback(nsITimer *aTimer, void* aClosure);
   static void DevicesChangeCallback(nsITimer *aTimer, void* aService);
 
@@ -368,16 +397,17 @@ class WindowsGamepadService
   void Cleanup();
 
   // List of connected devices.
   nsTArray<Gamepad> mGamepads;
 
   HIDLoader mHID;
   XInputLoader mXInput;
 
+  nsCOMPtr<nsITimer> mDirectInputTimer;
   nsCOMPtr<nsITimer> mXInputTimer;
   nsCOMPtr<nsITimer> mDeviceChangeTimer;
 };
 
 
 void
 WindowsGamepadService::ScanForRawInputDevices()
 {
@@ -887,16 +917,19 @@ WindowsGamepadService::Shutdown()
 {
   Cleanup();
 }
 
 void
 WindowsGamepadService::Cleanup()
 {
   mIsXInputMonitoring = false;
+  if (mDirectInputTimer) {
+    mDirectInputTimer->Cancel();
+  }
   if (mXInputTimer) {
     mXInputTimer->Cancel();
   }
   if (mDeviceChangeTimer) {
     mDeviceChangeTimer->Cancel();
   }
   mGamepads.Clear();
 }
@@ -909,18 +942,16 @@ WindowsGamepadService::DevicesChanged(bo
     mDeviceChangeTimer->InitWithFuncCallback(DevicesChangeCallback, this,
                                              kDevicesChangedStableDelay,
                                              nsITimer::TYPE_ONE_SHOT);
   } else {
     ScanForDevices();
   }
 }
 
-HWND sHWnd = nullptr;
-
 bool
 RegisterRawInput(HWND hwnd, bool enable)
 {
   nsTArray<RAWINPUTDEVICE> rid(ArrayLength(kUsagePages));
   rid.SetLength(ArrayLength(kUsagePages));
 
   for (unsigned i = 0; i < rid.Length(); i++) {
     rid[i].usUsagePage = kUsagePages[i].usagePage;
@@ -959,39 +990,16 @@ GamepadWindowProc(HWND hwnd, UINT msg, W
     if (gService) {
       gService->HandleRawInput(reinterpret_cast<HRAWINPUT>(lParam));
     }
     break;
   }
   return DefWindowProc(hwnd, msg, wParam, lParam);
 }
 
-class WindowGamepadMessageLoopOnceRunnable final : public Runnable
-{
-public:
-  WindowGamepadMessageLoopOnceRunnable() {}
-  NS_IMETHOD Run() override
-  {
-    MOZ_ASSERT(NS_GetCurrentThread() == gMonitorThread);
-    MSG msg;
-    while (PeekMessageW(&msg, sHWnd, 0, 0, PM_REMOVE) > 0) {
-      TranslateMessage(&msg);
-      DispatchMessage(&msg);
-    }
-    if (!sIsShutdown) {
-      nsCOMPtr<nsIRunnable> runnable = new WindowGamepadMessageLoopOnceRunnable();
-      NS_DelayedDispatchToCurrentThread(runnable.forget(),
-                                        kWindowsGamepadPollInterval);
-    }
-    return NS_OK;
-  }
-private:
-  ~WindowGamepadMessageLoopOnceRunnable() {}
-};
-
 class StartWindowsGamepadServiceRunnable final : public Runnable
 {
 public:
   StartWindowsGamepadServiceRunnable() {}
 
   NS_IMETHOD Run() override
   {
     MOZ_ASSERT(NS_GetCurrentThread() == gMonitorThread);
@@ -1012,17 +1020,17 @@ public:
 
       sHWnd = CreateWindowW(L"MozillaGamepadClass", L"Gamepad Watcher",
         0, 0, 0, 0, 0,
         nullptr, nullptr, hSelf, nullptr);
       RegisterRawInput(sHWnd, true);
     }
 
     // Explicitly start the message loop
-    NS_DispatchToCurrentThread(new WindowGamepadMessageLoopOnceRunnable());
+    gService->StartMessageLoop();
 
     return NS_OK;
   }
 private:
   ~StartWindowsGamepadServiceRunnable() {}
 };
 
 class StopWindowsGamepadServiceRunnable final : public Runnable