gfx/layers/d3d9/DeviceManagerD3D9.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial