michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef MOZILLA_GFX_TEXTURED3D9_H michael@0: #define MOZILLA_GFX_TEXTURED3D9_H michael@0: michael@0: #include "mozilla/layers/Compositor.h" michael@0: #include "mozilla/layers/TextureClient.h" michael@0: #include "mozilla/layers/TextureHost.h" michael@0: #include "mozilla/GfxMessageUtils.h" michael@0: #include "gfxWindowsPlatform.h" michael@0: #include "d3d9.h" michael@0: #include michael@0: #include "DeviceManagerD3D9.h" michael@0: michael@0: namespace mozilla { michael@0: namespace gfxs { michael@0: class DrawTarget; michael@0: } michael@0: } michael@0: michael@0: namespace mozilla { michael@0: namespace layers { michael@0: michael@0: class CompositorD3D9; michael@0: michael@0: class TextureSourceD3D9 michael@0: { michael@0: friend class DeviceManagerD3D9; michael@0: michael@0: public: michael@0: TextureSourceD3D9() michael@0: : mPreviousHost(nullptr) michael@0: , mNextHost(nullptr) michael@0: , mCreatingDeviceManager(nullptr) michael@0: {} michael@0: virtual ~TextureSourceD3D9(); michael@0: michael@0: virtual IDirect3DTexture9* GetD3D9Texture() { return mTexture; } michael@0: michael@0: StereoMode GetStereoMode() const { return mStereoMode; }; michael@0: michael@0: // Release all texture memory resources held by the texture host. michael@0: virtual void ReleaseTextureResources() michael@0: { michael@0: mTexture = nullptr; michael@0: } michael@0: michael@0: protected: michael@0: virtual gfx::IntSize GetSize() const { return mSize; } michael@0: void SetSize(const gfx::IntSize& aSize) { mSize = aSize; } michael@0: michael@0: // Helper methods for creating and copying textures. michael@0: TemporaryRef InitTextures( michael@0: DeviceManagerD3D9* aDeviceManager, michael@0: const gfx::IntSize &aSize, michael@0: _D3DFORMAT aFormat, michael@0: RefPtr& aSurface, michael@0: D3DLOCKED_RECT& aLockedRect); michael@0: michael@0: TemporaryRef DataToTexture( michael@0: DeviceManagerD3D9* aDeviceManager, michael@0: unsigned char *aData, michael@0: int aStride, michael@0: const gfx::IntSize &aSize, michael@0: _D3DFORMAT aFormat, michael@0: uint32_t aBPP); michael@0: michael@0: // aTexture should be in SYSTEMMEM, returns a texture in the default michael@0: // pool (that is, in video memory). michael@0: TemporaryRef TextureToTexture( michael@0: DeviceManagerD3D9* aDeviceManager, michael@0: IDirect3DTexture9* aTexture, michael@0: const gfx::IntSize& aSize, michael@0: _D3DFORMAT aFormat); michael@0: michael@0: TemporaryRef SurfaceToTexture( michael@0: DeviceManagerD3D9* aDeviceManager, michael@0: gfxWindowsSurface* aSurface, michael@0: const gfx::IntSize& aSize, michael@0: _D3DFORMAT aFormat); michael@0: michael@0: gfx::IntSize mSize; michael@0: michael@0: // Linked list of all objects holding d3d9 textures. michael@0: TextureSourceD3D9* mPreviousHost; michael@0: TextureSourceD3D9* mNextHost; michael@0: // The device manager that created our textures. michael@0: DeviceManagerD3D9* mCreatingDeviceManager; michael@0: michael@0: StereoMode mStereoMode; michael@0: RefPtr mTexture; michael@0: }; michael@0: michael@0: /** michael@0: * A TextureSource that implements the DataTextureSource interface. michael@0: * it can be used without a TextureHost and is able to upload texture data michael@0: * from a gfx::DataSourceSurface. michael@0: */ michael@0: class DataTextureSourceD3D9 : public DataTextureSource michael@0: , public TextureSourceD3D9 michael@0: , public TileIterator michael@0: { michael@0: public: michael@0: DataTextureSourceD3D9(gfx::SurfaceFormat aFormat, michael@0: CompositorD3D9* aCompositor, michael@0: TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT, michael@0: StereoMode aStereoMode = StereoMode::MONO); michael@0: michael@0: DataTextureSourceD3D9(gfx::SurfaceFormat aFormat, michael@0: gfx::IntSize aSize, michael@0: CompositorD3D9* aCompositor, michael@0: IDirect3DTexture9* aTexture, michael@0: TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT); michael@0: michael@0: virtual ~DataTextureSourceD3D9(); michael@0: michael@0: // DataTextureSource michael@0: michael@0: virtual bool Update(gfx::DataSourceSurface* aSurface, michael@0: nsIntRegion* aDestRegion = nullptr, michael@0: gfx::IntPoint* aSrcOffset = nullptr) MOZ_OVERRIDE; michael@0: michael@0: // TextureSource michael@0: michael@0: virtual TextureSourceD3D9* AsSourceD3D9() MOZ_OVERRIDE { return this; } michael@0: michael@0: virtual IDirect3DTexture9* GetD3D9Texture() MOZ_OVERRIDE; michael@0: michael@0: virtual DataTextureSource* AsDataTextureSource() MOZ_OVERRIDE { return this; } michael@0: michael@0: virtual void DeallocateDeviceData() MOZ_OVERRIDE { mTexture = nullptr; } michael@0: michael@0: virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; } michael@0: michael@0: virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; } michael@0: michael@0: virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; michael@0: michael@0: // TileIterator michael@0: michael@0: virtual TileIterator* AsTileIterator() MOZ_OVERRIDE { return mIsTiled ? this : nullptr; } michael@0: michael@0: virtual size_t GetTileCount() MOZ_OVERRIDE { return mTileTextures.size(); } michael@0: michael@0: virtual bool NextTile() MOZ_OVERRIDE { return (++mCurrentTile < mTileTextures.size()); } michael@0: michael@0: virtual nsIntRect GetTileRect() MOZ_OVERRIDE; michael@0: michael@0: virtual void EndTileIteration() MOZ_OVERRIDE { mIterating = false; } michael@0: michael@0: virtual void BeginTileIteration() MOZ_OVERRIDE michael@0: { michael@0: mIterating = true; michael@0: mCurrentTile = 0; michael@0: } michael@0: michael@0: /** michael@0: * Copy the content of aTexture using the GPU. michael@0: */ michael@0: bool UpdateFromTexture(IDirect3DTexture9* aTexture, const nsIntRegion* aRegion); michael@0: michael@0: // To use with DIBTextureHostD3D9 michael@0: michael@0: bool Update(gfxWindowsSurface* aSurface); michael@0: michael@0: protected: michael@0: gfx::IntRect GetTileRect(uint32_t aTileIndex) const; michael@0: michael@0: void Reset(); michael@0: michael@0: std::vector< RefPtr > mTileTextures; michael@0: RefPtr mCompositor; michael@0: gfx::SurfaceFormat mFormat; michael@0: uint32_t mCurrentTile; michael@0: TextureFlags mFlags; michael@0: bool mIsTiled; michael@0: bool mIterating; michael@0: }; michael@0: michael@0: /** michael@0: * Can only be drawn into through Cairo and need a D3D9 context on the client side. michael@0: * The corresponding TextureHost is TextureHostD3D9. michael@0: */ michael@0: class CairoTextureClientD3D9 : public TextureClient michael@0: { michael@0: public: michael@0: CairoTextureClientD3D9(gfx::SurfaceFormat aFormat, TextureFlags aFlags); michael@0: michael@0: virtual ~CairoTextureClientD3D9(); michael@0: michael@0: // TextureClient michael@0: michael@0: virtual bool IsAllocated() const MOZ_OVERRIDE { return !!mTexture; } michael@0: michael@0: virtual bool Lock(OpenMode aOpenMode) MOZ_OVERRIDE; michael@0: michael@0: virtual void Unlock() MOZ_OVERRIDE; michael@0: michael@0: virtual bool IsLocked() const MOZ_OVERRIDE { return mIsLocked; } michael@0: michael@0: virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE; michael@0: michael@0: virtual gfx::IntSize GetSize() const { return mSize; } michael@0: michael@0: virtual gfx::SurfaceFormat GetFormat() const { return mFormat; } michael@0: michael@0: virtual TextureClientData* DropTextureData() MOZ_OVERRIDE; michael@0: michael@0: virtual bool CanExposeDrawTarget() const MOZ_OVERRIDE { return true; } michael@0: michael@0: virtual TemporaryRef GetAsDrawTarget() MOZ_OVERRIDE; michael@0: michael@0: virtual bool AllocateForSurface(gfx::IntSize aSize, michael@0: TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE; michael@0: michael@0: virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; } michael@0: michael@0: private: michael@0: RefPtr mTexture; michael@0: nsRefPtr mD3D9Surface; michael@0: RefPtr mDrawTarget; michael@0: nsRefPtr mSurface; michael@0: gfx::IntSize mSize; michael@0: gfx::SurfaceFormat mFormat; michael@0: bool mIsLocked; michael@0: bool mNeedsClear; michael@0: bool mLockRect; michael@0: }; michael@0: michael@0: /** michael@0: * Can only be drawn into through Cairo. michael@0: * Prefer CairoTextureClientD3D9 when possible. michael@0: * The coresponding TextureHost is DIBTextureHostD3D9. michael@0: */ michael@0: class DIBTextureClientD3D9 : public TextureClient michael@0: { michael@0: public: michael@0: DIBTextureClientD3D9(gfx::SurfaceFormat aFormat, TextureFlags aFlags); michael@0: michael@0: virtual ~DIBTextureClientD3D9(); michael@0: michael@0: // TextureClient michael@0: michael@0: virtual bool IsAllocated() const MOZ_OVERRIDE { return !!mSurface; } michael@0: michael@0: virtual bool Lock(OpenMode aOpenMode) MOZ_OVERRIDE; michael@0: michael@0: virtual void Unlock() MOZ_OVERRIDE; michael@0: michael@0: virtual bool IsLocked() const MOZ_OVERRIDE { return mIsLocked; } michael@0: michael@0: virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE; michael@0: michael@0: virtual gfx::IntSize GetSize() const { return mSize; } michael@0: michael@0: virtual gfx::SurfaceFormat GetFormat() const { return mFormat; } michael@0: michael@0: virtual TextureClientData* DropTextureData() MOZ_OVERRIDE; michael@0: michael@0: virtual bool CanExposeDrawTarget() const MOZ_OVERRIDE { return true; } michael@0: michael@0: virtual TemporaryRef GetAsDrawTarget() MOZ_OVERRIDE; michael@0: michael@0: virtual bool AllocateForSurface(gfx::IntSize aSize, michael@0: TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE; michael@0: michael@0: virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; } michael@0: michael@0: protected: michael@0: nsRefPtr mSurface; michael@0: RefPtr mDrawTarget; michael@0: gfx::IntSize mSize; michael@0: gfx::SurfaceFormat mFormat; michael@0: bool mIsLocked; michael@0: }; michael@0: michael@0: /** michael@0: * Wraps a D3D9 texture, shared with the compositor though DXGI. michael@0: * At the moment it is only used with D3D11 compositing, and the corresponding michael@0: * TextureHost is DXGITextureHostD3D11. michael@0: */ michael@0: class SharedTextureClientD3D9 : public TextureClient michael@0: { michael@0: public: michael@0: SharedTextureClientD3D9(gfx::SurfaceFormat aFormat, TextureFlags aFlags); michael@0: michael@0: virtual ~SharedTextureClientD3D9(); michael@0: michael@0: // TextureClient michael@0: michael@0: virtual bool IsAllocated() const MOZ_OVERRIDE { return !!mTexture; } michael@0: michael@0: virtual bool Lock(OpenMode aOpenMode) MOZ_OVERRIDE; michael@0: michael@0: virtual void Unlock() MOZ_OVERRIDE; michael@0: michael@0: virtual bool IsLocked() const MOZ_OVERRIDE { return mIsLocked; } michael@0: michael@0: virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE; michael@0: michael@0: void InitWith(IDirect3DTexture9* aTexture, HANDLE aSharedHandle, D3DSURFACE_DESC aDesc) michael@0: { michael@0: MOZ_ASSERT(!mTexture); michael@0: mTexture = aTexture; michael@0: mHandle = aSharedHandle; michael@0: mDesc = aDesc; michael@0: } michael@0: michael@0: virtual gfx::IntSize GetSize() const michael@0: { michael@0: return gfx::IntSize(mDesc.Width, mDesc.Height); michael@0: } michael@0: michael@0: virtual TextureClientData* DropTextureData() MOZ_OVERRIDE; michael@0: michael@0: virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; } michael@0: michael@0: private: michael@0: RefPtr mTexture; michael@0: gfx::SurfaceFormat mFormat; michael@0: HANDLE mHandle; michael@0: D3DSURFACE_DESC mDesc; michael@0: bool mIsLocked; michael@0: }; michael@0: michael@0: class TextureHostD3D9 : public TextureHost michael@0: { michael@0: public: michael@0: TextureHostD3D9(TextureFlags aFlags, michael@0: const SurfaceDescriptorD3D9& aDescriptor); michael@0: michael@0: virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE; michael@0: michael@0: virtual void DeallocateDeviceData() MOZ_OVERRIDE; michael@0: michael@0: virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; michael@0: michael@0: virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; } michael@0: michael@0: virtual bool Lock() MOZ_OVERRIDE; michael@0: michael@0: virtual void Unlock() MOZ_OVERRIDE; michael@0: michael@0: virtual void Updated(const nsIntRegion* aRegion) MOZ_OVERRIDE; michael@0: michael@0: virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; } michael@0: michael@0: virtual TemporaryRef GetAsSurface() MOZ_OVERRIDE michael@0: { michael@0: return nullptr; michael@0: } michael@0: michael@0: virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; } michael@0: michael@0: protected: michael@0: TextureHostD3D9(TextureFlags aFlags); michael@0: IDirect3DDevice9* GetDevice(); michael@0: michael@0: RefPtr mTextureSource; michael@0: RefPtr mTexture; michael@0: RefPtr mCompositor; michael@0: gfx::IntSize mSize; michael@0: gfx::SurfaceFormat mFormat; michael@0: bool mIsLocked; michael@0: }; michael@0: michael@0: class DIBTextureHostD3D9 : public TextureHost michael@0: { michael@0: public: michael@0: DIBTextureHostD3D9(TextureFlags aFlags, michael@0: const SurfaceDescriptorDIB& aDescriptor); michael@0: michael@0: virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE; michael@0: michael@0: virtual void DeallocateDeviceData() MOZ_OVERRIDE; michael@0: michael@0: virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; michael@0: michael@0: virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; } michael@0: michael@0: virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; } michael@0: michael@0: virtual bool Lock() MOZ_OVERRIDE; michael@0: michael@0: virtual void Unlock() MOZ_OVERRIDE; michael@0: michael@0: virtual void Updated(const nsIntRegion* aRegion = nullptr); michael@0: michael@0: virtual TemporaryRef GetAsSurface() MOZ_OVERRIDE michael@0: { michael@0: return nullptr; // TODO: cf bug 872568 michael@0: } michael@0: michael@0: protected: michael@0: nsRefPtr mSurface; michael@0: RefPtr mTextureSource; michael@0: RefPtr mCompositor; michael@0: gfx::SurfaceFormat mFormat; michael@0: gfx::IntSize mSize; michael@0: bool mIsLocked; michael@0: }; michael@0: michael@0: class DXGITextureHostD3D9 : public TextureHost michael@0: { michael@0: public: michael@0: DXGITextureHostD3D9(TextureFlags aFlags, michael@0: const SurfaceDescriptorD3D10& aDescriptor); michael@0: michael@0: virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE; michael@0: michael@0: virtual void DeallocateDeviceData() MOZ_OVERRIDE; michael@0: michael@0: virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; michael@0: michael@0: virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; } michael@0: michael@0: virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; } michael@0: michael@0: virtual bool Lock() MOZ_OVERRIDE; michael@0: michael@0: virtual void Unlock() MOZ_OVERRIDE; michael@0: michael@0: virtual TemporaryRef GetAsSurface() MOZ_OVERRIDE michael@0: { michael@0: return nullptr; // TODO: cf bug 872568 michael@0: } michael@0: michael@0: protected: michael@0: RefPtr mTextureSource; michael@0: RefPtr mCompositor; michael@0: WindowsHandle mHandle; michael@0: gfx::SurfaceFormat mFormat; michael@0: gfx::IntSize mSize; michael@0: bool mIsLocked; michael@0: }; michael@0: michael@0: class CompositingRenderTargetD3D9 : public CompositingRenderTarget, michael@0: public TextureSourceD3D9 michael@0: { michael@0: public: michael@0: CompositingRenderTargetD3D9(IDirect3DTexture9* aTexture, michael@0: SurfaceInitMode aInit, michael@0: const gfx::IntRect& aRect); michael@0: // use for rendering to the main window, cannot be rendered as a texture michael@0: CompositingRenderTargetD3D9(IDirect3DSurface9* aSurface, michael@0: SurfaceInitMode aInit, michael@0: const gfx::IntRect& aRect); michael@0: virtual ~CompositingRenderTargetD3D9(); michael@0: michael@0: virtual TextureSourceD3D9* AsSourceD3D9() MOZ_OVERRIDE michael@0: { michael@0: MOZ_ASSERT(mTexture, michael@0: "No texture, can't be indirectly rendered. Is this the screen backbuffer?"); michael@0: return this; michael@0: } michael@0: michael@0: virtual gfx::IntSize GetSize() const MOZ_OVERRIDE; michael@0: michael@0: void BindRenderTarget(IDirect3DDevice9* aDevice); michael@0: michael@0: IDirect3DSurface9* GetD3D9Surface() const { return mSurface; } michael@0: michael@0: private: michael@0: friend class CompositorD3D9; michael@0: michael@0: nsRefPtr mSurface; michael@0: SurfaceInitMode mInitMode; michael@0: bool mInitialized; michael@0: }; michael@0: michael@0: } michael@0: } michael@0: michael@0: #endif /* MOZILLA_GFX_TEXTURED3D9_H */