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_
9 #include "base/basictypes.h"
10 #include "base/process.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"
24 enum class DeviceResetReason
;
27 class MemoryReportingProcess
;
28 class PRemoteDecoderManagerChild
;
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
;
44 class CompositorWidget
;
51 class GeckoChildProcessHost
;
56 class GPUProcessListener
;
57 class PVRManagerChild
;
58 class VsyncBridgeChild
;
59 class VsyncIOThreadHolder
;
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
;
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
;
83 static void Initialize();
84 static void Shutdown();
85 static GPUProcessManager
* Get();
89 // If not using a GPU process, launch a new GPU process asynchronously.
90 bool LaunchGPUProcess();
91 bool IsGPUProcessLaunching();
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();
101 already_AddRefed
<CompositorSession
> CreateTopLevelCompositor(
102 nsBaseWidget
* aWidget
, WebRenderLayerManager
* aLayerManager
,
103 CSSToLayoutDeviceScale aScale
, const CompositorOptions
& aOptions
,
104 bool aUseExternalSurfaceSize
, const gfx::IntSize
& aSurfaceSize
,
105 uint64_t aInnerWindowId
, bool* aRetry
);
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
);
115 // Initialize GPU process with consuming end of PVideoBridge.
116 void InitVideoBridge(
117 mozilla::ipc::Endpoint
<PVideoBridgeParent
>&& aVideoBridge
,
118 layers::VideoBridgeSource aSource
);
120 // Maps the layer tree and process together so that aOwningPID is allowed
121 // to access aLayersId across process.
122 void MapLayerTreeId(LayersId aLayersId
, base::ProcessId aOwningId
);
124 // Release compositor-thread resources referred to by |aID|.
126 // Must run on the content main thread.
127 void UnmapLayerTreeId(LayersId aLayersId
, base::ProcessId aOwningId
);
129 // Checks to see if aLayersId and aRequestingPID have been mapped by
131 bool IsLayerTreeIdMapped(LayersId aLayersId
, base::ProcessId aRequestingId
);
133 // Allocate an ID that can be used to refer to a layer tree and
134 // associated resources that live only on the compositor thread.
136 // Must run on the browser main thread.
137 LayersId
AllocateLayerTreeId();
139 // Allocate an ID that can be used as Namespace and
140 // Must run on the browser main thread.
141 uint32_t AllocateNamespace();
143 // Allocate a layers ID and connect it to a compositor. If the compositor is
144 // null, the connect operation will not be performed, but an ID will still be
145 // allocated. This must be called from the browser main thread.
147 // Note that a layer tree id is always allocated, even if this returns false.
148 bool AllocateAndConnectLayerTreeId(PCompositorBridgeChild
* aCompositorBridge
,
149 base::ProcessId aOtherPid
,
150 LayersId
* aOutLayersId
,
151 CompositorOptions
* aOutCompositorOptions
);
153 // Destroy and recreate all of the compositors
154 void ResetCompositors();
156 // Record the device reset in telemetry / annotate the crash report.
157 static void RecordDeviceReset(DeviceResetReason aReason
);
159 void OnProcessLaunchComplete(GPUProcessHost
* aHost
) override
;
160 void OnProcessUnexpectedShutdown(GPUProcessHost
* aHost
) override
;
161 void SimulateDeviceReset();
162 void DisableWebRender(wr::WebRenderError aError
, const nsCString
& aMsg
);
163 void NotifyWebRenderError(wr::WebRenderError aError
);
164 void OnInProcessDeviceReset(bool aTrackThreshold
);
165 void OnRemoteProcessDeviceReset(GPUProcessHost
* aHost
) override
;
166 void OnProcessDeclaredStable() override
;
167 void NotifyListenersOnCompositeDeviceReset();
169 // Notify the GPUProcessManager that a top-level PGPU protocol has been
170 // terminated. This may be called from any thread.
171 void NotifyRemoteActorDestroyed(const uint64_t& aProcessToken
);
173 void AddListener(GPUProcessListener
* aListener
);
174 void RemoveListener(GPUProcessListener
* aListener
);
176 // Send a message to the GPU process observer service to broadcast. Returns
177 // true if the message was sent, false if not.
178 bool NotifyGpuObservers(const char* aTopic
);
180 // Kills the GPU process. Used for tests and diagnostics
183 // Causes the GPU process to crash. Used for tests and diagnostics
186 // Returns -1 if there is no GPU process, or the platform pid for it.
187 base::ProcessId
GPUProcessPid();
189 // If a GPU process is present, create a MemoryReportingProcess object.
190 // Otherwise, return null.
191 RefPtr
<MemoryReportingProcess
> GetProcessMemoryReporter();
193 // Returns access to the PGPU protocol if a GPU process is present.
194 GPUChild
* GetGPUChild() { return mGPUChild
; }
196 // Returns whether or not a GPU process was ever launched.
197 bool AttemptedGPUProcess() const { return mTotalProcessAttempts
> 0; }
199 // Returns the process host
200 GPUProcessHost
* Process() { return mProcess
; }
203 * ** Test-only Method **
205 * Trigger GPU-process test metric instrumentation.
207 RefPtr
<PGPUChild::TestTriggerMetricsPromise
> TestTriggerMetrics();
210 // Called from our xpcom-shutdown observer.
211 void OnXPCOMShutdown();
212 void OnPreferenceChange(const char16_t
* aData
);
214 bool CreateContentCompositorManager(
215 base::ProcessId aOtherProcess
,
216 mozilla::ipc::Endpoint
<PCompositorManagerChild
>* aOutEndpoint
);
217 bool CreateContentImageBridge(
218 base::ProcessId aOtherProcess
,
219 mozilla::ipc::Endpoint
<PImageBridgeChild
>* aOutEndpoint
);
220 bool CreateContentVRManager(
221 base::ProcessId aOtherProcess
,
222 mozilla::ipc::Endpoint
<PVRManagerChild
>* aOutEndpoint
);
223 void CreateContentRemoteDecoderManager(
224 base::ProcessId aOtherProcess
,
225 mozilla::ipc::Endpoint
<PRemoteDecoderManagerChild
>* aOutEndPoint
);
227 // Called from RemoteCompositorSession. We track remote sessions so we can
228 // notify their owning widgets that the session must be restarted.
229 void RegisterRemoteProcessSession(RemoteCompositorSession
* aSession
);
230 void UnregisterRemoteProcessSession(RemoteCompositorSession
* aSession
);
232 // Called from InProcessCompositorSession. We track in process sessino so we
233 // can notify their owning widgets that the session must be restarted
234 void RegisterInProcessSession(InProcessCompositorSession
* aSession
);
235 void UnregisterInProcessSession(InProcessCompositorSession
* aSession
);
237 void DestroyRemoteCompositorSessions();
238 void DestroyInProcessCompositorSessions();
240 // Returns true if we crossed the threshold such that we should disable
242 bool OnDeviceReset(bool aTrackThreshold
);
244 // Returns true if WebRender was enabled and is now disabled.
245 bool DisableWebRenderConfig(wr::WebRenderError aError
, const nsCString
& aMsg
);
247 void FallbackToSoftware(const char* aMessage
);
252 // Permanently disable the GPU process and record a message why.
253 void DisableGPUProcess(const char* aMessage
);
255 // May permanently disable the GPU process and record a message why. May
256 // return false if the fallback process decided we should retry the GPU
257 // process, but only if aAllowRestart is also true.
258 bool MaybeDisableGPUProcess(const char* aMessage
, bool aAllowRestart
);
260 bool FallbackFromAcceleration(wr::WebRenderError aError
,
261 const nsCString
& aMsg
);
263 void ResetProcessStable();
265 // Returns true if the composting pocess is currently considered to be stable.
266 bool IsProcessStable(const TimeStamp
& aNow
);
268 // Shutdown the GPU process.
269 void CleanShutdown();
270 // Destroy the process and clean up resources.
271 // Setting aUnexpectedShutdown = true indicates that this is being called to
272 // clean up resources in response to an unexpected shutdown having been
274 void DestroyProcess(bool aUnexpectedShutdown
= false);
276 void HandleProcessLost();
277 // Reinitialize rendering following a GPU process loss.
278 void ReinitializeRendering();
280 void EnsureVsyncIOThread();
281 void ShutdownVsyncIOThread();
283 void EnsureProtocolsReady();
284 void EnsureCompositorManagerChild();
285 void EnsureImageBridgeChild();
286 void EnsureVRManager();
288 #if defined(MOZ_WIDGET_ANDROID)
289 already_AddRefed
<UiCompositorControllerChild
> CreateUiCompositorController(
290 nsBaseWidget
* aWidget
, const LayersId aId
);
291 #endif // defined(MOZ_WIDGET_ANDROID)
293 RefPtr
<CompositorSession
> CreateRemoteSession(
294 nsBaseWidget
* aWidget
, WebRenderLayerManager
* aLayerManager
,
295 const LayersId
& aRootLayerTreeId
, CSSToLayoutDeviceScale aScale
,
296 const CompositorOptions
& aOptions
, bool aUseExternalSurfaceSize
,
297 const gfx::IntSize
& aSurfaceSize
, uint64_t aInnerWindowId
);
299 DISALLOW_COPY_AND_ASSIGN(GPUProcessManager
);
301 class Observer final
: public nsIObserver
{
305 explicit Observer(GPUProcessManager
* aManager
);
308 virtual ~Observer() = default;
310 GPUProcessManager
* mManager
;
312 friend class Observer
;
315 bool mDecodeVideoOnGpuProcess
= true;
317 RefPtr
<Observer
> mObserver
;
318 mozilla::ipc::TaskFactory
<GPUProcessManager
> mTaskFactory
;
319 RefPtr
<VsyncIOThreadHolder
> mVsyncIOThread
;
320 uint32_t mNextNamespace
;
321 uint32_t mIdNamespace
;
322 uint32_t mResourceId
;
324 uint32_t mUnstableProcessAttempts
;
325 uint32_t mTotalProcessAttempts
;
326 TimeStamp mProcessAttemptLastTime
;
328 nsTArray
<RefPtr
<RemoteCompositorSession
>> mRemoteSessions
;
329 nsTArray
<RefPtr
<InProcessCompositorSession
>> mInProcessSessions
;
330 nsTArray
<GPUProcessListener
*> mListeners
;
332 uint32_t mDeviceResetCount
;
333 TimeStamp mDeviceResetLastTime
;
335 // Keeps track of whether not the application is in the foreground on android.
336 bool mAppInForeground
;
338 // Fields that are associated with the current GPU process.
339 GPUProcessHost
* mProcess
;
340 uint64_t mProcessToken
;
342 Maybe
<wr::WebRenderError
> mLastError
;
343 Maybe
<nsCString
> mLastErrorMsg
;
345 RefPtr
<VsyncBridgeChild
> mVsyncBridge
;
346 // Collects any pref changes that occur during process launch (after
347 // the initial map is passed in command-line arguments) to be sent
348 // when the process can receive IPC messages.
349 nsTArray
<mozilla::dom::Pref
> mQueuedPrefs
;
353 } // namespace mozilla
355 #endif // _include_mozilla_gfx_ipc_GPUProcessManager_h_