FeatureStatus DeviceManagerDx::CreateContentDevice() { RefPtr<IDXGIAdapter1> adapter; if (!mDeviceStatus->isWARP()) { adapter = GetDXGIAdapter(); if (!adapter) { gfxCriticalNote << "Could not get a DXGI adapter"; return FeatureStatus::Unavailable; } } HRESULT hr; RefPtr<ID3D11Device> device; UINT flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; D3D_DRIVER_TYPE type = mDeviceStatus->isWARP() ? D3D_DRIVER_TYPE_WARP : D3D_DRIVER_TYPE_UNKNOWN; if (!CreateDevice(adapter, type, flags, hr, device)) { gfxCriticalNote << "Recovered from crash while creating a D3D11 content device"; gfxWindowsPlatform::RecordContentDeviceFailure(TelemetryDeviceCode::Content); return FeatureStatus::CrashedInHandler; } if (FAILED(hr) || !device) { gfxCriticalNote << "Failed to create a D3D11 content device: " << hexa(hr); gfxWindowsPlatform::RecordContentDeviceFailure(TelemetryDeviceCode::Content); return FeatureStatus::Failed; } // InitializeD2D() will abort early if the compositor device did not support // texture sharing. If we're in the content process, we can't rely on the // parent device alone: some systems have dual GPUs that are capable of // binding the parent and child processes to different GPUs. As a safety net, // we re-check texture sharing against the newly created D3D11 content device. // If it fails, we won't use Direct2D. if (XRE_IsContentProcess()) { if (!D3D11Checks::DoesTextureSharingWork(device)) { return FeatureStatus::Failed; } DebugOnly<bool> ok = ContentAdapterIsParentAdapter(device); MOZ_ASSERT(ok); } { MutexAutoLock lock(mDeviceLock); mContentDevice = device; } mContentDevice->SetExceptionMode(0); RefPtr<ID3D10Multithread> multi; hr = mContentDevice->QueryInterface(__uuidof(ID3D10Multithread), getter_AddRefs(multi)); if (SUCCEEDED(hr) && multi) { multi->SetMultithreadProtected(TRUE); } return FeatureStatus::Available; }
bool DeviceManagerDx::CheckRemotePresentSupport() { MOZ_ASSERT(XRE_IsParentProcess()); RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter(); if (!adapter) { return false; } if (!D3D11Checks::DoesRemotePresentWork(adapter)) { return false; } return true; }
void DeviceManagerDx::CreateCompositorDevice(FeatureState& d3d11) { if (gfxPrefs::LayersD3D11ForceWARP()) { CreateWARPCompositorDevice(); return; } RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter(); if (!adapter) { d3d11.SetFailed(FeatureStatus::Unavailable, "Failed to acquire a DXGI adapter", NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DXGI")); return; } RefPtr<ID3D11Device> device; if (!CreateCompositorDeviceHelper(d3d11, adapter, true, device)) { // Try again without video support and record that it failed. mCompositorDeviceSupportsVideo = false; if (!CreateCompositorDeviceHelper(d3d11, adapter, false, device)) { return; } } else { mCompositorDeviceSupportsVideo = true; } // Only test this when not using WARP since it can fail and cause // GetDeviceRemovedReason to return weird values. bool textureSharingWorks = D3D11Checks::DoesTextureSharingWork(device); DXGI_ADAPTER_DESC desc; PodZero(&desc); adapter->GetDesc(&desc); if (!textureSharingWorks) { gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE, FeatureStatus::Broken, "Texture sharing doesn't work"); } if (D3D11Checks::DoesRenderTargetViewNeedRecreating(device)) { gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE, FeatureStatus::Broken, "RenderTargetViews need recreating"); } if (XRE_IsParentProcess()) { // It seems like this may only happen when we're using the NVIDIA gpu D3D11Checks::WarnOnAdapterMismatch(device); } int featureLevel = device->GetFeatureLevel(); { MutexAutoLock lock(mDeviceLock); mCompositorDevice = device; mDeviceStatus = Some(D3D11DeviceStatus( false, textureSharingWorks, featureLevel, DxgiAdapterDesc::From(desc))); } mCompositorDevice->SetExceptionMode(0); }
RefPtr<ID3D11Device> DeviceManagerDx::CreateDecoderDevice() { bool isAMD = false; { MutexAutoLock lock(mDeviceLock); if (!mDeviceStatus) { return nullptr; } isAMD = mDeviceStatus->adapter().VendorId == 0x1002; } bool reuseDevice = false; if (gfxPrefs::Direct3D11ReuseDecoderDevice() < 0) { // Use the default logic, which is to allow reuse of devices on AMD, but create // separate devices everywhere else. if (isAMD) { reuseDevice = true; } } else if (gfxPrefs::Direct3D11ReuseDecoderDevice() > 0) { reuseDevice = true; } if (reuseDevice) { if (mCompositorDevice && mCompositorDeviceSupportsVideo && !mDecoderDevice) { mDecoderDevice = mCompositorDevice; RefPtr<ID3D10Multithread> multi; mDecoderDevice->QueryInterface(__uuidof(ID3D10Multithread), getter_AddRefs(multi)); if (multi) { multi->SetMultithreadProtected(TRUE); } } if (mDecoderDevice) { RefPtr<ID3D11Device> dev = mDecoderDevice; return dev.forget(); } } if (!sD3D11CreateDeviceFn) { // We should just be on Windows Vista or XP in this case. return nullptr; } RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter(); if (!adapter) { return nullptr; } HRESULT hr; RefPtr<ID3D11Device> device; UINT flags = D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS | D3D11_CREATE_DEVICE_VIDEO_SUPPORT; if (!CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, flags, hr, device)) { return nullptr; } if (FAILED(hr) || !device || !D3D11Checks::DoesDeviceWork()) { return nullptr; } RefPtr<ID3D10Multithread> multi; device->QueryInterface(__uuidof(ID3D10Multithread), getter_AddRefs(multi)); multi->SetMultithreadProtected(TRUE); if (reuseDevice) { mDecoderDevice = device; } return device; }