mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Move D3D11 device creation out of gfxWindowsPlatform. (bug 1282364 part 3, r=mattwoodrow)
--HG-- extra : rebase_source : 2eadd72cf0c101c61fc3b2ab35d958fb3d540562
This commit is contained in:
parent
572069e3e9
commit
21cab137bc
@ -55,6 +55,12 @@ const char* FeatureStatusToString(FeatureStatus aStatus);
|
||||
bool IsFeatureStatusFailure(FeatureStatus aStatus);
|
||||
bool IsFeatureStatusSuccess(FeatureStatus aStatus);
|
||||
|
||||
enum class TelemetryDeviceCode : uint32_t {
|
||||
Content = 0,
|
||||
Image = 1,
|
||||
D2D1 = 2
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -121,7 +121,7 @@ D3D11Checks::DoesRenderTargetViewNeedRecreating(ID3D11Device *aDevice)
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
D3D11Checks::DoesD3D11DeviceWork()
|
||||
D3D11Checks::DoesDeviceWork()
|
||||
{
|
||||
static bool checked = false;
|
||||
static bool result = false;
|
||||
|
@ -15,7 +15,7 @@ namespace gfx {
|
||||
struct D3D11Checks
|
||||
{
|
||||
static bool DoesRenderTargetViewNeedRecreating(ID3D11Device* aDevice);
|
||||
static bool DoesD3D11DeviceWork();
|
||||
static bool DoesDeviceWork();
|
||||
static bool DoesTextureSharingWork(ID3D11Device *device);
|
||||
static bool DoesAlphaTextureSharingWork(ID3D11Device *device);
|
||||
static void WarnOnAdapterMismatch(ID3D11Device* device);
|
||||
|
@ -4,14 +4,32 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "DeviceManagerD3D11.h"
|
||||
#include "D3D11Checks.h"
|
||||
#include "gfxConfig.h"
|
||||
#include "GfxDriverInfo.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "mozilla/D3DMessageUtils.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#include "mozilla/gfx/GraphicsMessages.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "nsIGfxInfo.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
#include <d3d11.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
using namespace mozilla::widget;
|
||||
|
||||
StaticAutoPtr<DeviceManagerD3D11> DeviceManagerD3D11::sInstance;
|
||||
|
||||
// We don't have access to the D3D11CreateDevice type in gfxWindowsPlatform.h,
|
||||
// since it doesn't include d3d11.h, so we use a static here. It should only
|
||||
// be used within InitializeD3D11.
|
||||
decltype(D3D11CreateDevice)* sD3D11CreateDeviceFn = nullptr;
|
||||
|
||||
/* static */ void
|
||||
DeviceManagerD3D11::Init()
|
||||
{
|
||||
@ -24,63 +42,636 @@ DeviceManagerD3D11::Shutdown()
|
||||
sInstance = nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Device>
|
||||
DeviceManagerD3D11::GetCompositorDevice()
|
||||
DeviceManagerD3D11::DeviceManagerD3D11()
|
||||
: mDeviceLock("gfxWindowsPlatform.mDeviceLock"),
|
||||
mIsWARP(false),
|
||||
mTextureSharingWorks(false)
|
||||
{
|
||||
RefPtr<ID3D11Device> device;
|
||||
if (!gfxWindowsPlatform::GetPlatform()->GetD3D11Device(&device))
|
||||
return nullptr;
|
||||
return device;
|
||||
// Set up the D3D11 feature levels we can ask for.
|
||||
if (IsWin8OrLater()) {
|
||||
mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_11_1);
|
||||
}
|
||||
mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_11_0);
|
||||
mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_10_1);
|
||||
mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_10_0);
|
||||
mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_9_3);
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Device>
|
||||
DeviceManagerD3D11::GetImageBridgeDevice()
|
||||
static inline bool
|
||||
IsWARPStable()
|
||||
{
|
||||
RefPtr<ID3D11Device> device;
|
||||
if (!gfxWindowsPlatform::GetPlatform()->GetD3D11ImageBridgeDevice(&device)) {
|
||||
// It seems like nvdxgiwrap makes a mess of WARP. See bug 1154703.
|
||||
if (!IsWin8OrLater() || GetModuleHandleA("nvdxgiwrap.dll")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceManagerD3D11::CanUseD3D11ImageBridge()
|
||||
{
|
||||
if (XRE_IsContentProcess()) {
|
||||
if (!gfxPlatform::GetPlatform()->GetParentDevicePrefs().useD3D11ImageBridge()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !mIsWARP;
|
||||
}
|
||||
|
||||
void
|
||||
DeviceManagerD3D11::CreateDevices()
|
||||
{
|
||||
FeatureState& d3d11 = gfxConfig::GetFeature(Feature::D3D11_COMPOSITING);
|
||||
MOZ_ASSERT(d3d11.IsEnabled());
|
||||
|
||||
nsModuleHandle d3d11Module(LoadLibrarySystem32(L"d3d11.dll"));
|
||||
sD3D11CreateDeviceFn =
|
||||
(decltype(D3D11CreateDevice)*)GetProcAddress(d3d11Module, "D3D11CreateDevice");
|
||||
|
||||
if (!sD3D11CreateDeviceFn) {
|
||||
// We should just be on Windows Vista or XP in this case.
|
||||
d3d11.SetFailed(FeatureStatus::Unavailable, "Direct3D11 not available on this computer",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_LIB"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if a failure was injected for testing.
|
||||
if (gfxPrefs::DeviceFailForTesting()) {
|
||||
d3d11.SetFailed(FeatureStatus::Failed, "Direct3D11 device failure simulated by preference",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_SIM"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
if (!gfxConfig::UseFallback(Fallback::USE_D3D11_WARP_COMPOSITOR)) {
|
||||
AttemptD3D11DeviceCreation(d3d11);
|
||||
if (d3d11.GetValue() == FeatureStatus::CrashedInHandler) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we failed to get a device, but WARP is allowed and might work,
|
||||
// re-enable D3D11 and switch to WARP.
|
||||
if (!mCompositorDevice && IsWARPStable() && !gfxPrefs::LayersD3D11DisableWARP()) {
|
||||
gfxConfig::Reenable(Feature::D3D11_COMPOSITING, Fallback::USE_D3D11_WARP_COMPOSITOR);
|
||||
}
|
||||
}
|
||||
|
||||
// If that failed, see if we can use WARP.
|
||||
if (gfxConfig::UseFallback(Fallback::USE_D3D11_WARP_COMPOSITOR)) {
|
||||
MOZ_ASSERT(d3d11.IsEnabled());
|
||||
MOZ_ASSERT(!mCompositorDevice);
|
||||
MOZ_ASSERT(IsWARPStable() || gfxPrefs::LayersD3D11ForceWARP());
|
||||
|
||||
AttemptWARPDeviceCreation();
|
||||
if (d3d11.GetValue() == FeatureStatus::CrashedInHandler) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If we still have no device by now, exit.
|
||||
if (!mCompositorDevice) {
|
||||
MOZ_ASSERT(!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING));
|
||||
return;
|
||||
}
|
||||
|
||||
// Either device creation function should have returned Available.
|
||||
MOZ_ASSERT(d3d11.IsEnabled());
|
||||
} else {
|
||||
// Child processes do not need a compositor, but they do need to know
|
||||
// whether the parent process is using WARP and whether or not texture
|
||||
// sharing works.
|
||||
mIsWARP = gfxConfig::UseFallback(Fallback::USE_D3D11_WARP_COMPOSITOR);
|
||||
mTextureSharingWorks =
|
||||
gfxPlatform::GetPlatform()->GetParentDevicePrefs().d3d11TextureSharingWorks();
|
||||
}
|
||||
|
||||
if (CanUseD3D11ImageBridge()) {
|
||||
if (AttemptD3D11ImageBridgeDeviceCreation() == FeatureStatus::CrashedInHandler) {
|
||||
DisableD3D11AfterCrash();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (AttemptD3D11ContentDeviceCreation() == FeatureStatus::CrashedInHandler) {
|
||||
DisableD3D11AfterCrash();
|
||||
return;
|
||||
}
|
||||
|
||||
// We leak these everywhere and we need them our entire runtime anyway, let's
|
||||
// leak it here as well. We keep the pointer to sD3D11CreateDeviceFn around
|
||||
// as well for D2D1 and device resets.
|
||||
d3d11Module.disown();
|
||||
}
|
||||
|
||||
IDXGIAdapter1*
|
||||
DeviceManagerD3D11::GetDXGIAdapter()
|
||||
{
|
||||
if (mAdapter) {
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
nsModuleHandle dxgiModule(LoadLibrarySystem32(L"dxgi.dll"));
|
||||
decltype(CreateDXGIFactory1)* createDXGIFactory1 = (decltype(CreateDXGIFactory1)*)
|
||||
GetProcAddress(dxgiModule, "CreateDXGIFactory1");
|
||||
|
||||
if (!createDXGIFactory1) {
|
||||
return nullptr;
|
||||
}
|
||||
return device;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Device>
|
||||
DeviceManagerD3D11::GetContentDevice()
|
||||
{
|
||||
return gfxWindowsPlatform::GetPlatform()->GetD3D11ContentDevice();
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Device>
|
||||
DeviceManagerD3D11::GetDeviceForCurrentThread()
|
||||
{
|
||||
RefPtr<ID3D11Device> device;
|
||||
if (!gfxWindowsPlatform::GetPlatform()->GetD3D11DeviceForCurrentThread(&device)) {
|
||||
// Try to use a DXGI 1.1 adapter in order to share resources
|
||||
// across processes.
|
||||
RefPtr<IDXGIFactory1> factory1;
|
||||
HRESULT hr = createDXGIFactory1(__uuidof(IDXGIFactory1),
|
||||
getter_AddRefs(factory1));
|
||||
if (FAILED(hr) || !factory1) {
|
||||
// This seems to happen with some people running the iZ3D driver.
|
||||
// They won't get acceleration.
|
||||
return nullptr;
|
||||
}
|
||||
return device;
|
||||
|
||||
if (!XRE_IsContentProcess()) {
|
||||
// In the parent process, we pick the first adapter.
|
||||
if (FAILED(factory1->EnumAdapters1(0, getter_AddRefs(mAdapter)))) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
const DxgiAdapterDesc& parent =
|
||||
gfxPlatform::GetPlatform()->GetParentDevicePrefs().adapter();
|
||||
|
||||
// In the child process, we search for the adapter that matches the parent
|
||||
// process. The first adapter can be mismatched on dual-GPU systems.
|
||||
for (UINT index = 0; ; index++) {
|
||||
RefPtr<IDXGIAdapter1> adapter;
|
||||
if (FAILED(factory1->EnumAdapters1(index, getter_AddRefs(adapter)))) {
|
||||
break;
|
||||
}
|
||||
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
if (SUCCEEDED(adapter->GetDesc(&desc)) &&
|
||||
desc.AdapterLuid.HighPart == parent.AdapterLuid.HighPart &&
|
||||
desc.AdapterLuid.LowPart == parent.AdapterLuid.LowPart &&
|
||||
desc.VendorId == parent.VendorId &&
|
||||
desc.DeviceId == parent.DeviceId)
|
||||
{
|
||||
mAdapter = adapter.forget();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mAdapter) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We leak this module everywhere, we might as well do so here as well.
|
||||
dxgiModule.disown();
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceManagerD3D11::AttemptD3D11DeviceCreationHelper(
|
||||
IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aOutDevice, HRESULT& aResOut)
|
||||
{
|
||||
MOZ_SEH_TRY {
|
||||
aResOut =
|
||||
sD3D11CreateDeviceFn(
|
||||
aAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
|
||||
// Use D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
|
||||
// to prevent bug 1092260. IE 11 also uses this flag.
|
||||
D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
|
||||
mFeatureLevels.Elements(), mFeatureLevels.Length(),
|
||||
D3D11_SDK_VERSION, getter_AddRefs(aOutDevice), nullptr, nullptr);
|
||||
} MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
DeviceManagerD3D11::AttemptD3D11DeviceCreation(FeatureState& d3d11)
|
||||
{
|
||||
RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
|
||||
if (!adapter) {
|
||||
d3d11.SetFailed(FeatureStatus::Unavailable, "Failed to acquire a DXGI adapter",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DXGI"));
|
||||
return;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
RefPtr<ID3D11Device> device;
|
||||
if (!AttemptD3D11DeviceCreationHelper(adapter, device, hr)) {
|
||||
gfxCriticalError() << "Crash during D3D11 device creation";
|
||||
d3d11.SetFailed(FeatureStatus::CrashedInHandler, "Crashed trying to acquire a D3D11 device",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DEVICE1"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (FAILED(hr) || !device) {
|
||||
gfxCriticalError() << "D3D11 device creation failed: " << hexa(hr);
|
||||
d3d11.SetFailed(FeatureStatus::Failed, "Failed to acquire a D3D11 device",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DEVICE2"));
|
||||
return;
|
||||
}
|
||||
if (!D3D11Checks::DoesDeviceWork()) {
|
||||
d3d11.SetFailed(FeatureStatus::Broken, "Direct3D11 device was determined to be broken",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_BROKEN"));
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mDeviceLock);
|
||||
mCompositorDevice = device;
|
||||
}
|
||||
|
||||
// Only test this when not using WARP since it can fail and cause
|
||||
// GetDeviceRemovedReason to return weird values.
|
||||
mTextureSharingWorks = D3D11Checks::DoesTextureSharingWork(mCompositorDevice);
|
||||
|
||||
if (!mTextureSharingWorks) {
|
||||
gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE,
|
||||
FeatureStatus::Broken,
|
||||
"Texture sharing doesn't work");
|
||||
}
|
||||
|
||||
if (D3D11Checks::DoesRenderTargetViewNeedRecreating(mCompositorDevice)) {
|
||||
gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE,
|
||||
FeatureStatus::Broken,
|
||||
"RenderTargetViews need recreating");
|
||||
}
|
||||
|
||||
// It seems like this may only happen when we're using the NVIDIA gpu
|
||||
D3D11Checks::WarnOnAdapterMismatch(mCompositorDevice);
|
||||
|
||||
mCompositorDevice->SetExceptionMode(0);
|
||||
mIsWARP = false;
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceManagerD3D11::AttemptWARPDeviceCreationHelper(
|
||||
ScopedGfxFeatureReporter& aReporterWARP,
|
||||
RefPtr<ID3D11Device>& aOutDevice,
|
||||
HRESULT& aResOut)
|
||||
{
|
||||
MOZ_SEH_TRY {
|
||||
aResOut =
|
||||
sD3D11CreateDeviceFn(
|
||||
nullptr, D3D_DRIVER_TYPE_WARP, nullptr,
|
||||
// Use D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
|
||||
// to prevent bug 1092260. IE 11 also uses this flag.
|
||||
D3D11_CREATE_DEVICE_BGRA_SUPPORT,
|
||||
mFeatureLevels.Elements(), mFeatureLevels.Length(),
|
||||
D3D11_SDK_VERSION, getter_AddRefs(aOutDevice), nullptr, nullptr);
|
||||
|
||||
aReporterWARP.SetSuccessful();
|
||||
} MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
DeviceManagerD3D11::AttemptWARPDeviceCreation()
|
||||
{
|
||||
ScopedGfxFeatureReporter reporterWARP("D3D11-WARP", gfxPrefs::LayersD3D11ForceWARP());
|
||||
FeatureState& d3d11 = gfxConfig::GetFeature(Feature::D3D11_COMPOSITING);
|
||||
|
||||
HRESULT hr;
|
||||
RefPtr<ID3D11Device> device;
|
||||
if (!AttemptWARPDeviceCreationHelper(reporterWARP, device, hr)) {
|
||||
gfxCriticalError() << "Exception occurred initializing WARP D3D11 device!";
|
||||
d3d11.SetFailed(FeatureStatus::CrashedInHandler, "Crashed creating a D3D11 WARP device",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_WARP_DEVICE"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (FAILED(hr) || !device) {
|
||||
// This should always succeed... in theory.
|
||||
gfxCriticalError() << "Failed to initialize WARP D3D11 device! " << hexa(hr);
|
||||
d3d11.SetFailed(FeatureStatus::Failed, "Failed to create a D3D11 WARP device",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_WARP_DEVICE2"));
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mDeviceLock);
|
||||
mCompositorDevice = device;
|
||||
}
|
||||
|
||||
// Only test for texture sharing on Windows 8 since it puts the device into
|
||||
// an unusable state if used on Windows 7
|
||||
if (IsWin8OrLater()) {
|
||||
mTextureSharingWorks = D3D11Checks::DoesTextureSharingWork(mCompositorDevice);
|
||||
}
|
||||
mCompositorDevice->SetExceptionMode(0);
|
||||
mIsWARP = true;
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceManagerD3D11::AttemptD3D11ContentDeviceCreationHelper(
|
||||
IDXGIAdapter1* aAdapter, HRESULT& aResOut)
|
||||
{
|
||||
MOZ_SEH_TRY {
|
||||
aResOut =
|
||||
sD3D11CreateDeviceFn(
|
||||
aAdapter, mIsWARP ? D3D_DRIVER_TYPE_WARP : D3D_DRIVER_TYPE_UNKNOWN,
|
||||
nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT,
|
||||
mFeatureLevels.Elements(), mFeatureLevels.Length(),
|
||||
D3D11_SDK_VERSION, getter_AddRefs(mContentDevice), nullptr, nullptr);
|
||||
|
||||
} MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
FeatureStatus
|
||||
DeviceManagerD3D11::AttemptD3D11ContentDeviceCreation()
|
||||
{
|
||||
RefPtr<IDXGIAdapter1> adapter;
|
||||
if (!mIsWARP) {
|
||||
adapter = GetDXGIAdapter();
|
||||
if (!adapter) {
|
||||
return FeatureStatus::Unavailable;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
if (!AttemptD3D11ContentDeviceCreationHelper(adapter, hr)) {
|
||||
gfxCriticalNote << "Recovered from crash while creating a D3D11 content device";
|
||||
gfxWindowsPlatform::RecordContentDeviceFailure(TelemetryDeviceCode::Content);
|
||||
return FeatureStatus::CrashedInHandler;
|
||||
}
|
||||
|
||||
if (FAILED(hr) || !mContentDevice) {
|
||||
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(mContentDevice)) {
|
||||
mContentDevice = nullptr;
|
||||
return FeatureStatus::Failed;
|
||||
}
|
||||
|
||||
DebugOnly<bool> ok = ContentAdapterIsParentAdapter(mContentDevice);
|
||||
MOZ_ASSERT(ok);
|
||||
}
|
||||
|
||||
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
|
||||
DeviceManagerD3D11::AttemptD3D11ImageBridgeDeviceCreationHelper(
|
||||
IDXGIAdapter1* aAdapter,
|
||||
HRESULT& aResOut)
|
||||
{
|
||||
MOZ_SEH_TRY {
|
||||
aResOut =
|
||||
sD3D11CreateDeviceFn(GetDXGIAdapter(), D3D_DRIVER_TYPE_UNKNOWN, nullptr,
|
||||
D3D11_CREATE_DEVICE_BGRA_SUPPORT,
|
||||
mFeatureLevels.Elements(), mFeatureLevels.Length(),
|
||||
D3D11_SDK_VERSION, getter_AddRefs(mImageBridgeDevice), nullptr, nullptr);
|
||||
} MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
FeatureStatus
|
||||
DeviceManagerD3D11::AttemptD3D11ImageBridgeDeviceCreation()
|
||||
{
|
||||
HRESULT hr;
|
||||
if (!AttemptD3D11ImageBridgeDeviceCreationHelper(GetDXGIAdapter(), hr)) {
|
||||
gfxCriticalNote << "Recovered from crash while creating a D3D11 image bridge device";
|
||||
gfxWindowsPlatform::RecordContentDeviceFailure(TelemetryDeviceCode::Image);
|
||||
return FeatureStatus::CrashedInHandler;
|
||||
}
|
||||
|
||||
if (FAILED(hr) || !mImageBridgeDevice) {
|
||||
gfxCriticalNote << "Failed to create a content image bridge device: " << hexa(hr);
|
||||
gfxWindowsPlatform::RecordContentDeviceFailure(TelemetryDeviceCode::Image);
|
||||
return FeatureStatus::Failed;
|
||||
}
|
||||
|
||||
mImageBridgeDevice->SetExceptionMode(0);
|
||||
if (!D3D11Checks::DoesAlphaTextureSharingWork(mImageBridgeDevice)) {
|
||||
mImageBridgeDevice = nullptr;
|
||||
return FeatureStatus::Failed;
|
||||
}
|
||||
|
||||
if (XRE_IsContentProcess()) {
|
||||
ContentAdapterIsParentAdapter(mImageBridgeDevice);
|
||||
}
|
||||
return FeatureStatus::Available;
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceManagerD3D11::CreateD3D11DecoderDeviceHelper(
|
||||
IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aDevice, HRESULT& aResOut)
|
||||
{
|
||||
MOZ_SEH_TRY{
|
||||
aResOut =
|
||||
sD3D11CreateDeviceFn(
|
||||
aAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
|
||||
D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
|
||||
mFeatureLevels.Elements(), mFeatureLevels.Length(),
|
||||
D3D11_SDK_VERSION, getter_AddRefs(aDevice), nullptr, nullptr);
|
||||
|
||||
} MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Device>
|
||||
DeviceManagerD3D11::CreateDecoderDevice()
|
||||
{
|
||||
return gfxWindowsPlatform::GetPlatform()->CreateD3D11DecoderDevice();
|
||||
if (!sD3D11CreateDeviceFn) {
|
||||
// We should just be on Windows Vista or XP in this case.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
|
||||
if (!adapter) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Device> device;
|
||||
|
||||
HRESULT hr;
|
||||
if (!CreateD3D11DecoderDeviceHelper(adapter, device, hr)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (FAILED(hr) || !device || !D3D11Checks::DoesDeviceWork()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ID3D10Multithread> multi;
|
||||
device->QueryInterface(__uuidof(ID3D10Multithread), getter_AddRefs(multi));
|
||||
|
||||
multi->SetMultithreadProtected(TRUE);
|
||||
return device;
|
||||
}
|
||||
|
||||
void
|
||||
DeviceManagerD3D11::ResetDevices()
|
||||
{
|
||||
MutexAutoLock lock(mDeviceLock);
|
||||
|
||||
mCompositorDevice = nullptr;
|
||||
mContentDevice = nullptr;
|
||||
mImageBridgeDevice = nullptr;
|
||||
Factory::SetDirect3D11Device(nullptr);
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceManagerD3D11::ContentAdapterIsParentAdapter(ID3D11Device* device)
|
||||
{
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
if (!D3D11Checks::GetDxgiDesc(device, &desc)) {
|
||||
gfxCriticalNote << "Could not query device DXGI adapter info";
|
||||
return false;
|
||||
}
|
||||
|
||||
const DxgiAdapterDesc& parent =
|
||||
gfxPlatform::GetPlatform()->GetParentDevicePrefs().adapter();
|
||||
if (desc.VendorId != parent.VendorId ||
|
||||
desc.DeviceId != parent.DeviceId ||
|
||||
desc.SubSysId != parent.SubSysId ||
|
||||
desc.AdapterLuid.HighPart != parent.AdapterLuid.HighPart ||
|
||||
desc.AdapterLuid.LowPart != parent.AdapterLuid.LowPart)
|
||||
{
|
||||
gfxCriticalNote << "VendorIDMismatch P " << hexa(parent.VendorId) << " " << hexa(desc.VendorId);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static DeviceResetReason HResultToResetReason(HRESULT hr)
|
||||
{
|
||||
switch (hr) {
|
||||
case DXGI_ERROR_DEVICE_HUNG:
|
||||
return DeviceResetReason::HUNG;
|
||||
case DXGI_ERROR_DEVICE_REMOVED:
|
||||
return DeviceResetReason::REMOVED;
|
||||
case DXGI_ERROR_DEVICE_RESET:
|
||||
return DeviceResetReason::RESET;
|
||||
case DXGI_ERROR_DRIVER_INTERNAL_ERROR:
|
||||
return DeviceResetReason::DRIVER_ERROR;
|
||||
case DXGI_ERROR_INVALID_CALL:
|
||||
return DeviceResetReason::INVALID_CALL;
|
||||
case E_OUTOFMEMORY:
|
||||
return DeviceResetReason::OUT_OF_MEMORY;
|
||||
default:
|
||||
MOZ_ASSERT(false);
|
||||
}
|
||||
return DeviceResetReason::UNKNOWN;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
DidDeviceReset(RefPtr<ID3D11Device> aDevice, DeviceResetReason* aOutReason)
|
||||
{
|
||||
if (!aDevice) {
|
||||
return false;
|
||||
}
|
||||
HRESULT hr = aDevice->GetDeviceRemovedReason();
|
||||
if (hr == S_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*aOutReason = HResultToResetReason(hr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceManagerD3D11::GetAnyDeviceRemovedReason(DeviceResetReason* aOutReason)
|
||||
{
|
||||
// Note: this can be called off the main thread, so we need to use
|
||||
// our threadsafe getters.
|
||||
if (DidDeviceReset(GetCompositorDevice(), aOutReason) ||
|
||||
DidDeviceReset(GetImageBridgeDevice(), aOutReason) ||
|
||||
DidDeviceReset(GetContentDevice(), aOutReason))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
DeviceManagerD3D11::DisableD3D11AfterCrash()
|
||||
{
|
||||
gfxConfig::Disable(Feature::D3D11_COMPOSITING,
|
||||
FeatureStatus::CrashedInHandler,
|
||||
"Crashed while acquiring a Direct3D11 device",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_CRASH"));
|
||||
ResetDevices();
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Device>
|
||||
DeviceManagerD3D11::GetCompositorDevice()
|
||||
{
|
||||
MutexAutoLock lock(mDeviceLock);
|
||||
return mCompositorDevice;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Device>
|
||||
DeviceManagerD3D11::GetImageBridgeDevice()
|
||||
{
|
||||
MutexAutoLock lock(mDeviceLock);
|
||||
return mImageBridgeDevice;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Device>
|
||||
DeviceManagerD3D11::GetContentDevice()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mContentDevice;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Device>
|
||||
DeviceManagerD3D11::GetDeviceForCurrentThread()
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
return GetContentDevice();
|
||||
}
|
||||
return GetCompositorDevice();
|
||||
}
|
||||
|
||||
unsigned
|
||||
DeviceManagerD3D11::GetD3D11Version() const
|
||||
{
|
||||
return gfxWindowsPlatform::GetPlatform()->GetD3D11Version();
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mCompositorDevice) {
|
||||
return 0;
|
||||
}
|
||||
return mCompositorDevice->GetFeatureLevel();
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceManagerD3D11::TextureSharingWorks() const
|
||||
{
|
||||
return gfxWindowsPlatform::GetPlatform()->CompositorD3D11TextureSharingWorks();
|
||||
return mTextureSharingWorks;
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceManagerD3D11::IsWARP() const
|
||||
{
|
||||
return gfxWindowsPlatform::GetPlatform()->IsWARP();
|
||||
return mIsWARP;
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
|
@ -6,8 +6,12 @@
|
||||
#ifndef mozilla_gfx_thebes_DeviceManagerD3D11_h
|
||||
#define mozilla_gfx_thebes_DeviceManagerD3D11_h
|
||||
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxTelemetry.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <objbase.h>
|
||||
@ -26,7 +30,10 @@
|
||||
struct ID3D11Device;
|
||||
|
||||
namespace mozilla {
|
||||
class ScopedGfxFeatureReporter;
|
||||
|
||||
namespace gfx {
|
||||
class FeatureState;
|
||||
|
||||
class DeviceManagerD3D11 final
|
||||
{
|
||||
@ -34,6 +41,8 @@ public:
|
||||
static void Init();
|
||||
static void Shutdown();
|
||||
|
||||
DeviceManagerD3D11();
|
||||
|
||||
static DeviceManagerD3D11* Get() {
|
||||
return sInstance;
|
||||
}
|
||||
@ -48,8 +57,58 @@ public:
|
||||
bool TextureSharingWorks() const;
|
||||
bool IsWARP() const;
|
||||
|
||||
void CreateDevices();
|
||||
void ResetDevices();
|
||||
|
||||
// Call GetDeviceRemovedReason on each device until one returns
|
||||
// a failure.
|
||||
bool GetAnyDeviceRemovedReason(DeviceResetReason* aOutReason);
|
||||
|
||||
private:
|
||||
IDXGIAdapter1 *GetDXGIAdapter();
|
||||
|
||||
bool CanUseD3D11ImageBridge();
|
||||
|
||||
void DisableD3D11AfterCrash();
|
||||
|
||||
void AttemptD3D11DeviceCreation(mozilla::gfx::FeatureState& d3d11);
|
||||
bool AttemptD3D11DeviceCreationHelper(
|
||||
IDXGIAdapter1* aAdapter,
|
||||
RefPtr<ID3D11Device>& aOutDevice,
|
||||
HRESULT& aResOut);
|
||||
|
||||
void AttemptWARPDeviceCreation();
|
||||
bool AttemptWARPDeviceCreationHelper(
|
||||
mozilla::ScopedGfxFeatureReporter& aReporterWARP,
|
||||
RefPtr<ID3D11Device>& aOutDevice,
|
||||
HRESULT& aResOut);
|
||||
|
||||
bool AttemptD3D11ImageBridgeDeviceCreationHelper(
|
||||
IDXGIAdapter1* aAdapter, HRESULT& aResOut);
|
||||
mozilla::gfx::FeatureStatus AttemptD3D11ImageBridgeDeviceCreation();
|
||||
|
||||
mozilla::gfx::FeatureStatus AttemptD3D11ContentDeviceCreation();
|
||||
bool AttemptD3D11ContentDeviceCreationHelper(
|
||||
IDXGIAdapter1* aAdapter, HRESULT& aResOut);
|
||||
|
||||
// Create a D3D11 device to be used for DXVA decoding.
|
||||
bool CreateD3D11DecoderDeviceHelper(
|
||||
IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aDevice,
|
||||
HRESULT& aResOut);
|
||||
|
||||
bool ContentAdapterIsParentAdapter(ID3D11Device* device);
|
||||
|
||||
private:
|
||||
static StaticAutoPtr<DeviceManagerD3D11> sInstance;
|
||||
|
||||
mozilla::Mutex mDeviceLock;
|
||||
nsTArray<D3D_FEATURE_LEVEL> mFeatureLevels;
|
||||
RefPtr<IDXGIAdapter1> mAdapter;
|
||||
RefPtr<ID3D11Device> mCompositorDevice;
|
||||
RefPtr<ID3D11Device> mContentDevice;
|
||||
RefPtr<ID3D11Device> mImageBridgeDevice;
|
||||
mozilla::Atomic<bool> mIsWARP;
|
||||
mozilla::Atomic<bool> mTextureSharingWorks;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
@ -82,12 +82,6 @@ using namespace mozilla::layers;
|
||||
using namespace mozilla::widget;
|
||||
using namespace mozilla::image;
|
||||
|
||||
enum class TelemetryDeviceCode : uint32_t {
|
||||
Content = 0,
|
||||
Image = 1,
|
||||
D2D1 = 2
|
||||
};
|
||||
|
||||
DCFromDrawTarget::DCFromDrawTarget(DrawTarget& aDrawTarget)
|
||||
{
|
||||
mDC = nullptr;
|
||||
@ -338,10 +332,8 @@ NS_IMPL_ISUPPORTS(D3DSharedTexturesReporter, nsIMemoryReporter)
|
||||
gfxWindowsPlatform::gfxWindowsPlatform()
|
||||
: mRenderMode(RENDER_GDI)
|
||||
, mDeviceLock("gfxWindowsPlatform.mDeviceLock")
|
||||
, mIsWARP(false)
|
||||
, mHasDeviceReset(false)
|
||||
, mHasFakeDeviceReset(false)
|
||||
, mCompositorD3D11TextureSharingWorks(false)
|
||||
, mHasD3D9DeviceReset(false)
|
||||
{
|
||||
mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
|
||||
@ -361,14 +353,9 @@ gfxWindowsPlatform::~gfxWindowsPlatform()
|
||||
{
|
||||
DeviceManagerD3D11::Shutdown();
|
||||
mDeviceManager = nullptr;
|
||||
mD3D11Device = nullptr;
|
||||
mD3D11ContentDevice = nullptr;
|
||||
mD3D11ImageBridgeDevice = nullptr;
|
||||
|
||||
mozilla::gfx::Factory::D2DCleanup();
|
||||
|
||||
mAdapter = nullptr;
|
||||
|
||||
/*
|
||||
* Uninitialize COM
|
||||
*/
|
||||
@ -408,10 +395,11 @@ gfxWindowsPlatform::InitAcceleration()
|
||||
bool
|
||||
gfxWindowsPlatform::CanUseHardwareVideoDecoding()
|
||||
{
|
||||
if (!gfxPrefs::LayersPreferD3D9() && !mCompositorD3D11TextureSharingWorks) {
|
||||
DeviceManagerD3D11* dm = DeviceManagerD3D11::Get();
|
||||
if (!gfxPrefs::LayersPreferD3D9() && !dm->TextureSharingWorks()) {
|
||||
return false;
|
||||
}
|
||||
return !IsWARP() && gfxPlatform::CanUseHardwareVideoDecoding();
|
||||
return !dm->IsWARP() && gfxPlatform::CanUseHardwareVideoDecoding();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -457,15 +445,13 @@ gfxWindowsPlatform::HandleDeviceReset()
|
||||
}
|
||||
|
||||
// Remove devices and adapters.
|
||||
ResetD3D11Devices();
|
||||
mAdapter = nullptr;
|
||||
DeviceManagerD3D11::Get()->ResetDevices();
|
||||
|
||||
// Reset local state. Note: we leave feature status variables as-is. They
|
||||
// will be recomputed by InitializeDevices().
|
||||
mHasDeviceReset = false;
|
||||
mHasFakeDeviceReset = false;
|
||||
mHasD3D9DeviceReset = false;
|
||||
mCompositorD3D11TextureSharingWorks = false;
|
||||
mDeviceResetReason = DeviceResetReason::OK;
|
||||
|
||||
imgLoader::NormalLoader()->ClearCache(true);
|
||||
@ -921,27 +907,6 @@ gfxWindowsPlatform::IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlag
|
||||
return true;
|
||||
}
|
||||
|
||||
static DeviceResetReason HResultToResetReason(HRESULT hr)
|
||||
{
|
||||
switch (hr) {
|
||||
case DXGI_ERROR_DEVICE_HUNG:
|
||||
return DeviceResetReason::HUNG;
|
||||
case DXGI_ERROR_DEVICE_REMOVED:
|
||||
return DeviceResetReason::REMOVED;
|
||||
case DXGI_ERROR_DEVICE_RESET:
|
||||
return DeviceResetReason::RESET;
|
||||
case DXGI_ERROR_DRIVER_INTERNAL_ERROR:
|
||||
return DeviceResetReason::DRIVER_ERROR;
|
||||
case DXGI_ERROR_INVALID_CALL:
|
||||
return DeviceResetReason::INVALID_CALL;
|
||||
case E_OUTOFMEMORY:
|
||||
return DeviceResetReason::OUT_OF_MEMORY;
|
||||
default:
|
||||
MOZ_ASSERT(false);
|
||||
}
|
||||
return DeviceResetReason::UNKNOWN;
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::CompositorUpdated()
|
||||
{
|
||||
@ -949,20 +914,6 @@ gfxWindowsPlatform::CompositorUpdated()
|
||||
UpdateRenderMode();
|
||||
}
|
||||
|
||||
bool
|
||||
gfxWindowsPlatform::IsDeviceReset(HRESULT hr, DeviceResetReason* aResetReason)
|
||||
{
|
||||
if (hr != S_OK) {
|
||||
mDeviceResetReason = HResultToResetReason(hr);
|
||||
mHasDeviceReset = true;
|
||||
if (aResetReason) {
|
||||
*aResetReason = mDeviceResetReason;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::TestDeviceReset(DeviceResetReason aReason)
|
||||
{
|
||||
@ -987,18 +938,14 @@ gfxWindowsPlatform::DidRenderingDeviceReset(DeviceResetReason* aResetReason)
|
||||
*aResetReason = DeviceResetReason::OK;
|
||||
}
|
||||
|
||||
if (mD3D11Device) {
|
||||
HRESULT hr = mD3D11Device->GetDeviceRemovedReason();
|
||||
if (IsDeviceReset(hr, aResetReason)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (mD3D11ContentDevice) {
|
||||
HRESULT hr = mD3D11ContentDevice->GetDeviceRemovedReason();
|
||||
if (IsDeviceReset(hr, aResetReason)) {
|
||||
return true;
|
||||
if (DeviceManagerD3D11::Get()->GetAnyDeviceRemovedReason(&mDeviceResetReason)) {
|
||||
mHasDeviceReset = true;
|
||||
if (aResetReason) {
|
||||
*aResetReason = mDeviceResetReason;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mHasD3D9DeviceReset) {
|
||||
return true;
|
||||
}
|
||||
@ -1416,38 +1363,6 @@ gfxWindowsPlatform::GetD3D9DeviceManager()
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
gfxWindowsPlatform::GetD3D11Device(RefPtr<ID3D11Device>* aOutDevice)
|
||||
{
|
||||
MutexAutoLock lock(mDeviceLock);
|
||||
*aOutDevice = mD3D11Device;
|
||||
return !!mD3D11Device;
|
||||
}
|
||||
|
||||
ID3D11Device*
|
||||
gfxWindowsPlatform::GetD3D11ContentDevice()
|
||||
{
|
||||
return mD3D11ContentDevice;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxWindowsPlatform::GetD3D11ImageBridgeDevice(RefPtr<ID3D11Device>* aOutDevice)
|
||||
{
|
||||
MutexAutoLock lock(mDeviceLock);
|
||||
*aOutDevice = mD3D11ImageBridgeDevice;
|
||||
return !!mD3D11ImageBridgeDevice;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxWindowsPlatform::GetD3D11DeviceForCurrentThread(RefPtr<ID3D11Device>* aOutDevice)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
*aOutDevice = mD3D11ContentDevice;
|
||||
return !!mD3D11ContentDevice;
|
||||
}
|
||||
return GetD3D11ImageBridgeDevice(aOutDevice);
|
||||
}
|
||||
|
||||
ReadbackManagerD3D11*
|
||||
gfxWindowsPlatform::GetReadbackManager()
|
||||
{
|
||||
@ -1475,70 +1390,6 @@ gfxWindowsPlatform::IsOptimus()
|
||||
return knowIsOptimus;
|
||||
}
|
||||
|
||||
IDXGIAdapter1*
|
||||
gfxWindowsPlatform::GetDXGIAdapter()
|
||||
{
|
||||
if (mAdapter) {
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
nsModuleHandle dxgiModule(LoadLibrarySystem32(L"dxgi.dll"));
|
||||
decltype(CreateDXGIFactory1)* createDXGIFactory1 = (decltype(CreateDXGIFactory1)*)
|
||||
GetProcAddress(dxgiModule, "CreateDXGIFactory1");
|
||||
|
||||
if (!createDXGIFactory1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Try to use a DXGI 1.1 adapter in order to share resources
|
||||
// across processes.
|
||||
RefPtr<IDXGIFactory1> factory1;
|
||||
HRESULT hr = createDXGIFactory1(__uuidof(IDXGIFactory1),
|
||||
getter_AddRefs(factory1));
|
||||
if (FAILED(hr) || !factory1) {
|
||||
// This seems to happen with some people running the iZ3D driver.
|
||||
// They won't get acceleration.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!XRE_IsContentProcess()) {
|
||||
// In the parent process, we pick the first adapter.
|
||||
if (FAILED(factory1->EnumAdapters1(0, getter_AddRefs(mAdapter)))) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
const DxgiAdapterDesc& parent = GetParentDevicePrefs().adapter();
|
||||
|
||||
// In the child process, we search for the adapter that matches the parent
|
||||
// process. The first adapter can be mismatched on dual-GPU systems.
|
||||
for (UINT index = 0; ; index++) {
|
||||
RefPtr<IDXGIAdapter1> adapter;
|
||||
if (FAILED(factory1->EnumAdapters1(index, getter_AddRefs(adapter)))) {
|
||||
break;
|
||||
}
|
||||
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
if (SUCCEEDED(adapter->GetDesc(&desc)) &&
|
||||
desc.AdapterLuid.HighPart == parent.AdapterLuid.HighPart &&
|
||||
desc.AdapterLuid.LowPart == parent.AdapterLuid.LowPart &&
|
||||
desc.VendorId == parent.VendorId &&
|
||||
desc.DeviceId == parent.DeviceId)
|
||||
{
|
||||
mAdapter = adapter.forget();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mAdapter) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We leak this module everywhere, we might as well do so here as well.
|
||||
dxgiModule.disown();
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsWARPStable()
|
||||
{
|
||||
@ -1698,176 +1549,8 @@ gfxWindowsPlatform::UpdateDeviceInitData()
|
||||
return true;
|
||||
}
|
||||
|
||||
// We don't have access to the D3D11CreateDevice type in gfxWindowsPlatform.h,
|
||||
// since it doesn't include d3d11.h, so we use a static here. It should only
|
||||
// be used within InitializeD3D11.
|
||||
decltype(D3D11CreateDevice)* sD3D11CreateDeviceFn = nullptr;
|
||||
|
||||
bool
|
||||
gfxWindowsPlatform::AttemptD3D11DeviceCreationHelper(
|
||||
IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aOutDevice, HRESULT& aResOut)
|
||||
{
|
||||
MOZ_SEH_TRY {
|
||||
aResOut =
|
||||
sD3D11CreateDeviceFn(
|
||||
aAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
|
||||
// Use D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
|
||||
// to prevent bug 1092260. IE 11 also uses this flag.
|
||||
D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
|
||||
mFeatureLevels.Elements(), mFeatureLevels.Length(),
|
||||
D3D11_SDK_VERSION, getter_AddRefs(aOutDevice), nullptr, nullptr);
|
||||
} MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::AttemptD3D11DeviceCreation(FeatureState& d3d11)
|
||||
{
|
||||
RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
|
||||
if (!adapter) {
|
||||
d3d11.SetFailed(FeatureStatus::Unavailable, "Failed to acquire a DXGI adapter",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DXGI"));
|
||||
return;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
RefPtr<ID3D11Device> device;
|
||||
if (!AttemptD3D11DeviceCreationHelper(adapter, device, hr)) {
|
||||
gfxCriticalError() << "Crash during D3D11 device creation";
|
||||
d3d11.SetFailed(FeatureStatus::CrashedInHandler, "Crashed trying to acquire a D3D11 device",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DEVICE1"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (FAILED(hr) || !device) {
|
||||
gfxCriticalError() << "D3D11 device creation failed: " << hexa(hr);
|
||||
d3d11.SetFailed(FeatureStatus::Failed, "Failed to acquire a D3D11 device",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DEVICE2"));
|
||||
return;
|
||||
}
|
||||
if (!D3D11Checks::DoesD3D11DeviceWork()) {
|
||||
d3d11.SetFailed(FeatureStatus::Broken, "Direct3D11 device was determined to be broken",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_BROKEN"));
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mDeviceLock);
|
||||
mD3D11Device = device;
|
||||
}
|
||||
|
||||
// Only test this when not using WARP since it can fail and cause
|
||||
// GetDeviceRemovedReason to return weird values.
|
||||
mCompositorD3D11TextureSharingWorks =
|
||||
D3D11Checks::DoesTextureSharingWork(mD3D11Device);
|
||||
|
||||
if (!mCompositorD3D11TextureSharingWorks) {
|
||||
gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE,
|
||||
FeatureStatus::Broken,
|
||||
"Texture sharing doesn't work");
|
||||
}
|
||||
|
||||
if (D3D11Checks::DoesRenderTargetViewNeedRecreating(mD3D11Device)) {
|
||||
gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE,
|
||||
FeatureStatus::Broken,
|
||||
"RenderTargetViews need recreating");
|
||||
}
|
||||
|
||||
// It seems like this may only happen when we're using the NVIDIA gpu
|
||||
D3D11Checks::WarnOnAdapterMismatch(mD3D11Device);
|
||||
|
||||
mD3D11Device->SetExceptionMode(0);
|
||||
mIsWARP = false;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxWindowsPlatform::AttemptWARPDeviceCreationHelper(
|
||||
ScopedGfxFeatureReporter& aReporterWARP,
|
||||
RefPtr<ID3D11Device>& aOutDevice,
|
||||
HRESULT& aResOut)
|
||||
{
|
||||
MOZ_SEH_TRY {
|
||||
aResOut =
|
||||
sD3D11CreateDeviceFn(
|
||||
nullptr, D3D_DRIVER_TYPE_WARP, nullptr,
|
||||
// Use D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
|
||||
// to prevent bug 1092260. IE 11 also uses this flag.
|
||||
D3D11_CREATE_DEVICE_BGRA_SUPPORT,
|
||||
mFeatureLevels.Elements(), mFeatureLevels.Length(),
|
||||
D3D11_SDK_VERSION, getter_AddRefs(aOutDevice), nullptr, nullptr);
|
||||
|
||||
aReporterWARP.SetSuccessful();
|
||||
} MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::AttemptWARPDeviceCreation()
|
||||
{
|
||||
ScopedGfxFeatureReporter reporterWARP("D3D11-WARP", gfxPrefs::LayersD3D11ForceWARP());
|
||||
FeatureState& d3d11 = gfxConfig::GetFeature(Feature::D3D11_COMPOSITING);
|
||||
|
||||
HRESULT hr;
|
||||
RefPtr<ID3D11Device> device;
|
||||
if (!AttemptWARPDeviceCreationHelper(reporterWARP, device, hr)) {
|
||||
gfxCriticalError() << "Exception occurred initializing WARP D3D11 device!";
|
||||
d3d11.SetFailed(FeatureStatus::CrashedInHandler, "Crashed creating a D3D11 WARP device",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_WARP_DEVICE"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (FAILED(hr) || !device) {
|
||||
// This should always succeed... in theory.
|
||||
gfxCriticalError() << "Failed to initialize WARP D3D11 device! " << hexa(hr);
|
||||
d3d11.SetFailed(FeatureStatus::Failed, "Failed to create a D3D11 WARP device",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_WARP_DEVICE2"));
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mDeviceLock);
|
||||
mD3D11Device = device;
|
||||
}
|
||||
|
||||
// Only test for texture sharing on Windows 8 since it puts the device into
|
||||
// an unusable state if used on Windows 7
|
||||
if (IsWin8OrLater()) {
|
||||
mCompositorD3D11TextureSharingWorks =
|
||||
D3D11Checks::DoesTextureSharingWork(mD3D11Device);
|
||||
}
|
||||
mD3D11Device->SetExceptionMode(0);
|
||||
mIsWARP = true;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxWindowsPlatform::ContentAdapterIsParentAdapter(ID3D11Device* device)
|
||||
{
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
if (!D3D11Checks::GetDxgiDesc(device, &desc)) {
|
||||
gfxCriticalNote << "Could not query device DXGI adapter info";
|
||||
return false;
|
||||
}
|
||||
|
||||
const DxgiAdapterDesc& parent = GetParentDevicePrefs().adapter();
|
||||
if (desc.VendorId != parent.VendorId ||
|
||||
desc.DeviceId != parent.DeviceId ||
|
||||
desc.SubSysId != parent.SubSysId ||
|
||||
desc.AdapterLuid.HighPart != parent.AdapterLuid.HighPart ||
|
||||
desc.AdapterLuid.LowPart != parent.AdapterLuid.LowPart)
|
||||
{
|
||||
gfxCriticalNote << "VendorIDMismatch P " << hexa(parent.VendorId) << " " << hexa(desc.VendorId);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
RecordContentDeviceFailure(TelemetryDeviceCode aDevice)
|
||||
/* static */ void
|
||||
gfxWindowsPlatform::RecordContentDeviceFailure(TelemetryDeviceCode aDevice)
|
||||
{
|
||||
// If the parent process fails to acquire a device, we record this
|
||||
// normally as part of the environment. The exceptional case we're
|
||||
@ -1880,119 +1563,6 @@ RecordContentDeviceFailure(TelemetryDeviceCode aDevice)
|
||||
Telemetry::Accumulate(Telemetry::GFX_CONTENT_FAILED_TO_ACQUIRE_DEVICE, uint32_t(aDevice));
|
||||
}
|
||||
|
||||
bool
|
||||
gfxWindowsPlatform::AttemptD3D11ContentDeviceCreationHelper(
|
||||
IDXGIAdapter1* aAdapter, HRESULT& aResOut)
|
||||
{
|
||||
MOZ_SEH_TRY {
|
||||
aResOut =
|
||||
sD3D11CreateDeviceFn(
|
||||
aAdapter, mIsWARP ? D3D_DRIVER_TYPE_WARP : D3D_DRIVER_TYPE_UNKNOWN,
|
||||
nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT,
|
||||
mFeatureLevels.Elements(), mFeatureLevels.Length(),
|
||||
D3D11_SDK_VERSION, getter_AddRefs(mD3D11ContentDevice), nullptr, nullptr);
|
||||
|
||||
} MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
FeatureStatus
|
||||
gfxWindowsPlatform::AttemptD3D11ContentDeviceCreation()
|
||||
{
|
||||
RefPtr<IDXGIAdapter1> adapter;
|
||||
if (!mIsWARP) {
|
||||
adapter = GetDXGIAdapter();
|
||||
if (!adapter) {
|
||||
return FeatureStatus::Unavailable;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
if (!AttemptD3D11ContentDeviceCreationHelper(adapter, hr)) {
|
||||
gfxCriticalNote << "Recovered from crash while creating a D3D11 content device";
|
||||
RecordContentDeviceFailure(TelemetryDeviceCode::Content);
|
||||
return FeatureStatus::CrashedInHandler;
|
||||
}
|
||||
|
||||
if (FAILED(hr) || !mD3D11ContentDevice) {
|
||||
gfxCriticalNote << "Failed to create a D3D11 content device: " << hexa(hr);
|
||||
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(mD3D11ContentDevice)) {
|
||||
mD3D11ContentDevice = nullptr;
|
||||
return FeatureStatus::Failed;
|
||||
}
|
||||
|
||||
DebugOnly<bool> ok = ContentAdapterIsParentAdapter(mD3D11ContentDevice);
|
||||
MOZ_ASSERT(ok);
|
||||
}
|
||||
|
||||
mD3D11ContentDevice->SetExceptionMode(0);
|
||||
|
||||
RefPtr<ID3D10Multithread> multi;
|
||||
hr = mD3D11ContentDevice->QueryInterface(__uuidof(ID3D10Multithread), getter_AddRefs(multi));
|
||||
if (SUCCEEDED(hr) && multi) {
|
||||
multi->SetMultithreadProtected(TRUE);
|
||||
}
|
||||
return FeatureStatus::Available;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxWindowsPlatform::AttemptD3D11ImageBridgeDeviceCreationHelper(
|
||||
IDXGIAdapter1* aAdapter,
|
||||
HRESULT& aResOut)
|
||||
{
|
||||
MOZ_SEH_TRY {
|
||||
aResOut =
|
||||
sD3D11CreateDeviceFn(GetDXGIAdapter(), D3D_DRIVER_TYPE_UNKNOWN, nullptr,
|
||||
D3D11_CREATE_DEVICE_BGRA_SUPPORT,
|
||||
mFeatureLevels.Elements(), mFeatureLevels.Length(),
|
||||
D3D11_SDK_VERSION, getter_AddRefs(mD3D11ImageBridgeDevice), nullptr, nullptr);
|
||||
} MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
FeatureStatus
|
||||
gfxWindowsPlatform::AttemptD3D11ImageBridgeDeviceCreation()
|
||||
{
|
||||
HRESULT hr;
|
||||
if (!AttemptD3D11ImageBridgeDeviceCreationHelper(GetDXGIAdapter(), hr)) {
|
||||
gfxCriticalNote << "Recovered from crash while creating a D3D11 image bridge device";
|
||||
RecordContentDeviceFailure(TelemetryDeviceCode::Image);
|
||||
return FeatureStatus::CrashedInHandler;
|
||||
}
|
||||
|
||||
if (FAILED(hr) || !mD3D11ImageBridgeDevice) {
|
||||
gfxCriticalNote << "Failed to create a content image bridge device: " << hexa(hr);
|
||||
RecordContentDeviceFailure(TelemetryDeviceCode::Image);
|
||||
return FeatureStatus::Failed;
|
||||
}
|
||||
|
||||
mD3D11ImageBridgeDevice->SetExceptionMode(0);
|
||||
if (!D3D11Checks::DoesAlphaTextureSharingWork(mD3D11ImageBridgeDevice)) {
|
||||
mD3D11ImageBridgeDevice = nullptr;
|
||||
return FeatureStatus::Failed;
|
||||
}
|
||||
|
||||
if (XRE_IsContentProcess()) {
|
||||
ContentAdapterIsParentAdapter(mD3D11ImageBridgeDevice);
|
||||
}
|
||||
return FeatureStatus::Available;
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::InitializeDevices()
|
||||
{
|
||||
@ -2039,17 +1609,6 @@ gfxWindowsPlatform::InitializeDevices()
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
gfxWindowsPlatform::CanUseD3D11ImageBridge()
|
||||
{
|
||||
if (XRE_IsContentProcess()) {
|
||||
if (!GetParentDevicePrefs().useD3D11ImageBridge()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !mIsWARP;
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::InitializeD3D11()
|
||||
{
|
||||
@ -2059,110 +1618,12 @@ gfxWindowsPlatform::InitializeD3D11()
|
||||
// blacklisted, then this function will abort if WARP is disabled, causing us
|
||||
// to fallback to D3D9 or Basic layers. If WARP is not disabled it will use
|
||||
// a WARP device which should always be available on Windows 7 and higher.
|
||||
|
||||
// Check if D3D11 is supported on this hardware.
|
||||
FeatureState& d3d11 = gfxConfig::GetFeature(Feature::D3D11_COMPOSITING);
|
||||
if (!d3d11.IsEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if D3D11 is available on this system.
|
||||
nsModuleHandle d3d11Module(LoadLibrarySystem32(L"d3d11.dll"));
|
||||
sD3D11CreateDeviceFn =
|
||||
(decltype(D3D11CreateDevice)*)GetProcAddress(d3d11Module, "D3D11CreateDevice");
|
||||
if (!sD3D11CreateDeviceFn) {
|
||||
// We should just be on Windows Vista or XP in this case.
|
||||
d3d11.SetFailed(FeatureStatus::Unavailable, "Direct3D11 not available on this computer",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_LIB"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if a failure was injected for testing.
|
||||
if (gfxPrefs::DeviceFailForTesting()) {
|
||||
d3d11.SetFailed(FeatureStatus::Failed, "Direct3D11 device failure simulated by preference",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_SIM"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
if (!gfxConfig::UseFallback(Fallback::USE_D3D11_WARP_COMPOSITOR)) {
|
||||
AttemptD3D11DeviceCreation(d3d11);
|
||||
if (d3d11.GetValue() == FeatureStatus::CrashedInHandler) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we failed to get a device, but WARP is allowed and might work,
|
||||
// re-enable D3D11 and switch to WARP.
|
||||
if (!mD3D11Device && IsWARPStable() && !gfxPrefs::LayersD3D11DisableWARP()) {
|
||||
gfxConfig::Reenable(Feature::D3D11_COMPOSITING, Fallback::USE_D3D11_WARP_COMPOSITOR);
|
||||
}
|
||||
}
|
||||
|
||||
// If that failed, see if we can use WARP.
|
||||
if (gfxConfig::UseFallback(Fallback::USE_D3D11_WARP_COMPOSITOR)) {
|
||||
MOZ_ASSERT(d3d11.IsEnabled());
|
||||
MOZ_ASSERT(!mD3D11Device);
|
||||
MOZ_ASSERT(IsWARPStable() || gfxPrefs::LayersD3D11ForceWARP());
|
||||
|
||||
AttemptWARPDeviceCreation();
|
||||
if (d3d11.GetValue() == FeatureStatus::CrashedInHandler) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If we still have no device by now, exit.
|
||||
if (!mD3D11Device) {
|
||||
MOZ_ASSERT(!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING));
|
||||
return;
|
||||
}
|
||||
|
||||
// Either device creation function should have returned Available.
|
||||
MOZ_ASSERT(d3d11.IsEnabled());
|
||||
} else {
|
||||
// Child processes do not need a compositor, but they do need to know
|
||||
// whether the parent process is using WARP and whether or not texture
|
||||
// sharing works.
|
||||
mIsWARP = gfxConfig::UseFallback(Fallback::USE_D3D11_WARP_COMPOSITOR);
|
||||
mCompositorD3D11TextureSharingWorks = GetParentDevicePrefs().d3d11TextureSharingWorks();
|
||||
}
|
||||
|
||||
if (CanUseD3D11ImageBridge()) {
|
||||
if (AttemptD3D11ImageBridgeDeviceCreation() == FeatureStatus::CrashedInHandler) {
|
||||
DisableD3D11AfterCrash();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (AttemptD3D11ContentDeviceCreation() == FeatureStatus::CrashedInHandler) {
|
||||
DisableD3D11AfterCrash();
|
||||
return;
|
||||
}
|
||||
|
||||
// We leak these everywhere and we need them our entire runtime anyway, let's
|
||||
// leak it here as well. We keep the pointer to sD3D11CreateDeviceFn around
|
||||
// as well for D2D1 and device resets.
|
||||
d3d11Module.disown();
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::DisableD3D11AfterCrash()
|
||||
{
|
||||
gfxConfig::Disable(Feature::D3D11_COMPOSITING,
|
||||
FeatureStatus::CrashedInHandler,
|
||||
"Crashed while acquiring a Direct3D11 device",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_CRASH"));
|
||||
ResetD3D11Devices();
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::ResetD3D11Devices()
|
||||
{
|
||||
MutexAutoLock lock(mDeviceLock);
|
||||
|
||||
mD3D11Device = nullptr;
|
||||
mD3D11ContentDevice = nullptr;
|
||||
mD3D11ImageBridgeDevice = nullptr;
|
||||
Factory::SetDirect3D11Device(nullptr);
|
||||
DeviceManagerD3D11::Get()->CreateDevices();
|
||||
}
|
||||
|
||||
void
|
||||
@ -2204,9 +1665,11 @@ gfxWindowsPlatform::InitializeD2D()
|
||||
|
||||
FeatureState& d2d1 = gfxConfig::GetFeature(Feature::DIRECT2D);
|
||||
|
||||
DeviceManagerD3D11* dm = DeviceManagerD3D11::Get();
|
||||
|
||||
// We don't know this value ahead of time, but the user can force-override
|
||||
// it, so we use Disable instead of SetFailed.
|
||||
if (mIsWARP) {
|
||||
if (dm->IsWARP()) {
|
||||
d2d1.Disable(FeatureStatus::Blocked, "Direct2D is not compatible with Direct3D11 WARP",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_WARP_BLOCK"));
|
||||
}
|
||||
@ -2222,13 +1685,13 @@ gfxWindowsPlatform::InitializeD2D()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mD3D11ContentDevice) {
|
||||
if (!dm->GetContentDevice()) {
|
||||
d2d1.SetFailed(FeatureStatus::Failed, "Failed to acquire a Direct3D 11 content device",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_DEVICE"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mCompositorD3D11TextureSharingWorks) {
|
||||
if (!dm->TextureSharingWorks()) {
|
||||
d2d1.SetFailed(FeatureStatus::Failed, "Direct3D11 device does not support texture sharing",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_TXT_SHARING"));
|
||||
return;
|
||||
@ -2242,7 +1705,8 @@ gfxWindowsPlatform::InitializeD2D()
|
||||
}
|
||||
|
||||
// Verify that Direct2D device creation succeeded.
|
||||
if (!Factory::SetDirect3D11Device(mD3D11ContentDevice)) {
|
||||
RefPtr<ID3D11Device> contentDevice = dm->GetContentDevice();
|
||||
if (!Factory::SetDirect3D11Device(contentDevice)) {
|
||||
d2d1.SetFailed(FeatureStatus::Failed, "Failed to create a Direct2D device",
|
||||
NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_CREATE_FAILED"));
|
||||
return;
|
||||
@ -2252,57 +1716,6 @@ gfxWindowsPlatform::InitializeD2D()
|
||||
d2d1_1.SetSuccessful();
|
||||
}
|
||||
|
||||
bool
|
||||
gfxWindowsPlatform::CreateD3D11DecoderDeviceHelper(
|
||||
IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aDevice, HRESULT& aResOut)
|
||||
{
|
||||
MOZ_SEH_TRY{
|
||||
aResOut =
|
||||
sD3D11CreateDeviceFn(
|
||||
aAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
|
||||
D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
|
||||
mFeatureLevels.Elements(), mFeatureLevels.Length(),
|
||||
D3D11_SDK_VERSION, getter_AddRefs(aDevice), nullptr, nullptr);
|
||||
|
||||
} MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<ID3D11Device>
|
||||
gfxWindowsPlatform::CreateD3D11DecoderDevice()
|
||||
{
|
||||
if (!sD3D11CreateDeviceFn) {
|
||||
// We should just be on Windows Vista or XP in this case.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
|
||||
|
||||
if (!adapter) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Device> device;
|
||||
|
||||
HRESULT hr;
|
||||
if (!CreateD3D11DecoderDeviceHelper(adapter, device, hr)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (FAILED(hr) || !device || !D3D11Checks::DoesD3D11DeviceWork()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ID3D10Multithread> multi;
|
||||
device->QueryInterface(__uuidof(ID3D10Multithread), getter_AddRefs(multi));
|
||||
|
||||
multi->SetMultithreadProtected(TRUE);
|
||||
|
||||
return device.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
gfxWindowsPlatform::DwmCompositionEnabled()
|
||||
{
|
||||
@ -2602,7 +2015,7 @@ gfxWindowsPlatform::GetAcceleratedCompositorBackends(nsTArray<LayersBackend>& aB
|
||||
aBackends.AppendElement(LayersBackend::LAYERS_D3D9);
|
||||
}
|
||||
|
||||
if (mD3D11Device) {
|
||||
if (DeviceManagerD3D11::Get()->GetCompositorDevice()) {
|
||||
aBackends.AppendElement(LayersBackend::LAYERS_D3D11);
|
||||
} else {
|
||||
NS_WARNING("Direct3D 11-accelerated layers are not supported on this system.");
|
||||
@ -2613,16 +2026,6 @@ gfxWindowsPlatform::GetAcceleratedCompositorBackends(nsTArray<LayersBackend>& aB
|
||||
}
|
||||
}
|
||||
|
||||
unsigned
|
||||
gfxWindowsPlatform::GetD3D11Version()
|
||||
{
|
||||
RefPtr<ID3D11Device> device;
|
||||
if (!GetD3D11Device(&device)) {
|
||||
return 0;
|
||||
}
|
||||
return device->GetFeatureLevel();
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::GetDeviceInitData(DeviceInitData* aOut)
|
||||
{
|
||||
@ -2636,15 +2039,17 @@ gfxWindowsPlatform::GetDeviceInitData(DeviceInitData* aOut)
|
||||
return;
|
||||
}
|
||||
|
||||
DeviceManagerD3D11* dm = DeviceManagerD3D11::Get();
|
||||
|
||||
aOut->useD3D11() = true;
|
||||
aOut->useD3D11ImageBridge() = !!mD3D11ImageBridgeDevice;
|
||||
aOut->d3d11TextureSharingWorks() = mCompositorD3D11TextureSharingWorks;
|
||||
aOut->useD3D11WARP() = mIsWARP;
|
||||
aOut->useD3D11ImageBridge() = !!dm->GetImageBridgeDevice();
|
||||
aOut->d3d11TextureSharingWorks() = dm->TextureSharingWorks();
|
||||
aOut->useD3D11WARP() = dm->IsWARP();
|
||||
aOut->useD2D1() = gfxConfig::IsEnabled(Feature::DIRECT2D);
|
||||
|
||||
if (mD3D11Device) {
|
||||
if (RefPtr<ID3D11Device> device = dm->GetCompositorDevice()) {
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
if (!D3D11Checks::GetDxgiDesc(mD3D11Device, &desc)) {
|
||||
if (!D3D11Checks::GetDxgiDesc(device, &desc)) {
|
||||
return;
|
||||
}
|
||||
aOut->adapter() = DxgiAdapterDesc::From(desc);
|
||||
@ -2654,7 +2059,8 @@ gfxWindowsPlatform::GetDeviceInitData(DeviceInitData* aOut)
|
||||
bool
|
||||
gfxWindowsPlatform::SupportsPluginDirectDXGIDrawing()
|
||||
{
|
||||
if (!GetD3D11ContentDevice() || !CompositorD3D11TextureSharingWorks()) {
|
||||
DeviceManagerD3D11* dm = DeviceManagerD3D11::Get();
|
||||
if (!dm->GetContentDevice() || !dm->TextureSharingWorks()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -210,26 +210,6 @@ public:
|
||||
IDWriteRenderingParams *GetRenderingParams(TextRenderingMode aRenderMode)
|
||||
{ return mRenderingParams[aRenderMode]; }
|
||||
|
||||
private:
|
||||
bool GetD3D11Device(RefPtr<ID3D11Device>* aOutDevice);
|
||||
bool GetD3D11ImageBridgeDevice(RefPtr<ID3D11Device>* aOutDevice);
|
||||
bool GetD3D11DeviceForCurrentThread(RefPtr<ID3D11Device>* aOutDevice);
|
||||
ID3D11Device *GetD3D11ContentDevice();
|
||||
already_AddRefed<ID3D11Device> CreateD3D11DecoderDevice();
|
||||
unsigned GetD3D11Version();
|
||||
|
||||
// Create a D3D11 device to be used for DXVA decoding.
|
||||
bool CreateD3D11DecoderDeviceHelper(
|
||||
IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aDevice,
|
||||
HRESULT& aResOut);
|
||||
|
||||
// Returns whether the compositor's D3D11 device supports texture sharing.
|
||||
bool CompositorD3D11TextureSharingWorks() const {
|
||||
return mCompositorD3D11TextureSharingWorks;
|
||||
}
|
||||
|
||||
bool IsWARP() const { return mIsWARP; }
|
||||
|
||||
public:
|
||||
void OnDeviceManagerDestroy(mozilla::layers::DeviceManagerD3D9* aDeviceManager);
|
||||
already_AddRefed<mozilla::layers::DeviceManagerD3D9> GetD3D9DeviceManager();
|
||||
@ -265,6 +245,8 @@ public:
|
||||
}
|
||||
bool SupportsPluginDirectDXGIDrawing();
|
||||
|
||||
static void RecordContentDeviceFailure(mozilla::gfx::TelemetryDeviceCode aDevice);
|
||||
|
||||
protected:
|
||||
bool AccelerateLayersByDefault() override {
|
||||
return true;
|
||||
@ -296,50 +278,14 @@ private:
|
||||
void InitializeD3D11Config();
|
||||
void InitializeD2DConfig();
|
||||
|
||||
void AttemptD3D11DeviceCreation(mozilla::gfx::FeatureState& d3d11);
|
||||
bool AttemptD3D11DeviceCreationHelper(
|
||||
IDXGIAdapter1* aAdapter,
|
||||
RefPtr<ID3D11Device>& aOutDevice,
|
||||
HRESULT& aResOut);
|
||||
|
||||
void AttemptWARPDeviceCreation();
|
||||
bool AttemptWARPDeviceCreationHelper(
|
||||
mozilla::ScopedGfxFeatureReporter& aReporterWARP,
|
||||
RefPtr<ID3D11Device>& aOutDevice,
|
||||
HRESULT& aResOut);
|
||||
|
||||
bool AttemptD3D11ImageBridgeDeviceCreationHelper(
|
||||
IDXGIAdapter1* aAdapter, HRESULT& aResOut);
|
||||
mozilla::gfx::FeatureStatus AttemptD3D11ImageBridgeDeviceCreation();
|
||||
|
||||
mozilla::gfx::FeatureStatus AttemptD3D11ContentDeviceCreation();
|
||||
bool AttemptD3D11ContentDeviceCreationHelper(
|
||||
IDXGIAdapter1* aAdapter, HRESULT& aResOut);
|
||||
|
||||
bool CanUseWARP();
|
||||
bool CanUseD3D11ImageBridge();
|
||||
bool ContentAdapterIsParentAdapter(ID3D11Device* device);
|
||||
|
||||
void DisableD3D11AfterCrash();
|
||||
void ResetD3D11Devices();
|
||||
|
||||
IDXGIAdapter1 *GetDXGIAdapter();
|
||||
bool IsDeviceReset(HRESULT hr, DeviceResetReason* aReason);
|
||||
|
||||
RefPtr<IDWriteFactory> mDWriteFactory;
|
||||
RefPtr<IDWriteRenderingParams> mRenderingParams[TEXT_RENDERING_COUNT];
|
||||
DWRITE_MEASURING_MODE mMeasuringMode;
|
||||
|
||||
mozilla::Mutex mDeviceLock;
|
||||
RefPtr<IDXGIAdapter1> mAdapter;
|
||||
RefPtr<ID3D11Device> mD3D11Device;
|
||||
RefPtr<ID3D11Device> mD3D11ContentDevice;
|
||||
RefPtr<ID3D11Device> mD3D11ImageBridgeDevice;
|
||||
RefPtr<mozilla::layers::DeviceManagerD3D9> mDeviceManager;
|
||||
mozilla::Atomic<bool> mIsWARP;
|
||||
bool mHasDeviceReset;
|
||||
bool mHasFakeDeviceReset;
|
||||
mozilla::Atomic<bool> mCompositorD3D11TextureSharingWorks;
|
||||
mozilla::Atomic<bool> mHasD3D9DeviceReset;
|
||||
DeviceResetReason mDeviceResetReason;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user