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/UniquePtr.h" 13 #include "mozilla/dom/ipc/IdType.h" 14 #include "mozilla/gfx/GPUProcessHost.h" 15 #include "mozilla/gfx/PGPUChild.h" 16 #include "mozilla/gfx/Point.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 nsBaseWidget; 24 enum class DeviceResetReason; 25 26 namespace mozilla { 27 class MemoryReportingProcess; 28 class PRemoteDecoderManagerChild; 29 namespace layers { 30 class IAPZCTreeManager; 31 class CompositorOptions; 32 class CompositorSession; 33 class CompositorUpdateObserver; 34 class PCompositorBridgeChild; 35 class PCompositorManagerChild; 36 class PImageBridgeChild; 37 class PVideoBridgeParent; 38 class RemoteCompositorSession; 39 class InProcessCompositorSession; 40 class UiCompositorControllerChild; 41 class WebRenderLayerManager; 42 } // namespace layers 43 namespace widget { 44 class CompositorWidget; 45 } // namespace widget 46 namespace dom { 47 class ContentParent; 48 class BrowserParent; 49 } // namespace dom 50 namespace ipc { 51 class GeckoChildProcessHost; 52 } // namespace ipc 53 namespace gfx { 54 55 class GPUChild; 56 class GPUProcessListener; 57 class PVRManagerChild; 58 class VsyncBridgeChild; 59 class VsyncIOThreadHolder; 60 61 // The GPUProcessManager is a singleton responsible for creating GPU-bound 62 // objects that may live in another process. Currently, it provides access 63 // to the compositor via CompositorBridgeParent. 64 class GPUProcessManager final : public GPUProcessHost::Listener { 65 friend class layers::RemoteCompositorSession; 66 friend class layers::InProcessCompositorSession; 67 68 typedef layers::CompositorOptions CompositorOptions; 69 typedef layers::CompositorSession CompositorSession; 70 typedef layers::CompositorUpdateObserver CompositorUpdateObserver; 71 typedef layers::IAPZCTreeManager IAPZCTreeManager; 72 typedef layers::WebRenderLayerManager WebRenderLayerManager; 73 typedef layers::LayersId LayersId; 74 typedef layers::PCompositorBridgeChild PCompositorBridgeChild; 75 typedef layers::PCompositorManagerChild PCompositorManagerChild; 76 typedef layers::PImageBridgeChild PImageBridgeChild; 77 typedef layers::PVideoBridgeParent PVideoBridgeParent; 78 typedef layers::RemoteCompositorSession RemoteCompositorSession; 79 typedef layers::InProcessCompositorSession InProcessCompositorSession; 80 typedef layers::UiCompositorControllerChild UiCompositorControllerChild; 81 82 public: 83 static void Initialize(); 84 static void Shutdown(); 85 static GPUProcessManager* Get(); 86 87 ~GPUProcessManager(); 88 89 // If not using a GPU process, launch a new GPU process asynchronously. 90 void LaunchGPUProcess(); 91 bool IsGPUProcessLaunching(); 92 93 // Ensure that GPU-bound methods can be used. If no GPU process is being 94 // used, or one is launched and ready, this function returns immediately. 95 // Otherwise it blocks until the GPU process has finished launching. 96 // If the GPU process is enabled but has not yet been launched then this will 97 // launch the process. If that is not desired then check that return value of 98 // Process() is non-null before calling. 99 bool EnsureGPUReady(); 100 101 already_AddRefed<CompositorSession> CreateTopLevelCompositor( 102 nsBaseWidget* aWidget, WebRenderLayerManager* aLayerManager, 103 CSSToLayoutDeviceScale aScale, const CompositorOptions& aOptions, 104 bool aUseExternalSurfaceSize, const gfx::IntSize& aSurfaceSize, 105 bool* aRetry); 106 107 bool CreateContentBridges( 108 base::ProcessId aOtherProcess, 109 mozilla::ipc::Endpoint<PCompositorManagerChild>* aOutCompositor, 110 mozilla::ipc::Endpoint<PImageBridgeChild>* aOutImageBridge, 111 mozilla::ipc::Endpoint<PVRManagerChild>* aOutVRBridge, 112 mozilla::ipc::Endpoint<PRemoteDecoderManagerChild>* aOutVideoManager, 113 nsTArray<uint32_t>* aNamespaces); 114 115 // Initialize GPU process with consuming end of PVideoBridge. 116 void InitVideoBridge( 117 mozilla::ipc::Endpoint<PVideoBridgeParent>&& aVideoBridge); 118 119 // Maps the layer tree and process together so that aOwningPID is allowed 120 // to access aLayersId across process. 121 void MapLayerTreeId(LayersId aLayersId, base::ProcessId aOwningId); 122 123 // Release compositor-thread resources referred to by |aID|. 124 // 125 // Must run on the content main thread. 126 void UnmapLayerTreeId(LayersId aLayersId, base::ProcessId aOwningId); 127 128 // Checks to see if aLayersId and aRequestingPID have been mapped by 129 // MapLayerTreeId 130 bool IsLayerTreeIdMapped(LayersId aLayersId, base::ProcessId aRequestingId); 131 132 // Allocate an ID that can be used to refer to a layer tree and 133 // associated resources that live only on the compositor thread. 134 // 135 // Must run on the browser main thread. 136 LayersId AllocateLayerTreeId(); 137 138 // Allocate an ID that can be used as Namespace and 139 // Must run on the browser main thread. 140 uint32_t AllocateNamespace(); 141 142 // Allocate a layers ID and connect it to a compositor. If the compositor is 143 // null, the connect operation will not be performed, but an ID will still be 144 // allocated. This must be called from the browser main thread. 145 // 146 // Note that a layer tree id is always allocated, even if this returns false. 147 bool AllocateAndConnectLayerTreeId(PCompositorBridgeChild* aCompositorBridge, 148 base::ProcessId aOtherPid, 149 LayersId* aOutLayersId, 150 CompositorOptions* aOutCompositorOptions); 151 152 // Destroy and recreate all of the compositors 153 void ResetCompositors(); 154 155 // Record the device reset in telemetry / annotate the crash report. 156 static void RecordDeviceReset(DeviceResetReason aReason); 157 158 void OnProcessLaunchComplete(GPUProcessHost* aHost) override; 159 void OnProcessUnexpectedShutdown(GPUProcessHost* aHost) override; 160 void SimulateDeviceReset(); 161 void DisableWebRender(wr::WebRenderError aError, const nsCString& aMsg); 162 void NotifyWebRenderError(wr::WebRenderError aError); 163 void OnInProcessDeviceReset(bool aTrackThreshold); 164 void OnRemoteProcessDeviceReset(GPUProcessHost* aHost) override; 165 void OnProcessDeclaredStable() override; 166 void NotifyListenersOnCompositeDeviceReset(); 167 168 // Notify the GPUProcessManager that a top-level PGPU protocol has been 169 // terminated. This may be called from any thread. 170 void NotifyRemoteActorDestroyed(const uint64_t& aProcessToken); 171 172 void AddListener(GPUProcessListener* aListener); 173 void RemoveListener(GPUProcessListener* aListener); 174 175 // Send a message to the GPU process observer service to broadcast. Returns 176 // true if the message was sent, false if not. 177 bool NotifyGpuObservers(const char* aTopic); 178 179 // Kills the GPU process. Used for tests and diagnostics 180 void KillProcess(); 181 182 // Causes the GPU process to crash. Used for tests and diagnostics 183 void CrashProcess(); 184 185 // Returns -1 if there is no GPU process, or the platform pid for it. 186 base::ProcessId GPUProcessPid(); 187 188 // If a GPU process is present, create a MemoryReportingProcess object. 189 // Otherwise, return null. 190 RefPtr<MemoryReportingProcess> GetProcessMemoryReporter(); 191 192 // Returns access to the PGPU protocol if a GPU process is present. GetGPUChild()193 GPUChild* GetGPUChild() { return mGPUChild; } 194 195 // Returns whether or not a GPU process was ever launched. AttemptedGPUProcess()196 bool AttemptedGPUProcess() const { return mTotalProcessAttempts > 0; } 197 198 // Returns the process host Process()199 GPUProcessHost* Process() { return mProcess; } 200 201 /* 202 * ** Test-only Method ** 203 * 204 * Trigger GPU-process test metric instrumentation. 205 */ 206 RefPtr<PGPUChild::TestTriggerMetricsPromise> TestTriggerMetrics(); 207 208 private: 209 // Called from our xpcom-shutdown observer. 210 void OnXPCOMShutdown(); 211 void OnPreferenceChange(const char16_t* aData); 212 213 bool CreateContentCompositorManager( 214 base::ProcessId aOtherProcess, 215 mozilla::ipc::Endpoint<PCompositorManagerChild>* aOutEndpoint); 216 bool CreateContentImageBridge( 217 base::ProcessId aOtherProcess, 218 mozilla::ipc::Endpoint<PImageBridgeChild>* aOutEndpoint); 219 bool CreateContentVRManager( 220 base::ProcessId aOtherProcess, 221 mozilla::ipc::Endpoint<PVRManagerChild>* aOutEndpoint); 222 void CreateContentRemoteDecoderManager( 223 base::ProcessId aOtherProcess, 224 mozilla::ipc::Endpoint<PRemoteDecoderManagerChild>* aOutEndPoint); 225 226 // Called from RemoteCompositorSession. We track remote sessions so we can 227 // notify their owning widgets that the session must be restarted. 228 void RegisterRemoteProcessSession(RemoteCompositorSession* aSession); 229 void UnregisterRemoteProcessSession(RemoteCompositorSession* aSession); 230 231 // Called from InProcessCompositorSession. We track in process sessino so we 232 // can notify their owning widgets that the session must be restarted 233 void RegisterInProcessSession(InProcessCompositorSession* aSession); 234 void UnregisterInProcessSession(InProcessCompositorSession* aSession); 235 236 void DestroyRemoteCompositorSessions(); 237 void DestroyInProcessCompositorSessions(); 238 239 // Returns true if we crossed the threshold such that we should disable 240 // acceleration. 241 bool OnDeviceReset(bool aTrackThreshold); 242 243 // Returns true if WebRender was enabled and is now disabled. 244 bool DisableWebRenderConfig(wr::WebRenderError aError, const nsCString& aMsg); 245 246 void FallbackToSoftware(const char* aMessage); 247 248 private: 249 GPUProcessManager(); 250 251 // Permanently disable the GPU process and record a message why. 252 void DisableGPUProcess(const char* aMessage); 253 254 // May permanently disable the GPU process and record a message why. May 255 // return false if the fallback process decided we should retry the GPU 256 // process, but only if aAllowRestart is also true. 257 bool MaybeDisableGPUProcess(const char* aMessage, bool aAllowRestart); 258 259 // Shutdown the GPU process. 260 void CleanShutdown(); 261 // Destroy the process and clean up resources. 262 // Setting aUnexpectedShutdown = true indicates that this is being called to 263 // clean up resources in response to an unexpected shutdown having been 264 // detected. 265 void DestroyProcess(bool aUnexpectedShutdown = false); 266 267 void HandleProcessLost(); 268 // Reinitialize rendering following a GPU process loss. 269 void ReinitializeRendering(); 270 271 void EnsureVsyncIOThread(); 272 void ShutdownVsyncIOThread(); 273 274 void EnsureProtocolsReady(); 275 void EnsureCompositorManagerChild(); 276 void EnsureImageBridgeChild(); 277 void EnsureVRManager(); 278 279 #if defined(MOZ_WIDGET_ANDROID) 280 already_AddRefed<UiCompositorControllerChild> CreateUiCompositorController( 281 nsBaseWidget* aWidget, const LayersId aId); 282 #endif // defined(MOZ_WIDGET_ANDROID) 283 284 RefPtr<CompositorSession> CreateRemoteSession( 285 nsBaseWidget* aWidget, WebRenderLayerManager* aLayerManager, 286 const LayersId& aRootLayerTreeId, CSSToLayoutDeviceScale aScale, 287 const CompositorOptions& aOptions, bool aUseExternalSurfaceSize, 288 const gfx::IntSize& aSurfaceSize); 289 290 DISALLOW_COPY_AND_ASSIGN(GPUProcessManager); 291 292 class Observer final : public nsIObserver { 293 public: 294 NS_DECL_ISUPPORTS 295 NS_DECL_NSIOBSERVER 296 explicit Observer(GPUProcessManager* aManager); 297 298 protected: 299 virtual ~Observer() = default; 300 301 GPUProcessManager* mManager; 302 }; 303 friend class Observer; 304 305 private: 306 bool mDecodeVideoOnGpuProcess = true; 307 308 RefPtr<Observer> mObserver; 309 mozilla::ipc::TaskFactory<GPUProcessManager> mTaskFactory; 310 RefPtr<VsyncIOThreadHolder> mVsyncIOThread; 311 uint32_t mNextNamespace; 312 uint32_t mIdNamespace; 313 uint32_t mResourceId; 314 315 uint32_t mUnstableProcessAttempts; 316 uint32_t mTotalProcessAttempts; 317 TimeStamp mProcessAttemptLastTime; 318 319 nsTArray<RefPtr<RemoteCompositorSession>> mRemoteSessions; 320 nsTArray<RefPtr<InProcessCompositorSession>> mInProcessSessions; 321 nsTArray<GPUProcessListener*> mListeners; 322 323 uint32_t mDeviceResetCount; 324 TimeStamp mDeviceResetLastTime; 325 326 // Keeps track of whether not the application is in the foreground on android. 327 bool mAppInForeground; 328 329 // Fields that are associated with the current GPU process. 330 GPUProcessHost* mProcess; 331 uint64_t mProcessToken; 332 bool mProcessStable; 333 GPUChild* mGPUChild; 334 RefPtr<VsyncBridgeChild> mVsyncBridge; 335 // Collects any pref changes that occur during process launch (after 336 // the initial map is passed in command-line arguments) to be sent 337 // when the process can receive IPC messages. 338 nsTArray<mozilla::dom::Pref> mQueuedPrefs; 339 }; 340 341 } // namespace gfx 342 } // namespace mozilla 343 344 #endif // _include_mozilla_gfx_ipc_GPUProcessManager_h_ 345