Bug 612846 - Part 5: Make ContainerLayerD3D10 support component alpha. r=jrmuizel a=blocking-betan

This commit is contained in:
Bas Schouten 2011-01-28 06:34:33 +01:00
parent f1d664e045
commit 9c39576160

View File

@ -154,6 +154,16 @@ GetNextSiblingD3D10(LayerD3D10* aLayer)
: nsnull;
}
static PRBool
HasOpaqueAncestorLayer(Layer* aLayer)
{
for (Layer* l = aLayer->GetParent(); l; l = l->GetParent()) {
if (l->GetContentFlags() & Layer::CONTENT_OPAQUE)
return PR_TRUE;
}
return PR_FALSE;
}
void
ContainerLayerD3D10::RenderLayer()
{
@ -188,15 +198,47 @@ ContainerLayerD3D10::RenderLayer()
device()->CreateRenderTargetView(renderTexture, NULL, getter_AddRefs(rtView));
float black[] = { 0, 0, 0, 0};
device()->ClearRenderTargetView(rtView, black);
effect()->GetVariableByName("vRenderTargetOffset")->
GetRawValue(previousRenderTargetOffset, 0, 8);
if (mVisibleRegion.GetNumRects() != 1 || !(GetContentFlags() & CONTENT_OPAQUE)) {
const gfx3DMatrix& transform3D = GetEffectiveTransform();
gfxMatrix transform;
// If we have an opaque ancestor layer, then we can be sure that
// all the pixels we draw into are either opaque already or will be
// covered by something opaque. Otherwise copying up the background is
// not safe.
if (mSupportsComponentAlphaChildren) {
PRBool is2d = transform3D.Is2D(&transform);
NS_ASSERTION(is2d, "Transform should be 2d when mSupportsComponentAlphaChildren.");
// Copy background up from below. This applies any 2D transform that is
// applied to use relative to our parent, and compensates for the offset
// that was applied on our parent's rendering.
D3D10_BOX srcBox;
srcBox.left = visibleRect.x + PRInt32(transform.x0) - PRInt32(previousRenderTargetOffset[0]);
srcBox.top = visibleRect.y + PRInt32(transform.y0) - PRInt32(previousRenderTargetOffset[1]);
srcBox.right = srcBox.left + visibleRect.width;
srcBox.bottom = srcBox.top + visibleRect.height;
srcBox.back = 1;
srcBox.front = 0;
nsRefPtr<ID3D10Resource> srcResource;
previousRTView->GetResource(getter_AddRefs(srcResource));
device()->CopySubresourceRegion(renderTexture, 0,
0, 0, 0,
srcResource, 0,
&srcBox);
} else {
float black[] = { 0, 0, 0, 0};
device()->ClearRenderTargetView(rtView, black);
}
}
ID3D10RenderTargetView *rtViewPtr = rtView;
device()->OMSetRenderTargets(1, &rtViewPtr, NULL);
effect()->GetVariableByName("vRenderTargetOffset")->
GetRawValue(previousRenderTargetOffset, 0, 8);
renderTargetOffset[0] = (float)visibleRect.x;
renderTargetOffset[1] = (float)visibleRect.y;
effect()->GetVariableByName("vRenderTargetOffset")->
@ -205,10 +247,7 @@ ContainerLayerD3D10::RenderLayer()
previousViewportSize = mD3DManager->GetViewport();
mD3DManager->SetViewport(nsIntSize(visibleRect.Size()));
} else {
#ifdef DEBUG
PRBool is2d =
#endif
GetEffectiveTransform().Is2D(&contTransform);
PRBool is2d = GetEffectiveTransform().Is2D(&contTransform);
NS_ASSERTION(is2d, "Transform must be 2D");
}
@ -334,6 +373,31 @@ ContainerLayerD3D10::LayerManagerDestroyed()
void
ContainerLayerD3D10::Validate()
{
nsIntRect visibleRect = mVisibleRegion.GetBounds();
mSupportsComponentAlphaChildren = PR_FALSE;
if (UseIntermediateSurface()) {
const gfx3DMatrix& transform3D = GetEffectiveTransform();
gfxMatrix transform;
if (mVisibleRegion.GetNumRects() == 1 && (GetContentFlags() & CONTENT_OPAQUE)) {
// don't need a background, we're going to paint all opaque stuff
mSupportsComponentAlphaChildren = PR_TRUE;
} else {
if (HasOpaqueAncestorLayer(this) &&
transform3D.Is2D(&transform) && !transform.HasNonIntegerTranslation() &&
GetParent()->GetEffectiveVisibleRegion().GetBounds().Contains(visibleRect))
{
// In this case we can copy up the background. See RenderLayer.
mSupportsComponentAlphaChildren = PR_TRUE;
}
}
} else {
mSupportsComponentAlphaChildren = (GetContentFlags() & CONTENT_OPAQUE) ||
(mParent && mParent->SupportsComponentAlphaChildren());
}
Layer *layer = GetFirstChild();
while (layer) {
static_cast<LayerD3D10*>(layer->ImplData())->Validate();