Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  TextureHost.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 "TextureHost.h"

#include "CompositableHost.h"  // for CompositableHost
#include "mozilla/gfx/2D.h"    // for DataSourceSurface, Factory
#include "mozilla/gfx/CanvasManagerParent.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/ipc/Shmem.h"  // for Shmem
#include "mozilla/layers/AsyncImagePipelineManager.h"
#include "mozilla/layers/BufferTexture.h"
#include "mozilla/layers/CompositableTransactionParent.h"  // for CompositableParentManager
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/Compositor.h"         // for Compositor
#include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
#include "mozilla/layers/ImageBridgeParent.h"  // for ImageBridgeParent
#include "mozilla/layers/LayersSurfaces.h"     // for SurfaceDescriptor, etc
#include "mozilla/layers/RemoteTextureMap.h"
#include "mozilla/layers/TextureHostOGL.h"  // for TextureHostOGL
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/TextureClient.h"
#include "mozilla/layers/GPUVideoTextureHost.h"
#include "mozilla/layers/VideoBridgeParent.h"
#include "mozilla/layers/WebRenderTextureHost.h"
#include "mozilla/StaticPrefs_layers.h"
#include "mozilla/StaticPrefs_gfx.h"
#include "mozilla/webrender/RenderBufferTextureHost.h"
#include "mozilla/webrender/RenderExternalTextureHost.h"
#include "mozilla/webrender/RenderThread.h"
#include "mozilla/webrender/WebRenderAPI.h"
#include "nsAString.h"
#include "mozilla/RefPtr.h"   // for nsRefPtr
#include "nsPrintfCString.h"  // for nsPrintfCString
#include "mozilla/layers/PTextureParent.h"
#include <limits>
#include "../opengl/CompositorOGL.h"

#include "gfxUtils.h"

#ifdef XP_MACOSX
#  include "../opengl/MacIOSurfaceTextureHostOGL.h"
#endif

#ifdef XP_WIN
#  include "../d3d11/CompositorD3D11.h"
#  include "mozilla/layers/TextureD3D11.h"
#  ifdef MOZ_WMF_MEDIA_ENGINE
#    include "mozilla/layers/DcompSurfaceImage.h"
#  endif
#endif

#if 0
#  define RECYCLE_LOG(...) printf_stderr(__VA_ARGS__)
#else
#  define RECYCLE_LOG(...) \
    do {                   \
    } while (0)
#endif

namespace mozilla {
namespace layers {

/**
 * TextureParent is the host-side IPDL glue between TextureClient and
 * TextureHost. It is an IPDL actor just like LayerParent, CompositableParent,
 * etc.
 */

class TextureParent final : public PTextureParent {
 public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureParent, final)

  TextureParent(HostIPCAllocator* aAllocator,
                const dom::ContentParentId& aContentId, uint64_t aSerial,
                const wr::MaybeExternalImageId& aExternalImageId);

  bool Init(const SurfaceDescriptor& aSharedData,
            ReadLockDescriptor&& aReadLock, const LayersBackend& aLayersBackend,
            const TextureFlags& aFlags);

  void NotifyNotUsed(uint64_t aTransactionId);

  mozilla::ipc::IPCResult RecvRecycleTexture(
      const TextureFlags& aTextureFlags) final;

  mozilla::ipc::IPCResult RecvDestroy() final {
    (void)Send__delete__(this);
    return IPC_OK();
  }

  void ActorDestroy(ActorDestroyReason aWhy) override;

  TextureHost* GetTextureHost() { return mTextureHost; }

  void Destroy();

  const dom::ContentParentId& GetContentId() const { return mContentId; }

  uint64_t GetSerial() const { return mSerial; }

  HostIPCAllocator* mSurfaceAllocator;
  RefPtr<TextureHost> mTextureHost;
  dom::ContentParentId mContentId;
  // mSerial is unique in TextureClient's process.
  const uint64_t mSerial;
  wr::MaybeExternalImageId mExternalImageId;

