Bug 1274012 - use gfxConfig for WebGL prefs. r=dvander draft
authorBenoit Girard <b56girard@gmail.com>
Fri, 20 May 2016 17:45:12 -0400
changeset 369235 31e3444cba670f40dae4ecd3463896f475fd1868
parent 369234 d08b65582a8fa46cb8f1594009fd640eb3e3845e
child 521522 d187b17d79cb8ac4165e74d0d10d73dc8885fed7
push id18805
push userb56girard@gmail.com
push dateFri, 20 May 2016 21:45:30 +0000
reviewersdvander
bugs1274012
milestone49.0a1
Bug 1274012 - use gfxConfig for WebGL prefs. r=dvander MozReview-Commit-ID: Ji4Iu1tIykK
dom/canvas/WebGLContext.cpp
gfx/config/gfxFeature.h
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
gfx/thebes/gfxWindowsPlatform.cpp
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGLContext.h"
 
 #include <queue>
 
 #include "AccessCheck.h"
 #include "gfxContext.h"
+#include "gfxConfig.h"
 #include "gfxCrashReporterUtils.h"
 #include "gfxPattern.h"
 #include "gfxPrefs.h"
 #include "gfxUtils.h"
 #include "GLBlitHelper.h"
 #include "GLContext.h"
 #include "GLContextProvider.h"
 #include "GLReadTexImageHelper.h"
