Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/gfx/layers/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 7 kB image not shown  

Quelle  SourceSurfaceSharedData.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "SourceSurfaceSharedData.h"

#include "mozilla/Likely.h"
#include "mozilla/StaticPrefs_image.h"
#include "mozilla/Types.h"  // for decltype
#include "mozilla/layers/SharedSurfacesChild.h"
#include "mozilla/layers/SharedSurfacesParent.h"
#include "nsDebug.h"  // for NS_ABORT_OOM

#include "base/process_util.h"

#ifdef DEBUG
/**
 * If defined, this makes SourceSurfaceSharedData::Finalize memory protect the
 * underlying shared buffer in the producing process (the content or UI
 * process). Given flushing the page table is expensive, and its utility is
 * predominantly diagnostic (in case of overrun), turn it off by default.
 */

#  define SHARED_SURFACE_PROTECT_FINALIZED
#endif

using namespace mozilla::layers;

namespace mozilla {
namespace gfx {

void SourceSurfaceSharedDataWrapper::Init(const IntSize& aSize, int32_t aStride,
                                          SurfaceFormat aFormat,
                                          SharedMemory::Handle aHandle,
                                          base::ProcessId aCreatorPid) {
  MOZ_ASSERT(!mBuf);
  mSize = aSize;
  mStride = aStride;
  mFormat = aFormat;
  mCreatorPid = aCreatorPid;

  size_t len = GetAlignedDataLength();
  mBuf = MakeAndAddRef<SharedMemory>();
  if (!mBuf->SetHandle(std::move(aHandle), ipc::SharedMemory::RightsReadOnly)) {
    MOZ_CRASH("Invalid shared memory handle!");
  }

  bool mapped = EnsureMapped(len);
  if ((sizeof(uintptr_t) <= 4 ||
       StaticPrefs::image_mem_shared_unmap_force_enabled_AtStartup()) &&
      len / 1024 >
          StaticPrefs::image_mem_shared_unmap_min_threshold_kb_AtStartup()) {
    mHandleLock.emplace("SourceSurfaceSharedDataWrapper::mHandleLock");

    if (mapped) {
      // Tracking at the initial mapping, and not just after the first use of
      // the surface means we might get unmapped again before the next frame
      // gets rendered if a low virtual memory condition persists.
      SharedSurfacesParent::AddTracking(this);
    }
  } else if (!mapped) {
    // We don't support unmapping for this surface, and we failed to map it.
    NS_ABORT_OOM(len);
  } else {
    mBuf->CloseHandle();
  }
}

void SourceSurfaceSharedDataWrapper::Init(SourceSurfaceSharedData* aSurface) {
  MOZ_ASSERT(!mBuf);
  MOZ_ASSERT(aSurface);
  mSize = aSurface->mSize;
  mStride = aSurface->mStride;
  mFormat = aSurface->mFormat;
  mCreatorPid = base::GetCurrentProcId();
  mBuf = aSurface->mBuf;
}

bool SourceSurfaceSharedDataWrapper::EnsureMapped(size_t aLength) {
  MOZ_ASSERT(!GetData());

  while (!mBuf->Map(aLength)) {
    nsTArray<RefPtr<SourceSurfaceSharedDataWrapper>> expired;
    if (!SharedSurfacesParent::AgeOneGeneration(expired)) {
      return false;
    }
    MOZ_ASSERT(!expired.Contains(this));
    SharedSurfacesParent::ExpireMap(expired);
  }

  return true;
}

bool SourceSurfaceSharedDataWrapper::Map(MapType aMapType,
                                         MappedSurface* aMappedSurface) {
  uint8_t* dataPtr;

  if (aMapType != MapType::READ) {
    // The data may be write-protected
    return false;
  }

  if (mHandleLock) {
    MutexAutoLock lock(*mHandleLock);
    dataPtr = GetData();
    if (mMapCount == 0) {
      if (mConsumers > 0) {
        SharedSurfacesParent::RemoveTracking(this);
      }
      if (!dataPtr) {
        size_t len = GetAlignedDataLength();
        if (!EnsureMapped(len)) {
          NS_ABORT_OOM(len);
        }
        dataPtr = GetData();
      }
    }
    ++mMapCount;
  } else {
    dataPtr = GetData();
    ++mMapCount;
  }

  MOZ_ASSERT(dataPtr);
  aMappedSurface->mData = dataPtr;
  aMappedSurface->mStride = mStride;
  return true;
}

void SourceSurfaceSharedDataWrapper::Unmap() {
  if (mHandleLock) {
    MutexAutoLock lock(*mHandleLock);
    if (--mMapCount == 0 && mConsumers > 0) {
      SharedSurfacesParent::AddTracking(this);
    }
  } else {
    --mMapCount;
  }
  MOZ_ASSERT(mMapCount >= 0);
}

void SourceSurfaceSharedDataWrapper::ExpireMap() {
  MutexAutoLock lock(*mHandleLock);
  if (mMapCount == 0) {
    mBuf->Unmap();
  }
}

bool SourceSurfaceSharedData::Init(const IntSize& aSize, int32_t aStride,
                                   SurfaceFormat aFormat,
                                   bool aShare /* = true */) {
  mSize = aSize;
  mStride = aStride;
  mFormat = aFormat;

  size_t len = GetAlignedDataLength();
  mBuf = new SharedMemory();
  if (NS_WARN_IF(!mBuf->Create(len)) || NS_WARN_IF(!mBuf->Map(len))) {
    mBuf = nullptr;
    return false;
  }

  if (aShare) {
    layers::SharedSurfacesChild::Share(this);
  }

  return true;
}

void SourceSurfaceSharedData::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
                                                  SizeOfInfo& aInfo) const {
  MutexAutoLock lock(mMutex);
  aInfo.AddType(SurfaceType::DATA_SHARED);
  if (mBuf) {
    aInfo.mNonHeapBytes = GetAlignedDataLength();
  }
  if (!mClosed) {
    aInfo.mExternalHandles = 1;
  }
  Maybe<wr::ExternalImageId> extId = SharedSurfacesChild::GetExternalId(this);
  if (extId) {
    aInfo.mExternalId = wr::AsUint64(extId.ref());
  }
}

uint8_t* SourceSurfaceSharedData::GetDataInternal() const {
  mMutex.AssertCurrentThreadOwns();

  // If we have an old buffer lingering, it is because we get reallocated to
  // get a new handle to share, but there were still active mappings.
  if (MOZ_UNLIKELY(mOldBuf)) {
    MOZ_ASSERT(mMapCount > 0);
    MOZ_ASSERT(mFinalized);
    return static_cast<uint8_t*>(mOldBuf->Memory());
  }
  return static_cast<uint8_t*>(mBuf->Memory());
}

nsresult SourceSurfaceSharedData::CloneHandle(SharedMemory::Handle& aHandle) {
  MutexAutoLock lock(mMutex);
  MOZ_ASSERT(mHandleCount > 0);

  if (mClosed) {
    return NS_ERROR_NOT_AVAILABLE;
  }

  aHandle = mBuf->CloneHandle();
  if (MOZ_UNLIKELY(!aHandle)) {
    return NS_ERROR_FAILURE;
  }

  return NS_OK;
}

void SourceSurfaceSharedData::CloseHandleInternal() {
  mMutex.AssertCurrentThreadOwns();

  if (mClosed) {
    MOZ_ASSERT(mHandleCount == 0);
    MOZ_ASSERT(mShared);
    return;
  }

  if (mShared) {
    mBuf->CloseHandle();
    mClosed = true;
  }
}

bool SourceSurfaceSharedData::ReallocHandle() {
  MutexAutoLock lock(mMutex);
  MOZ_ASSERT(mHandleCount > 0);
  MOZ_ASSERT(mClosed);

  if (NS_WARN_IF(!mFinalized)) {
    // We haven't finished populating the surface data yet, which means we are
    // out of luck, as we have no means of synchronizing with the producer to
    // write new data to a new buffer. This should be fairly rare, caused by a
    // crash in the GPU process, while we were decoding an image.
    return false;
  }

  size_t len = GetAlignedDataLength();
  RefPtr<SharedMemory> buf = new SharedMemory();
  if (NS_WARN_IF(!buf->Create(len)) || NS_WARN_IF(!buf->Map(len))) {
    return false;
  }

  size_t copyLen = GetDataLength();
  memcpy(buf->Memory(), mBuf->Memory(), copyLen);
#ifdef SHARED_SURFACE_PROTECT_FINALIZED
  buf->Protect(static_cast<char*>(buf->Memory()), len, RightsRead);
#endif

  if (mMapCount > 0 && !mOldBuf) {
    mOldBuf = std::move(mBuf);
  }
  mBuf = std::move(buf);
  mClosed = false;
  mShared = false;
  return true;
}

void SourceSurfaceSharedData::Finalize() {
  MutexAutoLock lock(mMutex);
  MOZ_ASSERT(!mFinalized);

#ifdef SHARED_SURFACE_PROTECT_FINALIZED
  size_t len = GetAlignedDataLength();
  mBuf->Protect(static_cast<char*>(mBuf->Memory()), len, RightsRead);
#endif

  mFinalized = true;
}

}  // namespace gfx
}  // namespace mozilla

98%


¤ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

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 ist noch experimentell.