 private:
  virtual ~TextureParent();
};

static bool WrapWithWebRenderTextureHost(ISurfaceAllocator* aDeallocator,
                                         LayersBackend aBackend,
                                         TextureFlags aFlags) {
  if (!aDeallocator) {
    return false;
  }
  if ((aFlags & TextureFlags::SNAPSHOT) ||
      (!aDeallocator->UsesImageBridge() &&
       !aDeallocator->AsCompositorBridgeParentBase())) {
    return false;
  }
  return true;
}

////////////////////////////////////////////////////////////////////////////////
already_AddRefed<PTextureParent> TextureHost::CreateIPDLActor(
    HostIPCAllocator* aAllocator, const SurfaceDescriptor& aSharedData,
    ReadLockDescriptor&& aReadLock, LayersBackend aLayersBackend,
    TextureFlags aFlags, const dom::ContentParentId& aContentId,
    uint64_t aSerial, const wr::MaybeExternalImageId& aExternalImageId) {
  MOZ_ASSERT(!(aFlags & TextureFlags::DEALLOCATE_CLIENT));

  TextureFlags flags = aFlags & ~TextureFlags::DEALLOCATE_CLIENT;
  auto actor = MakeRefPtr<TextureParent>(aAllocator, aContentId, aSerial,
                                         aExternalImageId);
  if (!actor->Init(aSharedData, std::move(aReadLock), aLayersBackend, flags)) {
    return nullptr;
  }
  return actor.forget();
}

// static
TextureHost* TextureHost::AsTextureHost(PTextureParent* actor) {
  if (!actor) {
    return nullptr;
  }
  return static_cast<TextureParent*>(actor)->mTextureHost;
}

// static
uint64_t TextureHost::GetTextureSerial(PTextureParent* actor) {
  if (!actor) {
    return UINT64_MAX;
  }
  return static_cast<TextureParent*>(actor)->mSerial;
}

// static
dom::ContentParentId TextureHost::GetTextureContentId(PTextureParent* actor) {
  if (!actor) {
    return dom::ContentParentId();
  }
  return static_cast<TextureParent*>(actor)->mContentId;
}

PTextureParent* TextureHost::GetIPDLActor() { return mActor; }

void TextureHost::SetLastFwdTransactionId(uint64_t aTransactionId) {
  MOZ_ASSERT(mFwdTransactionId <= aTransactionId);
  mFwdTransactionId = aTransactionId;
}

already_AddRefed<TextureHost> CreateDummyBufferTextureHost(
    mozilla::layers::LayersBackend aBackend,
    mozilla::layers::TextureFlags aFlags) {
  // Ensure that the host will delete the memory.
  aFlags &= ~TextureFlags::DEALLOCATE_CLIENT;
  aFlags |= TextureFlags::DUMMY_TEXTURE;
  UniquePtr<TextureData> textureData(BufferTextureData::Create(
      gfx::IntSize(11), gfx::SurfaceFormat::B8G8R8A8, gfx::ColorSpace2::SRGB,
      gfx::TransferFunction::SRGB, gfx::BackendType::SKIA, aBackend, aFlags,
      TextureAllocationFlags::ALLOC_DEFAULT, nullptr));
  SurfaceDescriptor surfDesc;
  textureData->Serialize(surfDesc);
  const SurfaceDescriptorBuffer& bufferDesc =
      surfDesc.get_SurfaceDescriptorBuffer();
  const MemoryOrShmem& data = bufferDesc.data();
  RefPtr host = MakeRefPtr<MemoryTextureHost>(
      reinterpret_cast<uint8_t*>(data.get_uintptr_t()), bufferDesc.desc(),
      aFlags);
  return host.forget();
}

already_AddRefed<TextureHost> TextureHost::Create(
    const SurfaceDescriptor& aDesc, ReadLockDescriptor&& aReadLock,
    HostIPCAllocator* aDeallocator, LayersBackend aBackend, TextureFlags aFlags,
    wr::MaybeExternalImageId& aExternalImageId) {
  RefPtr<TextureHost> result;

  switch (aDesc.type()) {
    case SurfaceDescriptor::TSurfaceDescriptorBuffer:
    case SurfaceDescriptor::TSurfaceDescriptorGPUVideo:
      result = CreateBackendIndependentTextureHost(aDesc, aDeallocator,
                                                   aBackend, aFlags);
      break;

    case SurfaceDescriptor::TEGLImageDescriptor:
    case SurfaceDescriptor::TSurfaceTextureDescriptor:
    case SurfaceDescriptor::TSurfaceDescriptorAndroidHardwareBuffer:
    case SurfaceDescriptor::TSurfaceDescriptorSharedGLTexture:
    case SurfaceDescriptor::TSurfaceDescriptorDMABuf:
      result = CreateTextureHostOGL(aDesc, aDeallocator, aBackend, aFlags);
      break;

    case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface:
      result = CreateTextureHostOGL(aDesc, aDeallocator, aBackend, aFlags);
      break;

#ifdef XP_WIN
    case SurfaceDescriptor::TSurfaceDescriptorD3D10:
    case SurfaceDescriptor::TSurfaceDescriptorDXGIYCbCr:
      result = CreateTextureHostD3D11(aDesc, aDeallocator, aBackend, aFlags);
      break;
#  ifdef MOZ_WMF_MEDIA_ENGINE
    case SurfaceDescriptor::TSurfaceDescriptorDcompSurface:
      result =
          CreateTextureHostDcompSurface(aDesc, aDeallocator, aBackend, aFlags);
      break;
#  endif
#endif
    default:
      MOZ_CRASH("GFX: Unsupported Surface type host");
  }

  if (!result) {
    gfxCriticalNote << "TextureHost creation failure type=" << aDesc.type();
  }

  if (result && WrapWithWebRenderTextureHost(aDeallocator, aBackend, aFlags)) {
    MOZ_ASSERT(aExternalImageId.isSome());
    result = MakeRefPtr<WebRenderTextureHost>(aFlags, result,
                                              aExternalImageId.ref());
  }

  if (result) {
    result->DeserializeReadLock(std::move(aReadLock), aDeallocator);
  }

  return result.forget();
}

already_AddRefed<TextureHost> CreateBackendIndependentTextureHost(
    const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator,
    LayersBackend aBackend, TextureFlags aFlags) {
  RefPtr<TextureHost> result;
  switch (aDesc.type()) {
    case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
      const SurfaceDescriptorBuffer& bufferDesc =
          aDesc.get_SurfaceDescriptorBuffer();
      const MemoryOrShmem& data = bufferDesc.data();
      switch (data.type()) {
        case MemoryOrShmem::TShmem: {
          const ipc::Shmem& shmem = data.get_Shmem();
          if (!shmem.IsReadable()) {
            // We failed to map the shmem so we can't verify its size.
            // Attempting to construct a ShmemTextureHost with it will succeed,
            // but the resulting object will have a null shmem and can't ever be
            // locked or mapped -- it's not useful at all. We just return
            // nullptr instead.
            gfxCriticalError() << "Failed texture host with unmappable shmem.";
            return nullptr;
          }

          size_t bufSize = shmem.Size<char>();
          Maybe<size_t> reqSize;
          const BufferDescriptor& desc = bufferDesc.desc();
          switch (desc.type()) {
            case BufferDescriptor::TYCbCrDescriptor: {
              const YCbCrDescriptor& ycbcr = desc.get_YCbCrDescriptor();
              reqSize = ImageDataSerializer::ComputeYCbCrBufferSize(
                  ycbcr.display(), ycbcr.ySize(), ycbcr.yStride(),
                  ycbcr.cbCrSize(), ycbcr.cbCrStride(), ycbcr.yOffset(),
                  ycbcr.cbOffset(), ycbcr.crOffset(), ycbcr.colorDepth(),
                  ycbcr.chromaSubsampling());
              break;
            }
            case BufferDescriptor::TRGBDescriptor: {
              const RGBDescriptor& rgb = desc.get_RGBDescriptor();
              reqSize = ImageDataSerializer::ComputeRGBBufferSize(rgb.size(),
                                                                  rgb.format());
              break;
            }
            default:
              gfxCriticalError()
                  << "Bad buffer host descriptor " << (int)desc.type();
              MOZ_CRASH("GFX: Bad descriptor");
          }

          if (reqSize.isNothing() || bufSize < reqSize.value()) {
            NS_ERROR(
                "A client process gave a shmem too small to fit for its "
                "descriptor!");
            return nullptr;
          }

          result =
              MakeRefPtr<ShmemTextureHost>(shmem, desc, aDeallocator, aFlags);
          break;
        }
        case MemoryOrShmem::Tuintptr_t: {
          if (aDeallocator && !aDeallocator->IsSameProcess()) {
            NS_ERROR(
                "A client process is trying to peek at our address space using "
                "a MemoryTexture!");
            return nullptr;
          }

          result = MakeRefPtr<MemoryTextureHost>(
              reinterpret_cast<uint8_t*>(data.get_uintptr_t()),
              bufferDesc.desc(), aFlags);
          break;
        }
        default:
          gfxCriticalError()
              << "Failed texture host for backend " << (int)data.type();
          MOZ_CRASH("GFX: No texture host for backend");
      }
      break;
    }
    case SurfaceDescriptor::TSurfaceDescriptorGPUVideo: {
      MOZ_ASSERT(aDesc.get_SurfaceDescriptorGPUVideo().type() ==
                 SurfaceDescriptorGPUVideo::TSurfaceDescriptorRemoteDecoder);
      result = GPUVideoTextureHost::CreateFromDescriptor(
          aDeallocator->GetContentId(), aFlags,
          aDesc.get_SurfaceDescriptorGPUVideo());
      break;
    }
    default: {
      NS_WARNING("No backend independent TextureHost for this descriptor type");
    }
  }
  return result.forget();
}

