Bug 874721. CompositorD3D9, r=Bas

This commit is contained in:
Nicholas Cameron 2013-08-01 16:50:52 +12:00
parent fba07cd7c6
commit e86327c405
30 changed files with 1917 additions and 149 deletions

View File

@ -446,7 +446,8 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
PaintState result;
// We need to disable rotation if we're going to be resampled when
// drawing, because we might sample across the rotation boundary.
bool canHaveRotation = !(aFlags & (PAINT_WILL_RESAMPLE | PAINT_NO_ROTATION));
bool canHaveRotation = gfxPlatform::BufferRotationEnabled() &&
!(aFlags & (PAINT_WILL_RESAMPLE | PAINT_NO_ROTATION));
nsIntRegion validRegion = aLayer->GetValidRegion();

View File

@ -40,6 +40,7 @@ struct YCbCrBufferInfo
uint32_t mYHeight;
uint32_t mCbCrWidth;
uint32_t mCbCrHeight;
StereoMode mStereoMode;
};
static YCbCrBufferInfo* GetYCbCrBufferInfo(uint8_t* aData)
@ -103,6 +104,12 @@ gfxIntSize YCbCrImageDataDeserializerBase::GetCbCrSize()
return gfxIntSize(info->mCbCrWidth, info->mCbCrHeight);
}
StereoMode YCbCrImageDataDeserializerBase::GetStereoMode()
{
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
return info->mStereoMode;
}
// Offset in bytes
static size_t ComputeOffset(uint32_t aHeight, uint32_t aStride)
{
@ -144,7 +151,8 @@ YCbCrImageDataSerializer::ComputeMinBufferSize(uint32_t aSize)
void
YCbCrImageDataSerializer::InitializeBufferInfo(const gfx::IntSize& aYSize,
const gfx::IntSize& aCbCrSize)
const gfx::IntSize& aCbCrSize,
StereoMode aStereoMode)
{
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
info->mYOffset = MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
@ -157,14 +165,17 @@ YCbCrImageDataSerializer::InitializeBufferInfo(const gfx::IntSize& aYSize,
info->mYHeight = aYSize.height;
info->mCbCrWidth = aCbCrSize.width;
info->mCbCrHeight = aCbCrSize.height;
info->mStereoMode = aStereoMode;
}
void
YCbCrImageDataSerializer::InitializeBufferInfo(const gfxIntSize& aYSize,
const gfxIntSize& aCbCrSize)
const gfxIntSize& aCbCrSize,
StereoMode aStereoMode)
{
InitializeBufferInfo(gfx::IntSize(aYSize.width, aYSize.height),
gfx::IntSize(aCbCrSize.width, aCbCrSize.height));
gfx::IntSize(aCbCrSize.width, aCbCrSize.height),
aStereoMode);
}
static void CopyLineWithSkip(const uint8_t* src, uint8_t* dst, uint32_t len, uint32_t skip) {

View File

@ -66,6 +66,11 @@ public:
*/
gfxIntSize GetCbCrSize();
/**
* Stereo mode for the image.
*/
StereoMode GetStereoMode();
/**
* Return a pointer to the begining of the data buffer.
*/
@ -111,9 +116,11 @@ public:
* buffer on which we want to store the image.
*/
void InitializeBufferInfo(const gfx::IntSize& aYSize,
const gfx::IntSize& aCbCrSize);
const gfx::IntSize& aCbCrSize,
StereoMode aStereoMode);
void InitializeBufferInfo(const gfxIntSize& aYSize,
const gfxIntSize& aCbCrSize);
const gfxIntSize& aCbCrSize,
StereoMode aStereoMode);
bool CopyData(const uint8_t* aYData,
const uint8_t* aCbData, const uint8_t* aCrData,

View File

@ -10,6 +10,7 @@
#include "mozilla/layers/CompositableForwarder.h"
#include "gfxPlatform.h"
#ifdef XP_WIN
#include "mozilla/layers/TextureD3D9.h"
#include "mozilla/layers/TextureD3D11.h"
#include "gfxWindowsPlatform.h"
#endif
@ -112,6 +113,7 @@ CompositableClient::CreateDeprecatedTextureClient(DeprecatedTextureClientType aD
break;
case TEXTURE_YCBCR:
if (parentBackend == LAYERS_OPENGL ||
parentBackend == LAYERS_D3D9 ||
parentBackend == LAYERS_D3D11 ||
parentBackend == LAYERS_BASIC) {
result = new DeprecatedTextureClientShmemYCbCr(GetForwarder(), GetTextureInfo());
@ -123,6 +125,10 @@ CompositableClient::CreateDeprecatedTextureClient(DeprecatedTextureClientType aD
result = new DeprecatedTextureClientD3D11(GetForwarder(), GetTextureInfo());
break;
}
if (parentBackend == LAYERS_D3D9) {
result = new DeprecatedTextureClientD3D9(GetForwarder(), GetTextureInfo());
break;
}
#endif
// fall through to TEXTURE_SHMEM
case TEXTURE_SHMEM:

View File

@ -26,9 +26,10 @@ ContentClient::CreateContentClient(CompositableForwarder* aForwarder)
{
LayersBackend backend = aForwarder->GetCompositorBackendType();
if (backend != LAYERS_OPENGL &&
backend != LAYERS_D3D9 &&
backend != LAYERS_D3D11 &&
backend != LAYERS_BASIC) {
return nullptr;
return nullptr;
}
bool useDoubleBuffering = false;

View File

@ -121,7 +121,7 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer,
mFrontBuffer = CreateBufferTextureClient(gfx::FORMAT_YUV);
gfx::IntSize ySize(data->mYSize.width, data->mYSize.height);
gfx::IntSize cbCrSize(data->mCbCrSize.width, data->mCbCrSize.height);
if (!mFrontBuffer->AsTextureClientYCbCr()->AllocateForYCbCr(ySize, cbCrSize)) {
if (!mFrontBuffer->AsTextureClientYCbCr()->AllocateForYCbCr(ySize, cbCrSize, data->mStereoMode)) {
mFrontBuffer = nullptr;
return false;
}

View File

@ -210,7 +210,9 @@ BufferTextureClient::UpdateYCbCr(const PlanarYCbCrImage::Data& aData)
}
bool
BufferTextureClient::AllocateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize)
BufferTextureClient::AllocateForYCbCr(gfx::IntSize aYSize,
gfx::IntSize aCbCrSize,
StereoMode aStereoMode)
{
size_t bufSize = YCbCrImageDataSerializer::ComputeMinBufferSize(aYSize,
aCbCrSize);
@ -219,7 +221,8 @@ BufferTextureClient::AllocateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSiz
}
YCbCrImageDataSerializer serializer(GetBuffer());
serializer.InitializeBufferInfo(aYSize,
aCbCrSize);
aCbCrSize,
aStereoMode);
return true;
}
@ -549,7 +552,8 @@ bool AutoLockYCbCrClient::EnsureDeprecatedTextureClient(PlanarYCbCrImage* aImage
YCbCrImageDataSerializer serializer(shmem.get<uint8_t>());
serializer.InitializeBufferInfo(data->mYSize,
data->mCbCrSize);
data->mCbCrSize,
data->mStereoMode);
*mDescriptor = YCbCrImage(shmem, 0);

View File

@ -54,7 +54,9 @@ class TextureClientYCbCr
{
public:
virtual bool UpdateYCbCr(const PlanarYCbCrImage::Data& aData) = 0;
virtual bool AllocateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize) = 0;
virtual bool AllocateForYCbCr(gfx::IntSize aYSize,
gfx::IntSize aCbCrSize,
StereoMode aStereoMode) = 0;
};
@ -207,7 +209,9 @@ public:
virtual bool UpdateYCbCr(const PlanarYCbCrImage::Data& aData) MOZ_OVERRIDE;
virtual bool AllocateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize) MOZ_OVERRIDE;
virtual bool AllocateForYCbCr(gfx::IntSize aYSize,
gfx::IntSize aCbCrSize,
StereoMode aStereoMode) MOZ_OVERRIDE;
gfx::SurfaceFormat GetFormat() const { return mFormat; }

View File

