|
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 "CompositorD3D11.h" |
|
7 |
|
8 #include "TextureD3D11.h" |
|
9 #include "CompositorD3D11Shaders.h" |
|
10 |
|
11 #include "gfxWindowsPlatform.h" |
|
12 #include "nsIWidget.h" |
|
13 #include "mozilla/layers/ImageHost.h" |
|
14 #include "mozilla/layers/ContentHost.h" |
|
15 #include "mozilla/layers/Effects.h" |
|
16 #include "nsWindowsHelpers.h" |
|
17 #include "gfxPrefs.h" |
|
18 |
|
19 #ifdef MOZ_METRO |
|
20 #include <DXGI1_2.h> |
|
21 #endif |
|
22 |
|
23 namespace mozilla { |
|
24 |
|
25 using namespace gfx; |
|
26 |
|
27 namespace layers { |
|
28 |
|
29 struct Vertex |
|
30 { |
|
31 float position[2]; |
|
32 }; |
|
33 |
|
34 // {1E4D7BEB-D8EC-4A0B-BF0A-63E6DE129425} |
|
35 static const GUID sDeviceAttachmentsD3D11 = |
|
36 { 0x1e4d7beb, 0xd8ec, 0x4a0b, { 0xbf, 0xa, 0x63, 0xe6, 0xde, 0x12, 0x94, 0x25 } }; |
|
37 // {88041664-C835-4AA8-ACB8-7EC832357ED8} |
|
38 static const GUID sLayerManagerCount = |
|
39 { 0x88041664, 0xc835, 0x4aa8, { 0xac, 0xb8, 0x7e, 0xc8, 0x32, 0x35, 0x7e, 0xd8 } }; |
|
40 |
|
41 const FLOAT sBlendFactor[] = { 0, 0, 0, 0 }; |
|
42 |
|
43 struct DeviceAttachmentsD3D11 |
|
44 { |
|
45 RefPtr<ID3D11InputLayout> mInputLayout; |
|
46 RefPtr<ID3D11Buffer> mVertexBuffer; |
|
47 RefPtr<ID3D11VertexShader> mVSQuadShader[3]; |
|
48 RefPtr<ID3D11PixelShader> mSolidColorShader[2]; |
|
49 RefPtr<ID3D11PixelShader> mRGBAShader[3]; |
|
50 RefPtr<ID3D11PixelShader> mRGBShader[2]; |
|
51 RefPtr<ID3D11PixelShader> mYCbCrShader[2]; |
|
52 RefPtr<ID3D11PixelShader> mComponentAlphaShader[2]; |
|
53 RefPtr<ID3D11Buffer> mPSConstantBuffer; |
|
54 RefPtr<ID3D11Buffer> mVSConstantBuffer; |
|
55 RefPtr<ID3D11RasterizerState> mRasterizerState; |
|
56 RefPtr<ID3D11SamplerState> mLinearSamplerState; |
|
57 RefPtr<ID3D11SamplerState> mPointSamplerState; |
|
58 RefPtr<ID3D11BlendState> mPremulBlendState; |
|
59 RefPtr<ID3D11BlendState> mNonPremulBlendState; |
|
60 RefPtr<ID3D11BlendState> mComponentBlendState; |
|
61 RefPtr<ID3D11BlendState> mDisabledBlendState; |
|
62 }; |
|
63 |
|
64 CompositorD3D11::CompositorD3D11(nsIWidget* aWidget) |
|
65 : mAttachments(nullptr) |
|
66 , mWidget(aWidget) |
|
67 , mHwnd(nullptr) |
|
68 , mDisableSequenceForNextFrame(false) |
|
69 { |
|
70 SetBackend(LayersBackend::LAYERS_D3D11); |
|
71 } |
|
72 |
|
73 CompositorD3D11::~CompositorD3D11() |
|
74 { |
|
75 if (mDevice) { |
|
76 int referenceCount = 0; |
|
77 UINT size = sizeof(referenceCount); |
|
78 HRESULT hr = mDevice->GetPrivateData(sLayerManagerCount, &size, &referenceCount); |
|
79 NS_ASSERTION(SUCCEEDED(hr), "Reference count not found on device."); |
|
80 referenceCount--; |
|
81 mDevice->SetPrivateData(sLayerManagerCount, |
|
82 sizeof(referenceCount), |
|
83 &referenceCount); |
|
84 |
|
85 if (!referenceCount) { |
|
86 DeviceAttachmentsD3D11 *attachments; |
|
87 size = sizeof(attachments); |
|
88 mDevice->GetPrivateData(sDeviceAttachmentsD3D11, &size, &attachments); |
|
89 // No LayerManagers left for this device. Clear out interfaces stored |
|
90 // which hold a reference to the device. |
|
91 mDevice->SetPrivateData(sDeviceAttachmentsD3D11, 0, nullptr); |
|
92 |
|
93 delete attachments; |
|
94 } |
|
95 } |
|
96 } |
|
97 |
|
98 bool |
|
99 CompositorD3D11::Initialize() |
|
100 { |
|
101 HRESULT hr; |
|
102 |
|
103 mDevice = gfxWindowsPlatform::GetPlatform()->GetD3D11Device(); |
|
104 |
|
105 if (!mDevice) { |
|
106 return false; |
|
107 } |
|
108 |
|
109 mDevice->GetImmediateContext(byRef(mContext)); |
|
110 |
|
111 if (!mContext) { |
|
112 return false; |
|
113 } |
|
114 |
|
115 mHwnd = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW); |
|
116 |
|
117 memset(&mVSConstants, 0, sizeof(VertexShaderConstants)); |
|
118 |
|
119 int referenceCount = 0; |
|
120 UINT size = sizeof(referenceCount); |
|
121 // If this isn't there yet it'll fail, count will remain 0, which is correct. |
|
122 mDevice->GetPrivateData(sLayerManagerCount, &size, &referenceCount); |
|
123 referenceCount++; |
|
124 mDevice->SetPrivateData(sLayerManagerCount, |
|
125 sizeof(referenceCount), |
|
126 &referenceCount); |
|
127 |
|
128 size = sizeof(DeviceAttachmentsD3D11*); |
|
129 if (FAILED(mDevice->GetPrivateData(sDeviceAttachmentsD3D11, |
|
130 &size, |
|
131 &mAttachments))) { |
|
132 mAttachments = new DeviceAttachmentsD3D11; |
|
133 mDevice->SetPrivateData(sDeviceAttachmentsD3D11, |
|
134 sizeof(mAttachments), |
|
135 &mAttachments); |
|
136 |
|
137 D3D11_INPUT_ELEMENT_DESC layout[] = |
|
138 { |
|
139 { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, |
|
140 }; |
|
141 |
|
142 hr = mDevice->CreateInputLayout(layout, |
|
143 sizeof(layout) / sizeof(D3D11_INPUT_ELEMENT_DESC), |
|
144 LayerQuadVS, |
|
145 sizeof(LayerQuadVS), |
|
146 byRef(mAttachments->mInputLayout)); |
|
147 |
|
148 if (FAILED(hr)) { |
|
149 return false; |
|
150 } |
|
151 |
|
152 Vertex vertices[] = { {0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0} }; |
|
153 CD3D11_BUFFER_DESC bufferDesc(sizeof(vertices), D3D11_BIND_VERTEX_BUFFER); |
|
154 D3D11_SUBRESOURCE_DATA data; |
|
155 data.pSysMem = (void*)vertices; |
|
156 |
|
157 hr = mDevice->CreateBuffer(&bufferDesc, &data, byRef(mAttachments->mVertexBuffer)); |
|
158 |
|
159 if (FAILED(hr)) { |
|
160 return false; |
|
161 } |
|
162 |
|
163 if (!CreateShaders()) { |
|
164 return false; |
|
165 } |
|
166 |
|
167 CD3D11_BUFFER_DESC cBufferDesc(sizeof(VertexShaderConstants), |
|
168 D3D11_BIND_CONSTANT_BUFFER, |
|
169 D3D11_USAGE_DYNAMIC, |
|
170 D3D11_CPU_ACCESS_WRITE); |
|
171 |
|
172 hr = mDevice->CreateBuffer(&cBufferDesc, nullptr, byRef(mAttachments->mVSConstantBuffer)); |
|
173 if (FAILED(hr)) { |
|
174 return false; |
|
175 } |
|
176 |
|
177 cBufferDesc.ByteWidth = sizeof(PixelShaderConstants); |
|
178 hr = mDevice->CreateBuffer(&cBufferDesc, nullptr, byRef(mAttachments->mPSConstantBuffer)); |
|
179 if (FAILED(hr)) { |
|
180 return false; |
|
181 } |
|
182 |
|
183 CD3D11_RASTERIZER_DESC rastDesc(D3D11_DEFAULT); |
|
184 rastDesc.CullMode = D3D11_CULL_NONE; |
|
185 rastDesc.ScissorEnable = TRUE; |
|
186 |
|
187 hr = mDevice->CreateRasterizerState(&rastDesc, byRef(mAttachments->mRasterizerState)); |
|
188 if (FAILED(hr)) { |
|
189 return false; |
|
190 } |
|
191 |
|
192 CD3D11_SAMPLER_DESC samplerDesc(D3D11_DEFAULT); |
|
193 samplerDesc.AddressU = samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; |
|
194 hr = mDevice->CreateSamplerState(&samplerDesc, byRef(mAttachments->mLinearSamplerState)); |
|
195 if (FAILED(hr)) { |
|
196 return false; |
|
197 } |
|
198 |
|
199 samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; |
|
200 hr = mDevice->CreateSamplerState(&samplerDesc, byRef(mAttachments->mPointSamplerState)); |
|
201 if (FAILED(hr)) { |
|
202 return false; |
|
203 } |
|
204 |
|
205 CD3D11_BLEND_DESC blendDesc(D3D11_DEFAULT); |
|
206 D3D11_RENDER_TARGET_BLEND_DESC rtBlendPremul = { |
|
207 TRUE, |
|
208 D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, |
|
209 D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, |
|
210 D3D11_COLOR_WRITE_ENABLE_ALL |
|
211 }; |
|
212 blendDesc.RenderTarget[0] = rtBlendPremul; |
|
213 hr = mDevice->CreateBlendState(&blendDesc, byRef(mAttachments->mPremulBlendState)); |
|
214 if (FAILED(hr)) { |
|
215 return false; |
|
216 } |
|
217 |
|
218 D3D11_RENDER_TARGET_BLEND_DESC rtBlendNonPremul = { |
|
219 TRUE, |
|
220 D3D11_BLEND_SRC_ALPHA, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, |
|
221 D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, |
|
222 D3D11_COLOR_WRITE_ENABLE_ALL |
|
223 }; |
|
224 blendDesc.RenderTarget[0] = rtBlendNonPremul; |
|
225 hr = mDevice->CreateBlendState(&blendDesc, byRef(mAttachments->mNonPremulBlendState)); |
|
226 if (FAILED(hr)) { |
|
227 return false; |
|
228 } |
|
229 |
|
230 if (gfxPrefs::ComponentAlphaEnabled()) { |
|
231 D3D11_RENDER_TARGET_BLEND_DESC rtBlendComponent = { |
|
232 TRUE, |
|
233 D3D11_BLEND_ONE, |
|
234 D3D11_BLEND_INV_SRC1_COLOR, |
|
235 D3D11_BLEND_OP_ADD, |
|
236 D3D11_BLEND_ONE, |
|
237 D3D11_BLEND_INV_SRC_ALPHA, |
|
238 D3D11_BLEND_OP_ADD, |
|
239 D3D11_COLOR_WRITE_ENABLE_ALL |
|
240 }; |
|
241 blendDesc.RenderTarget[0] = rtBlendComponent; |
|
242 hr = mDevice->CreateBlendState(&blendDesc, byRef(mAttachments->mComponentBlendState)); |
|
243 if (FAILED(hr)) { |
|
244 return false; |
|
245 } |
|
246 } |
|
247 |
|
248 D3D11_RENDER_TARGET_BLEND_DESC rtBlendDisabled = { |
|
249 FALSE, |
|
250 D3D11_BLEND_SRC_ALPHA, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, |
|
251 D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, |
|
252 D3D11_COLOR_WRITE_ENABLE_ALL |
|
253 }; |
|
254 blendDesc.RenderTarget[0] = rtBlendDisabled; |
|
255 hr = mDevice->CreateBlendState(&blendDesc, byRef(mAttachments->mDisabledBlendState)); |
|
256 if (FAILED(hr)) { |
|
257 return false; |
|
258 } |
|
259 } |
|
260 |
|
261 nsRefPtr<IDXGIDevice> dxgiDevice; |
|
262 nsRefPtr<IDXGIAdapter> dxgiAdapter; |
|
263 |
|
264 mDevice->QueryInterface(dxgiDevice.StartAssignment()); |
|
265 dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter)); |
|
266 |
|
267 #ifdef MOZ_METRO |
|
268 if (IsRunningInWindowsMetro()) { |
|
269 nsRefPtr<IDXGIFactory2> dxgiFactory; |
|
270 dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment())); |
|
271 |
|
272 nsIntRect rect; |
|
273 mWidget->GetClientBounds(rect); |
|
274 |
|
275 DXGI_SWAP_CHAIN_DESC1 swapDesc = { 0 }; |
|
276 // Automatically detect the width and the height from the winrt CoreWindow |
|
277 swapDesc.Width = rect.width; |
|
278 swapDesc.Height = rect.height; |
|
279 // This is the most common swapchain format |
|
280 swapDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; |
|
281 swapDesc.Stereo = false; |
|
282 // Don't use multi-sampling |
|
283 swapDesc.SampleDesc.Count = 1; |
|
284 swapDesc.SampleDesc.Quality = 0; |
|
285 swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; |
|
286 // Use double buffering to enable flip |
|
287 swapDesc.BufferCount = 2; |
|
288 swapDesc.Scaling = DXGI_SCALING_NONE; |
|
289 // All Metro style apps must use this SwapEffect |
|
290 swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; |
|
291 swapDesc.Flags = 0; |
|
292 |
|
293 /** |
|
294 * Create a swap chain, this swap chain will contain the backbuffer for |
|
295 * the window we draw to. The front buffer is the full screen front |
|
296 * buffer. |
|
297 */ |
|
298 nsRefPtr<IDXGISwapChain1> swapChain1; |
|
299 hr = dxgiFactory->CreateSwapChainForCoreWindow( |
|
300 dxgiDevice, (IUnknown *)mWidget->GetNativeData(NS_NATIVE_ICOREWINDOW), |
|
301 &swapDesc, nullptr, getter_AddRefs(swapChain1)); |
|
302 if (FAILED(hr)) { |
|
303 return false; |
|
304 } |
|
305 mSwapChain = swapChain1; |
|
306 } else |
|
307 #endif |
|
308 { |
|
309 nsRefPtr<IDXGIFactory> dxgiFactory; |
|
310 dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment())); |
|
311 |
|
312 DXGI_SWAP_CHAIN_DESC swapDesc; |
|
313 ::ZeroMemory(&swapDesc, sizeof(swapDesc)); |
|
314 swapDesc.BufferDesc.Width = 0; |
|
315 swapDesc.BufferDesc.Height = 0; |
|
316 swapDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; |
|
317 swapDesc.BufferDesc.RefreshRate.Numerator = 60; |
|
318 swapDesc.BufferDesc.RefreshRate.Denominator = 1; |
|
319 swapDesc.SampleDesc.Count = 1; |
|
320 swapDesc.SampleDesc.Quality = 0; |
|
321 swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; |
|
322 swapDesc.BufferCount = 1; |
|
323 swapDesc.OutputWindow = mHwnd; |
|
324 swapDesc.Windowed = TRUE; |
|
325 // We don't really need this flag, however it seems on some NVidia hardware |
|
326 // smaller area windows do not present properly without this flag. This flag |
|
327 // should have no negative consequences by itself. See bug 613790. This flag |
|
328 // is broken on optimus devices. As a temporary solution we don't set it |
|
329 // there, the only way of reliably detecting we're on optimus is looking for |
|
330 // the DLL. See Bug 623807. |
|
331 if (gfxWindowsPlatform::IsOptimus()) { |
|
332 swapDesc.Flags = 0; |
|
333 } else { |
|
334 swapDesc.Flags = DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE; |
|
335 } |
|
336 |
|
337 /** |
|
338 * Create a swap chain, this swap chain will contain the backbuffer for |
|
339 * the window we draw to. The front buffer is the full screen front |
|
340 * buffer. |
|
341 */ |
|
342 hr = dxgiFactory->CreateSwapChain(dxgiDevice, &swapDesc, byRef(mSwapChain)); |
|
343 if (FAILED(hr)) { |
|
344 return false; |
|
345 } |
|
346 |
|
347 // We need this because we don't want DXGI to respond to Alt+Enter. |
|
348 dxgiFactory->MakeWindowAssociation(swapDesc.OutputWindow, |
|
349 DXGI_MWA_NO_WINDOW_CHANGES); |
|
350 } |
|
351 |
|
352 return true; |
|
353 } |
|
354 |
|
355 TemporaryRef<DataTextureSource> |
|
356 CompositorD3D11::CreateDataTextureSource(TextureFlags aFlags) |
|
357 { |
|
358 RefPtr<DataTextureSource> result = new DataTextureSourceD3D11(gfx::SurfaceFormat::UNKNOWN, |
|
359 this, aFlags); |
|
360 return result.forget(); |
|
361 } |
|
362 |
|
363 TextureFactoryIdentifier |
|
364 CompositorD3D11::GetTextureFactoryIdentifier() |
|
365 { |
|
366 TextureFactoryIdentifier ident; |
|
367 ident.mMaxTextureSize = GetMaxTextureSize(); |
|
368 ident.mParentProcessId = XRE_GetProcessType(); |
|
369 ident.mParentBackend = LayersBackend::LAYERS_D3D11; |
|
370 return ident; |
|
371 } |
|
372 |
|
373 bool |
|
374 CompositorD3D11::CanUseCanvasLayerForSize(const gfx::IntSize& aSize) |
|
375 { |
|
376 int32_t maxTextureSize = GetMaxTextureSize(); |
|
377 |
|
378 if (aSize.width > maxTextureSize || aSize.height > maxTextureSize) { |
|
379 return false; |
|
380 } |
|
381 |
|
382 return true; |
|
383 } |
|
384 |
|
385 int32_t |
|
386 CompositorD3D11::GetMaxTextureSize() const |
|
387 { |
|
388 return GetMaxTextureSizeForFeatureLevel(mFeatureLevel); |
|
389 } |
|
390 |
|
391 TemporaryRef<CompositingRenderTarget> |
|
392 CompositorD3D11::CreateRenderTarget(const gfx::IntRect& aRect, |
|
393 SurfaceInitMode aInit) |
|
394 { |
|
395 CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aRect.width, aRect.height, 1, 1, |
|
396 D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET); |
|
397 |
|
398 RefPtr<ID3D11Texture2D> texture; |
|
399 mDevice->CreateTexture2D(&desc, nullptr, byRef(texture)); |
|
400 NS_ASSERTION(texture, "Could not create texture"); |
|
401 if (!texture) { |
|
402 return nullptr; |
|
403 } |
|
404 |
|
405 RefPtr<CompositingRenderTargetD3D11> rt = new CompositingRenderTargetD3D11(texture, aRect.TopLeft()); |
|
406 rt->SetSize(IntSize(aRect.width, aRect.height)); |
|
407 |
|
408 if (aInit == INIT_MODE_CLEAR) { |
|
409 FLOAT clear[] = { 0, 0, 0, 0 }; |
|
410 mContext->ClearRenderTargetView(rt->mRTView, clear); |
|
411 } |
|
412 |
|
413 return rt; |
|
414 } |
|
415 |
|
416 TemporaryRef<CompositingRenderTarget> |
|
417 CompositorD3D11::CreateRenderTargetFromSource(const gfx::IntRect &aRect, |
|
418 const CompositingRenderTarget* aSource, |
|
419 const gfx::IntPoint &aSourcePoint) |
|
420 { |
|
421 CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, |
|
422 aRect.width, aRect.height, 1, 1, |
|
423 D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET); |
|
424 |
|
425 RefPtr<ID3D11Texture2D> texture; |
|
426 mDevice->CreateTexture2D(&desc, nullptr, byRef(texture)); |
|
427 NS_ASSERTION(texture, "Could not create texture"); |
|
428 if (!texture) { |
|
429 return nullptr; |
|
430 } |
|
431 |
|
432 if (aSource) { |
|
433 const CompositingRenderTargetD3D11* sourceD3D11 = |
|
434 static_cast<const CompositingRenderTargetD3D11*>(aSource); |
|
435 |
|
436 D3D11_BOX srcBox; |
|
437 srcBox.left = aSourcePoint.x; |
|
438 srcBox.top = aSourcePoint.y; |
|
439 srcBox.front = 0; |
|
440 srcBox.right = aSourcePoint.x + aRect.width; |
|
441 srcBox.bottom = aSourcePoint.y + aRect.height; |
|
442 srcBox.back = 0; |
|
443 |
|
444 const IntSize& srcSize = sourceD3D11->GetSize(); |
|
445 MOZ_ASSERT(srcSize.width >= 0 && srcSize.height >= 0, |
|
446 "render targets should have nonnegative sizes"); |
|
447 if (srcBox.right <= static_cast<uint32_t>(srcSize.width) && |
|
448 srcBox.bottom <= static_cast<uint32_t>(srcSize.height)) { |
|
449 mContext->CopySubresourceRegion(texture, 0, |
|
450 0, 0, 0, |
|
451 sourceD3D11->GetD3D11Texture(), 0, |
|
452 &srcBox); |
|
453 } else { |
|
454 NS_WARNING("Could not copy render target - source rect out of bounds"); |
|
455 } |
|
456 } |
|
457 |
|
458 RefPtr<CompositingRenderTargetD3D11> rt = |
|
459 new CompositingRenderTargetD3D11(texture, aRect.TopLeft()); |
|
460 rt->SetSize(aRect.Size()); |
|
461 |
|
462 return rt; |
|
463 } |
|
464 |
|
465 void |
|
466 CompositorD3D11::SetRenderTarget(CompositingRenderTarget* aRenderTarget) |
|
467 { |
|
468 MOZ_ASSERT(aRenderTarget); |
|
469 CompositingRenderTargetD3D11* newRT = |
|
470 static_cast<CompositingRenderTargetD3D11*>(aRenderTarget); |
|
471 ID3D11RenderTargetView* view = newRT->mRTView; |
|
472 mCurrentRT = newRT; |
|
473 mContext->OMSetRenderTargets(1, &view, nullptr); |
|
474 PrepareViewport(newRT->GetSize(), gfx::Matrix()); |
|
475 } |
|
476 |
|
477 void |
|
478 CompositorD3D11::SetPSForEffect(Effect* aEffect, MaskType aMaskType, gfx::SurfaceFormat aFormat) |
|
479 { |
|
480 switch (aEffect->mType) { |
|
481 case EFFECT_SOLID_COLOR: |
|
482 mContext->PSSetShader(mAttachments->mSolidColorShader[aMaskType], nullptr, 0); |
|
483 return; |
|
484 case EFFECT_RENDER_TARGET: |
|
485 mContext->PSSetShader(mAttachments->mRGBAShader[aMaskType], nullptr, 0); |
|
486 return; |
|
487 case EFFECT_RGB: |
|
488 mContext->PSSetShader((aFormat == SurfaceFormat::B8G8R8A8 || aFormat == SurfaceFormat::R8G8B8A8) |
|
489 ? mAttachments->mRGBAShader[aMaskType] |
|
490 : mAttachments->mRGBShader[aMaskType], nullptr, 0); |
|
491 return; |
|
492 case EFFECT_YCBCR: |
|
493 mContext->PSSetShader(mAttachments->mYCbCrShader[aMaskType], nullptr, 0); |
|
494 return; |
|
495 case EFFECT_COMPONENT_ALPHA: |
|
496 mContext->PSSetShader(mAttachments->mComponentAlphaShader[aMaskType], nullptr, 0); |
|
497 return; |
|
498 default: |
|
499 NS_WARNING("No shader to load"); |
|
500 return; |
|
501 } |
|
502 } |
|
503 |
|
504 void |
|
505 CompositorD3D11::ClearRect(const gfx::Rect& aRect) |
|
506 { |
|
507 mContext->OMSetBlendState(mAttachments->mDisabledBlendState, sBlendFactor, 0xFFFFFFFF); |
|
508 |
|
509 Matrix4x4 identity; |
|
510 memcpy(&mVSConstants.layerTransform, &identity._11, 64); |
|
511 |
|
512 mVSConstants.layerQuad = aRect; |
|
513 mVSConstants.renderTargetOffset[0] = 0; |
|
514 mVSConstants.renderTargetOffset[1] = 0; |
|
515 mPSConstants.layerOpacity[0] = 1.0f; |
|
516 |
|
517 D3D11_RECT scissor; |
|
518 scissor.left = aRect.x; |
|
519 scissor.right = aRect.XMost(); |
|
520 scissor.top = aRect.y; |
|
521 scissor.bottom = aRect.YMost(); |
|
522 mContext->RSSetScissorRects(1, &scissor); |
|
523 mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); |
|
524 mContext->VSSetShader(mAttachments->mVSQuadShader[MaskNone], nullptr, 0); |
|
525 |
|
526 mContext->PSSetShader(mAttachments->mSolidColorShader[MaskNone], nullptr, 0); |
|
527 mPSConstants.layerColor[0] = 0; |
|
528 mPSConstants.layerColor[1] = 0; |
|
529 mPSConstants.layerColor[2] = 0; |
|
530 mPSConstants.layerColor[3] = 0; |
|
531 |
|
532 UpdateConstantBuffers(); |
|
533 |
|
534 mContext->Draw(4, 0); |
|
535 |
|
536 mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF); |
|
537 } |
|
538 |
|
539 void |
|
540 CompositorD3D11::DrawQuad(const gfx::Rect& aRect, |
|
541 const gfx::Rect& aClipRect, |
|
542 const EffectChain& aEffectChain, |
|
543 gfx::Float aOpacity, |
|
544 const gfx::Matrix4x4& aTransform) |
|
545 { |
|
546 MOZ_ASSERT(mCurrentRT, "No render target"); |
|
547 memcpy(&mVSConstants.layerTransform, &aTransform._11, 64); |
|
548 IntPoint origin = mCurrentRT->GetOrigin(); |
|
549 mVSConstants.renderTargetOffset[0] = origin.x; |
|
550 mVSConstants.renderTargetOffset[1] = origin.y; |
|
551 mVSConstants.layerQuad = aRect; |
|
552 |
|
553 mPSConstants.layerOpacity[0] = aOpacity; |
|
554 |
|
555 bool restoreBlendMode = false; |
|
556 |
|
557 MaskType maskType = MaskNone; |
|
558 |
|
559 if (aEffectChain.mSecondaryEffects[EFFECT_MASK]) { |
|
560 if (aTransform.Is2D()) { |
|
561 maskType = Mask2d; |
|
562 } else { |
|
563 MOZ_ASSERT(aEffectChain.mPrimaryEffect->mType == EFFECT_RGB); |
|
564 maskType = Mask3d; |
|
565 } |
|
566 |
|
567 EffectMask* maskEffect = |
|
568 static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EFFECT_MASK].get()); |
|
569 TextureSourceD3D11* source = maskEffect->mMaskTexture->AsSourceD3D11(); |
|
570 |
|
571 if (!source) { |
|
572 NS_WARNING("Missing texture source!"); |
|
573 return; |
|
574 } |
|
575 |
|
576 RefPtr<ID3D11ShaderResourceView> view; |
|
577 mDevice->CreateShaderResourceView(source->GetD3D11Texture(), nullptr, byRef(view)); |
|
578 |
|
579 ID3D11ShaderResourceView* srView = view; |
|
580 mContext->PSSetShaderResources(3, 1, &srView); |
|
581 |
|
582 const gfx::Matrix4x4& maskTransform = maskEffect->mMaskTransform; |
|
583 NS_ASSERTION(maskTransform.Is2D(), "How did we end up with a 3D transform here?!"); |
|
584 Rect bounds = Rect(Point(), Size(maskEffect->mSize)); |
|
585 |
|
586 mVSConstants.maskQuad = maskTransform.As2D().TransformBounds(bounds); |
|
587 } |
|
588 |
|
589 |
|
590 D3D11_RECT scissor; |
|
591 scissor.left = aClipRect.x; |
|
592 scissor.right = aClipRect.XMost(); |
|
593 scissor.top = aClipRect.y; |
|
594 scissor.bottom = aClipRect.YMost(); |
|
595 mContext->RSSetScissorRects(1, &scissor); |
|
596 mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); |
|
597 mContext->VSSetShader(mAttachments->mVSQuadShader[maskType], nullptr, 0); |
|
598 |
|
599 |
|
600 switch (aEffectChain.mPrimaryEffect->mType) { |
|
601 case EFFECT_SOLID_COLOR: { |
|
602 SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, SurfaceFormat::UNKNOWN); |
|
603 |
|
604 Color color = |
|
605 static_cast<EffectSolidColor*>(aEffectChain.mPrimaryEffect.get())->mColor; |
|
606 mPSConstants.layerColor[0] = color.r * color.a * aOpacity; |
|
607 mPSConstants.layerColor[1] = color.g * color.a * aOpacity; |
|
608 mPSConstants.layerColor[2] = color.b * color.a * aOpacity; |
|
609 mPSConstants.layerColor[3] = color.a * aOpacity; |
|
610 } |
|
611 break; |
|
612 case EFFECT_RGB: |
|
613 case EFFECT_RENDER_TARGET: |
|
614 { |
|
615 TexturedEffect* texturedEffect = |
|
616 static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get()); |
|
617 |
|
618 mVSConstants.textureCoords = texturedEffect->mTextureCoords; |
|
619 |
|
620 TextureSourceD3D11* source = texturedEffect->mTexture->AsSourceD3D11(); |
|
621 |
|
622 if (!source) { |
|
623 NS_WARNING("Missing texture source!"); |
|
624 return; |
|
625 } |
|
626 |
|
627 SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, texturedEffect->mTexture->GetFormat()); |
|
628 |
|
629 RefPtr<ID3D11ShaderResourceView> view; |
|
630 mDevice->CreateShaderResourceView(source->GetD3D11Texture(), nullptr, byRef(view)); |
|
631 |
|
632 ID3D11ShaderResourceView* srView = view; |
|
633 mContext->PSSetShaderResources(0, 1, &srView); |
|
634 |
|
635 if (!texturedEffect->mPremultiplied) { |
|
636 mContext->OMSetBlendState(mAttachments->mNonPremulBlendState, sBlendFactor, 0xFFFFFFFF); |
|
637 restoreBlendMode = true; |
|
638 } |
|
639 |
|
640 SetSamplerForFilter(texturedEffect->mFilter); |
|
641 } |
|
642 break; |
|
643 case EFFECT_YCBCR: { |
|
644 EffectYCbCr* ycbcrEffect = |
|
645 static_cast<EffectYCbCr*>(aEffectChain.mPrimaryEffect.get()); |
|
646 |
|
647 SetSamplerForFilter(Filter::LINEAR); |
|
648 |
|
649 mVSConstants.textureCoords = ycbcrEffect->mTextureCoords; |
|
650 |
|
651 const int Y = 0, Cb = 1, Cr = 2; |
|
652 TextureSource* source = ycbcrEffect->mTexture; |
|
653 |
|
654 if (!source) { |
|
655 NS_WARNING("No texture to composite"); |
|
656 return; |
|
657 } |
|
658 |
|
659 SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, ycbcrEffect->mTexture->GetFormat()); |
|
660 |
|
661 if (!source->GetSubSource(Y) || !source->GetSubSource(Cb) || !source->GetSubSource(Cr)) { |
|
662 // This can happen if we failed to upload the textures, most likely |
|
663 // because of unsupported dimensions (we don't tile YCbCr textures). |
|
664 return; |
|
665 } |
|
666 |
|
667 TextureSourceD3D11* sourceY = source->GetSubSource(Y)->AsSourceD3D11(); |
|
668 TextureSourceD3D11* sourceCb = source->GetSubSource(Cb)->AsSourceD3D11(); |
|
669 TextureSourceD3D11* sourceCr = source->GetSubSource(Cr)->AsSourceD3D11(); |
|
670 |
|
671 RefPtr<ID3D11ShaderResourceView> views[3]; |
|
672 mDevice->CreateShaderResourceView(sourceY->GetD3D11Texture(), |
|
673 nullptr, byRef(views[0])); |
|
674 mDevice->CreateShaderResourceView(sourceCb->GetD3D11Texture(), |
|
675 nullptr, byRef(views[1])); |
|
676 mDevice->CreateShaderResourceView(sourceCr->GetD3D11Texture(), |
|
677 nullptr, byRef(views[2])); |
|
678 |
|
679 ID3D11ShaderResourceView* srViews[3] = { views[0], views[1], views[2] }; |
|
680 mContext->PSSetShaderResources(0, 3, srViews); |
|
681 } |
|
682 break; |
|
683 case EFFECT_COMPONENT_ALPHA: |
|
684 { |
|
685 MOZ_ASSERT(gfxPrefs::ComponentAlphaEnabled()); |
|
686 MOZ_ASSERT(mAttachments->mComponentBlendState); |
|
687 EffectComponentAlpha* effectComponentAlpha = |
|
688 static_cast<EffectComponentAlpha*>(aEffectChain.mPrimaryEffect.get()); |
|
689 |
|
690 TextureSourceD3D11* sourceOnWhite = effectComponentAlpha->mOnWhite->AsSourceD3D11(); |
|
691 TextureSourceD3D11* sourceOnBlack = effectComponentAlpha->mOnBlack->AsSourceD3D11(); |
|
692 |
|
693 if (!sourceOnWhite || !sourceOnBlack) { |
|
694 NS_WARNING("Missing texture source(s)!"); |
|
695 return; |
|
696 } |
|
697 |
|
698 SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, effectComponentAlpha->mOnWhite->GetFormat()); |
|
699 |
|
700 SetSamplerForFilter(effectComponentAlpha->mFilter); |
|
701 |
|
702 mVSConstants.textureCoords = effectComponentAlpha->mTextureCoords; |
|
703 RefPtr<ID3D11ShaderResourceView> views[2]; |
|
704 mDevice->CreateShaderResourceView(sourceOnBlack->GetD3D11Texture(), nullptr, byRef(views[0])); |
|
705 mDevice->CreateShaderResourceView(sourceOnWhite->GetD3D11Texture(), nullptr, byRef(views[1])); |
|
706 |
|
707 ID3D11ShaderResourceView* srViews[2] = { views[0], views[1] }; |
|
708 mContext->PSSetShaderResources(0, 2, srViews); |
|
709 |
|
710 mContext->OMSetBlendState(mAttachments->mComponentBlendState, sBlendFactor, 0xFFFFFFFF); |
|
711 restoreBlendMode = true; |
|
712 } |
|
713 break; |
|
714 default: |
|
715 NS_WARNING("Unknown shader type"); |
|
716 return; |
|
717 } |
|
718 UpdateConstantBuffers(); |
|
719 |
|
720 mContext->Draw(4, 0); |
|
721 if (restoreBlendMode) { |
|
722 mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF); |
|
723 } |
|
724 } |
|
725 |
|
726 void |
|
727 CompositorD3D11::BeginFrame(const nsIntRegion& aInvalidRegion, |
|
728 const Rect* aClipRectIn, |
|
729 const gfx::Matrix& aTransform, |
|
730 const Rect& aRenderBounds, |
|
731 Rect* aClipRectOut, |
|
732 Rect* aRenderBoundsOut) |
|
733 { |
|
734 // Don't composite if we are minimised. Other than for the sake of efficency, |
|
735 // this is important because resizing our buffers when mimised will fail and |
|
736 // cause a crash when we're restored. |
|
737 NS_ASSERTION(mHwnd, "Couldn't find an HWND when initialising?"); |
|
738 if (::IsIconic(mHwnd)) { |
|
739 *aRenderBoundsOut = Rect(); |
|
740 return; |
|
741 } |
|
742 |
|
743 UpdateRenderTarget(); |
|
744 |
|
745 // Failed to create a render target or the view. |
|
746 if (!mDefaultRT || !mDefaultRT->mRTView || |
|
747 mSize.width == 0 || mSize.height == 0) { |
|
748 *aRenderBoundsOut = Rect(); |
|
749 return; |
|
750 } |
|
751 |
|
752 mContext->IASetInputLayout(mAttachments->mInputLayout); |
|
753 |
|
754 ID3D11Buffer* buffer = mAttachments->mVertexBuffer; |
|
755 UINT size = sizeof(Vertex); |
|
756 UINT offset = 0; |
|
757 mContext->IASetVertexBuffers(0, 1, &buffer, &size, &offset); |
|
758 |
|
759 if (aClipRectOut) { |
|
760 *aClipRectOut = Rect(0, 0, mSize.width, mSize.height); |
|
761 } |
|
762 if (aRenderBoundsOut) { |
|
763 *aRenderBoundsOut = Rect(0, 0, mSize.width, mSize.height); |
|
764 } |
|
765 |
|
766 D3D11_RECT scissor; |
|
767 if (aClipRectIn) { |
|
768 scissor.left = aClipRectIn->x; |
|
769 scissor.right = aClipRectIn->XMost(); |
|
770 scissor.top = aClipRectIn->y; |
|
771 scissor.bottom = aClipRectIn->YMost(); |
|
772 } else { |
|
773 scissor.left = scissor.top = 0; |
|
774 scissor.right = mSize.width; |
|
775 scissor.bottom = mSize.height; |
|
776 } |
|
777 mContext->RSSetScissorRects(1, &scissor); |
|
778 |
|
779 FLOAT black[] = { 0, 0, 0, 0 }; |
|
780 mContext->ClearRenderTargetView(mDefaultRT->mRTView, black); |
|
781 |
|
782 mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF); |
|
783 mContext->RSSetState(mAttachments->mRasterizerState); |
|
784 |
|
785 SetRenderTarget(mDefaultRT); |
|
786 } |
|
787 |
|
788 void |
|
789 CompositorD3D11::EndFrame() |
|
790 { |
|
791 mContext->Flush(); |
|
792 |
|
793 nsIntSize oldSize = mSize; |
|
794 EnsureSize(); |
|
795 if (oldSize == mSize) { |
|
796 mSwapChain->Present(0, mDisableSequenceForNextFrame ? DXGI_PRESENT_DO_NOT_SEQUENCE : 0); |
|
797 mDisableSequenceForNextFrame = false; |
|
798 if (mTarget) { |
|
799 PaintToTarget(); |
|
800 } |
|
801 } |
|
802 |
|
803 mCurrentRT = nullptr; |
|
804 } |
|
805 |
|
806 void |
|
807 CompositorD3D11::PrepareViewport(const gfx::IntSize& aSize, |
|
808 const gfx::Matrix& aWorldTransform) |
|
809 { |
|
810 D3D11_VIEWPORT viewport; |
|
811 viewport.MaxDepth = 1.0f; |
|
812 viewport.MinDepth = 0; |
|
813 viewport.Width = aSize.width; |
|
814 viewport.Height = aSize.height; |
|
815 viewport.TopLeftX = 0; |
|
816 viewport.TopLeftY = 0; |
|
817 |
|
818 mContext->RSSetViewports(1, &viewport); |
|
819 |
|
820 Matrix viewMatrix; |
|
821 viewMatrix.Translate(-1.0, 1.0); |
|
822 viewMatrix.Scale(2.0f / float(aSize.width), 2.0f / float(aSize.height)); |
|
823 viewMatrix.Scale(1.0f, -1.0f); |
|
824 |
|
825 viewMatrix = aWorldTransform * viewMatrix; |
|
826 |
|
827 Matrix4x4 projection = Matrix4x4::From2D(viewMatrix); |
|
828 projection._33 = 0.0f; |
|
829 |
|
830 memcpy(&mVSConstants.projection, &projection, sizeof(mVSConstants.projection)); |
|
831 } |
|
832 |
|
833 void |
|
834 CompositorD3D11::EnsureSize() |
|
835 { |
|
836 nsIntRect rect; |
|
837 mWidget->GetClientBounds(rect); |
|
838 |
|
839 mSize = rect.Size(); |
|
840 } |
|
841 |
|
842 void |
|
843 CompositorD3D11::VerifyBufferSize() |
|
844 { |
|
845 DXGI_SWAP_CHAIN_DESC swapDesc; |
|
846 mSwapChain->GetDesc(&swapDesc); |
|
847 |
|
848 if ((swapDesc.BufferDesc.Width == mSize.width && |
|
849 swapDesc.BufferDesc.Height == mSize.height) || |
|
850 mSize.width == 0 || mSize.height == 0) { |
|
851 return; |
|
852 } |
|
853 |
|
854 mDefaultRT = nullptr; |
|
855 |
|
856 if (IsRunningInWindowsMetro()) { |
|
857 mSwapChain->ResizeBuffers(2, mSize.width, mSize.height, |
|
858 DXGI_FORMAT_B8G8R8A8_UNORM, |
|
859 0); |
|
860 mDisableSequenceForNextFrame = true; |
|
861 } else if (gfxWindowsPlatform::IsOptimus()) { |
|
862 mSwapChain->ResizeBuffers(1, mSize.width, mSize.height, |
|
863 DXGI_FORMAT_B8G8R8A8_UNORM, |
|
864 0); |
|
865 } else { |
|
866 mSwapChain->ResizeBuffers(1, mSize.width, mSize.height, |
|
867 DXGI_FORMAT_B8G8R8A8_UNORM, |
|
868 DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE); |
|
869 } |
|
870 } |
|
871 |
|
872 void |
|
873 CompositorD3D11::UpdateRenderTarget() |
|
874 { |
|
875 EnsureSize(); |
|
876 VerifyBufferSize(); |
|
877 |
|
878 if (mDefaultRT) { |
|
879 return; |
|
880 } |
|
881 |
|
882 HRESULT hr; |
|
883 |
|
884 nsRefPtr<ID3D11Texture2D> backBuf; |
|
885 |
|
886 hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)backBuf.StartAssignment()); |
|
887 if (FAILED(hr)) { |
|
888 return; |
|
889 } |
|
890 |
|
891 mDefaultRT = new CompositingRenderTargetD3D11(backBuf, IntPoint(0, 0)); |
|
892 mDefaultRT->SetSize(mSize.ToIntSize()); |
|
893 } |
|
894 |
|
895 bool |
|
896 CompositorD3D11::CreateShaders() |
|
897 { |
|
898 HRESULT hr; |
|
899 |
|
900 hr = mDevice->CreateVertexShader(LayerQuadVS, |
|
901 sizeof(LayerQuadVS), |
|
902 nullptr, |
|
903 byRef(mAttachments->mVSQuadShader[MaskNone])); |
|
904 if (FAILED(hr)) { |
|
905 return false; |
|
906 } |
|
907 |
|
908 hr = mDevice->CreateVertexShader(LayerQuadMaskVS, |
|
909 sizeof(LayerQuadMaskVS), |
|
910 nullptr, |
|
911 byRef(mAttachments->mVSQuadShader[Mask2d])); |
|
912 if (FAILED(hr)) { |
|
913 return false; |
|
914 } |
|
915 |
|
916 hr = mDevice->CreateVertexShader(LayerQuadMask3DVS, |
|
917 sizeof(LayerQuadMask3DVS), |
|
918 nullptr, |
|
919 byRef(mAttachments->mVSQuadShader[Mask3d])); |
|
920 if (FAILED(hr)) { |
|
921 return false; |
|
922 } |
|
923 |
|
924 #define LOAD_PIXEL_SHADER(x) hr = mDevice->CreatePixelShader(x, sizeof(x), nullptr, byRef(mAttachments->m##x[MaskNone])); \ |
|
925 if (FAILED(hr)) { \ |
|
926 return false; \ |
|
927 } \ |
|
928 hr = mDevice->CreatePixelShader(x##Mask, sizeof(x##Mask), nullptr, byRef(mAttachments->m##x[Mask2d])); \ |
|
929 if (FAILED(hr)) { \ |
|
930 return false; \ |
|
931 } |
|
932 |
|
933 LOAD_PIXEL_SHADER(SolidColorShader); |
|
934 LOAD_PIXEL_SHADER(RGBShader); |
|
935 LOAD_PIXEL_SHADER(RGBAShader); |
|
936 LOAD_PIXEL_SHADER(YCbCrShader); |
|
937 if (gfxPrefs::ComponentAlphaEnabled()) { |
|
938 LOAD_PIXEL_SHADER(ComponentAlphaShader); |
|
939 } |
|
940 |
|
941 #undef LOAD_PIXEL_SHADER |
|
942 |
|
943 hr = mDevice->CreatePixelShader(RGBAShaderMask3D, |
|
944 sizeof(RGBAShaderMask3D), |
|
945 nullptr, |
|
946 byRef(mAttachments->mRGBAShader[Mask3d])); |
|
947 if (FAILED(hr)) { |
|
948 return false; |
|
949 } |
|
950 |
|
951 return true; |
|
952 } |
|
953 |
|
954 void |
|
955 CompositorD3D11::UpdateConstantBuffers() |
|
956 { |
|
957 D3D11_MAPPED_SUBRESOURCE resource; |
|
958 mContext->Map(mAttachments->mVSConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource); |
|
959 *(VertexShaderConstants*)resource.pData = mVSConstants; |
|
960 mContext->Unmap(mAttachments->mVSConstantBuffer, 0); |
|
961 mContext->Map(mAttachments->mPSConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource); |
|
962 *(PixelShaderConstants*)resource.pData = mPSConstants; |
|
963 mContext->Unmap(mAttachments->mPSConstantBuffer, 0); |
|
964 |
|
965 ID3D11Buffer *buffer = mAttachments->mVSConstantBuffer; |
|
966 |
|
967 mContext->VSSetConstantBuffers(0, 1, &buffer); |
|
968 |
|
969 buffer = mAttachments->mPSConstantBuffer; |
|
970 mContext->PSSetConstantBuffers(0, 1, &buffer); |
|
971 } |
|
972 |
|
973 void |
|
974 CompositorD3D11::SetSamplerForFilter(Filter aFilter) |
|
975 { |
|
976 ID3D11SamplerState *sampler; |
|
977 switch (aFilter) { |
|
978 default: |
|
979 case Filter::LINEAR: |
|
980 sampler = mAttachments->mLinearSamplerState; |
|
981 break; |
|
982 case Filter::POINT: |
|
983 sampler = mAttachments->mPointSamplerState; |
|
984 break; |
|
985 } |
|
986 |
|
987 mContext->PSSetSamplers(0, 1, &sampler); |
|
988 } |
|
989 |
|
990 void |
|
991 CompositorD3D11::PaintToTarget() |
|
992 { |
|
993 nsRefPtr<ID3D11Texture2D> backBuf; |
|
994 |
|
995 mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)backBuf.StartAssignment()); |
|
996 |
|
997 D3D11_TEXTURE2D_DESC bbDesc; |
|
998 backBuf->GetDesc(&bbDesc); |
|
999 |
|
1000 CD3D11_TEXTURE2D_DESC softDesc(bbDesc.Format, bbDesc.Width, bbDesc.Height); |
|
1001 softDesc.MipLevels = 1; |
|
1002 softDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; |
|
1003 softDesc.Usage = D3D11_USAGE_STAGING; |
|
1004 softDesc.BindFlags = 0; |
|
1005 |
|
1006 nsRefPtr<ID3D11Texture2D> readTexture; |
|
1007 |
|
1008 HRESULT hr = mDevice->CreateTexture2D(&softDesc, nullptr, getter_AddRefs(readTexture)); |
|
1009 mContext->CopyResource(readTexture, backBuf); |
|
1010 |
|
1011 D3D11_MAPPED_SUBRESOURCE map; |
|
1012 mContext->Map(readTexture, 0, D3D11_MAP_READ, 0, &map); |
|
1013 RefPtr<DataSourceSurface> sourceSurface = |
|
1014 Factory::CreateWrappingDataSourceSurface((uint8_t*)map.pData, |
|
1015 map.RowPitch, |
|
1016 IntSize(bbDesc.Width, bbDesc.Height), |
|
1017 SurfaceFormat::B8G8R8A8); |
|
1018 mTarget->CopySurface(sourceSurface, |
|
1019 IntRect(0, 0, bbDesc.Width, bbDesc.Height), |
|
1020 IntPoint()); |
|
1021 mTarget->Flush(); |
|
1022 mContext->Unmap(readTexture, 0); |
|
1023 } |
|
1024 |
|
1025 } |
|
1026 } |