@@ -575,16 +576,20 @@ BaseCaps(const WebGLContextOptions& opti
 
 ////////////////////////////////////////
 
 static already_AddRefed<gl::GLContext>
 CreateGLWithEGL(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
                 WebGLContext* webgl, nsACString* const out_failReason,
                 nsACString* const out_failureId)
 {
+    if (!gfxConfig::IsEnabled(Feature::WEBGL_OPENGL)) {
+        return nullptr;
+    }
+
     const gfx::IntSize dummySize(16, 16);
     RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps,
                                                                      flags);
     if (gl && gl->IsANGLE()) {
         gl = nullptr;
     }
 
     if (!gl) {
@@ -599,16 +604,21 @@ CreateGLWithEGL(const gl::SurfaceCaps& c
     return gl.forget();
 }
 
 static already_AddRefed<GLContext>
 CreateGLWithANGLE(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
                   WebGLContext* webgl, nsACString* const out_failReason,
                   nsACString* const out_failureId)
 {
+    if (!gfxConfig::IsEnabled(Feature::WEBGL_ANGLE)) {
+        *out_failureId = gfxConfig::GetFailureId(Feature::WEBGL_ANGLE);
+        return nullptr;
+    }
+
     const gfx::IntSize dummySize(16, 16);
     RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps,
                                                                      flags);
     if (gl && !gl->IsANGLE()) {
         gl = nullptr;
     }
 
     if (!gl) {
@@ -623,24 +633,17 @@ CreateGLWithANGLE(const gl::SurfaceCaps&
     return gl.forget();
 }
 
 static already_AddRefed<gl::GLContext>
 CreateGLWithDefault(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
                     WebGLContext* webgl, nsACString* const out_failReason,
                     nsACString* const out_failureId)
 {
-    nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
-
-    if (!(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE) &&
-        IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_OPENGL, out_failureId))
-    {
-        if (out_failReason->Length()) {
-            out_failReason->AppendASCII("\n");
-        }
+    if (!gfxConfig::IsEnabled(Feature::WEBGL_OPENGL)) {
         out_failReason->AppendASCII("Refused to create native OpenGL context because of"
                                     " blacklisting.");
         return nullptr;
     }
 
     const gfx::IntSize dummySize(16, 16);
     RefPtr<GLContext> gl = gl::GLContextProvider::CreateOffscreen(dummySize, caps, flags);
 
@@ -695,22 +698,17 @@ WebGLContext::CreateAndInitGLWith(FnCrea
     return true;
 }
 
 bool
 WebGLContext::CreateAndInitGL(bool forceEnabled, nsACString* const out_failReason, nsACString* const out_failureId)
 {
     const bool useEGL = PR_GetEnv("MOZ_WEBGL_PREFER_EGL");
 
-    bool useANGLE = false;
-#ifdef XP_WIN
-    const bool disableANGLE = (gfxPrefs::WebGLDisableANGLE() ||
-                               PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL"));
-    useANGLE = !disableANGLE;
-#endif
+    bool useANGLE = gfxConfig::IsEnabled(Feature::WEBGL_ANGLE);
 
     gl::CreateContextFlags flags = gl::CreateContextFlags::NONE;
     if (forceEnabled) flags |= gl::CreateContextFlags::FORCE_ENABLE_HARDWARE;
     if (!IsWebGL2())  flags |= gl::CreateContextFlags::REQUIRE_COMPAT_PROFILE;
     if (IsWebGL2())   flags |= gl::CreateContextFlags::PREFER_ES3;
 
     const gl::SurfaceCaps baseCaps = BaseCaps(mOptions, this);
 
@@ -879,29 +877,16 @@ WebGLContext::SetDimensions(int32_t sign
         return NS_ERROR_FAILURE;
     }
 
     // increment the generation number - Do this early because later
     // in CreateOffscreenGL(), "default" objects are created that will
     // pick up the old generation.
     ++mGeneration;
 
-    bool disabled = gfxPrefs::WebGLDisabled();
-
-    // TODO: When we have software webgl support we should use that instead.
-    disabled |= gfxPlatform::InSafeMode();
-
-    if (disabled) {
-        Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID,
-                              NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_DISABLED"));
-        const nsLiteralCString text("WebGL is currently disabled.");
-        ThrowEvent_WebGLContextCreationError(text);
-        return NS_ERROR_FAILURE;
-    }
-
     bool failIfPerfCaveat = mOptions.failIfMajorPerformanceCaveat;
     if (gfxPrefs::WebGLDisableFailIfMajorPerformanceCaveat())
         failIfPerfCaveat = false;
 
     if (failIfPerfCaveat) {
         nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
         if (!HasAcceleratedLayers(gfxInfo)) {
             Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID,
--- a/gfx/config/gfxFeature.h
+++ b/gfx/config/gfxFeature.h
@@ -17,16 +17,18 @@ namespace gfx {
 
 #define GFX_FEATURE_MAP(_)                                                        \
   /* Name,                        Type,         Description */                    \
   _(HW_COMPOSITING,               Feature,      "Compositing")                    \
   _(D3D11_COMPOSITING,            Feature,      "Direct3D11 Compositing")         \
   _(D3D9_COMPOSITING,             Feature,      "Direct3D9 Compositing")          \
   _(DIRECT2D,                     Feature,      "Direct2D")                       \
   _(D3D11_ANGLE,                  Feature,      "Direct3D11 ANGLE")               \
+  _(WEBGL_ANGLE,                  Feature,      "WebGL ANGLE")                    \
+  _(WEBGL_OPENGL,                 Feature,      "WebGL OpenGL")                   \
   /* 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
 };
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -764,16 +764,18 @@ gfxPlatform::Init()
     if (skiaCacheSize != kDefaultGlyphCacheSize) {
       SkGraphics::SetFontCacheLimit(skiaCacheSize);
     }
 #endif
 
     ScrollMetadata::sNullMetadata = new ScrollMetadata();
     ClearOnShutdown(&ScrollMetadata::sNullMetadata);
 
+    InitWebGLConfig();
+
     if (obs) {
       obs->NotifyObservers(nullptr, "gfx-features-ready", nullptr);
     }
 }
 
 static bool sLayersIPCIsUp = false;
 
 void
@@ -2445,8 +2447,69 @@ gfxPlatform::SupportsApzDragInput() cons
   return gfxPrefs::APZDragEnabled();
 }
 
 void
 gfxPlatform::BumpDeviceCounter()
 {
   mDeviceCounter++;
 }
+
+void
+gfxPlatform::InitWebGLConfig()
+{
+    FeatureState& webglOpenGLFeature = gfxConfig::GetFeature(Feature::WEBGL_OPENGL);
+    webglOpenGLFeature.SetDefaultFromPref(gfxPrefs::GetWebGLDisabledPrefName(),
+                                          false, gfxPrefs::GetWebGLDisabledPrefDefault());
+
+    FeatureState& webglAngleFeature = gfxConfig::GetFeature(Feature::WEBGL_ANGLE);
+    webglAngleFeature.SetDefaultFromPref(gfxPrefs::GetWebGLDisableANGLEPrefName(),
+                                         false, gfxPrefs::GetWebGLDisableANGLEPrefDefault());
+
+    if (gfxPrefs::WebGLDisabled()) {
+      webglAngleFeature.UserDisable("User disabled WebGL by pref");
+    }
+
+#ifdef XP_WIN
+    if (PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL")) {
+      webglAngleFeature.UserDisable("User disabled, prefer WebGLOpenGL");
+    }
+#endif
+
+    if (InSafeMode()) {
+      webglOpenGLFeature.ForceDisable(FeatureStatus::Blocked, "Acceleration blocked by safe-mode");
+      webglAngleFeature.ForceDisable(FeatureStatus::Blocked, "Acceleration blocked by safe-mode");
+    }
+
+    nsCString message;
+    nsCString failureId;
+
+    if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_WEBGL_OPENGL, &message, &failureId)) {
+      webglOpenGLFeature.Disable(FeatureStatus::Blacklisted, message.get());
+      webglOpenGLFeature.SetFailureId(failureId);
+    }
+
+    if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_WEBGL_ANGLE, &message, &failureId)) {
+      webglAngleFeature.Disable(FeatureStatus::Blacklisted, message.get());
+      webglAngleFeature.SetFailureId(failureId);
+    }
+}
+
+/* static */ bool
+gfxPlatform::IsGfxInfoStatusOkay(int32_t aFeature, nsACString* const aOutMessage, nsACString* const aOutFailureId)
+{
+  nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
+  if (!gfxInfo) {
+    return true;
+  }
+
+  int32_t status;
+  if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(aFeature, *aOutFailureId, &status)) &&
+      status != nsIGfxInfo::FEATURE_STATUS_OK)
+  {
+    aOutMessage->AssignLiteral("#BLOCKLIST_");
+    aOutMessage->AppendASCII(aOutFailureId->BeginReading());
+    return false;
+  }
+
+  return true;
+}
+
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -746,16 +746,25 @@ protected:
     RefPtr<mozilla::gfx::DrawTarget> mScreenReferenceDrawTarget;
 
 private:
     /**
      * Start up Thebes.
      */
     static void Init();
 
+    static void InitWebGLConfig();
+
+    /**
+     * Check the blocklist for a feature. Returns false if the feature is blocked
+     * with an appropriate message and failure ID.
+     * */
+    static bool IsGfxInfoStatusOkay(int32_t aFeature, nsACString* const aOutMessage,
+                                    nsACString* const aOutFailureId);
+
     static void CreateCMSOutputProfile();
 
     static void GetCMSOutputProfileData(void *&mem, size_t &size);
 
     friend void RecordingPrefChanged(const char *aPrefName, void *aClosure);
 
     virtual void GetPlatformCMSOutputProfile(void *&mem, size_t &size);
 
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -1912,37 +1912,16 @@ 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)
-{
-  nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
-  if (!gfxInfo) {
-    return true;
-  }
-
-  int32_t status;
-  nsCString failureId;
-  if (SUCCEEDED(gfxInfo->GetFeatureStatus(aFeature, failureId, &status)) &&
-      status != nsIGfxInfo::FEATURE_STATUS_OK)
-  {
-    aOutMessage->AssignLiteral("#BLOCKLIST_");
-    aOutMessage->AppendASCII(failureId.get());
-    return false;
-  }
-
-  return true;
-}
-
-static inline bool
 IsWARPStable()
 {
   // It seems like nvdxgiwrap makes a mess of WARP. See bug 1154703.
   if (!IsWin8OrLater() || GetModuleHandleA("nvdxgiwrap.dll")) {
     return false;
   }
   return true;
 }
@@ -2011,23 +1990,25 @@ gfxWindowsPlatform::InitializeD3D11Confi
 
   // 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;
   }
 
   nsCString message;
-  if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, &message)) {
+  nsCString failureId;
+  if (!gfxPlatform::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.SetFailureId(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");
 
@@ -2537,18 +2518,20 @@ gfxWindowsPlatform::InitializeD2DConfig(
   }
 
   d2d1.SetDefaultFromPref(
     gfxPrefs::GetDirect2DDisabledPrefName(),
     false,
     gfxPrefs::GetDirect2DDisabledPrefDefault());
 
   nsCString message;
-  if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT2D, &message)) {
+  nsCString failureId,
+  if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT2D, &message, &failureId)) {
     d2d1.Disable(FeatureStatus::Blacklisted, message.get());
+    d3d1.SetFailureId(failureId);
   }
 
   if (!d2d1.IsEnabled() && gfxPrefs::Direct2DForceEnabled()) {
     d2d1.UserForceEnable("Force-enabled via user-preference");
   }
 }
 
 void