Bug 716439; c++ support for the shaders and textures for dx9 backend. r-Bas

This commit is contained in:
Nicholas Cameron 2012-03-07 10:07:48 +13:00
parent 69669ee102
commit fa43179112
5 changed files with 309 additions and 80 deletions

View File

@ -400,6 +400,68 @@ DeviceManagerD3D9::Init()
return false;
}
hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVSMask,
getter_AddRefs(mLayerVSMask));
if (FAILED(hr)) {
return false;
}
hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVSMask3D,
getter_AddRefs(mLayerVSMask3D));
if (FAILED(hr)) {
return false;
}
hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPSMask,
getter_AddRefs(mRGBPSMask));
if (FAILED(hr)) {
return false;
}
hr = mDevice->CreatePixelShader((DWORD*)RGBAShaderPSMask,
getter_AddRefs(mRGBAPSMask));
if (FAILED(hr)) {
return false;
}
hr = mDevice->CreatePixelShader((DWORD*)RGBAShaderPSMask3D,
getter_AddRefs(mRGBAPSMask3D));
if (FAILED(hr)) {
return false;
}
hr = mDevice->CreatePixelShader((DWORD*)ComponentPass1ShaderPSMask,
getter_AddRefs(mComponentPass1PSMask));
if (FAILED(hr)) {
return false;
}
hr = mDevice->CreatePixelShader((DWORD*)ComponentPass2ShaderPSMask,
getter_AddRefs(mComponentPass2PSMask));
if (FAILED(hr)) {
return false;
}
hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPSMask,
getter_AddRefs(mYCbCrPSMask));
if (FAILED(hr)) {
return false;
}
hr = mDevice->CreatePixelShader((DWORD*)SolidColorShaderPSMask,
getter_AddRefs(mSolidColorPSMask));
if (FAILED(hr)) {
return false;
}
if (!CreateVertexBuffer()) {
return false;
}
@ -494,34 +556,118 @@ DeviceManagerD3D9::CreateSwapChain(HWND hWnd)
return swapChain.forget();
}
void
DeviceManagerD3D9::SetShaderMode(ShaderMode aMode)
/*
* Finds a texture for the mask layer and sets it as an
* input to the shaders.
* Returns true if a texture is loaded, false if
* a texture for the mask layer could not be loaded.
*/
bool
LoadMaskTexture(Layer* aMask, IDirect3DDevice9* aDevice,
PRUint32 aMaskQuadTexture, PRUint32 aMaskTexRegister)
{
switch (aMode) {
case RGBLAYER:
mDevice->SetVertexShader(mLayerVS);
mDevice->SetPixelShader(mRGBPS);
break;
case RGBALAYER:
mDevice->SetVertexShader(mLayerVS);
mDevice->SetPixelShader(mRGBAPS);
break;
case COMPONENTLAYERPASS1:
mDevice->SetVertexShader(mLayerVS);
mDevice->SetPixelShader(mComponentPass1PS);
break;
case COMPONENTLAYERPASS2:
mDevice->SetVertexShader(mLayerVS);
mDevice->SetPixelShader(mComponentPass2PS);
break;
case YCBCRLAYER:
mDevice->SetVertexShader(mLayerVS);
mDevice->SetPixelShader(mYCbCrPS);
break;
case SOLIDCOLORLAYER:
mDevice->SetVertexShader(mLayerVS);
mDevice->SetPixelShader(mSolidColorPS);
break;
gfxIntSize size;
nsRefPtr<IDirect3DTexture9> texture =
static_cast<LayerD3D9*>(aMask->ImplData())->GetAsTexture(&size);
if (!texture) {
return false;
}
gfxMatrix maskTransform;
bool maskIs2D = aMask->GetEffectiveTransform().CanDraw2D(&maskTransform);
NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
gfxRect bounds = gfxRect(gfxPoint(), size);
bounds = maskTransform.TransformBounds(bounds);
aDevice->SetVertexShaderConstantF(aMaskQuadTexture,
ShaderConstantRect((float)bounds.x,
(float)bounds.y,
(float)bounds.width,
(float)bounds.height),
1);
aDevice->SetTexture(aMaskTexRegister, texture);
return true;
}
void
DeviceManagerD3D9::SetShaderMode(ShaderMode aMode, Layer* aMask, bool aIs2D)
{
if (aMask) {
// register allocations are taken from LayerManagerD3D9Shaders.h after
// the shaders are compiled (genshaders.sh)
const PRUint32 maskQuadRegister = 11;
PRUint32 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, nsnull, true);
}
} else {
switch (aMode) {
case RGBLAYER:
mDevice->SetVertexShader(mLayerVS);
mDevice->SetPixelShader(mRGBPS);
break;
case RGBALAYER:
mDevice->SetVertexShader(mLayerVS);
mDevice->SetPixelShader(mRGBAPS);
break;
case COMPONENTLAYERPASS1:
mDevice->SetVertexShader(mLayerVS);
mDevice->SetPixelShader(mComponentPass1PS);
break;
case COMPONENTLAYERPASS2:
mDevice->SetVertexShader(mLayerVS);
mDevice->SetPixelShader(mComponentPass2PS);
break;
case YCBCRLAYER:
mDevice->SetVertexShader(mLayerVS);
mDevice->SetPixelShader(mYCbCrPS);
break;
case SOLIDCOLORLAYER:
mDevice->SetVertexShader(mLayerVS);
mDevice->SetPixelShader(mSolidColorPS);
break;
}
}
}

