diff options
Diffstat (limited to 'gfx/layers/d3d11/TextureD3D11.h')
-rw-r--r-- | gfx/layers/d3d11/TextureD3D11.h | 455 |
1 files changed, 455 insertions, 0 deletions
diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h new file mode 100644 index 000000000..831342aa2 --- /dev/null +++ b/gfx/layers/d3d11/TextureD3D11.h @@ -0,0 +1,455 @@ +/* -*- 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 <d3d11.h> +#include "d3d9.h" +#include <vector> + +namespace mozilla { +namespace layers { + +class MOZ_RAII AutoTextureLock +{ +public: + AutoTextureLock(IDXGIKeyedMutex* aMutex, HRESULT& aResult, + uint32_t aTimeout = 0); + ~AutoTextureLock(); + +private: + RefPtr<IDXGIKeyedMutex> 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<gfx::DrawTarget> 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<gfx::DrawTarget> 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<ID3D11Texture2D> mTexture; +}; + +already_AddRefed<TextureClient> +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<gfx::DrawTarget> 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<IUnknown> 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<ID3D11Texture2D> mTexture; + RefPtr<ID3D11ShaderResourceView> 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<ID3D11Texture2D> > mTileTextures; + std::vector< RefPtr<ID3D11ShaderResourceView> > mTileSRVs; + RefPtr<CompositorD3D11> 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<TextureClient> +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<gfx::DataSourceSurface> GetAsSurface() override + { + return nullptr; + } + +protected: + bool LockInternal(); + void UnlockInternal(); + + RefPtr<ID3D11Device> GetDevice(); + + bool OpenSharedHandle(); + + RefPtr<ID3D11Texture2D> mTexture; + RefPtr<DataTextureSourceD3D11> mTextureSource; + RefPtr<CompositorD3D11> 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<gfx::DataSourceSurface> GetAsSurface() override + { + return nullptr; + } + +protected: + RefPtr<ID3D11Device> GetDevice(); + + bool OpenSharedHandle(); + + RefPtr<ID3D11Texture2D> mTextures[3]; + RefPtr<DataTextureSourceD3D11> mTextureSources[3]; + + RefPtr<CompositorD3D11> 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<ID3D11RenderTargetView> 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<ID3D11Texture2D> mD3D11Texture; + RefPtr<ID3D11Device> mD3D11Device; + std::vector<ID3D11Texture2D*> 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 */ |