1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef _WaylandVsyncSource_h_ 7 #define _WaylandVsyncSource_h_ 8 9 #include "base/thread.h" 10 #include "mozilla/RefPtr.h" 11 #include "mozilla/Mutex.h" 12 #include "mozilla/Monitor.h" 13 #include "mozilla/layers/NativeLayerWayland.h" 14 #include "MozContainer.h" 15 #include "nsWaylandDisplay.h" 16 #include "VsyncSource.h" 17 18 namespace mozilla { 19 20 using layers::NativeLayerRootWayland; 21 22 /* 23 * WaylandVsyncSource 24 * 25 * This class provides a per-widget VsyncSource under Wayland, emulated using 26 * frame callbacks on the widget surface with empty surface commits. 27 * 28 * Wayland does not expose vsync/vblank, as it considers that an implementation 29 * detail the clients should not concern themselves with. Instead, frame 30 * callbacks are provided whenever the compositor believes it is a good time to 31 * start drawing the next frame for a particular surface, giving us as much 32 * time as possible to do so. 33 * 34 * Note that the compositor sends frame callbacks only when it sees fit, and 35 * when that may be is entirely up to the compositor. One cannot expect a 36 * certain rate of callbacks, or any callbacks at all. Examples of common 37 * variations would be surfaces moved between outputs with different refresh 38 * rates, and surfaces that are hidden and therefore do not receieve any 39 * callbacks at all. Other hypothetical scenarios of variation could be 40 * throttling to conserve power, or because a user has requested it. 41 * 42 */ 43 class WaylandVsyncSource final : public gfx::VsyncSource { 44 public: WaylandVsyncSource()45 WaylandVsyncSource() { mGlobalDisplay = new WaylandDisplay(); } 46 ~WaylandVsyncSource()47 virtual ~WaylandVsyncSource() { MOZ_ASSERT(NS_IsMainThread()); } 48 GetGlobalDisplay()49 virtual Display& GetGlobalDisplay() override { return *mGlobalDisplay; } 50 51 class WaylandDisplay final : public mozilla::gfx::VsyncSource::Display { 52 public: 53 WaylandDisplay(); 54 55 void MaybeUpdateSource(MozContainer* aContainer); 56 void MaybeUpdateSource( 57 const RefPtr<NativeLayerRootWayland>& aNativeLayerRoot); 58 59 void EnableMonitor(); 60 void DisableMonitor(); 61 62 void FrameCallback(uint32_t timestampTime); 63 void Notify(); 64 65 TimeDuration GetVsyncRate() override; 66 67 virtual void EnableVsync() override; 68 69 virtual void DisableVsync() override; 70 71 virtual bool IsVsyncEnabled() override; 72 73 virtual void Shutdown() override; 74 75 private: 76 virtual ~WaylandDisplay() = default; 77 void Refresh(); 78 void SetupFrameCallback(); 79 void ClearFrameCallback(); 80 void CalculateVsyncRate(TimeStamp vsyncTimestamp); 81 82 Mutex mMutex; 83 bool mIsShutdown; 84 bool mVsyncEnabled; 85 bool mMonitorEnabled; 86 bool mCallbackRequested; 87 struct wl_display* mDisplay; 88 MozContainer* mContainer; 89 RefPtr<NativeLayerRootWayland> mNativeLayerRoot; 90 TimeDuration mVsyncRate; 91 TimeStamp mLastVsyncTimeStamp; 92 }; 93 94 private: 95 // We need a refcounted VsyncSource::Display to use chromium IPC runnables. 96 RefPtr<WaylandDisplay> mGlobalDisplay; 97 }; 98 99 } // namespace mozilla 100 101 #endif // _WaylandVsyncSource_h_ 102