Bug 1171228 - Expose WEBGL_debug_renderer_info to Web Content #ifndef MOZ_RELEASE_BUILD. - r=kamidphish, sr=jst
☠☠ backed out by ad967c23a4ea ☠ ☠
authorJeff Gilbert <jgilbert@mozilla.com>
Thu, 16 Jul 2015 17:20:15 -0700
changeset 273473 f266de469f27eee5f1307e676b9a59e6b64c3238
parent 273472 27c84bc564e9049e6219a66de001360082c4cf54
child 273474 7a5dd58d1b3ddfc8ca967421e38cd8b5a2869826
push id8304
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 19:25:01 +0000
treeherdermozilla-aurora@7308dd0a6c3b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskamidphish, jst
bugs1171228
milestone42.0a1
Bug 1171228 - Expose WEBGL_debug_renderer_info to Web Content #ifndef MOZ_RELEASE_BUILD. - r=kamidphish, sr=jst
dom/canvas/WebGLContextExtensions.cpp
dom/canvas/WebGLContextState.cpp
dom/canvas/test/webgl-mochitest.ini
dom/canvas/test/webgl-mochitest/test_privileged_exts.html
dom/canvas/test/webgl-mochitest/test_renderer_strings.html
modules/libpref/init/all.js
--- a/dom/canvas/WebGLContextExtensions.cpp
+++ b/dom/canvas/WebGLContextExtensions.cpp
@@ -154,16 +154,30 @@ WebGLContext::IsExtensionSupported(WebGL
         return gl->IsExtensionSupported(gl::GLContext::IMG_texture_compression_pvrtc);
     case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
         if (gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_s3tc))
             return true;
 
         return gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_dxt1) &&
                gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt3) &&
                gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt5);
+
+    case WebGLExtensionID::WEBGL_debug_renderer_info:
+        {
+            bool isEnabled = true;
+
+#ifdef RELEASE_BUILD
+            // Keep this disabled on Release and Beta for now. (see bug 1171228)
+            isEnabled = false;
+#endif
+            if (Preferences::GetBool("webgl.disable-debug-renderer-info", false))
+                isEnabled = false;
+
+            return isEnabled;
+        }
     case WebGLExtensionID::WEBGL_depth_texture:
         // WEBGL_depth_texture supports DEPTH_STENCIL textures
         if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil))
             return false;
 
         return gl->IsSupported(gl::GLFeature::depth_texture) ||
                gl->IsExtensionSupported(gl::GLContext::ANGLE_depth_texture);
     case WebGLExtensionID::WEBGL_draw_buffers:
--- a/dom/canvas/WebGLContextState.cpp
+++ b/dom/canvas/WebGLContextState.cpp
@@ -1,24 +1,27 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 "WebGLContext.h"
+
+#include "GLContext.h"
+#include "mozilla/dom/ToJSValue.h"
+#include "mozilla/Preferences.h"
+#include "nsString.h"
+#include "WebGLBuffer.h"
 #include "WebGLContextUtils.h"
-#include "WebGLBuffer.h"
+#include "WebGLFramebuffer.h"
+#include "WebGLProgram.h"
+#include "WebGLRenderbuffer.h"
 #include "WebGLShader.h"
-#include "WebGLProgram.h"
-#include "WebGLFramebuffer.h"
-#include "WebGLRenderbuffer.h"
 #include "WebGLTexture.h"
 #include "WebGLVertexArray.h"
