From 8aba9aaa4ad00a86e94340816357e00c304b4903 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Tue, 7 Jan 2014 17:19:52 +0100 Subject: [PATCH] Bug 938591 - New D3D11 TextureClient/Host. r=nrc --- gfx/layers/composite/TextureHost.cpp | 6 + gfx/layers/d3d11/CompositorD3D11.cpp | 24 +- gfx/layers/d3d11/CompositorD3D11.h | 2 +- gfx/layers/d3d11/TextureD3D11.cpp | 399 +++++++++++++++++++++++---- gfx/layers/d3d11/TextureD3D11.h | 177 ++++++++++-- 5 files changed, 518 insertions(+), 90 deletions(-) diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index 2c14f368f67..a054caa5a19 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -146,6 +146,11 @@ TemporaryRef CreateTextureHostBasic(const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator, TextureFlags aFlags); +// implemented in TextureD3D11.cpp +TemporaryRef CreateTextureHostD3D11(const SurfaceDescriptor& aDesc, + ISurfaceAllocator* aDeallocator, + TextureFlags aFlags); + // static TemporaryRef TextureHost::Create(const SurfaceDescriptor& aDesc, @@ -166,6 +171,7 @@ TextureHost::Create(const SurfaceDescriptor& aDesc, #endif #ifdef XP_WIN case LAYERS_D3D11: + return CreateTextureHostD3D11(aDesc, aDeallocator, aFlags); case LAYERS_D3D9: // XXX - not implemented yet #endif diff --git a/gfx/layers/d3d11/CompositorD3D11.cpp b/gfx/layers/d3d11/CompositorD3D11.cpp index ed21705f3fe..879ab09edf4 100644 --- a/gfx/layers/d3d11/CompositorD3D11.cpp +++ b/gfx/layers/d3d11/CompositorD3D11.cpp @@ -338,6 +338,14 @@ CompositorD3D11::Initialize() return true; } +TemporaryRef +CompositorD3D11::CreateDataTextureSource(TextureFlags aFlags) +{ + RefPtr result = new DataTextureSourceD3D11(gfx::FORMAT_UNKNOWN, + this); + return result.forget(); +} + TextureFactoryIdentifier CompositorD3D11::GetTextureFactoryIdentifier() { @@ -576,13 +584,19 @@ CompositorD3D11::DrawQuad(const gfx::Rect& aRect, mVSConstants.textureCoords = ycbcrEffect->mTextureCoords; - TextureSourceD3D11* source = ycbcrEffect->mTexture->AsSourceD3D11(); - TextureSourceD3D11::YCbCrTextures textures = source->GetYCbCrTextures(); + const int Y = 0, Cb = 1, Cr = 2; + TextureSource* source = ycbcrEffect->mTexture; + TextureSourceD3D11* sourceY = source->GetSubSource(Y)->AsSourceD3D11(); + TextureSourceD3D11* sourceCb = source->GetSubSource(Cb)->AsSourceD3D11(); + TextureSourceD3D11* sourceCr = source->GetSubSource(Cr)->AsSourceD3D11(); RefPtr views[3]; - mDevice->CreateShaderResourceView(textures.mY, nullptr, byRef(views[0])); - mDevice->CreateShaderResourceView(textures.mCb, nullptr, byRef(views[1])); - mDevice->CreateShaderResourceView(textures.mCr, nullptr, byRef(views[2])); + mDevice->CreateShaderResourceView(sourceY->GetD3D11Texture(), + nullptr, byRef(views[0])); + mDevice->CreateShaderResourceView(sourceCb->GetD3D11Texture(), + nullptr, byRef(views[1])); + mDevice->CreateShaderResourceView(sourceCr->GetD3D11Texture(), + nullptr, byRef(views[2])); ID3D11ShaderResourceView* srViews[3] = { views[0], views[1], views[2] }; mContext->PSSetShaderResources(0, 3, srViews); diff --git a/gfx/layers/d3d11/CompositorD3D11.h b/gfx/layers/d3d11/CompositorD3D11.h index 66441978865..8921fa9dac4 100644 --- a/gfx/layers/d3d11/CompositorD3D11.h +++ b/gfx/layers/d3d11/CompositorD3D11.h @@ -49,7 +49,7 @@ public: GetTextureFactoryIdentifier() MOZ_OVERRIDE; virtual TemporaryRef - CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE { return nullptr; } + CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE; virtual bool CanUseCanvasLayerForSize(const gfx::IntSize& aSize) MOZ_OVERRIDE; virtual int32_t GetMaxTextureSize() const MOZ_FINAL; diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index eff9330a2c6..657acdeb215 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -20,6 +20,266 @@ using namespace gfx; namespace layers { +static DXGI_FORMAT +SurfaceFormatToDXGIFormat(gfx::SurfaceFormat aFormat) +{ + switch (aFormat) { + case FORMAT_B8G8R8A8: + return DXGI_FORMAT_B8G8R8A8_UNORM; + case FORMAT_B8G8R8X8: + return DXGI_FORMAT_B8G8R8A8_UNORM; + case FORMAT_A8: + return DXGI_FORMAT_A8_UNORM; + default: + MOZ_ASSERT(false, "unsupported format"); + } +} + +static uint32_t +GetRequiredTilesD3D11(uint32_t aSize, uint32_t aMaxSize) +{ + uint32_t requiredTiles = aSize / aMaxSize; + if (aSize % aMaxSize) { + requiredTiles++; + } + return requiredTiles; +} + +static IntRect +GetTileRectD3D11(uint32_t aID, IntSize aSize, uint32_t aMaxSize) +{ + uint32_t horizontalTiles = GetRequiredTilesD3D11(aSize.width, aMaxSize); + uint32_t verticalTiles = GetRequiredTilesD3D11(aSize.height, aMaxSize); + + uint32_t verticalTile = aID / horizontalTiles; + uint32_t horizontalTile = aID % horizontalTiles; + + return IntRect(horizontalTile * aMaxSize, + verticalTile * aMaxSize, + horizontalTile < (horizontalTiles - 1) ? aMaxSize : aSize.width % aMaxSize, + verticalTile < (verticalTiles - 1) ? aMaxSize : aSize.height % aMaxSize); +} + +DataTextureSourceD3D11::DataTextureSourceD3D11(SurfaceFormat aFormat, + CompositorD3D11* aCompositor) + : mFormat(aFormat) + , mCompositor(aCompositor) +{ + MOZ_COUNT_CTOR(DataTextureSourceD3D11); +} + +DataTextureSourceD3D11::~DataTextureSourceD3D11() +{ + MOZ_COUNT_DTOR(DataTextureSourceD3D11); +} + + +template // ID3D10Texture2D or ID3D11Texture2D +static void LockD3DTexture(T* aTexture) +{ + MOZ_ASSERT(aTexture); + RefPtr mutex; + aTexture->QueryInterface((IDXGIKeyedMutex**)byRef(mutex)); + mutex->AcquireSync(0, INFINITE); +} + +template // ID3D10Texture2D or ID3D11Texture2D +static void UnlockD3DTexture(T* aTexture) +{ + MOZ_ASSERT(aTexture); + RefPtr mutex; + aTexture->QueryInterface((IDXGIKeyedMutex**)byRef(mutex)); + mutex->ReleaseSync(0); +} + +TemporaryRef +CreateTextureHostD3D11(const SurfaceDescriptor& aDesc, + ISurfaceAllocator* aDeallocator, + TextureFlags aFlags) +{ + RefPtr result; + switch (aDesc.type()) { + case SurfaceDescriptor::TSurfaceDescriptorShmem: + case SurfaceDescriptor::TSurfaceDescriptorMemory: { + result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags); + break; + } + case SurfaceDescriptor::TSurfaceDescriptorD3D10: { + result = new DXGITextureHostD3D11(aFlags, + aDesc.get_SurfaceDescriptorD3D10()); + break; + } + default: { + NS_WARNING("Unsupported SurfaceDescriptor type"); + } + } + return result; +} + +bool +TextureClientD3D11::Lock(OpenMode aMode) +{ + MOZ_ASSERT(!mIsLocked, "The Texture is already locked!"); + LockD3DTexture(mTexture.get()); + mIsLocked = true; + return true; +} + +void +TextureClientD3D11::Unlock() +{ + MOZ_ASSERT(mIsLocked, "Unlocked called while the texture is not locked!"); + UnlockD3DTexture(mTexture.get()); + mIsLocked = false; +} + +DataTextureSourceD3D11::DataTextureSourceD3D11(ID3D11Texture2D* aTexture, + SurfaceFormat aFormat) +: mFormat(aFormat) +{ + mTexture = aTexture; + D3D11_TEXTURE2D_DESC desc; + aTexture->GetDesc(&desc); + + mSize = IntSize(desc.Width, desc.Height); +} + +DXGITextureHostD3D11::DXGITextureHostD3D11(TextureFlags aFlags, + const SurfaceDescriptorD3D10& aDescriptor) + : TextureHost(aFlags) + , mHandle(aDescriptor.handle()) + , mFormat(aDescriptor.hasAlpha() ? FORMAT_B8G8R8A8 : FORMAT_B8G8R8X8) + , mIsLocked(false) +{} + +void +DXGITextureHostD3D11::SetCompositor(Compositor* aCompositor) +{ + CompositorD3D11 *d3dCompositor = static_cast(aCompositor); + mDevice = d3dCompositor ? d3dCompositor->GetDevice() : nullptr; +} + +bool +DXGITextureHostD3D11::Lock() +{ + if (!mDevice) { + NS_WARNING("trying to lock a TextureHost without a D3D device"); + return false; + } + if (!mTextureSource) { + RefPtr tex; + mDevice->OpenSharedResource((HANDLE)mHandle, + __uuidof(ID3D11Texture2D), + (void**)(ID3D11Texture2D**)byRef(tex)); + + mTextureSource = new DataTextureSourceD3D11(tex, mFormat); + D3D11_TEXTURE2D_DESC desc; + tex->GetDesc(&desc); + mSize = IntSize(desc.Width, desc.Height); + } + + LockD3DTexture(mTextureSource->GetD3D11Texture()); + + mIsLocked = true; + return true; +} + +void +DXGITextureHostD3D11::Unlock() +{ + MOZ_ASSERT(mIsLocked); + UnlockD3DTexture(mTextureSource->GetD3D11Texture()); + mIsLocked = false; +} + +NewTextureSource* +DXGITextureHostD3D11::GetTextureSources() +{ + return mTextureSource.get(); +} + +bool +DataTextureSourceD3D11::Update(DataSourceSurface* aSurface, + TextureFlags aFlags, + nsIntRegion* aDestRegion, + IntPoint* aSrcOffset) +{ + // Right now we only support null aDestRegion and aSrcOffset (which means) + // full surface update. Incremental update is only used on Mac so it is + // not clear that we ever will need to support it for D3D. + MOZ_ASSERT(!aDestRegion && !aSrcOffset); + MOZ_ASSERT(aSurface); + + if (!mCompositor || !mCompositor->GetDevice()) { + return false; + } + + uint32_t bpp = BytesPerPixel(aSurface->GetFormat()); + DXGI_FORMAT dxgiFormat = SurfaceFormatToDXGIFormat(aSurface->GetFormat()); + + mSize = aSurface->GetSize(); + + CD3D11_TEXTURE2D_DESC desc(dxgiFormat, mSize.width, mSize.height, + 1, 1, D3D11_BIND_SHADER_RESOURCE, + D3D11_USAGE_IMMUTABLE); + + int32_t maxSize = mCompositor->GetMaxTextureSize(); + if (mSize.width <= maxSize && mSize.height <= maxSize) { + D3D11_SUBRESOURCE_DATA initData; + initData.pSysMem = aSurface->GetData(); + initData.SysMemPitch = aSurface->Stride(); + + mCompositor->GetDevice()->CreateTexture2D(&desc, &initData, byRef(mTexture)); + mIsTiled = false; + } else { + mIsTiled = true; + uint32_t tileCount = GetRequiredTilesD3D11(mSize.width, maxSize) * + GetRequiredTilesD3D11(mSize.height, maxSize); + + mTileTextures.resize(tileCount); + + for (uint32_t i = 0; i < tileCount; i++) { + IntRect tileRect = GetTileRect(i); + + desc.Width = tileRect.width; + desc.Height = tileRect.height; + + D3D11_SUBRESOURCE_DATA initData; + initData.pSysMem = aSurface->GetData() + + tileRect.y * aSurface->Stride() + + tileRect.x * bpp; + initData.SysMemPitch = aSurface->Stride(); + + mCompositor->GetDevice()->CreateTexture2D(&desc, &initData, byRef(mTileTextures[i])); + } + } + return true; +} + +IntRect +DataTextureSourceD3D11::GetTileRect(uint32_t aIndex) const +{ + return GetTileRectD3D11(aIndex, mSize, mCompositor->GetMaxTextureSize()); +} + +nsIntRect +DataTextureSourceD3D11::GetTileRect() +{ + IntRect rect = GetTileRect(mCurrentTile); + return nsIntRect(rect.x, rect.y, rect.width, rect.height); +} + +void +DataTextureSourceD3D11::SetCompositor(Compositor* aCompositor) +{ + CompositorD3D11* d3dCompositor = static_cast(aCompositor); + if (mCompositor != d3dCompositor) { + mTexture = nullptr; + mTileTextures.resize(0); + } + mCompositor = d3dCompositor; +} + TemporaryRef CreateDeprecatedTextureHostD3D11(SurfaceDescriptorType aDescriptorType, uint32_t aDeprecatedTextureHostFlags, @@ -46,12 +306,12 @@ CompositingRenderTargetD3D11::CompositingRenderTargetD3D11(ID3D11Texture2D* aTex { MOZ_ASSERT(aTexture); - mTextures[0] = aTexture; + mTexture = aTexture; RefPtr device; - mTextures[0]->GetDevice(byRef(device)); + mTexture->GetDevice(byRef(device)); - HRESULT hr = device->CreateRenderTargetView(mTextures[0], nullptr, byRef(mRTView)); + HRESULT hr = device->CreateRenderTargetView(mTexture, nullptr, byRef(mRTView)); if (FAILED(hr)) { LOGD3D11("Failed to create RenderTargetView."); @@ -286,15 +546,6 @@ DeprecatedTextureHostShmemD3D11::GetTileRect() return nsIntRect(rect.x, rect.y, rect.width, rect.height); } -static uint32_t GetRequiredTilesD3D11(uint32_t aSize, uint32_t aMaxSize) -{ - uint32_t requiredTiles = aSize / aMaxSize; - if (aSize % aMaxSize) { - requiredTiles++; - } - return requiredTiles; -} - void DeprecatedTextureHostShmemD3D11::SetCompositor(Compositor* aCompositor) { @@ -351,7 +602,7 @@ DeprecatedTextureHostShmemD3D11::UpdateImpl(const SurfaceDescriptor& aImage, initData.pSysMem = surf->Data(); initData.SysMemPitch = surf->Stride(); - mDevice->CreateTexture2D(&desc, &initData, byRef(mTextures[0])); + mDevice->CreateTexture2D(&desc, &initData, byRef(mTexture)); mIsTiled = false; } else { mIsTiled = true; @@ -381,16 +632,7 @@ IntRect DeprecatedTextureHostShmemD3D11::GetTileRect(uint32_t aID) const { uint32_t maxSize = GetMaxTextureSizeForFeatureLevel(mDevice->GetFeatureLevel()); - uint32_t horizontalTiles = GetRequiredTilesD3D11(mSize.width, maxSize); - uint32_t verticalTiles = GetRequiredTilesD3D11(mSize.height, maxSize); - - uint32_t verticalTile = aID / horizontalTiles; - uint32_t horizontalTile = aID % horizontalTiles; - - return IntRect(horizontalTile * maxSize, - verticalTile * maxSize, - horizontalTile < (horizontalTiles - 1) ? maxSize : mSize.width % maxSize, - verticalTile < (verticalTiles - 1) ? maxSize : mSize.height % maxSize); + return GetTileRectD3D11(aID, mSize, maxSize); } void @@ -428,8 +670,8 @@ DeprecatedTextureHostDXGID3D11::UpdateImpl(const SurfaceDescriptor& aImage, HRESULT hr =mDevice->OpenSharedResource((HANDLE)aImage.get_SurfaceDescriptorD3D10().handle(), __uuidof(ID3D11Texture2D), - (void**)(ID3D11Texture2D**)byRef(mTextures[0])); - if (!mTextures[0] || FAILED(hr)) { + (void**)(ID3D11Texture2D**)byRef(mTexture)); + if (!mTexture || FAILED(hr)) { NS_WARNING("Could not open shared resource"); mSize = IntSize(0, 0); return; @@ -438,7 +680,7 @@ DeprecatedTextureHostDXGID3D11::UpdateImpl(const SurfaceDescriptor& aImage, mFormat = aImage.get_SurfaceDescriptorD3D10().hasAlpha() ? FORMAT_B8G8R8A8 : FORMAT_B8G8R8X8; D3D11_TEXTURE2D_DESC desc; - mTextures[0]->GetDesc(&desc); + mTexture->GetDesc(&desc); mSize = IntSize(desc.Width, desc.Height); } @@ -446,11 +688,11 @@ DeprecatedTextureHostDXGID3D11::UpdateImpl(const SurfaceDescriptor& aImage, void DeprecatedTextureHostDXGID3D11::LockTexture() { - if (!mTextures[0]) { + if (!mTexture) { return; } RefPtr mutex; - mTextures[0]->QueryInterface((IDXGIKeyedMutex**)byRef(mutex)); + mTexture->QueryInterface((IDXGIKeyedMutex**)byRef(mutex)); mutex->AcquireSync(0, INFINITE); } @@ -458,26 +700,45 @@ DeprecatedTextureHostDXGID3D11::LockTexture() void DeprecatedTextureHostDXGID3D11::ReleaseTexture() { - if (!mTextures[0]) { + if (!mTexture) { return; } RefPtr mutex; - mTextures[0]->QueryInterface((IDXGIKeyedMutex**)byRef(mutex)); + mTexture->QueryInterface((IDXGIKeyedMutex**)byRef(mutex)); mutex->ReleaseSync(0); } +DeprecatedTextureHostYCbCrD3D11::DeprecatedTextureHostYCbCrD3D11() + : mCompositor(nullptr) +{ + mFormat = FORMAT_YUV; +} + +DeprecatedTextureHostYCbCrD3D11::~DeprecatedTextureHostYCbCrD3D11() +{ +} + +ID3D11Device* +DeprecatedTextureHostYCbCrD3D11::GetDevice() +{ + return mCompositor ? mCompositor->GetDevice() : nullptr; + NewTextureSource* source = mFirstSource.get(); + while (source) { + static_cast(source)->SetCompositor(mCompositor); + source = source->GetNextSibling(); + } +} + void DeprecatedTextureHostYCbCrD3D11::SetCompositor(Compositor* aCompositor) { - CompositorD3D11* d3dCompositor = static_cast(aCompositor); - mDevice = d3dCompositor ? d3dCompositor->GetDevice() : nullptr; -} - -IntSize -DeprecatedTextureHostYCbCrD3D11::GetSize() const -{ - return TextureSourceD3D11::GetSize(); + mCompositor = static_cast(aCompositor); + NewTextureSource* source = mFirstSource.get(); + while (source) { + static_cast(source)->SetCompositor(mCompositor); + source = source->GetNextSibling(); + } } void @@ -493,25 +754,49 @@ DeprecatedTextureHostYCbCrD3D11::UpdateImpl(const SurfaceDescriptor& aImage, gfx::IntSize size = yuvDeserializer.GetYSize(); - D3D11_SUBRESOURCE_DATA initData; - initData.pSysMem = yuvDeserializer.GetYData(); - initData.SysMemPitch = yuvDeserializer.GetYStride(); - - CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_A8_UNORM, size.width, size.height, - 1, 1, D3D11_BIND_SHADER_RESOURCE, - D3D11_USAGE_IMMUTABLE); - - mDevice->CreateTexture2D(&desc, &initData, byRef(mTextures[0])); - - initData.pSysMem = yuvDeserializer.GetCbData(); - initData.SysMemPitch = yuvDeserializer.GetCbCrStride(); - desc.Width = yuvDeserializer.GetCbCrSize().width; - desc.Height = yuvDeserializer.GetCbCrSize().height; - - mDevice->CreateTexture2D(&desc, &initData, byRef(mTextures[1])); - - initData.pSysMem = yuvDeserializer.GetCrData(); - mDevice->CreateTexture2D(&desc, &initData, byRef(mTextures[2])); + RefPtr srcY; + RefPtr srcCb; + RefPtr srcCr; + if (!mFirstSource) { + srcY = new DataTextureSourceD3D11(FORMAT_A8, mCompositor); + srcCb = new DataTextureSourceD3D11(FORMAT_A8, mCompositor); + srcCr = new DataTextureSourceD3D11(FORMAT_A8, mCompositor); + mFirstSource = srcY; + srcY->SetNextSibling(srcCb); + srcCb->SetNextSibling(srcCr); + } else { + MOZ_ASSERT(mFirstSource->GetNextSibling()); + MOZ_ASSERT(mFirstSource->GetNextSibling()->GetNextSibling()); + srcY = mFirstSource; + srcCb = mFirstSource->GetNextSibling()->AsDataTextureSource(); + srcCr = mFirstSource->GetNextSibling()->GetNextSibling()->AsDataTextureSource(); + } + RefPtr wrapperY = + gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetYData(), + yuvDeserializer.GetYStride(), + yuvDeserializer.GetYSize(), + FORMAT_A8); + RefPtr wrapperCb = + gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCbData(), + yuvDeserializer.GetCbCrStride(), + yuvDeserializer.GetCbCrSize(), + FORMAT_A8); + RefPtr wrapperCr = + gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCrData(), + yuvDeserializer.GetCbCrStride(), + yuvDeserializer.GetCbCrSize(), + FORMAT_A8); + // We don't support partial updates for Y U V textures + NS_ASSERTION(!aRegion, "Unsupported partial updates for YCbCr textures"); + if (!srcY->Update(wrapperY, TEXTURE_FLAGS_DEFAULT) || + !srcCb->Update(wrapperCb, TEXTURE_FLAGS_DEFAULT) || + !srcCr->Update(wrapperCr, TEXTURE_FLAGS_DEFAULT)) { + NS_WARNING("failed to update the DataTextureSource"); + mFirstSource = nullptr; + mSize.width = 0; + mSize.height = 0; + return; + } mSize = IntSize(size.width, size.height); } diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h index 349f2e021a9..4b9bfeab9fc 100644 --- a/gfx/layers/d3d11/TextureD3D11.h +++ b/gfx/layers/d3d11/TextureD3D11.h @@ -19,33 +19,150 @@ class gfxD2DSurface; namespace mozilla { namespace layers { +class CompositorD3D11; + +/** + * A TextureClient to share a D3D10 texture with the compositor thread. + * The corresponding TextureHost is DXGITextureHostD3D11 + */ +class TextureClientD3D11 : public TextureClient +{ +public: + virtual bool IsAllocated() const MOZ_OVERRIDE; + + virtual bool Lock(OpenMode aOpenMode) MOZ_OVERRIDE; + + virtual void Unlock() MOZ_OVERRIDE; + + virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE; +protected: + RefPtr mTexture; + bool mIsLocked; +}; + +/** + * TextureSource that provides with the necessary APIs to be composited by a + * CompositorD3D11. + */ class TextureSourceD3D11 { public: TextureSourceD3D11() {} virtual ~TextureSourceD3D11() {} - virtual ID3D11Texture2D* GetD3D11Texture() const { return mTextures[0]; } - virtual bool IsYCbCrSource() const { return false; } - - struct YCbCrTextures - { - ID3D11Texture2D *mY; - ID3D11Texture2D *mCb; - ID3D11Texture2D *mCr; - }; - - virtual YCbCrTextures GetYCbCrTextures() - { - YCbCrTextures textures = { mTextures[0], mTextures[1], mTextures[2] }; - return textures; - } + virtual ID3D11Texture2D* GetD3D11Texture() const { return mTexture; } protected: virtual gfx::IntSize GetSize() const { return mSize; } gfx::IntSize mSize; - RefPtr mTextures[3]; + RefPtr mTexture; +}; + +/** + * 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 TileIterator +{ +public: + DataTextureSourceD3D11(gfx::SurfaceFormat aFormat, CompositorD3D11* aCompositor); + + DataTextureSourceD3D11(ID3D11Texture2D* aTexture, + gfx::SurfaceFormat aFormat); + + virtual ~DataTextureSourceD3D11(); + + void SetCompositor(Compositor* aCompositor); + + // DataTextureSource + + virtual bool Update(gfx::DataSourceSurface* aSurface, + TextureFlags aFlags, + nsIntRegion* aDestRegion = nullptr, + gfx::IntPoint* aSrcOffset = nullptr) MOZ_OVERRIDE; + + // TextureSource + + virtual TextureSourceD3D11* AsSourceD3D11() MOZ_OVERRIDE { return this; } + + virtual DataTextureSource* AsDataTextureSource() MOZ_OVERRIDE { return this; } + + virtual void DeallocateDeviceData() MOZ_OVERRIDE { mTexture = nullptr; } + + virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; } + + virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; } + + // TileIterator + + virtual TileIterator* AsTileIterator() MOZ_OVERRIDE { return mIsTiled ? this : nullptr; } + + virtual size_t GetTileCount() MOZ_OVERRIDE { return mTileTextures.size(); } + + virtual bool NextTile() MOZ_OVERRIDE { return (++mCurrentTile < mTileTextures.size()); } + + virtual nsIntRect GetTileRect() MOZ_OVERRIDE; + + virtual void EndTileIteration() MOZ_OVERRIDE { mIterating = false; } + + virtual void BeginTileIteration() MOZ_OVERRIDE + { + mIterating = true; + mCurrentTile = 0; + } + +protected: + gfx::IntRect GetTileRect(uint32_t aIndex) const; + + std::vector< RefPtr > mTileTextures; + RefPtr mCompositor; + gfx::SurfaceFormat mFormat; + TextureFlags mFlags; + uint32_t mCurrentTile; + bool mIsTiled; + bool mIterating; + +}; + +/** + * A TextureHost for shared D3D11 textures. + */ +class DXGITextureHostD3D11 : public TextureHost +{ +public: + DXGITextureHostD3D11(TextureFlags aFlags, + const SurfaceDescriptorD3D10& aDescriptor); + + virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE; + + virtual void DeallocateDeviceData() MOZ_OVERRIDE {} + + virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; + + virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; } + + virtual bool Lock() MOZ_OVERRIDE; + + virtual void Unlock() MOZ_OVERRIDE; + + virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; } + + virtual TemporaryRef GetAsSurface() MOZ_OVERRIDE + { + return nullptr; + } + +protected: + RefPtr mTextureSource; + RefPtr mDevice; + gfx::IntSize mSize; + WindowsHandle mHandle; + gfx::SurfaceFormat mFormat; + bool mIsLocked; }; class CompositingRenderTargetD3D11 : public CompositingRenderTarget, @@ -146,7 +263,7 @@ public: virtual TemporaryRef GetAsSurface() MOZ_OVERRIDE { - return nullptr; // TODO: cf bug 872568 + return nullptr; } virtual const char* Name() MOZ_OVERRIDE @@ -226,22 +343,24 @@ private: }; class DeprecatedTextureHostYCbCrD3D11 : public DeprecatedTextureHost - , public TextureSourceD3D11 { public: - DeprecatedTextureHostYCbCrD3D11() - : mDevice(nullptr) - { - mFormat = gfx::FORMAT_YUV; - } + DeprecatedTextureHostYCbCrD3D11(); + ~DeprecatedTextureHostYCbCrD3D11(); virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; - virtual TextureSourceD3D11* AsSourceD3D11() MOZ_OVERRIDE { return this; } + virtual TextureSourceD3D11* AsSourceD3D11() MOZ_OVERRIDE + { + return mFirstSource->AsSourceD3D11(); + } - virtual gfx::IntSize GetSize() const MOZ_OVERRIDE; + virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; } - virtual bool IsYCbCrSource() const MOZ_OVERRIDE { return true; } + TextureSource* GetSubSource(int index) MOZ_OVERRIDE + { + return mFirstSource ? mFirstSource->GetSubSource(index) : nullptr; + } virtual TemporaryRef GetAsSurface() MOZ_OVERRIDE { @@ -258,8 +377,12 @@ protected: nsIntRegion* aRegion, nsIntPoint* aOffset = nullptr) MOZ_OVERRIDE; + ID3D11Device* GetDevice(); + private: - RefPtr mDevice; + gfx::IntSize mSize; + RefPtr mFirstSource; + RefPtr mCompositor; }; inline uint32_t GetMaxTextureSizeForFeatureLevel(D3D_FEATURE_LEVEL aFeatureLevel)