Bug 1335296 - Expand about:support WebGL information. - r=qdot,daoshengmu,jrmuizel draft
authorJeff Gilbert <jgilbert@mozilla.com>
Mon, 30 Jan 2017 18:58:52 -0800
changeset 468337 f65d0cee6d1957c878b3acdd7e1b37a0aae29b56
parent 466286 24d9eb148461bb4789848b9880867c63c783a2ca
child 543918 ed9532042e11135a0647c3671aaf9792aaf90cf2
push id43432
push userbmo:jgilbert@mozilla.com
push dateTue, 31 Jan 2017 03:00:36 +0000
reviewersqdot, daoshengmu, jrmuizel
bugs1335296
milestone54.0a1
Bug 1335296 - Expand about:support WebGL information. - r=qdot,daoshengmu,jrmuizel MozReview-Commit-ID: 166aNL6VSOa
dom/bindings/Bindings.conf
dom/canvas/WebGLContextExtensions.cpp
dom/canvas/WebGLContextState.cpp
dom/canvas/WebGLContextUtils.cpp
dom/canvas/WebGLContextUtils.h
dom/canvas/WebGLExtensions.h
dom/canvas/WebGLTypes.h
dom/canvas/moz.build
dom/webidl/WebGLRenderingContext.webidl
gfx/gl/GLContext.h
gfx/gl/GLContextCGL.h
gfx/gl/GLContextEAGL.h
gfx/gl/GLContextEGL.h
gfx/gl/GLContextGLX.h
gfx/gl/GLContextProviderCGL.mm
gfx/gl/GLContextProviderEAGL.mm
gfx/gl/GLContextProviderEGL.cpp
gfx/gl/GLContextProviderGLX.cpp
gfx/gl/GLContextProviderWGL.cpp
gfx/gl/GLContextWGL.h
toolkit/content/aboutSupport.js
toolkit/locales/en-US/chrome/global/aboutSupport.properties
toolkit/modules/Troubleshoot.jsm
toolkit/modules/tests/browser/browser_Troubleshoot.js
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1289,16 +1289,21 @@ DOMInterfaces = {
     'headerFile': 'WebGLExtensions.h'
 },
 
 'EXT_disjoint_timer_query': {
     'nativeType': 'mozilla::WebGLExtensionDisjointTimerQuery',
     'headerFile': 'WebGLExtensions.h'
 },
 
+'MOZ_debug_get': {
+    'nativeType': 'mozilla::WebGLExtensionDebugGet',
+    'headerFile': 'WebGLExtensions.h'
+},
+
 'WebGLFramebuffer': {
     'nativeType': 'mozilla::WebGLFramebuffer',
     'headerFile': 'WebGLFramebuffer.h'
 },
 
 'WebGLProgram': {
     'nativeType': 'mozilla::WebGLProgram',
     'headerFile': 'WebGLProgram.h'
--- a/dom/canvas/WebGLContextExtensions.cpp
+++ b/dom/canvas/WebGLContextExtensions.cpp
@@ -35,16 +35,17 @@ WebGLContext::GetExtensionString(WebGLEx
         WEBGL_EXTENSION_IDENTIFIER(EXT_blend_minmax)
         WEBGL_EXTENSION_IDENTIFIER(EXT_color_buffer_float)
         WEBGL_EXTENSION_IDENTIFIER(EXT_color_buffer_half_float)
         WEBGL_EXTENSION_IDENTIFIER(EXT_frag_depth)
         WEBGL_EXTENSION_IDENTIFIER(EXT_shader_texture_lod)
         WEBGL_EXTENSION_IDENTIFIER(EXT_sRGB)
         WEBGL_EXTENSION_IDENTIFIER(EXT_texture_filter_anisotropic)
         WEBGL_EXTENSION_IDENTIFIER(EXT_disjoint_timer_query)
+        WEBGL_EXTENSION_IDENTIFIER(MOZ_debug_get)
         WEBGL_EXTENSION_IDENTIFIER(OES_element_index_uint)
         WEBGL_EXTENSION_IDENTIFIER(OES_standard_derivatives)
         WEBGL_EXTENSION_IDENTIFIER(OES_texture_float)
         WEBGL_EXTENSION_IDENTIFIER(OES_texture_float_linear)
         WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float)
         WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float_linear)
         WEBGL_EXTENSION_IDENTIFIER(OES_vertex_array_object)
         WEBGL_EXTENSION_IDENTIFIER(WEBGL_color_buffer_float)