TextureHost::TextureHost(TextureHostType aType, TextureFlags aFlags)
    : AtomicRefCountedWithFinalize("TextureHost"),
      mTextureHostType(aType),
      mActor(nullptr),
      mFlags(aFlags),
      mCompositableCount(0),
      mFwdTransactionId(0),
      mReadLocked(false) {}

TextureHost::~TextureHost() {
  MOZ_ASSERT(mExternalImageId.isNothing());

  if (mReadLocked) {
    // If we still have a ReadLock, unlock it. At this point we don't care about
    // the texture client being written into on the other side since it should
    // be destroyed by now. But we will hit assertions if we don't ReadUnlock
    // before destroying the lock itself.
    ReadUnlock();
  }
  if (mDestroyedCallback) {
    mDestroyedCallback();
  }
}

void TextureHost::Finalize() {
  MaybeDestroyRenderTexture();

  if (!(GetFlags() & TextureFlags::DEALLOCATE_CLIENT)) {
    DeallocateSharedData();
    DeallocateDeviceData();
  }
}

void TextureHost::UnbindTextureSource() {
  if (mReadLocked) {
    ReadUnlock();
  }
}

void TextureHost::RecycleTexture(TextureFlags aFlags) {
  MOZ_ASSERT(GetFlags() & TextureFlags::RECYCLE);
  MOZ_ASSERT(aFlags & TextureFlags::RECYCLE);
  mFlags = aFlags;
}

