Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/gfx/layers/ipc/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 9 kB image not shown  

Quelle  CompositorManagerChild.cpp

  Sprache: C
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "mozilla/layers/CompositorManagerChild.h"

#include "mozilla/StaticPrefs_layers.h"
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/layers/CompositorManagerParent.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/gfx/CanvasShutdownManager.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/dom/ContentChild.h"  // for ContentChild
#include "mozilla/dom/BrowserChild.h"  // for BrowserChild
#include "mozilla/ipc/Endpoint.h"
#include "VsyncSource.h"

namespace mozilla {
namespace layers {

using gfx::GPUProcessManager;

StaticRefPtr<CompositorManagerChild> CompositorManagerChild::sInstance;

static StaticMutex sCompositorProcInfoMutex;
static ipc::EndpointProcInfo sCompositorProcInfo
    MOZ_GUARDED_BY(sCompositorProcInfoMutex);

static void SetCompositorProcInfo(ipc::EndpointProcInfo aInfo) {
  StaticMutexAutoLock lock(sCompositorProcInfoMutex);
  sCompositorProcInfo = aInfo;
}

/* static */
ipc::EndpointProcInfo CompositorManagerChild::GetCompositorProcInfo() {
  StaticMutexAutoLock lock(sCompositorProcInfoMutex);
  return sCompositorProcInfo;
}

/* static */
bool CompositorManagerChild::IsInitialized(uint64_t aProcessToken) {
  MOZ_ASSERT(NS_IsMainThread());
  return sInstance && sInstance->CanSend() &&
         sInstance->mProcessToken == aProcessToken;
}

/* static */
void CompositorManagerChild::InitSameProcess(uint32_t aNamespace,
                                             uint64_t aProcessToken) {
  MOZ_ASSERT(NS_IsMainThread());
  if (NS_WARN_IF(IsInitialized(aProcessToken))) {
    MOZ_ASSERT_UNREACHABLE("Already initialized same process");
    return;
  }

  RefPtr<CompositorManagerParent> parent =
      CompositorManagerParent::CreateSameProcess(aNamespace);
  RefPtr<CompositorManagerChild> child = new CompositorManagerChild(
      aProcessToken, aNamespace, /* aSameProcess */ true);
  child->SetOtherEndpointProcInfo(ipc::EndpointProcInfo::Current());
  if (NS_WARN_IF(!child->Open(parent, CompositorThread(), ipc::ChildSide))) {
    MOZ_DIAGNOSTIC_CRASH("Failed to open same process protocol");
    return;
  }
  child->mCanSend = true;
  child->SetReplyTimeout();

  parent->BindComplete(/* aIsRoot */ true);
  sInstance = std::move(child);
  SetCompositorProcInfo(sInstance->OtherEndpointProcInfo());
}

/* static */
bool CompositorManagerChild::Init(Endpoint<PCompositorManagerChild>&& aEndpoint,
                                  uint32_t aNamespace,
                                  uint64_t aProcessToken /* = 0 */) {
  MOZ_ASSERT(NS_IsMainThread());
  if (sInstance) {
    MOZ_ASSERT(sInstance->mNamespace != aNamespace);
  }

  RefPtr<CompositorManagerChild> child =
      new CompositorManagerChild(aProcessToken, aNamespace,
                                 /* aSameProcess */ false);
  if (NS_WARN_IF(!aEndpoint.Bind(child))) {
    return false;
  }
  child->mCanSend = true;
  child->SetReplyTimeout();

  sInstance = std::move(child);
  SetCompositorProcInfo(sInstance->OtherEndpointProcInfo());

  // If there are any canvases waiting on the recreation of the GPUProcess or
  // CompositorManagerChild, then we need to notify them so that they can
  // restore their contexts.
  gfx::CanvasShutdownManager::OnCompositorManagerRestored();
  return true;
}

/* static */
void CompositorManagerChild::Shutdown() {
  MOZ_ASSERT(NS_IsMainThread());
  CompositorBridgeChild::ShutDown();

  if (!sInstance) {
    return;
  }

  sInstance->Close();
  sInstance = nullptr;
  SetCompositorProcInfo(ipc::EndpointProcInfo::Invalid());
}

/* static */
void CompositorManagerChild::OnGPUProcessLost(uint64_t aProcessToken) {
  MOZ_ASSERT(NS_IsMainThread());

  // Since GPUChild and CompositorManagerChild will race on ActorDestroy, we
  // cannot know if the CompositorManagerChild is about to be released but has
  // yet to be. As such, we want to pre-emptively set mCanSend to false.
  if (sInstance && sInstance->mProcessToken == aProcessToken) {
    sInstance->mCanSend = false;
    SetCompositorProcInfo(ipc::EndpointProcInfo::Invalid());
  }
}

/* static */
bool CompositorManagerChild::CreateContentCompositorBridge(
    uint32_t aNamespace) {
  MOZ_ASSERT(NS_IsMainThread());
  if (NS_WARN_IF(!sInstance || !sInstance->CanSend())) {
    return false;
  }

  CompositorBridgeOptions options = ContentCompositorOptions();

  RefPtr bridge = MakeRefPtr<CompositorBridgeChild>(sInstance);
  if (NS_WARN_IF(!sInstance->SendPCompositorBridgeConstructor(bridge, options,
                                                              aNamespace))) {
    return false;
  }

  bridge->InitForContent(aNamespace);
  return true;
}

/* static */
already_AddRefed<CompositorBridgeChild>
CompositorManagerChild::CreateWidgetCompositorBridge(
    uint64_t aProcessToken, uint32_t aNamespace, CSSToLayoutDeviceScale aScale,
    const CompositorOptions& aOptions, bool aUseExternalSurfaceSize,
    const gfx::IntSize& aSurfaceSize, uint64_t aInnerWindowId) {
  MOZ_ASSERT(XRE_IsParentProcess());
  MOZ_ASSERT(NS_IsMainThread());
  if (NS_WARN_IF(!sInstance || !sInstance->CanSend())) {
    return nullptr;
  }

  TimeDuration vsyncRate =
      gfxPlatform::GetPlatform()->GetGlobalVsyncDispatcher()->GetVsyncRate();

  CompositorBridgeOptions options = WidgetCompositorOptions(
      aScale, vsyncRate, aOptions, aUseExternalSurfaceSize, aSurfaceSize,
      aInnerWindowId);

  RefPtr bridge = MakeRefPtr<CompositorBridgeChild>(sInstance);
  if (NS_WARN_IF(!sInstance->SendPCompositorBridgeConstructor(bridge, options,
                                                              aNamespace))) {
    return nullptr;
  }

  bridge->InitForWidget(aProcessToken, aNamespace);
  return bridge.forget();
}

/* static */
already_AddRefed<CompositorBridgeChild>
CompositorManagerChild::CreateSameProcessWidgetCompositorBridge(
    uint32_t aNamespace) {
  MOZ_ASSERT(XRE_IsParentProcess());
  MOZ_ASSERT(NS_IsMainThread());
  if (NS_WARN_IF(!sInstance || !sInstance->CanSend())) {
    return nullptr;
  }

  CompositorBridgeOptions options = SameProcessWidgetCompositorOptions();

  RefPtr bridge = MakeRefPtr<CompositorBridgeChild>(sInstance);
  if (NS_WARN_IF(!sInstance->SendPCompositorBridgeConstructor(bridge, options,
                                                              aNamespace))) {
    return nullptr;
  }

  bridge->InitForWidget(1, aNamespace);
  return bridge.forget();
}

CompositorManagerChild::CompositorManagerChild(uint64_t aProcessToken,
                                               uint32_t aNamespace,
                                               bool aSameProcess)
    : mProcessToken(aProcessToken),
      mNamespace(aNamespace),
      mResourceId(0),
      mCanSend(false),
      mSameProcess(aSameProcess),
      mFwdTransactionCounter(this) {}

void CompositorManagerChild::ActorDestroy(ActorDestroyReason aReason) {
  mCanSend = false;
  if (sInstance == this) {
    sInstance = nullptr;
  }
}

void CompositorManagerChild::HandleFatalError(const char* aMsg) {
  dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aMsg, OtherChildID());
}

void CompositorManagerChild::ProcessingError(Result aCode,
                                             const char* aReason) {
  if (aCode != MsgDropped) {
    gfxDevCrash(gfx::LogReason::ProcessingError)
        << "Processing error in CompositorBridgeChild: " << int(aCode);
  }
}

void CompositorManagerChild::SetReplyTimeout() {
#ifndef DEBUG
  // Add a timeout for release builds to kill GPU process when it hangs.
  if (XRE_IsParentProcess() && GPUProcessManager::Get()->GetGPUChild()) {
    int32_t timeout =
        StaticPrefs::layers_gpu_process_ipc_reply_timeout_ms_AtStartup();
    SetReplyTimeoutMs(timeout);
  }
#endif
}

bool CompositorManagerChild::ShouldContinueFromReplyTimeout() {
  MOZ_ASSERT_IF(mSyncIPCStartTimeStamp.isSome(), XRE_IsParentProcess());

  if (XRE_IsParentProcess()) {
#ifndef DEBUG
    // Extend sync IPC reply timeout
    if (mSyncIPCStartTimeStamp.isSome()) {
      const int32_t maxDurationMs = StaticPrefs::
          layers_gpu_process_extend_ipc_reply_timeout_ms_AtStartup();
      const auto now = TimeStamp::Now();
      const auto durationMs = static_cast<int32_t>(
          (now - mSyncIPCStartTimeStamp.ref()).ToMilliseconds());

      if (durationMs < maxDurationMs) {
        return true;
      }
    }
#endif
    gfxCriticalNote << "Killing GPU process due to IPC reply timeout";
    MOZ_DIAGNOSTIC_ASSERT(GPUProcessManager::Get()->GetGPUChild());
    GPUProcessManager::Get()->KillProcess(/* aGenerateMinidump */ true);
  }
  return false;
}

mozilla::ipc::IPCResult CompositorManagerChild::RecvNotifyWebRenderError(
    const WebRenderError&& aError) {
  MOZ_ASSERT(XRE_IsParentProcess());
  MOZ_ASSERT(NS_IsMainThread());
  GPUProcessManager::Get()->NotifyWebRenderError(aError);
  return IPC_OK();
}

void CompositorManagerChild::SetSyncIPCStartTimeStamp() {
  MOZ_ASSERT(mSyncIPCStartTimeStamp.isNothing());

  mSyncIPCStartTimeStamp = Some(TimeStamp::Now());
}

void CompositorManagerChild::ClearSyncIPCStartTimeStamp() {
  mSyncIPCStartTimeStamp = Nothing();
}

}  // namespace layers
}  // namespace mozilla

Messung V0.5 in Prozent
C=92 H=98 G=94

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.