Add driver crash guards to WebGL. (bug 1190281 part 9, r=jgilbert)
☠☠ backed out by fe6aedfbb45a ☠ ☠
authorDavid Anderson <dvander@alliedmods.net>
Fri, 14 Aug 2015 12:52:37 -0700
changeset 257922 956b56977688149b9022f64550b2195d82a0d825
parent 257897 e8ae270ae0d5abf285d55b35fe8ea8d3bb255e4e
child 257923 7465a399094d44bbcc1f207d302805a4e638ba47
push id29238
push userryanvm@gmail.com
push dateMon, 17 Aug 2015 13:06:57 +0000
treeherdermozilla-central@a6eeb28458fd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs1190281
milestone43.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
Add driver crash guards to WebGL. (bug 1190281 part 9, r=jgilbert)
dom/ipc/ContentParent.cpp
gfx/gl/GLContext.cpp
gfx/src/DriverCrashGuard.cpp
gfx/src/DriverCrashGuard.h
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -5191,16 +5191,19 @@ ContentParent::RecvBeginDriverCrashGuard
   UniquePtr<gfx::DriverCrashGuard> guard;
   switch (gfx::CrashGuardType(aGuardType)) {
     case gfx::CrashGuardType::D3D11Layers:
       guard = MakeUnique<gfx::D3D11LayersCrashGuard>(this);
       break;
     case gfx::CrashGuardType::D3D9Video:
       guard = MakeUnique<gfx::D3D9VideoCrashGuard>(this);
       break;
+    case gfx::CrashGuardType::GLContext:
+      guard = MakeUnique<gfx::GLContextCrashGuard>(this);
+      break;
     default:
       MOZ_ASSERT_UNREACHABLE("unknown crash guard type");
       return false;
   }
 
   if (guard->Crashed()) {
     *aOutCrashed = true;
     return true;
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -25,16 +25,17 @@
 #include "prenv.h"
 #include "prlink.h"
 #include "ScopedGLHelpers.h"
 #include "SharedSurfaceGL.h"
 #include "GfxTexturesReporter.h"
 #include "TextureGarbageBin.h"
 #include "gfx2DGlue.h"
 #include "gfxPrefs.h"
+#include "DriverCrashGuard.h"
 #include "mozilla/IntegerPrintfMacros.h"
 
 #include "OGLShaderProgram.h" // for ShaderProgramType
 
 #include "mozilla/DebugOnly.h"
 
 #ifdef XP_MACOSX
 #include <CoreServices/CoreServices.h>
@@ -363,16 +364,21 @@ GLContext::InitWithPrefix(const char *pr
 {
     ScopedGfxFeatureReporter reporter("GL Context");
 
     if (mInitialized) {
         reporter.SetSuccessful();
         return true;
     }
 
+    GLContextCrashGuard crashGuard;
+    if (crashGuard.Crashed()) {
+        return false;
+    }
+
     mWorkAroundDriverBugs = gfxPrefs::WorkAroundDriverBugs();
 
     SymLoadStruct symbols[] = {
         { (PRFuncPtr*) &mSymbols.fActiveTexture, { "ActiveTexture", "ActiveTextureARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fAttachShader, { "AttachShader", "AttachShaderARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fBindAttribLocation, { "BindAttribLocation", "BindAttribLocationARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fBindBuffer, { "BindBuffer", "BindBufferARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fBindTexture, { "BindTexture", "BindTextureARB", nullptr } },
--- a/gfx/src/DriverCrashGuard.cpp
+++ b/gfx/src/DriverCrashGuard.cpp
@@ -20,16 +20,17 @@
 
 namespace mozilla {
 namespace gfx {
 
 static const size_t NUM_CRASH_GUARD_TYPES = size_t(CrashGuardType::NUM_TYPES);
 static const char* sCrashGuardNames[NUM_CRASH_GUARD_TYPES] = {
   "d3d11layers",
   "d3d9video",
+  "glcontext",
 };
 
 DriverCrashGuard::DriverCrashGuard(CrashGuardType aType, dom::ContentParent* aContentParent)
  : mType(aType)
  , mMode(aContentParent ? Mode::Proxy : Mode::Normal)
  , mInitialized(false)
  , mGuardActivated(false)
  , mCrashDetected(false)
@@ -49,16 +50,24 @@ DriverCrashGuard::InitializeIfNeeded()
 
   mInitialized = true;
   Initialize();
 }
 
 void
 DriverCrashGuard::Initialize()
 {
+  // Using DriverCrashGuard off the main thread currently does not work. Under
+  // e10s it could conceivably work by dispatching the IPC calls via the main
+  // thread. In the parent process this would be harder. For now, we simply
+  // exit early instead.
+  if (!NS_IsMainThread()) {
+    return;
+  }
+
   if (XRE_IsContentProcess()) {
     // Ask the parent whether or not activating the guard is okay. The parent
     // won't bother if it detected a crash.
     dom::ContentChild* cc = dom::ContentChild::GetSingleton();
     cc->SendBeginDriverCrashGuard(uint32_t(mType), &mCrashDetected);
     if (mCrashDetected) {
       LogFeatureDisabled();
       return;
@@ -448,10 +457,55 @@ D3D9VideoCrashGuard::LogCrashRecovery()
 }
 
 void
 D3D9VideoCrashGuard::LogFeatureDisabled()
 {
   gfxCriticalError(CriticalLog::DefaultOptions(false)) << "DXVA2D3D9 video decoding is disabled due to a previous crash.";
 }
 
+GLContextCrashGuard::GLContextCrashGuard(dom::ContentParent* aContentParent)
+ : DriverCrashGuard(CrashGuardType::GLContext, aContentParent)
+{
+}
+
+bool
+GLContextCrashGuard::UpdateEnvironment()
+{
+  static bool checked = false;
+  static bool changed = false;
+
+  if (checked) {
+    return changed;
+  }
+
+  checked = true;
+
+#if defined(XP_WIN)
+  changed |= CheckAndUpdateBoolPref("gfx.driver-init.webgl-angle-force-d3d11",
+                                    gfxPrefs::WebGLANGLEForceD3D11());
+  changed |= CheckAndUpdateBoolPref("gfx.driver-init.webgl-angle-try-d3d11",
+                                    gfxPrefs::WebGLANGLETryD3D11());
+  changed |= CheckAndUpdateBoolPref("gfx.driver-init.webgl-angle-force-warp",
+                                    gfxPrefs::WebGLANGLEForceWARP());
+  changed |= CheckAndUpdateBoolPref("gfx.driver-init.webgl-angle",
+                                    FeatureEnabled(nsIGfxInfo::FEATURE_WEBGL_ANGLE));
+  changed |= CheckAndUpdateBoolPref("gfx.driver-init.direct3d11-angle",
+                                    FeatureEnabled(nsIGfxInfo::FEATURE_DIRECT3D_11_ANGLE));
+#endif
+
+  return changed;
+}
+
+void
+GLContextCrashGuard::LogCrashRecovery()
+{
+  gfxCriticalError(CriticalLog::DefaultOptions(false)) << "GLContext just crashed and is now disabled.";
+}
+
+void
+GLContextCrashGuard::LogFeatureDisabled()
+{
+  gfxCriticalError(CriticalLog::DefaultOptions(false)) << "GLContext is disabled due to a previous crash.";
+}
+
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/src/DriverCrashGuard.h
+++ b/gfx/src/DriverCrashGuard.h
@@ -34,16 +34,17 @@ enum class DriverInitStatus
   // We crashed during driver initialization, and have restarted.
   Crashed
 };
 
 enum class CrashGuardType : uint32_t
 {
   D3D11Layers,
   D3D9Video,
+  GLContext,
   NUM_TYPES
 };
 
 // DriverCrashGuard is used to detect crashes at graphics driver callsites.
 // 
 // If the graphics environment is unrecognized or has changed since the last
 // session, the crash guard will activate and will detect any crashes within
 // the scope of the guard object.
@@ -137,13 +138,24 @@ class D3D9VideoCrashGuard final : public
   explicit D3D9VideoCrashGuard(dom::ContentParent* aContentParent = nullptr);
 
  protected:
   bool UpdateEnvironment() override;
   void LogCrashRecovery() override;
   void LogFeatureDisabled() override;
 };
 
+class GLContextCrashGuard final : public DriverCrashGuard
+{
+ public:
+  explicit GLContextCrashGuard(dom::ContentParent* aContentParent = nullptr);
+
+ protected:
+  bool UpdateEnvironment() override;
+  void LogCrashRecovery() override;
+  void LogFeatureDisabled() override;
+};
+
 } // namespace gfx
 } // namespace mozilla
 
 #endif // gfx_src_DriverCrashGuard_h__