Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
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/. */
6 #include "ContainerLayerD3D10.h"
8 #include "ThebesLayerD3D10.h"
9 #include "ReadbackProcessor.h"
11 using namespace mozilla::gfx;
13 namespace mozilla {
14 namespace layers {
16 ContainerLayerD3D10::ContainerLayerD3D10(LayerManagerD3D10 *aManager)
17 : ContainerLayer(aManager, nullptr)
18 , LayerD3D10(aManager)
19 {
20 mImplData = static_cast<LayerD3D10*>(this);
21 }
23 ContainerLayerD3D10::~ContainerLayerD3D10()
24 {
25 while (mFirstChild) {
26 RemoveChild(mFirstChild);
27 }
28 }
30 Layer*
31 ContainerLayerD3D10::GetLayer()
32 {
33 return this;
34 }
36 LayerD3D10*
37 ContainerLayerD3D10::GetFirstChildD3D10()
38 {
39 if (!mFirstChild) {
40 return nullptr;
41 }
42 return static_cast<LayerD3D10*>(mFirstChild->ImplData());
43 }
45 static inline LayerD3D10*
46 GetNextSiblingD3D10(LayerD3D10* aLayer)
47 {
48 Layer* layer = aLayer->GetLayer()->GetNextSibling();
49 return layer ? static_cast<LayerD3D10*>(layer->
50 ImplData())
51 : nullptr;
52 }
54 void
55 ContainerLayerD3D10::RenderLayer()
56 {
57 float renderTargetOffset[] = { 0, 0 };
59 nsIntRect visibleRect = mVisibleRegion.GetBounds();
60 float opacity = GetEffectiveOpacity();
61 bool useIntermediate = UseIntermediateSurface();
63 nsRefPtr<ID3D10RenderTargetView> previousRTView;
64 nsRefPtr<ID3D10Texture2D> renderTexture;
65 nsRefPtr<ID3D10RenderTargetView> rtView;
66 float previousRenderTargetOffset[2];
67 nsIntSize previousViewportSize;
69 gfx3DMatrix oldViewMatrix;
71 if (useIntermediate) {
72 device()->OMGetRenderTargets(1, getter_AddRefs(previousRTView), nullptr);
74 D3D10_TEXTURE2D_DESC desc;
75 memset(&desc, 0, sizeof(D3D10_TEXTURE2D_DESC));
76 desc.ArraySize = 1;
77 desc.MipLevels = 1;
78 desc.Width = visibleRect.width;
79 desc.Height = visibleRect.height;
80 desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
81 desc.SampleDesc.Count = 1;
82 desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
83 HRESULT hr;
84 hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(renderTexture));
86 if (FAILED(hr)) {
87 LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("Failed to create new texture for ContainerLayerD3D10!"),
88 hr);
89 return;
90 }
92 hr = device()->CreateRenderTargetView(renderTexture, nullptr, getter_AddRefs(rtView));
93 NS_ASSERTION(SUCCEEDED(hr), "Failed to create render target view for ContainerLayerD3D10!");
95 effect()->GetVariableByName("vRenderTargetOffset")->
96 GetRawValue(previousRenderTargetOffset, 0, 8);
98 previousViewportSize = mD3DManager->GetViewport();
100 if (mVisibleRegion.GetNumRects() != 1 || !(GetContentFlags() & CONTENT_OPAQUE)) {
101 Matrix4x4 transform3D = GetEffectiveTransform();
102 Matrix transform;
103 // If we have an opaque ancestor layer, then we can be sure that
104 // all the pixels we draw into are either opaque already or will be
105 // covered by something opaque. Otherwise copying up the background is
106 // not safe.
107 if (mSupportsComponentAlphaChildren) {
108 bool is2d = transform3D.Is2D(&transform);
109 NS_ASSERTION(is2d, "Transform should be 2d when mSupportsComponentAlphaChildren.");
111 // Copy background up from below. This applies any 2D transform that is
112 // applied to use relative to our parent, and compensates for the offset
113 // that was applied on our parent's rendering.
114 D3D10_BOX srcBox;
115 srcBox.left = std::max<int32_t>(visibleRect.x + int32_t(transform._31) - int32_t(previousRenderTargetOffset[0]), 0);
116 srcBox.top = std::max<int32_t>(visibleRect.y + int32_t(transform._32) - int32_t(previousRenderTargetOffset[1]), 0);
117 srcBox.right = std::min<int32_t>(srcBox.left + visibleRect.width, previousViewportSize.width);
118 srcBox.bottom = std::min<int32_t>(srcBox.top + visibleRect.height, previousViewportSize.height);
119 srcBox.back = 1;
120 srcBox.front = 0;
122 nsRefPtr<ID3D10Resource> srcResource;
123 previousRTView->GetResource(getter_AddRefs(srcResource));
125 device()->CopySubresourceRegion(renderTexture, 0,
126 0, 0, 0,
127 srcResource, 0,
128 &srcBox);
129 } else {
130 float black[] = { 0, 0, 0, 0};
131 device()->ClearRenderTargetView(rtView, black);
132 }
133 }
135 ID3D10RenderTargetView *rtViewPtr = rtView;
136 device()->OMSetRenderTargets(1, &rtViewPtr, nullptr);
138 renderTargetOffset[0] = (float)visibleRect.x;
139 renderTargetOffset[1] = (float)visibleRect.y;
140 effect()->GetVariableByName("vRenderTargetOffset")->
141 SetRawValue(renderTargetOffset, 0, 8);
143 mD3DManager->SetViewport(nsIntSize(visibleRect.Size()));
144 }
146 D3D10_RECT oldD3D10Scissor;
147 UINT numRects = 1;
148 device()->RSGetScissorRects(&numRects, &oldD3D10Scissor);
149 // Convert scissor to an nsIntRect. D3D10_RECT's are exclusive
150 // on the bottom and right values.
151 nsIntRect oldScissor(oldD3D10Scissor.left,
152 oldD3D10Scissor.top,
153 oldD3D10Scissor.right - oldD3D10Scissor.left,
154 oldD3D10Scissor.bottom - oldD3D10Scissor.top);
156 nsAutoTArray<Layer*, 12> children;
157 SortChildrenBy3DZOrder(children);
159 /*
160 * Render this container's contents.
161 */
162 for (uint32_t i = 0; i < children.Length(); i++) {
163 LayerD3D10* layerToRender = static_cast<LayerD3D10*>(children.ElementAt(i)->ImplData());
165 if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) {
166 continue;
167 }
169 nsIntRect scissorRect =
170 layerToRender->GetLayer()->CalculateScissorRect(oldScissor, nullptr);
171 if (scissorRect.IsEmpty()) {
172 continue;
173 }
175 D3D10_RECT d3drect;
176 d3drect.left = scissorRect.x;
177 d3drect.top = scissorRect.y;
178 d3drect.right = scissorRect.x + scissorRect.width;
179 d3drect.bottom = scissorRect.y + scissorRect.height;
180 device()->RSSetScissorRects(1, &d3drect);
182 layerToRender->RenderLayer();
183 }
185 device()->RSSetScissorRects(1, &oldD3D10Scissor);
187 if (useIntermediate) {
188 mD3DManager->SetViewport(previousViewportSize);
189 ID3D10RenderTargetView *rtView = previousRTView;
190 device()->OMSetRenderTargets(1, &rtView, nullptr);
191 effect()->GetVariableByName("vRenderTargetOffset")->
192 SetRawValue(previousRenderTargetOffset, 0, 8);
194 SetEffectTransformAndOpacity();
196 ID3D10EffectTechnique *technique;
197 if (LoadMaskTexture()) {
198 if (GetTransform().CanDraw2D()) {
199 technique = SelectShader(SHADER_RGBA | SHADER_PREMUL | SHADER_MASK);
200 } else {
201 technique = SelectShader(SHADER_RGBA | SHADER_PREMUL | SHADER_MASK_3D);
202 }
203 } else {
204 technique = SelectShader(SHADER_RGBA | SHADER_PREMUL | SHADER_NO_MASK);
205 }
207 effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
208 ShaderConstantRectD3D10(
209 (float)visibleRect.x,
210 (float)visibleRect.y,
211 (float)visibleRect.width,
212 (float)visibleRect.height)
213 );
215 technique->GetPassByIndex(0)->Apply(0);
217 ID3D10ShaderResourceView *view;
218 device()->CreateShaderResourceView(renderTexture, nullptr, &view);
219 device()->PSSetShaderResources(0, 1, &view);
220 device()->Draw(4, 0);
221 view->Release();
222 }
223 }
225 void
226 ContainerLayerD3D10::LayerManagerDestroyed()
227 {
228 while (mFirstChild) {
229 GetFirstChildD3D10()->LayerManagerDestroyed();
230 RemoveChild(mFirstChild);
231 }
232 }
234 void
235 ContainerLayerD3D10::Validate()
236 {
237 nsIntRect visibleRect = mVisibleRegion.GetBounds();
239 mSupportsComponentAlphaChildren = false;
241 if (UseIntermediateSurface()) {
242 Matrix4x4 transform3D = GetEffectiveTransform();
243 Matrix transform;
245 if (mVisibleRegion.GetNumRects() == 1 && (GetContentFlags() & CONTENT_OPAQUE)) {
246 // don't need a background, we're going to paint all opaque stuff
247 mSupportsComponentAlphaChildren = true;
248 } else {
249 if (HasOpaqueAncestorLayer(this) &&
250 transform3D.Is2D(&transform) && !ThebesMatrix(transform).HasNonIntegerTranslation() &&
251 GetParent()->GetEffectiveVisibleRegion().GetBounds().Contains(visibleRect))
252 {
253 // In this case we can copy up the background. See RenderLayer.
254 mSupportsComponentAlphaChildren = true;
255 }
256 }
257 } else {
258 mSupportsComponentAlphaChildren = (GetContentFlags() & CONTENT_OPAQUE) ||
259 (mParent && mParent->SupportsComponentAlphaChildren());
260 }
262 ReadbackProcessor readback;
263 readback.BuildUpdates(this);
265 Layer *layer = GetFirstChild();
266 while (layer) {
267 if (layer->GetType() == TYPE_THEBES) {
268 static_cast<ThebesLayerD3D10*>(layer)->Validate(&readback);
269 } else {
270 static_cast<LayerD3D10*>(layer->ImplData())->Validate();
271 }
272 layer = layer->GetNextSibling();
273 }
274 }
276 } /* layers */
277 } /* mozilla */