Bug 900244 - New D3D9 Textures for BufferTextures. r=nrc

This commit is contained in:
Nicolas Silva 2014-01-07 17:20:03 +01:00
parent 67f7bdeb1e
commit c13ae1926c
5 changed files with 334 additions and 68 deletions

View File

@ -151,6 +151,11 @@ TemporaryRef<TextureHost> CreateTextureHostD3D11(const SurfaceDescriptor& aDesc,
ISurfaceAllocator* aDeallocator,
TextureFlags aFlags);
// implemented in TextureD3D9.cpp
TemporaryRef<TextureHost> CreateTextureHostD3D9(const SurfaceDescriptor& aDesc,
ISurfaceAllocator* aDeallocator,
TextureFlags aFlags);
// static
TemporaryRef<TextureHost>
TextureHost::Create(const SurfaceDescriptor& aDesc,
@ -173,7 +178,7 @@ TextureHost::Create(const SurfaceDescriptor& aDesc,
case LAYERS_D3D11:
return CreateTextureHostD3D11(aDesc, aDeallocator, aFlags);
case LAYERS_D3D9:
// XXX - not implemented yet
return CreateTextureHostD3D9(aDesc, aDeallocator, aFlags);
#endif
default:
MOZ_CRASH("Couldn't create texture host");

View File

@ -86,6 +86,13 @@ CompositorD3D9::GetMaxTextureSize() const
return mDeviceManager ? mDeviceManager->GetMaxTextureSize() : INT32_MAX;
}
TemporaryRef<DataTextureSource>
CompositorD3D9::CreateDataTextureSource(TextureFlags aFlags)
{
return new DataTextureSourceD3D9(FORMAT_UNKNOWN, this,
!(aFlags & TEXTURE_DISALLOW_BIGIMAGE));
}
TemporaryRef<CompositingRenderTarget>
CompositorD3D9::CreateRenderTarget(const gfx::IntRect &aRect,
SurfaceInitMode aInit)
@ -323,16 +330,23 @@ CompositorD3D9::DrawQuad(const gfx::Rect &aRect,
textureCoords.width,
textureCoords.height),
1);
TextureSourceD3D9* source = ycbcrEffect->mTexture->AsSourceD3D9();
TextureSourceD3D9::YCbCrTextures textures = source->GetYCbCrTextures();
const int Y = 0, Cb = 1, Cr = 2;
TextureSource* source = ycbcrEffect->mTexture;
TextureSourceD3D9* sourceY = source->GetSubSource(Y)->AsSourceD3D9();
TextureSourceD3D9* sourceCb = source->GetSubSource(Cb)->AsSourceD3D9();
TextureSourceD3D9* sourceCr = source->GetSubSource(Cr)->AsSourceD3D9();
MOZ_ASSERT(sourceY->GetD3D9Texture());
MOZ_ASSERT(sourceCb->GetD3D9Texture());
MOZ_ASSERT(sourceCr->GetD3D9Texture());
/*
* Send 3d control data and metadata
*/
if (mDeviceManager->GetNv3DVUtils()) {
Nv_Stereo_Mode mode;
switch (textures.mStereoMode) {
switch (source->AsSourceD3D9()->GetStereoMode()) {
case STEREO_MODE_LEFT_RIGHT:
mode = NV_STEREO_MODE_LEFT_RIGHT;
break;
@ -353,14 +367,14 @@ CompositorD3D9::DrawQuad(const gfx::Rect &aRect,
// Send control data even in mono case so driver knows to leave stereo mode.
mDeviceManager->GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE);
if (textures.mStereoMode != STEREO_MODE_MONO) {
if (source->AsSourceD3D9()->GetStereoMode() != STEREO_MODE_MONO) {
mDeviceManager->GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE);
nsRefPtr<IDirect3DSurface9> renderTarget;
d3d9Device->GetRenderTarget(0, getter_AddRefs(renderTarget));
mDeviceManager->GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)aRect.width,
(unsigned int)aRect.height,
(HANDLE)(textures.mY),
(HANDLE)(sourceY->GetD3D9Texture()),
(HANDLE)(renderTarget));
}
}
@ -368,9 +382,9 @@ CompositorD3D9::DrawQuad(const gfx::Rect &aRect,
// Linear scaling is default here, adhering to mFilter is difficult since
// presumably even with point filtering we'll still want chroma upsampling
// to be linear. In the current approach we can't.
d3d9Device->SetTexture(0, textures.mY);
d3d9Device->SetTexture(1, textures.mCb);
d3d9Device->SetTexture(2, textures.mCr);
device()->SetTexture(Y, sourceY->GetD3D9Texture());
device()->SetTexture(Cb, sourceCb->GetD3D9Texture());
device()->SetTexture(Cr, sourceCr->GetD3D9Texture());
maskTexture = mDeviceManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER, maskType);
}
break;

