mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Bug 584494: Avoid creating intermediate surfaces in D3D9 layers. r=roc a=blocking-betaN
This commit is contained in:
parent
50c51b53cc
commit
a09e9678c4
@ -227,7 +227,7 @@ CanvasLayerD3D9::GetLayer()
|
||||
}
|
||||
|
||||
void
|
||||
CanvasLayerD3D9::RenderLayer()
|
||||
CanvasLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform)
|
||||
{
|
||||
if (!mTexture) {
|
||||
Updated(mBounds);
|
||||
@ -246,7 +246,8 @@ CanvasLayerD3D9::RenderLayer()
|
||||
|
||||
device()->SetVertexShaderConstantF(CBvLayerQuad, quad, 1);
|
||||
|
||||
device()->SetVertexShaderConstantF(CBmLayerTransform, &mTransform._11, 4);
|
||||
gfx3DMatrix transform = mTransform * aTransform;
|
||||
device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4);
|
||||
|
||||
float opacity[4];
|
||||
/*
|
||||
|
@ -70,7 +70,7 @@ public:
|
||||
|
||||
// LayerD3D9 implementation
|
||||
virtual Layer* GetLayer();
|
||||
virtual void RenderLayer();
|
||||
virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform);
|
||||
virtual void CleanResources();
|
||||
virtual void LayerManagerDestroyed();
|
||||
|
||||
|
@ -48,7 +48,7 @@ ColorLayerD3D9::GetLayer()
|
||||
}
|
||||
|
||||
void
|
||||
ColorLayerD3D9::RenderLayer()
|
||||
ColorLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform)
|
||||
{
|
||||
// XXX we might be able to improve performance by using
|
||||
// IDirect3DDevice9::Clear
|
||||
@ -63,14 +63,15 @@ ColorLayerD3D9::RenderLayer()
|
||||
visibleRect.height),
|
||||
1);
|
||||
|
||||
device()->SetVertexShaderConstantF(CBmLayerTransform, &mTransform._11, 4);
|
||||
gfx3DMatrix transform = mTransform * aTransform;
|
||||
device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4);
|
||||
|
||||
float color[4];
|
||||
// color is premultiplied, so we need to adjust all channels
|
||||
color[0] = (float)(mColor.r * GetOpacity());
|
||||
color[1] = (float)(mColor.g * GetOpacity());
|
||||
color[2] = (float)(mColor.b * GetOpacity());
|
||||
color[3] = (float)(mColor.a * GetOpacity());
|
||||
color[0] = (float)(mColor.r * GetOpacity() * aOpacity);
|
||||
color[1] = (float)(mColor.g * GetOpacity() * aOpacity);
|
||||
color[2] = (float)(mColor.b * GetOpacity() * aOpacity);
|
||||
color[3] = (float)(mColor.a * GetOpacity() * aOpacity);
|
||||
|
||||
device()->SetPixelShaderConstantF(0, color, 1);
|
||||
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
// LayerD3D9 Implementation
|
||||
virtual Layer* GetLayer();
|
||||
|
||||
virtual void RenderLayer();
|
||||
virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform);
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
|
@ -135,9 +135,9 @@ ContainerLayerD3D9::GetFirstChildD3D9()
|
||||
}
|
||||
|
||||
void
|
||||
ContainerLayerD3D9::RenderLayer()
|
||||
ContainerLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform)
|
||||
{
|
||||
float opacity = GetOpacity();
|
||||
float opacity = GetOpacity() * aOpacity;
|
||||
nsRefPtr<IDirect3DSurface9> previousRenderTarget;
|
||||
nsRefPtr<IDirect3DTexture9> renderTexture;
|
||||
float previousRenderTargetOffset[4];
|
||||
@ -145,12 +145,13 @@ ContainerLayerD3D9::RenderLayer()
|
||||
float renderTargetOffset[] = { 0, 0, 0, 0 };
|
||||
float oldViewMatrix[4][4];
|
||||
|
||||
gfx3DMatrix transform = mTransform * aTransform;
|
||||
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
PRBool useIntermediate = (opacity != 1.0 || !mTransform.IsIdentity());
|
||||
PRBool useIntermediate = ShouldUseIntermediate(opacity, transform);
|
||||
|
||||
if (useIntermediate) {
|
||||
device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget));
|
||||
device()->GetScissorRect(&oldClipRect);
|
||||
device()->CreateTexture(visibleRect.width, visibleRect.height, 1,
|
||||
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_DEFAULT, getter_AddRefs(renderTexture),
|
||||
@ -184,38 +185,54 @@ ContainerLayerD3D9::RenderLayer()
|
||||
LayerD3D9 *layerToRender = GetFirstChildD3D9();
|
||||
while (layerToRender) {
|
||||
const nsIntRect *clipRect = layerToRender->GetLayer()->GetClipRect();
|
||||
RECT r;
|
||||
if (clipRect) {
|
||||
r.left = (LONG)(clipRect->x - renderTargetOffset[0]);
|
||||
r.top = (LONG)(clipRect->y - renderTargetOffset[1]);
|
||||
r.right = (LONG)(clipRect->x - renderTargetOffset[0] + clipRect->width);
|
||||
r.bottom = (LONG)(clipRect->y - renderTargetOffset[1] + clipRect->height);
|
||||
} else {
|
||||
if (useIntermediate) {
|
||||
if (clipRect || useIntermediate) {
|
||||
RECT r;
|
||||
device()->GetScissorRect(&oldClipRect);
|
||||
if (clipRect) {
|
||||
r.left = (LONG)(clipRect->x - renderTargetOffset[0]);
|
||||
r.top = (LONG)(clipRect->y - renderTargetOffset[1]);
|
||||
r.right = (LONG)(clipRect->x - renderTargetOffset[0] + clipRect->width);
|
||||
r.bottom = (LONG)(clipRect->y - renderTargetOffset[1] + clipRect->height);
|
||||
} else {
|
||||
r.left = 0;
|
||||
r.top = 0;
|
||||
} else {
|
||||
r.left = visibleRect.x;
|
||||
r.top = visibleRect.y;
|
||||
r.right = visibleRect.width;
|
||||
r.bottom = visibleRect.height;
|
||||
}
|
||||
r.right = r.left + visibleRect.width;
|
||||
r.bottom = r.top + visibleRect.height;
|
||||
|
||||
nsRefPtr<IDirect3DSurface9> renderSurface;
|
||||
device()->GetRenderTarget(0, getter_AddRefs(renderSurface));
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
renderSurface->GetDesc(&desc);
|
||||
|
||||
if (!useIntermediate) {
|
||||
// Intersect with current clip rect.
|
||||
r.left = NS_MAX<PRInt32>(oldClipRect.left, r.left);
|
||||
r.right = NS_MIN<PRInt32>(oldClipRect.right, r.right);
|
||||
r.top = NS_MAX<PRInt32>(oldClipRect.top, r.top);
|
||||
r.bottom = NS_MAX<PRInt32>(oldClipRect.bottom, r.bottom);
|
||||
} else {
|
||||
// > 0 is implied during the intersection when useIntermediate == true;
|
||||
r.left = NS_MAX<LONG>(0, r.left);
|
||||
r.top = NS_MAX<LONG>(0, r.top);
|
||||
}
|
||||
r.bottom = NS_MIN<LONG>(r.bottom, desc.Height);
|
||||
r.right = NS_MIN<LONG>(r.right, desc.Width);
|
||||
|
||||
device()->SetScissorRect(&r);
|
||||
}
|
||||
|
||||
nsRefPtr<IDirect3DSurface9> renderSurface;
|
||||
device()->GetRenderTarget(0, getter_AddRefs(renderSurface));
|
||||
if (!useIntermediate) {
|
||||
layerToRender->RenderLayer(opacity, transform);
|
||||
} else {
|
||||
layerToRender->RenderLayer(1.0, gfx3DMatrix());
|
||||
}
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
renderSurface->GetDesc(&desc);
|
||||
if (clipRect || useIntermediate) {
|
||||
device()->SetScissorRect(&oldClipRect);
|
||||
}
|
||||
|
||||
r.left = NS_MAX<LONG>(0, r.left);
|
||||
r.top = NS_MAX<LONG>(0, r.top);
|
||||
r.bottom = NS_MIN<LONG>(r.bottom, desc.Height);
|
||||
r.right = NS_MIN<LONG>(r.right, desc.Width);
|
||||
|
||||
device()->SetScissorRect(&r);
|
||||
|
||||
layerToRender->RenderLayer();
|
||||
Layer *nextSibling = layerToRender->GetLayer()->GetNextSibling();
|
||||
layerToRender = nextSibling ? static_cast<LayerD3D9*>(nextSibling->
|
||||
ImplData())
|
||||
@ -224,7 +241,6 @@ ContainerLayerD3D9::RenderLayer()
|
||||
|
||||
if (useIntermediate) {
|
||||
device()->SetRenderTarget(0, previousRenderTarget);
|
||||
device()->SetScissorRect(&oldClipRect);
|
||||
device()->SetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1);
|
||||
device()->SetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4);
|
||||
|
||||
@ -235,7 +251,7 @@ ContainerLayerD3D9::RenderLayer()
|
||||
visibleRect.height),
|
||||
1);
|
||||
|
||||
device()->SetVertexShaderConstantF(CBmLayerTransform, &mTransform._11, 4);
|
||||
device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4);
|
||||
|
||||
float opacityVector[4];
|
||||
/*
|
||||
@ -261,5 +277,32 @@ ContainerLayerD3D9::LayerManagerDestroyed()
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ContainerLayerD3D9::ShouldUseIntermediate(float aOpacity,
|
||||
const gfx3DMatrix &aMatrix)
|
||||
{
|
||||
if (aOpacity == 1.0f && aMatrix.IsIdentity()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Layer *firstChild = GetFirstChild();
|
||||
|
||||
if (!firstChild || (!firstChild->GetNextSibling() &&
|
||||
!firstChild->GetClipRect())) {
|
||||
// If we forward our transform to a child without using an intermediate,
|
||||
// we need to be sure that child does not have a clip rect, since its clip
|
||||
// rect would be applied after our transform.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aMatrix.IsIdentity() && (!firstChild || !firstChild->GetNextSibling())) {
|
||||
// If there's no transforms applied and a single child, opacity can always
|
||||
// be forwarded to our only child.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
|
@ -65,9 +65,13 @@ public:
|
||||
|
||||
PRBool IsEmpty();
|
||||
|
||||
void RenderLayer();
|
||||
void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform);
|
||||
|
||||
virtual void LayerManagerDestroyed();
|
||||
|
||||
private:
|
||||
bool ShouldUseIntermediate(float aOpacity,
|
||||
const gfx3DMatrix &aMatrix);
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
|
@ -148,7 +148,7 @@ ImageLayerD3D9::GetLayer()
|
||||
}
|
||||
|
||||
void
|
||||
ImageLayerD3D9::RenderLayer()
|
||||
ImageLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform)
|
||||
{
|
||||
if (!GetContainer()) {
|
||||
return;
|
||||
@ -172,14 +172,15 @@ ImageLayerD3D9::RenderLayer()
|
||||
yuvImage->mSize.height),
|
||||
1);
|
||||
|
||||
device()->SetVertexShaderConstantF(CBmLayerTransform, &mTransform._11, 4);
|
||||
gfx3DMatrix transform = mTransform * aTransform;
|
||||
device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4);
|
||||
|
||||
float opacity[4];
|
||||
/*
|
||||
* We always upload a 4 component float, but the shader will
|
||||
* only use the the first component since it's declared as a 'float'.
|
||||
*/
|
||||
opacity[0] = GetOpacity();
|
||||
opacity[0] = GetOpacity() * aOpacity;
|
||||
device()->SetPixelShaderConstantF(CBfLayerOpacity, opacity, 1);
|
||||
|
||||
mD3DManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER);
|
||||
@ -220,14 +221,15 @@ ImageLayerD3D9::RenderLayer()
|
||||
cairoImage->mSize.height),
|
||||
1);
|
||||
|
||||
device()->SetVertexShaderConstantF(CBmLayerTransform, &mTransform._11, 4);
|
||||
gfx3DMatrix transform = mTransform * aTransform;
|
||||
device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4);
|
||||
|
||||
float opacity[4];
|
||||
/*
|
||||
* We always upload a 4 component float, but the shader will
|
||||
* only use the the first component since it's declared as a 'float'.
|
||||
*/
|
||||
opacity[0] = GetOpacity();
|
||||
opacity[0] = GetOpacity() * aOpacity;
|
||||
device()->SetPixelShaderConstantF(CBfLayerOpacity, opacity, 1);
|
||||
|
||||
mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER);
|
||||
|
@ -87,7 +87,7 @@ public:
|
||||
// LayerD3D9 Implementation
|
||||
virtual Layer* GetLayer();
|
||||
|
||||
virtual void RenderLayer();
|
||||
virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform);
|
||||
};
|
||||
|
||||
class THEBES_API ImageD3D9
|
||||
|
@ -298,7 +298,7 @@ LayerManagerD3D9::Render()
|
||||
}
|
||||
device()->SetScissorRect(&r);
|
||||
|
||||
static_cast<LayerD3D9*>(mRoot->ImplData())->RenderLayer();
|
||||
static_cast<LayerD3D9*>(mRoot->ImplData())->RenderLayer(1.0, gfx3DMatrix());
|
||||
}
|
||||
|
||||
device()->EndScene();
|
||||
|
@ -251,7 +251,7 @@ public:
|
||||
|
||||
virtual Layer* GetLayer() = 0;
|
||||
|
||||
virtual void RenderLayer() = 0;
|
||||
virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) = 0;
|
||||
|
||||
/* This function may be used on device resets to clear all VRAM resources
|
||||
* that a layer might be using.
|
||||
|
@ -172,7 +172,7 @@ ThebesLayerD3D9::InvalidateRegion(const nsIntRegion &aRegion)
|
||||
}
|
||||
|
||||
void
|
||||
ThebesLayerD3D9::RenderLayer()
|
||||
ThebesLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform)
|
||||
{
|
||||
if (mVisibleRegion.IsEmpty()) {
|
||||
return;
|
||||
@ -225,14 +225,15 @@ ThebesLayerD3D9::RenderLayer()
|
||||
mValidRegion = mVisibleRegion;
|
||||
}
|
||||
|
||||
device()->SetVertexShaderConstantF(CBmLayerTransform, &mTransform._11, 4);
|
||||
gfx3DMatrix transform = mTransform * aTransform;
|
||||
device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4);
|
||||
|
||||
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] = GetOpacity();
|
||||
opacity[0] = GetOpacity() * aOpacity;
|
||||
device()->SetPixelShaderConstantF(0, opacity, 1);
|
||||
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
|
@ -61,7 +61,7 @@ public:
|
||||
/* LayerD3D9 implementation */
|
||||
Layer* GetLayer();
|
||||
virtual PRBool IsEmpty();
|
||||
virtual void RenderLayer();
|
||||
virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform);
|
||||
virtual void CleanResources();
|
||||
virtual void LayerManagerDestroyed();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user