GPUProcessManager.h (16104B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 #ifndef _include_mozilla_gfx_ipc_GPUProcessManager_h_ 7 #define _include_mozilla_gfx_ipc_GPUProcessManager_h_ 8 9 #include "base/basictypes.h" 10 #include "base/process.h" 11 #include "Units.h" 12 #include "mozilla/dom/ipc/IdType.h" 13 #include "mozilla/gfx/GPUProcessHost.h" 14 #include "mozilla/gfx/PGPUChild.h" 15 #include "mozilla/gfx/Point.h" 16 #include "mozilla/Hal.h" 17 #include "mozilla/ipc/ProtocolUtils.h" 18 #include "mozilla/ipc/TaskFactory.h" 19 #include "mozilla/layers/LayersTypes.h" 20 #include "mozilla/webrender/WebRenderTypes.h" 21 #include "nsIObserver.h" 22 #include "nsThreadUtils.h" 23 class nsIWidget; 24 enum class DeviceResetReason; 25 26 namespace mozilla { 27 class MemoryReportingProcess; 28 class PRemoteMediaManagerChild; 29 class RDDProcessManager; 30 class RDDChild; 31 namespace layers { 32 class IAPZCTreeManager; 33 class CompositorOptions; 34 class CompositorSession; 35 class CompositorUpdateObserver; 36 class PCompositorBridgeChild; 37 class PCompositorManagerChild; 38 class PImageBridgeChild; 39 class PVideoBridgeParent; 40 class RemoteCompositorSession; 41 class InProcessCompositorSession; 42 class UiCompositorControllerChild; 43 class WebRenderLayerManager; 44 } // namespace layers 45 namespace widget { 46 class CompositorWidget; 47 } // namespace widget 48 namespace dom { 49 class ContentParent; 50 class BrowserParent; 51 } // namespace dom 52 namespace ipc { 53 class GeckoChildProcessHost; 54 #ifdef MOZ_WMF_MEDIA_ENGINE 55 class UtilityMediaServiceChild; 56 #endif 57 } // namespace ipc 58 namespace gfx { 59 60 class GPUChild; 61 class GPUProcessListener; 62 class PVRManagerChild; 63 class VsyncBridgeChild; 64 class VsyncIOThreadHolder; 65 66 // The GPUProcessManager is a singleton responsible for creating GPU-bound 67 // objects that may live in another process. Currently, it provides access 68 // to the compositor via CompositorBridgeParent. 69 class GPUProcessManager final : public GPUProcessHost::Listener { 70 friend class layers::RemoteCompositorSession; 71 friend class layers::InProcessCompositorSession; 72 73 typedef layers::CompositorOptions CompositorOptions; 74 typedef layers::CompositorSession CompositorSession; 75 typedef layers::CompositorUpdateObserver CompositorUpdateObserver; 76 typedef layers::IAPZCTreeManager IAPZCTreeManager; 77 typedef layers::WebRenderLayerManager WebRenderLayerManager; 78 typedef layers::LayersId LayersId; 79 typedef layers::PCompositorBridgeChild PCompositorBridgeChild; 80 typedef layers::PCompositorManagerChild PCompositorManagerChild; 81 typedef layers::PImageBridgeChild PImageBridgeChild; 82 typedef layers::PVideoBridgeParent PVideoBridgeParent; 83 typedef layers::RemoteCompositorSession RemoteCompositorSession; 84 typedef layers::InProcessCompositorSession InProcessCompositorSession; 85 typedef layers::UiCompositorControllerChild UiCompositorControllerChild; 86 87 public: 88 static void Initialize(); 89 static void Shutdown(); 90 static GPUProcessManager* Get(); 91 92 ~GPUProcessManager(); 93 94 // If not using a GPU process, launch a new GPU process asynchronously. 95 nsresult LaunchGPUProcess(); 96 bool IsGPUProcessLaunching(); 97 98 // Ensure that GPU-bound methods can be used. If no GPU process is being 99 // used, or one is launched and ready, this function returns immediately. 100 // Otherwise it blocks until the GPU process has finished launching. 101 // If the GPU process is enabled but has not yet been launched then this will 102 // launch the process. If that is not desired then check that return value of 103 // Process() is non-null before calling. 104 // 105 // Returns: 106 // - NS_OK if compositing is ready, in either the GPU process or the parent 107 // process, even if in shutdown. 108 // - NS_ERROR_ILLEGAL_DURING_SHUTDOWN if compositing is not ready, and we are 109 // in shutdown. 110 // - NS_ERROR_ABORT if on Android and we are in the background. This is a 111 // temporary error that we should recover from when in the foreground. 112 nsresult EnsureGPUReady(); 113 114 bool IsGPUReady() const; 115 116 already_AddRefed<CompositorSession> CreateTopLevelCompositor( 117 nsIWidget* aWidget, WebRenderLayerManager* aLayerManager, 118 CSSToLayoutDeviceScale aScale, const CompositorOptions& aOptions, 119 bool aUseExternalSurfaceSize, const gfx::IntSize& aSurfaceSize, 120 uint64_t aInnerWindowId, bool* aRetry); 121 122 // It is asserted that IsGPUReady() is true for this method. If not on a path 123 // which guarantees that, then the caller must call EnsureGPUReady() and check 124 // its return code first. 125 bool CreateContentBridges( 126 mozilla::ipc::EndpointProcInfo aOtherProcess, 127 mozilla::ipc::Endpoint<PCompositorManagerChild>* aOutCompositor, 128 mozilla::ipc::Endpoint<PImageBridgeChild>* aOutImageBridge, 129 mozilla::ipc::Endpoint<PVRManagerChild>* aOutVRBridge, 130 mozilla::ipc::Endpoint<PRemoteMediaManagerChild>* aOutVideoManager, 131 dom::ContentParentId aChildId, nsTArray<uint32_t>* aNamespaces); 132 133 nsresult CreateRddVideoBridge(RDDProcessManager* aRDD, RDDChild* aChild); 134 #ifdef MOZ_WMF_MEDIA_ENGINE 135 nsresult CreateUtilityMFCDMVideoBridge( 136 mozilla::ipc::UtilityMediaServiceChild* aChild, 137 mozilla::ipc::EndpointProcInfo aOtherProcess); 138 #endif 139 140 // Release compositor-thread resources referred to by |aID|. 141 // 142 // Must run on the content main thread. 143 void UnmapLayerTreeId(LayersId aLayersId, base::ProcessId aOwningId); 144 145 // Checks to see if aLayersId and aRequestingPID have been mapped by 146 // MapLayerTreeId 147 bool IsLayerTreeIdMapped(LayersId aLayersId, base::ProcessId aRequestingId); 148 149 // Allocate an ID that can be used to refer to a layer tree and 150 // associated resources that live only on the compositor thread. 151 // 152 // Must run on the browser main thread. 153 LayersId AllocateLayerTreeId(); 154 155 // Allocate an ID that can be used as Namespace and 156 // Must run on the browser main thread. 157 uint32_t AllocateNamespace(); 158 159 // Allocate a layers ID and connect it to a compositor. If the compositor is 160 // null, the connect operation will not be performed, but an ID will still be 161 // allocated. This must be called from the browser main thread. 162 // 163 // It also maps the layer tree and process together so that aOwningPID is 164 // allowed to access aLayersId across process. 165 // 166 // Note that a layer tree id is always allocated, even if this returns false. 167 bool AllocateAndConnectLayerTreeId(PCompositorBridgeChild* aCompositorBridge, 168 base::ProcessId aOtherPid, 169 LayersId* aOutLayersId, 170 CompositorOptions* aOutCompositorOptions); 171 172 // Destroy and recreate all of the compositors 173 void ResetCompositors(); 174 175 // Record the device reset in telemetry / annotate the crash report. 176 static void RecordDeviceReset(DeviceResetReason aReason); 177 178 static void NotifyDeviceReset(DeviceResetReason aReason, 179 DeviceResetDetectPlace aPlace); 180 181 void OnProcessLaunchComplete(GPUProcessHost* aHost) override; 182 void OnProcessUnexpectedShutdown(GPUProcessHost* aHost) override; 183 void SimulateDeviceReset(); 184 void DisableWebRender(wr::WebRenderError aError, const nsCString& aMsg); 185 void NotifyWebRenderError(wr::WebRenderError aError); 186 void OnInProcessDeviceReset(DeviceResetReason aReason, 187 DeviceResetDetectPlace aPlace); 188 void OnRemoteProcessDeviceReset( 189 GPUProcessHost* aHost, const DeviceResetReason& aReason, 190 const DeviceResetDetectPlace& aPlace) override; 191 void OnProcessDeclaredStable() override; 192 void NotifyListenersOnCompositeDeviceReset(); 193 194 // Notify the GPUProcessManager that a top-level PGPU protocol has been 195 // terminated. This may be called from any thread. 196 void NotifyRemoteActorDestroyed(const uint64_t& aProcessToken); 197 198 void AddListener(GPUProcessListener* aListener); 199 void RemoveListener(GPUProcessListener* aListener); 200 201 // Send a message to the GPU process observer service to broadcast. Returns 202 // true if the message was sent, false if not. 203 bool NotifyGpuObservers(const char* aTopic); 204 205 // Kills the GPU process. Used in normal operation to recover from an error, 206 // as well as for tests and diagnostics. 207 void KillProcess(bool aGenerateMinidump = false); 208 209 // Invoked when we know we will shutdown (but before shutdown begins), to 210 // avoid races with other shutdown observers. 211 void StopBatteryObserving(); 212 213 // Causes the GPU process to crash. Used for tests and diagnostics 214 void CrashProcess(); 215 216 // Returns -1 if there is no GPU process, or the platform pid for it. 217 base::ProcessId GPUProcessPid(); 218 219 // Returns Invalid() if there is no GPU process, or the proc info for it. 220 mozilla::ipc::EndpointProcInfo GPUEndpointProcInfo(); 221 222 // If a GPU process is present, create a MemoryReportingProcess object. 223 // Otherwise, return null. 224 RefPtr<MemoryReportingProcess> GetProcessMemoryReporter(); 225 226 // Returns access to the PGPU protocol if a GPU process is present. 227 GPUChild* GetGPUChild() { return mGPUChild; } 228 229 // Returns whether or not a GPU process was ever launched. 230 bool AttemptedGPUProcess() const { return mTotalProcessAttempts > 0; } 231 232 // Returns the process host 233 GPUProcessHost* Process() { return mProcess; } 234 235 // Sets the value of mAppInForeground, and (on Windows) adjusts the priority 236 // of the GPU process accordingly. 237 void SetAppInForeground(bool aInForeground); 238 239 /* 240 * ** Test-only Method ** 241 * 242 * Trigger GPU-process test metric instrumentation. 243 */ 244 RefPtr<PGPUChild::TestTriggerMetricsPromise> TestTriggerMetrics(); 245 246 private: 247 void OnPreferenceChange(const char16_t* aData); 248 void ScreenInformationChanged(); 249 250 bool CreateContentCompositorManager( 251 mozilla::ipc::EndpointProcInfo aOtherProcess, 252 dom::ContentParentId aChildId, uint32_t aNamespace, 253 mozilla::ipc::Endpoint<PCompositorManagerChild>* aOutEndpoint); 254 bool CreateContentImageBridge( 255 mozilla::ipc::EndpointProcInfo aOtherProcess, 256 dom::ContentParentId aChildId, 257 mozilla::ipc::Endpoint<PImageBridgeChild>* aOutEndpoint); 258 bool CreateContentVRManager( 259 mozilla::ipc::EndpointProcInfo aOtherProcess, 260 dom::ContentParentId aChildId, 261 mozilla::ipc::Endpoint<PVRManagerChild>* aOutEndpoint); 262 void CreateContentRemoteMediaManager( 263 mozilla::ipc::EndpointProcInfo aOtherProcess, 264 dom::ContentParentId aChildId, 265 mozilla::ipc::Endpoint<PRemoteMediaManagerChild>* aOutEndPoint); 266 267 nsresult EnsureVideoBridge( 268 layers::VideoBridgeSource aSource, 269 mozilla::ipc::EndpointProcInfo aOtherProcess, 270 mozilla::ipc::Endpoint<layers::PVideoBridgeChild>* aOutChildPipe); 271 272 // Called from RemoteCompositorSession. We track remote sessions so we can 273 // notify their owning widgets that the session must be restarted. 274 void RegisterRemoteProcessSession(RemoteCompositorSession* aSession); 275 void UnregisterRemoteProcessSession(RemoteCompositorSession* aSession); 276 277 // Called from InProcessCompositorSession. We track in process sessino so we 278 // can notify their owning widgets that the session must be restarted 279 void RegisterInProcessSession(InProcessCompositorSession* aSession); 280 void UnregisterInProcessSession(InProcessCompositorSession* aSession); 281 282 void DestroyRemoteCompositorSessions(); 283 void DestroyInProcessCompositorSessions(); 284 285 // Returns true if we crossed the threshold such that we should disable 286 // acceleration. 287 bool OnDeviceReset(bool aTrackThreshold); 288 289 void DisableWebRenderConfig(wr::WebRenderError aError, const nsCString& aMsg); 290 291 void FallbackToSoftware(const char* aMessage); 292 293 private: 294 GPUProcessManager(); 295 296 // Permanently disable the GPU process and record a message why. 297 void DisableGPUProcess(const char* aMessage); 298 299 // May permanently disable the GPU process and record a message why. May 300 // return false if the fallback process decided we should retry the GPU 301 // process, but only if aAllowRestart is also true. 302 bool MaybeDisableGPUProcess(const char* aMessage, bool aAllowRestart); 303 304 bool FallbackFromAcceleration(wr::WebRenderError aError, 305 const nsCString& aMsg); 306 307 // Crashes the parent process if we are disabling the GPU process and we 308 // ever once had a stable GPU process. This is to avoid fallback into the 309 // parent when we know the configuration allows for the GPU process. 310 void MaybeCrashIfGpuProcessOnceStable(); 311 312 void ResetProcessStable(); 313 314 // Returns true if the composting pocess is currently considered to be stable. 315 bool IsProcessStable(const TimeStamp& aNow); 316 317 // Shutdown the GPU process. 318 void ShutdownInternal(); 319 // Destroy the process and clean up resources. 320 // Setting aUnexpectedShutdown = true indicates that this is being called to 321 // clean up resources in response to an unexpected shutdown having been 322 // detected. 323 void DestroyProcess(bool aUnexpectedShutdown = false); 324 325 void HandleProcessLost(); 326 // Reinitialize rendering following a GPU process loss. 327 void ReinitializeRendering(); 328 329 void EnsureVsyncIOThread(); 330 void ShutdownVsyncIOThread(); 331 332 bool EnsureProtocolsReady(); 333 bool EnsureCompositorManagerChild(); 334 bool EnsureImageBridgeChild(); 335 bool EnsureVRManager(); 336 337 #if defined(XP_WIN) 338 void SetProcessIsForeground(); 339 #endif 340 341 #if defined(MOZ_WIDGET_ANDROID) 342 RefPtr<UiCompositorControllerChild> CreateUiCompositorController( 343 nsIWidget* aWidget, const LayersId aId); 344 #endif // defined(MOZ_WIDGET_ANDROID) 345 346 RefPtr<CompositorSession> CreateRemoteSession( 347 nsIWidget* aWidget, WebRenderLayerManager* aLayerManager, 348 const LayersId& aRootLayerTreeId, CSSToLayoutDeviceScale aScale, 349 const CompositorOptions& aOptions, bool aUseExternalSurfaceSize, 350 const gfx::IntSize& aSurfaceSize, uint64_t aInnerWindowId); 351 352 DISALLOW_COPY_AND_ASSIGN(GPUProcessManager); 353 354 void NotifyObserve(const char* aTopic, const char16_t* aData); 355 void NotifyBatteryInfo(const hal::BatteryInformation& aBatteryInfo); 356 357 class Observer final : public nsIObserver { 358 public: 359 NS_DECL_ISUPPORTS 360 NS_DECL_NSIOBSERVER 361 362 Observer(); 363 void Shutdown(); 364 365 protected: 366 virtual ~Observer() = default; 367 }; 368 friend class Observer; 369 370 class BatteryObserver final : public hal::BatteryObserver { 371 public: 372 NS_INLINE_DECL_REFCOUNTING(BatteryObserver) 373 374 BatteryObserver(); 375 void Notify(const hal::BatteryInformation& aBatteryInfo) override; 376 void Shutdown(); 377 378 protected: 379 ~BatteryObserver() override = default; 380 }; 381 382 private: 383 bool mDecodeVideoOnGpuProcess = true; 384 385 RefPtr<Observer> mObserver; 386 RefPtr<BatteryObserver> mBatteryObserver; 387 mozilla::ipc::TaskFactory<GPUProcessManager> mTaskFactory; 388 RefPtr<VsyncIOThreadHolder> mVsyncIOThread; 389 uint32_t mNextNamespace; 390 uint32_t mIdNamespace; 391 uint32_t mResourceId; 392 393 uint32_t mUnstableProcessAttempts; 394 uint32_t mTotalProcessAttempts; 395 uint32_t mLaunchProcessAttempts = 0; 396 TimeStamp mProcessAttemptLastTime; 397 398 nsTArray<RefPtr<RemoteCompositorSession>> mRemoteSessions; 399 nsTArray<RefPtr<InProcessCompositorSession>> mInProcessSessions; 400 nsTArray<RefPtr<GPUProcessListener>> mListeners; 401 402 uint32_t mDeviceResetCount; 403 TimeStamp mDeviceResetLastTime; 404 405 // Keeps track of whether not the application is in the foreground on android. 406 bool mAppInForeground; 407 408 // Fields that are associated with the current GPU process. 409 GPUProcessHost* mProcess; 410 uint64_t mProcessToken; 411 bool mProcessStable = false; 412 bool mProcessStableOnce = false; 413 Maybe<wr::WebRenderError> mLastError; 414 Maybe<nsCString> mLastErrorMsg; 415 GPUChild* mGPUChild; 416 RefPtr<VsyncBridgeChild> mVsyncBridge; 417 // Collects any pref changes that occur during process launch (after 418 // the initial map is passed in command-line arguments) to be sent 419 // when the process can receive IPC messages. 420 nsTArray<mozilla::dom::Pref> mQueuedPrefs; 421 }; 422 423 } // namespace gfx 424 } // namespace mozilla 425 426 #endif // _include_mozilla_gfx_ipc_GPUProcessManager_h_