summaryrefslogtreecommitdiffstats
path: root/gfx/layers/composite/GPUVideoTextureHost.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--gfx/layers/composite/GPUVideoTextureHost.cpp295
1 files changed, 295 insertions, 0 deletions
diff --git a/gfx/layers/composite/GPUVideoTextureHost.cpp b/gfx/layers/composite/GPUVideoTextureHost.cpp
new file mode 100644
index 0000000000..ed6be1972d
--- /dev/null
+++ b/gfx/layers/composite/GPUVideoTextureHost.cpp
@@ -0,0 +1,295 @@
+/* -*- 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 "GPUVideoTextureHost.h"
+
+#include "ImageContainer.h"
+#include "mozilla/RemoteDecoderManagerParent.h"
+#include "mozilla/layers/ImageBridgeParent.h"
+#include "mozilla/layers/VideoBridgeParent.h"
+#include "mozilla/webrender/RenderTextureHostWrapper.h"
+#include "mozilla/webrender/RenderThread.h"
+
+namespace mozilla {
+namespace layers {
+
+GPUVideoTextureHost::GPUVideoTextureHost(
+ TextureFlags aFlags, const SurfaceDescriptorGPUVideo& aDescriptor)
+ : TextureHost(aFlags), mDescriptor(aDescriptor) {
+ MOZ_COUNT_CTOR(GPUVideoTextureHost);
+}
+
+GPUVideoTextureHost::~GPUVideoTextureHost() {
+ MOZ_COUNT_DTOR(GPUVideoTextureHost);
+}
+
+GPUVideoTextureHost* GPUVideoTextureHost::CreateFromDescriptor(
+ TextureFlags aFlags, const SurfaceDescriptorGPUVideo& aDescriptor) {
+ return new GPUVideoTextureHost(aFlags, aDescriptor);
+}
+
+TextureHost* GPUVideoTextureHost::EnsureWrappedTextureHost() {
+ if (mWrappedTextureHost) {
+ return mWrappedTextureHost;
+ }
+
+ const auto& sd =
+ static_cast<const SurfaceDescriptorRemoteDecoder&>(mDescriptor);
+ VideoBridgeParent* parent = VideoBridgeParent::GetSingleton(sd.source());
+ if (!parent) {
+ // The VideoBridge went away. This can happen if the RDD process
+ // crashes.
+ return nullptr;
+ }
+ mWrappedTextureHost = parent->LookupTexture(sd.handle());
+
+ if (!mWrappedTextureHost) {
+ // The TextureHost hasn't been registered yet. This is due to a race
+ // between the ImageBridge (content) and the VideoBridge (RDD) and the
+ // ImageBridge won. See bug
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1630733#c14 for more
+ // details.
+ return nullptr;
+ }
+
+ if (mWrappedTextureHost->AsBufferTextureHost()) {
+ // TODO(miko): This code path is taken when WebRenderTextureHost wraps
+ // GPUVideoTextureHost, which wraps BufferTextureHost.
+ // Because this creates additional copies of the texture data, we should not
+ // do this.
+ mWrappedTextureHost->AsBufferTextureHost()->DisableExternalTextures();
+ }
+
+ if (mExternalImageId.isSome()) {
+ // External image id is allocated by mWrappedTextureHost.
+ mWrappedTextureHost->EnsureRenderTexture(Nothing());
+ MOZ_ASSERT(mWrappedTextureHost->mExternalImageId.isSome());
+ auto wrappedId = mWrappedTextureHost->mExternalImageId.ref();
+
+ RefPtr<wr::RenderTextureHost> texture =
+ new wr::RenderTextureHostWrapper(wrappedId);
+ wr::RenderThread::Get()->RegisterExternalImage(
+ wr::AsUint64(mExternalImageId.ref()), texture.forget());
+ }
+
+ if (mPendingSourceProvider) {
+ RefPtr<TextureSourceProvider> provider = mPendingSourceProvider.forget();
+ mWrappedTextureHost->SetTextureSourceProvider(provider);
+ }
+ if (mPendingUpdatedInternal) {
+ mWrappedTextureHost->UpdatedInternal(mPendingIntRegion.ptrOr(nullptr));
+ mPendingIntRegion.reset();
+ mPendingUpdatedInternal = false;
+ }
+ if (mPendingPrepareTextureSource) {
+ mWrappedTextureHost->PrepareTextureSource(*mPendingPrepareTextureSource);
+ mPendingPrepareTextureSource.reset();
+ }
+
+ return mWrappedTextureHost;
+}
+
+bool GPUVideoTextureHost::IsValid() { return !!EnsureWrappedTextureHost(); }
+
+bool GPUVideoTextureHost::Lock() {
+ if (!EnsureWrappedTextureHost()) {
+ return false;
+ }
+ return EnsureWrappedTextureHost()->Lock();
+}
+
+void GPUVideoTextureHost::Unlock() {
+ if (!EnsureWrappedTextureHost()) {
+ return;
+ }
+ EnsureWrappedTextureHost()->Unlock();
+}
+
+void GPUVideoTextureHost::PrepareTextureSource(
+ CompositableTextureSourceRef& aTexture) {
+ if (!EnsureWrappedTextureHost()) {
+ mPendingPrepareTextureSource = Some(aTexture);
+ return;
+ }
+ EnsureWrappedTextureHost()->PrepareTextureSource(aTexture);
+}
+
+bool GPUVideoTextureHost::BindTextureSource(
+ CompositableTextureSourceRef& aTexture) {
+ MOZ_ASSERT(EnsureWrappedTextureHost(), "Image isn't valid yet");
+ if (!EnsureWrappedTextureHost()) {
+ return false;
+ }
+ return EnsureWrappedTextureHost()->BindTextureSource(aTexture);
+}
+
+bool GPUVideoTextureHost::AcquireTextureSource(
+ CompositableTextureSourceRef& aTexture) {
+ MOZ_ASSERT(EnsureWrappedTextureHost(), "Image isn't valid yet");
+ if (!EnsureWrappedTextureHost()) {
+ return false;
+ }
+ return EnsureWrappedTextureHost()->AcquireTextureSource(aTexture);
+}
+
+void GPUVideoTextureHost::SetTextureSourceProvider(
+ TextureSourceProvider* aProvider) {
+ if (!EnsureWrappedTextureHost()) {
+ mPendingSourceProvider = aProvider;
+ return;
+ }
+ EnsureWrappedTextureHost()->SetTextureSourceProvider(aProvider);
+}
+
+gfx::YUVColorSpace GPUVideoTextureHost::GetYUVColorSpace() const {
+ MOZ_ASSERT(mWrappedTextureHost, "Image isn't valid yet");
+ if (!mWrappedTextureHost) {
+ return gfx::YUVColorSpace::UNKNOWN;
+ }
+ return mWrappedTextureHost->GetYUVColorSpace();
+}
+
+gfx::ColorDepth GPUVideoTextureHost::GetColorDepth() const {
+ MOZ_ASSERT(mWrappedTextureHost, "Image isn't valid yet");
+ if (!mWrappedTextureHost) {
+ return TextureHost::GetColorDepth();
+ }
+ return mWrappedTextureHost->GetColorDepth();
+}
+
+gfx::ColorRange GPUVideoTextureHost::GetColorRange() const {
+ MOZ_ASSERT(mWrappedTextureHost, "Image isn't valid yet");
+ if (!mWrappedTextureHost) {
+ return TextureHost::GetColorRange();
+ }
+ return mWrappedTextureHost->GetColorRange();
+}
+
+gfx::IntSize GPUVideoTextureHost::GetSize() const {
+ MOZ_ASSERT(mWrappedTextureHost, "Image isn't valid yet");
+ if (!mWrappedTextureHost) {
+ return gfx::IntSize();
+ }
+ return mWrappedTextureHost->GetSize();
+}
+
+gfx::SurfaceFormat GPUVideoTextureHost::GetFormat() const {
+ MOZ_ASSERT(mWrappedTextureHost, "Image isn't valid yet");
+ if (!mWrappedTextureHost) {
+ return gfx::SurfaceFormat::UNKNOWN;
+ }
+ return mWrappedTextureHost->GetFormat();
+}
+
+bool GPUVideoTextureHost::HasIntermediateBuffer() const {
+ MOZ_ASSERT(mWrappedTextureHost, "Image isn't valid yet");
+ if (!mWrappedTextureHost) {
+ return false;
+ }
+ return mWrappedTextureHost->HasIntermediateBuffer();
+}
+
+void GPUVideoTextureHost::UpdatedInternal(const nsIntRegion* Region) {
+ if (!EnsureWrappedTextureHost()) {
+ mPendingUpdatedInternal = true;
+ if (Region) {
+ mPendingIntRegion = Some(*Region);
+ } else {
+ mPendingIntRegion.reset();
+ }
+ return;
+ }
+ EnsureWrappedTextureHost()->UpdatedInternal(Region);
+}
+
+void GPUVideoTextureHost::CreateRenderTexture(
+ const wr::ExternalImageId& aExternalImageId) {
+ MOZ_ASSERT(mExternalImageId.isSome());
+
+ // When mWrappedTextureHost already exist, call CreateRenderTexture() here.
+ // In other cases, EnsureWrappedTextureHost() handles CreateRenderTexture().
+
+ if (mWrappedTextureHost) {
+ // External image id is allocated by mWrappedTextureHost.
+ mWrappedTextureHost->EnsureRenderTexture(Nothing());
+ MOZ_ASSERT(mWrappedTextureHost->mExternalImageId.isSome());
+ auto wrappedId = mWrappedTextureHost->mExternalImageId.ref();
+
+ RefPtr<wr::RenderTextureHost> texture =
+ new wr::RenderTextureHostWrapper(wrappedId);
+ wr::RenderThread::Get()->RegisterExternalImage(
+ wr::AsUint64(mExternalImageId.ref()), texture.forget());
+ return;
+ }
+
+ EnsureWrappedTextureHost();
+}
+
+void GPUVideoTextureHost::MaybeDestroyRenderTexture() {
+ if (mExternalImageId.isNothing() || !mWrappedTextureHost) {
+ // RenderTextureHost was not created
+ return;
+ }
+ // When GPUVideoTextureHost created RenderTextureHost, delete it here.
+ TextureHost::DestroyRenderTexture(mExternalImageId.ref());
+}
+
+uint32_t GPUVideoTextureHost::NumSubTextures() {
+ if (!EnsureWrappedTextureHost()) {
+ return 0;
+ }
+ return EnsureWrappedTextureHost()->NumSubTextures();
+}
+
+void GPUVideoTextureHost::PushResourceUpdates(
+ wr::TransactionBuilder& aResources, ResourceUpdateOp aOp,
+ const Range<wr::ImageKey>& aImageKeys, const wr::ExternalImageId& aExtID) {
+ MOZ_ASSERT(EnsureWrappedTextureHost(), "Image isn't valid yet");
+ if (!EnsureWrappedTextureHost()) {
+ return;
+ }
+ EnsureWrappedTextureHost()->PushResourceUpdates(aResources, aOp, aImageKeys,
+ aExtID);
+}
+
+void GPUVideoTextureHost::PushDisplayItems(
+ wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds,
+ const wr::LayoutRect& aClip, wr::ImageRendering aFilter,
+ const Range<wr::ImageKey>& aImageKeys, PushDisplayItemFlagSet aFlags) {
+ MOZ_ASSERT(EnsureWrappedTextureHost(), "Image isn't valid yet");
+ MOZ_ASSERT(aImageKeys.length() > 0);
+ if (!EnsureWrappedTextureHost()) {
+ return;
+ }
+
+ EnsureWrappedTextureHost()->PushDisplayItems(aBuilder, aBounds, aClip,
+ aFilter, aImageKeys, aFlags);
+}
+
+bool GPUVideoTextureHost::SupportsExternalCompositing() {
+ if (!EnsureWrappedTextureHost()) {
+ return false;
+ }
+ return EnsureWrappedTextureHost()->SupportsExternalCompositing();
+}
+
+void GPUVideoTextureHost::UnbindTextureSource() {
+ if (EnsureWrappedTextureHost()) {
+ EnsureWrappedTextureHost()->UnbindTextureSource();
+ }
+ // Handle read unlock
+ TextureHost::UnbindTextureSource();
+}
+
+void GPUVideoTextureHost::NotifyNotUsed() {
+ if (EnsureWrappedTextureHost()) {
+ EnsureWrappedTextureHost()->NotifyNotUsed();
+ }
+ TextureHost::NotifyNotUsed();
+}
+
+} // namespace layers
+} // namespace mozilla