View File

@ -117,8 +117,8 @@ public:
// If the offset is 0, 0 that's okay.
}
virtual TemporaryRef<DataTextureSource>
CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE { return nullptr; }
virtual TemporaryRef<DataTextureSource>
CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE;
private:
// ensure mSize is up to date with respect to mWidget
void EnsureSize();

View File

@ -12,6 +12,7 @@
#include "mozilla/layers/YCbCrImageDataSerializer.h"
#include "gfxWindowsPlatform.h"
#include "gfx2DGlue.h"
#include "gfxUtils.h"
using namespace mozilla::gfx;
@ -56,6 +57,31 @@ TextureSourceD3D9::~TextureSourceD3D9()
}
}
TemporaryRef<TextureHost>
CreateTextureHostD3D9(const SurfaceDescriptor& aDesc,
ISurfaceAllocator* aDeallocator,
TextureFlags aFlags)
{
RefPtr<TextureHost> result;
switch (aDesc.type()) {
case SurfaceDescriptor::TSurfaceDescriptorShmem:
case SurfaceDescriptor::TSurfaceDescriptorMemory: {
result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
break;
}
case SurfaceDescriptor::TSurfaceDescriptorD3D9: {
// TODO
}
case SurfaceDescriptor::TSurfaceDescriptorDIB: {
// TODO
}
default: {
NS_WARNING("Unsupported SurfaceDescriptor type");
}
}
return result.forget();
}
CompositingRenderTargetD3D9::CompositingRenderTargetD3D9(IDirect3DTexture9* aTexture,
SurfaceInitMode aInit,
const gfx::IntRect& aRect)
@ -66,8 +92,8 @@ CompositingRenderTargetD3D9::CompositingRenderTargetD3D9(IDirect3DTexture9* aTex
MOZ_COUNT_CTOR(CompositingRenderTargetD3D9);
MOZ_ASSERT(aTexture);
mTextures[0] = aTexture;
HRESULT hr = mTextures[0]->GetSurfaceLevel(0, getter_AddRefs(mSurface));
mTexture = aTexture;
HRESULT hr = mTexture->GetSurfaceLevel(0, getter_AddRefs(mSurface));
NS_ASSERTION(mSurface, "Couldn't create surface for texture");
TextureSourceD3D9::SetSize(aRect.Size());
}
@ -246,7 +272,7 @@ DeprecatedTextureHostD3D9::Reset()
{
mSize.width = 0;
mSize.height = 0;
mTextures[0] = nullptr;
mTexture = nullptr;
mIsTiled = false;
}
@ -294,10 +320,10 @@ DeprecatedTextureHostShmemD3D9::UpdateImpl(const SurfaceDescriptor& aImage,
int32_t maxSize = mCompositor->GetMaxTextureSize();
if (mSize.width <= maxSize && mSize.height <= maxSize) {
mTextures[0] = DataToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
surf->Data(), surf->Stride(),
mSize, format, bpp);
if (!mTextures[0]) {
mTexture = DataToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
surf->Data(), surf->Stride(),
mSize, format, bpp);
if (!mTexture) {
NS_WARNING("Could not upload texture");
Reset();
return;
@ -346,12 +372,16 @@ DeprecatedTextureHostD3D9::GetTileRect(uint32_t aID) const
}
DeprecatedTextureHostYCbCrD3D9::DeprecatedTextureHostYCbCrD3D9()
: mCompositor(nullptr)
{
mFormat = gfx::FORMAT_YUV;
mFormat = FORMAT_YUV;
MOZ_COUNT_CTOR(DeprecatedTextureHostYCbCrD3D9);
}
DeprecatedTextureHostYCbCrD3D9::~DeprecatedTextureHostYCbCrD3D9()
{
MOZ_COUNT_DTOR(DeprecatedTextureHostYCbCrD3D9);
}
void
@ -363,7 +393,7 @@ DeprecatedTextureHostYCbCrD3D9::SetCompositor(Compositor* aCompositor)
IntSize
DeprecatedTextureHostYCbCrD3D9::GetSize() const
{
return TextureSourceD3D9::GetSize();
return mSize;
}
void
@ -384,21 +414,50 @@ DeprecatedTextureHostYCbCrD3D9::UpdateImpl(const SurfaceDescriptor& aImage,
mStereoMode = yuvDeserializer.GetStereoMode();
DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
mTextures[0] = DataToTexture(deviceManager,
yuvDeserializer.GetYData(),
yuvDeserializer.GetYStride(),
mSize,
D3DFMT_A8, 1);
mTextures[1] = DataToTexture(deviceManager,
yuvDeserializer.GetCbData(),
yuvDeserializer.GetCbCrStride(),
cbCrSize,
D3DFMT_A8, 1);
mTextures[2] = DataToTexture(deviceManager,
yuvDeserializer.GetCrData(),
yuvDeserializer.GetCbCrStride(),
cbCrSize,
D3DFMT_A8, 1);
RefPtr<DataTextureSource> srcY;
RefPtr<DataTextureSource> srcU;
RefPtr<DataTextureSource> srcV;
if (!mFirstSource) {
srcY = new DataTextureSourceD3D9(FORMAT_A8, mCompositor, false, mStereoMode);
srcU = new DataTextureSourceD3D9(FORMAT_A8, mCompositor, false, mStereoMode);
srcV = new DataTextureSourceD3D9(FORMAT_A8, mCompositor, false, mStereoMode);
mFirstSource = srcY;
srcY->SetNextSibling(srcU);
srcU->SetNextSibling(srcV);
} else {
MOZ_ASSERT(mFirstSource->GetNextSibling());
MOZ_ASSERT(mFirstSource->GetNextSibling()->GetNextSibling());
srcY = mFirstSource;
srcU = mFirstSource->GetNextSibling()->AsDataTextureSource();
srcV = mFirstSource->GetNextSibling()->GetNextSibling()->AsDataTextureSource();
}
RefPtr<DataSourceSurface> wrapperY =
Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetYData(),
yuvDeserializer.GetYStride(),
yuvDeserializer.GetYSize(),
FORMAT_A8);
RefPtr<DataSourceSurface> wrapperCb =
Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCbData(),
yuvDeserializer.GetCbCrStride(),
yuvDeserializer.GetCbCrSize(),
FORMAT_A8);
RefPtr<DataSourceSurface> wrapperCr =
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) ||
!srcU->Update(wrapperCb, TEXTURE_FLAGS_DEFAULT) ||
!srcV->Update(wrapperCr, TEXTURE_FLAGS_DEFAULT)) {
NS_WARNING("failed to update the DataTextureSource");
mSize.width = 0;
mSize.height = 0;
mFirstSource = nullptr;
return;
}
}
TemporaryRef<IDirect3DTexture9>
@ -479,9 +538,9 @@ DeprecatedTextureHostSystemMemD3D9::UpdateImpl(const SurfaceDescriptor& aImage,
if (mSize.width <= maxSize && mSize.height <= maxSize) {
mIsTiled = false;
mTextures[0] = TextureToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
texture, mSize, format);
if (!mTextures[0]) {
mTexture = TextureToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
texture, mSize, format);
if (!mTexture) {
NS_WARNING("Could not upload texture");
Reset();
return;
@ -592,9 +651,9 @@ DeprecatedTextureHostDIB::UpdateImpl(const SurfaceDescriptor& aImage,
int32_t maxSize = mCompositor->GetMaxTextureSize();
if (mSize.width <= maxSize && mSize.height <= maxSize) {
mTextures[0] = SurfaceToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
surf, mSize, format);
if (!mTextures[0]) {
mTexture = SurfaceToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
surf, mSize, format);
if (!mTexture) {
NS_WARNING("Could not upload texture");
Reset();
return;
@ -891,5 +950,134 @@ DeprecatedTextureClientDIB::SetDescriptor(const SurfaceDescriptor& aDescriptor)
mDescriptor.get_SurfaceDescriptorDIB().surface());
}
DataTextureSourceD3D9::DataTextureSourceD3D9(gfx::SurfaceFormat aFormat,
CompositorD3D9* aCompositor,
bool aDisallowBigImage,
StereoMode aStereoMode)
: mFormat(aFormat)
, mCompositor(aCompositor)
, mCurrentTile(0)
, mDisallowBigImage(aDisallowBigImage)
, mIsTiled(false)
, mIterating(false)
{
mStereoMode = aStereoMode;
MOZ_COUNT_CTOR(DataTextureSourceD3D9);
}
DataTextureSourceD3D9::~DataTextureSourceD3D9()
{
MOZ_COUNT_DTOR(DataTextureSourceD3D9);
}
bool
DataTextureSourceD3D9::Update(gfx::DataSourceSurface* aSurface,
TextureFlags aFlags,
nsIntRegion* aDestRegion,
gfx::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);
if (!mCompositor || !mCompositor->device()) {
return false;
}
mSize = aSurface->GetSize();
uint32_t bpp = 0;
_D3DFORMAT format = D3DFMT_A8R8G8B8;
mFormat = aSurface->GetFormat();
switch (mFormat) {
case FORMAT_B8G8R8X8:
format = D3DFMT_X8R8G8B8;
bpp = 4;
break;
case FORMAT_B8G8R8A8:
format = D3DFMT_A8R8G8B8;
bpp = 4;
break;
case FORMAT_A8:
format = D3DFMT_A8;
bpp = 1;
break;
default:
NS_WARNING("Bad image format");
return false;
}
int32_t maxSize = mCompositor->GetMaxTextureSize();
DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
if (mSize.width <= maxSize && mSize.height <= maxSize) {
mTexture = DataToTexture(deviceManager,
aSurface->GetData(), aSurface->Stride(),
ThebesIntSize(mSize), format, bpp);
if (!mTexture) {
NS_WARNING("Could not upload texture");
Reset();
return false;
}
mIsTiled = false;
} else {
mIsTiled = true;
uint32_t tileCount = GetRequiredTilesD3D9(mSize.width, maxSize) *
GetRequiredTilesD3D9(mSize.height, maxSize);
mTileTextures.resize(tileCount);
for (uint32_t i = 0; i < tileCount; i++) {
IntRect tileRect = GetTileRect(i);
unsigned char* data = aSurface->GetData() +
tileRect.y * aSurface->Stride() +
tileRect.x * bpp;
mTileTextures[i] = DataToTexture(deviceManager,
data,
aSurface->Stride(),
gfxIntSize(tileRect.width, tileRect.height),
format,
bpp);
if (!mTileTextures[i]) {
NS_WARNING("Could not upload texture");
Reset();
return false;
}
}
}
return true;
}
void
DataTextureSourceD3D9::Reset()
{
mSize.width = 0;
mSize.height = 0;
mIsTiled = false;
mTexture = nullptr;
}
IntRect
DataTextureSourceD3D9::GetTileRect(uint32_t aTileIndex) const
{
uint32_t maxSize = mCompositor->GetMaxTextureSize();
uint32_t horizontalTiles = GetRequiredTilesD3D9(mSize.width, maxSize);
uint32_t verticalTiles = GetRequiredTilesD3D9(mSize.height, maxSize);
uint32_t verticalTile = aTileIndex / horizontalTiles;
uint32_t horizontalTile = aTileIndex % horizontalTiles;
return IntRect(horizontalTile * maxSize,
verticalTile * maxSize,
horizontalTile < (horizontalTiles - 1) ? maxSize : mSize.width % maxSize,
verticalTile < (verticalTiles - 1) ? maxSize : mSize.height % maxSize);
}
nsIntRect
DataTextureSourceD3D9::GetTileRect()
{
return ThebesIntRect(GetTileRect(mCurrentTile));
}
}
}