-#include "GLContext.h"
-#include "mozilla/dom/ToJSValue.h"
 
 namespace mozilla {
 
 void
 WebGLContext::Disable(GLenum cap)
 {
     if (IsContextLost())
         return;
@@ -52,16 +55,28 @@ 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* out_stencilBits)
 {
     *out_stencilBits = 0;
     if (mBoundDrawFramebuffer) {
         if (mBoundDrawFramebuffer->HasDepthStencilConflict()) {
             // Error, we don't know which stencil buffer's bits to use
             ErrorInvalidFramebufferOperation("getParameter: framebuffer has two stencil buffers bound");
@@ -171,29 +186,57 @@ WebGLContext::GetParameter(JSContext* cx
             realGLboolean disjoint = LOCAL_GL_FALSE;
             if (gl->IsExtensionSupported(gl::GLContext::EXT_disjoint_timer_query)) {
                 gl->fGetBooleanv(pname, &disjoint);
             }
             return JS::BooleanValue(bool(disjoint));
         }
     }
 
-    // Privileged string params exposed by WEBGL_debug_renderer_info:
+    // Privileged string params exposed by WEBGL_debug_renderer_info.
+    // The privilege check is done in WebGLContext::IsExtensionSupported.
+    // So here we just have to check that the extension is enabled.
     if (IsExtensionEnabled(WebGLExtensionID::WEBGL_debug_renderer_info)) {
         switch (pname) {
         case UNMASKED_VENDOR_WEBGL:
         case UNMASKED_RENDERER_WEBGL:
-            GLenum glstringname = LOCAL_GL_NONE;
-            if (pname == UNMASKED_VENDOR_WEBGL) {
-                glstringname = LOCAL_GL_VENDOR;
-            } else if (pname == UNMASKED_RENDERER_WEBGL) {
-                glstringname = LOCAL_GL_RENDERER;
+            {
+                const char* overridePref = nullptr;
+                GLenum driverEnum = LOCAL_GL_NONE;
+
+                switch (pname) {
+                case UNMASKED_RENDERER_WEBGL:
+                    overridePref = "webgl.renderer-string-override";
+                    driverEnum = LOCAL_GL_RENDERER;
+                    break;
+                case UNMASKED_VENDOR_WEBGL:
+                    overridePref = "webgl.vendor-string-override";
+                    driverEnum = LOCAL_GL_VENDOR;
+                    break;
+                default:
+                    MOZ_CRASH("bad `pname`");
+                }
+
+                bool hasRetVal = false;
+
+                nsAutoString ret;
+                if (overridePref) {
+                    nsresult res = Preferences::GetString(overridePref, &ret);
+                    if (NS_SUCCEEDED(res) && ret.Length() > 0)
+                        hasRetVal = true;
+                }
+
+                if (!hasRetVal) {
+                    const char* chars = reinterpret_cast<const char*>(gl->fGetString(driverEnum));
+                    ret = NS_ConvertASCIItoUTF16(chars);
+                    hasRetVal = true;
+                }
+
+                return StringValue(cx, ret, rv);
             }
-            const GLchar* string = (const GLchar*) gl->fGetString(glstringname);
-            return StringValue(cx, string, rv);
         }
     }
 
     if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives)) {
         if (pname == LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT) {
             GLint i = 0;
             gl->fGetIntegerv(pname, &i);
             return JS::Int32Value(i);
--- a/dom/canvas/test/webgl-mochitest.ini
+++ b/dom/canvas/test/webgl-mochitest.ini
@@ -17,16 +17,17 @@ support-files = captureStream_common.js
 [webgl-mochitest/test_hidden_alpha.html]
 skip-if = (os == 'b2g') || buildapp == 'mulet' # Mulet - bug 1093639 (crashes in libLLVM-3.0.so)
 [webgl-mochitest/test_implicit_color_buffer_float.html]
 [webgl-mochitest/test_highp_fs.html]
 [webgl-mochitest/test_no_arr_points.html]
 skip-if = android_version == '10' || android_version == '18' #Android 2.3 and 4.3 aws only; bug 1030942
 [webgl-mochitest/test_noprog_draw.html]
 [webgl-mochitest/test_privileged_exts.html]
+[webgl-mochitest/test_renderer_strings.html]
 [webgl-mochitest/test_texsubimage_float.html]
 [webgl-mochitest/test_uninit_data.html]
 [webgl-mochitest/test_webgl_available.html]
 skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
 #[webgl-mochitest/test_webgl_color_buffer_float.html]
 # We haven't cleaned up the Try results yet, but let's get this on the books first.
 [webgl-mochitest/test_webgl_conformance.html]
 skip-if = buildapp == 'mulet' || toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests
--- a/dom/canvas/test/webgl-mochitest/test_privileged_exts.html
+++ b/dom/canvas/test/webgl-mochitest/test_privileged_exts.html
@@ -19,14 +19,14 @@ function TestExt(gl, name) {
 (function() {
   var gl = WebGLUtil.getWebGL('c');
   if (!gl) {
     todo(gl, 'Get GL working here first.');
     return;
   }
 
   // Privileged extensions:
-  TestExt(gl, 'WEBGL_debug_renderer_info');
+  TestExt(gl, 'WEBGL_debug_shaders');
 })();
 
 </script>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/test_renderer_strings.html
@@ -0,0 +1,98 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+</head>
+<body>
+<script>
+
+function AssertError(gl, expected, info) {
+  var actual = gl.getError();
+  while (gl.getError()) {}
+
+  ok(actual == expected,
+     'For ' + info + ', expected 0x' + expected.toString(16) + ', got 0x'
+      + actual.toString(16));
+}
+
+var gl;
+
+var RENDERER_OVERRIDE = 'overridden renderer';
+var VENDOR_OVERRIDE = 'overridden vendor';
+
+function TestExt() {
+  var ext = gl.getExtension('WEBGL_debug_renderer_info');
+  ok(ext, 'Should have access to \'WEBGL_debug_renderer_info\'.');
+  AssertError(gl, 0, 'start of test');
+
+  var renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
+  AssertError(gl, 0, 'UNMASKED_RENDERER_WEBGL');
+  ok(renderer,
+     'UNMASKED_RENDERER_WEBGL value should not be empty, was \'' + renderer + '\'');
+
+  var vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);
+  AssertError(gl, 0, 'UNMASKED_VENDOR_WEBGL');
+  ok(vendor, 'UNMASKED_VENDOR_WEBGL value should not be empty, was \'' + vendor + '\'');
+
+  var prefArrArr = [
+    ['webgl.renderer-string-override', RENDERER_OVERRIDE],
+    ['webgl.vendor-string-override', VENDOR_OVERRIDE],
+  ];
+  var prefEnv = {'set': prefArrArr};
+  SpecialPowers.pushPrefEnv(prefEnv, TestOverrides);
+}
+
+function TestOverrides() {
+  var ext = gl.getExtension('WEBGL_debug_renderer_info');
+  ok(ext, 'Should have access to \'WEBGL_debug_renderer_info\'.');
+  AssertError(gl, 0, 'start of test');
+
+  var renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
+  AssertError(gl, 0, 'UNMASKED_RENDERER_WEBGL');
+  ok(renderer == RENDERER_OVERRIDE,
+     'UNMASKED_RENDERER_WEBGL value should be \'' + RENDERER_OVERRIDE + '\', was \''
+     + renderer + '\'');
+
+  var vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);
+  AssertError(gl, 0, 'UNMASKED_VENDOR_WEBGL');
+  ok(vendor == VENDOR_OVERRIDE,
+     'UNMASKED_VENDOR_WEBGL value should be \'' + VENDOR_OVERRIDE + '\', was \'' + vendor
+     + '\'');
+
+  var prefArrArr = [
+    ['webgl.disable-debug-renderer-info', true],
+  ];
+  var prefEnv = {'set': prefArrArr};
+  SpecialPowers.pushPrefEnv(prefEnv, TestDisable);
+}
+
+function TestDisable() {
+  var ext = gl.getExtension('WEBGL_debug_renderer_info');
+  ok(!ext, 'Should not have access to \'WEBGL_debug_renderer_info\'.');
+
+  ok(true, 'Test complete.');
+  SimpleTest.finish();
+}
+
+(function() {
+  var canvas = document.createElement('canvas');
+  gl = canvas.getContext('experimental-webgl');
+  if (!gl) {
+    todo(gl, 'Get WebGL working here first.');
+    ok(true, 'Test complete.');
+    return;
+  }
+
+  SimpleTest.waitForExplicitFinish();
+
+  var prefArrArr = [
+    ['webgl.disable-debug-renderer-info', false],
+  ];
+  var prefEnv = {'set': prefArrArr};
+  SpecialPowers.pushPrefEnv(prefEnv, TestExt);
+})();
+
+</script>
+</body>
+</html>
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4101,16 +4101,18 @@ pref("image.onload.decode.limit", 0);
 
 // WebGL prefs
 #ifdef ANDROID
 // Disable MSAA on mobile.
 pref("gl.msaa-level", 0);
 #else
 pref("gl.msaa-level", 2);
 #endif
+pref("gl.require-hardware", false);
+
 pref("webgl.force-enabled", false);
 pref("webgl.disabled", false);
 pref("webgl.disable-angle", false);
 pref("webgl.min_capability_mode", false);
 pref("webgl.disable-extensions", false);
 pref("webgl.msaa-force", false);
 pref("webgl.prefer-16bpp", false);
 pref("webgl.default-no-alpha", false);
@@ -4119,17 +4121,19 @@ pref("webgl.lose-context-on-memory-press
 pref("webgl.can-lose-context-in-foreground", true);
 pref("webgl.restore-context-when-visible", true);
 pref("webgl.max-warnings-per-context", 32);
 pref("webgl.enable-draft-extensions", false);
 pref("webgl.enable-privileged-extensions", false);
 pref("webgl.bypass-shader-validation", false);
 pref("webgl.enable-prototype-webgl2", false);
 pref("webgl.disable-fail-if-major-performance-caveat", false);
-pref("gl.require-hardware", false);
+pref("webgl.disable-debug-renderer-info", false);
+pref("webgl.renderer-string-override", "");
+pref("webgl.vendor-string-override", "");
 
 #ifdef XP_WIN
 pref("webgl.angle.try-d3d11", true);
 pref("webgl.angle.force-d3d11", false);
 #endif
 
 #ifdef MOZ_WIDGET_GONK
 pref("gfx.gralloc.fence-with-readpixels", false);