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

Quelle  TextureClientRecycleAllocator.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 "gfxPlatform.h"
#include "ImageContainer.h"
#include "mozilla/layers/BufferTexture.h"
#include "mozilla/layers/ISurfaceAllocator.h"
#include "mozilla/layers/TextureForwarder.h"
#include "TextureClientRecycleAllocator.h"

namespace mozilla {
namespace layers {

// Used to keep TextureClient's reference count stable as not to disrupt
// recycling.
class TextureClientHolder final {
  ~TextureClientHolder() = default;

 public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureClientHolder)

  explicit TextureClientHolder(TextureClient* aClient)
      : mTextureClient(aClient), mWillRecycle(true) {}

  TextureClient* GetTextureClient() { return mTextureClient; }

  bool WillRecycle() { return mWillRecycle; }

  void ClearWillRecycle() { mWillRecycle = false; }

  void ClearTextureClient() { mTextureClient = nullptr; }

 protected:
  RefPtr<TextureClient> mTextureClient;
  bool mWillRecycle;
};

class MOZ_RAII DefaultTextureClientAllocationHelper
    : public ITextureClientAllocationHelper {
 public:
  DefaultTextureClientAllocationHelper(
      TextureClientRecycleAllocator* aAllocator, gfx::SurfaceFormat aFormat,
      gfx::IntSize aSize, BackendSelector aSelector, TextureFlags aTextureFlags,
      TextureAllocationFlags aAllocationFlags)
      : ITextureClientAllocationHelper(aFormat, aSize, aSelector, aTextureFlags,
                                       aAllocationFlags),
        mAllocator(aAllocator) {}

  bool IsCompatible(TextureClient* aTextureClient) override {
    if (aTextureClient->GetFormat() != mFormat ||
        aTextureClient->GetSize() != mSize) {
      return false;
    }
    return true;
  }

  already_AddRefed<TextureClient> Allocate(
      KnowsCompositor* aKnowsCompositor) override {
    return mAllocator->Allocate(mFormat, mSize, mSelector, mTextureFlags,
                                mAllocationFlags);
  }

 protected:
  TextureClientRecycleAllocator* mAllocator;
};

YCbCrTextureClientAllocationHelper::YCbCrTextureClientAllocationHelper(
    const PlanarYCbCrData& aData, const gfx::IntSize& aYSize,
    const gfx::IntSize& aCbCrSize, TextureFlags aTextureFlags)
    : ITextureClientAllocationHelper(gfx::SurfaceFormat::YUV420, aYSize,
                                     BackendSelector::Content, aTextureFlags,
                                     ALLOC_DEFAULT),
      mData(aData),
      mYSize(aYSize),
      mCbCrSize(aCbCrSize) {}

YCbCrTextureClientAllocationHelper::YCbCrTextureClientAllocationHelper(
    const PlanarYCbCrData& aData, TextureFlags aTextureFlags)
    : YCbCrTextureClientAllocationHelper(aData, aData.YDataSize(),
                                         aData.CbCrDataSize(), aTextureFlags) {}

bool YCbCrTextureClientAllocationHelper::IsCompatible(
    TextureClient* aTextureClient) {
  MOZ_ASSERT(aTextureClient->GetFormat() == gfx::SurfaceFormat::YUV420);

  BufferTextureData* bufferData =
      aTextureClient->GetInternalData()->AsBufferTextureData();

  if (!bufferData ||
      !bufferData->GetPictureRect().IsEqualEdges(mData.mPictureRect) ||
      bufferData->GetYSize().isNothing() ||
      bufferData->GetYSize().ref() != mYSize ||
      bufferData->GetCbCrSize().isNothing() ||
      bufferData->GetCbCrSize().ref() != mCbCrSize ||
      bufferData->GetYStride().isNothing() ||
      bufferData->GetYStride().ref() != mData.mYStride ||
      bufferData->GetCbCrStride().isNothing() ||
      bufferData->GetCbCrStride().ref() != mData.mCbCrStride ||
      bufferData->GetYUVColorSpace().isNothing() ||
      bufferData->GetYUVColorSpace().ref() != mData.mYUVColorSpace ||
      bufferData->GetColorDepth().isNothing() ||
      bufferData->GetColorDepth().ref() != mData.mColorDepth ||
      bufferData->GetStereoMode().isNothing() ||
      bufferData->GetStereoMode().ref() != mData.mStereoMode ||
      bufferData->GetChromaSubsampling().isNothing() ||
      bufferData->GetChromaSubsampling().ref() != mData.mChromaSubsampling) {
    return false;
  }
  return true;
}

already_AddRefed<TextureClient> YCbCrTextureClientAllocationHelper::Allocate(
    KnowsCompositor* aKnowsCompositor) {
  return TextureClient::CreateForYCbCr(
      aKnowsCompositor, mData.mPictureRect, mYSize, mData.mYStride, mCbCrSize,
      mData.mCbCrStride, mData.mStereoMode, mData.mColorDepth,
      mData.mYUVColorSpace, mData.mColorRange, mData.mChromaSubsampling,
      mTextureFlags);
}

TextureClientRecycleAllocator::TextureClientRecycleAllocator(
    KnowsCompositor* aKnowsCompositor)
    : mKnowsCompositor(aKnowsCompositor),
      mMaxPooledSize(kMaxPooledSized),
      mLock("TextureClientRecycleAllocatorImp.mLock"),
      mIsDestroyed(false) {}

TextureClientRecycleAllocator::~TextureClientRecycleAllocator() {
  MutexAutoLock lock(mLock);
  while (!mPooledClients.empty()) {
    mPooledClients.pop();
  }
  MOZ_ASSERT(mInUseClients.empty());
}

void TextureClientRecycleAllocator::SetMaxPoolSize(uint32_t aMax) {
  mMaxPooledSize = aMax;
}

already_AddRefed<TextureClient> TextureClientRecycleAllocator::CreateOrRecycle(
    gfx::SurfaceFormat aFormat, gfx::IntSize aSize, BackendSelector aSelector,
    TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags) {
  MOZ_ASSERT(!(aTextureFlags & TextureFlags::RECYCLE));
  DefaultTextureClientAllocationHelper helper(this, aFormat, aSize, aSelector,
                                              aTextureFlags, aAllocFlags);
  return CreateOrRecycle(helper).unwrapOr(nullptr);
}

Result<already_AddRefed<TextureClient>, nsresult>
TextureClientRecycleAllocator::CreateOrRecycle(
    ITextureClientAllocationHelper& aHelper) {
  MOZ_ASSERT(aHelper.mTextureFlags & TextureFlags::RECYCLE);

  RefPtr<TextureClientHolder> textureHolder;

  {
    MutexAutoLock lock(mLock);
    if (mIsDestroyed || !mKnowsCompositor->GetTextureForwarder()) {
      return Err(NS_ERROR_NOT_AVAILABLE);
    }
    if (!mPooledClients.empty()) {
      textureHolder = mPooledClients.top();
      mPooledClients.pop();
      // If the texture's allocator is not open or a pooled TextureClient is
      // not compatible, release it.
      if (!textureHolder->GetTextureClient()->GetAllocator()->IPCOpen() ||
          !aHelper.IsCompatible(textureHolder->GetTextureClient())) {
        // Release TextureClient.
        RefPtr<Runnable> task =
            new TextureClientReleaseTask(textureHolder->GetTextureClient());
        textureHolder->ClearTextureClient();
        textureHolder = nullptr;
        mKnowsCompositor->GetTextureForwarder()->GetThread()->Dispatch(
            task.forget());
      } else {
        textureHolder->GetTextureClient()->RecycleTexture(
            aHelper.mTextureFlags);
      }
    }
  }

  if (!textureHolder) {
    // Allocate new TextureClient
    RefPtr<TextureClient> texture = aHelper.Allocate(mKnowsCompositor);
    if (!texture) {
      return Err(NS_ERROR_OUT_OF_MEMORY);
    }
    textureHolder = new TextureClientHolder(texture);
  }

  {
    MutexAutoLock lock(mLock);
    MOZ_ASSERT(mInUseClients.find(textureHolder->GetTextureClient()) ==
               mInUseClients.end());
    // Register TextureClient
    mInUseClients[textureHolder->GetTextureClient()] = textureHolder;
  }
  RefPtr<TextureClient> client(textureHolder->GetTextureClient());

  // Make sure the texture holds a reference to us, and ask it to call
  // RecycleTextureClient when its ref count drops to 1.
  client->SetRecycleAllocator(this);
  return client.forget();
}

already_AddRefed<TextureClient> TextureClientRecycleAllocator::Allocate(
    gfx::SurfaceFormat aFormat, gfx::IntSize aSize, BackendSelector aSelector,
    TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags) {
  return TextureClient::CreateForDrawing(mKnowsCompositor, aFormat, aSize,
                                         aSelector, aTextureFlags, aAllocFlags);
}

void TextureClientRecycleAllocator::ShrinkToMinimumSize() {
  MutexAutoLock lock(mLock);
  while (!mPooledClients.empty()) {
    mPooledClients.pop();
  }
  // We can not clear using TextureClients safely.
  // Just clear WillRecycle here.
  std::map<TextureClient*, RefPtr<TextureClientHolder> >::iterator it;
  for (it = mInUseClients.begin(); it != mInUseClients.end(); it++) {
    RefPtr<TextureClientHolder> holder = it->second;
    holder->ClearWillRecycle();
  }
}

void TextureClientRecycleAllocator::Destroy() {
  MutexAutoLock lock(mLock);
  while (!mPooledClients.empty()) {
    mPooledClients.pop();
  }
  mIsDestroyed = true;
}

void TextureClientRecycleAllocator::RecycleTextureClient(
    TextureClient* aClient) {
  // Clearing the recycle allocator drops a reference, so make sure we stay
  // alive for the duration of this function.
  RefPtr<TextureClientRecycleAllocator> kungFuDeathGrip(this);
  aClient->SetRecycleAllocator(nullptr);

  RefPtr<TextureClientHolder> textureHolder;
  {
    MutexAutoLock lock(mLock);
    if (mInUseClients.find(aClient) != mInUseClients.end()) {
      textureHolder =
          mInUseClients[aClient];  // Keep reference count of
                                   // TextureClientHolder within lock.
      if (textureHolder->WillRecycle() && !mIsDestroyed &&
          mPooledClients.size() < mMaxPooledSize) {
        mPooledClients.push(textureHolder);
      }
      mInUseClients.erase(aClient);
    }
  }
}

}  // namespace layers
}  // namespace mozilla

Messung V0.5
C=93 H=88 G=90

¤ Dauer der Verarbeitung: 0.14 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 und die Messung sind noch experimentell.