--- a/gfx/config/gfxConfig.cpp
+++ b/gfx/config/gfxConfig.cpp
@@ -1,158 +1,162 @@
/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sts=2 ts=8 sw=2 tw=99 et: */
/* 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 "gfxConfig.h"
+#include "mozilla/UniquePtr.h"
#include "plstr.h"
namespace mozilla {
namespace gfx {
-static gfxConfig sConfig;
+static UniquePtr<gfxConfig> sConfig;
/* static */ FeatureState&
gfxConfig::GetFeature(Feature aFeature)
{
- return sConfig.GetState(aFeature);
+ return sConfig->GetState(aFeature);
}
/* static */ bool
gfxConfig::IsEnabled(Feature aFeature)
{
- const FeatureState& state = sConfig.GetState(aFeature);
+ const FeatureState& state = sConfig->GetState(aFeature);
return state.IsEnabled();
}
/* static */ bool
gfxConfig::IsDisabledByDefault(Feature aFeature)
{
- const FeatureState& state = sConfig.GetState(aFeature);
+ const FeatureState& state = sConfig->GetState(aFeature);
return state.DisabledByDefault();
}
/* static */ bool
gfxConfig::IsForcedOnByUser(Feature aFeature)
{
- const FeatureState& state = sConfig.GetState(aFeature);
+ const FeatureState& state = sConfig->GetState(aFeature);
return state.IsForcedOnByUser();
}
/* static */ FeatureStatus
gfxConfig::GetValue(Feature aFeature)
{
- const FeatureState& state = sConfig.GetState(aFeature);
+ const FeatureState& state = sConfig->GetState(aFeature);
return state.GetValue();
}
/* static */ bool
gfxConfig::SetDefault(Feature aFeature,
bool aEnable,
FeatureStatus aDisableStatus,
const char* aDisableMessage)
{
- FeatureState& state = sConfig.GetState(aFeature);
+ FeatureState& state = sConfig->GetState(aFeature);
return state.SetDefault(aEnable, aDisableStatus, aDisableMessage);
}
/* static */ void
gfxConfig::DisableByDefault(Feature aFeature,
FeatureStatus aDisableStatus,
- const char* aDisableMessage)
+ const char* aDisableMessage,
+ const nsACString& aFailureId)
{
- FeatureState& state = sConfig.GetState(aFeature);
- state.DisableByDefault(aDisableStatus, aDisableMessage);
+ FeatureState& state = sConfig->GetState(aFeature);
+ state.DisableByDefault(aDisableStatus, aDisableMessage, aFailureId);
}
/* static */ void
gfxConfig::EnableByDefault(Feature aFeature)
{
- FeatureState& state = sConfig.GetState(aFeature);
+ FeatureState& state = sConfig->GetState(aFeature);
state.EnableByDefault();
}
/* static */ void
gfxConfig::SetDefaultFromPref(Feature aFeature,
const char* aPrefName,
bool aIsEnablePref,
bool aDefaultValue)
{
- FeatureState& state = sConfig.GetState(aFeature);
+ FeatureState& state = sConfig->GetState(aFeature);
return state.SetDefaultFromPref(aPrefName, aIsEnablePref, aDefaultValue);
}
/* static */ bool
gfxConfig::InitOrUpdate(Feature aFeature,
bool aEnable,
FeatureStatus aDisableStatus,
const char* aDisableMessage)
{
- FeatureState& state = sConfig.GetState(aFeature);
+ FeatureState& state = sConfig->GetState(aFeature);
return state.InitOrUpdate(aEnable, aDisableStatus, aDisableMessage);
}
/* static */ void
-gfxConfig::SetFailed(Feature aFeature, FeatureStatus aStatus, const char* aMessage)
+gfxConfig::SetFailed(Feature aFeature, FeatureStatus aStatus, const char* aMessage,
+ const nsACString& aFailureId)
{
- FeatureState& state = sConfig.GetState(aFeature);
- state.SetFailed(aStatus, aMessage);
+ FeatureState& state = sConfig->GetState(aFeature);
+ state.SetFailed(aStatus, aMessage, aFailureId);
}
/* static */ void
-gfxConfig::Disable(Feature aFeature, FeatureStatus aStatus, const char* aMessage)
+gfxConfig::Disable(Feature aFeature, FeatureStatus aStatus, const char* aMessage,
+ const nsACString& aFailureId)
{
- FeatureState& state = sConfig.GetState(aFeature);
- state.Disable(aStatus, aMessage);
+ FeatureState& state = sConfig->GetState(aFeature);
+ state.Disable(aStatus, aMessage, aFailureId);
}
/* static */ void
gfxConfig::UserEnable(Feature aFeature, const char* aMessage)
{
- FeatureState& state = sConfig.GetState(aFeature);
+ FeatureState& state = sConfig->GetState(aFeature);
state.UserEnable(aMessage);
}
/* static */ void
gfxConfig::UserForceEnable(Feature aFeature, const char* aMessage)
{
- FeatureState& state = sConfig.GetState(aFeature);
+ FeatureState& state = sConfig->GetState(aFeature);
state.UserForceEnable(aMessage);
}
/* static */ void
-gfxConfig::UserDisable(Feature aFeature, const char* aMessage)
+gfxConfig::UserDisable(Feature aFeature, const char* aMessage, const nsACString& aFailureId)
{
- FeatureState& state = sConfig.GetState(aFeature);
- state.UserDisable(aMessage);
+ FeatureState& state = sConfig->GetState(aFeature);
+ state.UserDisable(aMessage, aFailureId);
}
/* static */ void
gfxConfig::Reenable(Feature aFeature, Fallback aFallback)
{
- FeatureState& state = sConfig.GetState(aFeature);
+ 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);
+ return sConfig->UseFallbackImpl(aFallback);
}
/* static */ void
gfxConfig::EnableFallback(Fallback aFallback, const char* aMessage)
{
// Ignore aMessage for now.
- sConfig.EnableFallbackImpl(aFallback, aMessage);
+ sConfig->EnableFallbackImpl(aFallback, aMessage);
}
bool
gfxConfig::UseFallbackImpl(Fallback aFallback) const
{
return !!(mFallbackBits & (uint64_t(1) << uint64_t(aFallback)));
}
@@ -202,22 +206,41 @@ static const char* sFallbackNames[] = {
GFX_FALLBACK_MAP(FOR_EACH_FALLBACK)
#undef FOR_EACH_FALLBACK
nullptr
};
/* static */ void
gfxConfig::ForEachFallback(const FallbackIterCallback& aCallback)
{
- sConfig.ForEachFallbackImpl(aCallback);
+ sConfig->ForEachFallbackImpl(aCallback);
}
void
gfxConfig::ForEachFallbackImpl(const FallbackIterCallback& aCallback)
{
for (size_t i = 0; i < mNumFallbackLogEntries; i++) {
const FallbackLogEntry& entry = mFallbackLog[i];
aCallback(sFallbackNames[size_t(entry.mFallback)], entry.mMessage);
}
}
+/* static */ const nsACString&
+gfxConfig::GetFailureId(Feature aFeature)
+{
+ const FeatureState& state = sConfig->GetState(aFeature);
+ return state.GetFailureId();
+}
+
+/* static */ void
+gfxConfig::Init()
+{
+ sConfig = mozilla::MakeUnique<gfxConfig>();
+}
+
+/* static */ void
+gfxConfig::Shutdown()
+{
+ sConfig = nullptr;
+}
+
} // namespace gfx
} // namespace mozilla
--- a/gfx/config/gfxConfig.h
+++ b/gfx/config/gfxConfig.h
@@ -58,76 +58,82 @@ public:
// Initialize the base value of a parameter. The return value is aEnable.
static bool SetDefault(Feature aFeature,
bool aEnable,
FeatureStatus aDisableStatus,
const char* aDisableMessage);
static void DisableByDefault(Feature aFeature,
FeatureStatus aDisableStatus,
- const char* aDisableMessage);
+ const char* aDisableMessage,
+ const nsACString& aFailureId = EmptyCString());
static void EnableByDefault(Feature aFeature);
// Set a environment status that overrides both the default and user
// statuses; this should be used to disable features based on system
// or hardware problems that can be determined up-front. The only
// status that can override this decision is the user force-enabling
// the feature.
static void Disable(Feature aFeature,
FeatureStatus aStatus,
- const char* aMessage);
+ const char* aMessage,
+ const nsACString& aFailureId = EmptyCString());
// Given a preference name, infer the default value and whether or not the
// user has changed it. |aIsEnablePref| specifies whether or not the pref
// is intended to enable a feature (true), or disable it (false).
static void SetDefaultFromPref(Feature aFeature,
const char* aPrefName,
bool aIsEnablePref,
bool aDefaultValue);
// Disable a parameter based on a runtime decision. This permanently
// disables the feature, since runtime decisions override all other
// decisions.
static void SetFailed(Feature aFeature,
FeatureStatus aStatus,
- const char* aMessage);
+ const char* aMessage,
+ const nsACString& aFailureId = EmptyCString());
// Force a feature to be disabled permanently. This is the same as
// SetFailed(), but the name may be clearer depending on the context.
static void ForceDisable(Feature aFeature,
FeatureStatus aStatus,
- const char* aMessage)
+ const char* aMessage,
+ const nsACString& aFailureId = EmptyCString())
{
- SetFailed(aFeature, aStatus, aMessage);
+ SetFailed(aFeature, aStatus, aMessage, aFailureId);
}
// Convenience helpers for SetFailed().
static bool MaybeSetFailed(Feature aFeature,
bool aEnable,
FeatureStatus aDisableStatus,
- const char* aDisableMessage)
+ const char* aDisableMessage,
+ const nsACString& aFailureId = EmptyCString())
{
if (!aEnable) {
- SetFailed(aFeature, aDisableStatus, aDisableMessage);
+ SetFailed(aFeature, aDisableStatus, aDisableMessage, aFailureId);
return false;
}
return true;
}
// Convenience helper for SetFailed().
static bool MaybeSetFailed(Feature aFeature,
FeatureStatus aStatus,
- const char* aDisableMessage)
+ const char* aDisableMessage,
+ const nsACString& aFailureId = EmptyCString())
{
return MaybeSetFailed(
aFeature,
(aStatus != FeatureStatus::Available &&
aStatus != FeatureStatus::ForceEnabled),
aStatus,
- aDisableMessage);
+ aDisableMessage, aFailureId);
}
// 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);
@@ -139,17 +145,17 @@ public:
bool aEnable,
FeatureStatus aDisableStatus,
const char* aDisableMessage);
// Set a user status that overrides the base value (but not runtime value)
// of a parameter.
static void UserEnable(Feature aFeature, const char* aMessage);
static void UserForceEnable(Feature aFeature, const char* aMessage);
- static void UserDisable(Feature aFeature, const char* aMessage);
+ static void UserDisable(Feature aFeature, const char* aMessage, const nsACString& aFailureId = EmptyCString());
// Query whether a fallback has been toggled.
static bool UseFallback(Fallback aFallback);
// Enable a fallback.
static void EnableFallback(Fallback aFallback, const char* aMessage);
// Run a callback for each initialized FeatureState.
@@ -158,16 +164,22 @@ public:
FeatureState& aFeature)> FeatureIterCallback;
static void ForEachFeature(const FeatureIterCallback& aCallback);
// Run a callback for each enabled fallback.
typedef mozilla::function<void(const char* aName, const char* aMsg)>
FallbackIterCallback;
static void ForEachFallback(const FallbackIterCallback& aCallback);
+ // Get the most descriptive failure id message for this feature.
+ static const nsACString& GetFailureId(Feature aFeature);
+
+ static void Init();
+ static void Shutdown();
+
private:
void ForEachFallbackImpl(const FallbackIterCallback& aCallback);
private:
FeatureState& GetState(Feature aFeature) {
MOZ_ASSERT(size_t(aFeature) < kNumFeatures);
return mFeatures[size_t(aFeature)];
}
--- a/gfx/config/gfxFeature.cpp
+++ b/gfx/config/gfxFeature.cpp
@@ -38,17 +38,18 @@ FeatureState::GetValue() const
}
bool
FeatureState::SetDefault(bool aEnable,
FeatureStatus aDisableStatus,
const char* aDisableMessage)
{
if (!aEnable) {
- DisableByDefault(aDisableStatus, aDisableMessage);
+ DisableByDefault(aDisableStatus, aDisableMessage,
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_DISABLED"));
return false;
}
EnableByDefault();
return true;
}
void
FeatureState::SetDefaultFromPref(const char* aPrefName,
@@ -62,30 +63,30 @@ FeatureState::SetDefaultFromPref(const c
bool userValue = Preferences::GetBool(aPrefName, aDefaultValue);
if (userValue == aIsEnablePref) {
nsCString message("Enabled via ");
message.AppendASCII(aPrefName);
UserEnable(message.get());
} else {
nsCString message("Disabled via ");
message.AppendASCII(aPrefName);
- UserDisable(message.get());
+ UserDisable(message.get(), NS_LITERAL_CSTRING("FEATURE_FAILURE_PREF_OFF"));
}
}
}
bool
FeatureState::InitOrUpdate(bool aEnable,
FeatureStatus aDisableStatus,
const char* aDisableMessage)
{
if (!IsInitialized()) {
return SetDefault(aEnable, aDisableStatus, aDisableMessage);
}
- return MaybeSetFailed(aEnable, aDisableStatus, aDisableMessage);
+ return MaybeSetFailed(aEnable, aDisableStatus, aDisableMessage, nsCString());
}
void
FeatureState::UserEnable(const char* aMessage)
{
AssertInitialized();
SetUser(FeatureStatus::Available, aMessage);
}
@@ -93,60 +94,68 @@ FeatureState::UserEnable(const char* aMe
void
FeatureState::UserForceEnable(const char* aMessage)
{
AssertInitialized();
SetUser(FeatureStatus::ForceEnabled, aMessage);
}
void
-FeatureState::UserDisable(const char* aMessage)
+FeatureState::UserDisable(const char* aMessage, const nsACString& aFailureId)
{
AssertInitialized();
SetUser(FeatureStatus::Disabled, aMessage);
+ SetFailureId(aFailureId);
}
void
-FeatureState::Disable(FeatureStatus aStatus, const char* aMessage)
+FeatureState::Disable(FeatureStatus aStatus, const char* aMessage,
+ const nsACString& aFailureId)
{
AssertInitialized();
// We should never bother setting an environment status to "enabled," since
// it could override an explicit user decision to disable it.
MOZ_ASSERT(IsFeatureStatusFailure(aStatus));
SetEnvironment(aStatus, aMessage);
+ SetFailureId(aFailureId);
}
void
-FeatureState::SetFailed(FeatureStatus aStatus, const char* aMessage)
+FeatureState::SetFailed(FeatureStatus aStatus, const char* aMessage,
+ const nsACString& aFailureId)
{
AssertInitialized();
// We should never bother setting a runtime status to "enabled," since it could
// override an explicit user decision to disable it.
MOZ_ASSERT(IsFeatureStatusFailure(aStatus));
SetRuntime(aStatus, aMessage);
+ SetFailureId(aFailureId);
}
bool
-FeatureState::MaybeSetFailed(bool aEnable, FeatureStatus aStatus, const char* aMessage)
+FeatureState::MaybeSetFailed(bool aEnable, FeatureStatus aStatus, const char* aMessage,
+ const nsACString& aFailureId)
{
if (!aEnable) {
- SetFailed(aStatus, aMessage);
+ SetFailed(aStatus, aMessage, aFailureId);
return false;
}
return true;
}
bool
-FeatureState::MaybeSetFailed(FeatureStatus aStatus, const char* aMessage)
+FeatureState::MaybeSetFailed(FeatureStatus aStatus, const char* aMessage,
+ const nsACString& aFailureId)
{
- return MaybeSetFailed(IsFeatureStatusSuccess(aStatus), aStatus, aMessage);
+ return MaybeSetFailed(IsFeatureStatusSuccess(aStatus), aStatus, aMessage,
+ aFailureId);
}
bool
FeatureState::DisabledByDefault() const
{
AssertInitialized();
return mDefault.mStatus != FeatureStatus::Available;
}
@@ -165,24 +174,26 @@ FeatureState::EnableByDefault()
MOZ_ASSERT(!mUser.IsInitialized());
MOZ_ASSERT(!mEnvironment.IsInitialized());
MOZ_ASSERT(!mRuntime.IsInitialized());
mDefault.Set(FeatureStatus::Available);
}
void
-FeatureState::DisableByDefault(FeatureStatus aStatus, const char* aMessage)
+FeatureState::DisableByDefault(FeatureStatus aStatus, const char* aMessage,
+ const nsACString& aFailureId)
{
// User/runtime decisions should not have been made yet.
MOZ_ASSERT(!mUser.IsInitialized());
MOZ_ASSERT(!mEnvironment.IsInitialized());
MOZ_ASSERT(!mRuntime.IsInitialized());
mDefault.Set(aStatus, aMessage);
+ SetFailureId(aFailureId);
}
void
FeatureState::SetUser(FeatureStatus aStatus, const char* aMessage)
{
// Default decision must have been made, but not runtime or environment.
MOZ_ASSERT(mDefault.IsInitialized());
MOZ_ASSERT(!mEnvironment.IsInitialized());
@@ -229,16 +240,31 @@ FeatureState::ForEachStatusChange(const
aCallback("env", mEnvironment.mStatus, mEnvironment.Message());
}
if (mRuntime.IsInitialized()) {
aCallback("runtime", mRuntime.mStatus, mRuntime.Message());
}
}
void
+FeatureState::SetFailureId(const nsACString& aFailureId)
+{
+ if (mFailureId.IsEmpty()) {
+ mFailureId = aFailureId;
+ }
+}
+
+const nsACString&
+FeatureState::GetFailureId() const
+{
+ MOZ_ASSERT(!IsEnabled());
+ return mFailureId;
+}
+
+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
@@ -5,16 +5,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_gfx_config_gfxFeature_h
#define mozilla_gfx_config_gfxFeature_h
#include <stdint.h>
#include "gfxTelemetry.h"
#include "mozilla/Assertions.h"
#include "mozilla/Function.h"
+#include "nsString.h"
namespace mozilla {
namespace gfx {
#define GFX_FEATURE_MAP(_) \
/* Name, Type, Description */ \
_(HW_COMPOSITING, Feature, "Compositing") \
_(D3D11_COMPOSITING, Feature, "Direct3D11 Compositing") \
@@ -34,58 +35,62 @@ class FeatureState
{
friend class gfxConfig;
public:
bool IsEnabled() const;
FeatureStatus GetValue() const;
void EnableByDefault();
- void DisableByDefault(FeatureStatus aStatus, const char* aMessage);
+ void DisableByDefault(FeatureStatus aStatus, const char* aMessage, const nsACString& aFailureId);
bool SetDefault(bool aEnable, FeatureStatus aDisableStatus, const char* aDisableMessage);
bool InitOrUpdate(bool aEnable,
FeatureStatus aDisableStatus,
const char* aMessage);
void SetDefaultFromPref(const char* aPrefName,
bool aIsEnablePref,
bool aDefaultValue);
void UserEnable(const char* aMessage);
void UserForceEnable(const char* aMessage);
- void UserDisable(const char* aMessage);
- void Disable(FeatureStatus aStatus, const char* aMessage);
- void ForceDisable(FeatureStatus aStatus, const char* aMessage) {
- SetFailed(aStatus, aMessage);
+ void UserDisable(const char* aMessage, const nsACString& aFailureId);
+ void Disable(FeatureStatus aStatus, const char* aMessage, const nsACString& aFailureId);
+ void ForceDisable(FeatureStatus aStatus, const char* aMessage, const nsACString& aFailureId) {
+ SetFailed(aStatus, aMessage, aFailureId);
}
- void SetFailed(FeatureStatus aStatus, const char* aMessage);
- bool MaybeSetFailed(bool aEnable, FeatureStatus aStatus, const char* aMessage);
- bool MaybeSetFailed(FeatureStatus aStatus, const char* aMessage);
+ void SetFailed(FeatureStatus aStatus, const char* aMessage, const nsACString& aFailureId);
+ bool MaybeSetFailed(bool aEnable, FeatureStatus aStatus, const char* aMessage, const nsACString& aFailureId);
+ bool MaybeSetFailed(FeatureStatus aStatus, const char* aMessage, const nsACString& aFailureId);
// aType is "base", "user", "env", or "runtime".
// aMessage may be null.
typedef mozilla::function<void(const char* aType,
FeatureStatus aStatus,
const char* aMessage)> StatusIterCallback;
void ForEachStatusChange(const StatusIterCallback& aCallback) const;
+ const nsACString& GetFailureId() const;
+
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.IsInitialized();
}
void AssertInitialized() const {
MOZ_ASSERT(IsInitialized());
}
private:
+ void SetFailureId(const nsACString& aFailureId);
+
struct Instance {
char mMessage[64];
FeatureStatus mStatus;
void Set(FeatureStatus aStatus, const char* aMessage = nullptr);
bool IsInitialized() const {
return mStatus != FeatureStatus::Unused;
}
@@ -106,14 +111,18 @@ class FeatureState
// The environment state factors in any additional decisions made, such as
// availability or blacklisting.
//
// The runtime state factors in any problems discovered at runtime.
Instance mDefault;
Instance mUser;
Instance mEnvironment;
Instance mRuntime;
+
+ // Store the first reported failureId for now but we might want to track this
+ // by instance later if we need a specific breakdown.
+ nsCString mFailureId;
};
} // namespace gfx
} // namespace mozilla
#endif // mozilla_gfx_config_gfxFeature_h
--- a/gfx/gl/GLLibraryEGL.cpp
+++ b/gfx/gl/GLLibraryEGL.cpp
@@ -168,17 +168,18 @@ GetAndInitDisplay(GLLibraryEGL& egl, voi
static EGLDisplay
GetAndInitDisplayForAccelANGLE(GLLibraryEGL& egl)
{
EGLDisplay ret = 0;
FeatureState& d3d11ANGLE = gfxConfig::GetFeature(Feature::D3D11_HW_ANGLE);
if (!gfxPrefs::WebGLANGLETryD3D11())
- d3d11ANGLE.UserDisable("User disabled D3D11 ANGLE by pref");
+ d3d11ANGLE.UserDisable("User disabled D3D11 ANGLE by pref",
+ NS_LITERAL_CSTRING("FAILURE_ID_ANGLE_PREF"));
if (gfxPrefs::WebGLANGLEForceD3D11())
d3d11ANGLE.UserForceEnable("User force-enabled D3D11 ANGLE on disabled hardware");
if (gfxConfig::IsForcedOnByUser(Feature::D3D11_HW_ANGLE))
return GetAndInitDisplay(egl, LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE);
if (d3d11ANGLE.IsEnabled()) {
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -587,16 +587,18 @@ gfxPlatform::Init()
NS_RUNTIMEABORT("Already started???");
}
gEverInitialized = true;
// Initialize the preferences by creating the singleton.
gfxPrefs::GetSingleton();
MediaPrefs::GetSingleton();
+ gfxConfig::Init();
+
GPUProcessManager::Initialize();
auto fwd = new CrashStatsLogForwarder("GraphicsCriticalError");
fwd->SetCircularBufferSize(gfxPrefs::GfxLoggingCrashLength());
// Drop a note in the crash report if we end up forcing an option that could
// destabilize things. New items should be appended at the end (of an existing
// or in a new section), so that we don't have to know the version to interpret
@@ -852,16 +854,18 @@ gfxPlatform::Shutdown()
gfx::Factory::ShutDown();
delete gGfxPlatformPrefsLock;
gfxPrefs::DestroySingleton();
gfxFont::DestroySingletons();
+ gfxConfig::Shutdown();
+
delete gPlatform;
gPlatform = nullptr;
}
/* static */ void
gfxPlatform::InitLayersIPC()
{
if (sLayersIPCIsUp) {
@@ -2122,34 +2126,37 @@ gfxPlatform::InitCompositorAccelerationP
FeatureState& feature = gfxConfig::GetFeature(Feature::HW_COMPOSITING);
// Base value - does the platform allow acceleration?
if (feature.SetDefault(AccelerateLayersByDefault(),
FeatureStatus::Blocked,
"Acceleration blocked by platform"))
{
if (gfxPrefs::LayersAccelerationDisabledDoNotUseDirectly()) {
- feature.UserDisable("Disabled by pref");
+ feature.UserDisable("Disabled by pref",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_PREF"));
} else if (acceleratedEnv && *acceleratedEnv == '0') {
- feature.UserDisable("Disabled by envvar");
+ feature.UserDisable("Disabled by envvar",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_ENV"));
}
} else {
if (acceleratedEnv && *acceleratedEnv == '1') {
feature.UserEnable("Enabled by envvar");
}
}
// This has specific meaning elsewhere, so we always record it.
if (gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly()) {
feature.UserForceEnable("Force-enabled by pref");
}
// Safe mode trumps everything.
if (InSafeMode()) {
- feature.ForceDisable(FeatureStatus::Blocked, "Acceleration blocked by safe-mode");
+ feature.ForceDisable(FeatureStatus::Blocked, "Acceleration blocked by safe-mode",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_SAFEMODE"));
}
}
bool
gfxPlatform::CanUseHardwareVideoDecoding()
{
// this function is called from the compositor thread, so it is not
// safe to init the prefs etc. from here.
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -555,17 +555,18 @@ gfxWindowsPlatform::CreatePlatformFontLi
pfl = new gfxDWriteFontList();
if (NS_SUCCEEDED(pfl->InitFontList())) {
return pfl;
}
// DWrite font initialization failed! Don't know why this would happen,
// but apparently it can - see bug 594865.
// So we're going to fall back to GDI fonts & rendering.
gfxPlatformFontList::Shutdown();
- DisableD2D(FeatureStatus::Failed, "Failed to initialize fonts");
+ DisableD2D(FeatureStatus::Failed, "Failed to initialize fonts",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_FONT_FAIL"));
}
pfl = new gfxGDIFontList();
if (NS_SUCCEEDED(pfl->InitFontList())) {
return pfl;
}
@@ -575,19 +576,20 @@ gfxWindowsPlatform::CreatePlatformFontLi
// This function will permanently disable D2D for the session. It's intended to
// be used when, after initially chosing to use Direct2D, we encounter a
// scenario we can't support.
//
// This is called during gfxPlatform::Init() so at this point there should be no
// DrawTargetD2D/1 instances.
void
-gfxWindowsPlatform::DisableD2D(FeatureStatus aStatus, const char* aMessage)
+gfxWindowsPlatform::DisableD2D(FeatureStatus aStatus, const char* aMessage,
+ const nsACString& aFailureId)
{
- gfxConfig::SetFailed(Feature::DIRECT2D, aStatus, aMessage);
+ gfxConfig::SetFailed(Feature::DIRECT2D, aStatus, aMessage, aFailureId);
Factory::SetDirect3D11Device(nullptr);
UpdateBackendPrefs();
}
already_AddRefed<gfxASurface>
gfxWindowsPlatform::CreateOffscreenSurface(const IntSize& aSize,
gfxImageFormat aFormat)
{
@@ -1897,30 +1899,29 @@ bool DoesD3D11TextureSharingWork(ID3D11D
}
bool DoesD3D11AlphaTextureSharingWork(ID3D11Device *device)
{
return DoesD3D11TextureSharingWorkInternal(device, DXGI_FORMAT_R8_UNORM, D3D11_BIND_SHADER_RESOURCE);
}
static inline bool
-IsGfxInfoStatusOkay(int32_t aFeature, nsCString* aOutMessage)
+IsGfxInfoStatusOkay(int32_t aFeature, nsCString* aOutMessage, nsCString& aFailureId)
{
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
if (!gfxInfo) {
return true;
}
int32_t status;
- nsCString failureId;
- if (SUCCEEDED(gfxInfo->GetFeatureStatus(aFeature, failureId, &status)) &&
+ if (SUCCEEDED(gfxInfo->GetFeatureStatus(aFeature, aFailureId, &status)) &&
status != nsIGfxInfo::FEATURE_STATUS_OK)
{
aOutMessage->AssignLiteral("#BLOCKLIST_");
- aOutMessage->AppendASCII(failureId.get());
+ aOutMessage->AppendASCII(aFailureId.get());
return false;
}
return true;
}
static inline bool
IsWARPStable()
@@ -1933,25 +1934,28 @@ IsWARPStable()
}
static void
InitializeANGLEConfig()
{
FeatureState& d3d11ANGLE = gfxConfig::GetFeature(Feature::D3D11_HW_ANGLE);
if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
- d3d11ANGLE.DisableByDefault(FeatureStatus::Unavailable, "D3D11 compositing is disabled");
+ d3d11ANGLE.DisableByDefault(FeatureStatus::Unavailable, "D3D11 compositing is disabled",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DISABLED"));
return;
}
d3d11ANGLE.EnableByDefault();
nsCString message;
- if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT3D_11_ANGLE, &message)) {
- d3d11ANGLE.Disable(FeatureStatus::Blacklisted, message.get());
+ nsCString failureId;
+ if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT3D_11_ANGLE, &message,
+ failureId)) {
+ d3d11ANGLE.Disable(FeatureStatus::Blacklisted, message.get(), failureId);
}
}
void
gfxWindowsPlatform::InitializeConfig()
{
if (!XRE_IsParentProcess()) {
@@ -1968,17 +1972,18 @@ gfxWindowsPlatform::InitializeConfig()
void
gfxWindowsPlatform::InitializeD3D9Config()
{
MOZ_ASSERT(XRE_IsParentProcess());
FeatureState& d3d9 = gfxConfig::GetFeature(Feature::D3D9_COMPOSITING);
if (!gfxConfig::IsEnabled(Feature::HW_COMPOSITING)) {
- d3d9.DisableByDefault(FeatureStatus::Unavailable, "Hardware compositing is disabled");
+ d3d9.DisableByDefault(FeatureStatus::Unavailable, "Hardware compositing is disabled",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D9_NEED_HWCOMP"));
return;
}
if (!IsVistaOrLater()) {
d3d9.EnableByDefault();
} else {
d3d9.SetDefaultFromPref(
gfxPrefs::GetLayersAllowD3D9FallbackPrefName(),
@@ -1986,53 +1991,59 @@ gfxWindowsPlatform::InitializeD3D9Config
gfxPrefs::GetLayersAllowD3D9FallbackPrefDefault());
if (!d3d9.IsEnabled() && gfxPrefs::LayersPreferD3D9()) {
d3d9.UserEnable("Direct3D9 enabled via layers.prefer-d3d9");
}
}
nsCString message;
- if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, &message)) {
- d3d9.Disable(FeatureStatus::Blacklisted, message.get());
+ nsCString failureId;
+ if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, &message,
+ failureId)) {
+ d3d9.Disable(FeatureStatus::Blacklisted, message.get(), failureId);
}
if (gfxConfig::IsForcedOnByUser(Feature::HW_COMPOSITING)) {
d3d9.UserForceEnable("Hardware compositing is force-enabled");
}
}
void
gfxWindowsPlatform::InitializeD3D11Config()
{
MOZ_ASSERT(XRE_IsParentProcess());
FeatureState& d3d11 = gfxConfig::GetFeature(Feature::D3D11_COMPOSITING);
if (!gfxConfig::IsEnabled(Feature::HW_COMPOSITING)) {
- d3d11.DisableByDefault(FeatureStatus::Unavailable, "Hardware compositing is disabled");
+ d3d11.DisableByDefault(FeatureStatus::Unavailable, "Hardware compositing is disabled",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_NEED_HWCOMP"));
return;
}
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");
+ d3d11.UserDisable("Disabled due to user preference for Direct3D 9",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_PREF"));
return;
}
nsCString message;
- if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, &message)) {
+ nsCString failureId;
+ if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, &message, failureId)) {
if (IsWARPStable() && !gfxPrefs::LayersD3D11DisableWARP()) {
// We do not expect hardware D3D11 to work, so we'll try WARP.
gfxConfig::EnableFallback(Fallback::USE_D3D11_WARP_COMPOSITOR, message.get());
} else {
// There is little to no chance of D3D11 working, so just disable it.
- d3d11.Disable(FeatureStatus::Blacklisted, message.get());
+ d3d11.Disable(FeatureStatus::Blacklisted, message.get(),
+ failureId);
}
}
// 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");
@@ -2095,35 +2106,39 @@ gfxWindowsPlatform::AttemptD3D11DeviceCr
return true;
}
void
gfxWindowsPlatform::AttemptD3D11DeviceCreation(FeatureState& d3d11)
{
RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
if (!adapter) {
- d3d11.SetFailed(FeatureStatus::Unavailable, "Failed to acquire a DXGI 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");
+ 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");
+ d3d11.SetFailed(FeatureStatus::Failed, "Failed to acquire a D3D11 device",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DEVICE2"));
return;
}
if (!DoesD3D11DeviceWork()) {
- d3d11.SetFailed(FeatureStatus::Broken, "Direct3D11 device was determined to be broken");
+ d3d11.SetFailed(FeatureStatus::Broken, "Direct3D11 device was determined to be broken",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_BROKEN"));
return;
}
{
MutexAutoLock lock(mDeviceLock);
mD3D11Device = device;
}
@@ -2175,24 +2190,26 @@ gfxWindowsPlatform::AttemptWARPDeviceCre
{
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");
+ 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");
+ 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;
}
@@ -2429,23 +2446,25 @@ gfxWindowsPlatform::InitializeD3D11()
}
// 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");
+ 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");
+ 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;
@@ -2504,17 +2523,18 @@ gfxWindowsPlatform::InitializeD3D11()
d3d11Module.disown();
}
void
gfxWindowsPlatform::DisableD3D11AfterCrash()
{
gfxConfig::Disable(Feature::D3D11_COMPOSITING,
FeatureStatus::CrashedInHandler,
- "Crashed while acquiring a Direct3D11 device");
+ "Crashed while acquiring a Direct3D11 device",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_CRASH"));
ResetD3D11Devices();
}
void
gfxWindowsPlatform::ResetD3D11Devices()
{
MutexAutoLock lock(mDeviceLock);
@@ -2525,32 +2545,35 @@ gfxWindowsPlatform::ResetD3D11Devices()
}
void
gfxWindowsPlatform::InitializeD2DConfig()
{
FeatureState& d2d1 = gfxConfig::GetFeature(Feature::DIRECT2D);
if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
- d2d1.DisableByDefault(FeatureStatus::Unavailable, "Direct2D requires Direct3D 11 compositing");
+ d2d1.DisableByDefault(FeatureStatus::Unavailable, "Direct2D requires Direct3D 11 compositing",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_D3D11_COMP"));
return;
}
if (!IsVistaOrLater()) {
- d2d1.DisableByDefault(FeatureStatus::Unavailable, "Direct2D is not available on Windows XP");
+ d2d1.DisableByDefault(FeatureStatus::Unavailable, "Direct2D is not available on Windows XP",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_XP"));
return;
}
d2d1.SetDefaultFromPref(
gfxPrefs::GetDirect2DDisabledPrefName(),
false,
gfxPrefs::GetDirect2DDisabledPrefDefault());
nsCString message;
- if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT2D, &message)) {
- d2d1.Disable(FeatureStatus::Blacklisted, message.get());
+ nsCString failureId;
+ if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT2D, &message, failureId)) {
+ d2d1.Disable(FeatureStatus::Blacklisted, message.get(), failureId);
}
if (!d2d1.IsEnabled() && gfxPrefs::Direct2DForceEnabled()) {
d2d1.UserForceEnable("Force-enabled via user-preference");
}
}
void
@@ -2558,48 +2581,54 @@ gfxWindowsPlatform::InitializeD2D()
{
ScopedGfxFeatureReporter d2d1_1("D2D1.1");
FeatureState& d2d1 = gfxConfig::GetFeature(Feature::DIRECT2D);
// 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) {
- d2d1.Disable(FeatureStatus::Blocked, "Direct2D is not compatible with Direct3D11 WARP");
+ d2d1.Disable(FeatureStatus::Blocked, "Direct2D is not compatible with Direct3D11 WARP",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_WARP_BLOCK"));
}
// If we pass all the initial checks, we can proceed to runtime decisions.
if (!d2d1.IsEnabled()) {
return;
}
if (!Factory::SupportsD2D1()) {
- d2d1.SetFailed(FeatureStatus::Unavailable, "Failed to acquire a Direct2D 1.1 factory");
+ d2d1.SetFailed(FeatureStatus::Unavailable, "Failed to acquire a Direct2D 1.1 factory",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_FACTORY"));
return;
}
if (!mD3D11ContentDevice) {
- d2d1.SetFailed(FeatureStatus::Failed, "Failed to acquire a Direct3D 11 content device");
+ d2d1.SetFailed(FeatureStatus::Failed, "Failed to acquire a Direct3D 11 content device",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_DEVICE"));
return;
}
if (!mCompositorD3D11TextureSharingWorks) {
- d2d1.SetFailed(FeatureStatus::Failed, "Direct3D11 device does not support texture sharing");
+ d2d1.SetFailed(FeatureStatus::Failed, "Direct3D11 device does not support texture sharing",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_TXT_SHARING"));
return;
}
// Using Direct2D depends on DWrite support.
if (!mDWriteFactory && !InitDWriteSupport()) {
- d2d1.SetFailed(FeatureStatus::Failed, "Failed to initialize DirectWrite support");
+ d2d1.SetFailed(FeatureStatus::Failed, "Failed to initialize DirectWrite support",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_DWRITE"));
return;
}
// Verify that Direct2D device creation succeeded.
if (!Factory::SetDirect3D11Device(mD3D11ContentDevice)) {
- d2d1.SetFailed(FeatureStatus::Failed, "Failed to create a Direct2D device");
+ d2d1.SetFailed(FeatureStatus::Failed, "Failed to create a Direct2D device",
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_CREATE_FAILED"));
return;
}
MOZ_ASSERT(d2d1.IsEnabled());
d2d1_1.SetSuccessful();
}
bool
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -279,17 +279,18 @@ private:
void Init();
void InitAcceleration() override;
void InitializeDevices();
void InitializeD3D11();
void InitializeD2D();
bool InitDWriteSupport();
- void DisableD2D(mozilla::gfx::FeatureStatus aStatus, const char* aMessage);
+ void DisableD2D(mozilla::gfx::FeatureStatus aStatus, const char* aMessage,
+ const nsACString& aFailureId);
void InitializeConfig();
void InitializeD3D9Config();
void InitializeD3D11Config();
void InitializeD2DConfig();
void AttemptD3D11DeviceCreation(mozilla::gfx::FeatureState& d3d11);
bool AttemptD3D11DeviceCreationHelper(