michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "ContainerLayerD3D9.h" michael@0: michael@0: #include "ThebesLayerD3D9.h" michael@0: #include "ReadbackProcessor.h" michael@0: michael@0: using namespace mozilla::gfx; michael@0: michael@0: namespace mozilla { michael@0: namespace layers { michael@0: michael@0: ContainerLayerD3D9::ContainerLayerD3D9(LayerManagerD3D9 *aManager) michael@0: : ContainerLayer(aManager, nullptr) michael@0: , LayerD3D9(aManager) michael@0: { michael@0: mImplData = static_cast(this); michael@0: } michael@0: michael@0: ContainerLayerD3D9::~ContainerLayerD3D9() michael@0: { michael@0: while (mFirstChild) { michael@0: RemoveChild(mFirstChild); michael@0: } michael@0: } michael@0: michael@0: Layer* michael@0: ContainerLayerD3D9::GetLayer() michael@0: { michael@0: return this; michael@0: } michael@0: michael@0: LayerD3D9* michael@0: ContainerLayerD3D9::GetFirstChildD3D9() michael@0: { michael@0: if (!mFirstChild) { michael@0: return nullptr; michael@0: } michael@0: return static_cast(mFirstChild->ImplData()); michael@0: } michael@0: michael@0: void michael@0: ContainerLayerD3D9::RenderLayer() michael@0: { michael@0: nsRefPtr previousRenderTarget; michael@0: nsRefPtr renderTexture; michael@0: float previousRenderTargetOffset[4]; michael@0: float renderTargetOffset[] = { 0, 0, 0, 0 }; michael@0: float oldViewMatrix[4][4]; michael@0: michael@0: RECT containerD3D9ClipRect; michael@0: device()->GetScissorRect(&containerD3D9ClipRect); michael@0: // Convert scissor to an nsIntRect. RECT's are exclusive on the bottom and michael@0: // right values. michael@0: nsIntRect oldScissor(containerD3D9ClipRect.left, michael@0: containerD3D9ClipRect.top, michael@0: containerD3D9ClipRect.right - containerD3D9ClipRect.left, michael@0: containerD3D9ClipRect.bottom - containerD3D9ClipRect.top); michael@0: michael@0: ReadbackProcessor readback; michael@0: readback.BuildUpdates(this); michael@0: michael@0: nsIntRect visibleRect = GetEffectiveVisibleRegion().GetBounds(); michael@0: bool useIntermediate = UseIntermediateSurface(); michael@0: michael@0: mSupportsComponentAlphaChildren = false; michael@0: if (useIntermediate) { michael@0: nsRefPtr renderSurface; michael@0: if (!mD3DManager->CompositingDisabled()) { michael@0: device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget)); michael@0: HRESULT hr = device()->CreateTexture(visibleRect.width, visibleRect.height, 1, michael@0: D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, michael@0: D3DPOOL_DEFAULT, getter_AddRefs(renderTexture), michael@0: nullptr); michael@0: if (FAILED(hr)) { michael@0: ReportFailure(NS_LITERAL_CSTRING("ContainerLayerD3D9::ContainerRender(): Failed to create texture"), michael@0: hr); michael@0: return; michael@0: } michael@0: michael@0: nsRefPtr renderSurface; michael@0: renderTexture->GetSurfaceLevel(0, getter_AddRefs(renderSurface)); michael@0: device()->SetRenderTarget(0, renderSurface); michael@0: } michael@0: michael@0: if (mVisibleRegion.GetNumRects() == 1 && michael@0: (GetContentFlags() & CONTENT_OPAQUE)) { michael@0: // don't need a background, we're going to paint all opaque stuff michael@0: mSupportsComponentAlphaChildren = true; michael@0: } else { michael@0: Matrix4x4 transform3D = GetEffectiveTransform(); michael@0: Matrix transform; michael@0: // If we have an opaque ancestor layer, then we can be sure that michael@0: // all the pixels we draw into are either opaque already or will be michael@0: // covered by something opaque. Otherwise copying up the background is michael@0: // not safe. michael@0: HRESULT hr = E_FAIL; michael@0: if (HasOpaqueAncestorLayer(this) && michael@0: transform3D.Is2D(&transform) && !ThebesMatrix(transform).HasNonIntegerTranslation()) { michael@0: // Copy background up from below michael@0: RECT dest = { 0, 0, visibleRect.width, visibleRect.height }; michael@0: RECT src = dest; michael@0: ::OffsetRect(&src, michael@0: visibleRect.x + int32_t(transform._31), michael@0: visibleRect.y + int32_t(transform._32)); michael@0: if (!mD3DManager->CompositingDisabled()) { michael@0: hr = device()-> michael@0: StretchRect(previousRenderTarget, &src, renderSurface, &dest, D3DTEXF_NONE); michael@0: } michael@0: } michael@0: if (hr == S_OK) { michael@0: mSupportsComponentAlphaChildren = true; michael@0: } else if (!mD3DManager->CompositingDisabled()) { michael@0: device()-> michael@0: Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 0), 0, 0); michael@0: } michael@0: } michael@0: michael@0: device()-> michael@0: GetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1); michael@0: renderTargetOffset[0] = (float)visibleRect.x; michael@0: renderTargetOffset[1] = (float)visibleRect.y; michael@0: device()-> michael@0: SetVertexShaderConstantF(CBvRenderTargetOffset, renderTargetOffset, 1); michael@0: michael@0: gfx3DMatrix viewMatrix; michael@0: /* michael@0: * Matrix to transform to viewport space ( <-1.0, 1.0> topleft, michael@0: * <1.0, -1.0> bottomright) michael@0: */ michael@0: viewMatrix._11 = 2.0f / visibleRect.width; michael@0: viewMatrix._22 = -2.0f / visibleRect.height; michael@0: viewMatrix._41 = -1.0f; michael@0: viewMatrix._42 = 1.0f; michael@0: michael@0: device()-> michael@0: GetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4); michael@0: device()-> michael@0: SetVertexShaderConstantF(CBmProjection, &viewMatrix._11, 4); michael@0: } else { michael@0: mSupportsComponentAlphaChildren = michael@0: (GetContentFlags() & CONTENT_OPAQUE) || michael@0: (mParent && michael@0: mParent->SupportsComponentAlphaChildren()); michael@0: } michael@0: michael@0: nsAutoTArray children; michael@0: SortChildrenBy3DZOrder(children); michael@0: michael@0: /* michael@0: * Render this container's contents. michael@0: */ michael@0: for (uint32_t i = 0; i < children.Length(); i++) { michael@0: LayerD3D9* layerToRender = static_cast(children.ElementAt(i)->ImplData()); michael@0: michael@0: if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) { michael@0: continue; michael@0: } michael@0: michael@0: nsIntRect scissorRect = michael@0: layerToRender->GetLayer()->CalculateScissorRect(oldScissor, nullptr); michael@0: if (scissorRect.IsEmpty()) { michael@0: continue; michael@0: } michael@0: michael@0: RECT d3drect; michael@0: d3drect.left = scissorRect.x; michael@0: d3drect.top = scissorRect.y; michael@0: d3drect.right = scissorRect.x + scissorRect.width; michael@0: d3drect.bottom = scissorRect.y + scissorRect.height; michael@0: device()->SetScissorRect(&d3drect); michael@0: michael@0: if (layerToRender->GetLayer()->GetType() == TYPE_THEBES) { michael@0: static_cast(layerToRender)->RenderThebesLayer(&readback); michael@0: } else { michael@0: layerToRender->RenderLayer(); michael@0: } michael@0: } michael@0: michael@0: if (useIntermediate && !mD3DManager->CompositingDisabled()) { michael@0: device()->SetRenderTarget(0, previousRenderTarget); michael@0: device()->SetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1); michael@0: device()->SetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4); michael@0: michael@0: device()->SetVertexShaderConstantF(CBvLayerQuad, michael@0: ShaderConstantRect(visibleRect.x, michael@0: visibleRect.y, michael@0: visibleRect.width, michael@0: visibleRect.height), michael@0: 1); michael@0: michael@0: SetShaderTransformAndOpacity(); michael@0: mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER, michael@0: GetMaskLayer(), michael@0: GetTransform().CanDraw2D()); michael@0: michael@0: device()->SetTexture(0, renderTexture); michael@0: device()->SetScissorRect(&containerD3D9ClipRect); michael@0: device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); michael@0: } else { michael@0: device()->SetScissorRect(&containerD3D9ClipRect); michael@0: } michael@0: } michael@0: michael@0: void michael@0: ContainerLayerD3D9::LayerManagerDestroyed() michael@0: { michael@0: while (mFirstChild) { michael@0: GetFirstChildD3D9()->LayerManagerDestroyed(); michael@0: RemoveChild(mFirstChild); michael@0: } michael@0: } michael@0: michael@0: } /* layers */ michael@0: } /* mozilla */