1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/d3d9/DeviceManagerD3D9.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,953 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "DeviceManagerD3D9.h" 1.10 +#include "LayerManagerD3D9Shaders.h" 1.11 +#include "ThebesLayerD3D9.h" 1.12 +#include "nsIServiceManager.h" 1.13 +#include "nsIConsoleService.h" 1.14 +#include "nsPrintfCString.h" 1.15 +#include "Nv3DVUtils.h" 1.16 +#include "plstr.h" 1.17 +#include <algorithm> 1.18 +#include "gfx2DGlue.h" 1.19 +#include "gfxPlatform.h" 1.20 +#include "gfxWindowsPlatform.h" 1.21 +#include "TextureD3D9.h" 1.22 +#include "mozilla/gfx/Point.h" 1.23 + 1.24 +using namespace mozilla::gfx; 1.25 + 1.26 +namespace mozilla { 1.27 +namespace layers { 1.28 + 1.29 +const LPCWSTR kClassName = L"D3D9WindowClass"; 1.30 + 1.31 +#define USE_D3D9EX 1.32 + 1.33 +struct vertex { 1.34 + float x, y; 1.35 +}; 1.36 + 1.37 +SwapChainD3D9::SwapChainD3D9(DeviceManagerD3D9 *aDeviceManager) 1.38 + : mDeviceManager(aDeviceManager) 1.39 + , mWnd(0) 1.40 +{ 1.41 + mDeviceManager->mSwapChains.AppendElement(this); 1.42 +} 1.43 + 1.44 +SwapChainD3D9::~SwapChainD3D9() 1.45 +{ 1.46 + mDeviceManager->mSwapChains.RemoveElement(this); 1.47 +} 1.48 + 1.49 +bool 1.50 +SwapChainD3D9::Init(HWND hWnd) 1.51 +{ 1.52 + RECT r; 1.53 + ::GetClientRect(hWnd, &r); 1.54 + 1.55 + mWnd = hWnd; 1.56 + 1.57 + D3DPRESENT_PARAMETERS pp; 1.58 + memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS)); 1.59 + 1.60 + pp.BackBufferFormat = D3DFMT_A8R8G8B8; 1.61 + pp.SwapEffect = D3DSWAPEFFECT_COPY; 1.62 + pp.Windowed = TRUE; 1.63 + pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; 1.64 + pp.hDeviceWindow = mWnd; 1.65 + if (r.left == r.right || r.top == r.bottom) { 1.66 + pp.BackBufferHeight = 1; 1.67 + pp.BackBufferWidth = 1; 1.68 + } 1.69 + 1.70 + HRESULT hr = mDeviceManager->device()-> 1.71 + CreateAdditionalSwapChain(&pp, 1.72 + getter_AddRefs(mSwapChain)); 1.73 + 1.74 + if (FAILED(hr)) { 1.75 + NS_WARNING("Failed to create swap chain for window."); 1.76 + return false; 1.77 + } 1.78 + 1.79 + return true; 1.80 +} 1.81 + 1.82 +already_AddRefed<IDirect3DSurface9> 1.83 +SwapChainD3D9::GetBackBuffer() 1.84 +{ 1.85 + nsRefPtr<IDirect3DSurface9> backBuffer; 1.86 + mSwapChain->GetBackBuffer(0, 1.87 + D3DBACKBUFFER_TYPE_MONO, 1.88 + getter_AddRefs(backBuffer)); 1.89 + return backBuffer.forget(); 1.90 +} 1.91 + 1.92 +DeviceManagerState 1.93 +SwapChainD3D9::PrepareForRendering() 1.94 +{ 1.95 + RECT r; 1.96 + if (!::GetClientRect(mWnd, &r)) { 1.97 + return DeviceFail; 1.98 + } 1.99 + 1.100 + DeviceManagerState deviceState = mDeviceManager->VerifyReadyForRendering(); 1.101 + if (deviceState != DeviceOK) { 1.102 + return deviceState; 1.103 + } 1.104 + 1.105 + if (!mSwapChain) { 1.106 + Init(mWnd); 1.107 + } 1.108 + 1.109 + if (mSwapChain) { 1.110 + nsRefPtr<IDirect3DSurface9> backBuffer = GetBackBuffer(); 1.111 + 1.112 + D3DSURFACE_DESC desc; 1.113 + backBuffer->GetDesc(&desc); 1.114 + 1.115 + if (desc.Width == r.right - r.left && desc.Height == r.bottom - r.top) { 1.116 + mDeviceManager->device()->SetRenderTarget(0, backBuffer); 1.117 + return DeviceOK; 1.118 + } 1.119 + 1.120 + mSwapChain = nullptr; 1.121 + 1.122 + Init(mWnd); 1.123 + 1.124 + if (!mSwapChain) { 1.125 + return DeviceFail; 1.126 + } 1.127 + 1.128 + backBuffer = GetBackBuffer(); 1.129 + mDeviceManager->device()->SetRenderTarget(0, backBuffer); 1.130 + 1.131 + return DeviceOK; 1.132 + } 1.133 + 1.134 + return DeviceFail; 1.135 +} 1.136 + 1.137 +void 1.138 +SwapChainD3D9::Present(const nsIntRect &aRect) 1.139 +{ 1.140 + RECT r; 1.141 + r.left = aRect.x; 1.142 + r.top = aRect.y; 1.143 + r.right = aRect.XMost(); 1.144 + r.bottom = aRect.YMost(); 1.145 + 1.146 + mSwapChain->Present(&r, &r, 0, 0, 0); 1.147 +} 1.148 + 1.149 +void 1.150 +SwapChainD3D9::Present() 1.151 +{ 1.152 + mSwapChain->Present(nullptr, nullptr, 0, 0, 0); 1.153 +} 1.154 + 1.155 +void 1.156 +SwapChainD3D9::Reset() 1.157 +{ 1.158 + mSwapChain = nullptr; 1.159 +} 1.160 + 1.161 +#define HAS_CAP(a, b) (((a) & (b)) == (b)) 1.162 +#define LACKS_CAP(a, b) !(((a) & (b)) == (b)) 1.163 + 1.164 +uint32_t DeviceManagerD3D9::sMaskQuadRegister = 11; 1.165 + 1.166 +DeviceManagerD3D9::DeviceManagerD3D9() 1.167 + : mTextureHostList(nullptr) 1.168 + , mDeviceResetCount(0) 1.169 + , mMaxTextureSize(0) 1.170 + , mTextureAddressingMode(D3DTADDRESS_CLAMP) 1.171 + , mHasDynamicTextures(false) 1.172 + , mDeviceWasRemoved(false) 1.173 +{ 1.174 +} 1.175 + 1.176 +DeviceManagerD3D9::~DeviceManagerD3D9() 1.177 +{ 1.178 + DestroyDevice(); 1.179 +} 1.180 + 1.181 +bool 1.182 +DeviceManagerD3D9::Init() 1.183 +{ 1.184 + WNDCLASSW wc; 1.185 + HRESULT hr; 1.186 + 1.187 + if (!GetClassInfoW(GetModuleHandle(nullptr), kClassName, &wc)) { 1.188 + ZeroMemory(&wc, sizeof(WNDCLASSW)); 1.189 + wc.hInstance = GetModuleHandle(nullptr); 1.190 + wc.lpfnWndProc = ::DefWindowProc; 1.191 + wc.lpszClassName = kClassName; 1.192 + if (!RegisterClassW(&wc)) { 1.193 + NS_WARNING("Failed to register window class for DeviceManager."); 1.194 + return false; 1.195 + } 1.196 + } 1.197 + 1.198 + mFocusWnd = ::CreateWindowW(kClassName, L"D3D9Window", WS_OVERLAPPEDWINDOW, 1.199 + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, 1.200 + nullptr, GetModuleHandle(nullptr), nullptr); 1.201 + 1.202 + if (!mFocusWnd) { 1.203 + NS_WARNING("Failed to create DeviceManagerD3D9 Window."); 1.204 + return false; 1.205 + } 1.206 + 1.207 + /* Create an Nv3DVUtils instance */ 1.208 + if (!mNv3DVUtils) { 1.209 + mNv3DVUtils = new Nv3DVUtils(); 1.210 + if (!mNv3DVUtils) { 1.211 + NS_WARNING("Could not create a new instance of Nv3DVUtils.\n"); 1.212 + } 1.213 + } 1.214 + 1.215 + /* Initialize the Nv3DVUtils object */ 1.216 + if (mNv3DVUtils) { 1.217 + mNv3DVUtils->Initialize(); 1.218 + } 1.219 + 1.220 + HMODULE d3d9 = LoadLibraryW(L"d3d9.dll"); 1.221 + decltype(Direct3DCreate9)* d3d9Create = (decltype(Direct3DCreate9)*) 1.222 + GetProcAddress(d3d9, "Direct3DCreate9"); 1.223 + decltype(Direct3DCreate9Ex)* d3d9CreateEx = (decltype(Direct3DCreate9Ex)*) 1.224 + GetProcAddress(d3d9, "Direct3DCreate9Ex"); 1.225 + 1.226 +#ifdef USE_D3D9EX 1.227 + if (d3d9CreateEx) { 1.228 + hr = d3d9CreateEx(D3D_SDK_VERSION, getter_AddRefs(mD3D9Ex)); 1.229 + if (SUCCEEDED(hr)) { 1.230 + mD3D9 = mD3D9Ex; 1.231 + } 1.232 + } 1.233 +#endif 1.234 + 1.235 + if (!mD3D9) { 1.236 + if (!d3d9Create) { 1.237 + return false; 1.238 + } 1.239 + 1.240 + mD3D9 = dont_AddRef(d3d9Create(D3D_SDK_VERSION)); 1.241 + 1.242 + if (!mD3D9) { 1.243 + return false; 1.244 + } 1.245 + } 1.246 + 1.247 + D3DADAPTER_IDENTIFIER9 ident; 1.248 + hr = mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &ident); 1.249 + 1.250 + if (FAILED(hr)) { 1.251 + return false; 1.252 + } 1.253 + 1.254 + D3DPRESENT_PARAMETERS pp; 1.255 + memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS)); 1.256 + 1.257 + pp.BackBufferWidth = 1; 1.258 + pp.BackBufferHeight = 1; 1.259 + pp.BackBufferFormat = D3DFMT_A8R8G8B8; 1.260 + pp.SwapEffect = D3DSWAPEFFECT_DISCARD; 1.261 + pp.Windowed = TRUE; 1.262 + pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; 1.263 + pp.hDeviceWindow = mFocusWnd; 1.264 + 1.265 + if (mD3D9Ex) { 1.266 + hr = mD3D9Ex->CreateDeviceEx(D3DADAPTER_DEFAULT, 1.267 + D3DDEVTYPE_HAL, 1.268 + mFocusWnd, 1.269 + D3DCREATE_FPU_PRESERVE | 1.270 + D3DCREATE_MULTITHREADED | 1.271 + D3DCREATE_MIXED_VERTEXPROCESSING, 1.272 + &pp, 1.273 + nullptr, 1.274 + getter_AddRefs(mDeviceEx)); 1.275 + if (SUCCEEDED(hr)) { 1.276 + mDevice = mDeviceEx; 1.277 + } 1.278 + 1.279 + D3DCAPS9 caps; 1.280 + if (mDeviceEx && mDeviceEx->GetDeviceCaps(&caps)) { 1.281 + if (LACKS_CAP(caps.Caps2, D3DCAPS2_DYNAMICTEXTURES)) { 1.282 + // XXX - Should we actually hit this we'll need a CanvasLayer that 1.283 + // supports static D3DPOOL_DEFAULT textures. 1.284 + NS_WARNING("D3D9Ex device not used because of lack of support for \ 1.285 + dynamic textures. This is unexpected."); 1.286 + mDevice = nullptr; 1.287 + mDeviceEx = nullptr; 1.288 + } 1.289 + } 1.290 + } 1.291 + 1.292 + if (!mDevice) { 1.293 + hr = mD3D9->CreateDevice(D3DADAPTER_DEFAULT, 1.294 + D3DDEVTYPE_HAL, 1.295 + mFocusWnd, 1.296 + D3DCREATE_FPU_PRESERVE | 1.297 + D3DCREATE_MULTITHREADED | 1.298 + D3DCREATE_MIXED_VERTEXPROCESSING, 1.299 + &pp, 1.300 + getter_AddRefs(mDevice)); 1.301 + 1.302 + if (FAILED(hr)) { 1.303 + NS_WARNING("Failed to create Device for DeviceManagerD3D9."); 1.304 + return false; 1.305 + } 1.306 + } 1.307 + 1.308 + if (!VerifyCaps()) { 1.309 + return false; 1.310 + } 1.311 + 1.312 + /* Grab the associated HMONITOR so that we can find out 1.313 + * if it changed later */ 1.314 + D3DDEVICE_CREATION_PARAMETERS parameters; 1.315 + if (FAILED(mDevice->GetCreationParameters(¶meters))) 1.316 + return false; 1.317 + mDeviceMonitor = mD3D9->GetAdapterMonitor(parameters.AdapterOrdinal); 1.318 + 1.319 + 1.320 + /* 1.321 + * Do some post device creation setup 1.322 + */ 1.323 + if (mNv3DVUtils) { 1.324 + IUnknown* devUnknown = nullptr; 1.325 + if (mDevice) { 1.326 + mDevice->QueryInterface(IID_IUnknown, (void **)&devUnknown); 1.327 + } 1.328 + mNv3DVUtils->SetDeviceInfo(devUnknown); 1.329 + } 1.330 + 1.331 + hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVS, 1.332 + getter_AddRefs(mLayerVS)); 1.333 + 1.334 + if (FAILED(hr)) { 1.335 + return false; 1.336 + } 1.337 + 1.338 + hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPS, 1.339 + getter_AddRefs(mRGBPS)); 1.340 + 1.341 + if (FAILED(hr)) { 1.342 + return false; 1.343 + } 1.344 + 1.345 + hr = mDevice->CreatePixelShader((DWORD*)RGBAShaderPS, 1.346 + getter_AddRefs(mRGBAPS)); 1.347 + 1.348 + if (FAILED(hr)) { 1.349 + return false; 1.350 + } 1.351 + 1.352 + hr = mDevice->CreatePixelShader((DWORD*)ComponentPass1ShaderPS, 1.353 + getter_AddRefs(mComponentPass1PS)); 1.354 + 1.355 + if (FAILED(hr)) { 1.356 + return false; 1.357 + } 1.358 + 1.359 + hr = mDevice->CreatePixelShader((DWORD*)ComponentPass2ShaderPS, 1.360 + getter_AddRefs(mComponentPass2PS)); 1.361 + 1.362 + if (FAILED(hr)) { 1.363 + return false; 1.364 + } 1.365 + 1.366 + hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPS, 1.367 + getter_AddRefs(mYCbCrPS)); 1.368 + 1.369 + if (FAILED(hr)) { 1.370 + return false; 1.371 + } 1.372 + 1.373 + hr = mDevice->CreatePixelShader((DWORD*)SolidColorShaderPS, 1.374 + getter_AddRefs(mSolidColorPS)); 1.375 + 1.376 + if (FAILED(hr)) { 1.377 + return false; 1.378 + } 1.379 + 1.380 + hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVSMask, 1.381 + getter_AddRefs(mLayerVSMask)); 1.382 + 1.383 + if (FAILED(hr)) { 1.384 + return false; 1.385 + } 1.386 + hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVSMask3D, 1.387 + getter_AddRefs(mLayerVSMask3D)); 1.388 + 1.389 + if (FAILED(hr)) { 1.390 + return false; 1.391 + } 1.392 + 1.393 + hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPSMask, 1.394 + getter_AddRefs(mRGBPSMask)); 1.395 + 1.396 + if (FAILED(hr)) { 1.397 + return false; 1.398 + } 1.399 + 1.400 + hr = mDevice->CreatePixelShader((DWORD*)RGBAShaderPSMask, 1.401 + getter_AddRefs(mRGBAPSMask)); 1.402 + 1.403 + if (FAILED(hr)) { 1.404 + return false; 1.405 + } 1.406 + 1.407 + hr = mDevice->CreatePixelShader((DWORD*)RGBAShaderPSMask3D, 1.408 + getter_AddRefs(mRGBAPSMask3D)); 1.409 + 1.410 + if (FAILED(hr)) { 1.411 + return false; 1.412 + } 1.413 + 1.414 + hr = mDevice->CreatePixelShader((DWORD*)ComponentPass1ShaderPSMask, 1.415 + getter_AddRefs(mComponentPass1PSMask)); 1.416 + 1.417 + if (FAILED(hr)) { 1.418 + return false; 1.419 + } 1.420 + 1.421 + hr = mDevice->CreatePixelShader((DWORD*)ComponentPass2ShaderPSMask, 1.422 + getter_AddRefs(mComponentPass2PSMask)); 1.423 + 1.424 + if (FAILED(hr)) { 1.425 + return false; 1.426 + } 1.427 + 1.428 + hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPSMask, 1.429 + getter_AddRefs(mYCbCrPSMask)); 1.430 + 1.431 + if (FAILED(hr)) { 1.432 + return false; 1.433 + } 1.434 + 1.435 + hr = mDevice->CreatePixelShader((DWORD*)SolidColorShaderPSMask, 1.436 + getter_AddRefs(mSolidColorPSMask)); 1.437 + 1.438 + if (FAILED(hr)) { 1.439 + return false; 1.440 + } 1.441 + 1.442 + if (!CreateVertexBuffer()) { 1.443 + return false; 1.444 + } 1.445 + 1.446 + hr = mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex)); 1.447 + if (FAILED(hr)) { 1.448 + return false; 1.449 + } 1.450 + 1.451 + D3DVERTEXELEMENT9 elements[] = { 1.452 + { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, 1.453 + D3DDECLUSAGE_POSITION, 0 }, 1.454 + D3DDECL_END() 1.455 + }; 1.456 + 1.457 + mDevice->CreateVertexDeclaration(elements, getter_AddRefs(mVD)); 1.458 + 1.459 + nsCOMPtr<nsIConsoleService> 1.460 + console(do_GetService(NS_CONSOLESERVICE_CONTRACTID)); 1.461 + 1.462 + D3DADAPTER_IDENTIFIER9 identifier; 1.463 + mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier); 1.464 + 1.465 + if (console) { 1.466 + nsString msg; 1.467 + msg += 1.468 + NS_LITERAL_STRING("Direct3D 9 DeviceManager Initialized Successfully.\nDriver: "); 1.469 + msg += NS_ConvertUTF8toUTF16( 1.470 + nsDependentCString((const char*)identifier.Driver)); 1.471 + msg += NS_LITERAL_STRING("\nDescription: "); 1.472 + msg += NS_ConvertUTF8toUTF16( 1.473 + nsDependentCString((const char*)identifier.Description)); 1.474 + msg += NS_LITERAL_STRING("\nVersion: "); 1.475 + msg += NS_ConvertUTF8toUTF16( 1.476 + nsPrintfCString("%d.%d.%d.%d", 1.477 + HIWORD(identifier.DriverVersion.HighPart), 1.478 + LOWORD(identifier.DriverVersion.HighPart), 1.479 + HIWORD(identifier.DriverVersion.LowPart), 1.480 + LOWORD(identifier.DriverVersion.LowPart))); 1.481 + console->LogStringMessage(msg.get()); 1.482 + } 1.483 + 1.484 + return true; 1.485 +} 1.486 + 1.487 +void 1.488 +DeviceManagerD3D9::SetupRenderState() 1.489 +{ 1.490 + mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex)); 1.491 + mDevice->SetVertexDeclaration(mVD); 1.492 + mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 1.493 + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); 1.494 + mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); 1.495 + mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); 1.496 + mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); 1.497 + mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); 1.498 + mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE); 1.499 + mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA); 1.500 + mDevice->SetRenderState(D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD); 1.501 + mDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); 1.502 + mDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); 1.503 + mDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); 1.504 + mDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); 1.505 + mDevice->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); 1.506 + mDevice->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); 1.507 + mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, mTextureAddressingMode); 1.508 + mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, mTextureAddressingMode); 1.509 + mDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, mTextureAddressingMode); 1.510 + mDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, mTextureAddressingMode); 1.511 + mDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, mTextureAddressingMode); 1.512 + mDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, mTextureAddressingMode); 1.513 +} 1.514 + 1.515 +already_AddRefed<SwapChainD3D9> 1.516 +DeviceManagerD3D9::CreateSwapChain(HWND hWnd) 1.517 +{ 1.518 + nsRefPtr<SwapChainD3D9> swapChain = new SwapChainD3D9(this); 1.519 + 1.520 + // See bug 604647. This line means that if we create a window while the 1.521 + // device is lost LayerManager initialization will fail, this window 1.522 + // will be permanently unaccelerated. This should be a rare situation 1.523 + // though and the need for a low-risk fix for this bug outweighs the 1.524 + // downside. 1.525 + if (VerifyReadyForRendering() != DeviceOK) { 1.526 + return nullptr; 1.527 + } 1.528 + 1.529 + if (!swapChain->Init(hWnd)) { 1.530 + return nullptr; 1.531 + } 1.532 + 1.533 + return swapChain.forget(); 1.534 +} 1.535 + 1.536 +/* 1.537 + * Finds a texture for the mask layer and sets it as an 1.538 + * input to the shaders. 1.539 + * Returns true if a texture is loaded, false if 1.540 + * a texture for the mask layer could not be loaded. 1.541 + */ 1.542 +bool 1.543 +LoadMaskTexture(Layer* aMask, IDirect3DDevice9* aDevice, 1.544 + uint32_t aMaskTexRegister) 1.545 +{ 1.546 + IntSize size; 1.547 + nsRefPtr<IDirect3DTexture9> texture = 1.548 + static_cast<LayerD3D9*>(aMask->ImplData())->GetAsTexture(&size); 1.549 + 1.550 + if (!texture) { 1.551 + return false; 1.552 + } 1.553 + 1.554 + Matrix maskTransform; 1.555 + Matrix4x4 effectiveTransform = aMask->GetEffectiveTransform(); 1.556 + bool maskIs2D = effectiveTransform.CanDraw2D(&maskTransform); 1.557 + NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!"); 1.558 + Rect bounds = Rect(Point(), Size(size)); 1.559 + bounds = maskTransform.TransformBounds(bounds); 1.560 + 1.561 + aDevice->SetVertexShaderConstantF(DeviceManagerD3D9::sMaskQuadRegister, 1.562 + ShaderConstantRect((float)bounds.x, 1.563 + (float)bounds.y, 1.564 + (float)bounds.width, 1.565 + (float)bounds.height), 1.566 + 1); 1.567 + 1.568 + aDevice->SetTexture(aMaskTexRegister, texture); 1.569 + return true; 1.570 +} 1.571 + 1.572 +uint32_t 1.573 +DeviceManagerD3D9::SetShaderMode(ShaderMode aMode, MaskType aMaskType) 1.574 +{ 1.575 + if (aMaskType == MaskNone) { 1.576 + switch (aMode) { 1.577 + case RGBLAYER: 1.578 + mDevice->SetVertexShader(mLayerVS); 1.579 + mDevice->SetPixelShader(mRGBPS); 1.580 + break; 1.581 + case RGBALAYER: 1.582 + mDevice->SetVertexShader(mLayerVS); 1.583 + mDevice->SetPixelShader(mRGBAPS); 1.584 + break; 1.585 + case COMPONENTLAYERPASS1: 1.586 + mDevice->SetVertexShader(mLayerVS); 1.587 + mDevice->SetPixelShader(mComponentPass1PS); 1.588 + break; 1.589 + case COMPONENTLAYERPASS2: 1.590 + mDevice->SetVertexShader(mLayerVS); 1.591 + mDevice->SetPixelShader(mComponentPass2PS); 1.592 + break; 1.593 + case YCBCRLAYER: 1.594 + mDevice->SetVertexShader(mLayerVS); 1.595 + mDevice->SetPixelShader(mYCbCrPS); 1.596 + break; 1.597 + case SOLIDCOLORLAYER: 1.598 + mDevice->SetVertexShader(mLayerVS); 1.599 + mDevice->SetPixelShader(mSolidColorPS); 1.600 + break; 1.601 + } 1.602 + return 0; 1.603 + } 1.604 + 1.605 + uint32_t maskTexRegister; 1.606 + switch (aMode) { 1.607 + case RGBLAYER: 1.608 + mDevice->SetVertexShader(mLayerVSMask); 1.609 + mDevice->SetPixelShader(mRGBPSMask); 1.610 + maskTexRegister = 1; 1.611 + break; 1.612 + case RGBALAYER: 1.613 + if (aMaskType == Mask2d) { 1.614 + mDevice->SetVertexShader(mLayerVSMask); 1.615 + mDevice->SetPixelShader(mRGBAPSMask); 1.616 + } else { 1.617 + mDevice->SetVertexShader(mLayerVSMask3D); 1.618 + mDevice->SetPixelShader(mRGBAPSMask3D); 1.619 + } 1.620 + maskTexRegister = 1; 1.621 + break; 1.622 + case COMPONENTLAYERPASS1: 1.623 + mDevice->SetVertexShader(mLayerVSMask); 1.624 + mDevice->SetPixelShader(mComponentPass1PSMask); 1.625 + maskTexRegister = 2; 1.626 + break; 1.627 + case COMPONENTLAYERPASS2: 1.628 + mDevice->SetVertexShader(mLayerVSMask); 1.629 + mDevice->SetPixelShader(mComponentPass2PSMask); 1.630 + maskTexRegister = 2; 1.631 + break; 1.632 + case YCBCRLAYER: 1.633 + mDevice->SetVertexShader(mLayerVSMask); 1.634 + mDevice->SetPixelShader(mYCbCrPSMask); 1.635 + maskTexRegister = 3; 1.636 + break; 1.637 + case SOLIDCOLORLAYER: 1.638 + mDevice->SetVertexShader(mLayerVSMask); 1.639 + mDevice->SetPixelShader(mSolidColorPSMask); 1.640 + maskTexRegister = 0; 1.641 + break; 1.642 + } 1.643 + return maskTexRegister; 1.644 +} 1.645 + 1.646 +void 1.647 +DeviceManagerD3D9::SetShaderMode(ShaderMode aMode, Layer* aMask, bool aIs2D) 1.648 +{ 1.649 + MaskType maskType = MaskNone; 1.650 + if (aMask) { 1.651 + maskType = aIs2D ? Mask2d : Mask3d; 1.652 + } 1.653 + uint32_t maskTexRegister = SetShaderMode(aMode, maskType); 1.654 + if (aMask) { 1.655 + // register allocations are taken from LayerManagerD3D9Shaders.h after 1.656 + // the shaders are compiled (genshaders.sh) 1.657 + if (!LoadMaskTexture(aMask, mDevice, maskTexRegister)) { 1.658 + // if we can't load the mask, fall back to unmasked rendering 1.659 + NS_WARNING("Could not load texture for mask layer."); 1.660 + SetShaderMode(aMode, MaskNone); 1.661 + } 1.662 + } 1.663 +} 1.664 + 1.665 +void 1.666 +DeviceManagerD3D9::DestroyDevice() 1.667 +{ 1.668 + ++mDeviceResetCount; 1.669 + mDeviceWasRemoved = true; 1.670 + if (!IsD3D9Ex()) { 1.671 + ReleaseTextureResources(); 1.672 + } 1.673 + gfxWindowsPlatform::GetPlatform()->OnDeviceManagerDestroy(this); 1.674 +} 1.675 + 1.676 +DeviceManagerState 1.677 +DeviceManagerD3D9::VerifyReadyForRendering() 1.678 +{ 1.679 + if (mDeviceWasRemoved) { 1.680 + return DeviceMustRecreate; 1.681 + } 1.682 + 1.683 + HRESULT hr = mDevice->TestCooperativeLevel(); 1.684 + 1.685 + if (SUCCEEDED(hr)) { 1.686 + if (IsD3D9Ex()) { 1.687 + hr = mDeviceEx->CheckDeviceState(mFocusWnd); 1.688 + 1.689 + if (FAILED(hr)) { 1.690 + DestroyDevice(); 1.691 + return DeviceMustRecreate; 1.692 + } 1.693 + } 1.694 + return DeviceOK; 1.695 + } 1.696 + 1.697 + // We need to release all texture resources and swap chains before resetting. 1.698 + for (unsigned int i = 0; i < mLayersWithResources.Length(); i++) { 1.699 + mLayersWithResources[i]->CleanResources(); 1.700 + } 1.701 + ReleaseTextureResources(); 1.702 + for (unsigned int i = 0; i < mSwapChains.Length(); i++) { 1.703 + mSwapChains[i]->Reset(); 1.704 + } 1.705 + 1.706 + mVB = nullptr; 1.707 + 1.708 + D3DPRESENT_PARAMETERS pp; 1.709 + memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS)); 1.710 + 1.711 + pp.BackBufferWidth = 1; 1.712 + pp.BackBufferHeight = 1; 1.713 + pp.BackBufferFormat = D3DFMT_A8R8G8B8; 1.714 + pp.SwapEffect = D3DSWAPEFFECT_DISCARD; 1.715 + pp.Windowed = TRUE; 1.716 + pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; 1.717 + pp.hDeviceWindow = mFocusWnd; 1.718 + 1.719 + // Whatever happens from now on, either we reset the device, or we should 1.720 + // pretend we reset the device so that the layer manager or compositor 1.721 + // doesn't ignore it. 1.722 + ++mDeviceResetCount; 1.723 + 1.724 + // if we got this far, we know !SUCCEEDEED(hr), that means hr is one of 1.725 + // D3DERR_DEVICELOST, D3DERR_DEVICENOTRESET, D3DERR_DRIVERINTERNALERROR. 1.726 + // It is only worth resetting if we get D3DERR_DEVICENOTRESET. If we get 1.727 + // D3DERR_DEVICELOST we can wait and see if we get D3DERR_DEVICENOTRESET 1.728 + // later, then reset. 1.729 + if (hr == D3DERR_DEVICELOST) { 1.730 + HMONITOR hMonitorWindow; 1.731 + hMonitorWindow = MonitorFromWindow(mFocusWnd, MONITOR_DEFAULTTOPRIMARY); 1.732 + if (hMonitorWindow != mDeviceMonitor) { 1.733 + /* jrmuizel: I'm not sure how to trigger this case. Usually, we get 1.734 + * DEVICENOTRESET right away and Reset() succeeds without going through a 1.735 + * set of DEVICELOSTs. This is presumeably because we don't call 1.736 + * VerifyReadyForRendering when we don't have any reason to paint. 1.737 + * Hopefully comparing HMONITORs is not overly aggressive. 1.738 + * See bug 626678. 1.739 + */ 1.740 + /* The monitor has changed. We have to assume that the 1.741 + * DEVICENOTRESET will not be coming. */ 1.742 + DestroyDevice(); 1.743 + return DeviceMustRecreate; 1.744 + } 1.745 + return DeviceFail; 1.746 + } 1.747 + if (hr == D3DERR_DEVICENOTRESET) { 1.748 + hr = mDevice->Reset(&pp); 1.749 + } 1.750 + 1.751 + if (FAILED(hr) || !CreateVertexBuffer()) { 1.752 + DestroyDevice(); 1.753 + return DeviceMustRecreate; 1.754 + } 1.755 + 1.756 + return DeviceOK; 1.757 +} 1.758 + 1.759 +bool 1.760 +DeviceManagerD3D9::VerifyCaps() 1.761 +{ 1.762 + D3DCAPS9 caps; 1.763 + HRESULT hr = mDevice->GetDeviceCaps(&caps); 1.764 + 1.765 + if (FAILED(hr)) { 1.766 + return false; 1.767 + } 1.768 + 1.769 + if (LACKS_CAP(caps.DevCaps, D3DDEVCAPS_TEXTUREVIDEOMEMORY)) { 1.770 + return false; 1.771 + } 1.772 + 1.773 + if (LACKS_CAP(caps.PrimitiveMiscCaps, D3DPMISCCAPS_CULLNONE)) { 1.774 + return false; 1.775 + } 1.776 + 1.777 + if (LACKS_CAP(caps.SrcBlendCaps, D3DPBLENDCAPS_ONE) || 1.778 + LACKS_CAP(caps.SrcBlendCaps, D3DBLEND_SRCALPHA) || 1.779 + LACKS_CAP(caps.DestBlendCaps, D3DPBLENDCAPS_INVSRCALPHA)) { 1.780 + return false; 1.781 + } 1.782 + 1.783 + if (LACKS_CAP(caps.RasterCaps, D3DPRASTERCAPS_SCISSORTEST)) { 1.784 + return false; 1.785 + } 1.786 + 1.787 + if (LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_ALPHA) || 1.788 + HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_SQUAREONLY) || 1.789 + (HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_POW2) && 1.790 + LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL))) { 1.791 + return false; 1.792 + } 1.793 + 1.794 + if (LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MAGFLINEAR) || 1.795 + LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MINFLINEAR)) { 1.796 + return false; 1.797 + } 1.798 + 1.799 + if (LACKS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP)) { 1.800 + return false; 1.801 + } 1.802 + 1.803 + if (caps.MaxTextureHeight < 4096 || 1.804 + caps.MaxTextureWidth < 4096) { 1.805 + return false; 1.806 + } 1.807 + mMaxTextureSize = std::min(caps.MaxTextureHeight, caps.MaxTextureWidth); 1.808 + 1.809 + if ((caps.PixelShaderVersion & 0xffff) < 0x200 || 1.810 + (caps.VertexShaderVersion & 0xffff) < 0x200) { 1.811 + return false; 1.812 + } 1.813 + 1.814 + if (HAS_CAP(caps.Caps2, D3DCAPS2_DYNAMICTEXTURES)) { 1.815 + mHasDynamicTextures = true; 1.816 + } 1.817 + 1.818 + if (HAS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_WRAP) && 1.819 + LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL)) { 1.820 + mTextureAddressingMode = D3DTADDRESS_WRAP; 1.821 + } else { 1.822 + gfxPlatform::DisableBufferRotation(); 1.823 + } 1.824 + 1.825 + return true; 1.826 +} 1.827 + 1.828 +bool 1.829 +DeviceManagerD3D9::CreateVertexBuffer() 1.830 +{ 1.831 + HRESULT hr; 1.832 + 1.833 + hr = mDevice->CreateVertexBuffer(sizeof(vertex) * 4, 1.834 + D3DUSAGE_WRITEONLY, 1.835 + 0, 1.836 + D3DPOOL_DEFAULT, 1.837 + getter_AddRefs(mVB), 1.838 + nullptr); 1.839 + 1.840 + if (FAILED(hr)) { 1.841 + return false; 1.842 + } 1.843 + 1.844 + vertex *vertices; 1.845 + hr = mVB->Lock(0, 0, (void**)&vertices, 0); 1.846 + if (FAILED(hr)) { 1.847 + return false; 1.848 + } 1.849 + 1.850 + vertices[0].x = vertices[0].y = 0; 1.851 + vertices[1].x = 1; vertices[1].y = 0; 1.852 + vertices[2].x = 0; vertices[2].y = 1; 1.853 + vertices[3].x = 1; vertices[3].y = 1; 1.854 + 1.855 + mVB->Unlock(); 1.856 + 1.857 + return true; 1.858 +} 1.859 + 1.860 +TemporaryRef<IDirect3DTexture9> 1.861 +DeviceManagerD3D9::CreateTexture(const IntSize &aSize, 1.862 + _D3DFORMAT aFormat, 1.863 + D3DPOOL aPool, 1.864 + TextureSourceD3D9* aTextureHost) 1.865 +{ 1.866 + if (mDeviceWasRemoved) { 1.867 + return nullptr; 1.868 + } 1.869 + RefPtr<IDirect3DTexture9> result; 1.870 + if (FAILED(device()->CreateTexture(aSize.width, aSize.height, 1.871 + 1, 0, aFormat, aPool, 1.872 + byRef(result), nullptr))) { 1.873 + return nullptr; 1.874 + } 1.875 + 1.876 + NS_ASSERTION(aPool != D3DPOOL_MANAGED, 1.877 + "Should not be using MANAGED texture pool. We will get an error when we have to recreate the device"); 1.878 + if (aPool == D3DPOOL_DEFAULT) { 1.879 + MOZ_ASSERT(aTextureHost, "We need a texture host to track so we can release the texture."); 1.880 + RegisterTextureHost(aTextureHost); 1.881 + } 1.882 + 1.883 + return result; 1.884 +} 1.885 + 1.886 +#ifdef DEBUG 1.887 +bool 1.888 +DeviceManagerD3D9::IsInTextureHostList(TextureSourceD3D9* aFind) 1.889 +{ 1.890 + TextureSourceD3D9* cur = mTextureHostList; 1.891 + while(cur) { 1.892 + if (cur == aFind) { 1.893 + return true; 1.894 + } 1.895 + cur = cur->mNextHost; 1.896 + } 1.897 + 1.898 + return false; 1.899 +} 1.900 +#endif 1.901 + 1.902 +void 1.903 +DeviceManagerD3D9::RegisterTextureHost(TextureSourceD3D9* aHost) 1.904 +{ 1.905 + if (!aHost) { 1.906 + return; 1.907 + } 1.908 + 1.909 + // Don't add aHost to the list twice. 1.910 + if (aHost->mPreviousHost || 1.911 + mTextureHostList == aHost) { 1.912 + MOZ_ASSERT(IsInTextureHostList(aHost)); 1.913 + return; 1.914 + } 1.915 + 1.916 + MOZ_ASSERT(!aHost->mNextHost); 1.917 + MOZ_ASSERT(!IsInTextureHostList(aHost)); 1.918 + 1.919 + if (mTextureHostList) { 1.920 + MOZ_ASSERT(!mTextureHostList->mPreviousHost); 1.921 + mTextureHostList->mPreviousHost = aHost; 1.922 + aHost->mNextHost = mTextureHostList; 1.923 + } 1.924 + mTextureHostList = aHost; 1.925 + MOZ_ASSERT(!aHost->mCreatingDeviceManager, "Already created texture?"); 1.926 + MOZ_ASSERT(IsInTextureHostList(aHost)); 1.927 + aHost->mCreatingDeviceManager = this; 1.928 +} 1.929 + 1.930 +void 1.931 +DeviceManagerD3D9::ReleaseTextureResources() 1.932 +{ 1.933 + TextureSourceD3D9* host = mTextureHostList; 1.934 + while (host) { 1.935 + host->ReleaseTextureResources(); 1.936 + TextureSourceD3D9* oldHost = host; 1.937 + host = oldHost->mNextHost; 1.938 + oldHost->mPreviousHost = nullptr; 1.939 + oldHost->mNextHost = nullptr; 1.940 + oldHost->mCreatingDeviceManager = nullptr; 1.941 + } 1.942 + mTextureHostList = nullptr; 1.943 +} 1.944 + 1.945 +void 1.946 +DeviceManagerD3D9::RemoveTextureListHead(TextureSourceD3D9* aHost) 1.947 +{ 1.948 + MOZ_ASSERT(!aHost->mCreatingDeviceManager || aHost->mCreatingDeviceManager == this, 1.949 + "Wrong device manager"); 1.950 + MOZ_ASSERT(aHost && mTextureHostList == aHost, 1.951 + "aHost is not the head of the texture host list"); 1.952 + mTextureHostList = aHost->mNextHost; 1.953 +} 1.954 + 1.955 +} /* namespace layers */ 1.956 +} /* namespace mozilla */