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