@@ -85,16 +86,18 @@ bool WebGLContext::IsExtensionSupported(
     }
 
     if (gfxPrefs::WebGLPrivilegedExtensionsEnabled()) {
         allowPrivilegedExts = true;
     }
 
     if (allowPrivilegedExts) {
         switch (ext) {
+        case WebGLExtensionID::MOZ_debug_get:
+            return true;
         case WebGLExtensionID::WEBGL_debug_renderer_info:
             return true;
         case WebGLExtensionID::WEBGL_debug_shaders:
             return true;
         default:
             // For warnings-as-errors.
             break;
         }
@@ -370,16 +373,21 @@ WebGLContext::EnableExtension(WebGLExten
         break;
     case WebGLExtensionID::EXT_sRGB:
         obj = new WebGLExtensionSRGB(this);
         break;
     case WebGLExtensionID::EXT_texture_filter_anisotropic:
         obj = new WebGLExtensionTextureFilterAnisotropic(this);
         break;
 
+    // MOZ_
+    case WebGLExtensionID::MOZ_debug_get:
+        obj = new WebGLExtensionDebugGet(this);
+        break;
+
     // OES_
     case WebGLExtensionID::OES_element_index_uint:
         obj = new WebGLExtensionElementIndexUint(this);
         break;
     case WebGLExtensionID::OES_standard_derivatives:
         obj = new WebGLExtensionStandardDerivatives(this);
         break;
     case WebGLExtensionID::OES_texture_float:
--- a/dom/canvas/WebGLContextState.cpp
+++ b/dom/canvas/WebGLContextState.cpp
@@ -56,28 +56,16 @@ WebGLContext::Enable(GLenum cap)
     {
         *trackingSlot = 1;
     }
 
     MakeContextCurrent();
     gl->fEnable(cap);
 }
 
-static JS::Value
-StringValue(JSContext* cx, const nsAString& str, ErrorResult& rv)
-{
-    JSString* jsStr = JS_NewUCStringCopyN(cx, str.BeginReading(), str.Length());
-    if (!jsStr) {
-        rv.Throw(NS_ERROR_OUT_OF_MEMORY);
-        return JS::NullValue();
-    }
-
-    return JS::StringValue(jsStr);
-}
-
 bool
 WebGLContext::GetStencilBits(GLint* const out_stencilBits)
 {
     *out_stencilBits = 0;
     if (mBoundDrawFramebuffer) {
         if (mBoundDrawFramebuffer->StencilAttachment().IsDefined() &&
             mBoundDrawFramebuffer->DepthStencilAttachment().IsDefined())
         {
--- a/dom/canvas/WebGLContextUtils.cpp
+++ b/dom/canvas/WebGLContextUtils.cpp
@@ -906,9 +906,23 @@ InfoFrom(WebGLTexImageFunc func, WebGLTe
         default:
             MOZ_CRASH("GFX: invalid 3D TexDimensions");
         }
     default:
         MOZ_CRASH("GFX: invalid TexDimensions");
     }
 }
 
+////
+
+JS::Value
+StringValue(JSContext* cx, const nsAString& str, ErrorResult& er)
+{
+    JSString* jsStr = JS_NewUCStringCopyN(cx, str.BeginReading(), str.Length());
+    if (!jsStr) {
+        er.Throw(NS_ERROR_OUT_OF_MEMORY);
+        return JS::NullValue();
+    }
+
+    return JS::StringValue(jsStr);
+}
+
 } // namespace mozilla
--- a/dom/canvas/WebGLContextUtils.h
+++ b/dom/canvas/WebGLContextUtils.h
@@ -89,11 +89,13 @@ WebGLContext::WebGLObjectAsJSObject(JSCo
 }
 
 /**
  * Return the displayable name for the texture function that is the
  * source for validation.
  */
 const char* InfoFrom(WebGLTexImageFunc func, WebGLTexDimensions dims);
 
+JS::Value StringValue(JSContext* cx, const nsAString& str, ErrorResult& er);
+
 } // namespace mozilla
 
 #endif // WEBGL_CONTEXT_UTILS_H_
