mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-06 00:55:37 +00:00
1753 lines
47 KiB
C++
1753 lines
47 KiB
C++
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
* 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/. */
|
|
|
|
#include "TextureD3D9.h"
|
|
#include "CompositorD3D9.h"
|
|
#include "gfxContext.h"
|
|
#include "gfxImageSurface.h"
|
|
#include "Effects.h"
|
|
#include "ipc/AutoOpenSurface.h"
|
|
#include "mozilla/layers/YCbCrImageDataSerializer.h"
|
|
#include "gfxWindowsPlatform.h"
|
|
#include "gfx2DGlue.h"
|
|
#include "gfxUtils.h"
|
|
#include "mozilla/gfx/2D.h"
|
|
|
|
using namespace mozilla::gfx;
|
|
|
|
namespace mozilla {
|
|
namespace layers {
|
|
|
|
TemporaryRef<DeprecatedTextureHost>
|
|
CreateDeprecatedTextureHostD3D9(SurfaceDescriptorType aDescriptorType,
|
|
uint32_t aDeprecatedTextureHostFlags,
|
|
uint32_t aTextureFlags)
|
|
{
|
|
RefPtr<DeprecatedTextureHost> result;
|
|
if (aDescriptorType == SurfaceDescriptor::TYCbCrImage) {
|
|
result = new DeprecatedTextureHostYCbCrD3D9();
|
|
} else if (aDescriptorType == SurfaceDescriptor::TSurfaceDescriptorD3D9) {
|
|
result = new DeprecatedTextureHostSystemMemD3D9();
|
|
} else if (aDescriptorType == SurfaceDescriptor::TSurfaceDescriptorDIB) {
|
|
result = new DeprecatedTextureHostDIB();
|
|
} else {
|
|
result = new DeprecatedTextureHostShmemD3D9();
|
|
}
|
|
|
|
result->SetFlags(aTextureFlags);
|
|
return result;
|
|
}
|
|
|
|
TextureSourceD3D9::~TextureSourceD3D9()
|
|
{
|
|
MOZ_ASSERT(!mCreatingDeviceManager ||
|
|
mCreatingDeviceManager->IsInTextureHostList(this),
|
|
"Inconsistency in list of texture hosts.");
|
|
// Remove ourselves from the list of d3d9 texture hosts.
|
|
if (mPreviousHost) {
|
|
MOZ_ASSERT(mPreviousHost->mNextHost == this);
|
|
mPreviousHost->mNextHost = mNextHost;
|
|
} else if (mCreatingDeviceManager) {
|
|
mCreatingDeviceManager->RemoveTextureListHead(this);
|
|
}
|
|
if (mNextHost) {
|
|
MOZ_ASSERT(mNextHost->mPreviousHost == this);
|
|
mNextHost->mPreviousHost = mPreviousHost;
|
|
}
|
|
}
|
|
|
|
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: {
|
|
result = new TextureHostD3D9(aFlags, aDesc);
|
|
break;
|
|
}
|
|
case SurfaceDescriptor::TSurfaceDescriptorDIB: {
|
|
result = new DIBTextureHostD3D9(aFlags, aDesc);
|
|
break;
|
|
}
|
|
default: {
|
|
NS_WARNING("Unsupported SurfaceDescriptor type");
|
|
}
|
|
}
|
|
return result.forget();
|
|
}
|
|
|
|
static SurfaceFormat
|
|
D3D9FormatToSurfaceFormat(_D3DFORMAT format)
|
|
{
|
|
switch (format) {
|
|
case D3DFMT_X8R8G8B8:
|
|
return SurfaceFormat::B8G8R8X8;
|
|
case D3DFMT_A8R8G8B8:
|
|
return SurfaceFormat::B8G8R8A8;
|
|
case D3DFMT_A8:
|
|
return SurfaceFormat::A8;
|
|
default:
|
|
NS_ERROR("Bad texture format");
|
|
}
|
|
return SurfaceFormat::UNKNOWN;
|
|
}
|
|
|
|
static _D3DFORMAT
|
|
SurfaceFormatToD3D9Format(SurfaceFormat format)
|
|
{
|
|
switch (format) {
|
|
case SurfaceFormat::B8G8R8X8:
|
|
return D3DFMT_X8R8G8B8;
|
|
case SurfaceFormat::B8G8R8A8:
|
|
return D3DFMT_A8R8G8B8;
|
|
case SurfaceFormat::A8:
|
|
return D3DFMT_A8;
|
|
default:
|
|
NS_ERROR("Bad texture format");
|
|
}
|
|
return D3DFMT_A8R8G8B8;
|
|
}
|
|
|
|
CompositingRenderTargetD3D9::CompositingRenderTargetD3D9(IDirect3DTexture9* aTexture,
|
|
SurfaceInitMode aInit,
|
|
const gfx::IntRect& aRect)
|
|
: CompositingRenderTarget(aRect.TopLeft())
|
|
, mInitMode(aInit)
|
|
, mInitialized(false)
|
|
{
|
|
MOZ_COUNT_CTOR(CompositingRenderTargetD3D9);
|
|
MOZ_ASSERT(aTexture);
|
|
|
|
mTexture = aTexture;
|
|
HRESULT hr = mTexture->GetSurfaceLevel(0, getter_AddRefs(mSurface));
|
|
NS_ASSERTION(mSurface, "Couldn't create surface for texture");
|
|
TextureSourceD3D9::SetSize(aRect.Size());
|
|
}
|
|
|
|
CompositingRenderTargetD3D9::CompositingRenderTargetD3D9(IDirect3DSurface9* aSurface,
|
|
SurfaceInitMode aInit,
|
|
const gfx::IntRect& aRect)
|
|
: CompositingRenderTarget(aRect.TopLeft())
|
|
, mSurface(aSurface)
|
|
, mInitMode(aInit)
|
|
, mInitialized(false)
|
|
{
|
|
MOZ_COUNT_CTOR(CompositingRenderTargetD3D9);
|
|
MOZ_ASSERT(mSurface);
|
|
TextureSourceD3D9::SetSize(aRect.Size());
|
|
}
|
|
|
|
CompositingRenderTargetD3D9::~CompositingRenderTargetD3D9()
|
|
{
|
|
MOZ_COUNT_DTOR(CompositingRenderTargetD3D9);
|
|
}
|
|
|
|
void
|
|
CompositingRenderTargetD3D9::BindRenderTarget(IDirect3DDevice9* aDevice)
|
|
{
|
|
aDevice->SetRenderTarget(0, mSurface);
|
|
if (!mInitialized &&
|
|
mInitMode == INIT_MODE_CLEAR) {
|
|
mInitialized = true;
|
|
aDevice->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 0), 0, 0);
|
|
}
|
|
}
|
|
|
|
IntSize
|
|
CompositingRenderTargetD3D9::GetSize() const
|
|
{
|
|
return TextureSourceD3D9::GetSize();
|
|
}
|
|
|
|
DeprecatedTextureHostD3D9::DeprecatedTextureHostD3D9()
|
|
: mIsTiled(false)
|
|
, mCurrentTile(0)
|
|
, mIterating(false)
|
|
{
|
|
MOZ_COUNT_CTOR(DeprecatedTextureHostD3D9);
|
|
}
|
|
|
|
DeprecatedTextureHostD3D9::~DeprecatedTextureHostD3D9()
|
|
{
|
|
MOZ_COUNT_DTOR(DeprecatedTextureHostD3D9);
|
|
}
|
|
|
|
IntSize
|
|
DeprecatedTextureHostD3D9::GetSize() const
|
|
{
|
|
if (mIterating) {
|
|
IntRect rect = GetTileRect(mCurrentTile);
|
|
return rect.Size();
|
|
}
|
|
return TextureSourceD3D9::GetSize();
|
|
}
|
|
|
|
nsIntRect
|
|
DeprecatedTextureHostD3D9::GetTileRect()
|
|
{
|
|
IntRect rect = GetTileRect(mCurrentTile);
|
|
return nsIntRect(rect.x, rect.y, rect.width, rect.height);
|
|
}
|
|
|
|
static uint32_t GetRequiredTilesD3D9(uint32_t aSize, uint32_t aMaxSize)
|
|
{
|
|
uint32_t requiredTiles = aSize / aMaxSize;
|
|
if (aSize % aMaxSize) {
|
|
requiredTiles++;
|
|
}
|
|
return requiredTiles;
|
|
}
|
|
|
|
void
|
|
DeprecatedTextureHostD3D9::SetCompositor(Compositor* aCompositor)
|
|
{
|
|
mCompositor = static_cast<CompositorD3D9*>(aCompositor);
|
|
}
|
|
|
|
/**
|
|
* Helper method for DataToTexture and SurfaceToTexture.
|
|
* The last three params are out params.
|
|
* Returns the created texture, or null if we fail.
|
|
*/
|
|
TemporaryRef<IDirect3DTexture9>
|
|
TextureSourceD3D9::InitTextures(DeviceManagerD3D9* aDeviceManager,
|
|
const IntSize &aSize,
|
|
_D3DFORMAT aFormat,
|
|
RefPtr<IDirect3DSurface9>& aSurface,
|
|
D3DLOCKED_RECT& aLockedRect)
|
|
{
|
|
if (!aDeviceManager) {
|
|
return nullptr;
|
|
}
|
|
RefPtr<IDirect3DTexture9> result;
|
|
// D3D9Ex doesn't support managed textures and we don't want the hassle even
|
|
// if we don't have Ex. We could use dynamic textures
|
|
// here but since Images are immutable that probably isn't such a great
|
|
// idea.
|
|
result = aDeviceManager->CreateTexture(aSize, aFormat, D3DPOOL_DEFAULT, this);
|
|
if (!result) {
|
|
return nullptr;
|
|
}
|
|
|
|
RefPtr<IDirect3DTexture9> tmpTexture =
|
|
aDeviceManager->CreateTexture(aSize, aFormat, D3DPOOL_SYSTEMMEM, this);
|
|
if (!tmpTexture) {
|
|
return nullptr;
|
|
}
|
|
|
|
tmpTexture->GetSurfaceLevel(0, byRef(aSurface));
|
|
aSurface->LockRect(&aLockedRect, nullptr, 0);
|
|
if (!aLockedRect.pBits) {
|
|
NS_WARNING("Could not lock surface");
|
|
return nullptr;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Helper method for DataToTexture and SurfaceToTexture.
|
|
*/
|
|
static void
|
|
FinishTextures(DeviceManagerD3D9* aDeviceManager,
|
|
IDirect3DTexture9* aTexture,
|
|
IDirect3DSurface9* aSurface)
|
|
{
|
|
if (!aDeviceManager) {
|
|
return;
|
|
}
|
|
|
|
aSurface->UnlockRect();
|
|
nsRefPtr<IDirect3DSurface9> dstSurface;
|
|
aTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
|
|
aDeviceManager->device()->UpdateSurface(aSurface, nullptr, dstSurface,
|
|
nullptr);
|
|
}
|
|
|
|
TemporaryRef<IDirect3DTexture9>
|
|
TextureSourceD3D9::DataToTexture(DeviceManagerD3D9* aDeviceManager,
|
|
unsigned char *aData,
|
|
int aStride,
|
|
const IntSize &aSize,
|
|
_D3DFORMAT aFormat,
|
|
uint32_t aBPP)
|
|
{
|
|
RefPtr<IDirect3DSurface9> surface;
|
|
D3DLOCKED_RECT lockedRect;
|
|
RefPtr<IDirect3DTexture9> texture = InitTextures(aDeviceManager, aSize, aFormat,
|
|
surface, lockedRect);
|
|
if (!texture) {
|
|
return nullptr;
|
|
}
|
|
|
|
uint32_t width = aSize.width * aBPP;
|
|
|
|
for (int y = 0; y < aSize.height; y++) {
|
|
memcpy((char*)lockedRect.pBits + lockedRect.Pitch * y,
|
|
aData + aStride * y,
|
|
width);
|
|
}
|
|
|
|
FinishTextures(aDeviceManager, texture, surface);
|
|
|
|
return texture;
|
|
}
|
|
|
|
void
|
|
DeprecatedTextureHostD3D9::Reset()
|
|
{
|
|
mSize.width = 0;
|
|
mSize.height = 0;
|
|
mTexture = nullptr;
|
|
mIsTiled = false;
|
|
}
|
|
|
|
void
|
|
DeprecatedTextureHostShmemD3D9::UpdateImpl(const SurfaceDescriptor& aImage,
|
|
nsIntRegion *aRegion,
|
|
nsIntPoint *aOffset)
|
|
{
|
|
MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TShmem ||
|
|
aImage.type() == SurfaceDescriptor::TMemoryImage);
|
|
MOZ_ASSERT(mCompositor, "Must have compositor to update.");
|
|
|
|
if (!mCompositor->device()) {
|
|
return;
|
|
}
|
|
|
|
AutoOpenSurface openSurf(OPEN_READ_ONLY, aImage);
|
|
|
|
nsRefPtr<gfxImageSurface> surf = openSurf.GetAsImage();
|
|
|
|
mSize = ToIntSize(surf->GetSize());
|
|
|
|
uint32_t bpp = 0;
|
|
|
|
_D3DFORMAT format = D3DFMT_A8R8G8B8;
|
|
switch (surf->Format()) {
|
|
case gfxImageFormat::RGB24:
|
|
mFormat = SurfaceFormat::B8G8R8X8;
|
|
format = D3DFMT_X8R8G8B8;
|
|
bpp = 4;
|
|
break;
|
|
case gfxImageFormat::ARGB32:
|
|
mFormat = SurfaceFormat::B8G8R8A8;
|
|
format = D3DFMT_A8R8G8B8;
|
|
bpp = 4;
|
|
break;
|
|
case gfxImageFormat::A8:
|
|
mFormat = SurfaceFormat::A8;
|
|
format = D3DFMT_A8;
|
|
bpp = 1;
|
|
break;
|
|
default:
|
|
NS_ERROR("Bad image format");
|
|
}
|
|
|
|
int32_t maxSize = mCompositor->GetMaxTextureSize();
|
|
if (mSize.width <= maxSize && mSize.height <= maxSize) {
|
|
mTexture = DataToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
|
|
surf->Data(), surf->Stride(),
|
|
mSize, format, bpp);
|
|
if (!mTexture) {
|
|
NS_WARNING("Could not upload texture");
|
|
Reset();
|
|
return;
|
|
}
|
|
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 = surf->Data() +
|
|
tileRect.y * surf->Stride() +
|
|
tileRect.x * bpp;
|
|
mTileTextures[i] = DataToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
|
|
data,
|
|
surf->Stride(),
|
|
tileRect.Size(),
|
|
format,
|
|
bpp);
|
|
if (!mTileTextures[i]) {
|
|
NS_WARNING("Could not upload texture");
|
|
Reset();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
IntRect
|
|
DeprecatedTextureHostD3D9::GetTileRect(uint32_t aID) const
|
|
{
|
|
uint32_t maxSize = mCompositor->GetMaxTextureSize();
|
|
uint32_t horizontalTiles = GetRequiredTilesD3D9(mSize.width, maxSize);
|
|
uint32_t verticalTiles = GetRequiredTilesD3D9(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);
|
|
}
|
|
|
|
DeprecatedTextureHostYCbCrD3D9::DeprecatedTextureHostYCbCrD3D9()
|
|
: mCompositor(nullptr)
|
|
{
|
|
mFormat = SurfaceFormat::YUV;
|
|
|
|
MOZ_COUNT_CTOR(DeprecatedTextureHostYCbCrD3D9);
|
|
}
|
|
|
|
DeprecatedTextureHostYCbCrD3D9::~DeprecatedTextureHostYCbCrD3D9()
|
|
{
|
|
MOZ_COUNT_DTOR(DeprecatedTextureHostYCbCrD3D9);
|
|
}
|
|
|
|
void
|
|
DeprecatedTextureHostYCbCrD3D9::SetCompositor(Compositor* aCompositor)
|
|
{
|
|
mCompositor = static_cast<CompositorD3D9*>(aCompositor);
|
|
}
|
|
|
|
IntSize
|
|
DeprecatedTextureHostYCbCrD3D9::GetSize() const
|
|
{
|
|
return mSize;
|
|
}
|
|
|
|
void
|
|
DeprecatedTextureHostYCbCrD3D9::UpdateImpl(const SurfaceDescriptor& aImage,
|
|
nsIntRegion *aRegion,
|
|
nsIntPoint *aOffset)
|
|
{
|
|
MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TYCbCrImage);
|
|
|
|
if (!mCompositor->device()) {
|
|
return;
|
|
}
|
|
|
|
YCbCrImageDataDeserializer yuvDeserializer(aImage.get_YCbCrImage().data().get<uint8_t>(),
|
|
aImage.get_YCbCrImage().data().Size<uint8_t>());
|
|
|
|
mSize = yuvDeserializer.GetYSize();
|
|
IntSize cbCrSize = yuvDeserializer.GetCbCrSize();
|
|
mStereoMode = yuvDeserializer.GetStereoMode();
|
|
|
|
DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
|
|
RefPtr<DataTextureSource> srcY;
|
|
RefPtr<DataTextureSource> srcCb;
|
|
RefPtr<DataTextureSource> srcCr;
|
|
if (!mFirstSource) {
|
|
srcY = new DataTextureSourceD3D9(SurfaceFormat::A8, mCompositor,
|
|
TEXTURE_DISALLOW_BIGIMAGE, mStereoMode);
|
|
srcCb = new DataTextureSourceD3D9(SurfaceFormat::A8, mCompositor,
|
|
TEXTURE_DISALLOW_BIGIMAGE, mStereoMode);
|
|
srcCr = new DataTextureSourceD3D9(SurfaceFormat::A8, mCompositor,
|
|
TEXTURE_DISALLOW_BIGIMAGE, mStereoMode);
|
|
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<DataSourceSurface> wrapperY =
|
|
Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetYData(),
|
|
yuvDeserializer.GetYStride(),
|
|
yuvDeserializer.GetYSize(),
|
|
SurfaceFormat::A8);
|
|
RefPtr<DataSourceSurface> wrapperCb =
|
|
Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCbData(),
|
|
yuvDeserializer.GetCbCrStride(),
|
|
yuvDeserializer.GetCbCrSize(),
|
|
SurfaceFormat::A8);
|
|
RefPtr<DataSourceSurface> wrapperCr =
|
|
Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCrData(),
|
|
yuvDeserializer.GetCbCrStride(),
|
|
yuvDeserializer.GetCbCrSize(),
|
|
SurfaceFormat::A8);
|
|
// We don't support partial updates for YCbCr textures
|
|
NS_ASSERTION(!aRegion, "Unsupported partial updates for YCbCr textures");
|
|
if (!srcY->Update(wrapperY) ||
|
|
!srcCb->Update(wrapperCb) ||
|
|
!srcCr->Update(wrapperCr)) {
|
|
NS_WARNING("failed to update the DataTextureSource");
|
|
mSize.width = 0;
|
|
mSize.height = 0;
|
|
mFirstSource = nullptr;
|
|
return;
|
|
}
|
|
}
|
|
|
|
TemporaryRef<IDirect3DTexture9>
|
|
TextureSourceD3D9::TextureToTexture(DeviceManagerD3D9* aDeviceManager,
|
|
IDirect3DTexture9* aTexture,
|
|
const IntSize& aSize,
|
|
_D3DFORMAT aFormat)
|
|
{
|
|
if (!aDeviceManager) {
|
|
return nullptr;
|
|
}
|
|
|
|
RefPtr<IDirect3DTexture9> texture =
|
|
aDeviceManager->CreateTexture(aSize, aFormat, D3DPOOL_DEFAULT, this);
|
|
if (!texture) {
|
|
return nullptr;
|
|
}
|
|
|
|
HRESULT hr = aDeviceManager->device()->UpdateTexture(aTexture, texture);
|
|
if (FAILED(hr)) {
|
|
return nullptr;
|
|
}
|
|
|
|
return texture;
|
|
}
|
|
|
|
void
|
|
DeprecatedTextureHostSystemMemD3D9::UpdateImpl(const SurfaceDescriptor& aImage,
|
|
nsIntRegion *aRegion,
|
|
nsIntPoint *aOffset)
|
|
{
|
|
MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TSurfaceDescriptorD3D9);
|
|
MOZ_ASSERT(mCompositor, "Must have compositor to update.");
|
|
|
|
if (!mCompositor->device()) {
|
|
return;
|
|
}
|
|
|
|
IDirect3DTexture9* texture =
|
|
reinterpret_cast<IDirect3DTexture9*>(aImage.get_SurfaceDescriptorD3D9().texture());
|
|
|
|
if (!texture) {
|
|
Reset();
|
|
return;
|
|
}
|
|
|
|
D3DSURFACE_DESC desc;
|
|
texture->GetLevelDesc(0, &desc);
|
|
HRESULT hr = texture->GetLevelDesc(0, &desc);
|
|
if (FAILED(hr)) {
|
|
Reset();
|
|
return;
|
|
}
|
|
|
|
mSize.width = desc.Width;
|
|
mSize.height = desc.Height;
|
|
|
|
_D3DFORMAT format = desc.Format;
|
|
uint32_t bpp = 0;
|
|
switch (format) {
|
|
case D3DFMT_X8R8G8B8:
|
|
mFormat = SurfaceFormat::B8G8R8X8;
|
|
bpp = 4;
|
|
break;
|
|
case D3DFMT_A8R8G8B8:
|
|
mFormat = SurfaceFormat::B8G8R8A8;
|
|
bpp = 4;
|
|
break;
|
|
case D3DFMT_A8:
|
|
mFormat = SurfaceFormat::A8;
|
|
bpp = 1;
|
|
break;
|
|
default:
|
|
NS_ERROR("Bad image format");
|
|
}
|
|
|
|
int32_t maxSize = mCompositor->GetMaxTextureSize();
|
|
if (mSize.width <= maxSize && mSize.height <= maxSize) {
|
|
mIsTiled = false;
|
|
|
|
mTexture = TextureToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
|
|
texture, mSize, format);
|
|
if (!mTexture) {
|
|
NS_WARNING("Could not upload texture");
|
|
Reset();
|
|
return;
|
|
}
|
|
} 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);
|
|
RECT d3dTileRect;
|
|
d3dTileRect.left = tileRect.x;
|
|
d3dTileRect.top = tileRect.y;
|
|
d3dTileRect.right = tileRect.XMost();
|
|
d3dTileRect.bottom = tileRect.YMost();
|
|
D3DLOCKED_RECT lockedRect;
|
|
texture->LockRect(0, &lockedRect, &d3dTileRect, 0);
|
|
mTileTextures[i] = DataToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
|
|
reinterpret_cast<unsigned char*>(lockedRect.pBits),
|
|
lockedRect.Pitch,
|
|
tileRect.Size(),
|
|
format,
|
|
bpp);
|
|
texture->UnlockRect(0);
|
|
if (!mTileTextures[i]) {
|
|
NS_WARNING("Could not upload texture");
|
|
Reset();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TemporaryRef<IDirect3DTexture9>
|
|
TextureSourceD3D9::SurfaceToTexture(DeviceManagerD3D9* aDeviceManager,
|
|
gfxWindowsSurface* aSurface,
|
|
const IntSize& aSize,
|
|
_D3DFORMAT aFormat)
|
|
{
|
|
RefPtr<IDirect3DSurface9> surface;
|
|
D3DLOCKED_RECT lockedRect;
|
|
|
|
RefPtr<IDirect3DTexture9> texture = InitTextures(aDeviceManager, aSize, aFormat,
|
|
surface, lockedRect);
|
|
if (!texture) {
|
|
return nullptr;
|
|
}
|
|
|
|
nsRefPtr<gfxImageSurface> imgSurface =
|
|
new gfxImageSurface(reinterpret_cast<unsigned char*>(lockedRect.pBits),
|
|
gfxIntSize(aSize.width, aSize.height),
|
|
lockedRect.Pitch,
|
|
gfxPlatform::GetPlatform()->OptimalFormatForContent(aSurface->GetContentType()));
|
|
|
|
nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
|
|
context->SetSource(aSurface);
|
|
context->SetOperator(gfxContext::OPERATOR_SOURCE);
|
|
context->Paint();
|
|
|
|
FinishTextures(aDeviceManager, texture, surface);
|
|
|
|
return texture;
|
|
}
|
|
|
|
void
|
|
DeprecatedTextureHostDIB::UpdateImpl(const SurfaceDescriptor& aImage,
|
|
nsIntRegion *aRegion,
|
|
nsIntPoint *aOffset)
|
|
{
|
|
MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TSurfaceDescriptorDIB);
|
|
MOZ_ASSERT(mCompositor, "Must have compositor to update.");
|
|
|
|
if (!mCompositor->device()) {
|
|
return;
|
|
}
|
|
|
|
// We added an extra ref for transport, so we shouldn't AddRef now.
|
|
nsRefPtr<gfxWindowsSurface> surf =
|
|
dont_AddRef(reinterpret_cast<gfxWindowsSurface*>(aImage.get_SurfaceDescriptorDIB().surface()));
|
|
|
|
mSize = ToIntSize(surf->GetSize());
|
|
|
|
uint32_t bpp = 0;
|
|
|
|
_D3DFORMAT format = D3DFMT_A8R8G8B8;
|
|
switch (gfxPlatform::GetPlatform()->OptimalFormatForContent(surf->GetContentType())) {
|
|
case gfxImageFormat::RGB24:
|
|
mFormat = SurfaceFormat::B8G8R8X8;
|
|
format = D3DFMT_X8R8G8B8;
|
|
bpp = 4;
|
|
break;
|
|
case gfxImageFormat::ARGB32:
|
|
mFormat = SurfaceFormat::B8G8R8A8;
|
|
format = D3DFMT_A8R8G8B8;
|
|
bpp = 4;
|
|
break;
|
|
case gfxImageFormat::A8:
|
|
mFormat = SurfaceFormat::A8;
|
|
format = D3DFMT_A8;
|
|
bpp = 1;
|
|
break;
|
|
default:
|
|
NS_ERROR("Bad image format");
|
|
}
|
|
|
|
int32_t maxSize = mCompositor->GetMaxTextureSize();
|
|
if (mSize.width <= maxSize && mSize.height <= maxSize) {
|
|
mTexture = SurfaceToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
|
|
surf, mSize, format);
|
|
if (!mTexture) {
|
|
NS_WARNING("Could not upload texture");
|
|
Reset();
|
|
return;
|
|
}
|
|
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);
|
|
nsRefPtr<gfxImageSurface> imgSurface = surf->GetAsImageSurface();
|
|
unsigned char* data = imgSurface->Data() +
|
|
tileRect.y * imgSurface->Stride() +
|
|
tileRect.x * bpp;
|
|
mTileTextures[i] = DataToTexture(gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(),
|
|
data,
|
|
imgSurface->Stride(),
|
|
tileRect.Size(),
|
|
format,
|
|
bpp);
|
|
if (!mTileTextures[i]) {
|
|
NS_WARNING("Could not upload texture");
|
|
Reset();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
DeprecatedTextureClientD3D9::DeprecatedTextureClientD3D9(CompositableForwarder* aCompositableForwarder,
|
|
const TextureInfo& aTextureInfo)
|
|
: DeprecatedTextureClient(aCompositableForwarder, aTextureInfo)
|
|
{
|
|
MOZ_COUNT_CTOR(DeprecatedTextureClientD3D9);
|
|
}
|
|
|
|
DeprecatedTextureClientD3D9::~DeprecatedTextureClientD3D9()
|
|
{
|
|
MOZ_COUNT_DTOR(DeprecatedTextureClientD3D9);
|
|
Unlock();
|
|
mDescriptor = SurfaceDescriptor();
|
|
|
|
mDrawTarget = nullptr;
|
|
}
|
|
|
|
bool
|
|
DeprecatedTextureClientD3D9::EnsureAllocated(gfx::IntSize aSize,
|
|
gfxContentType aType)
|
|
{
|
|
if (mTexture) {
|
|
D3DSURFACE_DESC desc;
|
|
mTexture->GetLevelDesc(0, &desc);
|
|
|
|
if (desc.Width == aSize.width &&
|
|
desc.Height == aSize.height) {
|
|
return true;
|
|
}
|
|
|
|
Unlock();
|
|
mD3D9Surface = nullptr;
|
|
mTexture = nullptr;
|
|
}
|
|
|
|
mSize = aSize;
|
|
|
|
_D3DFORMAT format = D3DFMT_A8R8G8B8;
|
|
switch (aType) {
|
|
case gfxContentType::COLOR:
|
|
format = D3DFMT_X8R8G8B8;
|
|
break;
|
|
case gfxContentType::COLOR_ALPHA:
|
|
// fallback to DIB texture client
|
|
return false;
|
|
case gfxContentType::ALPHA:
|
|
format = D3DFMT_A8;
|
|
break;
|
|
default:
|
|
NS_ERROR("Bad image type");
|
|
}
|
|
|
|
DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
|
|
if (!deviceManager ||
|
|
!(mTexture = deviceManager->CreateTexture(aSize, format, D3DPOOL_SYSTEMMEM, nullptr))) {
|
|
NS_WARNING("Could not create texture");
|
|
return false;
|
|
}
|
|
|
|
MOZ_ASSERT(mTexture);
|
|
mDescriptor = SurfaceDescriptorD3D9(reinterpret_cast<uintptr_t>(mTexture.get()));
|
|
|
|
mContentType = aType;
|
|
return true;
|
|
}
|
|
|
|
gfxASurface*
|
|
DeprecatedTextureClientD3D9::LockSurface()
|
|
{
|
|
if (!gfxWindowsPlatform::GetPlatform()->GetD3D9Device()) {
|
|
// If the device has failed then we should not lock the surface,
|
|
// even if we could.
|
|
Unlock();
|
|
mD3D9Surface = nullptr;
|
|
mTexture = nullptr;
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
if (mSurface) {
|
|
return mSurface.get();
|
|
}
|
|
|
|
if (!mTexture) {
|
|
NS_WARNING("No texture to lock");
|
|
return nullptr;
|
|
}
|
|
|
|
if (!mD3D9Surface) {
|
|
HRESULT hr = mTexture->GetSurfaceLevel(0, getter_AddRefs(mD3D9Surface));
|
|
if (FAILED(hr)) {
|
|
NS_WARNING("Failed to get texture surface level.");
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
mSurface = new gfxWindowsSurface(mD3D9Surface);
|
|
if (!mSurface || mSurface->CairoStatus()) {
|
|
NS_WARNING("Could not create surface for d3d9 surface");
|
|
mSurface = nullptr;
|
|
return nullptr;
|
|
}
|
|
|
|
return mSurface.get();
|
|
}
|
|
|
|
DrawTarget*
|
|
DeprecatedTextureClientD3D9::LockDrawTarget()
|
|
{
|
|
if (!mDrawTarget) {
|
|
if (gfxASurface* surface = LockSurface()) {
|
|
mDrawTarget =
|
|
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(LockSurface(), mSize);
|
|
}
|
|
}
|
|
|
|
return mDrawTarget.get();
|
|
}
|
|
|
|
void
|
|
DeprecatedTextureClientD3D9::Unlock()
|
|
{
|
|
if (mDrawTarget) {
|
|
mDrawTarget->Flush();
|
|
mDrawTarget = nullptr;
|
|
}
|
|
|
|
if (mSurface) {
|
|
mSurface = nullptr;
|
|
}
|
|
}
|
|
|
|
void
|
|
DeprecatedTextureClientD3D9::SetDescriptor(const SurfaceDescriptor& aDescriptor)
|
|
{
|
|
if (aDescriptor.type() == SurfaceDescriptor::Tnull_t) {
|
|
EnsureAllocated(mSize, mContentType);
|
|
return;
|
|
}
|
|
|
|
mDescriptor = aDescriptor;
|
|
mSurface = nullptr;
|
|
mDrawTarget = nullptr;
|
|
|
|
if (aDescriptor.type() == SurfaceDescriptor::T__None) {
|
|
return;
|
|
}
|
|
|
|
MOZ_ASSERT(aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorD3D9);
|
|
Unlock();
|
|
mD3D9Surface = nullptr;
|
|
mTexture = reinterpret_cast<IDirect3DTexture9*>(
|
|
mDescriptor.get_SurfaceDescriptorD3D9().texture());
|
|
}
|
|
|
|
DeprecatedTextureClientDIB::DeprecatedTextureClientDIB(CompositableForwarder* aCompositableForwarder,
|
|
const TextureInfo& aTextureInfo)
|
|
: DeprecatedTextureClient(aCompositableForwarder, aTextureInfo)
|
|
{
|
|
MOZ_COUNT_CTOR(DeprecatedTextureClientDIB);
|
|
}
|
|
|
|
DeprecatedTextureClientDIB::~DeprecatedTextureClientDIB()
|
|
{
|
|
MOZ_COUNT_DTOR(DeprecatedTextureClientDIB);
|
|
Unlock();
|
|
// It is OK not to dealloc the surface descriptor because it is only a pointer
|
|
// to mSurface and we will release our strong reference to that automatically.
|
|
mDescriptor = SurfaceDescriptor();
|
|
mDrawTarget = nullptr;
|
|
}
|
|
|
|
bool
|
|
DeprecatedTextureClientDIB::EnsureAllocated(gfx::IntSize aSize,
|
|
gfxContentType aType)
|
|
{
|
|
if (mSurface) {
|
|
gfx::IntSize size = gfx::ToIntSize(mSurface->GetSize());
|
|
if (size.width == aSize.width &&
|
|
size.height == aSize.height) {
|
|
return true;
|
|
}
|
|
|
|
Unlock();
|
|
mSurface = nullptr;
|
|
}
|
|
|
|
mSurface = new gfxWindowsSurface(gfxIntSize(aSize.width, aSize.height),
|
|
gfxPlatform::GetPlatform()->OptimalFormatForContent(aType));
|
|
if (!mSurface || mSurface->CairoStatus())
|
|
{
|
|
NS_WARNING("Could not create surface");
|
|
mSurface = nullptr;
|
|
mDescriptor = SurfaceDescriptor();
|
|
return false;
|
|
}
|
|
mSize = aSize;
|
|
mContentType = aType;
|
|
|
|
mDescriptor = SurfaceDescriptorDIB(reinterpret_cast<uintptr_t>(mSurface.get()));
|
|
|
|
return true;
|
|
}
|
|
|
|
SurfaceDescriptor*
|
|
DeprecatedTextureClientDIB::LockSurfaceDescriptor()
|
|
{
|
|
// The host will release this ref when it receives the surface descriptor.
|
|
// We AddRef in case we die before the host receives the pointer.
|
|
NS_ASSERTION(mSurface == reinterpret_cast<gfxWindowsSurface*>(mDescriptor.get_SurfaceDescriptorDIB().surface()),
|
|
"SurfaceDescriptor is not up to date");
|
|
mSurface->AddRef();
|
|
return GetDescriptor();
|
|
}
|
|
|
|
gfxASurface*
|
|
DeprecatedTextureClientDIB::LockSurface()
|
|
{
|
|
if (mSurface) {
|
|
return mSurface.get();
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
DrawTarget*
|
|
DeprecatedTextureClientDIB::LockDrawTarget()
|
|
{
|
|
if (!mDrawTarget) {
|
|
if (gfxASurface* surface = LockSurface()) {
|
|
mDrawTarget =
|
|
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(LockSurface(), mSize);
|
|
}
|
|
}
|
|
|
|
return mDrawTarget.get();
|
|
}
|
|
|
|
void
|
|
DeprecatedTextureClientDIB::Unlock()
|
|
{
|
|
if (mDrawTarget) {
|
|
mDrawTarget->Flush();
|
|
mDrawTarget = nullptr;
|
|
}
|
|
}
|
|
|
|
void
|
|
DeprecatedTextureClientDIB::SetDescriptor(const SurfaceDescriptor& aDescriptor)
|
|
{
|
|
mDescriptor = aDescriptor;
|
|
mDrawTarget = nullptr;
|
|
|
|
if (aDescriptor.type() == SurfaceDescriptor::T__None) {
|
|
mSurface = nullptr;
|
|
return;
|
|
}
|
|
|
|
MOZ_ASSERT(aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorDIB);
|
|
Unlock();
|
|
mSurface = reinterpret_cast<gfxWindowsSurface*>(
|
|
mDescriptor.get_SurfaceDescriptorDIB().surface());
|
|
}
|
|
|
|
class D3D9TextureClientData : public TextureClientData
|
|
{
|
|
public:
|
|
D3D9TextureClientData(IDirect3DTexture9* aTexture)
|
|
: mTexture(aTexture)
|
|
{}
|
|
|
|
D3D9TextureClientData(gfxWindowsSurface* aWindowSurface)
|
|
: mWindowSurface(aWindowSurface)
|
|
{}
|
|
|
|
virtual void DeallocateSharedData(ISurfaceAllocator*) MOZ_OVERRIDE
|
|
{
|
|
mWindowSurface = nullptr;
|
|
mTexture = nullptr;
|
|
}
|
|
|
|
private:
|
|
RefPtr<IDirect3DTexture9> mTexture;
|
|
nsRefPtr<gfxWindowsSurface> mWindowSurface;
|
|
};
|
|
|
|
DataTextureSourceD3D9::DataTextureSourceD3D9(gfx::SurfaceFormat aFormat,
|
|
CompositorD3D9* aCompositor,
|
|
TextureFlags aFlags,
|
|
StereoMode aStereoMode)
|
|
: mFormat(aFormat)
|
|
, mCompositor(aCompositor)
|
|
, mCurrentTile(0)
|
|
, mFlags(aFlags)
|
|
, mIsTiled(false)
|
|
, mIterating(false)
|
|
{
|
|
mStereoMode = aStereoMode;
|
|
MOZ_COUNT_CTOR(DataTextureSourceD3D9);
|
|
}
|
|
|
|
DataTextureSourceD3D9::DataTextureSourceD3D9(gfx::SurfaceFormat aFormat,
|
|
gfx::IntSize aSize,
|
|
CompositorD3D9* aCompositor,
|
|
IDirect3DTexture9* aTexture,
|
|
TextureFlags aFlags)
|
|
: mFormat(aFormat)
|
|
, mCompositor(aCompositor)
|
|
, mCurrentTile(0)
|
|
, mFlags(aFlags)
|
|
, mIsTiled(false)
|
|
, mIterating(false)
|
|
{
|
|
mSize = aSize;
|
|
mTexture = aTexture;
|
|
mStereoMode = StereoMode::MONO;
|
|
MOZ_COUNT_CTOR(DataTextureSourceD3D9);
|
|
}
|
|
|
|
DataTextureSourceD3D9::~DataTextureSourceD3D9()
|
|
{
|
|
MOZ_COUNT_DTOR(DataTextureSourceD3D9);
|
|
}
|
|
|
|
IDirect3DTexture9*
|
|
DataTextureSourceD3D9::GetD3D9Texture()
|
|
{
|
|
return mIterating ? mTileTextures[mCurrentTile]
|
|
: mTexture;
|
|
}
|
|
|
|
bool
|
|
DataTextureSourceD3D9::Update(gfx::DataSourceSurface* aSurface,
|
|
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()) {
|
|
NS_WARNING("No D3D device to update the texture.");
|
|
return false;
|
|
}
|
|
mSize = aSurface->GetSize();
|
|
|
|
uint32_t bpp = 0;
|
|
|
|
_D3DFORMAT format = D3DFMT_A8R8G8B8;
|
|
mFormat = aSurface->GetFormat();
|
|
switch (mFormat) {
|
|
case SurfaceFormat::B8G8R8X8:
|
|
format = D3DFMT_X8R8G8B8;
|
|
bpp = 4;
|
|
break;
|
|
case SurfaceFormat::B8G8R8A8:
|
|
format = D3DFMT_A8R8G8B8;
|
|
bpp = 4;
|
|
break;
|
|
case SurfaceFormat::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) ||
|
|
(mFlags & TEXTURE_DISALLOW_BIGIMAGE)) {
|
|
mTexture = DataToTexture(deviceManager,
|
|
aSurface->GetData(), aSurface->Stride(),
|
|
IntSize(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);
|
|
mTexture = nullptr;
|
|
|
|
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(),
|
|
IntSize(tileRect.width, tileRect.height),
|
|
format,
|
|
bpp);
|
|
if (!mTileTextures[i]) {
|
|
NS_WARNING("Could not upload texture");
|
|
Reset();
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
DataTextureSourceD3D9::Update(gfxWindowsSurface* aSurface)
|
|
{
|
|
MOZ_ASSERT(aSurface);
|
|
if (!mCompositor || !mCompositor->device()) {
|
|
NS_WARNING("No D3D device to update the texture.");
|
|
return false;
|
|
}
|
|
mSize = ToIntSize(aSurface->GetSize());
|
|
|
|
uint32_t bpp = 0;
|
|
|
|
_D3DFORMAT format = D3DFMT_A8R8G8B8;
|
|
mFormat = ImageFormatToSurfaceFormat(
|
|
gfxPlatform::GetPlatform()->OptimalFormatForContent(aSurface->GetContentType()));
|
|
switch (mFormat) {
|
|
case SurfaceFormat::B8G8R8X8:
|
|
format = D3DFMT_X8R8G8B8;
|
|
bpp = 4;
|
|
break;
|
|
case SurfaceFormat::B8G8R8A8:
|
|
format = D3DFMT_A8R8G8B8;
|
|
bpp = 4;
|
|
break;
|
|
case SurfaceFormat::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) ||
|
|
(mFlags & TEXTURE_DISALLOW_BIGIMAGE)) {
|
|
mTexture = SurfaceToTexture(deviceManager, aSurface, mSize, format);
|
|
|
|
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);
|
|
mTexture = nullptr;
|
|
nsRefPtr<gfxImageSurface> imgSurface = aSurface->GetAsImageSurface();
|
|
|
|
for (uint32_t i = 0; i < tileCount; i++) {
|
|
IntRect tileRect = GetTileRect(i);
|
|
unsigned char* data = imgSurface->Data() +
|
|
tileRect.y * imgSurface->Stride() +
|
|
tileRect.x * bpp;
|
|
mTileTextures[i] = DataToTexture(deviceManager,
|
|
data,
|
|
imgSurface->Stride(),
|
|
IntSize(tileRect.width, tileRect.height),
|
|
format,
|
|
bpp);
|
|
if (!mTileTextures[i]) {
|
|
NS_WARNING("Could not upload texture");
|
|
Reset();
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void
|
|
DataTextureSourceD3D9::SetCompositor(Compositor* aCompositor)
|
|
{
|
|
CompositorD3D9* d3dCompositor = static_cast<CompositorD3D9*>(aCompositor);
|
|
if (mCompositor && mCompositor != d3dCompositor) {
|
|
Reset();
|
|
}
|
|
mCompositor = d3dCompositor;
|
|
}
|
|
|
|
void
|
|
DataTextureSourceD3D9::Reset()
|
|
{
|
|
mSize.width = 0;
|
|
mSize.height = 0;
|
|
mIsTiled = false;
|
|
mTexture = nullptr;
|
|
mTileTextures.clear();
|
|
}
|
|
|
|
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));
|
|
}
|
|
|
|
CairoTextureClientD3D9::CairoTextureClientD3D9(gfx::SurfaceFormat aFormat, TextureFlags aFlags)
|
|
: TextureClient(aFlags)
|
|
, mFormat(aFormat)
|
|
, mIsLocked(false)
|
|
, mNeedsClear(false)
|
|
, mLockRect(false)
|
|
{
|
|
MOZ_COUNT_CTOR(CairoTextureClientD3D9);
|
|
}
|
|
|
|
CairoTextureClientD3D9::~CairoTextureClientD3D9()
|
|
{
|
|
MOZ_COUNT_DTOR(CairoTextureClientD3D9);
|
|
}
|
|
|
|
bool
|
|
CairoTextureClientD3D9::Lock(OpenMode)
|
|
{
|
|
MOZ_ASSERT(!mIsLocked);
|
|
if (!IsValid() || !IsAllocated()) {
|
|
return false;
|
|
}
|
|
|
|
if (!gfxWindowsPlatform::GetPlatform()->GetD3D9Device()) {
|
|
// If the device has failed then we should not lock the surface,
|
|
// even if we could.
|
|
mD3D9Surface = nullptr;
|
|
return false;
|
|
}
|
|
|
|
if (!mD3D9Surface) {
|
|
HRESULT hr = mTexture->GetSurfaceLevel(0, getter_AddRefs(mD3D9Surface));
|
|
if (FAILED(hr)) {
|
|
NS_WARNING("Failed to get texture surface level.");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
mIsLocked = true;
|
|
|
|
if (mNeedsClear) {
|
|
mDrawTarget = GetAsDrawTarget();
|
|
mDrawTarget->ClearRect(Rect(0, 0, GetSize().width, GetSize().height));
|
|
mNeedsClear = false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void
|
|
CairoTextureClientD3D9::Unlock()
|
|
{
|
|
MOZ_ASSERT(mIsLocked, "Unlocked called while the texture is not locked!");
|
|
if (mDrawTarget) {
|
|
mDrawTarget->Flush();
|
|
mDrawTarget = nullptr;
|
|
}
|
|
|
|
if (mLockRect) {
|
|
mD3D9Surface->UnlockRect();
|
|
mLockRect = false;
|
|
}
|
|
|
|
if (mSurface) {
|
|
mSurface = nullptr;
|
|
}
|
|
mIsLocked = false;
|
|
}
|
|
|
|
bool
|
|
CairoTextureClientD3D9::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
|
|
{
|
|
MOZ_ASSERT(IsValid());
|
|
if (!IsAllocated()) {
|
|
return false;
|
|
}
|
|
|
|
aOutDescriptor = SurfaceDescriptorD3D9(reinterpret_cast<uintptr_t>(mTexture.get()));
|
|
return true;
|
|
}
|
|
|
|
TemporaryRef<gfx::DrawTarget>
|
|
CairoTextureClientD3D9::GetAsDrawTarget()
|
|
{
|
|
MOZ_ASSERT(mIsLocked && mD3D9Surface);
|
|
if (mDrawTarget) {
|
|
return mDrawTarget;
|
|
}
|
|
|
|
if (ContentForFormat(mFormat) == gfxContentType::COLOR) {
|
|
mSurface = new gfxWindowsSurface(mD3D9Surface);
|
|
if (!mSurface || mSurface->CairoStatus()) {
|
|
NS_WARNING("Could not create surface for d3d9 surface");
|
|
mSurface = nullptr;
|
|
return nullptr;
|
|
}
|
|
} else {
|
|
// gfxWindowsSurface don't support transparency so we can't use the d3d9
|
|
// windows surface optimization.
|
|
// Instead we have to use a gfxImageSurface and fallback for font drawing.
|
|
D3DLOCKED_RECT rect;
|
|
mD3D9Surface->LockRect(&rect, nullptr, 0);
|
|
mSurface = new gfxImageSurface((uint8_t*)rect.pBits, ThebesIntSize(mSize),
|
|
rect.Pitch, SurfaceFormatToImageFormat(mFormat));
|
|
mLockRect = true;
|
|
}
|
|
|
|
mDrawTarget =
|
|
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mSurface, mSize);
|
|
|
|
return mDrawTarget;
|
|
}
|
|
|
|
bool
|
|
CairoTextureClientD3D9::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags)
|
|
{
|
|
MOZ_ASSERT(!IsAllocated());
|
|
mSize = aSize;
|
|
_D3DFORMAT format = SurfaceFormatToD3D9Format(mFormat);
|
|
|
|
DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
|
|
if (!deviceManager ||
|
|
!(mTexture = deviceManager->CreateTexture(mSize, format, D3DPOOL_SYSTEMMEM, nullptr))) {
|
|
NS_WARNING("Could not create d3d9 texture");
|
|
return false;
|
|
}
|
|
|
|
mNeedsClear = aFlags & ALLOC_CLEAR_BUFFER;
|
|
|
|
MOZ_ASSERT(mTexture);
|
|
return true;
|
|
}
|
|
|
|
TextureClientData*
|
|
CairoTextureClientD3D9::DropTextureData()
|
|
{
|
|
TextureClientData* data = new D3D9TextureClientData(mTexture);
|
|
mTexture = nullptr;
|
|
MarkInvalid();
|
|
return data;
|
|
}
|
|
|
|
DIBTextureClientD3D9::DIBTextureClientD3D9(gfx::SurfaceFormat aFormat, TextureFlags aFlags)
|
|
: TextureClient(aFlags)
|
|
, mFormat(aFormat)
|
|
, mIsLocked(false)
|
|
{
|
|
MOZ_COUNT_CTOR(DIBTextureClientD3D9);
|
|
}
|
|
|
|
DIBTextureClientD3D9::~DIBTextureClientD3D9()
|
|
{
|
|
MOZ_COUNT_DTOR(DIBTextureClientD3D9);
|
|
}
|
|
|
|
bool
|
|
DIBTextureClientD3D9::Lock(OpenMode)
|
|
{
|
|
MOZ_ASSERT(!mIsLocked);
|
|
if (!IsValid()) {
|
|
return false;
|
|
}
|
|
mIsLocked = true;
|
|
return true;
|
|
}
|
|
|
|
void
|
|
DIBTextureClientD3D9::Unlock()
|
|
{
|
|
MOZ_ASSERT(mIsLocked, "Unlocked called while the texture is not locked!");
|
|
if (mDrawTarget) {
|
|
mDrawTarget->Flush();
|
|
mDrawTarget = nullptr;
|
|
}
|
|
|
|
mIsLocked = false;
|
|
}
|
|
|
|
bool
|
|
DIBTextureClientD3D9::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
|
|
{
|
|
MOZ_ASSERT(IsValid());
|
|
if (!IsAllocated()) {
|
|
return false;
|
|
}
|
|
MOZ_ASSERT(mSurface);
|
|
// The host will release this ref when it receives the surface descriptor.
|
|
// We AddRef in case we die before the host receives the pointer.
|
|
aOutDescriptor = SurfaceDescriptorDIB(reinterpret_cast<uintptr_t>(mSurface.get()));
|
|
mSurface->AddRef();
|
|
return true;
|
|
}
|
|
|
|
TemporaryRef<gfx::DrawTarget>
|
|
DIBTextureClientD3D9::GetAsDrawTarget()
|
|
{
|
|
MOZ_ASSERT(mIsLocked && IsAllocated());
|
|
|
|
if (!mDrawTarget) {
|
|
mDrawTarget =
|
|
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mSurface, mSize);
|
|
}
|
|
|
|
return mDrawTarget;
|
|
}
|
|
|
|
bool
|
|
DIBTextureClientD3D9::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags)
|
|
{
|
|
MOZ_ASSERT(!IsAllocated());
|
|
mSize = aSize;
|
|
|
|
mSurface = new gfxWindowsSurface(gfxIntSize(aSize.width, aSize.height),
|
|
SurfaceFormatToImageFormat(mFormat));
|
|
if (!mSurface || mSurface->CairoStatus())
|
|
{
|
|
NS_WARNING("Could not create surface");
|
|
mSurface = nullptr;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
TextureClientData*
|
|
DIBTextureClientD3D9::DropTextureData()
|
|
{
|
|
TextureClientData* data = new D3D9TextureClientData(mSurface);
|
|
mSurface = nullptr;
|
|
MarkInvalid();
|
|
return data;
|
|
}
|
|
|
|
SharedTextureClientD3D9::SharedTextureClientD3D9(gfx::SurfaceFormat aFormat, TextureFlags aFlags)
|
|
: TextureClient(aFlags)
|
|
, mFormat(aFormat)
|
|
, mHandle(0)
|
|
, mIsLocked(false)
|
|
{
|
|
MOZ_COUNT_CTOR(SharedTextureClientD3D9);
|
|
}
|
|
|
|
SharedTextureClientD3D9::~SharedTextureClientD3D9()
|
|
{
|
|
MOZ_COUNT_DTOR(SharedTextureClientD3D9);
|
|
}
|
|
|
|
TextureClientData*
|
|
SharedTextureClientD3D9::DropTextureData()
|
|
{
|
|
TextureClientData* data = new D3D9TextureClientData(mTexture);
|
|
mTexture = nullptr;
|
|
MarkInvalid();
|
|
return data;
|
|
}
|
|
|
|
bool
|
|
SharedTextureClientD3D9::Lock(OpenMode)
|
|
{
|
|
MOZ_ASSERT(!mIsLocked);
|
|
if (!IsValid()) {
|
|
return false;
|
|
}
|
|
mIsLocked = true;
|
|
return true;
|
|
}
|
|
|
|
void
|
|
SharedTextureClientD3D9::Unlock()
|
|
{
|
|
MOZ_ASSERT(mIsLocked, "Unlock called while the texture is not locked!");
|
|
}
|
|
|
|
bool
|
|
SharedTextureClientD3D9::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
|
|
{
|
|
MOZ_ASSERT(IsValid());
|
|
if (!IsAllocated()) {
|
|
return false;
|
|
}
|
|
|
|
aOutDescriptor = SurfaceDescriptorD3D10((WindowsHandle)(mHandle), mFormat);
|
|
return true;
|
|
}
|
|
|
|
TextureHostD3D9::TextureHostD3D9(TextureFlags aFlags,
|
|
const SurfaceDescriptorD3D9& aDescriptor)
|
|
: TextureHost(aFlags)
|
|
, mFormat(SurfaceFormat::UNKNOWN)
|
|
, mIsLocked(false)
|
|
{
|
|
mTexture = reinterpret_cast<IDirect3DTexture9*>(aDescriptor.texture());
|
|
MOZ_ASSERT(mTexture);
|
|
D3DSURFACE_DESC desc;
|
|
HRESULT hr = mTexture->GetLevelDesc(0, &desc);
|
|
if (!FAILED(hr)) {
|
|
mFormat = D3D9FormatToSurfaceFormat(desc.Format);
|
|
mSize.width = desc.Width;
|
|
mSize.height = desc.Height;
|
|
}
|
|
}
|
|
|
|
bool
|
|
DataTextureSourceD3D9::UpdateFromTexture(IDirect3DTexture9* aTexture,
|
|
const nsIntRegion* aRegion)
|
|
{
|
|
MOZ_ASSERT(aTexture);
|
|
|
|
D3DSURFACE_DESC desc;
|
|
HRESULT hr = aTexture->GetLevelDesc(0, &desc);
|
|
if (FAILED(hr)) {
|
|
return false;
|
|
} else {
|
|
// If we changed the compositor, the size might have been reset to zero
|
|
// Otherwise the texture size must not change.
|
|
MOZ_ASSERT(mFormat == D3D9FormatToSurfaceFormat(desc.Format));
|
|
MOZ_ASSERT(!mSize.width || mSize.width == desc.Width);
|
|
MOZ_ASSERT(!mSize.height || mSize.height == desc.Height);
|
|
mSize = IntSize(desc.Width, desc.Height);
|
|
}
|
|
|
|
DeviceManagerD3D9* dm = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
|
|
if (!mTexture) {
|
|
mTexture = dm->CreateTexture(mSize, SurfaceFormatToD3D9Format(mFormat),
|
|
D3DPOOL_DEFAULT, this);
|
|
if (!mTexture) {
|
|
NS_WARNING("Failed to create a texture");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
RefPtr<IDirect3DSurface9> srcSurface;
|
|
RefPtr<IDirect3DSurface9> dstSurface;
|
|
|
|
hr = aTexture->GetSurfaceLevel(0, byRef(srcSurface));
|
|
if (FAILED(hr)) {
|
|
return false;
|
|
}
|
|
hr = mTexture->GetSurfaceLevel(0, byRef(dstSurface));
|
|
if (FAILED(hr)) {
|
|
return false;
|
|
}
|
|
|
|
if (aRegion) {
|
|
nsIntRegionRectIterator iter(*aRegion);
|
|
const nsIntRect *iterRect;
|
|
while ((iterRect = iter.Next())) {
|
|
RECT rect;
|
|
rect.left = iterRect->x;
|
|
rect.top = iterRect->y;
|
|
rect.right = iterRect->XMost();
|
|
rect.bottom = iterRect->YMost();
|
|
|
|
POINT point;
|
|
point.x = iterRect->x;
|
|
point.y = iterRect->y;
|
|
hr = dm->device()->UpdateSurface(srcSurface, &rect, dstSurface, &point);
|
|
if (FAILED(hr)) {
|
|
NS_WARNING("Failed Update the surface");
|
|
return false;
|
|
}
|
|
}
|
|
} else {
|
|
hr = dm->device()->UpdateSurface(srcSurface, nullptr, dstSurface, nullptr);
|
|
if (FAILED(hr)) {
|
|
NS_WARNING("Failed Update the surface");
|
|
return false;
|
|
}
|
|
}
|
|
mIsTiled = false;
|
|
return true;
|
|
}
|
|
|
|
void
|
|
TextureHostD3D9::Updated(const nsIntRegion* aRegion)
|
|
{
|
|
if (!mTexture) {
|
|
return;
|
|
}
|
|
|
|
if (!mTextureSource) {
|
|
mTextureSource = new DataTextureSourceD3D9(mFormat, mSize, mCompositor,
|
|
nullptr, mFlags);
|
|
}
|
|
|
|
mTextureSource->UpdateFromTexture(mTexture, aRegion);
|
|
}
|
|
|
|
IDirect3DDevice9*
|
|
TextureHostD3D9::GetDevice()
|
|
{
|
|
return mCompositor ? mCompositor->device() : nullptr;
|
|
}
|
|
|
|
void
|
|
TextureHostD3D9::SetCompositor(Compositor* aCompositor)
|
|
{
|
|
mCompositor = static_cast<CompositorD3D9*>(aCompositor);
|
|
if (mTextureSource) {
|
|
mTextureSource->SetCompositor(aCompositor);
|
|
}
|
|
}
|
|
|
|
NewTextureSource*
|
|
TextureHostD3D9::GetTextureSources()
|
|
{
|
|
MOZ_ASSERT(mIsLocked);
|
|
return mTextureSource;
|
|
}
|
|
|
|
bool
|
|
TextureHostD3D9::Lock()
|
|
{
|
|
MOZ_ASSERT(!mIsLocked);
|
|
mIsLocked = true;
|
|
return true;
|
|
}
|
|
|
|
void
|
|
TextureHostD3D9::Unlock()
|
|
{
|
|
MOZ_ASSERT(mIsLocked);
|
|
mIsLocked = false;
|
|
}
|
|
|
|
void
|
|
TextureHostD3D9::DeallocateDeviceData()
|
|
{
|
|
mTextureSource = nullptr;
|
|
}
|
|
|
|
DIBTextureHostD3D9::DIBTextureHostD3D9(TextureFlags aFlags,
|
|
const SurfaceDescriptorDIB& aDescriptor)
|
|
: TextureHost(aFlags)
|
|
, mIsLocked(false)
|
|
{
|
|
// We added an extra ref for transport, so we shouldn't AddRef now.
|
|
mSurface =
|
|
dont_AddRef(reinterpret_cast<gfxWindowsSurface*>(aDescriptor.surface()));
|
|
MOZ_ASSERT(mSurface);
|
|
|
|
mSize = ToIntSize(mSurface->GetSize());
|
|
mFormat = ImageFormatToSurfaceFormat(
|
|
gfxPlatform::GetPlatform()->OptimalFormatForContent(mSurface->GetContentType()));
|
|
}
|
|
|
|
NewTextureSource*
|
|
DIBTextureHostD3D9::GetTextureSources()
|
|
{
|
|
if (!mTextureSource) {
|
|
Updated();
|
|
}
|
|
|
|
return mTextureSource;
|
|
}
|
|
|
|
void
|
|
DIBTextureHostD3D9::Updated(const nsIntRegion*)
|
|
{
|
|
if (!mTextureSource) {
|
|
mTextureSource = new DataTextureSourceD3D9(mFormat, mCompositor, mFlags);
|
|
}
|
|
|
|
if (!mTextureSource->Update(mSurface)) {
|
|
mTextureSource = nullptr;
|
|
}
|
|
}
|
|
|
|
bool
|
|
DIBTextureHostD3D9::Lock()
|
|
{
|
|
MOZ_ASSERT(!mIsLocked);
|
|
mIsLocked = true;
|
|
return true;
|
|
}
|
|
|
|
void
|
|
DIBTextureHostD3D9::Unlock()
|
|
{
|
|
MOZ_ASSERT(mIsLocked);
|
|
mIsLocked = false;
|
|
}
|
|
|
|
void
|
|
DIBTextureHostD3D9::SetCompositor(Compositor* aCompositor)
|
|
{
|
|
mCompositor = static_cast<CompositorD3D9*>(aCompositor);
|
|
}
|
|
|
|
void
|
|
DIBTextureHostD3D9::DeallocateDeviceData()
|
|
{
|
|
mTextureSource = nullptr;
|
|
}
|
|
|
|
}
|
|
}
|