|
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "ContainerLayerD3D9.h" |
|
7 |
|
8 #include "ThebesLayerD3D9.h" |
|
9 #include "ReadbackProcessor.h" |
|
10 |
|
11 using namespace mozilla::gfx; |
|
12 |
|
13 namespace mozilla { |
|
14 namespace layers { |
|
15 |
|
16 ContainerLayerD3D9::ContainerLayerD3D9(LayerManagerD3D9 *aManager) |
|
17 : ContainerLayer(aManager, nullptr) |
|
18 , LayerD3D9(aManager) |
|
19 { |
|
20 mImplData = static_cast<LayerD3D9*>(this); |
|
21 } |
|
22 |
|
23 ContainerLayerD3D9::~ContainerLayerD3D9() |
|
24 { |
|
25 while (mFirstChild) { |
|
26 RemoveChild(mFirstChild); |
|
27 } |
|
28 } |
|
29 |
|
30 Layer* |
|
31 ContainerLayerD3D9::GetLayer() |
|
32 { |
|
33 return this; |
|
34 } |
|
35 |
|
36 LayerD3D9* |
|
37 ContainerLayerD3D9::GetFirstChildD3D9() |
|
38 { |
|
39 if (!mFirstChild) { |
|
40 return nullptr; |
|
41 } |
|
42 return static_cast<LayerD3D9*>(mFirstChild->ImplData()); |
|
43 } |
|
44 |
|
45 void |
|
46 ContainerLayerD3D9::RenderLayer() |
|
47 { |
|
48 nsRefPtr<IDirect3DSurface9> previousRenderTarget; |
|
49 nsRefPtr<IDirect3DTexture9> renderTexture; |
|
50 float previousRenderTargetOffset[4]; |
|
51 float renderTargetOffset[] = { 0, 0, 0, 0 }; |
|
52 float oldViewMatrix[4][4]; |
|
53 |
|
54 RECT containerD3D9ClipRect; |
|
55 device()->GetScissorRect(&containerD3D9ClipRect); |
|
56 // Convert scissor to an nsIntRect. RECT's are exclusive on the bottom and |
|
57 // right values. |
|
58 nsIntRect oldScissor(containerD3D9ClipRect.left, |
|
59 containerD3D9ClipRect.top, |
|
60 containerD3D9ClipRect.right - containerD3D9ClipRect.left, |
|
61 containerD3D9ClipRect.bottom - containerD3D9ClipRect.top); |
|
62 |
|
63 ReadbackProcessor readback; |
|
64 readback.BuildUpdates(this); |
|
65 |
|
66 nsIntRect visibleRect = GetEffectiveVisibleRegion().GetBounds(); |
|
67 bool useIntermediate = UseIntermediateSurface(); |
|
68 |
|
69 mSupportsComponentAlphaChildren = false; |
|
70 if (useIntermediate) { |
|
71 nsRefPtr<IDirect3DSurface9> renderSurface; |
|
72 if (!mD3DManager->CompositingDisabled()) { |
|
73 device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget)); |
|
74 HRESULT hr = device()->CreateTexture(visibleRect.width, visibleRect.height, 1, |
|
75 D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, |
|
76 D3DPOOL_DEFAULT, getter_AddRefs(renderTexture), |
|
77 nullptr); |
|
78 if (FAILED(hr)) { |
|
79 ReportFailure(NS_LITERAL_CSTRING("ContainerLayerD3D9::ContainerRender(): Failed to create texture"), |
|
80 hr); |
|
81 return; |
|
82 } |
|
83 |
|
84 nsRefPtr<IDirect3DSurface9> renderSurface; |
|
85 renderTexture->GetSurfaceLevel(0, getter_AddRefs(renderSurface)); |
|
86 device()->SetRenderTarget(0, renderSurface); |
|
87 } |
|
88 |
|
89 if (mVisibleRegion.GetNumRects() == 1 && |
|
90 (GetContentFlags() & CONTENT_OPAQUE)) { |
|
91 // don't need a background, we're going to paint all opaque stuff |
|
92 mSupportsComponentAlphaChildren = true; |
|
93 } else { |
|
94 Matrix4x4 transform3D = GetEffectiveTransform(); |
|
95 Matrix transform; |
|
96 // If we have an opaque ancestor layer, then we can be sure that |
|
97 // all the pixels we draw into are either opaque already or will be |
|
98 // covered by something opaque. Otherwise copying up the background is |
|
99 // not safe. |
|
100 HRESULT hr = E_FAIL; |
|
101 if (HasOpaqueAncestorLayer(this) && |
|
102 transform3D.Is2D(&transform) && !ThebesMatrix(transform).HasNonIntegerTranslation()) { |
|
103 // Copy background up from below |
|
104 RECT dest = { 0, 0, visibleRect.width, visibleRect.height }; |
|
105 RECT src = dest; |
|
106 ::OffsetRect(&src, |
|
107 visibleRect.x + int32_t(transform._31), |
|
108 visibleRect.y + int32_t(transform._32)); |
|
109 if (!mD3DManager->CompositingDisabled()) { |
|
110 hr = device()-> |
|
111 StretchRect(previousRenderTarget, &src, renderSurface, &dest, D3DTEXF_NONE); |
|
112 } |
|
113 } |
|
114 if (hr == S_OK) { |
|
115 mSupportsComponentAlphaChildren = true; |
|
116 } else if (!mD3DManager->CompositingDisabled()) { |
|
117 device()-> |
|
118 Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 0), 0, 0); |
|
119 } |
|
120 } |
|
121 |
|
122 device()-> |
|
123 GetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1); |
|
124 renderTargetOffset[0] = (float)visibleRect.x; |
|
125 renderTargetOffset[1] = (float)visibleRect.y; |
|
126 device()-> |
|
127 SetVertexShaderConstantF(CBvRenderTargetOffset, renderTargetOffset, 1); |
|
128 |
|
129 gfx3DMatrix viewMatrix; |
|
130 /* |
|
131 * Matrix to transform to viewport space ( <-1.0, 1.0> topleft, |
|
132 * <1.0, -1.0> bottomright) |
|
133 */ |
|
134 viewMatrix._11 = 2.0f / visibleRect.width; |
|
135 viewMatrix._22 = -2.0f / visibleRect.height; |
|
136 viewMatrix._41 = -1.0f; |
|
137 viewMatrix._42 = 1.0f; |
|
138 |
|
139 device()-> |
|
140 GetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4); |
|
141 device()-> |
|
142 SetVertexShaderConstantF(CBmProjection, &viewMatrix._11, 4); |
|
143 } else { |
|
144 mSupportsComponentAlphaChildren = |
|
145 (GetContentFlags() & CONTENT_OPAQUE) || |
|
146 (mParent && |
|
147 mParent->SupportsComponentAlphaChildren()); |
|
148 } |
|
149 |
|
150 nsAutoTArray<Layer*, 12> children; |
|
151 SortChildrenBy3DZOrder(children); |
|
152 |
|
153 /* |
|
154 * Render this container's contents. |
|
155 */ |
|
156 for (uint32_t i = 0; i < children.Length(); i++) { |
|
157 LayerD3D9* layerToRender = static_cast<LayerD3D9*>(children.ElementAt(i)->ImplData()); |
|
158 |
|
159 if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) { |
|
160 continue; |
|
161 } |
|
162 |
|
163 nsIntRect scissorRect = |
|
164 layerToRender->GetLayer()->CalculateScissorRect(oldScissor, nullptr); |
|
165 if (scissorRect.IsEmpty()) { |
|
166 continue; |
|
167 } |
|
168 |
|
169 RECT d3drect; |
|
170 d3drect.left = scissorRect.x; |
|
171 d3drect.top = scissorRect.y; |
|
172 d3drect.right = scissorRect.x + scissorRect.width; |
|
173 d3drect.bottom = scissorRect.y + scissorRect.height; |
|
174 device()->SetScissorRect(&d3drect); |
|
175 |
|
176 if (layerToRender->GetLayer()->GetType() == TYPE_THEBES) { |
|
177 static_cast<ThebesLayerD3D9*>(layerToRender)->RenderThebesLayer(&readback); |
|
178 } else { |
|
179 layerToRender->RenderLayer(); |
|
180 } |
|
181 } |
|
182 |
|
183 if (useIntermediate && !mD3DManager->CompositingDisabled()) { |
|
184 device()->SetRenderTarget(0, previousRenderTarget); |
|
185 device()->SetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1); |
|
186 device()->SetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4); |
|
187 |
|
188 device()->SetVertexShaderConstantF(CBvLayerQuad, |
|
189 ShaderConstantRect(visibleRect.x, |
|
190 visibleRect.y, |
|
191 visibleRect.width, |
|
192 visibleRect.height), |
|
193 1); |
|
194 |
|
195 SetShaderTransformAndOpacity(); |
|
196 mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER, |
|
197 GetMaskLayer(), |
|
198 GetTransform().CanDraw2D()); |
|
199 |
|
200 device()->SetTexture(0, renderTexture); |
|
201 device()->SetScissorRect(&containerD3D9ClipRect); |
|
202 device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); |
|
203 } else { |
|
204 device()->SetScissorRect(&containerD3D9ClipRect); |
|
205 } |
|
206 } |
|
207 |
|
208 void |
|
209 ContainerLayerD3D9::LayerManagerDestroyed() |
|
210 { |
|
211 while (mFirstChild) { |
|
212 GetFirstChildD3D9()->LayerManagerDestroyed(); |
|
213 RemoveChild(mFirstChild); |
|
214 } |
|
215 } |
|
216 |
|
217 } /* layers */ |
|
218 } /* mozilla */ |