View File

@ -50,6 +50,7 @@ namespace layers {
class DeviceManagerD3D9;
class LayerD3D9;
class Nv3DVUtils;
class Layer;
// Shader Constant locations
const int CBmLayerTransform = 0;
@ -148,7 +149,7 @@ public:
SOLIDCOLORLAYER
};
void SetShaderMode(ShaderMode aMode);
void SetShaderMode(ShaderMode aMode, Layer* aMask, bool aIs2D);
/**
* Return pointer to the Nv3DVUtils instance
@ -224,6 +225,17 @@ private:
/* Pixel shader used for solid colors */
nsRefPtr<IDirect3DPixelShader9> mSolidColorPS;
/* As above, but using a mask layer */
nsRefPtr<IDirect3DVertexShader9> mLayerVSMask;
nsRefPtr<IDirect3DVertexShader9> mLayerVSMask3D;
nsRefPtr<IDirect3DPixelShader9> mRGBPSMask;
nsRefPtr<IDirect3DPixelShader9> mRGBAPSMask;
nsRefPtr<IDirect3DPixelShader9> mRGBAPSMask3D;
nsRefPtr<IDirect3DPixelShader9> mComponentPass1PSMask;
nsRefPtr<IDirect3DPixelShader9> mComponentPass2PSMask;
nsRefPtr<IDirect3DPixelShader9> mYCbCrPSMask;
nsRefPtr<IDirect3DPixelShader9> mSolidColorPSMask;
/* Vertex buffer containing our basic vertex structure */
nsRefPtr<IDirect3DVertexBuffer9> mVB;

View File

@ -308,6 +308,69 @@ ImageLayerD3D9::GetLayer()
return this;
}
/*
* Returns a texture which backs aImage
* Will only work if aImage is a cairo or remote image.
* Returns nsnull if unsuccessful.
* If successful, aHasAlpha will be set to true if the texture has an
* alpha component, false otherwise.
*/
IDirect3DTexture9*
ImageLayerD3D9::GetTexture(Image *aImage, bool& aHasAlpha)
{
NS_ASSERTION(aImage, "Null image.");
if (aImage->GetFormat() == Image::REMOTE_IMAGE_BITMAP) {
RemoteBitmapImage *remoteImage =
static_cast<RemoteBitmapImage*>(aImage);
if (!aImage->GetBackendData(LayerManager::LAYERS_D3D9)) {
nsAutoPtr<TextureD3D9BackendData> dat = new TextureD3D9BackendData();
dat->mTexture = DataToTexture(device(), remoteImage->mData, remoteImage->mStride, remoteImage->mSize);
if (dat->mTexture) {
aImage->SetBackendData(LayerManager::LAYERS_D3D9, dat.forget());
}
}
aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
} else if (aImage->GetFormat() == Image::CAIRO_SURFACE) {
CairoImage *cairoImage =
static_cast<CairoImage*>(aImage);
if (!cairoImage->mSurface) {
return nsnull;
}
if (!aImage->GetBackendData(LayerManager::LAYERS_D3D9)) {
nsAutoPtr<TextureD3D9BackendData> dat = new TextureD3D9BackendData();
dat->mTexture = SurfaceToTexture(device(), cairoImage->mSurface, cairoImage->mSize);
if (dat->mTexture) {
aImage->SetBackendData(LayerManager::LAYERS_D3D9, dat.forget());
}
}
aHasAlpha = cairoImage->mSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA;
} else {
NS_WARNING("Inappropriate image type.");
return nsnull;
}
TextureD3D9BackendData *data =
static_cast<TextureD3D9BackendData*>(aImage->GetBackendData(LayerManager::LAYERS_D3D9));
if (!data) {
return nsnull;
}
nsRefPtr<IDirect3DDevice9> dev;
data->mTexture->GetDevice(getter_AddRefs(dev));
if (dev != device()) {
return nsnull;
}
return data->mTexture;
}
void
ImageLayerD3D9::RenderLayer()
{
@ -327,54 +390,11 @@ ImageLayerD3D9::RenderLayer()
gfxIntSize size = mScaleMode == SCALE_NONE ? image->GetSize() : mScaleToSize;
if (image->GetFormat() == Image::CAIRO_SURFACE || image->GetFormat() == Image::REMOTE_IMAGE_BITMAP)
if (image->GetFormat() == Image::CAIRO_SURFACE ||
image->GetFormat() == Image::REMOTE_IMAGE_BITMAP)
{
bool hasAlpha = false;
if (image->GetFormat() == Image::REMOTE_IMAGE_BITMAP) {
RemoteBitmapImage *remoteImage =
static_cast<RemoteBitmapImage*>(image);
if (!image->GetBackendData(LayerManager::LAYERS_D3D9)) {
nsAutoPtr<TextureD3D9BackendData> dat = new TextureD3D9BackendData();
dat->mTexture = DataToTexture(device(), remoteImage->mData, remoteImage->mStride, remoteImage->mSize);
if (dat->mTexture) {
image->SetBackendData(LayerManager::LAYERS_D3D9, dat.forget());
}
}
hasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
} else {
CairoImage *cairoImage =
static_cast<CairoImage*>(image);
if (!cairoImage->mSurface) {
return;
}
if (!image->GetBackendData(LayerManager::LAYERS_D3D9)) {
nsAutoPtr<TextureD3D9BackendData> dat = new TextureD3D9BackendData();
dat->mTexture = SurfaceToTexture(device(), cairoImage->mSurface, cairoImage->mSize);
if (dat->mTexture) {
image->SetBackendData(LayerManager::LAYERS_D3D9, dat.forget());
}
}
hasAlpha = cairoImage->mSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA;
}
TextureD3D9BackendData *data =
static_cast<TextureD3D9BackendData*>(image->GetBackendData(LayerManager::LAYERS_D3D9));
if (!data) {
return;
}
nsRefPtr<IDirect3DDevice9> dev;
data->mTexture->GetDevice(getter_AddRefs(dev));
if (dev != device()) {
return;
}
nsRefPtr<IDirect3DTexture9> texture = GetTexture(image, hasAlpha);
device()->SetVertexShaderConstantF(CBvLayerQuad,
ShaderConstantRect(0,
@ -384,19 +404,18 @@ ImageLayerD3D9::RenderLayer()
1);
if (hasAlpha) {
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER);
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER, GetMaskLayer());
} else {
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER);
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER, GetMaskLayer());
}
if (mFilter == gfxPattern::FILTER_NEAREST) {
device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
}
device()->SetTexture(0, data->mTexture);
device()->SetTexture(0, texture);
image = nsnull;
data = nsnull;
autoLock.Unlock();
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
@ -503,6 +522,33 @@ ImageLayerD3D9::RenderLayer()
GetContainer()->NotifyPaintedImage(image);
}
already_AddRefed<IDirect3DTexture9>
ImageLayerD3D9::GetAsTexture(gfxIntSize* aSize)
{
if (!GetContainer()) {
return nsnull;
}
AutoLockImage autoLock(GetContainer());
Image *image = autoLock.GetImage();
if (!image) {
return nsnull;
}
if (image->GetFormat() != Image::CAIRO_SURFACE &&
image->GetFormat() != Image::REMOTE_IMAGE_BITMAP) {
return nsnull;
}
bool dontCare;
*aSize = image->GetSize();
nsRefPtr<IDirect3DTexture9> result = GetTexture(image, dontCare);
return result.forget();
}
ShadowImageLayerD3D9::ShadowImageLayerD3D9(LayerManagerD3D9* aManager)
: ShadowImageLayer(aManager, nsnull)
, LayerD3D9(aManager)