@ -27,15 +27,11 @@ TemporaryRef<DeprecatedTextureHost> CreateBasicDeprecatedTextureHost(SurfaceDesc
uint32_t aDeprecatedTextureHostFlags,
uint32_t aTextureFlags);
#ifdef XP_WIN
TemporaryRef<DeprecatedTextureHost> CreateDeprecatedTextureHostD3D9(SurfaceDescriptorType aDescriptorType,
uint32_t aDeprecatedTextureHostFlags,
uint32_t aTextureFlags)
{
NS_RUNTIMEABORT("not implemented");
return nullptr;
}
uint32_t aTextureFlags);
#ifdef XP_WIN
TemporaryRef<DeprecatedTextureHost> CreateDeprecatedTextureHostD3D11(SurfaceDescriptorType aDescriptorType,
uint32_t aDeprecatedTextureHostFlags,
uint32_t aTextureFlags);
@ -51,11 +47,11 @@ DeprecatedTextureHost::CreateDeprecatedTextureHost(SurfaceDescriptorType aDescri
return CreateDeprecatedTextureHostOGL(aDescriptorType,
aDeprecatedTextureHostFlags,
aTextureFlags);
#ifdef XP_WIN
case LAYERS_D3D9:
return CreateDeprecatedTextureHostD3D9(aDescriptorType,
aDeprecatedTextureHostFlags,
aTextureFlags);
#ifdef XP_WIN
case LAYERS_D3D11:
return CreateDeprecatedTextureHostD3D11(aDescriptorType,
aDeprecatedTextureHostFlags,

View File

@ -31,6 +31,7 @@ class Compositor;
class SurfaceDescriptor;
class ISurfaceAllocator;
class TextureSourceOGL;
class TextureSourceD3D9;
class TextureSourceD3D11;
class TextureSourceBasic;
class TextureParent;
@ -87,18 +88,11 @@ public:
virtual gfx::SurfaceFormat GetFormat() const { return gfx::FORMAT_UNKNOWN; }
/**
* Cast to a TextureSource for the OpenGL backend.
* Cast to a TextureSource for for each backend..
*/
virtual TextureSourceOGL* AsSourceOGL() { return nullptr; }
/**
* Cast to a TextureSource for the D3D11 backend.
*/
virtual TextureSourceD3D9* AsSourceD3D9() { return nullptr; }
virtual TextureSourceD3D11* AsSourceD3D11() { return nullptr; }
/**
* Cast to a TextureSource for the software backend.
*/
virtual TextureSourceBasic* AsSourceBasic() { return nullptr; }
/**

View File

@ -46,7 +46,7 @@ RenderColorLayerD3D9(ColorLayer* aLayer, LayerManagerD3D9 *aManager)
color[2] = (float)(layerColor.b * opacity);
color[3] = (float)(opacity);
aManager->device()->SetPixelShaderConstantF(0, color, 1);
aManager->device()->SetPixelShaderConstantF(CBvColor, color, 1);
aManager->SetShaderMode(DeviceManagerD3D9::SOLIDCOLORLAYER,
aLayer->GetMaskLayer());

View File

@ -0,0 +1,560 @@
/* -*- 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 "CompositorD3D9.h"
#include "LayerManagerD3D9Shaders.h"
#include "gfxWindowsPlatform.h"
#include "nsIWidget.h"
#include "mozilla/layers/ImageHost.h"
#include "mozilla/layers/ContentHost.h"
#include "mozilla/layers/Effects.h"
#include "nsWindowsHelpers.h"
#include "Nv3DVUtils.h"
#include "gfxFailure.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
CompositorD3D9::CompositorD3D9(nsIWidget *aWidget)
: mWidget(aWidget)
{
sBackend = LAYERS_D3D9;
}
CompositorD3D9::~CompositorD3D9()
{
mSwapChain = nullptr;
mDeviceManager = nullptr;
}
bool
CompositorD3D9::Initialize()
{
if (!gfxPlatform::CanUseDirect3D9()) {
NS_WARNING("Direct3D 9-accelerated layers are not supported on this system.");
return false;
}
mDeviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
if (!mDeviceManager) {
return false;
}
mSwapChain = mDeviceManager->
CreateSwapChain((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW));
if (!mSwapChain) {
return false;
}
return true;
}
TextureFactoryIdentifier
CompositorD3D9::GetTextureFactoryIdentifier()
{
TextureFactoryIdentifier ident;
ident.mMaxTextureSize = GetMaxTextureSize();
ident.mParentBackend = LAYERS_D3D9;
return ident;
}
bool
CompositorD3D9::CanUseCanvasLayerForSize(const gfxIntSize &aSize)
{
int32_t maxTextureSize = GetMaxTextureSize();
if (aSize.width > maxTextureSize || aSize.height > maxTextureSize) {
return false;
}
return true;
}
int32_t
CompositorD3D9::GetMaxTextureSize() const
{
return mDeviceManager->GetMaxTextureSize();
}
TemporaryRef<CompositingRenderTarget>
CompositorD3D9::CreateRenderTarget(const gfx::IntRect &aRect,
SurfaceInitMode aInit)
{
RefPtr<IDirect3DTexture9> texture;
HRESULT hr = device()->CreateTexture(aRect.width, aRect.height, 1,
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT, byRef(texture),
NULL);
if (FAILED(hr)) {
ReportFailure(NS_LITERAL_CSTRING("CompositorD3D9::CreateRenderTarget: Failed to create texture"),
hr);
return nullptr;
}
RefPtr<CompositingRenderTargetD3D9> rt =
new CompositingRenderTargetD3D9(texture, aInit, IntSize(aRect.width, aRect.height));
return rt;
}
// TODO this method doesn't actually use aSource - do we need it to? (d3d11 doesn't)
TemporaryRef<CompositingRenderTarget>
CompositorD3D9::CreateRenderTargetFromSource(const gfx::IntRect &aRect,
const CompositingRenderTarget *aSource)
{
RefPtr<IDirect3DTexture9> texture;
HRESULT hr = device()->CreateTexture(aRect.width, aRect.height, 1,
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT, byRef(texture),
NULL);
if (FAILED(hr)) {
ReportFailure(NS_LITERAL_CSTRING("CompositorD3D9::CreateRenderTarget: Failed to create texture"),
hr);
return nullptr;
}
RefPtr<CompositingRenderTargetD3D9> rt =
new CompositingRenderTargetD3D9(texture, INIT_MODE_NONE, IntSize(aRect.width, aRect.height));
return rt;
}
void
CompositorD3D9::SetRenderTarget(CompositingRenderTarget *aRenderTarget)
{
MOZ_ASSERT(aRenderTarget);
RefPtr<CompositingRenderTargetD3D9> oldRT = mCurrentRT;
mCurrentRT = static_cast<CompositingRenderTargetD3D9*>(aRenderTarget);
mCurrentRT->BindRenderTarget(device());
PrepareViewport(mCurrentRT->GetSize(), gfxMatrix());
}
static DeviceManagerD3D9::ShaderMode
ShaderModeForEffectType(EffectTypes aEffectType)
{
switch (aEffectType) {
case EFFECT_SOLID_COLOR:
return DeviceManagerD3D9::SOLIDCOLORLAYER;
case EFFECT_BGRA:
case EFFECT_RENDER_TARGET:
return DeviceManagerD3D9::RGBALAYER;
case EFFECT_BGRX:
return DeviceManagerD3D9::RGBLAYER;
case EFFECT_YCBCR:
return DeviceManagerD3D9::YCBCRLAYER;
}
MOZ_CRASH("Bad effect type");
}
void
CompositorD3D9::DrawQuad(const gfx::Rect &aRect, const gfx::Rect &aClipRect,
const EffectChain &aEffectChain,
gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform,
const gfx::Point &aOffset)
{
MOZ_ASSERT(mCurrentRT, "No render target");
device()->SetVertexShaderConstantF(CBmLayerTransform, &aTransform._11, 4);
float renderTargetOffset[] = { aOffset.x, aOffset.y, 0, 0 };
device()->SetVertexShaderConstantF(CBvRenderTargetOffset,
renderTargetOffset,
1);
device()->SetVertexShaderConstantF(CBvLayerQuad,
ShaderConstantRect(aRect.x,
aRect.y,
aRect.width,
aRect.height),
1);
bool target = false;
if (aEffectChain.mPrimaryEffect->mType != EFFECT_SOLID_COLOR) {
float opacity[4];
/*
* We always upload a 4 component float, but the shader will use only the
* first component since it's declared as a 'float'.
*/
opacity[0] = aOpacity;
device()->SetPixelShaderConstantF(CBfLayerOpacity, opacity, 1);
}
bool isPremultiplied = true;
MaskType maskType = MaskNone;
if (aEffectChain.mSecondaryEffects[EFFECT_MASK]) {
if (aTransform.Is2D()) {
maskType = Mask2d;
} else {
maskType = Mask3d;
}
}
RECT scissor;
scissor.left = aClipRect.x;
scissor.right = aClipRect.XMost();
scissor.top = aClipRect.y;
scissor.bottom = aClipRect.YMost();
device()->SetScissorRect(&scissor);
uint32_t maskTexture = 0;
switch (aEffectChain.mPrimaryEffect->mType) {
case EFFECT_SOLID_COLOR:
{
// output color is premultiplied, so we need to adjust all channels.
Color layerColor =
static_cast<EffectSolidColor*>(aEffectChain.mPrimaryEffect.get())->mColor;
float color[4];
color[0] = layerColor.r * layerColor.a * aOpacity;
color[1] = layerColor.g * layerColor.a * aOpacity;
color[2] = layerColor.b * layerColor.a * aOpacity;
color[3] = layerColor.a * aOpacity;
device()->SetPixelShaderConstantF(CBvColor, color, 1);
maskTexture = mDeviceManager
->SetShaderMode(DeviceManagerD3D9::SOLIDCOLORLAYER, maskType);
}
break;
case EFFECT_RENDER_TARGET:
case EFFECT_BGRX:
case EFFECT_BGRA:
{
TexturedEffect* texturedEffect =
static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
Rect textureCoords = texturedEffect->mTextureCoords;
device()->SetVertexShaderConstantF(CBvTextureCoords,
ShaderConstantRect(
textureCoords.x,
textureCoords.y,
textureCoords.width,
textureCoords.height),
1);
SetSamplerForFilter(texturedEffect->mFilter);
TextureSourceD3D9* source = texturedEffect->mTexture->AsSourceD3D9();
device()->SetTexture(0, source->GetD3D9Texture());
maskTexture = mDeviceManager
->SetShaderMode(ShaderModeForEffectType(aEffectChain.mPrimaryEffect->mType),
maskType);
isPremultiplied = texturedEffect->mPremultiplied;
}
break;
case EFFECT_YCBCR:
{
EffectYCbCr* ycbcrEffect =
static_cast<EffectYCbCr*>(aEffectChain.mPrimaryEffect.get());
SetSamplerForFilter(FILTER_LINEAR);
Rect textureCoords = ycbcrEffect->mTextureCoords;
device()->SetVertexShaderConstantF(CBvTextureCoords,
ShaderConstantRect(
textureCoords.x,
textureCoords.y,
textureCoords.width,
textureCoords.height),
1);
TextureSourceD3D9* source = ycbcrEffect->mTexture->AsSourceD3D9();
TextureSourceD3D9::YCbCrTextures textures = source->GetYCbCrTextures();
/*
* Send 3d control data and metadata
*/
if (mDeviceManager->GetNv3DVUtils()) {
Nv_Stereo_Mode mode;
switch (textures.mStereoMode) {
case STEREO_MODE_LEFT_RIGHT:
mode = NV_STEREO_MODE_LEFT_RIGHT;
break;
case STEREO_MODE_RIGHT_LEFT:
mode = NV_STEREO_MODE_RIGHT_LEFT;
break;
case STEREO_MODE_BOTTOM_TOP:
mode = NV_STEREO_MODE_BOTTOM_TOP;
break;
case STEREO_MODE_TOP_BOTTOM:
mode = NV_STEREO_MODE_TOP_BOTTOM;
break;
case STEREO_MODE_MONO:
mode = NV_STEREO_MODE_MONO;
break;
}
// 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) {
mDeviceManager->GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE);
nsRefPtr<IDirect3DSurface9> renderTarget;
device()->GetRenderTarget(0, getter_AddRefs(renderTarget));
mDeviceManager->GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)aRect.width,
(unsigned int)aRect.height,
(HANDLE)(textures.mY),
(HANDLE)(renderTarget));
}
}
// 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.
device()->SetTexture(0, textures.mY);
device()->SetTexture(1, textures.mCb);
device()->SetTexture(2, textures.mCr);
maskTexture = mDeviceManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER, maskType);
}
break;
case EFFECT_COMPONENT_ALPHA:
{
EffectComponentAlpha* effectComponentAlpha =
static_cast<EffectComponentAlpha*>(aEffectChain.mPrimaryEffect.get());
TextureSourceD3D9* sourceOnWhite = effectComponentAlpha->mOnWhite->AsSourceD3D9();
TextureSourceD3D9* sourceOnBlack = effectComponentAlpha->mOnBlack->AsSourceD3D9();
Rect textureCoords = effectComponentAlpha->mTextureCoords;
device()->SetVertexShaderConstantF(CBvTextureCoords,
ShaderConstantRect(
textureCoords.x,
textureCoords.y,
textureCoords.width,
textureCoords.height),
1);
SetSamplerForFilter(effectComponentAlpha->mFilter);
SetMask(aEffectChain, maskTexture);
maskTexture = mDeviceManager->SetShaderMode(DeviceManagerD3D9::COMPONENTLAYERPASS1, maskType);
device()->SetTexture(0, sourceOnBlack->GetD3D9Texture());
device()->SetTexture(1, sourceOnWhite->GetD3D9Texture());
device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
device()->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
device()->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
maskTexture = mDeviceManager->SetShaderMode(DeviceManagerD3D9::COMPONENTLAYERPASS2, maskType);
device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
device()->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
// Restore defaults
device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
device()->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
device()->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
device()->SetTexture(1, NULL);
}
return;
default:
NS_WARNING("Unknown shader type");
return;
}
SetMask(aEffectChain, maskTexture);
if (!isPremultiplied) {
device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
device()->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
}
HRESULT hr = device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
if (!isPremultiplied) {
device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
device()->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
}
}
void
CompositorD3D9::SetMask(const EffectChain &aEffectChain, uint32_t aMaskTexture)
{
EffectMask *maskEffect =
static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EFFECT_MASK].get());
if (!maskEffect) {
return;
}
TextureSourceD3D9 *source = maskEffect->mMaskTexture->AsSourceD3D9();
MOZ_ASSERT(aMaskTexture >= 0);
device()->SetTexture(aMaskTexture, source->GetD3D9Texture());
const gfx::Matrix4x4& maskTransform = maskEffect->mMaskTransform;
NS_ASSERTION(maskTransform.Is2D(), "How did we end up with a 3D transform here?!");
Rect bounds = Rect(Point(), Size(maskEffect->mSize));
bounds = maskTransform.As2D().TransformBounds(bounds);
device()->SetVertexShaderConstantF(DeviceManagerD3D9::sMaskQuadRegister,
ShaderConstantRect(bounds.x,
bounds.y,
bounds.width,
bounds.height),
1);
}
void
CompositorD3D9::BeginFrame(const Rect *aClipRectIn,
const gfxMatrix& aTransform,
const Rect& aRenderBounds,
Rect *aClipRectOut,
Rect *aRenderBoundsOut)
{
if (!mSwapChain->PrepareForRendering()) {
return;
}
mDeviceManager->SetupRenderState();
nsIntRect rect;
mWidget->GetClientBounds(rect);
device()->Clear(0, NULL, D3DCLEAR_TARGET, 0x00000000, 0, 0);
device()->BeginScene();
if (aClipRectOut) {
*aClipRectOut = Rect(0, 0, rect.width, rect.height);
}
if (aRenderBoundsOut) {
*aRenderBoundsOut = Rect(0, 0, rect.width, rect.height);
}
RECT r;
if (aClipRectIn) {
r.left = (LONG)aClipRectIn->x;
r.top = (LONG)aClipRectIn->y;
r.right = (LONG)(aClipRectIn->x + aClipRectIn->width);
r.bottom = (LONG)(aClipRectIn->y + aClipRectIn->height);
} else {
r.left = r.top = 0;
r.right = rect.width;
r.bottom = rect.height;
}
device()->SetScissorRect(&r);
nsRefPtr<IDirect3DSurface9> backBuffer = mSwapChain->GetBackBuffer();
mDefaultRT = new CompositingRenderTargetD3D9(backBuffer,
INIT_MODE_CLEAR,
IntSize(rect.width, rect.height));
SetRenderTarget(mDefaultRT);
}
void
CompositorD3D9::EndFrame()
{
device()->EndScene();
if (!!mTarget) {
PaintToTarget();
} else {
mSwapChain->Present();
}
mCurrentRT = nullptr;
}
void
CompositorD3D9::PrepareViewport(const gfx::IntSize& aSize,
const gfxMatrix &aWorldTransform)
{
gfx3DMatrix viewMatrix;
/*
* Matrix to transform to viewport space ( <-1.0, 1.0> topleft,
* <1.0, -1.0> bottomright)
*/
viewMatrix._11 = 2.0f / aSize.width;
viewMatrix._22 = -2.0f / aSize.height;
viewMatrix._41 = -1.0f;
viewMatrix._42 = 1.0f;
viewMatrix = gfx3DMatrix::From2D(aWorldTransform) * viewMatrix;
HRESULT hr = device()->SetVertexShaderConstantF(CBmProjection, &viewMatrix._11, 4);
if (FAILED(hr)) {
NS_WARNING("Failed to set projection matrix");
}
}
nsIntSize&
CompositorD3D9::GetWidgetSize()
{
nsIntRect rect;
mWidget->GetClientBounds(rect);
mSize = rect.Size();
return mSize;
}
void
CompositorD3D9::SetSamplerForFilter(Filter aFilter)
{
switch (aFilter) {
case FILTER_LINEAR:
device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
return;
case FILTER_POINT:
device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
return;
default:
device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
}
}
void
CompositorD3D9::PaintToTarget()
{
nsRefPtr<IDirect3DSurface9> backBuff;
nsRefPtr<IDirect3DSurface9> destSurf;
device()->GetRenderTarget(0, getter_AddRefs(backBuff));
D3DSURFACE_DESC desc;
backBuff->GetDesc(&desc);
device()->CreateOffscreenPlainSurface(desc.Width, desc.Height,
D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM,
getter_AddRefs(destSurf), NULL);
device()->GetRenderTargetData(backBuff, destSurf);
D3DLOCKED_RECT rect;
destSurf->LockRect(&rect, NULL, D3DLOCK_READONLY);
nsRefPtr<gfxImageSurface> imageSurface =
new gfxImageSurface((unsigned char*)rect.pBits,
gfxIntSize(desc.Width, desc.Height),
rect.Pitch,
gfxASurface::ImageFormatARGB32);
mTarget->SetSource(imageSurface);
mTarget->SetOperator(gfxContext::OPERATOR_OVER);
mTarget->Paint();
destSurf->UnlockRect();
}
void
CompositorD3D9::ReportFailure(const nsACString &aMsg, HRESULT aCode)
{
// We could choose to abort here when hr == E_OUTOFMEMORY.
nsCString msg;
msg.Append(aMsg);
msg.AppendLiteral(" Error code: ");
msg.AppendInt(uint32_t(aCode));
NS_WARNING(msg.BeginReading());
gfx::LogFailure(msg);
}
}
}

