Bug 1260944 - Fix ANGLE D3D WARP for WebGL. - r=jrmuizel a=ritu
authorJeff Gilbert <jgilbert@mozilla.com>
Wed, 06 Apr 2016 13:47:25 -0700
changeset 326170 7754cd79897df6a4110a1a0b54b2a4a62ea2e353
parent 326169 f139d7717a06c30e68fcdb8d54be45e5ba60c2ee
child 326171 430e684887b691cda24ade3db0d45469bd476d0d
push id1128
push userjlund@mozilla.com
push dateWed, 01 Jun 2016 01:31:59 +0000
treeherdermozilla-release@fe0d30de989d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel, ritu
bugs1260944
milestone47.0
Bug 1260944 - Fix ANGLE D3D WARP for WebGL. - r=jrmuizel a=ritu
dom/canvas/moz.build
dom/canvas/test/webgl-mochitest.ini
dom/canvas/test/webgl-mochitest/test_backends.html
gfx/gl/GLDefs.h
gfx/gl/GLLibraryEGL.cpp
gfx/thebes/gfxPrefs.h
--- a/dom/canvas/moz.build
+++ b/dom/canvas/moz.build
@@ -2,17 +2,17 @@
 # vim: set filetype=python:
 # 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/.
 
 TEST_DIRS += ['compiledtest']
 
 # Number changes to this file to avoid bug 1081323 (clobber after changing a manifest):