--- a/dom/canvas/WebGLExtensions.h
+++ b/dom/canvas/WebGLExtensions.h
@@ -9,16 +9,17 @@
 #include "mozilla/AlreadyAddRefed.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsWrapperCache.h"
 #include "WebGLObjectModel.h"
 #include "WebGLTypes.h"
 
 namespace mozilla {
+class ErrorResult;
 
 namespace dom {
 template<typename> struct Nullable;
 template<typename> class Sequence;
 } // namespace dom
 
 namespace webgl {
 class FormatUsageAuthority;
@@ -398,11 +399,24 @@ public:
     void GetQueryObjectEXT(JSContext* cx, const WebGLQuery& query,
                            GLenum pname, JS::MutableHandleValue retval) const;
 
     static bool IsSupported(const WebGLContext*);
 
     DECL_WEBGL_EXTENSION_GOOP
 };
 
+class WebGLExtensionDebugGet final
+    : public WebGLExtensionBase
+{
+public:
+    explicit WebGLExtensionDebugGet(WebGLContext* webgl);
+    virtual ~WebGLExtensionDebugGet();
+
+    void GetParameter(JSContext* cx, GLenum pname,
+                      JS::MutableHandle<JS::Value> retval, ErrorResult& er) const;
+
+    DECL_WEBGL_EXTENSION_GOOP
+};
+
 } // namespace mozilla
 
 #endif // WEBGL_EXTENSIONS_H_
--- a/dom/canvas/WebGLTypes.h
+++ b/dom/canvas/WebGLTypes.h
@@ -144,16 +144,17 @@ enum class WebGLExtensionID : uint8_t {
     EXT_blend_minmax,
     EXT_color_buffer_float,
     EXT_color_buffer_half_float,
     EXT_frag_depth,
     EXT_sRGB,
     EXT_shader_texture_lod,
     EXT_texture_filter_anisotropic,
     EXT_disjoint_timer_query,
+    MOZ_debug_get,
     OES_element_index_uint,
     OES_standard_derivatives,
     OES_texture_float,
     OES_texture_float_linear,
     OES_texture_half_float,
     OES_texture_half_float_linear,
     OES_vertex_array_object,
     WEBGL_color_buffer_float,
--- a/dom/canvas/moz.build
+++ b/dom/canvas/moz.build
@@ -108,16 +108,17 @@ UNIFIED_SOURCES += [
     'WebGLExtensionColorBufferFloat.cpp',
     'WebGLExtensionColorBufferHalfFloat.cpp',
     'WebGLExtensionCompressedTextureASTC.cpp',
     'WebGLExtensionCompressedTextureATC.cpp',
     'WebGLExtensionCompressedTextureES3.cpp',
     'WebGLExtensionCompressedTextureETC1.cpp',
     'WebGLExtensionCompressedTexturePVRTC.cpp',
     'WebGLExtensionCompressedTextureS3TC.cpp',
+    'WebGLExtensionDebugGet.cpp',
     'WebGLExtensionDebugRendererInfo.cpp',
     'WebGLExtensionDebugShaders.cpp',
     'WebGLExtensionDepthTexture.cpp',
     'WebGLExtensionDisjointTimerQuery.cpp',
     'WebGLExtensionDrawBuffers.cpp',
     'WebGLExtensionElementIndexUint.cpp',
     'WebGLExtensionEXTColorBufferFloat.cpp',
     'WebGLExtensionFragDepth.cpp',
--- a/dom/webidl/WebGLRenderingContext.webidl
+++ b/dom/webidl/WebGLRenderingContext.webidl
@@ -1078,8 +1078,17 @@ interface EXT_disjoint_timer_query {
     void deleteQueryEXT(WebGLQuery? query);
     [WebGLHandlesContextLoss] boolean isQueryEXT(WebGLQuery? query);
     void beginQueryEXT(GLenum target, WebGLQuery query);
     void endQueryEXT(GLenum target);
     void queryCounterEXT(WebGLQuery query, GLenum target);
     any getQueryEXT(GLenum target, GLenum pname);
     any getQueryObjectEXT(WebGLQuery query, GLenum pname);
 };
+
+[NoInterfaceObject]
+interface MOZ_debug_get {
+    const GLenum EXTENSIONS = 0x1F03;
+    const GLenum WSI_INFO   = 0x10000;
+
+    [Throws]
+    any getParameter(GLenum pname);
+};
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -216,16 +216,18 @@ public:
     /**
     * Returns true if the context is using WARP. This should only be overridden
     * for an ANGLE implementation.
     */
     virtual bool IsWARP() const {
         return false;
     }
 
+    virtual void GetWSIInfo(nsCString* const out) const = 0;
+
     /**
      * Return true if we are running on a OpenGL core profile context
      */
     inline bool IsCoreProfile() const {
         MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
 
         return mProfile == ContextProfile::OpenGLCore;
     }
--- a/gfx/gl/GLContextCGL.h
+++ b/gfx/gl/GLContextCGL.h
@@ -53,14 +53,16 @@ public:
 
     virtual bool SetupLookupFunction() override;
 
     virtual bool IsDoubleBuffered() const override;
 
     virtual bool SupportsRobustness() const override { return false; }
 
     virtual bool SwapBuffers() override;
+
+    virtual void GetWSIInfo(nsCString* const out) const override;
 };
 
 } // namespace gl
 } // namespace mozilla
 
 #endif // GLCONTEXTCGL_H_