View File

@ -0,0 +1,133 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_GFX_COMPOSITORD3D9_H
#define MOZILLA_GFX_COMPOSITORD3D9_H
#include "mozilla/layers/Compositor.h"
#include "mozilla/layers/TextureD3D9.h"
#include "DeviceManagerD3D9.h"
class nsWidget;
namespace mozilla {
namespace layers {
class CompositorD3D9 : public Compositor
{
public:
CompositorD3D9(nsIWidget *aWidget);
~CompositorD3D9();
virtual bool Initialize() MOZ_OVERRIDE;
virtual void Destroy() MOZ_OVERRIDE {}
virtual TextureFactoryIdentifier
GetTextureFactoryIdentifier() MOZ_OVERRIDE;
virtual bool CanUseCanvasLayerForSize(const gfxIntSize &aSize) MOZ_OVERRIDE;
virtual int32_t GetMaxTextureSize() const MOZ_FINAL;
virtual void SetTargetContext(gfxContext *aTarget) MOZ_OVERRIDE
{
mTarget = aTarget;
}
virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) MOZ_OVERRIDE {}
virtual TemporaryRef<CompositingRenderTarget>
CreateRenderTarget(const gfx::IntRect &aRect,
SurfaceInitMode aInit) MOZ_OVERRIDE;
virtual TemporaryRef<CompositingRenderTarget>
CreateRenderTargetFromSource(const gfx::IntRect &aRect,
const CompositingRenderTarget *aSource) MOZ_OVERRIDE;
virtual void SetRenderTarget(CompositingRenderTarget *aSurface);
virtual CompositingRenderTarget* GetCurrentRenderTarget() MOZ_OVERRIDE
{
return mCurrentRT;
}
virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) MOZ_OVERRIDE {}
virtual void DrawQuad(const gfx::Rect &aRect, const gfx::Rect &aClipRect,
const EffectChain &aEffectChain,
gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform,
const gfx::Point &aOffset) MOZ_OVERRIDE;
virtual void BeginFrame(const gfx::Rect *aClipRectIn,
const gfxMatrix& aTransform,
const gfx::Rect& aRenderBounds,
gfx::Rect *aClipRectOut = nullptr,
gfx::Rect *aRenderBoundsOut = nullptr) MOZ_OVERRIDE;
virtual void EndFrame() MOZ_OVERRIDE;
virtual void EndFrameForExternalComposition(const gfxMatrix& aTransform) MOZ_OVERRIDE {}
virtual void AbortFrame() MOZ_OVERRIDE {}
virtual void PrepareViewport(const gfx::IntSize& aSize,
const gfxMatrix& aWorldTransform) MOZ_OVERRIDE;
virtual bool SupportsPartialTextureUpdate() MOZ_OVERRIDE{ return true; }
#ifdef MOZ_DUMP_PAINTING
virtual const char* Name() const MOZ_OVERRIDE { return "Direct3D9"; }
#endif
virtual void NotifyLayersTransaction() MOZ_OVERRIDE {}
virtual nsIWidget* GetWidget() const MOZ_OVERRIDE { return mWidget; }
virtual nsIntSize& GetWidgetSize() MOZ_OVERRIDE;
IDirect3DDevice9* device() const { return mDeviceManager->device(); }
/**
* Declare an offset to use when rendering layers. This will be ignored when
* rendering to a target instead of the screen.
*/
virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) MOZ_OVERRIDE
{
if (aOffset.x || aOffset.y) {
NS_RUNTIMEABORT("SetScreenRenderOffset not supported by CompositorD3D9.");
}
// If the offset is 0, 0 that's okay.
}
virtual TemporaryRef<DataTextureSource>
CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE { return nullptr; }
private:
void SetSamplerForFilter(gfx::Filter aFilter);
void PaintToTarget();
void SetMask(const EffectChain &aEffectChain, uint32_t aMaskTexture);
void ReportFailure(const nsACString &aMsg, HRESULT aCode);
/* Device manager instance for this compositor */
nsRefPtr<DeviceManagerD3D9> mDeviceManager;
/* Swap chain associated with this compositor */
nsRefPtr<SwapChainD3D9> mSwapChain;
/* Widget associated with this layer manager */
nsIWidget *mWidget;
/*
* Context target, NULL when drawing directly to our swap chain.
*/
nsRefPtr<gfxContext> mTarget;
RefPtr<CompositingRenderTargetD3D9> mDefaultRT;
RefPtr<CompositingRenderTargetD3D9> mCurrentRT;
nsIntSize mSize;
};
}
}
#endif