void TextureHost::PrepareForUse() {}

void TextureHost::NotifyNotUsed() {
  if (!mActor) {
    if ((mFlags & TextureFlags::REMOTE_TEXTURE) && AsSurfaceTextureHost()) {
      MOZ_ASSERT(mExternalImageId.isSome());
      wr::RenderThread::Get()->NotifyNotUsed(*mExternalImageId);
    }
    return;
  }

  // Do not need to call NotifyNotUsed() if TextureHost does not have
  // TextureFlags::RECYCLE flag nor TextureFlags::WAIT_HOST_USAGE_END flag.
  if (!(GetFlags() & TextureFlags::RECYCLE) &&
      !(GetFlags() & TextureFlags::WAIT_HOST_USAGE_END)) {
    return;
  }

  mActor->NotifyNotUsed(mFwdTransactionId);
}

void TextureHost::CallNotifyNotUsed() {
  if (!mActor) {
    return;
  }
  mActor->NotifyNotUsed(mFwdTransactionId);
}

void TextureHost::MaybeDestroyRenderTexture() {
  if (mExternalImageId.isNothing()) {
    // RenderTextureHost was not created
    return;
  }
  // When TextureHost created RenderTextureHost, delete it here.
  TextureHost::DestroyRenderTexture(mExternalImageId.ref());
  mExternalImageId = Nothing();
}

void TextureHost::DestroyRenderTexture(
    const wr::ExternalImageId& aExternalImageId) {
  wr::RenderThread::Get()->UnregisterExternalImage(aExternalImageId);
}

void TextureHost::EnsureRenderTexture(
    const wr::MaybeExternalImageId& aExternalImageId) {
  if (aExternalImageId.isNothing()) {
    // TextureHost is wrapped by GPUVideoTextureHost.
    if (mExternalImageId.isSome()) {
      // RenderTextureHost was already created.
      return;
    }
    mExternalImageId =
        Some(AsyncImagePipelineManager::GetNextExternalImageId());
  } else {
    // TextureHost is wrapped by WebRenderTextureHost.
    if (aExternalImageId == mExternalImageId) {
      // The texture has already been created.
      return;
    }
    MOZ_ASSERT(mExternalImageId.isNothing());
    mExternalImageId = aExternalImageId;
  }
  CreateRenderTexture(mExternalImageId.ref());
}

TextureSource::TextureSource() : mCompositableCount(0) {}

TextureSource::~TextureSource() = default;
BufferTextureHost::BufferTextureHost(const BufferDescriptor& aDesc,
                                     TextureFlags aFlags)
    : TextureHost(TextureHostType::Buffer, aFlags), mLocked(false) {
  mDescriptor = aDesc;
  switch (mDescriptor.type()) {
    case BufferDescriptor::TYCbCrDescriptor: {
      const YCbCrDescriptor& ycbcr = mDescriptor.get_YCbCrDescriptor();
      MOZ_ASSERT(gfx::IntRect(gfx::IntPoint(), ycbcr.ySize())
                     .Contains(ycbcr.display()));
      mSize = ycbcr.display().Size();
      if (ycbcr.colorDepth() == gfx::ColorDepth::COLOR_8) {
        mFormat = gfx::SurfaceFormat::YUV420;
      } else if (ycbcr.colorDepth() == gfx::ColorDepth::COLOR_10) {
        mFormat = gfx::SurfaceFormat::YUV420P10;
      } else {
        // we should probably do better for the other depths
        // but UNKNOWN seems good enough.
        mFormat = gfx::SurfaceFormat::UNKNOWN;
      }
      break;
    }
    case BufferDescriptor::TRGBDescriptor: {
      const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();
      mSize = rgb.size();
      mFormat = rgb.format();
      break;
    }
    default:
      gfxCriticalError() << "Bad buffer host descriptor "
                         << (int)mDescriptor.type();
      MOZ_CRASH("GFX: Bad descriptor");
  }

#ifdef XP_MACOSX
  const int kMinSize = 1024;
  const int kMaxSize = 4096;
  mUseExternalTextures =
      kMaxSize >= mSize.width && mSize.width >= kMinSize &&
      kMaxSize >= mSize.height && mSize.height >= kMinSize &&
      StaticPrefs::gfx_webrender_enable_client_storage_AtStartup();
#else
  mUseExternalTextures = false;
#endif
}

BufferTextureHost::~BufferTextureHost() = default;

void BufferTextureHost::DeallocateDeviceData() {}

bool BufferTextureHost::IsYCbCr() const {
  return mDescriptor.type() == BufferDescriptor::TYCbCrDescriptor;
}

