summaryrefslogtreecommitdiffstats
path: root/gfx/layers/composite/TextureHost.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/composite/TextureHost.h')
-rw-r--r--gfx/layers/composite/TextureHost.h1026
1 files changed, 1026 insertions, 0 deletions
diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h
new file mode 100644
index 0000000000..343ba6f600
--- /dev/null
+++ b/gfx/layers/composite/TextureHost.h
@@ -0,0 +1,1026 @@
+/* -*- 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/. */
+
+#ifndef MOZILLA_GFX_TEXTUREHOST_H
+#define MOZILLA_GFX_TEXTUREHOST_H
+
+#include <stddef.h> // for size_t
+#include <stdint.h> // for uint64_t, uint32_t, uint8_t
+#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
+#include "mozilla/Attributes.h" // for override
+#include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed, etc
+#include "mozilla/dom/ipc/IdType.h"
+#include "mozilla/gfx/Logging.h"
+#include "mozilla/gfx/Matrix.h"
+#include "mozilla/gfx/Point.h" // for IntSize, IntPoint
+#include "mozilla/gfx/Rect.h"
+#include "mozilla/gfx/Types.h" // for SurfaceFormat, etc
+#include "mozilla/ipc/FileDescriptor.h"
+#include "mozilla/layers/CompositorTypes.h" // for TextureFlags, etc
+#include "mozilla/layers/LayersTypes.h" // for LayerRenderState, etc
+#include "mozilla/layers/LayersMessages.h"
+#include "mozilla/layers/LayersSurfaces.h"
+#include "mozilla/layers/TextureSourceProvider.h"
+#include "mozilla/mozalloc.h" // for operator delete
+#include "mozilla/Range.h"
+#include "mozilla/UniquePtr.h" // for UniquePtr
+#include "mozilla/webrender/WebRenderTypes.h"
+#include "nsCOMPtr.h" // for already_AddRefed
+#include "nsDebug.h" // for NS_WARNING
+#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
+#include "nsRect.h"
+#include "nsRegion.h" // for nsIntRegion
+#include "nsTraceRefcnt.h" // for MOZ_COUNT_CTOR, etc
+#include "nscore.h" // for nsACString
+#include "mozilla/layers/AtomicRefCountedWithFinalize.h"
+
+class MacIOSurface;
+namespace mozilla {
+namespace gfx {
+class DataSourceSurface;
+}
+
+namespace ipc {
+class Shmem;
+} // namespace ipc
+
+namespace wr {
+class DisplayListBuilder;
+class TransactionBuilder;
+} // namespace wr
+
+namespace layers {
+
+class AndroidHardwareBuffer;
+class AndroidHardwareBufferTextureHost;
+class BufferDescriptor;
+class BufferTextureHost;
+class Compositor;
+class CompositableParentManager;
+class ReadLockDescriptor;
+class CompositorBridgeParent;
+class SurfaceDescriptor;
+class HostIPCAllocator;
+class ISurfaceAllocator;
+class MacIOSurfaceTextureHostOGL;
+class ShmemTextureHost;
+class SurfaceTextureHost;
+class TextureHostOGL;
+class TextureReadLock;
+class TextureSourceOGL;
+class TextureSourceD3D11;
+class DataTextureSource;
+class PTextureParent;
+class RemoteTextureHostWrapper;
+class TextureParent;
+class WebRenderTextureHost;
+class WrappingTextureSourceYCbCrBasic;
+class TextureHostWrapperD3D11;
+
+/**
+ * A view on a TextureHost where the texture is internally represented as tiles
+ * (contrast with a tiled buffer, where each texture is a tile). For iteration
+ * by the texture's buffer host. This is only useful when the underlying surface
+ * is too big to fit in one device texture, which forces us to split it in
+ * smaller parts. Tiled Compositable is a different thing.
+ */
+class BigImageIterator {
+ public:
+ virtual void BeginBigImageIteration() = 0;
+ virtual void EndBigImageIteration(){};
+ virtual gfx::IntRect GetTileRect() = 0;
+ virtual size_t GetTileCount() = 0;
+ virtual bool NextTile() = 0;
+};
+
+/**
+ * TextureSource is the interface for texture objects that can be composited
+ * by a given compositor backend. Since the drawing APIs are different
+ * between backends, the TextureSource interface is split into different
+ * interfaces (TextureSourceOGL, etc.), and TextureSource mostly provide
+ * access to these interfaces.
+ *
+ * This class is used on the compositor side.
+ */
+class TextureSource : public RefCounted<TextureSource> {
+ public:
+ MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(TextureSource)
+
+ TextureSource();
+
+ virtual ~TextureSource();
+
+ virtual const char* Name() const = 0;
+
+ /**
+ * Should be overridden in order to deallocate the data that is associated
+ * with the rendering backend, such as GL textures.
+ */
+ virtual void DeallocateDeviceData() {}
+
+ /**
+ * Return the size of the texture in texels.
+ * If this is a tile iterator, GetSize must return the size of the current
+ * tile.
+ */
+ virtual gfx::IntSize GetSize() const = 0;
+
+ /**
+ * Return the pixel format of this texture
+ */
+ virtual gfx::SurfaceFormat GetFormat() const {
+ return gfx::SurfaceFormat::UNKNOWN;
+ }
+
+ /**
+ * Cast to a TextureSource for for each backend..
+ */
+ virtual TextureSourceOGL* AsSourceOGL() {
+ gfxCriticalNote << "Failed to cast " << Name()
+ << " into a TextureSourceOGL";
+ return nullptr;
+ }
+ virtual TextureSourceD3D11* AsSourceD3D11() { return nullptr; }
+ /**
+ * Cast to a DataTextureSurce.
+ */
+ virtual DataTextureSource* AsDataTextureSource() { return nullptr; }
+
+ /**
+ * Overload this if the TextureSource supports big textures that don't fit in
+ * one device texture and must be tiled internally.
+ */
+ virtual BigImageIterator* AsBigImageIterator() { return nullptr; }
+
+ virtual void Unbind() {}
+
+ void SetNextSibling(TextureSource* aTexture) { mNextSibling = aTexture; }
+
+ TextureSource* GetNextSibling() const { return mNextSibling; }
+
+ /**
+ * In some rare cases we currently need to consider a group of textures as one
+ * TextureSource, that can be split in sub-TextureSources.
+ */
+ TextureSource* GetSubSource(int index) {
+ switch (index) {
+ case 0:
+ return this;
+ case 1:
+ return GetNextSibling();
+ case 2:
+ return GetNextSibling() ? GetNextSibling()->GetNextSibling() : nullptr;
+ }
+ return nullptr;
+ }
+
+ void AddCompositableRef() { ++mCompositableCount; }
+
+ void ReleaseCompositableRef() {
+ --mCompositableCount;
+ MOZ_ASSERT(mCompositableCount >= 0);
+ }
+
+ // When iterating as a BigImage, this creates temporary TextureSources
+ // wrapping individual tiles.
+ virtual RefPtr<TextureSource> ExtractCurrentTile() {
+ NS_WARNING("Implementation does not expose tile sources");
+ return nullptr;
+ }
+
+ int NumCompositableRefs() const { return mCompositableCount; }
+
+ // The direct-map cpu buffer should be alive when gpu uses it. And it
+ // should not be updated while gpu reads it. This Sync() function
+ // implements this synchronized behavior by allowing us to check if
+ // the GPU is done with the texture, and block on it if aBlocking is
+ // true.
+ virtual bool Sync(bool aBlocking) { return true; }
+
+ protected:
+ RefPtr<TextureSource> mNextSibling;
+ int mCompositableCount;
+};
+
+/// Equivalent of a RefPtr<TextureSource>, that calls AddCompositableRef and
+/// ReleaseCompositableRef in addition to the usual AddRef and Release.
+///
+/// The semantoics of these CompositableTextureRefs are important because they
+/// are used both as a synchronization/safety mechanism, and as an optimization
+/// mechanism. They are also tricky and subtle because we use them in a very
+/// implicit way (assigning to a CompositableTextureRef is less visible than
+/// explicitly calling a method or whatnot).
+/// It is Therefore important to be careful about the way we use this tool.
+///
+/// CompositableTextureRef is a mechanism that lets us count how many
+/// compositables are using a given texture (for TextureSource and TextureHost).
+/// We use it to run specific code when a texture is not used anymore, and also
+/// we trigger fast paths on some operations when we can see that the texture's
+/// CompositableTextureRef counter is equal to 1 (the texture is not shared
+/// between compositables).
+/// This means that it is important to observe the following rules:
+/// * CompositableHosts that receive UseTexture and similar messages *must*
+/// store all of the TextureHosts they receive in CompositableTextureRef slots
+/// for as long as they may be using them.
+/// * CompositableHosts must store each texture in a *single*
+/// CompositableTextureRef slot to ensure that the counter properly reflects how
+/// many compositables are using the texture. If a compositable needs to hold
+/// two references to a given texture (for example to have a pointer to the
+/// current texture in a list of textures that may be used), it can hold its
+/// extra references with RefPtr or whichever pointer type makes sense.
+template <typename T>
+class CompositableTextureRef {
+ public:
+ CompositableTextureRef() = default;
+
+ explicit CompositableTextureRef(const CompositableTextureRef& aOther) {
+ *this = aOther;
+ }
+
+ explicit CompositableTextureRef(T* aOther) { *this = aOther; }
+
+ ~CompositableTextureRef() {
+ if (mRef) {
+ mRef->ReleaseCompositableRef();
+ }
+ }
+
+ CompositableTextureRef& operator=(const CompositableTextureRef& aOther) {
+ if (aOther.get()) {
+ aOther->AddCompositableRef();
+ }
+ if (mRef) {
+ mRef->ReleaseCompositableRef();
+ }
+ mRef = aOther.get();
+ return *this;
+ }
+
+ CompositableTextureRef& operator=(T* aOther) {
+ if (aOther) {
+ aOther->AddCompositableRef();
+ }
+ if (mRef) {
+ mRef->ReleaseCompositableRef();
+ }
+ mRef = aOther;
+ return *this;
+ }
+
+ T* get() const { return mRef; }
+ operator T*() const { return mRef; }
+ T* operator->() const { return mRef; }
+ T& operator*() const { return *mRef; }
+
+ private:
+ RefPtr<T> mRef;
+};
+
+typedef CompositableTextureRef<TextureSource> CompositableTextureSourceRef;
+typedef CompositableTextureRef<TextureHost> CompositableTextureHostRef;
+
+/**
+ * Interface for TextureSources that can be updated from a DataSourceSurface.
+ *
+ * All backend should implement at least one DataTextureSource.
+ */
+class DataTextureSource : public TextureSource {
+ public:
+ DataTextureSource() : mOwner(0), mUpdateSerial(0) {}
+
+ const char* Name() const override { return "DataTextureSource"; }
+
+ DataTextureSource* AsDataTextureSource() override { return this; }
+
+ /**
+ * Upload a (portion of) surface to the TextureSource.
+ *
+ * The DataTextureSource doesn't own aSurface, although it owns and manage
+ * the device texture it uploads to internally.
+ */
+ virtual bool Update(gfx::DataSourceSurface* aSurface,
+ nsIntRegion* aDestRegion = nullptr,
+ gfx::IntPoint* aSrcOffset = nullptr,
+ gfx::IntPoint* aDstOffset = nullptr) = 0;
+
+ /**
+ * A facility to avoid reuploading when it is not necessary.
+ * The caller of Update can use GetUpdateSerial to see if the number has
+ * changed since last update, and call SetUpdateSerial after each successful
+ * update. The caller is responsible for managing the update serial except
+ * when the texture data is deallocated in which case the TextureSource should
+ * always reset the update serial to zero.
+ */
+ uint32_t GetUpdateSerial() const { return mUpdateSerial; }
+ void SetUpdateSerial(uint32_t aValue) { mUpdateSerial = aValue; }
+
+ // By default at least set the update serial to zero.
+ // overloaded versions should do that too.
+ void DeallocateDeviceData() override { SetUpdateSerial(0); }
+
+#ifdef DEBUG
+ /**
+ * Provide read access to the data as a DataSourceSurface.
+ *
+ * This is expected to be very slow and should be used for mostly debugging.
+ * XXX - implement everywhere and make it pure virtual.
+ */
+ virtual already_AddRefed<gfx::DataSourceSurface> ReadBack() {
+ return nullptr;
+ };
+#endif
+
+ void SetOwner(TextureHost* aOwner) {
+ auto newOwner = (uintptr_t)aOwner;
+ if (newOwner != mOwner) {
+ mOwner = newOwner;
+ SetUpdateSerial(0);
+ }
+ }
+
+ bool IsOwnedBy(TextureHost* aOwner) const {
+ return mOwner == (uintptr_t)aOwner;
+ }
+
+ bool HasOwner() const { return !IsOwnedBy(nullptr); }
+
+ private:
+ // We store mOwner as an integer rather than as a pointer to make it clear
+ // it is not intended to be dereferenced.
+ uintptr_t mOwner;
+ uint32_t mUpdateSerial;
+};
+
+enum class TextureHostType : int8_t {
+ Unknown = 0,
+ Buffer,
+ DXGI,
+ DXGIYCbCr,
+ DcompSurface,
+ DMABUF,
+ MacIOSurface,
+ AndroidSurfaceTexture,
+ AndroidHardwareBuffer,
+ EGLImage,
+ GLTexture,
+ Last
+};
+
+/**
+ * TextureHost is a thin abstraction over texture data that need to be shared
+ * between the content process and the compositor process. It is the
+ * compositor-side half of a TextureClient/TextureHost pair. A corresponding
+ * TextureClient lives on the content-side.
+ *
+ * TextureHost only knows how to deserialize or synchronize generic image data
+ * (SurfaceDescriptor) and provide access to one or more TextureSource objects
+ * (these provide the necessary APIs for compositor backends to composite the
+ * image).
+ *
+ * A TextureHost implementation corresponds to one SurfaceDescriptor type, as
+ * opposed to TextureSource that corresponds to device textures.
+ * This means that for YCbCr planes, even though they are represented as
+ * 3 textures internally (3 TextureSources), we use 1 TextureHost and not 3,
+ * because the 3 planes are stored in the same buffer of shared memory, before
+ * they are uploaded separately.
+ *
+ * There is always one and only one TextureHost per TextureClient, and the
+ * TextureClient/Host pair only owns one buffer of image data through its
+ * lifetime. This means that the lifetime of the underlying shared data
+ * matches the lifetime of the TextureClient/Host pair. It also means
+ * TextureClient/Host do not implement double buffering, which is the
+ * reponsibility of the compositable (which would use two Texture pairs).
+ *
+ * The Lock/Unlock mecanism here mirrors Lock/Unlock in TextureClient.
+ *
+ */
+class TextureHost : public AtomicRefCountedWithFinalize<TextureHost> {
+ /**
+ * Called once, just before the destructor.
+ *
+ * Here goes the shut-down code that uses virtual methods.
+ * Must only be called by Release().
+ */
+ void Finalize();
+
+ friend class AtomicRefCountedWithFinalize<TextureHost>;
+
+ public:
+ TextureHost(TextureHostType aType, TextureFlags aFlags);
+
+ protected:
+ virtual ~TextureHost();
+
+ public:
+ /**
+ * Factory method.
+ */
+ static already_AddRefed<TextureHost> Create(
+ const SurfaceDescriptor& aDesc, ReadLockDescriptor&& aReadLock,
+ HostIPCAllocator* aDeallocator, LayersBackend aBackend,
+ TextureFlags aFlags, wr::MaybeExternalImageId& aExternalImageId);
+
+ /**
+ * Lock the texture host for compositing without using compositor.
+ */
+ virtual bool LockWithoutCompositor() { return true; }
+ /**
+ * Similar to Unlock(), but it should be called with LockWithoutCompositor().
+ */
+ virtual void UnlockWithoutCompositor() {}
+
+ /**
+ * Note that the texture host format can be different from its corresponding
+ * texture source's. For example a ShmemTextureHost can have the ycbcr
+ * format and produce 3 "alpha" textures sources.
+ */
+ virtual gfx::SurfaceFormat GetFormat() const = 0;
+ /**
+ * Return the format used for reading the texture.
+ * Apple's YCBCR_422 is R8G8B8X8.
+ */
+ virtual gfx::SurfaceFormat GetReadFormat() const { return GetFormat(); }
+
+ virtual gfx::YUVColorSpace GetYUVColorSpace() const {
+ return gfx::YUVColorSpace::Identity;
+ }
+
+ /**
+ * Return the color depth of the image. Used with YUV textures.
+ */
+ virtual gfx::ColorDepth GetColorDepth() const {
+ return gfx::ColorDepth::COLOR_8;
+ }
+
+ /**
+ * Return true if using full range values (0-255 if 8 bits YUV). Used with YUV
+ * textures.
+ */
+ virtual gfx::ColorRange GetColorRange() const {
+ return gfx::ColorRange::LIMITED;
+ }
+
+ /**
+ * Called when another TextureHost will take over.
+ */
+ virtual void UnbindTextureSource();
+
+ virtual bool IsValid() { return true; }
+
+ /**
+ * Should be overridden in order to deallocate the data that is associated
+ * with the rendering backend, such as GL textures.
+ */
+ virtual void DeallocateDeviceData() {}
+
+ /**
+ * Should be overridden in order to deallocate the data that is shared with
+ * the content side, such as shared memory.
+ */
+ virtual void DeallocateSharedData() {}
+
+ /**
+ * Should be overridden in order to force the TextureHost to drop all
+ * references to it's shared data.
+ *
+ * This is important to ensure the correctness of the deallocation protocol.
+ */
+ virtual void ForgetSharedData() {}
+
+ virtual gfx::IntSize GetSize() const = 0;
+
+ /**
+ * Should be overridden if TextureHost supports crop rect.
+ */
+ virtual void SetCropRect(nsIntRect aCropRect) {}
+
+ /**
+ * Debug facility.
+ * XXX - cool kids use Moz2D. See bug 882113.
+ */
+ virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() = 0;
+
+ /**
+ * XXX - Flags should only be set at creation time, this will be removed.
+ */
+ void SetFlags(TextureFlags aFlags) { mFlags = aFlags; }
+
+ /**
+ * XXX - Flags should only be set at creation time, this will be removed.
+ */
+ void AddFlag(TextureFlags aFlag) { mFlags |= aFlag; }
+
+ TextureFlags GetFlags() { return mFlags; }
+
+ wr::MaybeExternalImageId GetMaybeExternalImageId() const {
+ return mExternalImageId;
+ }
+
+ /**
+ * Allocate and deallocate a TextureParent actor.
+ *
+ * TextureParent< is an implementation detail of TextureHost that is not
+ * exposed to the rest of the code base. CreateIPDLActor and DestroyIPDLActor
+ * are for use with the managing IPDL protocols only (so that they can
+ * implement AllocPTextureParent and DeallocPTextureParent).
+ */
+ static PTextureParent* CreateIPDLActor(
+ HostIPCAllocator* aAllocator, const SurfaceDescriptor& aSharedData,
+ ReadLockDescriptor&& aDescriptor, LayersBackend aLayersBackend,
+ TextureFlags aFlags, const dom::ContentParentId& aContentId,
+ uint64_t aSerial, const wr::MaybeExternalImageId& aExternalImageId);
+ static bool DestroyIPDLActor(PTextureParent* actor);
+
+ /**
+ * Destroy the TextureChild/Parent pair.
+ */
+ static bool SendDeleteIPDLActor(PTextureParent* actor);
+
+ static void ReceivedDestroy(PTextureParent* actor);
+
+ /**
+ * Get the TextureHost corresponding to the actor passed in parameter.
+ */
+ static TextureHost* AsTextureHost(PTextureParent* actor);
+
+ static uint64_t GetTextureSerial(PTextureParent* actor);
+
+ static dom::ContentParentId GetTextureContentId(PTextureParent* actor);
+
+ /**
+ * Return a pointer to the IPDLActor.
+ *
+ * This is to be used with IPDL messages only. Do not store the returned
+ * pointer.
+ */
+ PTextureParent* GetIPDLActor();
+
+ // If a texture host holds a reference to shmem, it should override this
+ // method to forget about the shmem _without_ releasing it.
+ virtual void OnShutdown() {}
+
+ // Forget buffer actor. Used only for hacky fix for bug 966446.
+ virtual void ForgetBufferActor() {}
+
+ virtual const char* Name() { return "TextureHost"; }
+
+ /**
+ * Returns true if the TextureHost can be released before the rendering is
+ * completed, otherwise returns false.
+ */
+ virtual bool NeedsDeferredDeletion() const { return true; }
+
+ void AddCompositableRef() {
+ ++mCompositableCount;
+ if (mCompositableCount == 1) {
+ PrepareForUse();
+ }
+ }
+
+ void ReleaseCompositableRef() {
+ --mCompositableCount;
+ MOZ_ASSERT(mCompositableCount >= 0);
+ if (mCompositableCount == 0) {
+ UnbindTextureSource();
+ // Send mFwdTransactionId to client side if necessary.
+ NotifyNotUsed();
+ }
+ }
+
+ int NumCompositableRefs() const { return mCompositableCount; }
+
+ void SetLastFwdTransactionId(uint64_t aTransactionId);
+
+ void DeserializeReadLock(ReadLockDescriptor&& aDesc,
+ ISurfaceAllocator* aAllocator);
+ void SetReadLocked();
+
+ TextureReadLock* GetReadLock() { return mReadLock; }
+
+ virtual BufferTextureHost* AsBufferTextureHost() { return nullptr; }
+ virtual ShmemTextureHost* AsShmemTextureHost() { return nullptr; }
+ virtual MacIOSurfaceTextureHostOGL* AsMacIOSurfaceTextureHost() {
+ return nullptr;
+ }
+ virtual WebRenderTextureHost* AsWebRenderTextureHost() { return nullptr; }
+ virtual SurfaceTextureHost* AsSurfaceTextureHost() { return nullptr; }
+ virtual AndroidHardwareBufferTextureHost*
+ AsAndroidHardwareBufferTextureHost() {
+ return nullptr;
+ }
+ virtual RemoteTextureHostWrapper* AsRemoteTextureHostWrapper() {
+ return nullptr;
+ }
+
+ virtual TextureHostWrapperD3D11* AsTextureHostWrapperD3D11() {
+ return nullptr;
+ }
+
+ virtual bool IsWrappingSurfaceTextureHost() { return false; }
+
+ // Create the corresponding RenderTextureHost type of this texture, and
+ // register the RenderTextureHost into render thread.
+ virtual void CreateRenderTexture(
+ const wr::ExternalImageId& aExternalImageId) {
+ MOZ_RELEASE_ASSERT(
+ false,
+ "No CreateRenderTexture() implementation for this TextureHost type.");
+ }
+
+ void EnsureRenderTexture(const wr::MaybeExternalImageId& aExternalImageId);
+
+ // Destroy RenderTextureHost when it was created by the TextureHost.
+ // It is called in TextureHost::Finalize().
+ virtual void MaybeDestroyRenderTexture();
+
+ static void DestroyRenderTexture(const wr::ExternalImageId& aExternalImageId);
+
+ /// Returns the number of actual textures that will be used to render this.
+ /// For example in a lot of YUV cases it will be 3
+ virtual uint32_t NumSubTextures() { return 1; }
+
+ enum ResourceUpdateOp {
+ ADD_IMAGE,
+ UPDATE_IMAGE,
+ };
+
+ // Add all necessary TextureHost informations to the resource update queue.
+ virtual void PushResourceUpdates(wr::TransactionBuilder& aResources,
+ ResourceUpdateOp aOp,
+ const Range<wr::ImageKey>& aImageKeys,
+ const wr::ExternalImageId& aExtID) {
+ MOZ_ASSERT_UNREACHABLE("Unimplemented");
+ }
+
+ enum class PushDisplayItemFlag {
+ // Passed if the caller wants these display items to be promoted
+ // to compositor surfaces if possible.
+ PREFER_COMPOSITOR_SURFACE,
+
+ // Passed in the RenderCompositor supports BufferTextureHosts
+ // being used directly as external compositor surfaces.
+ SUPPORTS_EXTERNAL_BUFFER_TEXTURES,
+ };
+ using PushDisplayItemFlagSet = EnumSet<PushDisplayItemFlag>;
+
+ // Put all necessary WR commands into DisplayListBuilder for this textureHost
+ // rendering.
+ virtual void PushDisplayItems(wr::DisplayListBuilder& aBuilder,
+ const wr::LayoutRect& aBounds,
+ const wr::LayoutRect& aClip,
+ wr::ImageRendering aFilter,
+ const Range<wr::ImageKey>& aKeys,
+ PushDisplayItemFlagSet aFlags) {
+ MOZ_ASSERT_UNREACHABLE(
+ "No PushDisplayItems() implementation for this TextureHost type.");
+ }
+
+ /**
+ * Some API's can use the cross-process IOSurface directly, such as OpenVR
+ */
+ virtual MacIOSurface* GetMacIOSurface() { return nullptr; }
+
+ virtual bool NeedsYFlip() const;
+
+ virtual void SetAcquireFence(mozilla::ipc::FileDescriptor&& aFenceFd) {}
+
+ virtual void SetReleaseFence(mozilla::ipc::FileDescriptor&& aFenceFd) {}
+
+ virtual mozilla::ipc::FileDescriptor GetAndResetReleaseFence() {
+ return mozilla::ipc::FileDescriptor();
+ }
+
+ virtual AndroidHardwareBuffer* GetAndroidHardwareBuffer() const {
+ return nullptr;
+ }
+
+ virtual bool SupportsExternalCompositing(WebRenderBackend aBackend) {
+ return false;
+ }
+
+ virtual TextureHostType GetTextureHostType() { return mTextureHostType; }
+
+ // Our WebRender backend may impose restrictions on whether textures are
+ // prepared as native textures or not, or it may have no restriction at
+ // all. This enumerates those possibilities.
+ enum NativeTexturePolicy {
+ REQUIRE,
+ FORBID,
+ DONT_CARE,
+ };
+
+ static NativeTexturePolicy BackendNativeTexturePolicy(
+ layers::WebRenderBackend aBackend, gfx::IntSize aSize) {
+ static const int32_t SWGL_DIMENSION_MAX = 1 << 15;
+ if (aBackend == WebRenderBackend::SOFTWARE) {
+ return (aSize.width <= SWGL_DIMENSION_MAX &&
+ aSize.height <= SWGL_DIMENSION_MAX)
+ ? REQUIRE
+ : FORBID;
+ }
+ return DONT_CARE;
+ }
+
+ void SetDestroyedCallback(std::function<void()>&& aDestroyedCallback) {
+ MOZ_ASSERT(!mDestroyedCallback);
+ mDestroyedCallback = std::move(aDestroyedCallback);
+ }
+
+ protected:
+ virtual void ReadUnlock();
+
+ void RecycleTexture(TextureFlags aFlags);
+
+ /**
+ * Called when mCompositableCount becomes from 0 to 1.
+ */
+ virtual void PrepareForUse();
+
+ /**
+ * Called when mCompositableCount becomes 0.
+ */
+ virtual void NotifyNotUsed();
+
+ // for Compositor.
+ void CallNotifyNotUsed();
+
+ TextureHostType mTextureHostType;
+ PTextureParent* mActor;
+ RefPtr<TextureReadLock> mReadLock;
+ TextureFlags mFlags;
+ int mCompositableCount;
+ uint64_t mFwdTransactionId;
+ bool mReadLocked;
+ wr::MaybeExternalImageId mExternalImageId;
+
+ std::function<void()> mDestroyedCallback;
+
+ friend class Compositor;
+ friend class RemoteTextureHostWrapper;
+ friend class TextureParent;
+ friend class TextureSourceProvider;
+ friend class GPUVideoTextureHost;
+ friend class WebRenderTextureHost;
+ friend class TextureHostWrapperD3D11;
+};
+
+/**
+ * TextureHost that wraps a random access buffer such as a Shmem or some raw
+ * memory.
+ *
+ * This TextureHost is backend-independent and the backend-specific bits are
+ * in the TextureSource.
+ * This class must be inherited to implement GetBuffer and DeallocSharedData
+ * (see ShmemTextureHost and MemoryTextureHost)
+ *
+ * Uploads happen when Lock is called.
+ *
+ * BufferTextureHost supports YCbCr and flavours of RGBA images (RGBX, A, etc.).
+ */
+class BufferTextureHost : public TextureHost {
+ public:
+ BufferTextureHost(const BufferDescriptor& aDescriptor, TextureFlags aFlags);
+
+ virtual ~BufferTextureHost();
+
+ virtual uint8_t* GetBuffer() = 0;
+
+ virtual size_t GetBufferSize() = 0;
+
+ void UnbindTextureSource() override;
+
+ void DeallocateDeviceData() override;
+
+ /**
+ * Return the format that is exposed to the compositor when calling
+ * BindTextureSource.
+ *
+ * If the shared format is YCbCr and the compositor does not support it,
+ * GetFormat will be RGB32 (even though mFormat is SurfaceFormat::YUV).
+ */
+ gfx::SurfaceFormat GetFormat() const override;
+
+ gfx::YUVColorSpace GetYUVColorSpace() const override;
+
+ gfx::ColorDepth GetColorDepth() const override;
+
+ gfx::ColorRange GetColorRange() const override;
+
+ gfx::ChromaSubsampling GetChromaSubsampling() const;
+
+ gfx::IntSize GetSize() const override { return mSize; }
+
+ already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override;
+
+ bool NeedsDeferredDeletion() const override {
+ return TextureHost::NeedsDeferredDeletion() || UseExternalTextures();
+ }
+
+ BufferTextureHost* AsBufferTextureHost() override { return this; }
+
+ const BufferDescriptor& GetBufferDescriptor() const { return mDescriptor; }
+
+ void CreateRenderTexture(
+ const wr::ExternalImageId& aExternalImageId) override;
+
+ uint32_t NumSubTextures() override;
+
+ void PushResourceUpdates(wr::TransactionBuilder& aResources,
+ ResourceUpdateOp aOp,
+ const Range<wr::ImageKey>& aImageKeys,
+ const wr::ExternalImageId& aExtID) override;
+
+ void PushDisplayItems(wr::DisplayListBuilder& aBuilder,
+ const wr::LayoutRect& aBounds,
+ const wr::LayoutRect& aClip, wr::ImageRendering aFilter,
+ const Range<wr::ImageKey>& aImageKeys,
+ PushDisplayItemFlagSet aFlags) override;
+
+ uint8_t* GetYChannel();
+ uint8_t* GetCbChannel();
+ uint8_t* GetCrChannel();
+ int32_t GetYStride() const;
+ int32_t GetCbCrStride() const;
+
+ protected:
+ bool UseExternalTextures() const { return mUseExternalTextures; }
+
+ BufferDescriptor mDescriptor;
+ RefPtr<Compositor> mCompositor;
+ gfx::IntSize mSize;
+ gfx::SurfaceFormat mFormat;
+ bool mLocked;
+ bool mUseExternalTextures;
+
+ class DataTextureSourceYCbCrBasic;
+};
+
+/**
+ * TextureHost that wraps shared memory.
+ * the corresponding texture on the client side is ShmemTextureClient.
+ * This TextureHost is backend-independent.
+ */
+class ShmemTextureHost : public BufferTextureHost {
+ public:
+ ShmemTextureHost(const mozilla::ipc::Shmem& aShmem,
+ const BufferDescriptor& aDesc,
+ ISurfaceAllocator* aDeallocator, TextureFlags aFlags);
+
+ protected:
+ ~ShmemTextureHost();
+
+ public:
+ void DeallocateSharedData() override;
+
+ void ForgetSharedData() override;
+
+ uint8_t* GetBuffer() override;
+
+ size_t GetBufferSize() override;
+
+ const char* Name() override { return "ShmemTextureHost"; }
+
+ void OnShutdown() override;
+
+ ShmemTextureHost* AsShmemTextureHost() override { return this; }
+
+ protected:
+ UniquePtr<mozilla::ipc::Shmem> mShmem;
+ RefPtr<ISurfaceAllocator> mDeallocator;
+};
+
+/**
+ * TextureHost that wraps raw memory.
+ * The corresponding texture on the client side is MemoryTextureClient.
+ * Can obviously not be used in a cross process setup.
+ * This TextureHost is backend-independent.
+ */
+class MemoryTextureHost : public BufferTextureHost {
+ public:
+ MemoryTextureHost(uint8_t* aBuffer, const BufferDescriptor& aDesc,
+ TextureFlags aFlags);
+
+ protected:
+ ~MemoryTextureHost();
+
+ public:
+ void DeallocateSharedData() override;
+
+ void ForgetSharedData() override;
+
+ uint8_t* GetBuffer() override;
+
+ size_t GetBufferSize() override;
+
+ const char* Name() override { return "MemoryTextureHost"; }
+
+ protected:
+ uint8_t* mBuffer;
+};
+
+class MOZ_STACK_CLASS AutoLockTextureHostWithoutCompositor {
+ public:
+ explicit AutoLockTextureHostWithoutCompositor(TextureHost* aTexture)
+ : mTexture(aTexture) {
+ mLocked = mTexture ? mTexture->LockWithoutCompositor() : false;
+ }
+
+ ~AutoLockTextureHostWithoutCompositor() {
+ if (mTexture && mLocked) {
+ mTexture->UnlockWithoutCompositor();
+ }
+ }
+
+ bool Failed() { return mTexture && !mLocked; }
+
+ private:
+ RefPtr<TextureHost> mTexture;
+ bool mLocked;
+};
+
+/**
+ * This can be used as an offscreen rendering target by the compositor, and
+ * subsequently can be used as a source by the compositor.
+ */
+class CompositingRenderTarget : public TextureSource {
+ public:
+ explicit CompositingRenderTarget(const gfx::IntPoint& aOrigin)
+ : mClearOnBind(false),
+ mOrigin(aOrigin),
+ mZNear(0),
+ mZFar(0),
+ mHasComplexProjection(false),
+ mEnableDepthBuffer(false) {}
+ virtual ~CompositingRenderTarget() = default;
+
+ const char* Name() const override { return "CompositingRenderTarget"; }
+
+#ifdef MOZ_DUMP_PAINTING
+ virtual already_AddRefed<gfx::DataSourceSurface> Dump(
+ Compositor* aCompositor) {
+ return nullptr;
+ }
+#endif
+
+ /**
+ * Perform a clear when recycling a non opaque surface.
+ * The clear is deferred to when the render target is bound.
+ */
+ void ClearOnBind() { mClearOnBind = true; }
+
+ const gfx::IntPoint& GetOrigin() const { return mOrigin; }
+ gfx::IntRect GetRect() { return gfx::IntRect(GetOrigin(), GetSize()); }
+
+ /**
+ * If a Projection matrix is set, then it is used for rendering to
+ * this render target instead of generating one. If no explicit
+ * projection is set, Compositors are expected to generate an
+ * orthogonal maaping that maps 0..1 to the full size of the render
+ * target.
+ */
+ bool HasComplexProjection() const { return mHasComplexProjection; }
+ void ClearProjection() { mHasComplexProjection = false; }
+ void SetProjection(const gfx::Matrix4x4& aNewMatrix, bool aEnableDepthBuffer,
+ float aZNear, float aZFar) {
+ mProjectionMatrix = aNewMatrix;
+ mEnableDepthBuffer = aEnableDepthBuffer;
+ mZNear = aZNear;
+ mZFar = aZFar;
+ mHasComplexProjection = true;
+ }
+ void GetProjection(gfx::Matrix4x4& aMatrix, bool& aEnableDepth, float& aZNear,
+ float& aZFar) {
+ MOZ_ASSERT(mHasComplexProjection);
+ aMatrix = mProjectionMatrix;
+ aEnableDepth = mEnableDepthBuffer;
+ aZNear = mZNear;
+ aZFar = mZFar;
+ }
+
+ protected:
+ bool mClearOnBind;
+
+ private:
+ gfx::IntPoint mOrigin;
+
+ gfx::Matrix4x4 mProjectionMatrix;
+ float mZNear, mZFar;
+ bool mHasComplexProjection;
+ bool mEnableDepthBuffer;
+};
+
+/**
+ * Creates a TextureHost that can be used with any of the existing backends
+ * Not all SurfaceDescriptor types are supported
+ */
+already_AddRefed<TextureHost> CreateBackendIndependentTextureHost(
+ const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator,
+ LayersBackend aBackend, TextureFlags aFlags);
+
+} // namespace layers
+} // namespace mozilla
+
+#endif