tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

GPUProcessManager.h (16104B)


      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/dom/ipc/IdType.h"
     13 #include "mozilla/gfx/GPUProcessHost.h"
     14 #include "mozilla/gfx/PGPUChild.h"
     15 #include "mozilla/gfx/Point.h"
     16 #include "mozilla/Hal.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 nsIWidget;
     24 enum class DeviceResetReason;
     25 
     26 namespace mozilla {
     27 class MemoryReportingProcess;
     28 class PRemoteMediaManagerChild;
     29 class RDDProcessManager;
     30 class RDDChild;
     31 namespace layers {
     32 class IAPZCTreeManager;
     33 class CompositorOptions;
     34 class CompositorSession;
     35 class CompositorUpdateObserver;
     36 class PCompositorBridgeChild;
     37 class PCompositorManagerChild;
     38 class PImageBridgeChild;
     39 class PVideoBridgeParent;
     40 class RemoteCompositorSession;
     41 class InProcessCompositorSession;
     42 class UiCompositorControllerChild;
     43 class WebRenderLayerManager;
     44 }  // namespace layers
     45 namespace widget {
     46 class CompositorWidget;
     47 }  // namespace widget
     48 namespace dom {
     49 class ContentParent;
     50 class BrowserParent;
     51 }  // namespace dom
     52 namespace ipc {
     53 class GeckoChildProcessHost;
     54 #ifdef MOZ_WMF_MEDIA_ENGINE
     55 class UtilityMediaServiceChild;
     56 #endif
     57 }  // namespace ipc
     58 namespace gfx {
     59 
     60 class GPUChild;
     61 class GPUProcessListener;
     62 class PVRManagerChild;
     63 class VsyncBridgeChild;
     64 class VsyncIOThreadHolder;
     65 
     66 // The GPUProcessManager is a singleton responsible for creating GPU-bound
     67 // objects that may live in another process. Currently, it provides access
     68 // to the compositor via CompositorBridgeParent.
     69 class GPUProcessManager final : public GPUProcessHost::Listener {
     70  friend class layers::RemoteCompositorSession;
     71  friend class layers::InProcessCompositorSession;
     72 
     73  typedef layers::CompositorOptions CompositorOptions;
     74  typedef layers::CompositorSession CompositorSession;
     75  typedef layers::CompositorUpdateObserver CompositorUpdateObserver;
     76  typedef layers::IAPZCTreeManager IAPZCTreeManager;
     77  typedef layers::WebRenderLayerManager WebRenderLayerManager;
     78  typedef layers::LayersId LayersId;
     79  typedef layers::PCompositorBridgeChild PCompositorBridgeChild;
     80  typedef layers::PCompositorManagerChild PCompositorManagerChild;
     81  typedef layers::PImageBridgeChild PImageBridgeChild;
     82  typedef layers::PVideoBridgeParent PVideoBridgeParent;
     83  typedef layers::RemoteCompositorSession RemoteCompositorSession;
     84  typedef layers::InProcessCompositorSession InProcessCompositorSession;
     85  typedef layers::UiCompositorControllerChild UiCompositorControllerChild;
     86 
     87 public:
     88  static void Initialize();
     89  static void Shutdown();
     90  static GPUProcessManager* Get();
     91 
     92  ~GPUProcessManager();
     93 
     94  // If not using a GPU process, launch a new GPU process asynchronously.
     95  nsresult LaunchGPUProcess();
     96  bool IsGPUProcessLaunching();
     97 
     98  // Ensure that GPU-bound methods can be used. If no GPU process is being
     99  // used, or one is launched and ready, this function returns immediately.
    100  // Otherwise it blocks until the GPU process has finished launching.
    101  // If the GPU process is enabled but has not yet been launched then this will
    102  // launch the process. If that is not desired then check that return value of
    103  // Process() is non-null before calling.
    104  //
    105  // Returns:
    106  // - NS_OK if compositing is ready, in either the GPU process or the parent
    107  // process, even if in shutdown.
    108  // - NS_ERROR_ILLEGAL_DURING_SHUTDOWN if compositing is not ready, and we are
    109  // in shutdown.
    110  // - NS_ERROR_ABORT if on Android and we are in the background. This is a
    111  // temporary error that we should recover from when in the foreground.
    112  nsresult EnsureGPUReady();
    113 
    114  bool IsGPUReady() const;
    115 
    116  already_AddRefed<CompositorSession> CreateTopLevelCompositor(
    117      nsIWidget* aWidget, WebRenderLayerManager* aLayerManager,
    118      CSSToLayoutDeviceScale aScale, const CompositorOptions& aOptions,
    119      bool aUseExternalSurfaceSize, const gfx::IntSize& aSurfaceSize,
    120      uint64_t aInnerWindowId, bool* aRetry);
    121 
    122  // It is asserted that IsGPUReady() is true for this method. If not on a path
    123  // which guarantees that, then the caller must call EnsureGPUReady() and check
    124  // its return code first.
    125  bool CreateContentBridges(
    126      mozilla::ipc::EndpointProcInfo aOtherProcess,
    127      mozilla::ipc::Endpoint<PCompositorManagerChild>* aOutCompositor,
    128      mozilla::ipc::Endpoint<PImageBridgeChild>* aOutImageBridge,
    129      mozilla::ipc::Endpoint<PVRManagerChild>* aOutVRBridge,
    130      mozilla::ipc::Endpoint<PRemoteMediaManagerChild>* aOutVideoManager,
    131      dom::ContentParentId aChildId, nsTArray<uint32_t>* aNamespaces);
    132 
    133  nsresult CreateRddVideoBridge(RDDProcessManager* aRDD, RDDChild* aChild);
    134 #ifdef MOZ_WMF_MEDIA_ENGINE
    135  nsresult CreateUtilityMFCDMVideoBridge(
    136      mozilla::ipc::UtilityMediaServiceChild* aChild,
    137      mozilla::ipc::EndpointProcInfo aOtherProcess);
    138 #endif
    139 
    140  // Release compositor-thread resources referred to by |aID|.
    141  //
    142  // Must run on the content main thread.
    143  void UnmapLayerTreeId(LayersId aLayersId, base::ProcessId aOwningId);
    144 
    145  // Checks to see if aLayersId and aRequestingPID have been mapped by
    146  // MapLayerTreeId
    147  bool IsLayerTreeIdMapped(LayersId aLayersId, base::ProcessId aRequestingId);
    148 
    149  // Allocate an ID that can be used to refer to a layer tree and
    150  // associated resources that live only on the compositor thread.
    151  //
    152  // Must run on the browser main thread.
    153  LayersId AllocateLayerTreeId();
    154 
    155  // Allocate an ID that can be used as Namespace and
    156  // Must run on the browser main thread.
    157  uint32_t AllocateNamespace();
    158 
    159  // Allocate a layers ID and connect it to a compositor. If the compositor is
    160  // null, the connect operation will not be performed, but an ID will still be
    161  // allocated. This must be called from the browser main thread.
    162  //
    163  // It also maps the layer tree and process together so that aOwningPID is
    164  // allowed to access aLayersId across process.
    165  //
    166  // Note that a layer tree id is always allocated, even if this returns false.
    167  bool AllocateAndConnectLayerTreeId(PCompositorBridgeChild* aCompositorBridge,
    168                                     base::ProcessId aOtherPid,
    169                                     LayersId* aOutLayersId,
    170                                     CompositorOptions* aOutCompositorOptions);
    171 
    172  // Destroy and recreate all of the compositors
    173  void ResetCompositors();
    174 
    175  // Record the device reset in telemetry / annotate the crash report.
    176  static void RecordDeviceReset(DeviceResetReason aReason);
    177 
    178  static void NotifyDeviceReset(DeviceResetReason aReason,
    179                                DeviceResetDetectPlace aPlace);
    180 
    181  void OnProcessLaunchComplete(GPUProcessHost* aHost) override;
    182  void OnProcessUnexpectedShutdown(GPUProcessHost* aHost) override;
    183  void SimulateDeviceReset();
    184  void DisableWebRender(wr::WebRenderError aError, const nsCString& aMsg);
    185  void NotifyWebRenderError(wr::WebRenderError aError);
    186  void OnInProcessDeviceReset(DeviceResetReason aReason,
    187                              DeviceResetDetectPlace aPlace);
    188  void OnRemoteProcessDeviceReset(
    189      GPUProcessHost* aHost, const DeviceResetReason& aReason,
    190      const DeviceResetDetectPlace& aPlace) override;
    191  void OnProcessDeclaredStable() override;
    192  void NotifyListenersOnCompositeDeviceReset();
    193 
    194  // Notify the GPUProcessManager that a top-level PGPU protocol has been
    195  // terminated. This may be called from any thread.
    196  void NotifyRemoteActorDestroyed(const uint64_t& aProcessToken);
    197 
    198  void AddListener(GPUProcessListener* aListener);
    199  void RemoveListener(GPUProcessListener* aListener);
    200 
    201  // Send a message to the GPU process observer service to broadcast. Returns
    202  // true if the message was sent, false if not.
    203  bool NotifyGpuObservers(const char* aTopic);
    204 
    205  // Kills the GPU process. Used in normal operation to recover from an error,
    206  // as well as for tests and diagnostics.
    207  void KillProcess(bool aGenerateMinidump = false);
    208 
    209  // Invoked when we know we will shutdown (but before shutdown begins), to
    210  // avoid races with other shutdown observers.
    211  void StopBatteryObserving();
    212 
    213  // Causes the GPU process to crash. Used for tests and diagnostics
    214  void CrashProcess();
    215 
    216  // Returns -1 if there is no GPU process, or the platform pid for it.
    217  base::ProcessId GPUProcessPid();
    218 
    219  // Returns Invalid() if there is no GPU process, or the proc info for it.
    220  mozilla::ipc::EndpointProcInfo GPUEndpointProcInfo();
    221 
    222  // If a GPU process is present, create a MemoryReportingProcess object.
    223  // Otherwise, return null.
    224  RefPtr<MemoryReportingProcess> GetProcessMemoryReporter();
    225 
    226  // Returns access to the PGPU protocol if a GPU process is present.
    227  GPUChild* GetGPUChild() { return mGPUChild; }
    228 
    229  // Returns whether or not a GPU process was ever launched.
    230  bool AttemptedGPUProcess() const { return mTotalProcessAttempts > 0; }
    231 
    232  // Returns the process host
    233  GPUProcessHost* Process() { return mProcess; }
    234 
    235  // Sets the value of mAppInForeground, and (on Windows) adjusts the priority
    236  // of the GPU process accordingly.
    237  void SetAppInForeground(bool aInForeground);
    238 
    239  /*
    240   * ** Test-only Method **
    241   *
    242   * Trigger GPU-process test metric instrumentation.
    243   */
    244  RefPtr<PGPUChild::TestTriggerMetricsPromise> TestTriggerMetrics();
    245 
    246 private:
    247  void OnPreferenceChange(const char16_t* aData);
    248  void ScreenInformationChanged();
    249 
    250  bool CreateContentCompositorManager(
    251      mozilla::ipc::EndpointProcInfo aOtherProcess,
    252      dom::ContentParentId aChildId, uint32_t aNamespace,
    253      mozilla::ipc::Endpoint<PCompositorManagerChild>* aOutEndpoint);
    254  bool CreateContentImageBridge(
    255      mozilla::ipc::EndpointProcInfo aOtherProcess,
    256      dom::ContentParentId aChildId,
    257      mozilla::ipc::Endpoint<PImageBridgeChild>* aOutEndpoint);
    258  bool CreateContentVRManager(
    259      mozilla::ipc::EndpointProcInfo aOtherProcess,
    260      dom::ContentParentId aChildId,
    261      mozilla::ipc::Endpoint<PVRManagerChild>* aOutEndpoint);
    262  void CreateContentRemoteMediaManager(
    263      mozilla::ipc::EndpointProcInfo aOtherProcess,
    264      dom::ContentParentId aChildId,
    265      mozilla::ipc::Endpoint<PRemoteMediaManagerChild>* aOutEndPoint);
    266 
    267  nsresult EnsureVideoBridge(
    268      layers::VideoBridgeSource aSource,
    269      mozilla::ipc::EndpointProcInfo aOtherProcess,
    270      mozilla::ipc::Endpoint<layers::PVideoBridgeChild>* aOutChildPipe);
    271 
    272  // Called from RemoteCompositorSession. We track remote sessions so we can
    273  // notify their owning widgets that the session must be restarted.
    274  void RegisterRemoteProcessSession(RemoteCompositorSession* aSession);
    275  void UnregisterRemoteProcessSession(RemoteCompositorSession* aSession);
    276 
    277  // Called from InProcessCompositorSession. We track in process sessino so we
    278  // can notify their owning widgets that the session must be restarted
    279  void RegisterInProcessSession(InProcessCompositorSession* aSession);
    280  void UnregisterInProcessSession(InProcessCompositorSession* aSession);
    281 
    282  void DestroyRemoteCompositorSessions();
    283  void DestroyInProcessCompositorSessions();
    284 
    285  // Returns true if we crossed the threshold such that we should disable
    286  // acceleration.
    287  bool OnDeviceReset(bool aTrackThreshold);
    288 
    289  void DisableWebRenderConfig(wr::WebRenderError aError, const nsCString& aMsg);
    290 
    291  void FallbackToSoftware(const char* aMessage);
    292 
    293 private:
    294  GPUProcessManager();
    295 
    296  // Permanently disable the GPU process and record a message why.
    297  void DisableGPUProcess(const char* aMessage);
    298 
    299  // May permanently disable the GPU process and record a message why. May
    300  // return false if the fallback process decided we should retry the GPU
    301  // process, but only if aAllowRestart is also true.
    302  bool MaybeDisableGPUProcess(const char* aMessage, bool aAllowRestart);
    303 
    304  bool FallbackFromAcceleration(wr::WebRenderError aError,
    305                                const nsCString& aMsg);
    306 
    307  // Crashes the parent process if we are disabling the GPU process and we
    308  // ever once had a stable GPU process. This is to avoid fallback into the
    309  // parent when we know the configuration allows for the GPU process.
    310  void MaybeCrashIfGpuProcessOnceStable();
    311 
    312  void ResetProcessStable();
    313 
    314  // Returns true if the composting pocess is currently considered to be stable.
    315  bool IsProcessStable(const TimeStamp& aNow);
    316 
    317  // Shutdown the GPU process.
    318  void ShutdownInternal();
    319  // Destroy the process and clean up resources.
    320  // Setting aUnexpectedShutdown = true indicates that this is being called to
    321  // clean up resources in response to an unexpected shutdown having been
    322  // detected.
    323  void DestroyProcess(bool aUnexpectedShutdown = false);
    324 
    325  void HandleProcessLost();
    326  // Reinitialize rendering following a GPU process loss.
    327  void ReinitializeRendering();
    328 
    329  void EnsureVsyncIOThread();
    330  void ShutdownVsyncIOThread();
    331 
    332  bool EnsureProtocolsReady();
    333  bool EnsureCompositorManagerChild();
    334  bool EnsureImageBridgeChild();
    335  bool EnsureVRManager();
    336 
    337 #if defined(XP_WIN)
    338  void SetProcessIsForeground();
    339 #endif
    340 
    341 #if defined(MOZ_WIDGET_ANDROID)
    342  RefPtr<UiCompositorControllerChild> CreateUiCompositorController(
    343      nsIWidget* aWidget, const LayersId aId);
    344 #endif  // defined(MOZ_WIDGET_ANDROID)
    345 
    346  RefPtr<CompositorSession> CreateRemoteSession(
    347      nsIWidget* aWidget, WebRenderLayerManager* aLayerManager,
    348      const LayersId& aRootLayerTreeId, CSSToLayoutDeviceScale aScale,
    349      const CompositorOptions& aOptions, bool aUseExternalSurfaceSize,
    350      const gfx::IntSize& aSurfaceSize, uint64_t aInnerWindowId);
    351 
    352  DISALLOW_COPY_AND_ASSIGN(GPUProcessManager);
    353 
    354  void NotifyObserve(const char* aTopic, const char16_t* aData);
    355  void NotifyBatteryInfo(const hal::BatteryInformation& aBatteryInfo);
    356 
    357  class Observer final : public nsIObserver {
    358   public:
    359    NS_DECL_ISUPPORTS
    360    NS_DECL_NSIOBSERVER
    361 
    362    Observer();
    363    void Shutdown();
    364 
    365   protected:
    366    virtual ~Observer() = default;
    367  };
    368  friend class Observer;
    369 
    370  class BatteryObserver final : public hal::BatteryObserver {
    371   public:
    372    NS_INLINE_DECL_REFCOUNTING(BatteryObserver)
    373 
    374    BatteryObserver();
    375    void Notify(const hal::BatteryInformation& aBatteryInfo) override;
    376    void Shutdown();
    377 
    378   protected:
    379    ~BatteryObserver() override = default;
    380  };
    381 
    382 private:
    383  bool mDecodeVideoOnGpuProcess = true;
    384 
    385  RefPtr<Observer> mObserver;
    386  RefPtr<BatteryObserver> mBatteryObserver;
    387  mozilla::ipc::TaskFactory<GPUProcessManager> mTaskFactory;
    388  RefPtr<VsyncIOThreadHolder> mVsyncIOThread;
    389  uint32_t mNextNamespace;
    390  uint32_t mIdNamespace;
    391  uint32_t mResourceId;
    392 
    393  uint32_t mUnstableProcessAttempts;
    394  uint32_t mTotalProcessAttempts;
    395  uint32_t mLaunchProcessAttempts = 0;
    396  TimeStamp mProcessAttemptLastTime;
    397 
    398  nsTArray<RefPtr<RemoteCompositorSession>> mRemoteSessions;
    399  nsTArray<RefPtr<InProcessCompositorSession>> mInProcessSessions;
    400  nsTArray<RefPtr<GPUProcessListener>> mListeners;
    401 
    402  uint32_t mDeviceResetCount;
    403  TimeStamp mDeviceResetLastTime;
    404 
    405  // Keeps track of whether not the application is in the foreground on android.
    406  bool mAppInForeground;
    407 
    408  // Fields that are associated with the current GPU process.
    409  GPUProcessHost* mProcess;
    410  uint64_t mProcessToken;
    411  bool mProcessStable = false;
    412  bool mProcessStableOnce = false;
    413  Maybe<wr::WebRenderError> mLastError;
    414  Maybe<nsCString> mLastErrorMsg;
    415  GPUChild* mGPUChild;
    416  RefPtr<VsyncBridgeChild> mVsyncBridge;
    417  // Collects any pref changes that occur during process launch (after
    418  // the initial map is passed in command-line arguments) to be sent
    419  // when the process can receive IPC messages.
    420  nsTArray<mozilla::dom::Pref> mQueuedPrefs;
    421 };
    422 
    423 }  // namespace gfx
    424 }  // namespace mozilla
    425 
    426 #endif  // _include_mozilla_gfx_ipc_GPUProcessManager_h_