--- a/gfx/gl/GLContextEAGL.h
+++ b/gfx/gl/GLContextEAGL.h
@@ -50,16 +50,18 @@ public:
     virtual bool SetupLookupFunction() override;
 
     virtual bool IsDoubleBuffered() const override;
 
     virtual bool SupportsRobustness() const override { return false; }
 
     virtual bool SwapBuffers() override;
 
+    virtual void GetWSIInfo(nsCString* const out) const override;
+
     virtual GLuint GetDefaultFramebuffer() override {
         return mBackbufferFB;
     }
 
     virtual bool RenewSurface(nsIWidget* aWidget) override {
         // FIXME: should use the passed widget instead of the existing one.
         return RecreateRB();
     }
--- a/gfx/gl/GLContextEGL.h
+++ b/gfx/gl/GLContextEGL.h
@@ -84,16 +84,18 @@ public:
     virtual bool RenewSurface(nsIWidget* aWidget) override;
 
     virtual void ReleaseSurface() override;
 
     virtual bool SetupLookupFunction() override;
 
     virtual bool SwapBuffers() override;
 
+    virtual void GetWSIInfo(nsCString* const out) const override;
+
     // hold a reference to the given surface
     // for the lifetime of this context.
     void HoldSurface(gfxASurface* aSurf);
 
     EGLSurface GetEGLSurface() const {
         return mSurface;
     }
 
--- a/gfx/gl/GLContextGLX.h
+++ b/gfx/gl/GLContextGLX.h
@@ -54,16 +54,18 @@ public:
     virtual bool SetupLookupFunction() override;
 
     virtual bool IsDoubleBuffered() const override;
 
     virtual bool SupportsRobustness() const override;
 
     virtual bool SwapBuffers() override;
 
+    virtual void GetWSIInfo(nsCString* const out) const override;
+
     // Overrides the current GLXDrawable backing the context and makes the
     // context current.
     bool OverrideDrawable(GLXDrawable drawable);
 
     // Undoes the effect of a drawable override.
     bool RestoreDrawable();
 
 private:
--- a/gfx/gl/GLContextProviderCGL.mm
+++ b/gfx/gl/GLContextProviderCGL.mm
@@ -161,16 +161,21 @@ GLContextCGL::SwapBuffers()
 {
   PROFILER_LABEL("GLContextCGL", "SwapBuffers",
     js::ProfileEntry::Category::GRAPHICS);
 
   [mContext flushBuffer];
   return true;
 }
 
