Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 "DeviceManagerD3D9.h"
7 #include "LayerManagerD3D9Shaders.h"
8 #include "ThebesLayerD3D9.h"
9 #include "nsIServiceManager.h"
10 #include "nsIConsoleService.h"
11 #include "nsPrintfCString.h"
12 #include "Nv3DVUtils.h"
13 #include "plstr.h"
14 #include <algorithm>
15 #include "gfx2DGlue.h"
16 #include "gfxPlatform.h"
17 #include "gfxWindowsPlatform.h"
18 #include "TextureD3D9.h"
19 #include "mozilla/gfx/Point.h"
21 using namespace mozilla::gfx;
23 namespace mozilla {
24 namespace layers {
26 const LPCWSTR kClassName = L"D3D9WindowClass";
28 #define USE_D3D9EX
30 struct vertex {
31 float x, y;
32 };
34 SwapChainD3D9::SwapChainD3D9(DeviceManagerD3D9 *aDeviceManager)
35 : mDeviceManager(aDeviceManager)
36 , mWnd(0)
37 {
38 mDeviceManager->mSwapChains.AppendElement(this);
39 }
41 SwapChainD3D9::~SwapChainD3D9()
42 {
43 mDeviceManager->mSwapChains.RemoveElement(this);
44 }
46 bool
47 SwapChainD3D9::Init(HWND hWnd)
48 {
49 RECT r;
50 ::GetClientRect(hWnd, &r);
52 mWnd = hWnd;
54 D3DPRESENT_PARAMETERS pp;
55 memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
57 pp.BackBufferFormat = D3DFMT_A8R8G8B8;
58 pp.SwapEffect = D3DSWAPEFFECT_COPY;
59 pp.Windowed = TRUE;
60 pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
61 pp.hDeviceWindow = mWnd;
62 if (r.left == r.right || r.top == r.bottom) {
63 pp.BackBufferHeight = 1;
64 pp.BackBufferWidth = 1;
65 }
67 HRESULT hr = mDeviceManager->device()->
68 CreateAdditionalSwapChain(&pp,
69 getter_AddRefs(mSwapChain));
71 if (FAILED(hr)) {
72 NS_WARNING("Failed to create swap chain for window.");
73 return false;
74 }
76 return true;
77 }
79 already_AddRefed<IDirect3DSurface9>
80 SwapChainD3D9::GetBackBuffer()
81 {
82 nsRefPtr<IDirect3DSurface9> backBuffer;
83 mSwapChain->GetBackBuffer(0,
84 D3DBACKBUFFER_TYPE_MONO,
85 getter_AddRefs(backBuffer));
86 return backBuffer.forget();
87 }
89 DeviceManagerState
90 SwapChainD3D9::PrepareForRendering()
91 {
92 RECT r;
93 if (!::GetClientRect(mWnd, &r)) {
94 return DeviceFail;
95 }
97 DeviceManagerState deviceState = mDeviceManager->VerifyReadyForRendering();
98 if (deviceState != DeviceOK) {
99 return deviceState;
100 }
102 if (!mSwapChain) {
103 Init(mWnd);
104 }
106 if (mSwapChain) {
107 nsRefPtr<IDirect3DSurface9> backBuffer = GetBackBuffer();
109 D3DSURFACE_DESC desc;
110 backBuffer->GetDesc(&desc);
112 if (desc.Width == r.right - r.left && desc.Height == r.bottom - r.top) {
113 mDeviceManager->device()->SetRenderTarget(0, backBuffer);
114 return DeviceOK;
115 }
117 mSwapChain = nullptr;
119 Init(mWnd);
121 if (!mSwapChain) {
122 return DeviceFail;
123 }
125 backBuffer = GetBackBuffer();
126 mDeviceManager->device()->SetRenderTarget(0, backBuffer);
128 return DeviceOK;
129 }
131 return DeviceFail;
132 }
134 void
135 SwapChainD3D9::Present(const nsIntRect &aRect)
136 {
137 RECT r;
138 r.left = aRect.x;
139 r.top = aRect.y;
140 r.right = aRect.XMost();
141 r.bottom = aRect.YMost();
143 mSwapChain->Present(&r, &r, 0, 0, 0);
144 }
146 void
147 SwapChainD3D9::Present()
148 {
149 mSwapChain->Present(nullptr, nullptr, 0, 0, 0);
150 }
152 void
153 SwapChainD3D9::Reset()
154 {
155 mSwapChain = nullptr;
156 }
158 #define HAS_CAP(a, b) (((a) & (b)) == (b))
159 #define LACKS_CAP(a, b) !(((a) & (b)) == (b))
161 uint32_t DeviceManagerD3D9::sMaskQuadRegister = 11;
163 DeviceManagerD3D9::DeviceManagerD3D9()
164 : mTextureHostList(nullptr)
165 , mDeviceResetCount(0)
166 , mMaxTextureSize(0)
167 , mTextureAddressingMode(D3DTADDRESS_CLAMP)
168 , mHasDynamicTextures(false)
169 , mDeviceWasRemoved(false)
170 {
171 }
173 DeviceManagerD3D9::~DeviceManagerD3D9()
174 {
175 DestroyDevice();
176 }
178 bool
179 DeviceManagerD3D9::Init()
180 {
181 WNDCLASSW wc;
182 HRESULT hr;
184 if (!GetClassInfoW(GetModuleHandle(nullptr), kClassName, &wc)) {
185 ZeroMemory(&wc, sizeof(WNDCLASSW));
186 wc.hInstance = GetModuleHandle(nullptr);
187 wc.lpfnWndProc = ::DefWindowProc;
188 wc.lpszClassName = kClassName;
189 if (!RegisterClassW(&wc)) {
190 NS_WARNING("Failed to register window class for DeviceManager.");
191 return false;
192 }
193 }
195 mFocusWnd = ::CreateWindowW(kClassName, L"D3D9Window", WS_OVERLAPPEDWINDOW,
196 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr,
197 nullptr, GetModuleHandle(nullptr), nullptr);
199 if (!mFocusWnd) {
200 NS_WARNING("Failed to create DeviceManagerD3D9 Window.");
201 return false;
202 }
204 /* Create an Nv3DVUtils instance */
205 if (!mNv3DVUtils) {
206 mNv3DVUtils = new Nv3DVUtils();
207 if (!mNv3DVUtils) {
208 NS_WARNING("Could not create a new instance of Nv3DVUtils.\n");
209 }
210 }
212 /* Initialize the Nv3DVUtils object */
213 if (mNv3DVUtils) {
214 mNv3DVUtils->Initialize();
215 }
217 HMODULE d3d9 = LoadLibraryW(L"d3d9.dll");
218 decltype(Direct3DCreate9)* d3d9Create = (decltype(Direct3DCreate9)*)
219 GetProcAddress(d3d9, "Direct3DCreate9");
220 decltype(Direct3DCreate9Ex)* d3d9CreateEx = (decltype(Direct3DCreate9Ex)*)
221 GetProcAddress(d3d9, "Direct3DCreate9Ex");
223 #ifdef USE_D3D9EX
224 if (d3d9CreateEx) {
225 hr = d3d9CreateEx(D3D_SDK_VERSION, getter_AddRefs(mD3D9Ex));
226 if (SUCCEEDED(hr)) {
227 mD3D9 = mD3D9Ex;
228 }
229 }
230 #endif
232 if (!mD3D9) {
233 if (!d3d9Create) {
234 return false;
235 }
237 mD3D9 = dont_AddRef(d3d9Create(D3D_SDK_VERSION));
239 if (!mD3D9) {
240 return false;
241 }
242 }
244 D3DADAPTER_IDENTIFIER9 ident;
245 hr = mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &ident);
247 if (FAILED(hr)) {
248 return false;
249 }
251 D3DPRESENT_PARAMETERS pp;
252 memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
254 pp.BackBufferWidth = 1;
255 pp.BackBufferHeight = 1;
256 pp.BackBufferFormat = D3DFMT_A8R8G8B8;
257 pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
258 pp.Windowed = TRUE;
259 pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
260 pp.hDeviceWindow = mFocusWnd;
262 if (mD3D9Ex) {
263 hr = mD3D9Ex->CreateDeviceEx(D3DADAPTER_DEFAULT,
264 D3DDEVTYPE_HAL,
265 mFocusWnd,
266 D3DCREATE_FPU_PRESERVE |
267 D3DCREATE_MULTITHREADED |
268 D3DCREATE_MIXED_VERTEXPROCESSING,
269 &pp,
270 nullptr,
271 getter_AddRefs(mDeviceEx));
272 if (SUCCEEDED(hr)) {
273 mDevice = mDeviceEx;
274 }
276 D3DCAPS9 caps;
277 if (mDeviceEx && mDeviceEx->GetDeviceCaps(&caps)) {
278 if (LACKS_CAP(caps.Caps2, D3DCAPS2_DYNAMICTEXTURES)) {
279 // XXX - Should we actually hit this we'll need a CanvasLayer that
280 // supports static D3DPOOL_DEFAULT textures.
281 NS_WARNING("D3D9Ex device not used because of lack of support for \
282 dynamic textures. This is unexpected.");
283 mDevice = nullptr;
284 mDeviceEx = nullptr;
285 }
286 }
287 }
289 if (!mDevice) {
290 hr = mD3D9->CreateDevice(D3DADAPTER_DEFAULT,
291 D3DDEVTYPE_HAL,
292 mFocusWnd,
293 D3DCREATE_FPU_PRESERVE |
294 D3DCREATE_MULTITHREADED |
295 D3DCREATE_MIXED_VERTEXPROCESSING,
296 &pp,
297 getter_AddRefs(mDevice));
299 if (FAILED(hr)) {
300 NS_WARNING("Failed to create Device for DeviceManagerD3D9.");
301 return false;
302 }
303 }
305 if (!VerifyCaps()) {
306 return false;
307 }
309 /* Grab the associated HMONITOR so that we can find out
310 * if it changed later */
311 D3DDEVICE_CREATION_PARAMETERS parameters;
312 if (FAILED(mDevice->GetCreationParameters(¶meters)))
313 return false;
314 mDeviceMonitor = mD3D9->GetAdapterMonitor(parameters.AdapterOrdinal);
317 /*
318 * Do some post device creation setup
319 */
320 if (mNv3DVUtils) {
321 IUnknown* devUnknown = nullptr;
322 if (mDevice) {
323 mDevice->QueryInterface(IID_IUnknown, (void **)&devUnknown);
324 }
325 mNv3DVUtils->SetDeviceInfo(devUnknown);
326 }
328 hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVS,
329 getter_AddRefs(mLayerVS));
331 if (FAILED(hr)) {
332 return false;
333 }
335 hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPS,
336 getter_AddRefs(mRGBPS));
338 if (FAILED(hr)) {
339 return false;
340 }
342 hr = mDevice->CreatePixelShader((DWORD*)RGBAShaderPS,
343 getter_AddRefs(mRGBAPS));
345 if (FAILED(hr)) {
346 return false;
347 }
349 hr = mDevice->CreatePixelShader((DWORD*)ComponentPass1ShaderPS,
350 getter_AddRefs(mComponentPass1PS));
352 if (FAILED(hr)) {
353 return false;
354 }
356 hr = mDevice->CreatePixelShader((DWORD*)ComponentPass2ShaderPS,
357 getter_AddRefs(mComponentPass2PS));
359 if (FAILED(hr)) {
360 return false;
361 }
363 hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPS,
364 getter_AddRefs(mYCbCrPS));
366 if (FAILED(hr)) {
367 return false;
368 }
370 hr = mDevice->CreatePixelShader((DWORD*)SolidColorShaderPS,
371 getter_AddRefs(mSolidColorPS));
373 if (FAILED(hr)) {
374 return false;
375 }
377 hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVSMask,
378 getter_AddRefs(mLayerVSMask));
380 if (FAILED(hr)) {
381 return false;
382 }
383 hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVSMask3D,
384 getter_AddRefs(mLayerVSMask3D));
386 if (FAILED(hr)) {
387 return false;
388 }
390 hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPSMask,
391 getter_AddRefs(mRGBPSMask));
393 if (FAILED(hr)) {
394 return false;
395 }
397 hr = mDevice->CreatePixelShader((DWORD*)RGBAShaderPSMask,
398 getter_AddRefs(mRGBAPSMask));
400 if (FAILED(hr)) {
401 return false;
402 }
404 hr = mDevice->CreatePixelShader((DWORD*)RGBAShaderPSMask3D,
405 getter_AddRefs(mRGBAPSMask3D));
407 if (FAILED(hr)) {
408 return false;
409 }
411 hr = mDevice->CreatePixelShader((DWORD*)ComponentPass1ShaderPSMask,
412 getter_AddRefs(mComponentPass1PSMask));
414 if (FAILED(hr)) {
415 return false;
416 }
418 hr = mDevice->CreatePixelShader((DWORD*)ComponentPass2ShaderPSMask,
419 getter_AddRefs(mComponentPass2PSMask));
421 if (FAILED(hr)) {
422 return false;
423 }
425 hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPSMask,
426 getter_AddRefs(mYCbCrPSMask));
428 if (FAILED(hr)) {
429 return false;
430 }
432 hr = mDevice->CreatePixelShader((DWORD*)SolidColorShaderPSMask,
433 getter_AddRefs(mSolidColorPSMask));
435 if (FAILED(hr)) {
436 return false;
437 }
439 if (!CreateVertexBuffer()) {
440 return false;
441 }
443 hr = mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
444 if (FAILED(hr)) {
445 return false;
446 }
448 D3DVERTEXELEMENT9 elements[] = {
449 { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
450 D3DDECLUSAGE_POSITION, 0 },
451 D3DDECL_END()
452 };
454 mDevice->CreateVertexDeclaration(elements, getter_AddRefs(mVD));
456 nsCOMPtr<nsIConsoleService>
457 console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
459 D3DADAPTER_IDENTIFIER9 identifier;
460 mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier);
462 if (console) {
463 nsString msg;
464 msg +=
465 NS_LITERAL_STRING("Direct3D 9 DeviceManager Initialized Successfully.\nDriver: ");
466 msg += NS_ConvertUTF8toUTF16(
467 nsDependentCString((const char*)identifier.Driver));
468 msg += NS_LITERAL_STRING("\nDescription: ");
469 msg += NS_ConvertUTF8toUTF16(
470 nsDependentCString((const char*)identifier.Description));
471 msg += NS_LITERAL_STRING("\nVersion: ");
472 msg += NS_ConvertUTF8toUTF16(
473 nsPrintfCString("%d.%d.%d.%d",
474 HIWORD(identifier.DriverVersion.HighPart),
475 LOWORD(identifier.DriverVersion.HighPart),
476 HIWORD(identifier.DriverVersion.LowPart),
477 LOWORD(identifier.DriverVersion.LowPart)));
478 console->LogStringMessage(msg.get());
479 }
481 return true;
482 }
484 void
485 DeviceManagerD3D9::SetupRenderState()
486 {
487 mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
488 mDevice->SetVertexDeclaration(mVD);
489 mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
490 mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
491 mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
492 mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
493 mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
494 mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
495 mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
496 mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA);
497 mDevice->SetRenderState(D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD);
498 mDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
499 mDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
500 mDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
501 mDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
502 mDevice->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
503 mDevice->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
504 mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, mTextureAddressingMode);
505 mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, mTextureAddressingMode);
506 mDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, mTextureAddressingMode);
507 mDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, mTextureAddressingMode);
508 mDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, mTextureAddressingMode);
509 mDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, mTextureAddressingMode);
510 }
512 already_AddRefed<SwapChainD3D9>
513 DeviceManagerD3D9::CreateSwapChain(HWND hWnd)
514 {
515 nsRefPtr<SwapChainD3D9> swapChain = new SwapChainD3D9(this);
517 // See bug 604647. This line means that if we create a window while the
518 // device is lost LayerManager initialization will fail, this window
519 // will be permanently unaccelerated. This should be a rare situation
520 // though and the need for a low-risk fix for this bug outweighs the
521 // downside.
522 if (VerifyReadyForRendering() != DeviceOK) {
523 return nullptr;
524 }
526 if (!swapChain->Init(hWnd)) {
527 return nullptr;
528 }
530 return swapChain.forget();
531 }
533 /*
534 * Finds a texture for the mask layer and sets it as an
535 * input to the shaders.
536 * Returns true if a texture is loaded, false if
537 * a texture for the mask layer could not be loaded.
538 */
539 bool
540 LoadMaskTexture(Layer* aMask, IDirect3DDevice9* aDevice,
541 uint32_t aMaskTexRegister)
542 {
543 IntSize size;
544 nsRefPtr<IDirect3DTexture9> texture =
545 static_cast<LayerD3D9*>(aMask->ImplData())->GetAsTexture(&size);
547 if (!texture) {
548 return false;
549 }
551 Matrix maskTransform;
552 Matrix4x4 effectiveTransform = aMask->GetEffectiveTransform();
553 bool maskIs2D = effectiveTransform.CanDraw2D(&maskTransform);
554 NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
555 Rect bounds = Rect(Point(), Size(size));
556 bounds = maskTransform.TransformBounds(bounds);
558 aDevice->SetVertexShaderConstantF(DeviceManagerD3D9::sMaskQuadRegister,
559 ShaderConstantRect((float)bounds.x,
560 (float)bounds.y,
561 (float)bounds.width,
562 (float)bounds.height),
563 1);
565 aDevice->SetTexture(aMaskTexRegister, texture);
566 return true;
567 }
569 uint32_t
570 DeviceManagerD3D9::SetShaderMode(ShaderMode aMode, MaskType aMaskType)
571 {
572 if (aMaskType == MaskNone) {
573 switch (aMode) {
574 case RGBLAYER:
575 mDevice->SetVertexShader(mLayerVS);
576 mDevice->SetPixelShader(mRGBPS);
577 break;
578 case RGBALAYER:
579 mDevice->SetVertexShader(mLayerVS);
580 mDevice->SetPixelShader(mRGBAPS);
581 break;
582 case COMPONENTLAYERPASS1:
583 mDevice->SetVertexShader(mLayerVS);
584 mDevice->SetPixelShader(mComponentPass1PS);
585 break;
586 case COMPONENTLAYERPASS2:
587 mDevice->SetVertexShader(mLayerVS);
588 mDevice->SetPixelShader(mComponentPass2PS);
589 break;
590 case YCBCRLAYER:
591 mDevice->SetVertexShader(mLayerVS);
592 mDevice->SetPixelShader(mYCbCrPS);
593 break;
594 case SOLIDCOLORLAYER:
595 mDevice->SetVertexShader(mLayerVS);
596 mDevice->SetPixelShader(mSolidColorPS);
597 break;
598 }
599 return 0;
600 }
602 uint32_t maskTexRegister;
603 switch (aMode) {
604 case RGBLAYER:
605 mDevice->SetVertexShader(mLayerVSMask);
606 mDevice->SetPixelShader(mRGBPSMask);
607 maskTexRegister = 1;
608 break;
609 case RGBALAYER:
610 if (aMaskType == Mask2d) {
611 mDevice->SetVertexShader(mLayerVSMask);
612 mDevice->SetPixelShader(mRGBAPSMask);
613 } else {
614 mDevice->SetVertexShader(mLayerVSMask3D);
615 mDevice->SetPixelShader(mRGBAPSMask3D);
616 }
617 maskTexRegister = 1;
618 break;
619 case COMPONENTLAYERPASS1:
620 mDevice->SetVertexShader(mLayerVSMask);
621 mDevice->SetPixelShader(mComponentPass1PSMask);
622 maskTexRegister = 2;
623 break;
624 case COMPONENTLAYERPASS2:
625 mDevice->SetVertexShader(mLayerVSMask);
626 mDevice->SetPixelShader(mComponentPass2PSMask);
627 maskTexRegister = 2;
628 break;
629 case YCBCRLAYER:
630 mDevice->SetVertexShader(mLayerVSMask);
631 mDevice->SetPixelShader(mYCbCrPSMask);
632 maskTexRegister = 3;
633 break;
634 case SOLIDCOLORLAYER:
635 mDevice->SetVertexShader(mLayerVSMask);
636 mDevice->SetPixelShader(mSolidColorPSMask);
637 maskTexRegister = 0;
638 break;
639 }
640 return maskTexRegister;
641 }
643 void
644 DeviceManagerD3D9::SetShaderMode(ShaderMode aMode, Layer* aMask, bool aIs2D)
645 {
646 MaskType maskType = MaskNone;
647 if (aMask) {
648 maskType = aIs2D ? Mask2d : Mask3d;
649 }
650 uint32_t maskTexRegister = SetShaderMode(aMode, maskType);
651 if (aMask) {
652 // register allocations are taken from LayerManagerD3D9Shaders.h after
653 // the shaders are compiled (genshaders.sh)
654 if (!LoadMaskTexture(aMask, mDevice, maskTexRegister)) {
655 // if we can't load the mask, fall back to unmasked rendering
656 NS_WARNING("Could not load texture for mask layer.");
657 SetShaderMode(aMode, MaskNone);
658 }
659 }
660 }
662 void
663 DeviceManagerD3D9::DestroyDevice()
664 {
665 ++mDeviceResetCount;
666 mDeviceWasRemoved = true;
667 if (!IsD3D9Ex()) {
668 ReleaseTextureResources();
669 }
670 gfxWindowsPlatform::GetPlatform()->OnDeviceManagerDestroy(this);
671 }
673 DeviceManagerState
674 DeviceManagerD3D9::VerifyReadyForRendering()
675 {
676 if (mDeviceWasRemoved) {
677 return DeviceMustRecreate;
678 }
680 HRESULT hr = mDevice->TestCooperativeLevel();
682 if (SUCCEEDED(hr)) {
683 if (IsD3D9Ex()) {
684 hr = mDeviceEx->CheckDeviceState(mFocusWnd);
686 if (FAILED(hr)) {
687 DestroyDevice();
688 return DeviceMustRecreate;
689 }
690 }
691 return DeviceOK;
692 }
694 // We need to release all texture resources and swap chains before resetting.
695 for (unsigned int i = 0; i < mLayersWithResources.Length(); i++) {
696 mLayersWithResources[i]->CleanResources();
697 }
698 ReleaseTextureResources();
699 for (unsigned int i = 0; i < mSwapChains.Length(); i++) {
700 mSwapChains[i]->Reset();
701 }
703 mVB = nullptr;
705 D3DPRESENT_PARAMETERS pp;
706 memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
708 pp.BackBufferWidth = 1;
709 pp.BackBufferHeight = 1;
710 pp.BackBufferFormat = D3DFMT_A8R8G8B8;
711 pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
712 pp.Windowed = TRUE;
713 pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
714 pp.hDeviceWindow = mFocusWnd;
716 // Whatever happens from now on, either we reset the device, or we should
717 // pretend we reset the device so that the layer manager or compositor
718 // doesn't ignore it.
719 ++mDeviceResetCount;
721 // if we got this far, we know !SUCCEEDEED(hr), that means hr is one of
722 // D3DERR_DEVICELOST, D3DERR_DEVICENOTRESET, D3DERR_DRIVERINTERNALERROR.
723 // It is only worth resetting if we get D3DERR_DEVICENOTRESET. If we get
724 // D3DERR_DEVICELOST we can wait and see if we get D3DERR_DEVICENOTRESET
725 // later, then reset.
726 if (hr == D3DERR_DEVICELOST) {
727 HMONITOR hMonitorWindow;
728 hMonitorWindow = MonitorFromWindow(mFocusWnd, MONITOR_DEFAULTTOPRIMARY);
729 if (hMonitorWindow != mDeviceMonitor) {
730 /* jrmuizel: I'm not sure how to trigger this case. Usually, we get
731 * DEVICENOTRESET right away and Reset() succeeds without going through a
732 * set of DEVICELOSTs. This is presumeably because we don't call
733 * VerifyReadyForRendering when we don't have any reason to paint.
734 * Hopefully comparing HMONITORs is not overly aggressive.
735 * See bug 626678.
736 */
737 /* The monitor has changed. We have to assume that the
738 * DEVICENOTRESET will not be coming. */
739 DestroyDevice();
740 return DeviceMustRecreate;
741 }
742 return DeviceFail;
743 }
744 if (hr == D3DERR_DEVICENOTRESET) {
745 hr = mDevice->Reset(&pp);
746 }
748 if (FAILED(hr) || !CreateVertexBuffer()) {
749 DestroyDevice();
750 return DeviceMustRecreate;
751 }
753 return DeviceOK;
754 }
756 bool
757 DeviceManagerD3D9::VerifyCaps()
758 {
759 D3DCAPS9 caps;
760 HRESULT hr = mDevice->GetDeviceCaps(&caps);
762 if (FAILED(hr)) {
763 return false;
764 }
766 if (LACKS_CAP(caps.DevCaps, D3DDEVCAPS_TEXTUREVIDEOMEMORY)) {
767 return false;
768 }
770 if (LACKS_CAP(caps.PrimitiveMiscCaps, D3DPMISCCAPS_CULLNONE)) {
771 return false;
772 }
774 if (LACKS_CAP(caps.SrcBlendCaps, D3DPBLENDCAPS_ONE) ||
775 LACKS_CAP(caps.SrcBlendCaps, D3DBLEND_SRCALPHA) ||
776 LACKS_CAP(caps.DestBlendCaps, D3DPBLENDCAPS_INVSRCALPHA)) {
777 return false;
778 }
780 if (LACKS_CAP(caps.RasterCaps, D3DPRASTERCAPS_SCISSORTEST)) {
781 return false;
782 }
784 if (LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_ALPHA) ||
785 HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_SQUAREONLY) ||
786 (HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_POW2) &&
787 LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL))) {
788 return false;
789 }
791 if (LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MAGFLINEAR) ||
792 LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MINFLINEAR)) {
793 return false;
794 }
796 if (LACKS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP)) {
797 return false;
798 }
800 if (caps.MaxTextureHeight < 4096 ||
801 caps.MaxTextureWidth < 4096) {
802 return false;
803 }
804 mMaxTextureSize = std::min(caps.MaxTextureHeight, caps.MaxTextureWidth);
806 if ((caps.PixelShaderVersion & 0xffff) < 0x200 ||
807 (caps.VertexShaderVersion & 0xffff) < 0x200) {
808 return false;
809 }
811 if (HAS_CAP(caps.Caps2, D3DCAPS2_DYNAMICTEXTURES)) {
812 mHasDynamicTextures = true;
813 }
815 if (HAS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_WRAP) &&
816 LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL)) {
817 mTextureAddressingMode = D3DTADDRESS_WRAP;
818 } else {
819 gfxPlatform::DisableBufferRotation();
820 }
822 return true;
823 }
825 bool
826 DeviceManagerD3D9::CreateVertexBuffer()
827 {
828 HRESULT hr;
830 hr = mDevice->CreateVertexBuffer(sizeof(vertex) * 4,
831 D3DUSAGE_WRITEONLY,
832 0,
833 D3DPOOL_DEFAULT,
834 getter_AddRefs(mVB),
835 nullptr);
837 if (FAILED(hr)) {
838 return false;
839 }
841 vertex *vertices;
842 hr = mVB->Lock(0, 0, (void**)&vertices, 0);
843 if (FAILED(hr)) {
844 return false;
845 }
847 vertices[0].x = vertices[0].y = 0;
848 vertices[1].x = 1; vertices[1].y = 0;
849 vertices[2].x = 0; vertices[2].y = 1;
850 vertices[3].x = 1; vertices[3].y = 1;
852 mVB->Unlock();
854 return true;
855 }
857 TemporaryRef<IDirect3DTexture9>
858 DeviceManagerD3D9::CreateTexture(const IntSize &aSize,
859 _D3DFORMAT aFormat,
860 D3DPOOL aPool,
861 TextureSourceD3D9* aTextureHost)
862 {
863 if (mDeviceWasRemoved) {
864 return nullptr;
865 }
866 RefPtr<IDirect3DTexture9> result;
867 if (FAILED(device()->CreateTexture(aSize.width, aSize.height,
868 1, 0, aFormat, aPool,
869 byRef(result), nullptr))) {
870 return nullptr;
871 }
873 NS_ASSERTION(aPool != D3DPOOL_MANAGED,
874 "Should not be using MANAGED texture pool. We will get an error when we have to recreate the device");
875 if (aPool == D3DPOOL_DEFAULT) {
876 MOZ_ASSERT(aTextureHost, "We need a texture host to track so we can release the texture.");
877 RegisterTextureHost(aTextureHost);
878 }
880 return result;
881 }
883 #ifdef DEBUG
884 bool
885 DeviceManagerD3D9::IsInTextureHostList(TextureSourceD3D9* aFind)
886 {
887 TextureSourceD3D9* cur = mTextureHostList;
888 while(cur) {
889 if (cur == aFind) {
890 return true;
891 }
892 cur = cur->mNextHost;
893 }
895 return false;
896 }
897 #endif
899 void
900 DeviceManagerD3D9::RegisterTextureHost(TextureSourceD3D9* aHost)
901 {
902 if (!aHost) {
903 return;
904 }
906 // Don't add aHost to the list twice.
907 if (aHost->mPreviousHost ||
908 mTextureHostList == aHost) {
909 MOZ_ASSERT(IsInTextureHostList(aHost));
910 return;
911 }
913 MOZ_ASSERT(!aHost->mNextHost);
914 MOZ_ASSERT(!IsInTextureHostList(aHost));
916 if (mTextureHostList) {
917 MOZ_ASSERT(!mTextureHostList->mPreviousHost);
918 mTextureHostList->mPreviousHost = aHost;
919 aHost->mNextHost = mTextureHostList;
920 }
921 mTextureHostList = aHost;
922 MOZ_ASSERT(!aHost->mCreatingDeviceManager, "Already created texture?");
923 MOZ_ASSERT(IsInTextureHostList(aHost));
924 aHost->mCreatingDeviceManager = this;
925 }
927 void
928 DeviceManagerD3D9::ReleaseTextureResources()
929 {
930 TextureSourceD3D9* host = mTextureHostList;
931 while (host) {
932 host->ReleaseTextureResources();
933 TextureSourceD3D9* oldHost = host;
934 host = oldHost->mNextHost;
935 oldHost->mPreviousHost = nullptr;
936 oldHost->mNextHost = nullptr;
937 oldHost->mCreatingDeviceManager = nullptr;
938 }
939 mTextureHostList = nullptr;
940 }
942 void
943 DeviceManagerD3D9::RemoveTextureListHead(TextureSourceD3D9* aHost)
944 {
945 MOZ_ASSERT(!aHost->mCreatingDeviceManager || aHost->mCreatingDeviceManager == this,
946 "Wrong device manager");
947 MOZ_ASSERT(aHost && mTextureHostList == aHost,
948 "aHost is not the head of the texture host list");
949 mTextureHostList = aHost->mNextHost;
950 }
952 } /* namespace layers */
953 } /* namespace mozilla */