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