+void
+GLContextCGL::GetWSIInfo(nsCString* const out) const
+{
+    out->AppendLiteral("CGL");
+}
 
 already_AddRefed<GLContext>
 GLContextProviderCGL::CreateWrappingExisting(void*, void*)
 {
     return nullptr;
 }
 
 static const NSOpenGLPixelFormatAttribute kAttribs_singleBuffered[] = {
--- a/gfx/gl/GLContextProviderEAGL.mm
+++ b/gfx/gl/GLContextProviderEAGL.mm
@@ -150,16 +150,21 @@ GLContextEAGL::SwapBuffers()
 {
   PROFILER_LABEL("GLContextEAGL", "SwapBuffers",
     js::ProfileEntry::Category::GRAPHICS);
 
   [mContext presentRenderbuffer:LOCAL_GL_RENDERBUFFER];
   return true;
 }
 
+void
+GLContextEAGL::GetWSIInfo(nsCString* const out) const
+{
+    out->AppendLiteral("EAGL");
+}
 
 already_AddRefed<GLContext>
 GLContextProviderEAGL::CreateWrappingExisting(void*, void*)
 {
     return nullptr;
 }
 
 static GLContextEAGL*
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -414,16 +414,34 @@ GLContextEGL::SwapBuffers()
                           : mSurface;
     if (surface) {
         return sEGLLibrary.fSwapBuffers(EGL_DISPLAY(), surface);
     } else {
         return false;
     }
 }
 
+void
+GLContextEGL::GetWSIInfo(nsCString* const out) const
+{
+    out->AppendLiteral("EGL_VENDOR: ");
+    out->Append((const char*)sEGLLibrary.fQueryString(EGL_DISPLAY(), LOCAL_EGL_VENDOR));
+
+    out->AppendLiteral("\nEGL_VERSION: ");
+    out->Append((const char*)sEGLLibrary.fQueryString(EGL_DISPLAY(), LOCAL_EGL_VERSION));
+
+    out->AppendLiteral("\nEGL_EXTENSIONS: ");
+    out->Append((const char*)sEGLLibrary.fQueryString(EGL_DISPLAY(), LOCAL_EGL_EXTENSIONS));
+
+#ifndef ANDROID // This query will crash some old android.
+    out->AppendLiteral("\nEGL_EXTENSIONS(nullptr): ");
+    out->Append((const char*)sEGLLibrary.fQueryString(nullptr, LOCAL_EGL_EXTENSIONS));
+#endif
+}
+
 // hold a reference to the given surface
 // for the lifetime of this context.
 void
 GLContextEGL::HoldSurface(gfxASurface* aSurf) {
     mThebesSurface = aSurf;
 }
 
 /* static */ EGLSurface
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -993,16 +993,37 @@ bool
 GLContextGLX::SwapBuffers()
 {
     if (!mDoubleBuffered)
         return false;
     mGLX->xSwapBuffers(mDisplay, mDrawable);
     return true;
 }
 
+void
+GLContextGLX::GetWSIInfo(nsCString* const out) const
+{
+    Display* display = DefaultXDisplay();
+    int screen = DefaultScreen(display);
+
+    int majorVersion, minorVersion;
+    xQueryVersion(display, &majorVersion, &minorVersion);
+
+    out->Append(nsPrintfCString("GLX %u.%u", majorVersion, minorVersion));
+
+    out->AppendLiteral("\nGLX_VENDOR(client): ");
+    out->Append(xGetClientString(display, LOCAL_GLX_VENDOR));
+
+    out->AppendLiteral("\nGLX_VENDOR(server): ");
+    out->Append(xQueryServerString(display, screen, LOCAL_GLX_VENDOR));
+
+    out->AppendLiteral("\nExtensions: ");
+    out->Append(xQueryExtensionsString(display, screen));
+}
+
 bool
 GLContextGLX::OverrideDrawable(GLXDrawable drawable)
 {
     if (Screen())
         Screen()->AssureBlitted();
     Bool result = mGLX->xMakeCurrent(mDisplay, drawable, mContext);
     return result;
 }
--- a/gfx/gl/GLContextProviderWGL.cpp
+++ b/gfx/gl/GLContextProviderWGL.cpp
@@ -372,16 +372,23 @@ GLContextWGL::SupportsRobustness() const
 
 bool
 GLContextWGL::SwapBuffers() {
     if (!mIsDoubleBuffered)
         return false;
     return ::SwapBuffers(mDC);
 }
 