View File

@ -12,6 +12,7 @@
#include "Nv3DVUtils.h"
#include "plstr.h"
#include <algorithm>
#include "gfxPlatform.h"
namespace mozilla {
namespace layers {
@ -78,6 +79,16 @@ SwapChainD3D9::Init(HWND hWnd)
return true;
}
already_AddRefed<IDirect3DSurface9>
SwapChainD3D9::GetBackBuffer()
{
nsRefPtr<IDirect3DSurface9> backBuffer;
mSwapChain->GetBackBuffer(0,
D3DBACKBUFFER_TYPE_MONO,
getter_AddRefs(backBuffer));
return backBuffer.forget();
}
bool
SwapChainD3D9::PrepareForRendering()
{
@ -95,10 +106,7 @@ SwapChainD3D9::PrepareForRendering()
}
if (mSwapChain) {
nsRefPtr<IDirect3DSurface9> backBuffer;
mSwapChain->GetBackBuffer(0,
D3DBACKBUFFER_TYPE_MONO,
getter_AddRefs(backBuffer));
nsRefPtr<IDirect3DSurface9> backBuffer = GetBackBuffer();
D3DSURFACE_DESC desc;
backBuffer->GetDesc(&desc);
@ -116,10 +124,7 @@ SwapChainD3D9::PrepareForRendering()
return false;
}
mSwapChain->GetBackBuffer(0,
D3DBACKBUFFER_TYPE_MONO,
getter_AddRefs(backBuffer));
backBuffer = GetBackBuffer();
mDeviceManager->device()->SetRenderTarget(0, backBuffer);
return true;
@ -139,6 +144,12 @@ SwapChainD3D9::Present(const nsIntRect &aRect)
mSwapChain->Present(&r, &r, 0, 0, 0);
}
void
SwapChainD3D9::Present()
{
mSwapChain->Present(NULL, NULL, 0, 0, 0);
}
void
SwapChainD3D9::Reset()
{
@ -148,9 +159,12 @@ SwapChainD3D9::Reset()
#define HAS_CAP(a, b) (((a) & (b)) == (b))
#define LACKS_CAP(a, b) !(((a) & (b)) == (b))
uint32_t DeviceManagerD3D9::sMaskQuadRegister = 11;
DeviceManagerD3D9::DeviceManagerD3D9()
: mDeviceResetCount(0)
, mMaxTextureSize(0)
, mTextureAddressingMode(D3DTADDRESS_CLAMP)
, mHasDynamicTextures(false)
, mDeviceWasRemoved(false)
{
@ -161,9 +175,6 @@ DeviceManagerD3D9::~DeviceManagerD3D9()
LayerManagerD3D9::OnDeviceManagerDestroy(this);
}
NS_IMPL_ADDREF(DeviceManagerD3D9)
NS_IMPL_RELEASE(DeviceManagerD3D9)
bool
DeviceManagerD3D9::Init()
{
@ -496,12 +507,12 @@ DeviceManagerD3D9::SetupRenderState()
mDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
mDevice->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
mDevice->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
mDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
mDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
mDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
mDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, mTextureAddressingMode);
mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, mTextureAddressingMode);
mDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, mTextureAddressingMode);
mDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, mTextureAddressingMode);
mDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, mTextureAddressingMode);
mDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, mTextureAddressingMode);
}
already_AddRefed<SwapChainD3D9>
@ -533,7 +544,7 @@ DeviceManagerD3D9::CreateSwapChain(HWND hWnd)
*/
bool
LoadMaskTexture(Layer* aMask, IDirect3DDevice9* aDevice,
uint32_t aMaskQuadTexture, uint32_t aMaskTexRegister)
uint32_t aMaskTexRegister)
{
gfxIntSize size;
nsRefPtr<IDirect3DTexture9> texture =
@ -549,7 +560,7 @@ LoadMaskTexture(Layer* aMask, IDirect3DDevice9* aDevice,
gfxRect bounds = gfxRect(gfxPoint(), size);
bounds = maskTransform.TransformBounds(bounds);
aDevice->SetVertexShaderConstantF(aMaskQuadTexture,
aDevice->SetVertexShaderConstantF(DeviceManagerD3D9::sMaskQuadRegister,
ShaderConstantRect((float)bounds.x,
(float)bounds.y,
(float)bounds.width,
@ -560,57 +571,10 @@ LoadMaskTexture(Layer* aMask, IDirect3DDevice9* aDevice,
return true;
}
void
DeviceManagerD3D9::SetShaderMode(ShaderMode aMode, Layer* aMask, bool aIs2D)
uint32_t
DeviceManagerD3D9::SetShaderMode(ShaderMode aMode, MaskType aMaskType)
{
if (aMask) {
// register allocations are taken from LayerManagerD3D9Shaders.h after
// the shaders are compiled (genshaders.sh)
const uint32_t maskQuadRegister = 11;
uint32_t maskTexRegister;
switch (aMode) {
case RGBLAYER:
mDevice->SetVertexShader(mLayerVSMask);
mDevice->SetPixelShader(mRGBPSMask);
maskTexRegister = 1;
break;
case RGBALAYER:
if (aIs2D) {
mDevice->SetVertexShader(mLayerVSMask);
mDevice->SetPixelShader(mRGBAPSMask);
} else {
mDevice->SetVertexShader(mLayerVSMask3D);
mDevice->SetPixelShader(mRGBAPSMask3D);
}
maskTexRegister = 1;
break;
case COMPONENTLAYERPASS1:
mDevice->SetVertexShader(mLayerVSMask);
mDevice->SetPixelShader(mComponentPass1PSMask);
maskTexRegister = 2;
break;
case COMPONENTLAYERPASS2:
mDevice->SetVertexShader(mLayerVSMask);
mDevice->SetPixelShader(mComponentPass2PSMask);
maskTexRegister = 2;
break;
case YCBCRLAYER:
mDevice->SetVertexShader(mLayerVSMask);
mDevice->SetPixelShader(mYCbCrPSMask);
maskTexRegister = 3;
break;
case SOLIDCOLORLAYER:
mDevice->SetVertexShader(mLayerVSMask);
mDevice->SetPixelShader(mSolidColorPSMask);
maskTexRegister = 0;
break;
}
if (!LoadMaskTexture(aMask, mDevice, maskQuadRegister, maskTexRegister)) {
// if we can't load the mask, fall back to unmasked rendering
NS_WARNING("Could not load texture for mask layer.");
SetShaderMode(aMode, nullptr, true);
}
} else {
if (aMaskType == MaskNone) {
switch (aMode) {
case RGBLAYER:
mDevice->SetVertexShader(mLayerVS);
@ -637,6 +601,66 @@ DeviceManagerD3D9::SetShaderMode(ShaderMode aMode, Layer* aMask, bool aIs2D)
mDevice->SetPixelShader(mSolidColorPS);
break;
}
return 0;
}
uint32_t maskTexRegister;
switch (aMode) {
case RGBLAYER:
mDevice->SetVertexShader(mLayerVSMask);
mDevice->SetPixelShader(mRGBPSMask);
maskTexRegister = 1;
break;
case RGBALAYER:
if (aMaskType == Mask2d) {
mDevice->SetVertexShader(mLayerVSMask);
mDevice->SetPixelShader(mRGBAPSMask);
} else {
mDevice->SetVertexShader(mLayerVSMask3D);
mDevice->SetPixelShader(mRGBAPSMask3D);
}
maskTexRegister = 1;
break;
case COMPONENTLAYERPASS1:
mDevice->SetVertexShader(mLayerVSMask);
mDevice->SetPixelShader(mComponentPass1PSMask);
maskTexRegister = 2;
break;
case COMPONENTLAYERPASS2:
mDevice->SetVertexShader(mLayerVSMask);
mDevice->SetPixelShader(mComponentPass2PSMask);
maskTexRegister = 2;
break;
case YCBCRLAYER:
mDevice->SetVertexShader(mLayerVSMask);
mDevice->SetPixelShader(mYCbCrPSMask);
maskTexRegister = 3;
break;
case SOLIDCOLORLAYER:
mDevice->SetVertexShader(mLayerVSMask);
mDevice->SetPixelShader(mSolidColorPSMask);
maskTexRegister = 0;
break;
}
return maskTexRegister;
}
void
DeviceManagerD3D9::SetShaderMode(ShaderMode aMode, Layer* aMask, bool aIs2D)
{
MaskType maskType = MaskNone;
if (aMask) {
maskType = aIs2D ? Mask2d : Mask3d;
}
uint32_t maskTexRegister = SetShaderMode(aMode, maskType);
if (aMask) {
// register allocations are taken from LayerManagerD3D9Shaders.h after
// the shaders are compiled (genshaders.sh)
if (!LoadMaskTexture(aMask, mDevice, maskTexRegister)) {
// if we can't load the mask, fall back to unmasked rendering
NS_WARNING("Could not load texture for mask layer.");
SetShaderMode(aMode, MaskNone);
}
}
}
@ -773,6 +797,13 @@ DeviceManagerD3D9::VerifyCaps()
mHasDynamicTextures = true;
}
if (HAS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_WRAP) &&
LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL)) {
mTextureAddressingMode = D3DTADDRESS_WRAP;
} else {
gfxPlatform::DisableBufferRotation();
}
return true;
}

View File

@ -11,6 +11,7 @@
#include "nsAutoPtr.h"
#include "d3d9.h"
#include "nsTArray.h"
#include "mozilla/layers/CompositorTypes.h"
namespace mozilla {
namespace layers {
@ -26,7 +27,39 @@ const int CBmProjection = 4;
const int CBvRenderTargetOffset = 8;
const int CBvTextureCoords = 9;
const int CBvLayerQuad = 10;
// we don't use opacity with solid color shaders
const int CBfLayerOpacity = 0;
const int CBvColor = 0;
/**
* This structure is used to pass rectangles to our shader constant. We can use
* this for passing rectangular areas to SetVertexShaderConstant. In the format
* of a 4 component float(x,y,width,height). Our vertex shader can then use
* this to construct rectangular positions from the 0,0-1,1 quad that we source
* it with.
*/
struct ShaderConstantRect
{
float mX, mY, mWidth, mHeight;
// Provide all the commonly used argument types to prevent all the local
// casts in the code.
ShaderConstantRect(float aX, float aY, float aWidth, float aHeight)
: mX(aX), mY(aY), mWidth(aWidth), mHeight(aHeight)
{ }
ShaderConstantRect(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight)
: mX((float)aX), mY((float)aY)
, mWidth((float)aWidth), mHeight((float)aHeight)
{ }
ShaderConstantRect(int32_t aX, int32_t aY, float aWidth, float aHeight)
: mX((float)aX), mY((float)aY), mWidth(aWidth), mHeight(aHeight)
{ }
// For easy passing to SetVertexShaderConstantF.
operator float* () { return &mX; }
};
/**
* SwapChain class, this class manages the swap chain belonging to a
@ -50,11 +83,14 @@ public:
*/
bool PrepareForRendering();
already_AddRefed<IDirect3DSurface9> GetBackBuffer();
/**
* This function will present the selected rectangle of the swap chain to
* its associated window.
*/
void Present(const nsIntRect &aRect);
void Present();
private:
friend class DeviceManagerD3D9;
@ -83,13 +119,8 @@ class DeviceManagerD3D9 MOZ_FINAL
{
public:
DeviceManagerD3D9();
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
protected:
nsAutoRefCnt mRefCnt;
NS_DECL_OWNINGTHREAD
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DeviceManagerD3D9)
public:
bool Init();
/**
@ -118,6 +149,8 @@ public:
};
void SetShaderMode(ShaderMode aMode, Layer* aMask, bool aIs2D);
// returns the register to be used for the mask texture, if appropriate
uint32_t SetShaderMode(ShaderMode aMode, MaskType aMaskType);
/**
* Return pointer to the Nv3DVUtils instance
@ -139,6 +172,8 @@ public:
int32_t GetMaxTextureSize() { return mMaxTextureSize; }
static uint32_t sMaskQuadRegister;
private:
friend class SwapChainD3D9;
@ -222,6 +257,12 @@ private:
uint32_t mMaxTextureSize;
/**
* Wrap (repeat) or clamp textures. We prefer the former so we can do buffer
* rotation, but some older hardware doesn't support it.
*/
D3DTEXTUREADDRESS mTextureAddressingMode;
/* If this device supports dynamic textures */
bool mHasDynamicTextures;

View File

@ -22,36 +22,6 @@ namespace layers {
class LayerD3D9;
class ThebesLayerD3D9;
/**
* This structure is used to pass rectangles to our shader constant. We can use
* this for passing rectangular areas to SetVertexShaderConstant. In the format
* of a 4 component float(x,y,width,height). Our vertex shader can then use
* this to construct rectangular positions from the 0,0-1,1 quad that we source
* it with.
*/
struct ShaderConstantRect
{
float mX, mY, mWidth, mHeight;
// Provide all the commonly used argument types to prevent all the local
// casts in the code.
ShaderConstantRect(float aX, float aY, float aWidth, float aHeight)
: mX(aX), mY(aY), mWidth(aWidth), mHeight(aHeight)
{ }
ShaderConstantRect(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight)
: mX((float)aX), mY((float)aY)
, mWidth((float)aWidth), mHeight((float)aHeight)
{ }
ShaderConstantRect(int32_t aX, int32_t aY, float aWidth, float aHeight)
: mX((float)aX), mY((float)aY), mWidth(aWidth), mHeight(aHeight)
{ }
// For easy passing to SetVertexShaderConstantF.
operator float* () { return &mX; }
};
/*
* This is the LayerManager used for Direct3D 9. For now this will render on
* the main thread.

View File

@ -0,0 +1,617 @@
/* -*- 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"
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 {
result = new DeprecatedTextureHostShmemD3D9();
}
result->SetFlags(aTextureFlags);
return result.forget();
}
CompositingRenderTargetD3D9::CompositingRenderTargetD3D9(IDirect3DTexture9* aTexture,
SurfaceInitMode aInit,
const gfx::IntSize& aSize)
: mInitMode(aInit)
, mInitialized(false)
{
MOZ_COUNT_CTOR(CompositingRenderTargetD3D9);
MOZ_ASSERT(aTexture);
mTextures[0] = aTexture;
mTextures[0]->GetSurfaceLevel(0, getter_AddRefs(mSurface));
TextureSourceD3D9::SetSize(aSize);
}
CompositingRenderTargetD3D9::CompositingRenderTargetD3D9(IDirect3DSurface9* aSurface,
SurfaceInitMode aInit,
const gfx::IntSize& aSize)
: mSurface(aSurface)
, mInitMode(aInit)
, mInitialized(false)
{
MOZ_COUNT_CTOR(CompositingRenderTargetD3D9);
MOZ_ASSERT(aSurface);
TextureSourceD3D9::SetSize(aSize);
}
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) {
gfx::IntRect rect = GetTileRect(mCurrentTile);
return gfx::IntSize(rect.width, rect.height);
}
return TextureSourceD3D9::GetSize();
}
nsIntRect
DeprecatedTextureHostD3D9::GetTileRect()
{
IntRect rect = GetTileRect(mCurrentTile);
return nsIntRect(rect.x, rect.y, rect.width, rect.height);
}
static uint32_t GetRequiredTiles(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);
mDevice = mCompositor ? mCompositor->device() : nullptr;
}
static TemporaryRef<IDirect3DTexture9>
DataToTexture(IDirect3DDevice9 *aDevice,
unsigned char *aData,
int aStride,
const gfxIntSize &aSize,
_D3DFORMAT aFormat,
uint32_t aBPP)
{
RefPtr<IDirect3DTexture9> texture;
nsRefPtr<IDirect3DDevice9Ex> deviceEx;
aDevice->QueryInterface(IID_IDirect3DDevice9Ex,
(void**)getter_AddRefs(deviceEx));
RefPtr<IDirect3DSurface9> surface;
D3DLOCKED_RECT lockedRect;
if (deviceEx) {
// D3D9Ex doesn't support managed textures. We could use dynamic textures
// here but since Images are immutable that probably isn't such a great
// idea.
if (FAILED(aDevice->
CreateTexture(aSize.width, aSize.height,
1, 0, aFormat, D3DPOOL_DEFAULT,
byRef(texture), nullptr)))
{
return nullptr;
}
RefPtr<IDirect3DTexture9> tmpTexture;
if (FAILED(aDevice->
CreateTexture(aSize.width, aSize.height,
1, 0, aFormat, D3DPOOL_SYSTEMMEM,
byRef(tmpTexture), nullptr)))
{
return nullptr;
}
tmpTexture->GetSurfaceLevel(0, byRef(surface));
surface->LockRect(&lockedRect, NULL, 0);
NS_ASSERTION(lockedRect.pBits, "Could not lock surface");
} else {
if (FAILED(aDevice->
CreateTexture(aSize.width, aSize.height,
1, 0, aFormat, D3DPOOL_MANAGED,
byRef(texture), nullptr))) {
return nullptr;
}
/* lock the entire texture */
texture->LockRect(0, &lockedRect, nullptr, 0);
}
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);
}
if (deviceEx) {
surface->UnlockRect();
nsRefPtr<IDirect3DSurface9> dstSurface;
texture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
aDevice->UpdateSurface(surface, NULL, dstSurface, NULL);
} else {
texture->UnlockRect(0);
}
return texture.forget();
}
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.");
AutoOpenSurface openSurf(OPEN_READ_ONLY, aImage);
nsRefPtr<gfxImageSurface> surf = openSurf.GetAsImage();
gfxIntSize size = surf->GetSize();
mSize = IntSize(size.width, size.height);
uint32_t bpp = 0;
_D3DFORMAT format = D3DFMT_A8R8G8B8;
switch (surf->Format()) {
case gfxImageSurface::ImageFormatRGB24:
mFormat = FORMAT_B8G8R8X8;
format = D3DFMT_X8R8G8B8;
bpp = 4;
break;
case gfxImageSurface::ImageFormatARGB32:
mFormat = FORMAT_B8G8R8A8;
format = D3DFMT_A8R8G8B8;
bpp = 4;
break;
case gfxImageSurface::ImageFormatA8:
mFormat = FORMAT_A8;
format = D3DFMT_A8;
bpp = 1;
break;
default:
NS_ERROR("Bad image format");
}
int32_t maxSize = mCompositor->GetMaxTextureSize();
if (size.width <= maxSize && size.height <= maxSize) {
mTextures[0] = DataToTexture(mDevice,
surf->Data(), surf->Stride(),
size, format, bpp);
NS_ASSERTION(mTextures[0], "Could not upload texture");
mIsTiled = false;
} else {
mIsTiled = true;
uint32_t tileCount = GetRequiredTiles(size.width, maxSize) *
GetRequiredTiles(size.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(mDevice,
data,
surf->Stride(),
gfxIntSize(tileRect.width, tileRect.height),
format,
bpp);
}
}
}
IntRect
DeprecatedTextureHostD3D9::GetTileRect(uint32_t aID) const
{
uint32_t maxSize = mCompositor->GetMaxTextureSize();
uint32_t horizontalTiles = GetRequiredTiles(mSize.width, maxSize);
uint32_t verticalTiles = GetRequiredTiles(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);
}
void
DeprecatedTextureHostYCbCrD3D9::SetCompositor(Compositor* aCompositor)
{
CompositorD3D9 *d3dCompositor = static_cast<CompositorD3D9*>(aCompositor);
mDevice = d3dCompositor ? d3dCompositor->device() : nullptr;
}
IntSize
DeprecatedTextureHostYCbCrD3D9::GetSize() const
{
return TextureSourceD3D9::GetSize();
}
void
DeprecatedTextureHostYCbCrD3D9::UpdateImpl(const SurfaceDescriptor& aImage,
nsIntRegion *aRegion,
nsIntPoint *aOffset)
{
MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TYCbCrImage);
YCbCrImageDataDeserializer yuvDeserializer(aImage.get_YCbCrImage().data().get<uint8_t>());
gfxIntSize gfxCbCrSize = yuvDeserializer.GetCbCrSize();
gfxIntSize size = yuvDeserializer.GetYSize();
mSize = IntSize(size.width, size.height);
mStereoMode = yuvDeserializer.GetStereoMode();
mTextures[0] = DataToTexture(mDevice,
yuvDeserializer.GetYData(),
yuvDeserializer.GetYStride(),
size,
D3DFMT_L8, 1);
mTextures[1] = DataToTexture(mDevice,
yuvDeserializer.GetCbData(),
yuvDeserializer.GetCbCrStride(),
gfxCbCrSize,
D3DFMT_L8, 1);
mTextures[2] = DataToTexture(mDevice,
yuvDeserializer.GetCrData(),
yuvDeserializer.GetCbCrStride(),
gfxCbCrSize,
D3DFMT_L8, 1);
}
// aTexture should be in SYSTEMMEM, returns a texture in the default
// pool (that is, in video memory).
static TemporaryRef<IDirect3DTexture9>
TextureToTexture(IDirect3DDevice9* aDevice,
IDirect3DTexture9* aTexture,
const IntSize& aSize,
_D3DFORMAT aFormat)
{
RefPtr<IDirect3DTexture9> texture;
if (FAILED(aDevice->
CreateTexture(aSize.width, aSize.height,
1, 0, aFormat, D3DPOOL_DEFAULT,
byRef(texture), nullptr))) {
return nullptr;
}
HRESULT hr = aDevice->UpdateTexture(aTexture, texture);
if (FAILED(hr)) {
return nullptr;
}
return texture.forget();
}
void
DeprecatedTextureHostSystemMemD3D9::UpdateImpl(const SurfaceDescriptor& aImage,
nsIntRegion *aRegion,
nsIntPoint *aOffset)
{
MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TSurfaceDescriptorD3D9);
MOZ_ASSERT(mCompositor, "Must have compositor to update.");
IDirect3DTexture9* texture =
reinterpret_cast<IDirect3DTexture9*>(aImage.get_SurfaceDescriptorD3D9().texture());
if (!texture) {
mTextures[0] = nullptr;
return;
}
D3DSURFACE_DESC desc;
texture->GetLevelDesc(0, &desc);
mSize.width = desc.Width;
mSize.height = desc.Height;
_D3DFORMAT format = desc.Format;
uint32_t bpp = 0;
switch (format) {
case D3DFMT_X8R8G8B8:
mFormat = FORMAT_B8G8R8X8;
bpp = 4;
break;
case D3DFMT_A8R8G8B8:
mFormat = FORMAT_B8G8R8A8;
bpp = 4;
break;
case D3DFMT_A8:
mFormat = FORMAT_A8;
bpp = 1;
break;
default:
NS_ERROR("Bad image format");
}
int32_t maxSize = mCompositor->GetMaxTextureSize();
if (mSize.width <= maxSize && mSize.height <= maxSize) {
mIsTiled = false;
mTextures[0] = TextureToTexture(mDevice, texture, mSize, format);
NS_ASSERTION(mTextures[0], "Could not upload texture");
} else {
mIsTiled = true;
uint32_t tileCount = GetRequiredTiles(mSize.width, maxSize) *
GetRequiredTiles(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(mDevice,
reinterpret_cast<unsigned char*>(lockedRect.pBits),
lockedRect.Pitch,
gfxIntSize(tileRect.width, tileRect.height),
format,
bpp);
texture->UnlockRect(0);
}
}
}
DeprecatedTextureClientD3D9::DeprecatedTextureClientD3D9(CompositableForwarder* aCompositableForwarder,
const TextureInfo& aTextureInfo)
: DeprecatedTextureClient(aCompositableForwarder, aTextureInfo)
, mDC(nullptr)
, mTextureLocked(false)
{
MOZ_COUNT_CTOR(DeprecatedTextureClientD3D9);
}
DeprecatedTextureClientD3D9::~DeprecatedTextureClientD3D9()
{
MOZ_COUNT_DTOR(DeprecatedTextureClientD3D9);
Unlock();
mDescriptor = SurfaceDescriptor();
ClearDT();
}
bool
DeprecatedTextureClientD3D9::EnsureAllocated(gfx::IntSize aSize,
gfxASurface::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 gfxASurface::CONTENT_COLOR:
format = D3DFMT_X8R8G8B8;
mIsOpaque = true;
break;
case gfxASurface::CONTENT_COLOR_ALPHA:
format = D3DFMT_A8R8G8B8;
mIsOpaque = false;
break;
case gfxASurface::CONTENT_ALPHA:
format = D3DFMT_A8;
mIsOpaque = true;
break;
default:
NS_ERROR("Bad image type");
}
IDirect3DDevice9 *device = gfxWindowsPlatform::GetPlatform()->GetD3D9Device();
if (!device ||
FAILED(device->
CreateTexture(aSize.width, aSize.height,
1, 0, format, D3DPOOL_SYSTEMMEM,
getter_AddRefs(mTexture), 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 (mSurface) {
return mSurface.get();
}
MOZ_ASSERT(mTexture, "Cannot lock surface without a texture to lock");
if (mIsOpaque) {
MOZ_ASSERT(!mTextureLocked, "Shouldn't lock texture and have a surface");
if (!mD3D9Surface) {
HRESULT hr = mTexture->GetSurfaceLevel(0, getter_AddRefs(mD3D9Surface));
if (FAILED(hr)) {
NS_WARNING("Failed to get texture surface level.");
return nullptr;
}
}
if (!mDC) {
HRESULT hr = mD3D9Surface->GetDC(&mDC);
if (FAILED(hr)) {
NS_WARNING("Failed to get device context for texture surface.");
return nullptr;
}
}
NS_ASSERTION(mDC, "We need a DC here");
mSurface = new gfxWindowsSurface(mDC);
} else {
// d3d9 SYSTEMMEM surfaces do not support GDI with an alpha channel
MOZ_ASSERT(!mD3D9Surface && !mDC, "Shouldn't lock texture and have a surface");
if (!mTextureLocked) {
D3DLOCKED_RECT lockedRect;
mTexture->LockRect(0, &lockedRect, nullptr, 0);
mTextureLocked = true;
mSurface = new gfxImageSurface(reinterpret_cast<unsigned char*>(lockedRect.pBits),
gfxIntSize(mSize.width, mSize.height),
lockedRect.Pitch,
gfxASurface::ImageFormatARGB32);
}
}
NS_ASSERTION(mSurface, "should have a surface one way or the other");
return mSurface.get();
}
DrawTarget*
DeprecatedTextureClientD3D9::LockDrawTarget()
{
if (!mDrawTarget) {
mDrawTarget =
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(LockSurface(), mSize);
}
return mDrawTarget.get();
}
void
DeprecatedTextureClientD3D9::Unlock()
{
if (mDrawTarget) {
mDrawTarget->Flush();
mDrawTarget = nullptr;
}
if (mTextureLocked) {
MOZ_ASSERT(!mD3D9Surface && !mDC, "Shouldn't lock texture and have a surface");
mTexture->UnlockRect(0);
mTextureLocked = false;
} else if (mDC) {
MOZ_ASSERT(mD3D9Surface, "we need a D3D9Surface to release our DC");
MOZ_ASSERT(!mTextureLocked, "Shouldn't lock texture and have a surface");
mD3D9Surface->ReleaseDC(mDC);
mDC = 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;
ClearDT();
if (aDescriptor.type() == SurfaceDescriptor::T__None) {
return;
}
MOZ_ASSERT(aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorD3D9);
Unlock();
mD3D9Surface = nullptr;
mTexture = reinterpret_cast<IDirect3DTexture9*>(
mDescriptor.get_SurfaceDescriptorD3D9().texture());
}
void
DeprecatedTextureClientD3D9::ClearDT()
{
// Perhaps this should be debug only.
if (mDrawTarget) {
mDrawTarget = nullptr;
}
}
}
}

View File

@ -0,0 +1,256 @@
/* -*- 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/. */
#ifndef MOZILLA_GFX_TEXTURED3D9_H
#define MOZILLA_GFX_TEXTURED3D9_H
#include "mozilla/layers/Compositor.h"
#include "mozilla/layers/TextureClient.h"
#include "mozilla/layers/TextureHost.h"
#include "gfxWindowsPlatform.h"
#include "d3d9.h"
#include <vector>
namespace mozilla {
namespace layers {
class CompositorD3D9;
class TextureSourceD3D9
{
public:
virtual IDirect3DTexture9* GetD3D9Texture() { return mTextures[0]; }
virtual bool IsYCbCrSource() const { return false; }
struct YCbCrTextures
{
IDirect3DTexture9 *mY;
IDirect3DTexture9 *mCb;
IDirect3DTexture9 *mCr;
StereoMode mStereoMode;
};
virtual YCbCrTextures GetYCbCrTextures() {
YCbCrTextures textures = { mTextures[0],
mTextures[1],
mTextures[2],
mStereoMode };
return textures;
}
protected:
virtual gfx::IntSize GetSize() const { return mSize; }
void SetSize(const gfx::IntSize& aSize) { mSize = aSize; }
gfx::IntSize mSize;
StereoMode mStereoMode;
RefPtr<IDirect3DTexture9> mTextures[3];
};
class CompositingRenderTargetD3D9 : public CompositingRenderTarget,
public TextureSourceD3D9
{
public:
CompositingRenderTargetD3D9(IDirect3DTexture9* aTexture,
SurfaceInitMode aInit,
const gfx::IntSize& aSize);
// use for rendering to the main window, cannot be rendered as a texture
CompositingRenderTargetD3D9(IDirect3DSurface9* aSurface,
SurfaceInitMode aInit,
const gfx::IntSize& aSize);
~CompositingRenderTargetD3D9();
virtual TextureSourceD3D9* AsSourceD3D9() MOZ_OVERRIDE
{
MOZ_ASSERT(mTextures[0],
"No texture, can't be indirectly rendered. Is this the screen backbuffer?");
return this;
}
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
void BindRenderTarget(IDirect3DDevice9* aDevice);
private:
friend class CompositorD3D9;
nsRefPtr<IDirect3DSurface9> mSurface;
SurfaceInitMode mInitMode;
bool mInitialized;
};
// Shared functionality for non-YCbCr texture hosts
class DeprecatedTextureHostD3D9 : public DeprecatedTextureHost
, public TextureSourceD3D9
, public TileIterator
{
public:
DeprecatedTextureHostD3D9();
virtual ~DeprecatedTextureHostD3D9();
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
virtual TextureSourceD3D9* AsSourceD3D9() MOZ_OVERRIDE { return this; }
virtual IDirect3DTexture9 *GetD3D9Texture() MOZ_OVERRIDE {
return mIsTiled ? mTileTextures[mCurrentTile].get()
: TextureSourceD3D9::GetD3D9Texture();
}
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
virtual LayerRenderState GetRenderState() { return LayerRenderState(); }
virtual bool Lock() MOZ_OVERRIDE { return true; }
virtual already_AddRefed<gfxImageSurface> GetAsSurface() MOZ_OVERRIDE
{
return nullptr; // TODO: cf bug 872568
}
virtual void BeginTileIteration() MOZ_OVERRIDE
{
mIterating = true;
mCurrentTile = 0;
}
virtual void EndTileIteration() MOZ_OVERRIDE
{
mIterating = false;
}
virtual nsIntRect GetTileRect() MOZ_OVERRIDE;
virtual size_t GetTileCount() MOZ_OVERRIDE { return mTileTextures.size(); }
virtual bool NextTile() MOZ_OVERRIDE
{
return (++mCurrentTile < mTileTextures.size());
}
virtual TileIterator* AsTileIterator() MOZ_OVERRIDE
{
return mIsTiled ? this : nullptr;
}
protected:
gfx::IntRect GetTileRect(uint32_t aID) const;
RefPtr<IDirect3DDevice9> mDevice;
RefPtr<CompositorD3D9> mCompositor;
bool mIsTiled;
std::vector< RefPtr<IDirect3DTexture9> > mTileTextures;
uint32_t mCurrentTile;
bool mIterating;
};
class DeprecatedTextureHostShmemD3D9 : public DeprecatedTextureHostD3D9
{
public:
#ifdef MOZ_LAYERS_HAVE_LOG
virtual const char* Name() { return "DeprecatedTextureHostShmemD3D9"; }
#endif
protected:
virtual void UpdateImpl(const SurfaceDescriptor& aSurface,
nsIntRegion* aRegion,
nsIntPoint *aOffset = nullptr) MOZ_OVERRIDE;
};
class DeprecatedTextureHostSystemMemD3D9 : public DeprecatedTextureHostD3D9
{
public:
#ifdef MOZ_LAYERS_HAVE_LOG
virtual const char* Name() { return "DeprecatedTextureHostSystemMemD3D9"; }
#endif
protected:
virtual void UpdateImpl(const SurfaceDescriptor& aSurface,
nsIntRegion* aRegion,
nsIntPoint *aOffset = nullptr) MOZ_OVERRIDE;
nsRefPtr<IDirect3DTexture9> mTexture;
};
class DeprecatedTextureHostYCbCrD3D9 : public DeprecatedTextureHost
, public TextureSourceD3D9
{
public:
DeprecatedTextureHostYCbCrD3D9()
: mDevice(nullptr)
{
mFormat = gfx::FORMAT_YUV;
}
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 already_AddRefed<gfxImageSurface> GetAsSurface() MOZ_OVERRIDE
{
return nullptr; // TODO: cf bug 872568
}
#ifdef MOZ_LAYERS_HAVE_LOG
virtual const char* Name() MOZ_OVERRIDE
{
return "TextureImageDeprecatedTextureHostD3D11";
}
#endif
protected:
virtual void UpdateImpl(const SurfaceDescriptor& aSurface,
nsIntRegion* aRegion,
nsIntPoint* aOffset = nullptr) MOZ_OVERRIDE;
private:
RefPtr<IDirect3DDevice9> mDevice;
};
// If we want to use d3d9 textures for transport, use this class.
// If we are using shmem, then use DeprecatedTextureClientShmem with DeprecatedTextureHostShmemD3D9
class DeprecatedTextureClientD3D9 : public DeprecatedTextureClient
{
public:
DeprecatedTextureClientD3D9(CompositableForwarder* aCompositableForwarder,
const TextureInfo& aTextureInfo);
virtual ~DeprecatedTextureClientD3D9();
virtual bool SupportsType(DeprecatedTextureClientType aType) MOZ_OVERRIDE
{
return aType == TEXTURE_CONTENT;
}
virtual bool EnsureAllocated(gfx::IntSize aSize,
gfxASurface::gfxContentType aType) MOZ_OVERRIDE;
virtual gfxASurface* LockSurface() MOZ_OVERRIDE;
virtual gfx::DrawTarget* LockDrawTarget() MOZ_OVERRIDE;
virtual void Unlock() MOZ_OVERRIDE;
virtual void SetDescriptor(const SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE;
virtual gfxASurface::gfxContentType GetContentType() MOZ_OVERRIDE
{
return mContentType;
}
private:
void ClearDT();
nsRefPtr<IDirect3DTexture9> mTexture;
nsRefPtr<gfxASurface> mSurface;
nsRefPtr<IDirect3DSurface9> mD3D9Surface;
HDC mDC;
RefPtr<gfx::DrawTarget> mDrawTarget;
gfx::IntSize mSize;
gfxContentType mContentType;
bool mTextureLocked;
bool mIsOpaque;
};
}
}
#endif /* MOZILLA_GFX_TEXTURED3D9_H */

View File

@ -14,6 +14,7 @@
#include "mozilla/layers/BasicCompositor.h"
#ifdef XP_WIN
#include "mozilla/layers/CompositorD3D11.h"
#include "mozilla/layers/CompositorD3D9.h"
#endif
#include "LayerTransactionParent.h"
#include "nsIWidget.h"
@ -625,6 +626,9 @@ CompositorParent::AllocPLayerTransactionParent(const LayersBackend& aBackendHint
} else if (aBackendHint == mozilla::layers::LAYERS_D3D11) {
mLayerManager =
new LayerManagerComposite(new CompositorD3D11(mWidget));
} else if (aBackendHint == mozilla::layers::LAYERS_D3D9) {
mLayerManager =
new LayerManagerComposite(new CompositorD3D9(mWidget));
#endif
} else {
NS_ERROR("Unsupported backend selected for Async Compositor");

View File

@ -133,6 +133,7 @@ ISurfaceAllocator::DestroySharedSurface(SurfaceDescriptor* aSurface)
case SurfaceDescriptor::TRGBImage:
DeallocShmem(aSurface->get_RGBImage().data());
break;
case SurfaceDescriptor::TSurfaceDescriptorD3D9:
case SurfaceDescriptor::TSurfaceDescriptorD3D10:
break;
case SurfaceDescriptor::TMemoryImage:

View File

@ -36,6 +36,11 @@ union MaybeMagicGrallocBufferHandle {
null_t;
};
struct SurfaceDescriptorD3D9 {
// IDirect3DTexture9*
uintptr_t texture;
};
struct SurfaceDescriptorD3D10 {
WindowsHandle handle;
bool hasAlpha;
@ -124,6 +129,7 @@ struct SurfaceDescriptorShmem {
union SurfaceDescriptor {
SurfaceDescriptorShmem;
SurfaceDescriptorMemory;
SurfaceDescriptorD3D9;
SurfaceDescriptorD3D10;
SurfaceDescriptorX11;
SharedTextureDescriptor;

View File

@ -119,7 +119,8 @@ SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
mSize = aData.mPicSize;
YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer());
serializer.InitializeBufferInfo(aData.mYSize,
aData.mCbCrSize);
aData.mCbCrSize,
aData.mStereoMode);
}
uint8_t*
@ -153,7 +154,8 @@ SharedPlanarYCbCrImage::Allocate(PlanarYCbCrImage::Data& aData)
YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer());
serializer.InitializeBufferInfo(aData.mYSize,
aData.mCbCrSize);
aData.mCbCrSize,
aData.mStereoMode);
MOZ_ASSERT(serializer.IsValid());
aData.mYChannel = serializer.GetYData();
@ -239,7 +241,8 @@ DeprecatedSharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
mSize = aData.mPicSize;
YCbCrImageDataSerializer serializer(mShmem.get<uint8_t>());
serializer.InitializeBufferInfo(aData.mYSize,
aData.mCbCrSize);
aData.mCbCrSize,
aData.mStereoMode);
}
uint8_t*
@ -269,7 +272,8 @@ DeprecatedSharedPlanarYCbCrImage::Allocate(PlanarYCbCrImage::Data& aData)
YCbCrImageDataSerializer serializer(mShmem.get<uint8_t>());
serializer.InitializeBufferInfo(aData.mYSize,
aData.mCbCrSize);
aData.mCbCrSize,
aData.mStereoMode);
if (!serializer.IsValid() || mShmem.Size<uint8_t>() < size) {
mSurfaceAllocator->DeallocShmem(mShmem);
return false;

View File

@ -52,7 +52,13 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
'd3d9/DeviceManagerD3D9.h',
'd3d9/LayerManagerD3D9.h',
]
EXPORTS.mozilla.layers += [
'CompositorD3D9.h',
'TextureD3D9.h',
]
CPP_SOURCES += [
'CompositorD3D9.cpp',
'TextureD3D9.cpp',
'LayerManagerD3D9.cpp',
'ThebesLayerD3D9.cpp',
'ContainerLayerD3D9.cpp',

View File

@ -77,6 +77,7 @@
#include "mozilla/Preferences.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/Mutex.h"
#include "nsIGfxInfo.h"
@ -86,6 +87,8 @@ using namespace mozilla::layers;
gfxPlatform *gPlatform = nullptr;
static bool gEverInitialized = false;
static Mutex* gGfxPlatformPrefsLock = nullptr;
// These two may point to the same profile
static qcms_profile *gCMSOutputProfile = nullptr;
static qcms_profile *gCMSsRGBProfile = nullptr;
@ -313,6 +316,8 @@ gfxPlatform::Init()
sCmapDataLog = PR_NewLogModule("cmapdata");;
#endif
gGfxPlatformPrefsLock = new Mutex("gfxPlatform::gGfxPlatformPrefsLock");
/* Initialize the GfxInfo service.
* Note: we can't call functions on GfxInfo that depend
* on gPlatform until after it has been initialized
@ -475,6 +480,8 @@ gfxPlatform::Shutdown()
CompositorParent::ShutDown();
delete gGfxPlatformPrefsLock;
delete gPlatform;
gPlatform = nullptr;
}
@ -1856,11 +1863,15 @@ static bool sPrefLayersAccelerationForceEnabled = false;
static bool sPrefLayersAccelerationDisabled = false;
static bool sPrefLayersPreferOpenGL = false;
static bool sPrefLayersPreferD3D9 = false;
static bool sLayersSupportsD3D9 = true;
static int sPrefLayoutFrameRate = -1;
static bool sBufferRotationEnabled = false;
void InitLayersAccelerationPrefs()
static bool sLayersAccelerationPrefsInitialized = false;
void
InitLayersAccelerationPrefs()
{
static bool sLayersAccelerationPrefsInitialized = false;
if (!sLayersAccelerationPrefsInitialized)
{
sPrefLayersOffMainThreadCompositionEnabled = Preferences::GetBool("layers.offmainthreadcomposition.enabled", false);
@ -1871,12 +1882,24 @@ void InitLayersAccelerationPrefs()
sPrefLayersPreferOpenGL = Preferences::GetBool("layers.prefer-opengl", false);
sPrefLayersPreferD3D9 = Preferences::GetBool("layers.prefer-d3d9", false);
sPrefLayoutFrameRate = Preferences::GetInt("layout.frame_rate", -1);
sBufferRotationEnabled = Preferences::GetBool("layers.bufferrotation.enabled", true);
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
if (gfxInfo) {
int32_t status;
if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, &status))) {
if (status != nsIGfxInfo::FEATURE_NO_INFO && !sPrefLayersAccelerationForceEnabled) {
sLayersSupportsD3D9 = false;
}
}
}
sLayersAccelerationPrefsInitialized = true;
}
}
bool gfxPlatform::GetPrefLayersOffMainThreadCompositionEnabled()
bool
gfxPlatform::GetPrefLayersOffMainThreadCompositionEnabled()
{
InitLayersAccelerationPrefs();
return sPrefLayersOffMainThreadCompositionEnabled ||
@ -1884,13 +1907,15 @@ bool gfxPlatform::GetPrefLayersOffMainThreadCompositionEnabled()
sPrefLayersOffMainThreadCompositionTestingEnabled;
}
bool gfxPlatform::GetPrefLayersOffMainThreadCompositionForceEnabled()
bool
gfxPlatform::GetPrefLayersOffMainThreadCompositionForceEnabled()
{
InitLayersAccelerationPrefs();
return sPrefLayersOffMainThreadCompositionForceEnabled;
}
bool gfxPlatform::GetPrefLayersAccelerationForceEnabled()
bool
gfxPlatform::GetPrefLayersAccelerationForceEnabled()
{
InitLayersAccelerationPrefs();
return sPrefLayersAccelerationForceEnabled;
@ -1903,20 +1928,49 @@ gfxPlatform::GetPrefLayersAccelerationDisabled()
return sPrefLayersAccelerationDisabled;
}
bool gfxPlatform::GetPrefLayersPreferOpenGL()
bool
gfxPlatform::GetPrefLayersPreferOpenGL()
{
InitLayersAccelerationPrefs();
return sPrefLayersPreferOpenGL;
}
bool gfxPlatform::GetPrefLayersPreferD3D9()
bool
gfxPlatform::GetPrefLayersPreferD3D9()
{
InitLayersAccelerationPrefs();
return sPrefLayersPreferD3D9;
}
int gfxPlatform::GetPrefLayoutFrameRate()
bool
gfxPlatform::CanUseDirect3D9()
{
// this function is called from the compositor thread, so it is not
// safe to init the prefs etc. from here.
MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
return sLayersSupportsD3D9;
}
int
gfxPlatform::GetPrefLayoutFrameRate()
{
InitLayersAccelerationPrefs();
return sPrefLayoutFrameRate;
}
bool
gfxPlatform::BufferRotationEnabled()
{
MutexAutoLock autoLock(*gGfxPlatformPrefsLock);
InitLayersAccelerationPrefs();
return sBufferRotationEnabled;
}
void
gfxPlatform::DisableBufferRotation()
{
MutexAutoLock autoLock(*gGfxPlatformPrefsLock);
sBufferRotationEnabled = false;
}

View File

@ -471,8 +471,14 @@ public:
static bool GetPrefLayersAccelerationDisabled();
static bool GetPrefLayersPreferOpenGL();
static bool GetPrefLayersPreferD3D9();
static bool CanUseDirect3D9();
static int GetPrefLayoutFrameRate();
/**
* Is it possible to use buffer rotation
*/
static bool BufferRotationEnabled();
static void DisableBufferRotation();
/**
* Are we going to try color management?
*/

View File

@ -28,6 +28,8 @@
#include "gfxGDIFontList.h"
#include "gfxGDIFont.h"
#include "DeviceManagerD3D9.h"
#ifdef CAIRO_HAS_DWRITE_FONT
#include "gfxDWriteFontList.h"
#include "gfxDWriteFonts.h"
@ -42,6 +44,7 @@
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::layers;
#ifdef CAIRO_HAS_D2D_SURFACE
#include "gfxD2DSurface.h"
@ -350,7 +353,8 @@ BuildKeyNameFromFontName(nsAString &aName)
}
gfxWindowsPlatform::gfxWindowsPlatform()
: mD3D11DeviceInitialized(false)
: mD3D9DeviceInitialized(false)
, mD3D11DeviceInitialized(false)
{
mPrefFonts.Init(50);
@ -384,6 +388,8 @@ gfxWindowsPlatform::~gfxWindowsPlatform()
{
NS_UnregisterMemoryMultiReporter(mGPUAdapterMultiReporter);
mDeviceManager = nullptr;
::ReleaseDC(nullptr, mScreenDC);
// not calling FT_Done_FreeType because cairo may still hold references to
// these FT_Faces. See bug 458169.
@ -1447,6 +1453,29 @@ gfxWindowsPlatform::SetupClearTypeParams()
#endif
}
IDirect3DDevice9*
gfxWindowsPlatform::GetD3D9Device()
{
DeviceManagerD3D9* manager = GetD3D9DeviceManager();
return manager ? manager->device() : nullptr;
}
DeviceManagerD3D9*
gfxWindowsPlatform::GetD3D9DeviceManager()
{
if (!mD3D9DeviceInitialized) {
mD3D9DeviceInitialized = true;
mDeviceManager = new DeviceManagerD3D9();
if (!mDeviceManager->Init()) {
NS_WARNING("Could not initialise devive manager");
mDeviceManager = nullptr;
}
}
return mDeviceManager;
}
ID3D11Device*
gfxWindowsPlatform::GetD3D11Device()
{

View File

@ -43,6 +43,12 @@
#define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096
#endif
namespace mozilla {
namespace layers {
class DeviceManagerD3D9;
}
}
class IDirect3DDevice9;
class ID3D11Device;
class IDXGIAdapter1;
@ -265,6 +271,8 @@ public:
#else
inline bool DWriteEnabled() { return false; }
#endif
mozilla::layers::DeviceManagerD3D9* GetD3D9DeviceManager();
IDirect3DDevice9* GetD3D9Device();
#ifdef CAIRO_HAS_D2D_SURFACE
cairo_device_t *GetD2DDevice() { return mD2DDevice; }
ID3D10Device1 *GetD3D10Device() { return mD2DDevice ? cairo_d2d_device_get_device(mD2DDevice) : nullptr; }
@ -297,7 +305,9 @@ private:
cairo_device_t *mD2DDevice;
#endif
mozilla::RefPtr<IDXGIAdapter1> mAdapter;
nsRefPtr<mozilla::layers::DeviceManagerD3D9> mDeviceManager;
mozilla::RefPtr<ID3D11Device> mD3D11Device;
bool mD3D9DeviceInitialized;
bool mD3D11DeviceInitialized;
virtual qcms_profile* GetPlatformCMSOutputProfile();

View File

@ -4088,6 +4088,8 @@ pref("layers.offmainthreadcomposition.async-animations", false);
// Whether to prefer normal memory over shared memory. Ignored with cross-process compositing
pref("layers.prefer-memory-over-shmem", true);
pref("layers.bufferrotation.enabled", true);
#ifdef MOZ_X11
#ifdef MOZ_WIDGET_GTK2
pref("gfx.xrender.enabled",true);

View File

@ -6554,6 +6554,20 @@ nsWindow::StartAllowingD3D9(bool aReinitialize)
}
}
mozilla::layers::LayersBackend
nsWindow::GetPreferredCompositorBackend()
{
LayerManagerPrefs prefs;
GetLayerManagerPrefs(&prefs);
if (prefs.mDisableAcceleration) {
return mozilla::layers::LAYERS_BASIC;
}
if (prefs.mPreferD3D9) {
return mozilla::layers::LAYERS_D3D9;
}
return mozilla::layers::LAYERS_D3D11;
}
bool
nsWindow::HasBogusPopupsDropShadowOnMultiMonitor() {
if (sHasBogusPopupsDropShadowOnMultiMonitor == TRI_UNKNOWN) {

View File

@ -274,7 +274,7 @@ public:
bool const DestroyCalled() { return mDestroyCalled; }
virtual mozilla::layers::LayersBackend GetPreferredCompositorBackend() { return mozilla::layers::LAYERS_D3D11; }
virtual mozilla::layers::LayersBackend GetPreferredCompositorBackend();
protected: