void ContainerLayerD3D9::LayerManagerDestroyed() { while (mFirstChild) { GetFirstChildD3D9()->LayerManagerDestroyed(); RemoveChild(mFirstChild); } }
void ContainerLayerD3D9::RenderLayer() { nsRefPtr<IDirect3DSurface9> previousRenderTarget; nsRefPtr<IDirect3DTexture9> renderTexture; float previousRenderTargetOffset[4]; RECT containerClipRect; float renderTargetOffset[] = { 0, 0, 0, 0 }; float oldViewMatrix[4][4]; device()->GetScissorRect(&containerClipRect); ReadbackProcessor readback; readback.BuildUpdates(this); nsIntRect visibleRect = mVisibleRegion.GetBounds(); PRBool useIntermediate = UseIntermediateSurface(); mSupportsComponentAlphaChildren = PR_FALSE; gfxMatrix contTransform; if (useIntermediate) { device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget)); device()->CreateTexture(visibleRect.width, visibleRect.height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, getter_AddRefs(renderTexture), NULL); nsRefPtr<IDirect3DSurface9> renderSurface; renderTexture->GetSurfaceLevel(0, getter_AddRefs(renderSurface)); device()->SetRenderTarget(0, renderSurface); if (mVisibleRegion.GetNumRects() == 1 && (GetContentFlags() & CONTENT_OPAQUE)) { // don't need a background, we're going to paint all opaque stuff mSupportsComponentAlphaChildren = PR_TRUE; } else { 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. HRESULT hr = E_FAIL; if (HasOpaqueAncestorLayer(this) && transform3D.Is2D(&transform) && !transform.HasNonIntegerTranslation()) { // Copy background up from below RECT dest = { 0, 0, visibleRect.width, visibleRect.height }; RECT src = dest; ::OffsetRect(&src, visibleRect.x + PRInt32(transform.x0), visibleRect.y + PRInt32(transform.y0)); hr = device()-> StretchRect(previousRenderTarget, &src, renderSurface, &dest, D3DTEXF_NONE); } if (hr == S_OK) { mSupportsComponentAlphaChildren = PR_TRUE; } else { device()->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 0), 0, 0); } } device()->GetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1); renderTargetOffset[0] = (float)visibleRect.x; renderTargetOffset[1] = (float)visibleRect.y; device()->SetVertexShaderConstantF(CBvRenderTargetOffset, renderTargetOffset, 1); gfx3DMatrix viewMatrix; /* * Matrix to transform to viewport space ( <-1.0, 1.0> topleft, * <1.0, -1.0> bottomright) */ viewMatrix._11 = 2.0f / visibleRect.width; viewMatrix._22 = -2.0f / visibleRect.height; viewMatrix._41 = -1.0f; viewMatrix._42 = 1.0f; device()->GetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4); device()->SetVertexShaderConstantF(CBmProjection, &viewMatrix._11, 4); } else { #ifdef DEBUG PRBool is2d = #endif GetEffectiveTransform().Is2D(&contTransform); NS_ASSERTION(is2d, "Transform must be 2D"); mSupportsComponentAlphaChildren = (GetContentFlags() & CONTENT_OPAQUE) || (mParent && mParent->SupportsComponentAlphaChildren()); } /* * Render this container's contents. */ for (LayerD3D9* layerToRender = GetFirstChildD3D9(); layerToRender != nsnull; layerToRender = GetNextSiblingD3D9(layerToRender)) { const nsIntRect* clipRect = layerToRender->GetLayer()->GetClipRect(); if ((clipRect && clipRect->IsEmpty()) || layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) { continue; } if (clipRect || useIntermediate) { 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 { r.left = 0; r.top = 0; r.right = visibleRect.width; r.bottom = visibleRect.height; } nsRefPtr<IDirect3DSurface9> renderSurface; device()->GetRenderTarget(0, getter_AddRefs(renderSurface)); D3DSURFACE_DESC desc; renderSurface->GetDesc(&desc); if (!useIntermediate) { // Transform clip rect if (clipRect) { gfxRect cliprect(r.left, r.top, r.right - r.left, r.bottom - r.top); gfxRect trScissor = contTransform.TransformBounds(cliprect); trScissor.Round(); nsIntRect trIntScissor; if (gfxUtils::GfxRectToIntRect(trScissor, &trIntScissor)) { r.left = trIntScissor.x; r.top = trIntScissor.y; r.right = trIntScissor.XMost(); r.bottom = trIntScissor.YMost(); } else { r.left = 0; r.top = 0; r.right = visibleRect.width; r.bottom = visibleRect.height; clipRect = nsnull; } } // Intersect with current clip rect. r.left = NS_MAX<PRInt32>(containerClipRect.left, r.left); r.right = NS_MIN<PRInt32>(containerClipRect.right, r.right); r.top = NS_MAX<PRInt32>(containerClipRect.top, r.top); r.bottom = NS_MIN<PRInt32>(containerClipRect.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); } if (layerToRender->GetLayer()->GetType() == TYPE_THEBES) { static_cast<ThebesLayerD3D9*>(layerToRender)->RenderThebesLayer(&readback); } else { layerToRender->RenderLayer(); } if (clipRect && !useIntermediate) { // In this situation we've set a new scissor rect and we will continue // to render directly to our container. We need to restore its scissor. // Not setting this when useIntermediate is true is an optimization since // we'll get a new one set anyway. device()->SetScissorRect(&containerClipRect); } } if (useIntermediate) { device()->SetRenderTarget(0, previousRenderTarget); device()->SetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1); device()->SetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4); device()->SetVertexShaderConstantF(CBvLayerQuad, ShaderConstantRect(visibleRect.x, visibleRect.y, visibleRect.width, visibleRect.height), 1); SetShaderTransformAndOpacity(); mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER); device()->SetScissorRect(&containerClipRect); device()->SetTexture(0, renderTexture); device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); } }