/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- * 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_TEXTURED3D11_H #define MOZILLA_GFX_TEXTURED3D11_H #include "mozilla/gfx/2D.h" #include "mozilla/layers/Compositor.h" #include "mozilla/layers/TextureClient.h" #include "mozilla/layers/TextureHost.h" #include "gfxWindowsPlatform.h" #include "mozilla/GfxMessageUtils.h" #include #include "d3d9.h" #include namespace mozilla { namespace layers { class MOZ_RAII AutoTextureLock { public: AutoTextureLock(IDXGIKeyedMutex* aMutex, HRESULT& aResult, uint32_t aTimeout = 0); ~AutoTextureLock(); private: RefPtr mMutex; HRESULT mResult; }; class CompositorD3D11; class DXGITextureData : public TextureData { public: virtual void FillInfo(TextureData::Info& aInfo) const override; virtual bool Serialize(SurfaceDescriptor& aOutDescrptor) override; static DXGITextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, TextureAllocationFlags aFlags); protected: bool PrepareDrawTargetInLock(OpenMode aMode); DXGITextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, bool aNeedsClear, bool aNeedsClearWhite, bool aIsForOutOfBandContent); virtual void GetDXGIResource(IDXGIResource** aOutResource) = 0; // Hold on to the DrawTarget because it is expensive to create one each ::Lock. RefPtr mDrawTarget; gfx::IntSize mSize; gfx::SurfaceFormat mFormat; bool mNeedsClear; bool mNeedsClearWhite; bool mHasSynchronization; bool mIsForOutOfBandContent; }; class D3D11TextureData : public DXGITextureData { public: // If aDevice is null, use one provided by gfxWindowsPlatform. static DXGITextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, TextureAllocationFlags aAllocFlags, ID3D11Device* aDevice = nullptr); static DXGITextureData* Create(gfx::SourceSurface* aSurface, TextureAllocationFlags aAllocFlags, ID3D11Device* aDevice = nullptr); virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override; virtual bool Lock(OpenMode aMode) override; virtual void Unlock() override; virtual already_AddRefed BorrowDrawTarget() override; virtual TextureData* CreateSimilar(LayersIPCChannel* aAllocator, LayersBackend aLayersBackend, TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const override; virtual void SyncWithObject(SyncObject* aSync) override; ID3D11Texture2D* GetD3D11Texture() { return mTexture; } virtual void Deallocate(LayersIPCChannel* aAllocator) override; D3D11TextureData* AsD3D11TextureData() override { return this; } ~D3D11TextureData(); protected: D3D11TextureData(ID3D11Texture2D* aTexture, gfx::IntSize aSize, gfx::SurfaceFormat aFormat, bool aNeedsClear, bool aNeedsClearWhite, bool aIsForOutOfBandContent); virtual void GetDXGIResource(IDXGIResource** aOutResource) override; static DXGITextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::SourceSurface* aSurface, TextureAllocationFlags aAllocFlags, ID3D11Device* aDevice = nullptr); RefPtr mTexture; }; already_AddRefed CreateD3D11extureClientWithDevice(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags, ID3D11Device* aDevice, LayersIPCChannel* aAllocator); class DXGIYCbCrTextureData : public TextureData { public: static DXGIYCbCrTextureData* Create(TextureFlags aFlags, IUnknown* aTextureY, IUnknown* aTextureCb, IUnknown* aTextureCr, HANDLE aHandleY, HANDLE aHandleCb, HANDLE aHandleCr, const gfx::IntSize& aSize, const gfx::IntSize& aSizeY, const gfx::IntSize& aSizeCbCr); static DXGIYCbCrTextureData* Create(TextureFlags aFlags, ID3D11Texture2D* aTextureCb, ID3D11Texture2D* aTextureY, ID3D11Texture2D* aTextureCr, const gfx::IntSize& aSize, const gfx::IntSize& aSizeY, const gfx::IntSize& aSizeCbCr); virtual bool Lock(OpenMode) override { return true; } virtual void Unlock() override {} virtual void FillInfo(TextureData::Info& aInfo) const override; virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override; virtual already_AddRefed BorrowDrawTarget() override { return nullptr; } virtual void Deallocate(LayersIPCChannel* aAllocator) override; virtual bool UpdateFromSurface(gfx::SourceSurface*) override { return false; } virtual TextureFlags GetTextureFlags() const override { return TextureFlags::DEALLOCATE_MAIN_THREAD; } protected: RefPtr mHoldRefs[3]; HANDLE mHandles[3]; gfx::IntSize mSize; gfx::IntSize mSizeY; gfx::IntSize mSizeCbCr; }; /** * TextureSource that provides with the necessary APIs to be composited by a * CompositorD3D11. */ class TextureSourceD3D11 { public: TextureSourceD3D11() : mFormatOverride(DXGI_FORMAT_UNKNOWN) {} virtual ~TextureSourceD3D11() {} virtual ID3D11Texture2D* GetD3D11Texture() const { return mTexture; } virtual ID3D11ShaderResourceView* GetShaderResourceView(); protected: virtual gfx::IntSize GetSize() const { return mSize; } gfx::IntSize mSize; RefPtr mTexture; RefPtr mSRV; DXGI_FORMAT mFormatOverride; }; /** * A TextureSource that implements the DataTextureSource interface. * it can be used without a TextureHost and is able to upload texture data * from a gfx::DataSourceSurface. */ class DataTextureSourceD3D11 : public DataTextureSource , public TextureSourceD3D11 , public BigImageIterator { public: /// Constructor allowing the texture to perform texture uploads. /// /// The texture can be used as an actual DataTextureSource. DataTextureSourceD3D11(gfx::SurfaceFormat aFormat, CompositorD3D11* aCompositor, TextureFlags aFlags); /// Constructor for textures created around DXGI shared handles, disallowing /// texture uploads. /// /// The texture CANNOT be used as a DataTextureSource. DataTextureSourceD3D11(gfx::SurfaceFormat aFormat, CompositorD3D11* aCompositor, ID3D11Texture2D* aTexture); virtual ~DataTextureSourceD3D11(); virtual const char* Name() const override { return "DataTextureSourceD3D11"; } // DataTextureSource virtual bool Update(gfx::DataSourceSurface* aSurface, nsIntRegion* aDestRegion = nullptr, gfx::IntPoint* aSrcOffset = nullptr) override; // TextureSource virtual TextureSourceD3D11* AsSourceD3D11() override { return this; } virtual ID3D11Texture2D* GetD3D11Texture() const override; virtual ID3D11ShaderResourceView* GetShaderResourceView() override; // Returns nullptr if this texture was created by a DXGI TextureHost. virtual DataTextureSource* AsDataTextureSource() override { return mAllowTextureUploads ? this : false; } virtual void DeallocateDeviceData() override { mTexture = nullptr; } virtual gfx::IntSize GetSize() const override { return mSize; } virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; } virtual void SetCompositor(Compositor* aCompositor) override; // BigImageIterator virtual BigImageIterator* AsBigImageIterator() override { return mIsTiled ? this : nullptr; } virtual size_t GetTileCount() override { return mTileTextures.size(); } virtual bool NextTile() override { return (++mCurrentTile < mTileTextures.size()); } virtual gfx::IntRect GetTileRect() override; virtual void EndBigImageIteration() override { mIterating = false; } virtual void BeginBigImageIteration() override { mIterating = true; mCurrentTile = 0; } protected: gfx::IntRect GetTileRect(uint32_t aIndex) const; void Reset(); std::vector< RefPtr > mTileTextures; std::vector< RefPtr > mTileSRVs; RefPtr mCompositor; gfx::SurfaceFormat mFormat; TextureFlags mFlags; uint32_t mCurrentTile; bool mIsTiled; bool mIterating; // Sadly, the code was originally organized so that this class is used both in // the cases where we want to perform texture uploads through the DataTextureSource // interface, and the cases where we wrap the texture around an existing DXGI // handle in which case we should not use it as a DataTextureSource. // This member differentiates the two scenarios. When it is false the texture // "pretends" to not be a DataTextureSource. bool mAllowTextureUploads; }; already_AddRefed CreateD3D11TextureClientWithDevice(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags, ID3D11Device* aDevice, LayersIPCChannel* aAllocator); /** * A TextureHost for shared D3D11 textures. */ class DXGITextureHostD3D11 : public TextureHost { public: DXGITextureHostD3D11(TextureFlags aFlags, const SurfaceDescriptorD3D10& aDescriptor); virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override; virtual void DeallocateDeviceData() override {} virtual void SetCompositor(Compositor* aCompositor) override; virtual Compositor* GetCompositor() override; virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; } virtual bool Lock() override; virtual void Unlock() override; virtual bool LockWithoutCompositor() override; virtual void UnlockWithoutCompositor() override; virtual gfx::IntSize GetSize() const override { return mSize; } virtual already_AddRefed GetAsSurface() override { return nullptr; } protected: bool LockInternal(); void UnlockInternal(); RefPtr GetDevice(); bool OpenSharedHandle(); RefPtr mTexture; RefPtr mTextureSource; RefPtr mCompositor; gfx::IntSize mSize; WindowsHandle mHandle; gfx::SurfaceFormat mFormat; bool mIsLocked; }; class DXGIYCbCrTextureHostD3D11 : public TextureHost { public: DXGIYCbCrTextureHostD3D11(TextureFlags aFlags, const SurfaceDescriptorDXGIYCbCr& aDescriptor); virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override; virtual void DeallocateDeviceData() override{} virtual void SetCompositor(Compositor* aCompositor) override; virtual Compositor* GetCompositor() override; virtual gfx::SurfaceFormat GetFormat() const override{ return gfx::SurfaceFormat::YUV; } // Bug 1305906 fixes YUVColorSpace handling virtual YUVColorSpace GetYUVColorSpace() const override { return YUVColorSpace::BT601; } virtual bool Lock() override; virtual void Unlock() override; virtual gfx::IntSize GetSize() const override { return mSize; } virtual already_AddRefed GetAsSurface() override { return nullptr; } protected: RefPtr GetDevice(); bool OpenSharedHandle(); RefPtr mTextures[3]; RefPtr mTextureSources[3]; RefPtr mCompositor; gfx::IntSize mSize; WindowsHandle mHandles[3]; bool mIsLocked; }; class CompositingRenderTargetD3D11 : public CompositingRenderTarget, public TextureSourceD3D11 { public: CompositingRenderTargetD3D11(ID3D11Texture2D* aTexture, const gfx::IntPoint& aOrigin, DXGI_FORMAT aFormatOverride = DXGI_FORMAT_UNKNOWN); virtual const char* Name() const override { return "CompositingRenderTargetD3D11"; } virtual TextureSourceD3D11* AsSourceD3D11() override { return this; } void BindRenderTarget(ID3D11DeviceContext* aContext); virtual gfx::IntSize GetSize() const override; void SetSize(const gfx::IntSize& aSize) { mSize = aSize; } private: friend class CompositorD3D11; RefPtr mRTView; }; class SyncObjectD3D11 : public SyncObject { public: SyncObjectD3D11(SyncHandle aSyncHandle); virtual void FinalizeFrame(); virtual bool IsSyncObjectValid(); virtual SyncType GetSyncType() { return SyncType::D3D11; } void RegisterTexture(ID3D11Texture2D* aTexture); private: RefPtr mD3D11Texture; RefPtr mD3D11Device; std::vector mD3D11SyncedTextures; SyncHandle mHandle; }; inline uint32_t GetMaxTextureSizeForFeatureLevel(D3D_FEATURE_LEVEL aFeatureLevel) { int32_t maxTextureSize; switch (aFeatureLevel) { case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: maxTextureSize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; break; case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: maxTextureSize = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; break; case D3D_FEATURE_LEVEL_9_3: maxTextureSize = D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; break; default: maxTextureSize = D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; } return maxTextureSize; } } } #endif /* MOZILLA_GFX_TEXTURED3D11_H */