Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
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/. */
6 #include "CompositorD3D11.h"
8 #include "TextureD3D11.h"
9 #include "CompositorD3D11Shaders.h"
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"
19 #ifdef MOZ_METRO
20 #include <DXGI1_2.h>
21 #endif
23 namespace mozilla {
25 using namespace gfx;
27 namespace layers {
29 struct Vertex
30 {
31 float position[2];
32 };
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 } };
41 const FLOAT sBlendFactor[] = { 0, 0, 0, 0 };
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 };
64 CompositorD3D11::CompositorD3D11(nsIWidget* aWidget)
65 : mAttachments(nullptr)
66 , mWidget(aWidget)
67 , mHwnd(nullptr)
68 , mDisableSequenceForNextFrame(false)
69 {
70 SetBackend(LayersBackend::LAYERS_D3D11);
71 }
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);
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);
93 delete attachments;
94 }
95 }
96 }
98 bool
99 CompositorD3D11::Initialize()
100 {
101 HRESULT hr;
103 mDevice = gfxWindowsPlatform::GetPlatform()->GetD3D11Device();
105 if (!mDevice) {
106 return false;
107 }
109 mDevice->GetImmediateContext(byRef(mContext));
111 if (!mContext) {
112 return false;
113 }
115 mHwnd = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
117 memset(&mVSConstants, 0, sizeof(VertexShaderConstants));
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);
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);
137 D3D11_INPUT_ELEMENT_DESC layout[] =
138 {
139 { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
140 };
142 hr = mDevice->CreateInputLayout(layout,
143 sizeof(layout) / sizeof(D3D11_INPUT_ELEMENT_DESC),
144 LayerQuadVS,
145 sizeof(LayerQuadVS),
146 byRef(mAttachments->mInputLayout));
148 if (FAILED(hr)) {
149 return false;
150 }
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;
157 hr = mDevice->CreateBuffer(&bufferDesc, &data, byRef(mAttachments->mVertexBuffer));
159 if (FAILED(hr)) {
160 return false;
161 }
163 if (!CreateShaders()) {
164 return false;
165 }
167 CD3D11_BUFFER_DESC cBufferDesc(sizeof(VertexShaderConstants),
168 D3D11_BIND_CONSTANT_BUFFER,
169 D3D11_USAGE_DYNAMIC,
170 D3D11_CPU_ACCESS_WRITE);
172 hr = mDevice->CreateBuffer(&cBufferDesc, nullptr, byRef(mAttachments->mVSConstantBuffer));
173 if (FAILED(hr)) {
174 return false;
175 }
177 cBufferDesc.ByteWidth = sizeof(PixelShaderConstants);
178 hr = mDevice->CreateBuffer(&cBufferDesc, nullptr, byRef(mAttachments->mPSConstantBuffer));
179 if (FAILED(hr)) {
180 return false;
181 }
183 CD3D11_RASTERIZER_DESC rastDesc(D3D11_DEFAULT);
184 rastDesc.CullMode = D3D11_CULL_NONE;
185 rastDesc.ScissorEnable = TRUE;
187 hr = mDevice->CreateRasterizerState(&rastDesc, byRef(mAttachments->mRasterizerState));
188 if (FAILED(hr)) {
189 return false;
190 }
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 }
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 }
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 }
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 }
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 }
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 }
261 nsRefPtr<IDXGIDevice> dxgiDevice;
262 nsRefPtr<IDXGIAdapter> dxgiAdapter;
264 mDevice->QueryInterface(dxgiDevice.StartAssignment());
265 dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter));
267 #ifdef MOZ_METRO
268 if (IsRunningInWindowsMetro()) {
269 nsRefPtr<IDXGIFactory2> dxgiFactory;
270 dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment()));
272 nsIntRect rect;
273 mWidget->GetClientBounds(rect);
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;
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()));
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 }
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 }
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 }
352 return true;
353 }
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 }
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 }
373 bool
374 CompositorD3D11::CanUseCanvasLayerForSize(const gfx::IntSize& aSize)
375 {
376 int32_t maxTextureSize = GetMaxTextureSize();
378 if (aSize.width > maxTextureSize || aSize.height > maxTextureSize) {
379 return false;
380 }
382 return true;
383 }
385 int32_t
386 CompositorD3D11::GetMaxTextureSize() const
387 {
388 return GetMaxTextureSizeForFeatureLevel(mFeatureLevel);
389 }
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);
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 }
405 RefPtr<CompositingRenderTargetD3D11> rt = new CompositingRenderTargetD3D11(texture, aRect.TopLeft());
406 rt->SetSize(IntSize(aRect.width, aRect.height));
408 if (aInit == INIT_MODE_CLEAR) {
409 FLOAT clear[] = { 0, 0, 0, 0 };
410 mContext->ClearRenderTargetView(rt->mRTView, clear);
411 }
413 return rt;
414 }
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);
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 }
432 if (aSource) {
433 const CompositingRenderTargetD3D11* sourceD3D11 =
434 static_cast<const CompositingRenderTargetD3D11*>(aSource);
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;
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 }
458 RefPtr<CompositingRenderTargetD3D11> rt =
459 new CompositingRenderTargetD3D11(texture, aRect.TopLeft());
460 rt->SetSize(aRect.Size());
462 return rt;
463 }
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 }
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 }
504 void
505 CompositorD3D11::ClearRect(const gfx::Rect& aRect)
506 {
507 mContext->OMSetBlendState(mAttachments->mDisabledBlendState, sBlendFactor, 0xFFFFFFFF);
509 Matrix4x4 identity;
510 memcpy(&mVSConstants.layerTransform, &identity._11, 64);
512 mVSConstants.layerQuad = aRect;
513 mVSConstants.renderTargetOffset[0] = 0;
514 mVSConstants.renderTargetOffset[1] = 0;
515 mPSConstants.layerOpacity[0] = 1.0f;
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);
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;
532 UpdateConstantBuffers();
534 mContext->Draw(4, 0);
536 mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
537 }
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;
553 mPSConstants.layerOpacity[0] = aOpacity;
555 bool restoreBlendMode = false;
557 MaskType maskType = MaskNone;
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 }
567 EffectMask* maskEffect =
568 static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EFFECT_MASK].get());
569 TextureSourceD3D11* source = maskEffect->mMaskTexture->AsSourceD3D11();
571 if (!source) {
572 NS_WARNING("Missing texture source!");
573 return;
574 }
576 RefPtr<ID3D11ShaderResourceView> view;
577 mDevice->CreateShaderResourceView(source->GetD3D11Texture(), nullptr, byRef(view));
579 ID3D11ShaderResourceView* srView = view;
580 mContext->PSSetShaderResources(3, 1, &srView);
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));
586 mVSConstants.maskQuad = maskTransform.As2D().TransformBounds(bounds);
587 }
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);
600 switch (aEffectChain.mPrimaryEffect->mType) {
601 case EFFECT_SOLID_COLOR: {
602 SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, SurfaceFormat::UNKNOWN);
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());
618 mVSConstants.textureCoords = texturedEffect->mTextureCoords;
620 TextureSourceD3D11* source = texturedEffect->mTexture->AsSourceD3D11();
622 if (!source) {
623 NS_WARNING("Missing texture source!");
624 return;
625 }
627 SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, texturedEffect->mTexture->GetFormat());
629 RefPtr<ID3D11ShaderResourceView> view;
630 mDevice->CreateShaderResourceView(source->GetD3D11Texture(), nullptr, byRef(view));
632 ID3D11ShaderResourceView* srView = view;
633 mContext->PSSetShaderResources(0, 1, &srView);
635 if (!texturedEffect->mPremultiplied) {
636 mContext->OMSetBlendState(mAttachments->mNonPremulBlendState, sBlendFactor, 0xFFFFFFFF);
637 restoreBlendMode = true;
638 }
640 SetSamplerForFilter(texturedEffect->mFilter);
641 }
642 break;
643 case EFFECT_YCBCR: {
644 EffectYCbCr* ycbcrEffect =
645 static_cast<EffectYCbCr*>(aEffectChain.mPrimaryEffect.get());
647 SetSamplerForFilter(Filter::LINEAR);
649 mVSConstants.textureCoords = ycbcrEffect->mTextureCoords;
651 const int Y = 0, Cb = 1, Cr = 2;
652 TextureSource* source = ycbcrEffect->mTexture;
654 if (!source) {
655 NS_WARNING("No texture to composite");
656 return;
657 }
659 SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, ycbcrEffect->mTexture->GetFormat());
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 }
667 TextureSourceD3D11* sourceY = source->GetSubSource(Y)->AsSourceD3D11();
668 TextureSourceD3D11* sourceCb = source->GetSubSource(Cb)->AsSourceD3D11();
669 TextureSourceD3D11* sourceCr = source->GetSubSource(Cr)->AsSourceD3D11();
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]));
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());
690 TextureSourceD3D11* sourceOnWhite = effectComponentAlpha->mOnWhite->AsSourceD3D11();
691 TextureSourceD3D11* sourceOnBlack = effectComponentAlpha->mOnBlack->AsSourceD3D11();
693 if (!sourceOnWhite || !sourceOnBlack) {
694 NS_WARNING("Missing texture source(s)!");
695 return;
696 }
698 SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, effectComponentAlpha->mOnWhite->GetFormat());
700 SetSamplerForFilter(effectComponentAlpha->mFilter);
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]));
707 ID3D11ShaderResourceView* srViews[2] = { views[0], views[1] };
708 mContext->PSSetShaderResources(0, 2, srViews);
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();
720 mContext->Draw(4, 0);
721 if (restoreBlendMode) {
722 mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
723 }
724 }
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 }
743 UpdateRenderTarget();
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 }
752 mContext->IASetInputLayout(mAttachments->mInputLayout);
754 ID3D11Buffer* buffer = mAttachments->mVertexBuffer;
755 UINT size = sizeof(Vertex);
756 UINT offset = 0;
757 mContext->IASetVertexBuffers(0, 1, &buffer, &size, &offset);
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 }
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);
779 FLOAT black[] = { 0, 0, 0, 0 };
780 mContext->ClearRenderTargetView(mDefaultRT->mRTView, black);
782 mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
783 mContext->RSSetState(mAttachments->mRasterizerState);
785 SetRenderTarget(mDefaultRT);
786 }
788 void
789 CompositorD3D11::EndFrame()
790 {
791 mContext->Flush();
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 }
803 mCurrentRT = nullptr;
804 }
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;
818 mContext->RSSetViewports(1, &viewport);
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);
825 viewMatrix = aWorldTransform * viewMatrix;
827 Matrix4x4 projection = Matrix4x4::From2D(viewMatrix);
828 projection._33 = 0.0f;
830 memcpy(&mVSConstants.projection, &projection, sizeof(mVSConstants.projection));
831 }
833 void
834 CompositorD3D11::EnsureSize()
835 {
836 nsIntRect rect;
837 mWidget->GetClientBounds(rect);
839 mSize = rect.Size();
840 }
842 void
843 CompositorD3D11::VerifyBufferSize()
844 {
845 DXGI_SWAP_CHAIN_DESC swapDesc;
846 mSwapChain->GetDesc(&swapDesc);
848 if ((swapDesc.BufferDesc.Width == mSize.width &&
849 swapDesc.BufferDesc.Height == mSize.height) ||
850 mSize.width == 0 || mSize.height == 0) {
851 return;
852 }
854 mDefaultRT = nullptr;
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 }
872 void
873 CompositorD3D11::UpdateRenderTarget()
874 {
875 EnsureSize();
876 VerifyBufferSize();
878 if (mDefaultRT) {
879 return;
880 }
882 HRESULT hr;
884 nsRefPtr<ID3D11Texture2D> backBuf;
886 hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)backBuf.StartAssignment());
887 if (FAILED(hr)) {
888 return;
889 }
891 mDefaultRT = new CompositingRenderTargetD3D11(backBuf, IntPoint(0, 0));
892 mDefaultRT->SetSize(mSize.ToIntSize());
893 }
895 bool
896 CompositorD3D11::CreateShaders()
897 {
898 HRESULT hr;
900 hr = mDevice->CreateVertexShader(LayerQuadVS,
901 sizeof(LayerQuadVS),
902 nullptr,
903 byRef(mAttachments->mVSQuadShader[MaskNone]));
904 if (FAILED(hr)) {
905 return false;
906 }
908 hr = mDevice->CreateVertexShader(LayerQuadMaskVS,
909 sizeof(LayerQuadMaskVS),
910 nullptr,
911 byRef(mAttachments->mVSQuadShader[Mask2d]));
912 if (FAILED(hr)) {
913 return false;
914 }
916 hr = mDevice->CreateVertexShader(LayerQuadMask3DVS,
917 sizeof(LayerQuadMask3DVS),
918 nullptr,
919 byRef(mAttachments->mVSQuadShader[Mask3d]));
920 if (FAILED(hr)) {
921 return false;
922 }
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 }
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 }
941 #undef LOAD_PIXEL_SHADER
943 hr = mDevice->CreatePixelShader(RGBAShaderMask3D,
944 sizeof(RGBAShaderMask3D),
945 nullptr,
946 byRef(mAttachments->mRGBAShader[Mask3d]));
947 if (FAILED(hr)) {
948 return false;
949 }
951 return true;
952 }
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);
965 ID3D11Buffer *buffer = mAttachments->mVSConstantBuffer;
967 mContext->VSSetConstantBuffers(0, 1, &buffer);
969 buffer = mAttachments->mPSConstantBuffer;
970 mContext->PSSetConstantBuffers(0, 1, &buffer);
971 }
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 }
987 mContext->PSSetSamplers(0, 1, &sampler);
988 }
990 void
991 CompositorD3D11::PaintToTarget()
992 {
993 nsRefPtr<ID3D11Texture2D> backBuf;
995 mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)backBuf.StartAssignment());
997 D3D11_TEXTURE2D_DESC bbDesc;
998 backBuf->GetDesc(&bbDesc);
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;
1006 nsRefPtr<ID3D11Texture2D> readTexture;
1008 HRESULT hr = mDevice->CreateTexture2D(&softDesc, nullptr, getter_AddRefs(readTexture));
1009 mContext->CopyResource(readTexture, backBuf);
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 }
1025 }
1026 }