☠☠ backed out by df82a3088812 ☠ ☠ | |
author | David Anderson <danderson@mozilla.com> |
Wed, 27 Apr 2016 22:54:26 -0700 | |
changeset 295170 | 993906e53329b6eb88b3f0a26507cdae0ae17be0 |
parent 295169 | e8abac801a515dbaa2210c0a78907b9e8f6301e6 |
child 295171 | b5ab83af342ced09135b9e743a594422856f3ac9 |
push id | 75834 |
push user | danderson@mozilla.com |
push date | Thu, 28 Apr 2016 05:58:25 +0000 |
treeherder | mozilla-inbound@f749ee384012 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jrmuizel |
bugs | 1254899 |
milestone | 49.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/gfx/config/gfxConfig.cpp +++ b/gfx/config/gfxConfig.cpp @@ -110,16 +110,27 @@ gfxConfig::UserForceEnable(Feature aFeat /* static */ void gfxConfig::UserDisable(Feature aFeature, const char* aMessage) { FeatureState& state = sConfig.GetState(aFeature); state.UserDisable(aMessage); } +/* static */ void +gfxConfig::Reenable(Feature aFeature, Fallback aFallback) +{ + FeatureState& state = sConfig.GetState(aFeature); + MOZ_ASSERT(IsFeatureStatusFailure(state.GetValue())); + + const char* message = state.GetRuntimeMessage(); + EnableFallback(aFallback, message); + state.SetRuntime(FeatureStatus::Available, nullptr); +} + /* static */ bool gfxConfig::UseFallback(Fallback aFallback) { return sConfig.UseFallbackImpl(aFallback); } /* static */ void gfxConfig::EnableFallback(Fallback aFallback, const char* aMessage)
--- a/gfx/config/gfxConfig.h +++ b/gfx/config/gfxConfig.h @@ -111,16 +111,22 @@ public: return MaybeSetFailed( aFeature, (aStatus != FeatureStatus::Available && aStatus != FeatureStatus::ForceEnabled), aStatus, aDisableMessage); } + // Re-enables a feature that was previously disabled, by attaching it to a + // fallback. The fallback inherits the message that was used for disabling + // the feature. This can be used, for example, when D3D11 fails at runtime + // but we acquire a second, successful device with WARP. + static void Reenable(Feature aFeature, Fallback aFallback); + // Same as SetDefault, except if the feature already has a default value // set, the new value will be set as a runtime value. This is useful for // when the base value can change (for example, via an update from the // parent process). static bool InitOrUpdate(Feature aFeature, bool aEnable, FeatureStatus aDisableStatus, const char* aDisableMessage);
--- a/gfx/config/gfxFallback.h +++ b/gfx/config/gfxFallback.h @@ -9,16 +9,17 @@ #include <stdint.h> #include "gfxTelemetry.h" namespace mozilla { namespace gfx { #define GFX_FALLBACK_MAP(_) \ /* Name */ \ + _(USE_D3D11_WARP_COMPOSITOR) \ /* Add new entries above this comment */ enum class Fallback : uint32_t { #define MAKE_ENUM(name) name, GFX_FALLBACK_MAP(MAKE_ENUM) #undef MAKE_ENUM NumValues };
--- a/gfx/config/gfxFeature.cpp +++ b/gfx/config/gfxFeature.cpp @@ -179,16 +179,23 @@ void FeatureState::SetRuntime(FeatureStatus aStatus, const char* aMessage) { // Default decision must have been made. MOZ_ASSERT(mDefault.mStatus != FeatureStatus::Unused); mRuntime.Set(aStatus, aMessage); } +const char* +FeatureState::GetRuntimeMessage() const +{ + MOZ_ASSERT(IsFeatureStatusFailure(mRuntime.mStatus)); + return mRuntime.mMessage; +} + void FeatureState::Instance::Set(FeatureStatus aStatus, const char* aMessage /* = nullptr */) { mStatus = aStatus; if (aMessage) { PR_snprintf(mMessage, sizeof(mMessage), "%s", aMessage); } }
--- a/gfx/config/gfxFeature.h +++ b/gfx/config/gfxFeature.h @@ -11,16 +11,17 @@ #include "mozilla/Assertions.h" namespace mozilla { namespace gfx { #define GFX_FEATURE_MAP(_) \ /* Name, Type, Description */ \ _(HW_COMPOSITING, Feature, "Compositing") \ + _(D3D11_COMPOSITING, Feature, "Direct3D11 Compositing") \ /* Add new entries above this comment */ enum class Feature : uint32_t { #define MAKE_ENUM(name, type, desc) name, GFX_FEATURE_MAP(MAKE_ENUM) #undef MAKE_ENUM NumValues }; @@ -52,16 +53,17 @@ class FeatureState bool MaybeSetFailed(FeatureStatus aStatus, const char* aMessage); private: void SetUser(FeatureStatus aStatus, const char* aMessage); void SetEnvironment(FeatureStatus aStatus, const char* aMessage); void SetRuntime(FeatureStatus aStatus, const char* aMessage); bool IsForcedOnByUser() const; bool DisabledByDefault() const; + const char* GetRuntimeMessage() const; bool IsInitialized() const { return mDefault.mStatus != FeatureStatus::Unused; } void AssertInitialized() const { MOZ_ASSERT(IsInitialized()); }
--- a/gfx/layers/d3d11/CompositorD3D11.cpp +++ b/gfx/layers/d3d11/CompositorD3D11.cpp @@ -12,16 +12,17 @@ #include "gfxWindowsPlatform.h" #include "nsIWidget.h" #include "nsIGfxInfo.h" #include "mozilla/layers/ImageHost.h" #include "mozilla/layers/ContentHost.h" #include "mozilla/layers/Effects.h" #include "nsWindowsHelpers.h" #include "gfxPrefs.h" +#include "gfxConfig.h" #include "gfxCrashReporterUtils.h" #include "gfxVR.h" #include "mozilla/gfx/StackArray.h" #include "mozilla/Services.h" #include "mozilla/EnumeratedArray.h" #include "mozilla/Telemetry.h" #include "BlendShaderConstants.h" @@ -193,17 +194,17 @@ CompositorD3D11::~CompositorD3D11() } } bool CompositorD3D11::Initialize() { ScopedGfxFeatureReporter reporter("D3D11 Layers"); - MOZ_ASSERT(gfxPlatform::CanUseDirect3D11()); + MOZ_ASSERT(gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)); HRESULT hr; if (!gfxWindowsPlatform::GetPlatform()->GetD3D11Device(&mDevice)) { return false; } mDevice->GetImmediateContext(getter_AddRefs(mContext));
--- a/gfx/src/gfxTelemetry.cpp +++ b/gfx/src/gfxTelemetry.cpp @@ -27,16 +27,18 @@ FeatureStatusToString(FeatureStatus aSta case FeatureStatus::Disabled: return "disabled"; case FeatureStatus::Available: return "available"; case FeatureStatus::ForceEnabled: return "force_enabled"; case FeatureStatus::CrashedOnStartup: return "crashed_on_startup"; + case FeatureStatus::Broken: + return "broken"; default: MOZ_ASSERT_UNREACHABLE("missing status case"); return "unknown"; } } bool IsFeatureStatusFailure(FeatureStatus aStatus)
--- a/gfx/src/gfxTelemetry.h +++ b/gfx/src/gfxTelemetry.h @@ -40,17 +40,20 @@ enum class FeatureStatus // This feature is available for use. Available, // This feature was explicitly force-enabled by the user. ForceEnabled, // This feature was disabled due to the startup crash guard. - CrashedOnStartup + CrashedOnStartup, + + // This feature was attempted but later determined to be broken. + Broken }; const char* FeatureStatusToString(FeatureStatus aStatus); bool IsFeatureStatusFailure(FeatureStatus aStatus); bool IsFeatureStatusSuccess(FeatureStatus aStatus); } // namespace gfx } // namespace mozilla
--- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -2051,17 +2051,16 @@ gfxPlatform::OptimalFormatForContent(gfx /** * There are a number of layers acceleration (or layers in general) preferences * that should be consistent for the lifetime of the application (bug 840967). * As such, we will evaluate them all as soon as one of them is evaluated * and remember the values. Changing these preferences during the run will * not have any effect until we restart. */ static bool sLayersSupportsD3D9 = false; -static bool sLayersSupportsD3D11 = false; bool gANGLESupportsD3D11 = false; static bool sLayersSupportsHardwareVideoDecoding = false; static bool sLayersHardwareVideoDecodingFailed = false; static bool sBufferRotationCheckPref = true; static bool sPrefBrowserTabsRemoteAutostart = false; static bool sLayersAccelerationPrefsInitialized = false; @@ -2084,33 +2083,23 @@ gfxPlatform::InitAcceleration() sPrefBrowserTabsRemoteAutostart = BrowserTabsRemoteAutostart(); nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo(); nsCString discardFailureId; int32_t status; #ifdef XP_WIN if (gfxConfig::IsForcedOnByUser(Feature::HW_COMPOSITING)) { sLayersSupportsD3D9 = true; - sLayersSupportsD3D11 = true; } else if (!gfxPrefs::LayersAccelerationDisabledDoNotUseDirectly() && gfxInfo) { if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, discardFailureId, &status))) { if (status == nsIGfxInfo::FEATURE_STATUS_OK) { MOZ_ASSERT(!sPrefBrowserTabsRemoteAutostart || IsVistaOrLater()); sLayersSupportsD3D9 = true; } } - if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, discardFailureId, &status))) { - if (status == nsIGfxInfo::FEATURE_STATUS_OK) { - sLayersSupportsD3D11 = true; - } - } - if (!gfxPrefs::LayersD3D11DisableWARP()) { - // Always support D3D11 when WARP is allowed. - sLayersSupportsD3D11 = true; - } if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_ANGLE, discardFailureId, &status))) { if (status == nsIGfxInfo::FEATURE_STATUS_OK) { gANGLESupportsD3D11 = true; } } } #endif @@ -2171,25 +2160,16 @@ gfxPlatform::CanUseDirect3D9() { // this function is called from the compositor thread, so it is not // safe to init the prefs etc. from here. MOZ_ASSERT(sLayersAccelerationPrefsInitialized); return sLayersSupportsD3D9; } bool -gfxPlatform::CanUseDirect3D11() -{ - // this function is called from the compositor thread, so it is not - // safe to init the prefs etc. from here. - MOZ_ASSERT(sLayersAccelerationPrefsInitialized); - return sLayersSupportsD3D11; -} - -bool gfxPlatform::CanUseHardwareVideoDecoding() { // this function is called from the compositor thread, so it is not // safe to init the prefs etc. from here. MOZ_ASSERT(sLayersAccelerationPrefsInitialized); return sLayersSupportsHardwareVideoDecoding && !sLayersHardwareVideoDecodingFailed; } @@ -2450,35 +2430,36 @@ gfxPlatform::NotifyCompositorCreated(Lay void gfxPlatform::GetDeviceInitData(mozilla::gfx::DeviceInitData* aOut) { MOZ_ASSERT(XRE_IsParentProcess()); aOut->useHwCompositing() = gfxConfig::IsEnabled(Feature::HW_COMPOSITING); } -void +bool gfxPlatform::UpdateDeviceInitData() { if (XRE_IsParentProcess()) { // The parent process figures out device initialization on its own. - return; + return false; } mozilla::gfx::DeviceInitData data; mozilla::dom::ContentChild::GetSingleton()->SendGetGraphicsDeviceInitData(&data); sDeviceInitDataDoNotUseDirectly = data; // Ensure that child processes have inherited the HW_COMPOSITING pref. gfxConfig::InitOrUpdate( Feature::HW_COMPOSITING, GetParentDevicePrefs().useHwCompositing(), FeatureStatus::Blocked, "Hardware-accelerated compositing disabled in parent process"); + return true; } bool gfxPlatform::SupportsApzDragInput() const { return gfxPrefs::APZDragEnabled(); }
--- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -445,17 +445,16 @@ public: } // Are we in safe mode? static bool InSafeMode(); static bool OffMainThreadCompositingEnabled(); static bool CanUseDirect3D9(); - static bool CanUseDirect3D11(); virtual bool CanUseHardwareVideoDecoding(); static bool CanUseDirect3D11ANGLE(); // Returns a prioritized list of all available compositor backends. void GetCompositorBackends(bool useAcceleration, nsTArray<mozilla::layers::LayersBackend>& aBackends); /** * Is it possible to use buffer rotation. Note that these @@ -679,19 +678,20 @@ protected: * aBackendBitmask specifies the backends which are acceptable to the caller. * The backend used is determined by aBackendBitmask and the order specified * by the gfx.canvas.azure.backends pref. */ void InitBackendPrefs(uint32_t aCanvasBitmask, mozilla::gfx::BackendType aCanvasDefault, uint32_t aContentBitmask, mozilla::gfx::BackendType aContentDefault); /** - * If in a child process, triggers a refresh of device preferences. + * If in a child process, triggers a refresh of device preferences, then returns true. + * In a parent process, nothing happens and false is returned. */ - void UpdateDeviceInitData(); + virtual bool UpdateDeviceInitData(); /** * Increase the global device counter after a device has been removed/reset. */ void BumpDeviceCounter(); /** * returns the first backend named in the pref gfx.canvas.azure.backends
--- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -360,17 +360,16 @@ NS_IMPL_ISUPPORTS(D3D9SharedTextureRepor gfxWindowsPlatform::gfxWindowsPlatform() : mRenderMode(RENDER_GDI) , mDeviceLock("gfxWindowsPlatform.mDeviceLock") , mIsWARP(false) , mHasDeviceReset(false) , mHasFakeDeviceReset(false) , mCompositorD3D11TextureSharingWorks(false) - , mD3D11Status(FeatureStatus::Unused) , mD2D1Status(FeatureStatus::Unused) , mHasD3D9DeviceReset(false) { mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE; mUseClearTypeAlways = UNINITIALIZED_VALUE; /* * Initialize COM @@ -411,16 +410,17 @@ gfxWindowsPlatform::InitAcceleration() 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); + InitializeConfig(); InitializeDevices(); UpdateRenderMode(); } bool gfxWindowsPlatform::CanUseHardwareVideoDecoding() { if (!gfxPrefs::LayersPreferD3D9() && !mCompositorD3D11TextureSharingWorks) { @@ -525,17 +525,17 @@ gfxWindowsPlatform::UpdateRenderMode() UpdateBackendPrefs(); if (didReset) { mScreenReferenceDrawTarget = CreateOffscreenContentDrawTarget(IntSize(1, 1), SurfaceFormat::B8G8R8A8); if (!mScreenReferenceDrawTarget) { gfxCriticalNote << "Failed to update reference draw target after device reset" << ", D3D11 device:" << hexa(Factory::GetDirect3D11Device()) - << ", D3D11 status:" << FeatureStatusToString(GetD3D11Status()) + << ", D3D11 status:" << FeatureStatusToString(gfxConfig::GetValue(Feature::D3D11_COMPOSITING)) << ", D2D1 device:" << hexa(Factory::GetD2D1Device()) << ", D2D1 status:" << FeatureStatusToString(GetD2D1Status()) << ", content:" << int(GetDefaultContentBackend()) << ", compositor:" << int(GetCompositorBackend()); MOZ_CRASH("GFX: Failed to update reference draw target after device reset"); } } } @@ -1907,81 +1907,109 @@ bool DoesD3D11TextureSharingWork(ID3D11D return DoesD3D11TextureSharingWorkInternal(device, DXGI_FORMAT_B8G8R8A8_UNORM, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE); } bool DoesD3D11AlphaTextureSharingWork(ID3D11Device *device) { return DoesD3D11TextureSharingWorkInternal(device, DXGI_FORMAT_R8_UNORM, D3D11_BIND_SHADER_RESOURCE); } -bool -gfxWindowsPlatform::CanUseWARP() +static inline bool +IsGfxInfoStatusOkay(int32_t aFeature) { - if (gfxPrefs::LayersD3D11ForceWARP()) { + nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo(); + if (!gfxInfo) { return true; } - // The child process can only use WARP if the parent process is also using - // WARP. - if (XRE_IsContentProcess()) { - return GetParentDevicePrefs().useD3D11WARP(); + int32_t status; + nsCString discardFailureId; + if (FAILED(gfxInfo->GetFeatureStatus(aFeature, discardFailureId, &status))) { + return true; } + return status == nsIGfxInfo::FEATURE_STATUS_OK; +} + +static inline bool +IsWARPStable() +{ // It seems like nvdxgiwrap makes a mess of WARP. See bug 1154703. - if (!IsWin8OrLater() || - gfxPrefs::LayersD3D11DisableWARP() || - GetModuleHandleA("nvdxgiwrap.dll")) - { + if (!IsWin8OrLater() || GetModuleHandleA("nvdxgiwrap.dll")) { return false; } return true; } -FeatureStatus -gfxWindowsPlatform::CheckD3D11Support(bool* aCanUseHardware) +void +gfxWindowsPlatform::InitializeConfig() { - // Don't revive D3D11 support after a failure. - if (IsFeatureStatusFailure(mD3D11Status)) { - return mD3D11Status; - } - - if (XRE_IsContentProcess()) { - if (!GetParentDevicePrefs().useD3D11()) { - return FeatureStatus::Blocked; - } - *aCanUseHardware = !GetParentDevicePrefs().useD3D11WARP(); - return FeatureStatus::Available; + if (!XRE_IsParentProcess()) { + return; } - if (gfxPrefs::LayersD3D11ForceWARP()) { - *aCanUseHardware = false; - return FeatureStatus::Available; - } - if (gfxConfig::IsForcedOnByUser(Feature::HW_COMPOSITING)) { - *aCanUseHardware = true; - return FeatureStatus::Available; + InitializeD3D11Config(); +} + +void +gfxWindowsPlatform::InitializeD3D11Config() +{ + MOZ_ASSERT(XRE_IsParentProcess()); + + FeatureState& d3d11 = gfxConfig::GetFeature(Feature::D3D11_COMPOSITING); + + d3d11.EnableByDefault(); + + // If the user prefers D3D9, act as though they disabled D3D11. + if (gfxPrefs::LayersPreferD3D9()) { + d3d11.UserDisable("Disabled due to user preference for Direct3D 9"); + return; } - if (nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo()) { - int32_t status; - nsCString discardFailureId; - if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, discardFailureId, &status))) { - if (status != nsIGfxInfo::FEATURE_STATUS_OK) { - if (CanUseWARP()) { - *aCanUseHardware = false; - return FeatureStatus::Available; - } - return FeatureStatus::Blacklisted; - } + if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS)) { + if (IsWARPStable() && !gfxPrefs::LayersD3D11DisableWARP()) { + // We do not expect hardware D3D11 to work, so we'll try WARP. + gfxConfig::EnableFallback( + Fallback::USE_D3D11_WARP_COMPOSITOR, + "Hardware-accelerated Direct3D11 compositing is blocklisted"); + } else { + // There is little to no chance of D3D11 working, so just disable it. + d3d11.Disable(FeatureStatus::Blacklisted, "Hardware-accelerated Direct3D11 compositing is blocklisted"); } } - // If we've used WARP once, we continue to use it after device resets. - *aCanUseHardware = !mIsWARP; - return FeatureStatus::Available; + // Check if the user really, really wants WARP. + if (gfxPrefs::LayersD3D11ForceWARP()) { + // Force D3D11 on even if we disabled it. + d3d11.UserForceEnable("User force-enabled WARP on disabled hardware"); + + gfxConfig::EnableFallback( + Fallback::USE_D3D11_WARP_COMPOSITOR, + "Force-enabled by user preference"); + } +} + +bool +gfxWindowsPlatform::UpdateDeviceInitData() +{ + if (!gfxPlatform::UpdateDeviceInitData()) { + return false; + } + + if (gfxConfig::InitOrUpdate(Feature::D3D11_COMPOSITING, + GetParentDevicePrefs().useD3D11(), + FeatureStatus::Disabled, + "Disabled by parent process")) + { + if (GetParentDevicePrefs().useD3D11WARP()) { + gfxConfig::EnableFallback(Fallback::USE_D3D11_WARP_COMPOSITOR, "Requested by parent process"); + } + } + + 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 @@ -1998,37 +2026,41 @@ gfxWindowsPlatform::AttemptD3D11DeviceCr mFeatureLevels.Elements(), mFeatureLevels.Length(), D3D11_SDK_VERSION, getter_AddRefs(aOutDevice), nullptr, nullptr); } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { return false; } return true; } -FeatureStatus -gfxWindowsPlatform::AttemptD3D11DeviceCreation() +void +gfxWindowsPlatform::AttemptD3D11DeviceCreation(FeatureState& d3d11) { RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter(); if (!adapter) { - return FeatureStatus::Unavailable; + d3d11.SetFailed(FeatureStatus::Unavailable, "Failed to acquire a DXGI adapter"); + return; } HRESULT hr; RefPtr<ID3D11Device> device; if (!AttemptD3D11DeviceCreationHelper(adapter, device, hr)) { gfxCriticalError() << "Crash during D3D11 device creation"; - return FeatureStatus::CrashedInHandler; + d3d11.SetFailed(FeatureStatus::CrashedInHandler, "Crashed trying to acquire a D3D11 device"); + return; } if (FAILED(hr) || !device) { gfxCriticalError() << "D3D11 device creation failed: " << hexa(hr); - return FeatureStatus::Failed; + d3d11.SetFailed(FeatureStatus::Failed, "Failed to acquire a D3D11 device"); + return; } if (!DoesD3D11DeviceWork()) { - return FeatureStatus::Blocked; + d3d11.SetFailed(FeatureStatus::Broken, "Direct3D11 device was determined to be broken"); + return; } { MutexAutoLock lock(mDeviceLock); mD3D11Device = device; } // Only test this when not using WARP since it can fail and cause @@ -2036,17 +2068,16 @@ gfxWindowsPlatform::AttemptD3D11DeviceCr mCompositorD3D11TextureSharingWorks = ::DoesD3D11TextureSharingWork(mD3D11Device); if (!mCompositorD3D11TextureSharingWorks || DoesRenderTargetViewNeedsRecreating(mD3D11Device)) { gANGLESupportsD3D11 = false; } mD3D11Device->SetExceptionMode(0); mIsWARP = false; - return FeatureStatus::Available; } bool gfxWindowsPlatform::AttemptWARPDeviceCreationHelper( ScopedGfxFeatureReporter& aReporterWARP, RefPtr<ID3D11Device>& aOutDevice, HRESULT& aResOut) { @@ -2062,47 +2093,49 @@ gfxWindowsPlatform::AttemptWARPDeviceCre aReporterWARP.SetSuccessful(); } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { return false; } return true; } -FeatureStatus +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!"; - return FeatureStatus::CrashedInHandler; + d3d11.SetFailed(FeatureStatus::CrashedInHandler, "Crashed creating a D3D11 WARP device"); + return; } if (FAILED(hr) || !device) { // This should always succeed... in theory. gfxCriticalError() << "Failed to initialize WARP D3D11 device! " << hexa(hr); - return FeatureStatus::Failed; + d3d11.SetFailed(FeatureStatus::Failed, "Failed to create a D3D11 WARP device"); + 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 = ::DoesD3D11TextureSharingWork(mD3D11Device); } mD3D11Device->SetExceptionMode(0); mIsWARP = true; - return FeatureStatus::Available; } bool gfxWindowsPlatform::ContentAdapterIsParentAdapter(ID3D11Device* device) { DXGI_ADAPTER_DESC desc; if (!GetDxgiDesc(device, &desc)) { gfxCriticalNote << "Could not query device DXGI adapter info"; @@ -2254,42 +2287,39 @@ void gfxWindowsPlatform::InitializeDevices() { // Ask the parent process for an updated list of which devices to create. UpdateDeviceInitData(); // If acceleration is disabled, we refuse to initialize anything. FeatureStatus compositing = gfxConfig::GetValue(Feature::HW_COMPOSITING); if (IsFeatureStatusFailure(compositing)) { + gfxConfig::DisableByDefault(Feature::D3D11_COMPOSITING, compositing, "Hardware compositing is disabled"); return; } MOZ_ASSERT(!InSafeMode()); // If we previously crashed initializing devices, bail out now. D3D11LayersCrashGuard detectCrashes; if (detectCrashes.Crashed()) { gfxConfig::SetFailed(Feature::HW_COMPOSITING, FeatureStatus::CrashedOnStartup, "Crashed during startup in a previous session"); - return; - } - - // If we're going to prefer D3D9, stop here. The rest of this function - // attempts to use D3D11 features. - if (gfxPrefs::LayersPreferD3D9()) { - mD3D11Status = FeatureStatus::Disabled; + gfxConfig::SetFailed(Feature::D3D11_COMPOSITING, + FeatureStatus::CrashedOnStartup, + "Harware acceleration crashed during startup in a previous session"); return; } // First, initialize D3D11. If this succeeds we attempt to use Direct2D. InitializeD3D11(); // Initialize Direct2D. - if (mD3D11Status == FeatureStatus::Available) { + if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) { InitializeD2D(); } // Usually we want D2D in order to use DWrite, but if the users have it // forced, we'll let them have it, as unsupported configuration. if (gfxPrefs::DirectWriteFontRenderingForceEnabled() && IsFeatureStatusFailure(mD2D1Status) && !mDWriteFactory) { @@ -2315,71 +2345,77 @@ gfxWindowsPlatform::InitializeD3D11() // This function attempts to initialize our D3D11 devices, if the hardware // is not blacklisted for D3D11 layers. This first attempt will try to create // a hardware accelerated device. If this creation fails or the hardware is // 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. - bool canUseHardware = true; - mD3D11Status = CheckD3D11Support(&canUseHardware); - if (IsFeatureStatusFailure(mD3D11Status)) { + 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. - mD3D11Status = FeatureStatus::Unavailable; + d3d11.SetFailed(FeatureStatus::Unavailable, "Direct3D11 not available on this computer"); return; } // Check if a failure was injected for testing. if (gfxPrefs::DeviceFailForTesting()) { - mD3D11Status = FeatureStatus::Failed; + d3d11.SetFailed(FeatureStatus::Failed, "Direct3D11 device failure simulated by preference"); return; } if (XRE_IsParentProcess()) { - // First try to create a hardware accelerated device. - if (canUseHardware) { - mD3D11Status = AttemptD3D11DeviceCreation(); - if (mD3D11Status == FeatureStatus::CrashedInHandler) { + 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 (!mD3D11Device) { - if (!CanUseWARP()) { - mD3D11Status = FeatureStatus::Blocked; + 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; } - mD3D11Status = AttemptWARPDeviceCreation(); } // If we still have no device by now, exit. if (!mD3D11Device) { - MOZ_ASSERT(IsFeatureStatusFailure(mD3D11Status)); + MOZ_ASSERT(!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)); return; } // Either device creation function should have returned Available. - MOZ_ASSERT(mD3D11Status == FeatureStatus::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 = !canUseHardware; + mIsWARP = gfxConfig::UseFallback(Fallback::USE_D3D11_WARP_COMPOSITOR); mCompositorD3D11TextureSharingWorks = GetParentDevicePrefs().d3d11TextureSharingWorks(); - mD3D11Status = FeatureStatus::Available; } if (CanUseD3D11ImageBridge()) { if (AttemptD3D11ImageBridgeDeviceCreation() == FeatureStatus::CrashedInHandler) { DisableD3D11AfterCrash(); return; } } @@ -2393,17 +2429,19 @@ gfxWindowsPlatform::InitializeD3D11() // leak it here as well. We keep the pointer to sD3D11CreateDeviceFn around // as well for D2D1 and device resets. d3d11Module.disown(); } void gfxWindowsPlatform::DisableD3D11AfterCrash() { - mD3D11Status = FeatureStatus::CrashedInHandler; + gfxConfig::Disable(Feature::D3D11_COMPOSITING, + FeatureStatus::CrashedInHandler, + "Crashed while acquiring a Direct3D11 device"); ResetD3D11Devices(); } void gfxWindowsPlatform::ResetD3D11Devices() { MutexAutoLock lock(mDeviceLock); @@ -2855,17 +2893,17 @@ void gfxWindowsPlatform::GetAcceleratedCompositorBackends(nsTArray<LayersBackend>& aBackends) { if (gfxPrefs::LayersPreferOpenGL()) { aBackends.AppendElement(LayersBackend::LAYERS_OPENGL); } bool allowTryingD3D9 = false; if (!gfxPrefs::LayersPreferD3D9()) { - if (gfxPlatform::CanUseDirect3D11() && mD3D11Device) { + if (mD3D11Device) { aBackends.AppendElement(LayersBackend::LAYERS_D3D11); } else { allowTryingD3D9 = gfxPrefs::LayersAllowD3D9Fallback(); NS_WARNING("Direct3D 11-accelerated layers are not supported on this system."); } } if (gfxPrefs::LayersPreferD3D9() || !IsVistaOrLater() || allowTryingD3D9) { @@ -2876,28 +2914,19 @@ gfxWindowsPlatform::GetAcceleratedCompos NS_WARNING("Direct3D 9-accelerated layers are not supported on this system."); } } } // Some features are dependent on other features. If this is the case, we // try to propagate the status of the parent feature if it wasn't available. FeatureStatus -gfxWindowsPlatform::GetD3D11Status() const -{ - if (!gfxConfig::IsEnabled(Feature::HW_COMPOSITING)) { - return gfxConfig::GetValue(Feature::HW_COMPOSITING); - } - return mD3D11Status; -} - -FeatureStatus gfxWindowsPlatform::GetD2D1Status() const { - if (GetD3D11Status() != FeatureStatus::Available) { + if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) { return FeatureStatus::Unavailable; } return mD2D1Status; } unsigned gfxWindowsPlatform::GetD3D11Version() { @@ -2912,17 +2941,17 @@ void gfxWindowsPlatform::GetDeviceInitData(DeviceInitData* aOut) { // Check for device resets before giving back new graphics information. UpdateRenderMode(); gfxPlatform::GetDeviceInitData(aOut); // IPDL initializes each field to false for us so we can early return. - if (GetD3D11Status() != FeatureStatus::Available) { + if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) { return; } aOut->useD3D11() = true; aOut->useD3D11ImageBridge() = !!mD3D11ImageBridgeDevice; aOut->d3d11TextureSharingWorks() = mCompositorD3D11TextureSharingWorks; aOut->useD3D11WARP() = mIsWARP; aOut->useD2D1() = (GetD2D1Status() == FeatureStatus::Available);
--- a/gfx/thebes/gfxWindowsPlatform.h +++ b/gfx/thebes/gfxWindowsPlatform.h @@ -41,16 +41,17 @@ #define D3D_FEATURE_LEVEL_11_1 static_cast<D3D_FEATURE_LEVEL>(0xb100) #define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048 #define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096 #endif namespace mozilla { namespace gfx { class DrawTarget; +class FeatureState; } namespace layers { class DeviceManagerD3D9; class ReadbackManagerD3D11; } } struct IDirect3DDevice9; struct ID3D11Device; @@ -241,17 +242,16 @@ public: // Recreate devices as needed for a device reset. Returns true if a device // reset occurred. bool HandleDeviceReset(); void UpdateBackendPrefs(); // Return the diagnostic status of DirectX initialization. If // initialization has not been attempted, this returns // FeatureStatus::Unused. - mozilla::gfx::FeatureStatus GetD3D11Status() const; mozilla::gfx::FeatureStatus GetD2D1Status() const; unsigned GetD3D11Version(); void TestDeviceReset(DeviceResetReason aReason); virtual already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource() override; static mozilla::Atomic<size_t> sD3D11MemoryUsed; static mozilla::Atomic<size_t> sD3D9MemoryUsed; @@ -265,16 +265,17 @@ public: bool SupportsPluginDirectDXGIDrawing(); protected: bool AccelerateLayersByDefault() override { return true; } void GetAcceleratedCompositorBackends(nsTArray<mozilla::layers::LayersBackend>& aBackends) override; virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size) override; + bool UpdateDeviceInitData() override; protected: RenderMode mRenderMode; int8_t mUseClearTypeForDownloadableFonts; int8_t mUseClearTypeAlways; private: @@ -283,26 +284,27 @@ private: void InitializeDevices(); void InitializeD3D11(); void InitializeD2D(); bool InitDWriteSupport(); void DisableD2D(); - mozilla::gfx::FeatureStatus CheckD3D11Support(bool* aCanUseHardware); + void InitializeConfig(); + void InitializeD3D11Config(); mozilla::gfx::FeatureStatus CheckD2D1Support(); - mozilla::gfx::FeatureStatus AttemptD3D11DeviceCreation(); + void AttemptD3D11DeviceCreation(mozilla::gfx::FeatureState& d3d11); bool AttemptD3D11DeviceCreationHelper( IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aOutDevice, HRESULT& aResOut); - mozilla::gfx::FeatureStatus AttemptWARPDeviceCreation(); + void AttemptWARPDeviceCreation(); bool AttemptWARPDeviceCreationHelper( mozilla::ScopedGfxFeatureReporter& aReporterWARP, RefPtr<ID3D11Device>& aOutDevice, HRESULT& aResOut); bool AttemptD3D11ImageBridgeDeviceCreationHelper( IDXGIAdapter1* aAdapter, HRESULT& aResOut); mozilla::gfx::FeatureStatus AttemptD3D11ImageBridgeDeviceCreation(); @@ -337,15 +339,14 @@ private: bool mCompositorD3D11TextureSharingWorks; mozilla::Atomic<bool> mHasD3D9DeviceReset; DeviceResetReason mDeviceResetReason; RefPtr<mozilla::layers::ReadbackManagerD3D11> mD3D11ReadbackManager; // These should not be accessed directly. Use the Get[Feature]Status // accessors instead. - mozilla::gfx::FeatureStatus mD3D11Status; mozilla::gfx::FeatureStatus mD2D1Status; nsTArray<D3D_FEATURE_LEVEL> mFeatureLevels; }; #endif /* GFX_WINDOWS_PLATFORM_H */
--- a/widget/windows/GfxInfo.cpp +++ b/widget/windows/GfxInfo.cpp @@ -2,16 +2,17 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/ArrayUtils.h" #include <windows.h> #include <setupapi.h> +#include "gfxConfig.h" #include "gfxWindowsPlatform.h" #include "GfxInfo.h" #include "GfxInfoWebGL.h" #include "nsUnicharUtils.h" #include "prenv.h" #include "prprf.h" #include "GfxDriverInfo.h" #include "mozilla/Preferences.h" @@ -21,16 +22,17 @@ #if defined(MOZ_CRASHREPORTER) #include "nsExceptionHandler.h" #include "nsICrashReporter.h" #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1" #endif using namespace mozilla; +using namespace mozilla::gfx; using namespace mozilla::widget; #ifdef DEBUG NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug) #endif static const uint32_t allWindowsVersions = 0xffffffff; @@ -1255,31 +1257,40 @@ GfxInfo::FindMonitors(JSContext* aCx, JS void GfxInfo::DescribeFeatures(JSContext* aCx, JS::Handle<JSObject*> aObj) { JS::Rooted<JSObject*> obj(aCx); gfxWindowsPlatform* platform = gfxWindowsPlatform::GetPlatform(); - gfx::FeatureStatus d3d11 = platform->GetD3D11Status(); + gfx::FeatureStatus d3d11 = gfxConfig::GetValue(Feature::D3D11_COMPOSITING); if (!InitFeatureObject(aCx, aObj, "d3d11", d3d11, &obj)) { return; } if (d3d11 == gfx::FeatureStatus::Available) { JS::Rooted<JS::Value> val(aCx, JS::Int32Value(platform->GetD3D11Version())); JS_SetProperty(aCx, obj, "version", val); val = JS::BooleanValue(platform->IsWARP()); JS_SetProperty(aCx, obj, "warp", val); val = JS::BooleanValue(platform->CompositorD3D11TextureSharingWorks()); JS_SetProperty(aCx, obj, "textureSharing", val); - val = JS::BooleanValue(!platform->CanUseDirect3D11()); + bool blacklisted = false; + if (nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo()) { + int32_t status; + nsCString discardFailureId; + if (SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, discardFailureId, &status))) { + blacklisted = (status != nsIGfxInfo::FEATURE_STATUS_OK); + } + } + + val = JS::BooleanValue(blacklisted); JS_SetProperty(aCx, obj, "blacklisted", val); } gfx::FeatureStatus d2d = platform->GetD2D1Status(); if (!InitFeatureObject(aCx, aObj, "d2d", d2d, &obj)) { return; } {