View File

@ -62,6 +62,11 @@ public:
virtual Layer* GetLayer();
virtual void RenderLayer();
virtual already_AddRefed<IDirect3DTexture9> GetAsTexture(gfxIntSize* aSize);
private:
IDirect3DTexture9* GetTexture(Image *aImage, bool& aHasAlpha);
};
class THEBES_API ImageD3D9

View File

@ -180,8 +180,9 @@ public:
*/
void SetClippingEnabled(bool aEnabled);
void SetShaderMode(DeviceManagerD3D9::ShaderMode aMode)
{ mDeviceManager->SetShaderMode(aMode); }
void SetShaderMode(DeviceManagerD3D9::ShaderMode aMode,
Layer* aMask, bool aIs2D = true)
{ mDeviceManager->SetShaderMode(aMode, aMask, aIs2D); }
IDirect3DDevice9 *device() const { return mDeviceManager->device(); }
DeviceManagerD3D9 *deviceManager() const { return mDeviceManager; }
@ -196,6 +197,9 @@ public:
mDefaultDeviceManager = nsnull;
}
virtual gfxASurface::gfxImageFormat MaskImageFormat()
{ return gfxASurface::ImageFormatARGB32; }
#ifdef MOZ_LAYERS_HAVE_LOG
virtual const char* Name() const { return "D3D9"; }
#endif // MOZ_LAYERS_HAVE_LOG
@ -297,6 +301,22 @@ public:
device()->SetPixelShaderConstantF(CBfLayerOpacity, opacity, 1);
}
/*
* Returns a texture containing the contents of this
* layer. Will try to return an existing texture if possible, or a temporary
* one if not. It is the callee's responsibility to release the shader
* resource view. Will return null if a texture could not be constructed.
* The texture will not be transformed, i.e., it will be in the same coord
* space as this.
* Any layer that can be used as a mask layer should override this method.
* If aSize is non-null and a texture is successfully returned, aSize will
* contain the size of the texture.
*/
virtual already_AddRefed<IDirect3DTexture9> GetAsTexture(gfxIntSize* aSize)
{
return nsnull;
}
protected:
LayerManagerD3D9 *mD3DManager;
};