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: 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 <algorithm>
8 #include "LayerManagerD3D10.h"
9 #include "LayerManagerD3D10Effect.h"
10 #include "gfxWindowsPlatform.h"
11 #include "gfx2DGlue.h"
12 #include "gfxD2DSurface.h"
13 #include "gfxFailure.h"
14 #include "cairo-win32.h"
15 #include "dxgi.h"
17 #include "ContainerLayerD3D10.h"
18 #include "ThebesLayerD3D10.h"
19 #include "ColorLayerD3D10.h"
20 #include "CanvasLayerD3D10.h"
21 #include "ReadbackLayerD3D10.h"
22 #include "ImageLayerD3D10.h"
23 #include "mozilla/layers/PLayerChild.h"
24 #include "mozilla/WidgetUtils.h"
26 #include "../d3d9/Nv3DVUtils.h"
28 #include "gfxCrashReporterUtils.h"
29 #include "nsWindowsHelpers.h"
30 #ifdef MOZ_METRO
31 #include "DXGI1_2.h"
32 #endif
34 using namespace std;
35 using namespace mozilla::dom;
36 using namespace mozilla::gfx;
38 namespace mozilla {
39 namespace layers {
41 struct Vertex
42 {
43 float position[2];
44 };
46 // {592BF306-0EED-4F76-9D03-A0846450F472}
47 static const GUID sDeviceAttachments =
48 { 0x592bf306, 0xeed, 0x4f76, { 0x9d, 0x3, 0xa0, 0x84, 0x64, 0x50, 0xf4, 0x72 } };
49 // {716AEDB1-C9C3-4B4D-8332-6F65D44AF6A8}
50 static const GUID sLayerManagerCount =
51 { 0x716aedb1, 0xc9c3, 0x4b4d, { 0x83, 0x32, 0x6f, 0x65, 0xd4, 0x4a, 0xf6, 0xa8 } };
53 LayerManagerD3D10::LayerManagerD3D10(nsIWidget *aWidget)
54 : mWidget(aWidget)
55 , mDisableSequenceForNextFrame(false)
56 {
57 }
59 struct DeviceAttachments
60 {
61 nsRefPtr<ID3D10Effect> mEffect;
62 nsRefPtr<ID3D10InputLayout> mInputLayout;
63 nsRefPtr<ID3D10Buffer> mVertexBuffer;
64 nsRefPtr<ReadbackManagerD3D10> mReadbackManager;
65 };
67 LayerManagerD3D10::~LayerManagerD3D10()
68 {
69 if (mDevice) {
70 int referenceCount = 0;
71 UINT size = sizeof(referenceCount);
72 HRESULT hr = mDevice->GetPrivateData(sLayerManagerCount, &size, &referenceCount);
73 NS_ASSERTION(SUCCEEDED(hr), "Reference count not found on device.");
74 referenceCount--;
75 mDevice->SetPrivateData(sLayerManagerCount, sizeof(referenceCount), &referenceCount);
77 if (!referenceCount) {
78 DeviceAttachments *attachments;
79 size = sizeof(attachments);
80 mDevice->GetPrivateData(sDeviceAttachments, &size, &attachments);
81 // No LayerManagers left for this device. Clear out interfaces stored which
82 // hold a reference to the device.
83 mDevice->SetPrivateData(sDeviceAttachments, 0, nullptr);
85 delete attachments;
86 }
87 }
89 Destroy();
90 }
92 static inline void
93 SetHRESULT(HRESULT* aHresultPtr, HRESULT aHresult)
94 {
95 if (aHresultPtr) {
96 *aHresultPtr = aHresult;
97 }
98 }
100 bool
101 LayerManagerD3D10::Initialize(bool force, HRESULT* aHresultPtr)
102 {
103 ScopedGfxFeatureReporter reporter("D3D10 Layers", force);
105 HRESULT hr = E_UNEXPECTED;
107 /* Create an Nv3DVUtils instance */
108 if (!mNv3DVUtils) {
109 mNv3DVUtils = new Nv3DVUtils();
110 if (!mNv3DVUtils) {
111 NS_WARNING("Could not create a new instance of Nv3DVUtils.\n");
112 }
113 }
115 /* Initialize the Nv3DVUtils object */
116 if (mNv3DVUtils) {
117 mNv3DVUtils->Initialize();
118 }
120 mDevice = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
121 if (!mDevice) {
122 SetHRESULT(aHresultPtr, hr);
123 return false;
124 }
126 /*
127 * Do some post device creation setup
128 */
129 if (mNv3DVUtils) {
130 IUnknown* devUnknown = nullptr;
131 if (mDevice) {
132 mDevice->QueryInterface(IID_IUnknown, (void **)&devUnknown);
133 }
134 mNv3DVUtils->SetDeviceInfo(devUnknown);
135 }
137 int referenceCount = 0;
138 UINT size = sizeof(referenceCount);
139 // If this isn't there yet it'll fail, count will remain 0, which is correct.
140 mDevice->GetPrivateData(sLayerManagerCount, &size, &referenceCount);
141 referenceCount++;
142 mDevice->SetPrivateData(sLayerManagerCount, sizeof(referenceCount), &referenceCount);
144 DeviceAttachments *attachments;
145 size = sizeof(DeviceAttachments*);
146 if (FAILED(mDevice->GetPrivateData(sDeviceAttachments, &size, &attachments))) {
147 attachments = new DeviceAttachments;
148 mDevice->SetPrivateData(sDeviceAttachments, sizeof(attachments), &attachments);
150 SetLastError(0);
151 decltype(D3D10CreateEffectFromMemory)* createEffect =
152 (decltype(D3D10CreateEffectFromMemory)*)
153 GetProcAddress(LoadLibraryA("d3d10_1.dll"), "D3D10CreateEffectFromMemory");
154 if (!createEffect) {
155 SetHRESULT(aHresultPtr, HRESULT_FROM_WIN32(GetLastError()));
156 return false;
157 }
159 hr = createEffect((void*)g_main,
160 sizeof(g_main),
161 D3D10_EFFECT_SINGLE_THREADED,
162 mDevice,
163 nullptr,
164 getter_AddRefs(mEffect));
166 if (FAILED(hr)) {
167 SetHRESULT(aHresultPtr, hr);
168 return false;
169 }
171 attachments->mEffect = mEffect;
173 D3D10_INPUT_ELEMENT_DESC layout[] =
174 {
175 { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
176 };
177 D3D10_PASS_DESC passDesc;
178 mEffect->GetTechniqueByName("RenderRGBLayerPremul")->GetPassByIndex(0)->
179 GetDesc(&passDesc);
181 hr = mDevice->CreateInputLayout(layout,
182 sizeof(layout) / sizeof(D3D10_INPUT_ELEMENT_DESC),
183 passDesc.pIAInputSignature,
184 passDesc.IAInputSignatureSize,
185 getter_AddRefs(mInputLayout));
187 if (FAILED(hr)) {
188 SetHRESULT(aHresultPtr, hr);
189 return false;
190 }
192 attachments->mInputLayout = mInputLayout;
194 Vertex vertices[] = { {0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0} };
195 CD3D10_BUFFER_DESC bufferDesc(sizeof(vertices), D3D10_BIND_VERTEX_BUFFER);
196 D3D10_SUBRESOURCE_DATA data;
197 data.pSysMem = (void*)vertices;
199 hr = mDevice->CreateBuffer(&bufferDesc, &data, getter_AddRefs(mVertexBuffer));
201 if (FAILED(hr)) {
202 SetHRESULT(aHresultPtr, hr);
203 return false;
204 }
206 attachments->mVertexBuffer = mVertexBuffer;
207 } else {
208 mEffect = attachments->mEffect;
209 mVertexBuffer = attachments->mVertexBuffer;
210 mInputLayout = attachments->mInputLayout;
211 }
213 nsRefPtr<IDXGIDevice> dxgiDevice;
214 nsRefPtr<IDXGIAdapter> dxgiAdapter;
216 mDevice->QueryInterface(dxgiDevice.StartAssignment());
217 dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter));
219 #ifdef MOZ_METRO
220 if (IsRunningInWindowsMetro()) {
221 nsRefPtr<IDXGIFactory2> dxgiFactory;
222 dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment()));
224 nsIntRect rect;
225 mWidget->GetClientBounds(rect);
227 DXGI_SWAP_CHAIN_DESC1 swapDesc = { 0 };
228 // Automatically detect the width and the height from the winrt CoreWindow
229 swapDesc.Width = rect.width;
230 swapDesc.Height = rect.height;
231 // This is the most common swapchain format
232 swapDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
233 swapDesc.Stereo = false;
234 // Don't use multi-sampling
235 swapDesc.SampleDesc.Count = 1;
236 swapDesc.SampleDesc.Quality = 0;
237 swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
238 // Use double buffering to enable flip
239 swapDesc.BufferCount = 2;
240 swapDesc.Scaling = DXGI_SCALING_NONE;
241 // All Metro style apps must use this SwapEffect
242 swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
243 swapDesc.Flags = 0;
245 /**
246 * Create a swap chain, this swap chain will contain the backbuffer for
247 * the window we draw to. The front buffer is the full screen front
248 * buffer.
249 */
250 nsRefPtr<IDXGISwapChain1> swapChain1;
251 hr = dxgiFactory->CreateSwapChainForCoreWindow(
252 dxgiDevice, (IUnknown *)mWidget->GetNativeData(NS_NATIVE_ICOREWINDOW),
253 &swapDesc, nullptr, getter_AddRefs(swapChain1));
254 if (FAILED(hr)) {
255 SetHRESULT(aHresultPtr, hr);
256 return false;
257 }
258 mSwapChain = swapChain1;
259 } else
260 #endif
261 {
262 nsRefPtr<IDXGIFactory> dxgiFactory;
263 dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment()));
265 DXGI_SWAP_CHAIN_DESC swapDesc;
266 ::ZeroMemory(&swapDesc, sizeof(swapDesc));
267 swapDesc.BufferDesc.Width = 0;
268 swapDesc.BufferDesc.Height = 0;
269 swapDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
270 swapDesc.BufferDesc.RefreshRate.Numerator = 60;
271 swapDesc.BufferDesc.RefreshRate.Denominator = 1;
272 swapDesc.SampleDesc.Count = 1;
273 swapDesc.SampleDesc.Quality = 0;
274 swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
275 swapDesc.BufferCount = 1;
276 swapDesc.OutputWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
277 swapDesc.Windowed = TRUE;
278 // We don't really need this flag, however it seems on some NVidia hardware
279 // smaller area windows do not present properly without this flag. This flag
280 // should have no negative consequences by itself. See bug 613790. This flag
281 // is broken on optimus devices. As a temporary solution we don't set it
282 // there, the only way of reliably detecting we're on optimus is looking for
283 // the DLL. See Bug 623807.
284 if (gfxWindowsPlatform::IsOptimus()) {
285 swapDesc.Flags = 0;
286 } else {
287 swapDesc.Flags = DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE;
288 }
290 /**
291 * Create a swap chain, this swap chain will contain the backbuffer for
292 * the window we draw to. The front buffer is the full screen front
293 * buffer.
294 */
295 hr = dxgiFactory->CreateSwapChain(dxgiDevice, &swapDesc, getter_AddRefs(mSwapChain));
296 if (FAILED(hr)) {
297 return false;
298 }
300 // We need this because we don't want DXGI to respond to Alt+Enter.
301 dxgiFactory->MakeWindowAssociation(swapDesc.OutputWindow, DXGI_MWA_NO_WINDOW_CHANGES);
302 }
304 reporter.SetSuccessful();
305 return true;
306 }
308 void
309 LayerManagerD3D10::Destroy()
310 {
311 if (!IsDestroyed()) {
312 if (mRoot) {
313 static_cast<LayerD3D10*>(mRoot->ImplData())->LayerManagerDestroyed();
314 }
315 // XXX need to be careful here about surface destruction
316 // racing with share-to-chrome message
317 }
318 LayerManager::Destroy();
319 }
321 void
322 LayerManagerD3D10::SetRoot(Layer *aRoot)
323 {
324 mRoot = aRoot;
325 }
327 void
328 LayerManagerD3D10::BeginTransaction()
329 {
330 mInTransaction = true;
332 #ifdef MOZ_LAYERS_HAVE_LOG
333 MOZ_LAYERS_LOG(("[----- BeginTransaction"));
334 Log();
335 #endif
336 }
338 void
339 LayerManagerD3D10::BeginTransactionWithTarget(gfxContext* aTarget)
340 {
341 mInTransaction = true;
342 mTarget = aTarget;
343 }
345 bool
346 LayerManagerD3D10::EndEmptyTransaction(EndTransactionFlags aFlags)
347 {
348 mInTransaction = false;
350 if (!mRoot)
351 return false;
353 EndTransaction(nullptr, nullptr, aFlags);
354 return true;
355 }
357 void
358 LayerManagerD3D10::EndTransaction(DrawThebesLayerCallback aCallback,
359 void* aCallbackData,
360 EndTransactionFlags aFlags)
361 {
362 mInTransaction = false;
364 if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
365 mCurrentCallbackInfo.Callback = aCallback;
366 mCurrentCallbackInfo.CallbackData = aCallbackData;
368 if (aFlags & END_NO_COMPOSITE) {
369 // Apply pending tree updates before recomputing effective
370 // properties.
371 mRoot->ApplyPendingUpdatesToSubtree();
372 }
374 // The results of our drawing always go directly into a pixel buffer,
375 // so we don't need to pass any global transform here.
376 mRoot->ComputeEffectiveTransforms(Matrix4x4());
378 #ifdef MOZ_LAYERS_HAVE_LOG
379 MOZ_LAYERS_LOG((" ----- (beginning paint)"));
380 Log();
381 #endif
383 Render(aFlags);
384 mCurrentCallbackInfo.Callback = nullptr;
385 mCurrentCallbackInfo.CallbackData = nullptr;
386 }
388 #ifdef MOZ_LAYERS_HAVE_LOG
389 Log();
390 MOZ_LAYERS_LOG(("]----- EndTransaction"));
391 #endif
393 mTarget = nullptr;
394 }
396 already_AddRefed<ThebesLayer>
397 LayerManagerD3D10::CreateThebesLayer()
398 {
399 nsRefPtr<ThebesLayer> layer = new ThebesLayerD3D10(this);
400 return layer.forget();
401 }
403 already_AddRefed<ContainerLayer>
404 LayerManagerD3D10::CreateContainerLayer()
405 {
406 nsRefPtr<ContainerLayer> layer = new ContainerLayerD3D10(this);
407 return layer.forget();
408 }
410 already_AddRefed<ImageLayer>
411 LayerManagerD3D10::CreateImageLayer()
412 {
413 nsRefPtr<ImageLayer> layer = new ImageLayerD3D10(this);
414 return layer.forget();
415 }
417 already_AddRefed<ColorLayer>
418 LayerManagerD3D10::CreateColorLayer()
419 {
420 nsRefPtr<ColorLayer> layer = new ColorLayerD3D10(this);
421 return layer.forget();
422 }
424 already_AddRefed<CanvasLayer>
425 LayerManagerD3D10::CreateCanvasLayer()
426 {
427 nsRefPtr<CanvasLayer> layer = new CanvasLayerD3D10(this);
428 return layer.forget();
429 }
431 already_AddRefed<ReadbackLayer>
432 LayerManagerD3D10::CreateReadbackLayer()
433 {
434 nsRefPtr<ReadbackLayer> layer = new ReadbackLayerD3D10(this);
435 return layer.forget();
436 }
438 static void ReleaseTexture(void *texture)
439 {
440 static_cast<ID3D10Texture2D*>(texture)->Release();
441 }
443 TemporaryRef<DrawTarget>
444 LayerManagerD3D10::CreateOptimalDrawTarget(const IntSize &aSize,
445 SurfaceFormat aFormat)
446 {
447 if ((aFormat != SurfaceFormat::B8G8R8X8 &&
448 aFormat != SurfaceFormat::B8G8R8A8)) {
449 return LayerManager::CreateOptimalDrawTarget(aSize, aFormat);
450 }
452 nsRefPtr<ID3D10Texture2D> texture;
454 CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
455 desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
456 desc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE;
458 HRESULT hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
460 if (FAILED(hr)) {
461 NS_WARNING("Failed to create new texture for CreateOptimalDrawTarget!");
462 return LayerManager::CreateOptimalDrawTarget(aSize, aFormat);
463 }
465 RefPtr<DrawTarget> dt =
466 Factory::CreateDrawTargetForD3D10Texture(texture, aFormat);
468 if (!dt) {
469 return LayerManager::CreateOptimalDrawTarget(aSize, aFormat);
470 }
472 return dt;
473 }
476 TemporaryRef<DrawTarget>
477 LayerManagerD3D10::CreateOptimalMaskDrawTarget(const IntSize &aSize)
478 {
479 return CreateOptimalDrawTarget(aSize, SurfaceFormat::B8G8R8A8);
480 }
483 TemporaryRef<DrawTarget>
484 LayerManagerD3D10::CreateDrawTarget(const IntSize &aSize,
485 SurfaceFormat aFormat)
486 {
487 if ((aFormat != SurfaceFormat::B8G8R8A8 &&
488 aFormat != SurfaceFormat::B8G8R8X8) ||
489 gfxPlatform::GetPlatform()->GetPreferredCanvasBackend() != BackendType::DIRECT2D) {
490 return LayerManager::CreateDrawTarget(aSize, aFormat);
491 }
493 nsRefPtr<ID3D10Texture2D> texture;
495 CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
496 desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
498 HRESULT hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
500 if (FAILED(hr)) {
501 NS_WARNING("Failed to create new texture for CreateOptimalDrawTarget!");
502 return LayerManager::CreateDrawTarget(aSize, aFormat);
503 }
505 RefPtr<DrawTarget> surface =
506 Factory::CreateDrawTargetForD3D10Texture(texture, aFormat);
508 if (!surface) {
509 return LayerManager::CreateDrawTarget(aSize, aFormat);
510 }
512 return surface;
513 }
515 ReadbackManagerD3D10*
516 LayerManagerD3D10::readbackManager()
517 {
518 EnsureReadbackManager();
519 return mReadbackManager;
520 }
522 void
523 LayerManagerD3D10::SetViewport(const nsIntSize &aViewport)
524 {
525 mViewport = aViewport;
527 D3D10_VIEWPORT viewport;
528 viewport.MaxDepth = 1.0f;
529 viewport.MinDepth = 0;
530 viewport.Width = aViewport.width;
531 viewport.Height = aViewport.height;
532 viewport.TopLeftX = 0;
533 viewport.TopLeftY = 0;
535 mDevice->RSSetViewports(1, &viewport);
537 gfx3DMatrix projection;
538 /*
539 * Matrix to transform to viewport space ( <-1.0, 1.0> topleft,
540 * <1.0, -1.0> bottomright)
541 */
542 projection._11 = 2.0f / aViewport.width;
543 projection._22 = -2.0f / aViewport.height;
544 projection._33 = 0.0f;
545 projection._41 = -1.0f;
546 projection._42 = 1.0f;
547 projection._44 = 1.0f;
549 HRESULT hr = mEffect->GetVariableByName("mProjection")->
550 SetRawValue(&projection._11, 0, 64);
552 if (FAILED(hr)) {
553 NS_WARNING("Failed to set projection matrix.");
554 }
555 }
557 void
558 LayerManagerD3D10::SetupInputAssembler()
559 {
560 mDevice->IASetInputLayout(mInputLayout);
562 UINT stride = sizeof(Vertex);
563 UINT offset = 0;
564 ID3D10Buffer *buffer = mVertexBuffer;
565 mDevice->IASetVertexBuffers(0, 1, &buffer, &stride, &offset);
566 mDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
567 }
569 void
570 LayerManagerD3D10::SetupPipeline()
571 {
572 VerifyBufferSize();
573 UpdateRenderTarget();
575 nsIntRect rect;
576 mWidget->GetClientBounds(rect);
578 HRESULT hr;
580 hr = mEffect->GetVariableByName("vTextureCoords")->AsVector()->
581 SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
583 if (FAILED(hr)) {
584 NS_WARNING("Failed to set Texture Coordinates.");
585 return;
586 }
588 ID3D10RenderTargetView *view = mRTView;
589 mDevice->OMSetRenderTargets(1, &view, nullptr);
591 SetupInputAssembler();
593 SetViewport(nsIntSize(rect.width, rect.height));
594 }
596 void
597 LayerManagerD3D10::UpdateRenderTarget()
598 {
599 if (mRTView || !mSwapChain) {
600 return;
601 }
603 HRESULT hr;
605 nsRefPtr<ID3D10Texture2D> backBuf;
606 hr = mSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (void**)backBuf.StartAssignment());
607 if (FAILED(hr)) {
608 return;
609 }
610 mDevice->CreateRenderTargetView(backBuf, nullptr, getter_AddRefs(mRTView));
611 }
613 void
614 LayerManagerD3D10::VerifyBufferSize()
615 {
616 nsIntRect rect;
617 mWidget->GetClientBounds(rect);
619 if (mSwapChain) {
620 DXGI_SWAP_CHAIN_DESC swapDesc;
621 mSwapChain->GetDesc(&swapDesc);
623 if (swapDesc.BufferDesc.Width == rect.width &&
624 swapDesc.BufferDesc.Height == rect.height) {
625 return;
626 }
628 mRTView = nullptr;
629 if (IsRunningInWindowsMetro()) {
630 mSwapChain->ResizeBuffers(2, rect.width, rect.height,
631 DXGI_FORMAT_B8G8R8A8_UNORM,
632 0);
633 mDisableSequenceForNextFrame = true;
634 } else if (gfxWindowsPlatform::IsOptimus()) {
635 mSwapChain->ResizeBuffers(1, rect.width, rect.height,
636 DXGI_FORMAT_B8G8R8A8_UNORM,
637 0);
638 } else {
639 mSwapChain->ResizeBuffers(1, rect.width, rect.height,
640 DXGI_FORMAT_B8G8R8A8_UNORM,
641 DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE);
642 }
643 }
644 }
646 void
647 LayerManagerD3D10::EnsureReadbackManager()
648 {
649 if (mReadbackManager) {
650 return;
651 }
653 DeviceAttachments *attachments;
654 UINT size = sizeof(DeviceAttachments*);
655 if (FAILED(mDevice->GetPrivateData(sDeviceAttachments, &size, &attachments))) {
656 // Strange! This shouldn't happen ... return a readback manager for this
657 // layer manager only.
658 mReadbackManager = new ReadbackManagerD3D10();
659 gfx::LogFailure(NS_LITERAL_CSTRING("Couldn't get device attachments for device."));
660 return;
661 }
663 if (attachments->mReadbackManager) {
664 mReadbackManager = attachments->mReadbackManager;
665 return;
666 }
668 mReadbackManager = new ReadbackManagerD3D10();
669 attachments->mReadbackManager = mReadbackManager;
670 }
672 void
673 LayerManagerD3D10::Render(EndTransactionFlags aFlags)
674 {
675 static_cast<LayerD3D10*>(mRoot->ImplData())->Validate();
677 if (aFlags & END_NO_COMPOSITE) {
678 return;
679 }
681 SetupPipeline();
683 float black[] = { 0, 0, 0, 0 };
684 device()->ClearRenderTargetView(mRTView, black);
686 nsIntRect rect;
687 mWidget->GetClientBounds(rect);
689 const nsIntRect *clipRect = mRoot->GetClipRect();
690 D3D10_RECT r;
691 if (clipRect) {
692 r.left = (LONG)clipRect->x;
693 r.top = (LONG)clipRect->y;
694 r.right = (LONG)(clipRect->x + clipRect->width);
695 r.bottom = (LONG)(clipRect->y + clipRect->height);
696 } else {
697 r.left = r.top = 0;
698 r.right = rect.width;
699 r.bottom = rect.height;
700 }
701 device()->RSSetScissorRects(1, &r);
703 static_cast<LayerD3D10*>(mRoot->ImplData())->RenderLayer();
705 if (!mRegionToClear.IsEmpty()) {
706 float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
707 gfx::Matrix4x4 transform;
708 effect()->GetVariableByName("mLayerTransform")->SetRawValue(&transform, 0, 64);
709 effect()->GetVariableByName("fLayerColor")->AsVector()->SetFloatVector(color);
711 ID3D10EffectTechnique *technique = effect()->GetTechniqueByName("RenderClearLayer");
713 nsIntRegionRectIterator iter(mRegionToClear);
714 const nsIntRect *r;
715 while ((r = iter.Next())) {
716 effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
717 ShaderConstantRectD3D10(
718 (float)r->x,
719 (float)r->y,
720 (float)r->width,
721 (float)r->height)
722 );
724 technique->GetPassByIndex(0)->Apply(0);
725 device()->Draw(4, 0);
726 }
727 }
729 // See bug 630197 - we have some reasons to believe if an earlier call
730 // returned an error, the upcoming present call may raise an exception.
731 // This will check if any of the calls done recently has returned an error
732 // and bails on composition. On the -next- frame we will then abandon
733 // hardware acceleration from gfxWindowsPlatform::VerifyD2DDevice.
734 // This might not be the 'optimal' solution but it will help us assert
735 // whether our thoughts of the causes of the issues are correct.
736 if (FAILED(mDevice->GetDeviceRemovedReason())) {
737 return;
738 }
740 if (mTarget) {
741 PaintToTarget();
742 } else {
743 mSwapChain->Present(0, mDisableSequenceForNextFrame ? DXGI_PRESENT_DO_NOT_SEQUENCE : 0);
744 mDisableSequenceForNextFrame = false;
745 }
746 RecordFrame();
747 PostPresent();
748 }
750 void
751 LayerManagerD3D10::PaintToTarget()
752 {
753 nsRefPtr<ID3D10Texture2D> backBuf;
755 mSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (void**)backBuf.StartAssignment());
757 D3D10_TEXTURE2D_DESC bbDesc;
758 backBuf->GetDesc(&bbDesc);
760 CD3D10_TEXTURE2D_DESC softDesc(bbDesc.Format, bbDesc.Width, bbDesc.Height);
761 softDesc.MipLevels = 1;
762 softDesc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
763 softDesc.Usage = D3D10_USAGE_STAGING;
764 softDesc.BindFlags = 0;
766 nsRefPtr<ID3D10Texture2D> readTexture;
768 HRESULT hr = device()->CreateTexture2D(&softDesc, nullptr, getter_AddRefs(readTexture));
769 if (FAILED(hr)) {
770 ReportFailure(NS_LITERAL_CSTRING("LayerManagerD3D10::PaintToTarget(): Failed to create texture"),
771 hr);
772 return;
773 }
775 device()->CopyResource(readTexture, backBuf);
777 D3D10_MAPPED_TEXTURE2D map;
778 readTexture->Map(0, D3D10_MAP_READ, 0, &map);
780 nsRefPtr<gfxImageSurface> tmpSurface =
781 new gfxImageSurface((unsigned char*)map.pData,
782 gfxIntSize(bbDesc.Width, bbDesc.Height),
783 map.RowPitch,
784 gfxImageFormat::ARGB32);
786 mTarget->SetSource(tmpSurface);
787 mTarget->SetOperator(gfxContext::OPERATOR_OVER);
788 mTarget->Paint();
790 readTexture->Unmap(0);
791 }
793 void
794 LayerManagerD3D10::ReportFailure(const nsACString &aMsg, HRESULT aCode)
795 {
796 // We could choose to abort here when hr == E_OUTOFMEMORY.
797 nsCString msg;
798 msg.Append(aMsg);
799 msg.AppendLiteral(" Error code: ");
800 msg.AppendInt(uint32_t(aCode));
801 NS_WARNING(msg.BeginReading());
803 gfx::LogFailure(msg);
804 }
806 LayerD3D10::LayerD3D10(LayerManagerD3D10 *aManager)
807 : mD3DManager(aManager)
808 {
809 }
811 ID3D10EffectTechnique*
812 LayerD3D10::SelectShader(uint8_t aFlags)
813 {
814 switch (aFlags) {
815 case (SHADER_RGBA | SHADER_NON_PREMUL | SHADER_LINEAR | SHADER_MASK):
816 return effect()->GetTechniqueByName("RenderRGBALayerNonPremulMask");
817 case (SHADER_RGBA | SHADER_NON_PREMUL | SHADER_LINEAR | SHADER_NO_MASK):
818 return effect()->GetTechniqueByName("RenderRGBALayerNonPremul");
819 case (SHADER_RGBA | SHADER_NON_PREMUL | SHADER_POINT | SHADER_NO_MASK):
820 return effect()->GetTechniqueByName("RenderRGBALayerNonPremulPoint");
821 case (SHADER_RGBA | SHADER_NON_PREMUL | SHADER_POINT | SHADER_MASK):
822 return effect()->GetTechniqueByName("RenderRGBALayerNonPremulPointMask");
823 case (SHADER_RGBA | SHADER_PREMUL | SHADER_LINEAR | SHADER_MASK_3D):
824 return effect()->GetTechniqueByName("RenderRGBALayerPremulMask3D");
825 case (SHADER_RGBA | SHADER_PREMUL | SHADER_LINEAR | SHADER_MASK):
826 return effect()->GetTechniqueByName("RenderRGBALayerPremulMask");
827 case (SHADER_RGBA | SHADER_PREMUL | SHADER_LINEAR | SHADER_NO_MASK):
828 return effect()->GetTechniqueByName("RenderRGBALayerPremul");
829 case (SHADER_RGBA | SHADER_PREMUL | SHADER_POINT | SHADER_MASK):
830 return effect()->GetTechniqueByName("RenderRGBALayerPremulPointMask");
831 case (SHADER_RGBA | SHADER_PREMUL | SHADER_POINT | SHADER_NO_MASK):
832 return effect()->GetTechniqueByName("RenderRGBALayerPremulPoint");
833 case (SHADER_RGB | SHADER_PREMUL | SHADER_POINT | SHADER_MASK):
834 return effect()->GetTechniqueByName("RenderRGBLayerPremulPointMask");
835 case (SHADER_RGB | SHADER_PREMUL | SHADER_POINT | SHADER_NO_MASK):
836 return effect()->GetTechniqueByName("RenderRGBLayerPremulPoint");
837 case (SHADER_RGB | SHADER_PREMUL | SHADER_LINEAR | SHADER_MASK):
838 return effect()->GetTechniqueByName("RenderRGBLayerPremulMask");
839 case (SHADER_RGB | SHADER_PREMUL | SHADER_LINEAR | SHADER_NO_MASK):
840 return effect()->GetTechniqueByName("RenderRGBLayerPremul");
841 case (SHADER_SOLID | SHADER_MASK):
842 return effect()->GetTechniqueByName("RenderSolidColorLayerMask");
843 case (SHADER_SOLID | SHADER_NO_MASK):
844 return effect()->GetTechniqueByName("RenderSolidColorLayer");
845 case (SHADER_COMPONENT_ALPHA | SHADER_MASK):
846 return effect()->GetTechniqueByName("RenderComponentAlphaLayerMask");
847 case (SHADER_COMPONENT_ALPHA | SHADER_NO_MASK):
848 return effect()->GetTechniqueByName("RenderComponentAlphaLayer");
849 case (SHADER_YCBCR | SHADER_MASK):
850 return effect()->GetTechniqueByName("RenderYCbCrLayerMask");
851 case (SHADER_YCBCR | SHADER_NO_MASK):
852 return effect()->GetTechniqueByName("RenderYCbCrLayer");
853 default:
854 NS_ERROR("Invalid shader.");
855 return nullptr;
856 }
857 }
859 uint8_t
860 LayerD3D10::LoadMaskTexture()
861 {
862 if (Layer* maskLayer = GetLayer()->GetMaskLayer()) {
863 IntSize size;
864 nsRefPtr<ID3D10ShaderResourceView> maskSRV =
865 static_cast<LayerD3D10*>(maskLayer->ImplData())->GetAsTexture(&size);
867 if (!maskSRV) {
868 return SHADER_NO_MASK;
869 }
871 Matrix maskTransform;
872 Matrix4x4 effectiveTransform = maskLayer->GetEffectiveTransform();
873 bool maskIs2D = effectiveTransform.CanDraw2D(&maskTransform);
874 NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
875 Rect bounds = Rect(Point(), Size(size));
876 bounds = maskTransform.TransformBounds(bounds);
878 effect()->GetVariableByName("vMaskQuad")->AsVector()->SetFloatVector(
879 ShaderConstantRectD3D10(
880 (float)bounds.x,
881 (float)bounds.y,
882 (float)bounds.width,
883 (float)bounds.height)
884 );
886 effect()->GetVariableByName("tMask")->AsShaderResource()->SetResource(maskSRV);
887 return SHADER_MASK;
888 }
890 return SHADER_NO_MASK;
891 }
893 }
894 }