-# 11
+# 12
 
 MOCHITEST_MANIFESTS += [
     'test/crossorigin/mochitest.ini',
     'test/mochitest-subsuite-webgl.ini',
     'test/mochitest.ini',
 ]
 
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome/chrome.ini']
--- a/dom/canvas/test/webgl-mochitest.ini
+++ b/dom/canvas/test/webgl-mochitest.ini
@@ -43,16 +43,17 @@ fail-if = (os == 'android') || (os == 'l
 fail-if = (os == 'mac' && os_version == '10.6')
 [webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html]
 # Win7 is 6.1
 fail-if = (os == 'android') || (os == 'win' && (os_version == '5.1' || os_version == '6.1'))
 
 [webgl-mochitest/ensure-exts/test_common.html]
 
 
+[webgl-mochitest/test_backends.html]
 [webgl-mochitest/test_backbuffer_channels.html]
 fail-if = (os == 'b2g')
 [webgl-mochitest/test_depth_readpixels.html]
 [webgl-mochitest/test_capture.html]
 support-files = captureStream_common.js
 [webgl-mochitest/test_cubemap_must_be_square.html]
 [webgl-mochitest/test_depth_tex_lazy_clear.html]
 [webgl-mochitest/test_draw.html]
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/test_backends.html
@@ -0,0 +1,170 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset='UTF-8'>
+  <script src='/tests/SimpleTest/SimpleTest.js'></script>
+  <link rel='stylesheet' href='/tests/SimpleTest/test.css'>
+</head>
+<body>
+<script>
+
+function RunWithPrefs(prefPairList, func) {
+  var prefEnv = {'set': prefPairList};
+  try {
+    SpecialPowers.pushPrefEnv(prefEnv, func);
+  } catch (e) {
+    console.log('Warning: Failed to set prefs: ' + JSON.stringify(prefPairList));
+    func();
+  }
+}
+
+////////////////////////////////////////
+
+var ANGLE_IS_SINGLETON = true;
+
+var expectD3DType;
+try {
+  // code borrowed from browser/modules/test/browser_taskbar_preview.js
+  var version = SpecialPowers.Services.sysinfo.getProperty('version');
+  version = parseFloat(version);
+
+  // Version 6.0 is Vista, 6.1 is 7.
+  // Our Win7 slaves prefer d3d9, though!
+  if (version <= 6.1)
+    expectD3DType = 'd3d9';
+  else
+    expectD3DType = 'd3d11';
+} catch (e) {
+  expectD3DType = 'd3d11';
+}
+
+function GetRenderer() {
+  var c = document.createElement('canvas');
+  var gl = c.getContext('experimental-webgl');
+  if (!gl)
+    return undefined;
+
+  var ext = gl.getExtension('WEBGL_debug_renderer_info');
+  if (!ext)
+    throw new Error('Requires WEBGL_debug_renderer_info.');
+
+  var renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
+  return renderer;
+}
+
+function GetRendererType() {
+  var renderer = GetRenderer();
+  if (renderer === undefined)
+    return 'none';
+
+  if (renderer.includes('ANGLE')) {
+    if (renderer.includes('Microsoft Basic Render Driver')) // Also includes 'Direct3D11'.
+      return 'warp';
+    if (renderer.includes('Direct3D11'))
+      return 'd3d11';
+    if (renderer.includes('Direct3D9'))
+      return 'd3d9';
+
+  } else {
+    return 'gl';
+  }
+
+  throw new Error('Unrecognized renderer type for: ' + renderer);
+}
+
+function TestActualType(testName, expectedType) {
+  var actualType = GetRendererType();
+  ok(actualType == expectedType,
+     '[' + testName + '] Expected ' + expectedType + ', was ' + actualType);
+}
+
+////////////////////////////////////////
+
+function TestDefault() {
+  var expectedType = 'gl';
+  var isWindows = (navigator.platform.indexOf('Win') == 0);
+  if (isWindows) {
+    expectedType = expectD3DType;
+  }
+  TestActualType('TestDefault', expectedType);
+
+  if (isWindows && !ANGLE_IS_SINGLETON) {
+    var prefPairList = [
+      ['webgl.angle.force-warp', true],
+    ];
+    RunWithPrefs(prefPairList, TestWARP);
+    return;
+  }
+
+  var prefPairList = [
+    ['webgl.disabled', true],
+  ];
+  RunWithPrefs(prefPairList, TestDisabled);
+  return;
+}
+
+
+function TestWARP() {
+  var expectedType = (expectD3DType == 'd3d11') ? 'warp' : 'none';
+  TestActualType('TestWARP', expectedType);
+
+  var prefPairList = [
+    ['webgl.angle.force-warp', false],
+    ['webgl.angle.force-d3d11', true],
+  ];
+  RunWithPrefs(prefPairList, TestD3D11);
+}
+
+
+function TestD3D11() {
+  var expectedType = (expectD3DType == 'd3d11') ? 'd3d11' : 'none';
+  TestActualType('TestD3D11', expectedType);
+
+  var prefPairList = [
+    ['webgl.angle.force-d3d11', false],
+    ['webgl.angle.try-d3d11', false],
+  ];
+  RunWithPrefs(prefPairList, TestD3D9);
+}
+
+
+function TestD3D9() {
+  TestActualType('TestD3D9', 'd3d9');
+
+  var prefPairList = [
+    ['webgl.angle.try-d3d11', true],
+    ['webgl.disable-angle', true],
+  ];
+  RunWithPrefs(prefPairList, TestWinGL);
+}
+
+
+function TestWinGL() {
+  TestActualType('TestWinGL', 'gl');
+
+  var prefPairList = [
+    ['webgl.disabled', true],
+  ];
+  RunWithPrefs(prefPairList, TestDisabled);
+}
+
+
+function TestDisabled() {
+  TestActualType('TestDisabled', 'none');
+
+  SimpleTest.finish();
+}
+
+////////////////////////////////////////
+
+SimpleTest.waitForExplicitFinish();
+
+var prefPairList = [
+  ['webgl.force-enabled', true],
+  ['webgl.enable-debug-renderer-info', true],
+];
+RunWithPrefs(prefPairList, TestDefault);
+
+</script>
+</body>
+</html>
--- a/gfx/gl/GLDefs.h
+++ b/gfx/gl/GLDefs.h
@@ -45,34 +45,44 @@
 #define LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA            0x87EE
 
 // EGL_ANDROID_image_crop
 #define LOCAL_EGL_IMAGE_CROP_LEFT_ANDROID               0x3148
 #define LOCAL_EGL_IMAGE_CROP_TOP_ANDROID                0x3149
 #define LOCAL_EGL_IMAGE_CROP_RIGHT_ANDROID              0x314A
 #define LOCAL_EGL_IMAGE_CROP_BOTTOM_ANDROID             0x314B
 
+// EGL_ANGLE_platform_angle
+#define LOCAL_EGL_PLATFORM_ANGLE_ANGLE                      0x3202
+#define LOCAL_EGL_PLATFORM_ANGLE_TYPE_ANGLE                 0x3203
+#define LOCAL_EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE    0x3204
+#define LOCAL_EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE    0x3205
+#define LOCAL_EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE         0x3206
+
+// EGL_ANGLE_platform_angle_d3d
+#define LOCAL_EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE              0x3207
+#define LOCAL_EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE             0x3208
+#define LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE            0x3209
+#define LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE   0x320A
+#define LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE       0x320B
+#define LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE  0x320C
+#define LOCAL_EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE  0x320F
+
+// EGL_ANGLE_direct3d_display
+#define LOCAL_EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE         ((EGLNativeDisplayType)-2)
+#define LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE              ((EGLNativeDisplayType)-3)
+
+// WGL_NV_DX_interop
+#define LOCAL_WGL_ACCESS_READ_ONLY                      0x0000
+#define LOCAL_WGL_ACCESS_READ_WRITE                     0x0001
+#define LOCAL_WGL_ACCESS_WRITE_DISCARD                  0x0002
+
 // Others
 #define LOCAL_EGL_PRESERVED_RESOURCES                   0x3030
 #define LOCAL_EGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
-
-// ANGLE_platform_angle_d3d
-#define LOCAL_EGL_PLATFORM_ANGLE_ANGLE                  0x3201
-#define LOCAL_EGL_PLATFORM_ANGLE_TYPE_ANGLE             0x3202
-#define LOCAL_EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE  0x3206
-
 #define LOCAL_GL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
 #define LOCAL_GL_CONTEXT_LOST                           0x9242
 #define LOCAL_GL_CONTEXT_FLAGS_ARB                      0x2094
 #define LOCAL_GL_CONTEXT_CORE_PROFILE_BIT_ARB           0x00000001
 #define LOCAL_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB  0x00000002
 #define LOCAL_GL_CONTEXT_ROBUST_ACCESS_BIT_ARB          0x00000004
 
-
-#define LOCAL_EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE         ((EGLNativeDisplayType)-2)
-#define LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE              ((EGLNativeDisplayType)-3)
-
-// WGL_NV_DX_interop
-#define LOCAL_WGL_ACCESS_READ_ONLY                           0x0000
-#define LOCAL_WGL_ACCESS_READ_WRITE                          0x0001
-#define LOCAL_WGL_ACCESS_WRITE_DISCARD                       0x0002
-
 #endif
--- a/gfx/gl/GLLibraryEGL.cpp
+++ b/gfx/gl/GLLibraryEGL.cpp
@@ -109,25 +109,34 @@ LoadLibraryForEGLOnWindows(const nsAStri
     return lib;
 }
 
 #endif // XP_WIN
 
 static EGLDisplay
 GetAndInitWARPDisplay(GLLibraryEGL& egl, void* displayType)
 {
-    EGLint attrib_list[] = {  LOCAL_EGL_PLATFORM_ANGLE_TYPE_ANGLE,
-                              LOCAL_EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE,
+    EGLint attrib_list[] = {  LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
+                              LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
+                              // Requires:
+                              LOCAL_EGL_PLATFORM_ANGLE_TYPE_ANGLE,
+                              LOCAL_EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
                               LOCAL_EGL_NONE };
     EGLDisplay display = egl.fGetPlatformDisplayEXT(LOCAL_EGL_PLATFORM_ANGLE_ANGLE,
                                                     displayType,
                                                     attrib_list);
 
-    if (display == EGL_NO_DISPLAY)
+    if (display == EGL_NO_DISPLAY) {
+        const EGLint err = egl.fGetError();
+        if (err != LOCAL_EGL_SUCCESS) {
+            printf_stderr("Unexpected error: 0x%04x", err);
+            MOZ_CRASH("Unexpected error.");
+        }
         return EGL_NO_DISPLAY;
+    }
 
     if (!egl.fInitialize(display, nullptr, nullptr))
         return EGL_NO_DISPLAY;
 
     return display;
 }
 
 static bool
@@ -370,27 +379,25 @@ GLLibraryEGL::EnsureInitialized(bool for
     // Check the ANGLE support the system has
     nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
     mIsANGLE = IsExtensionSupported(ANGLE_platform_angle);
 
     EGLDisplay chosenDisplay = nullptr;
 
     if (IsExtensionSupported(ANGLE_platform_angle_d3d)) {
         bool accelAngleSupport = IsAccelAngleSupported(gfxInfo);
-        bool warpAngleSupport = gfxPlatform::CanUseDirect3D11ANGLE();
 
         bool shouldTryAccel = forceAccel || accelAngleSupport;
-        bool shouldTryWARP = !shouldTryAccel && warpAngleSupport;
+        bool shouldTryWARP = !shouldTryAccel;
         if (gfxPrefs::WebGLANGLEForceWARP()) {
             shouldTryWARP = true;
             shouldTryAccel = false;
         }
 
-        // Fallback to a WARP display if non-WARP is blacklisted,
-        // or if WARP is forced
+        // Fallback to a WARP display if non-WARP is blacklisted, or if WARP is forced.
         if (shouldTryWARP) {
             chosenDisplay = GetAndInitWARPDisplay(*this, EGL_DEFAULT_DISPLAY);
             if (chosenDisplay) {
                 mIsWARP = true;
             }
         }
 
         if (!chosenDisplay) {
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -422,17 +422,17 @@ private:
   DECL_GFX_PREF(Live, "test.mousescroll",                      MouseScrollTestingEnabled, bool, false);
 
   DECL_GFX_PREF(Live, "ui.click_hold_context_menus.delay",     UiClickHoldContextMenusDelay, int32_t, 500);
 
   // WebGL (for pref access from Worker threads)
   DECL_GFX_PREF(Live, "webgl.all-angle-options",               WebGLAllANGLEOptions, bool, false);
   DECL_GFX_PREF(Live, "webgl.angle.force-d3d11",               WebGLANGLEForceD3D11, bool, false);
   DECL_GFX_PREF(Live, "webgl.angle.try-d3d11",                 WebGLANGLETryD3D11, bool, false);
-  DECL_GFX_PREF(Once, "webgl.angle.force-warp",                WebGLANGLEForceWARP, bool, false);
+  DECL_GFX_PREF(Live, "webgl.angle.force-warp",                WebGLANGLEForceWARP, bool, false);
   DECL_GFX_PREF(Live, "webgl.bypass-shader-validation",        WebGLBypassShaderValidator, bool, true);
   DECL_GFX_PREF(Live, "webgl.can-lose-context-in-foreground",  WebGLCanLoseContextInForeground, bool, true);
   DECL_GFX_PREF(Live, "webgl.default-no-alpha",                WebGLDefaultNoAlpha, bool, false);
   DECL_GFX_PREF(Live, "webgl.disable-angle",                   WebGLDisableANGLE, bool, false);
   DECL_GFX_PREF(Live, "webgl.disable-extensions",              WebGLDisableExtensions, bool, false);
   DECL_GFX_PREF(Once, "webgl.dxgl.enabled",                    WebGLDXGLEnabled, bool, false);
 
   DECL_GFX_PREF(Live, "webgl.disable-fail-if-major-performance-caveat",