+void
+GLContextWGL::GetWSIInfo(nsCString* const out) const
+{
+    out->AppendLiteral("wglGetExtensionsString: ");
+    out->Append(sWGLLib.fGetExtensionsString(mDC));
+}
+
 bool
 GLContextWGL::SetupLookupFunction()
 {
     // Make sure that we have a ref to the OGL library;
     // when run under CodeXL, wglGetProcAddress won't return
     // the right thing for some core functions.
     MOZ_ASSERT(mLibrary == nullptr);
 
--- a/gfx/gl/GLContextWGL.h
+++ b/gfx/gl/GLContextWGL.h
@@ -54,16 +54,18 @@ public:
     virtual bool IsDoubleBuffered() const override;
 
     virtual bool SupportsRobustness() const override;
 
     virtual bool SwapBuffers() override;
 
     virtual bool SetupLookupFunction() override;
 
+    virtual void GetWSIInfo(nsCString* const out) const override;
+
     HGLRC Context() { return mContext; }
 
 protected:
     friend class GLContextProviderWGL;
 
     HDC mDC;
     HGLRC mContext;
     HWND mWnd;
--- a/toolkit/content/aboutSupport.js
+++ b/toolkit/content/aboutSupport.js
@@ -242,19 +242,22 @@ var snapshotFormatters = {
         title = key.substr(1);
       } else {
         try {
           title = strings.GetStringFromName(key);
         } catch (e) {
           title = key;
         }
       }
+      let td = $.new("td", value);
+      td.style["white-space"] = "pre-wrap";
+
       return $.new("tr", [
         $.new("th", title, "column"),
-        $.new("td", value),
+        td,
       ]);
     }
 
     // @where    The name in "graphics-<name>-tbody", of the element to append to.
     // @trs      Array of row elements.
     function addRows(where, trs) {
       $.append($("graphics-" + where + "-tbody"), trs);
     }