void BufferTextureHost::CreateRenderTexture(
    const wr::ExternalImageId& aExternalImageId) {
  MOZ_ASSERT(mExternalImageId.isSome());

  RefPtr<wr::RenderTextureHost> texture;

  if (UseExternalTextures()) {
    texture = MakeRefPtr<wr::RenderExternalTextureHost>(GetBuffer(),
                                                        GetBufferDescriptor());
  } else {
    texture = MakeRefPtr<wr::RenderBufferTextureHost>(GetBuffer(),
                                                      GetBufferDescriptor());
  }

  if (auto* shmemTextureHost = AsShmemTextureHost()) {
    shmemTextureHost->OnRenderTextureCreated(texture);
  }

  wr::RenderThread::Get()->RegisterExternalImage(aExternalImageId,
                                                 texture.forget());
}

uint32_t BufferTextureHost::NumSubTextures() {
  if (IsYCbCr()) {
    return 3;
  }

  return 1;
}

void BufferTextureHost::PushResourceUpdates(
    wr::TransactionBuilder& aResources, ResourceUpdateOp aOp,
    const Range<wr::ImageKey>& aImageKeys, const wr::ExternalImageId& aExtID) {
  auto method = aOp == TextureHost::ADD_IMAGE
                    ? &wr::TransactionBuilder::AddExternalImage
                    : &wr::TransactionBuilder::UpdateExternalImage;

  // Use native textures if our backend requires it, or if our backend doesn't
  // forbid it and we want to use them.
  NativeTexturePolicy policy =
      BackendNativeTexturePolicy(aResources.GetBackendType(), GetSize());
  bool useNativeTexture =
      (policy == REQUIRE) || (policy != FORBID && UseExternalTextures());
  auto imageType = useNativeTexture ? wr::ExternalImageType::TextureHandle(
                                          wr::ImageBufferKind::TextureRect)
                                    : wr::ExternalImageType::Buffer();

  if (!IsYCbCr()) {
    if (aImageKeys.length() != 1) {
      MOZ_ASSERT_UNREACHABLE("unexpected keys lenght");
      return;
    }

    auto stride =
        ImageDataSerializer::ComputeRGBStride(GetFormat(), GetSize().width);
    if (NS_WARN_IF(stride.isNothing())) {
      return;
    }

    auto format = wr::SurfaceFormatToImageFormat(GetFormat());
    if (NS_WARN_IF(!format)) {
      return;
    }
    wr::ImageDescriptor descriptor(GetSize(), stride.value(), *format,
                                   wr::ToOpacityType(GetFormat()));
    (aResources.*method)(aImageKeys[0], descriptor, aExtID, imageType, 0,
                         /* aNormalizedUvs */ false);
  } else {
    if (aImageKeys.length() != 3) {
      MOZ_ASSERT_UNREACHABLE("unexpected keys lenght");
      return;
    }

    const layers::YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
    gfx::IntSize ySize = desc.display().Size();
    gfx::IntSize cbcrSize = ImageDataSerializer::GetCroppedCbCrSize(desc);
    gfx::SurfaceFormat surfaceFormat =
        SurfaceFormatForColorDepth(desc.colorDepth());
    auto format = wr::SurfaceFormatToImageFormat(surfaceFormat);
    if (NS_WARN_IF(!format)) {
      return;
    }
    auto opacity = wr::ToOpacityType(surfaceFormat);
    wr::ImageDescriptor yDescriptor(ySize, desc.yStride(), *format, opacity);
    wr::ImageDescriptor cbcrDescriptor(cbcrSize, desc.cbCrStride(), *format,
                                       opacity);
    (aResources.*method)(aImageKeys[0], yDescriptor, aExtID, imageType, 0,
                         /* aNormalizedUvs */ false);
    (aResources.*method)(aImageKeys[1], cbcrDescriptor, aExtID, imageType, 1,
                         /* aNormalizedUvs */ false);
    (aResources.*method)(aImageKeys[2], cbcrDescriptor, aExtID, imageType, 2,
                         /* aNormalizedUvs */ false);
  }
}

void BufferTextureHost::PushDisplayItems(wr::DisplayListBuilder& aBuilder,
                                         const wr::LayoutRect& aBounds,
                                         const wr::LayoutRect& aClip,
                                         wr::ImageRendering aFilter,
                                         const Range<wr::ImageKey>& aImageKeys,
                                         PushDisplayItemFlagSet aFlags) {
  // SWGL should always try to bypass shaders and composite directly.
  bool preferCompositorSurface =
      aFlags.contains(PushDisplayItemFlag::PREFER_COMPOSITOR_SURFACE);
  bool useExternalSurface =
      aFlags.contains(PushDisplayItemFlag::SUPPORTS_EXTERNAL_BUFFER_TEXTURES);
  if (!IsYCbCr()) {
    if (aImageKeys.length() != 1) {
      MOZ_ASSERT_UNREACHABLE("unexpected key length");
      return;
    }
    aBuilder.PushImage(aBounds, aClip, true, false, aFilter, aImageKeys[0],
                       !(mFlags & TextureFlags::NON_PREMULTIPLIED),
                       wr::ColorF{1.0f, 1.0f, 1.0f, 1.0f},
                       preferCompositorSurface, useExternalSurface);
  } else {
    if (aImageKeys.length() != 3) {
      MOZ_ASSERT_UNREACHABLE("unexpected key length");
      return;
    }
    const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
    aBuilder.PushYCbCrPlanarImage(
        aBounds, aClip, true, aImageKeys[0], aImageKeys[1], aImageKeys[2],
        wr::ToWrColorDepth(desc.colorDepth()),
        wr::ToWrYuvColorSpace(desc.yUVColorSpace()),
        wr::ToWrColorRange(desc.colorRange()), aFilter, preferCompositorSurface,
        useExternalSurface);
  }
}