View File

@ -32,31 +32,14 @@ public:
{}
virtual ~TextureSourceD3D9();
virtual IDirect3DTexture9* GetD3D9Texture() { return mTextures[0]; }
virtual bool IsYCbCrSource() const { return false; }
virtual IDirect3DTexture9* GetD3D9Texture() { return mTexture; }
struct YCbCrTextures
{
IDirect3DTexture9 *mY;
IDirect3DTexture9 *mCb;
IDirect3DTexture9 *mCr;
StereoMode mStereoMode;
};
virtual YCbCrTextures GetYCbCrTextures() {
YCbCrTextures textures = { mTextures[0],
mTextures[1],
mTextures[2],
mStereoMode };
return textures;
}
StereoMode GetStereoMode() const { return mStereoMode; };
// Release all texture memory resources held by the texture host.
virtual void ReleaseTextureResources()
{
for (size_t i = 0; i < 3; ++i) {
mTextures[i] = nullptr;
}
mTexture = nullptr;
}
protected:
@ -102,7 +85,75 @@ protected:
DeviceManagerD3D9* mCreatingDeviceManager;
StereoMode mStereoMode;
RefPtr<IDirect3DTexture9> mTextures[3];
RefPtr<IDirect3DTexture9> 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 DataTextureSourceD3D9 : public DataTextureSource
, public TextureSourceD3D9
, public TileIterator
{
public:
DataTextureSourceD3D9(gfx::SurfaceFormat aFormat,
CompositorD3D9* aCompositor,
bool aAllowBigImage = true,
StereoMode aStereoMode = STEREO_MODE_MONO);
virtual ~DataTextureSourceD3D9();
// DataTextureSource
virtual bool Update(gfx::DataSourceSurface* aSurface,
TextureFlags aFlags,
nsIntRegion* aDestRegion = nullptr,
gfx::IntPoint* aSrcOffset = nullptr) MOZ_OVERRIDE;
// TextureSource
virtual TextureSourceD3D9* AsSourceD3D9() 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 aTileIndex) const;
void Reset();
std::vector< RefPtr<IDirect3DTexture9> > mTileTextures;
RefPtr<CompositorD3D9> mCompositor;
gfx::SurfaceFormat mFormat;
uint32_t mCurrentTile;
bool mDisallowBigImage;
bool mIsTiled;
bool mIterating;
};
class CompositingRenderTargetD3D9 : public CompositingRenderTarget,
@ -120,7 +171,7 @@ public:
virtual TextureSourceD3D9* AsSourceD3D9() MOZ_OVERRIDE
{
MOZ_ASSERT(mTextures[0],
MOZ_ASSERT(mTexture,
"No texture, can't be indirectly rendered. Is this the screen backbuffer?");
return this;
}
@ -239,11 +290,17 @@ public:
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
virtual TextureSourceD3D9* AsSourceD3D9() MOZ_OVERRIDE { return this; }
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
virtual bool IsYCbCrSource() const MOZ_OVERRIDE { return true; }
virtual TextureSourceD3D9* AsSourceD3D9() MOZ_OVERRIDE
{
return mFirstSource->AsSourceD3D9();
}
virtual TextureSource* GetSubSource(int index) MOZ_OVERRIDE
{
return mFirstSource ? mFirstSource->GetSubSource(index) : nullptr;
}
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE
{
@ -252,7 +309,7 @@ public:
virtual const char* Name() MOZ_OVERRIDE
{
return "TextureImageDeprecatedTextureHostD3D11";
return "DeprecatedTextureHostYCbCrD3D9";
}
protected:
@ -261,6 +318,8 @@ protected:
nsIntPoint* aOffset = nullptr) MOZ_OVERRIDE;
private:
gfx::IntSize mSize;
RefPtr<DataTextureSource> mFirstSource;
RefPtr<CompositorD3D9> mCompositor;
};