@@ -368,18 +371,24 @@ var snapshotFormatters = {
     delete data.numTotalWindows;
     delete data.numAcceleratedWindows;
     delete data.numAcceleratedWindowsMessage;
 
     addRow("features", "asyncPanZoom",
            apzInfo.length
            ? apzInfo.join("; ")
            : localizedMsg(["apzNone"]));
-    addRowFromKey("features", "webglRenderer");
+    addRowFromKey("features", "webgl1Renderer");
+    addRowFromKey("features", "webgl1Version");
+    addRowFromKey("features", "webgl1Extensions");
+    addRowFromKey("features", "webgl1WSIInfo");
     addRowFromKey("features", "webgl2Renderer");
+    addRowFromKey("features", "webgl2Version");
+    addRowFromKey("features", "webgl2Extensions");
+    addRowFromKey("features", "webgl2WSIInfo");
     addRowFromKey("features", "supportsHardwareH264", "hardwareH264");
     addRowFromKey("features", "currentAudioBackend", "audioBackend");
     addRowFromKey("features", "direct2DEnabled", "#Direct2D");
 
     if ("directWriteEnabled" in data) {
       let message = data.directWriteEnabled;
       if ("directWriteVersion" in data)
         message += " (" + data.directWriteVersion + ")";
--- a/toolkit/locales/en-US/chrome/global/aboutSupport.properties
+++ b/toolkit/locales/en-US/chrome/global/aboutSupport.properties
@@ -66,18 +66,24 @@ gpuDescription = Description
 gpuVendorID = Vendor ID
 gpuDeviceID = Device ID
 gpuSubsysID = Subsys ID
 gpuDrivers = Drivers
 gpuRAM = RAM
 gpuDriverVersion = Driver Version
 gpuDriverDate = Driver Date
 gpuActive = Active
-webglRenderer = WebGL Renderer
-webgl2Renderer = WebGL2 Renderer
+webgl1Renderer = WebGL 1 Renderer
+webgl1Version = WebGL 1 GL Version
+webgl1Extensions = WebGL 1 GL Extensions
+webgl1WSIInfo = WebGL 1 WSI Info
+webgl2Renderer = WebGL 2 Renderer
+webgl2Version = WebGL 2 GL Version
+webgl2Extensions = WebGL 2 GL Extensions
+webgl2WSIInfo = WebGL 2 WSI Info
 GPU1 = GPU #1
 GPU2 = GPU #2
 blocklistedBug = Blocklisted due to known issues
 # LOCALIZATION NOTE %1$S will be replaced with a bug number string.
 bugLink = bug %1$S
 # LOCALIZATION NOTE %1$S will be replaced with an arbitrary identifier
 # string that can be searched on DXR/MXR or grepped in the source tree.
 unknownFailure = Blocklisted; failure code %1$S
--- a/toolkit/modules/Troubleshoot.jsm
+++ b/toolkit/modules/Troubleshoot.jsm
@@ -414,63 +414,74 @@ var dataProviders = {
         statusMsgForFeature(Ci.nsIGfxInfo.FEATURE_DIRECT2D);
 
 
     let doc =
       Cc["@mozilla.org/xmlextras/domparser;1"]
       .createInstance(Ci.nsIDOMParser)
       .parseFromString("<html/>", "text/html");
 
-    function GetWebGLInfo(contextType) {
+    function GetWebGLInfo(data, keyPrefix, contextType) {
+        data[keyPrefix + "Renderer"] = "-";
+        data[keyPrefix + "Version"] = "-";
+        data[keyPrefix + "Extensions"] = "-";
+        data[keyPrefix + "WSIInfo"] = "-";
+
+        ////
+
         let canvas = doc.createElement("canvas");
         canvas.width = 1;
         canvas.height = 1;
 
+        ////
 
         let creationError = null;
 
         canvas.addEventListener(
             "webglcontextcreationerror",
 
             function(e) {
                 creationError = e.statusMessage;
             }
         );
 
         let gl = null;
         try {
-          gl = canvas.getContext(contextType);
+            gl = canvas.getContext(contextType);
         } catch (e) {
-          if (!creationError) {
-            creationError = e.toString();
-          }
+            if (!creationError) {
+                creationError = e.toString();
+            }
         }
-        if (!gl)
-            return creationError || "(no info)";
+        if (!gl) {
+            data[keyPrefix + "Renderer"] = creationError || "(no creation error info)";
+            return;
+        }
 
+        ////
 
-        let infoExt = gl.getExtension("WEBGL_debug_renderer_info");
+        let ext = gl.getExtension("MOZ_debug_get");
         // This extension is unconditionally available to chrome. No need to check.
-        let vendor = gl.getParameter(infoExt.UNMASKED_VENDOR_WEBGL);
-        let renderer = gl.getParameter(infoExt.UNMASKED_RENDERER_WEBGL);
+        let vendor = ext.getParameter(gl.VENDOR);
+        let renderer = ext.getParameter(gl.RENDERER);
 
-        let contextInfo = vendor + " -- " + renderer;
+        data[keyPrefix + "Renderer"] = vendor + " -- " + renderer;
+        data[keyPrefix + "Version"] = ext.getParameter(gl.VERSION);
+        data[keyPrefix + "Extensions"] = ext.getParameter(ext.EXTENSIONS);
+        data[keyPrefix + "WSIInfo"] = ext.getParameter(ext.WSI_INFO);
 
+        ////
 
         // Eagerly free resources.
         let loseExt = gl.getExtension("WEBGL_lose_context");
         loseExt.loseContext();
-
-
-        return contextInfo;
     }
 
-
-    data.webglRenderer = GetWebGLInfo("webgl");
-    data.webgl2Renderer = GetWebGLInfo("webgl2");
+    GetWebGLInfo(data, "webgl1", "webgl");
+    GetWebGLInfo(data, "webgl2", "webgl2");
 
 
     let infoInfo = gfxInfo.getInfo();
     if (infoInfo)
       data.info = infoInfo;
 
     let failureCount = {};
     let failureIndices = {};
--- a/toolkit/modules/tests/browser/browser_Troubleshoot.js
+++ b/toolkit/modules/tests/browser/browser_Troubleshoot.js
@@ -292,22 +292,40 @@ const SNAPSHOT_SCHEMA = {
           type: "boolean",
         },
         directWriteVersion: {
           type: "string",
         },
         clearTypeParameters: {
           type: "string",
         },
-        webglRenderer: {
+        webgl1Renderer: {
+          type: "string",
+        },
+        webgl1Version: {
+          type: "string",
+        },
+        webgl1Extensions: {
+          type: "string",
+        },
+        webgl1WSIInfo: {
           type: "string",
         },
         webgl2Renderer: {
           type: "string",
         },
+        webgl2Version: {
+          type: "string",
+        },
+        webgl2Extensions: {
+          type: "string",
+        },
+        webgl2WSIInfo: {
+          type: "string",
+        },
         info: {
           type: "object",
         },
         failures: {
           type: "array",
           items: {
             type: "string",
           },