void TextureHost::DeserializeReadLock(ReadLockDescriptor&& aDesc,
                                      ISurfaceAllocator* aAllocator) {
  if (mReadLock) {
    return;
  }

  mReadLock = TextureReadLock::Deserialize(std::move(aDesc), aAllocator);
}

void TextureHost::SetReadLocked() {
  if (!mReadLock) {
    return;
  }
  // If mReadLocked is true it means we haven't read unlocked yet and the
  // content side should not have been able to write into this texture and read
  // lock again!
  MOZ_ASSERT(!mReadLocked);
  mReadLocked = true;
}

void TextureHost::ReadUnlock() {
  if (mReadLock && mReadLocked) {
    mReadLock->ReadUnlock();
    mReadLocked = false;
  }
}

bool TextureHost::NeedsYFlip() const {
  return bool(mFlags & TextureFlags::ORIGIN_BOTTOM_LEFT);
}

void BufferTextureHost::UnbindTextureSource() {
  // This texture is not used by any layer anymore.
  // If the texture has an intermediate buffer we don't care either because
  // texture uploads are also performed synchronously for BufferTextureHost.
  ReadUnlock();
}

gfx::SurfaceFormat BufferTextureHost::GetFormat() const { return mFormat; }

gfx::YUVColorSpace BufferTextureHost::GetYUVColorSpace() const {
  if (IsYCbCr()) {
    const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
    return desc.yUVColorSpace();
  }
  return gfx::YUVColorSpace::Identity;
}

gfx::TransferFunction BufferTextureHost::GetTransferFunction() const {
  if (IsYCbCr()) {
    const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
    return desc.transferFunction();
  }
  return gfx::TransferFunction::BT709;
}

gfx::ColorDepth BufferTextureHost::GetColorDepth() const {
  if (IsYCbCr()) {
    const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
    return desc.colorDepth();
  }
  return gfx::ColorDepth::COLOR_8;
}

gfx::ColorRange BufferTextureHost::GetColorRange() const {
  if (IsYCbCr()) {
    const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
    return desc.colorRange();
  }
  return TextureHost::GetColorRange();
}

gfx::ChromaSubsampling BufferTextureHost::GetChromaSubsampling() const {
  if (IsYCbCr()) {
    const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
    return desc.chromaSubsampling();
  }
  return gfx::ChromaSubsampling::FULL;
}

uint8_t* BufferTextureHost::GetYChannel() {
  if (mFormat == gfx::SurfaceFormat::YUV420) {
    const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
    return ImageDataSerializer::GetYChannel(GetBuffer(), desc);
  }
  return nullptr;
}

uint8_t* BufferTextureHost::GetCbChannel() {
  if (mFormat == gfx::SurfaceFormat::YUV420) {
    const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
    return ImageDataSerializer::GetCbChannel(GetBuffer(), desc);
  }
  return nullptr;
}

uint8_t* BufferTextureHost::GetCrChannel() {
  if (mFormat == gfx::SurfaceFormat::YUV420) {
    const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
    return ImageDataSerializer::GetCrChannel(GetBuffer(), desc);
  }
  return nullptr;
}

uint16_t* BufferTextureHost::GetYChannel16() {
  if (mFormat == gfx::SurfaceFormat::YUV420P10) {
    const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
    return ImageDataSerializer::GetYChannel(GetBuffer16(), desc);
  }
  MOZ_ASSERT_UNREACHABLE("Unexpected to be called!");
  return nullptr;
}

uint16_t* BufferTextureHost::GetCbChannel16() {
  if (mFormat == gfx::SurfaceFormat::YUV420P10) {
    const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
    return ImageDataSerializer::GetCbChannel(GetBuffer16(), desc);
  }
  MOZ_ASSERT_UNREACHABLE("Unexpected to be called!");
  return nullptr;
}

uint16_t* BufferTextureHost::GetCrChannel16() {
  if (mFormat == gfx::SurfaceFormat::YUV420P10) {
    const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
    return ImageDataSerializer::GetCrChannel(GetBuffer16(), desc);
  }
  MOZ_ASSERT_UNREACHABLE("Unexpected to be called!");
  return nullptr;
}

int32_t BufferTextureHost::GetYStride() const {
  if (IsYCbCr()) {
    const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
    return desc.yStride();
  }
  return 0;
}

int32_t BufferTextureHost::GetCbCrStride() const {
  if (IsYCbCr()) {
    const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
    return desc.cbCrStride();
  }
  return 0;
}

