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