already_AddRefed<gfx::DataSourceSurface> BufferTextureHost::GetAsSurface(
    gfx::DataSourceSurface* aSurface) {
  RefPtr<gfx::DataSourceSurface> result;
  if (mFormat == gfx::SurfaceFormat::UNKNOWN) {
    NS_WARNING("BufferTextureHost: unsupported format!");
    return nullptr;
  }
  if (!GetBuffer()) {
    return nullptr;
  }
  if (IsYCbCr()) {
    result = ImageDataSerializer::DataSourceSurfaceFromYCbCrDescriptor(
        GetBuffer(), mDescriptor.get_YCbCrDescriptor(), aSurface);
    if (NS_WARN_IF(!result)) {
      return nullptr;
    }
  } else {
    auto stride =
        ImageDataSerializer::GetRGBStride(mDescriptor.get_RGBDescriptor());
    if (stride.isNothing()) {
      return nullptr;
    }

    struct Closure {
      RefPtr<nsISerialEventTarget> mEventTarget;
      RefPtr<Runnable> mRunnable;
    };

    RefPtr<nsISerialEventTarget> eventTarget = CompositorThread();
    RefPtr<Runnable> runnable =
        NS_NewRunnableFunction("BufferTextureHost::GetAsSurface::Runnable",
                               [self = RefPtr{this}]() {});

    Closure* closure = new Closure{eventTarget.forget(), runnable.forget()};

    auto destroyedCallback = [](void* aClosure) mutable {
      auto* closure = static_cast<Closure*>(aClosure);
      closure->mEventTarget->Dispatch(closure->mRunnable.forget());
      delete closure;
    };

    result = gfx::Factory::CreateWrappingDataSourceSurface(
        GetBuffer(), stride.value(), mSize, mFormat, destroyedCallback,
        closure);
  }
  return result.forget();
}

ShmemTextureHost::ShmemTextureHost(const ipc::Shmem& aShmem,
                                   const BufferDescriptor& aDesc,
                                   ISurfaceAllocator* aDeallocator,
                                   TextureFlags aFlags)
    : BufferTextureHost(aDesc, aFlags), mDeallocator(aDeallocator) {
  MOZ_ASSERT(!(mFlags & TextureFlags::DEALLOCATE_CLIENT));

  if (aShmem.IsReadable()) {
    UniquePtr<mozilla::ipc::Shmem> shmem = MakeUnique<ipc::Shmem>(aShmem);
    mShmemDeallocRunnable =
        MakeRefPtr<ShmemDeallocRunnable>(mDeallocator, std::move(shmem));
  } else {
    // This can happen if we failed to map the shmem on this process, perhaps
    // because it was big and we didn't have enough contiguous address space
    // available, even though we did on the child process.
    // As a result this texture will be in an invalid state and Lock will
    // always fail.

    gfxCriticalNote << "Failed to create a valid ShmemTextureHost";
  }

  MOZ_COUNT_CTOR(ShmemTextureHost);
}

ShmemTextureHost::~ShmemTextureHost() {
  DeallocateDeviceData();
  MOZ_COUNT_DTOR(ShmemTextureHost);
}

void ShmemTextureHost::DeallocateSharedData() {}

void ShmemTextureHost::ForgetSharedData() {}

void ShmemTextureHost::OnShutdown() { mShmemDeallocRunnable = nullptr; }

ShmemTextureHost::ShmemDeallocRunnable::ShmemDeallocRunnable(
    ISurfaceAllocator* aDeallocator, UniquePtr<mozilla::ipc::Shmem>&& aShmem)
    : Runnable("ShmemDeallocRunnable"),
      mDeallocator(aDeallocator),
      mShmem(std::move(aShmem)) {}

nsresult ShmemTextureHost::ShmemDeallocRunnable::Run() {
  if (!mDeallocator || !mShmem) {
    return NS_OK;
  }
  mDeallocator->AsShmemAllocator()->DeallocShmem(*mShmem);
  mShmem = nullptr;
  return NS_OK;
}

ShmemTextureHost::ShmemDeallocRunnable::~ShmemDeallocRunnable() {
  if (!mDeallocator || !mShmem) {
    return;
  }
  mDeallocator->AsShmemAllocator()->DeallocShmem(*mShmem);
}

void ShmemTextureHost::OnRenderTextureCreated(
    wr::RenderTextureHost* aRenderTexture) {
  MOZ_ASSERT(aRenderTexture);

  if (!mShmemDeallocRunnable || !mShmemDeallocRunnable->GetShmem()) {
    return;
  }

  RefPtr<nsISerialEventTarget> eventTarget = GetCurrentSerialEventTarget();
  RefPtr<ShmemDeallocRunnable> runnable = mShmemDeallocRunnable;

  auto destroyedCallback = [eventTarget = std::move(eventTarget),
                            runnable = std::move(runnable)]() mutable {
    eventTarget->Dispatch(runnable.forget());
  };

  aRenderTexture->SetDestroyedCallback(destroyedCallback);
}

uint8_t* ShmemTextureHost::GetBuffer() const {
  if (mShmemDeallocRunnable && mShmemDeallocRunnable->GetShmem()) {
    return mShmemDeallocRunnable->GetShmem()->get<uint8_t>();
  }
  return nullptr;
}

uint16_t* ShmemTextureHost::GetBuffer16() const {
  if (mShmemDeallocRunnable && mShmemDeallocRunnable->GetShmem()) {
    return mShmemDeallocRunnable->GetShmem()->get<uint16_t>();
  }
  return nullptr;
}

size_t ShmemTextureHost::GetBufferSize() const {
  if (mShmemDeallocRunnable && mShmemDeallocRunnable->GetShmem()) {
    return mShmemDeallocRunnable->GetShmem()->Size<uint8_t>();
  }
  return 0;
}

MemoryTextureHost::MemoryTextureHost(uint8_t* aBuffer,
                                     const BufferDescriptor& aDesc,
                                     TextureFlags aFlags)
    : BufferTextureHost(aDesc, aFlags), mBuffer(aBuffer) {
  MOZ_COUNT_CTOR(MemoryTextureHost);
}

MemoryTextureHost::~MemoryTextureHost() {
  MOZ_ASSERT(!mBuffer || (mFlags & TextureFlags::DEALLOCATE_CLIENT),
             "Leaking our buffer");
  DeallocateDeviceData();
  MOZ_COUNT_DTOR(MemoryTextureHost);
}

void MemoryTextureHost::DeallocateSharedData() {
  if (mBuffer) {
    GfxMemoryImageReporter::WillFree(mBuffer);
  }
  delete[] mBuffer;
  mBuffer = nullptr;
}

void MemoryTextureHost::ForgetSharedData() { mBuffer = nullptr; }

uint8_t* MemoryTextureHost::GetBuffer() const { return mBuffer; }
uint16_t* MemoryTextureHost::GetBuffer16() const {
  return reinterpret_cast<uint16_t*>(mBuffer);
}

size_t MemoryTextureHost::GetBufferSize() const {
  // MemoryTextureHost just trusts that the buffer size is large enough to read
  // anything we need to. That's because MemoryTextureHost has to trust the
  // buffer pointer anyway, so the security model here is just that
  // MemoryTexture's are restricted to same-process clients.
  return std::numeric_limits<size_t>::max();
}

TextureParent::TextureParent(HostIPCAllocator* aSurfaceAllocator,
                             const dom::ContentParentId& aContentId,
                             uint64_t aSerial,
                             const wr::MaybeExternalImageId& aExternalImageId)
    : mSurfaceAllocator(aSurfaceAllocator),
      mContentId(aContentId),
      mSerial(aSerial),
      mExternalImageId(aExternalImageId) {
  MOZ_COUNT_CTOR(TextureParent);
}

TextureParent::~TextureParent() { MOZ_COUNT_DTOR(TextureParent); }

void TextureParent::NotifyNotUsed(uint64_t aTransactionId) {
  if (!mTextureHost) {
    return;
  }
  mSurfaceAllocator->NotifyNotUsed(this, aTransactionId);
}

bool TextureParent::Init(const SurfaceDescriptor& aSharedData,
                         ReadLockDescriptor&& aReadLock,
                         const LayersBackend& aBackend,
                         const TextureFlags& aFlags) {
  mTextureHost =
      TextureHost::Create(aSharedData, std::move(aReadLock), mSurfaceAllocator,
                          aBackend, aFlags, mExternalImageId);
  if (mTextureHost) {
    mTextureHost->mActor = this;
  }

  return !!mTextureHost;
}

void TextureParent::Destroy() {
  if (!mTextureHost) {
    return;
  }

  if (mTextureHost->mReadLocked) {
    // ReadUnlock here to make sure the ReadLock's shmem does not outlive the
    // protocol that created it.
    mTextureHost->ReadUnlock();
  }

  if (mTextureHost->GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
    mTextureHost->ForgetSharedData();
  }

  mTextureHost->mActor = nullptr;
  mTextureHost = nullptr;
}

void TextureHost::ReceivedDestroy(PTextureParent* aActor) {
  static_cast<TextureParent*>(aActor)->RecvDestroy();
}

mozilla::ipc::IPCResult TextureParent::RecvRecycleTexture(
    const TextureFlags& aTextureFlags) {
  if (!mTextureHost) {
    return IPC_OK();
  }
  mTextureHost->RecycleTexture(aTextureFlags);
  return IPC_OK();
}

void TextureParent::ActorDestroy(ActorDestroyReason aWhy) {
  auto* manager = Manager();
  if (manager->GetProtocolId() == ipc::ProtocolId::PVideoBridgeMsgStart) {
    static_cast<VideoBridgeParent*>(manager)->RemoveTexture(mSerial);
  }
  Destroy();
}

////////////////////////////////////////////////////////////////////////////////

}  // namespace layers
}  // namespace mozilla

Messung V0.5 in Prozent
C=93 H=100 G=96

¤ Dauer der Verarbeitung: 0.15 Sekunden  ¤

*© 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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=434850
#Domains=655579