From cf1277a469edcd89e60c71efb12d3701d560fcc3 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Thu, 19 Sep 2013 15:37:54 -0700 Subject: [PATCH] Bug 911346 - Add a test for WebGL context creation. - r=bjacob --- .../test/webgl/non-conf-tests/Makefile.in | 4 + .../test/webgl/non-conf-tests/driver-info.js | 125 ++++++++++++++++++ .../non-conf-tests/test_webgl_available.html | 37 ++++++ .../test_webgl_conformance.html | 10 +- .../test/webgl/non-conf-tests/webgl-util.js | 114 ++++++++++++++++ 5 files changed, 287 insertions(+), 3 deletions(-) create mode 100644 content/canvas/test/webgl/non-conf-tests/driver-info.js create mode 100644 content/canvas/test/webgl/non-conf-tests/test_webgl_available.html create mode 100644 content/canvas/test/webgl/non-conf-tests/webgl-util.js diff --git a/content/canvas/test/webgl/non-conf-tests/Makefile.in b/content/canvas/test/webgl/non-conf-tests/Makefile.in index aca1b163808f..bb4dae8c3b53 100644 --- a/content/canvas/test/webgl/non-conf-tests/Makefile.in +++ b/content/canvas/test/webgl/non-conf-tests/Makefile.in @@ -4,6 +4,10 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. MOCHITEST_FILES = \ + driver-info.js \ + webgl-util.js \ + \ + test_webgl_available.html \ test_webgl_conformance.html \ test_webgl_request_mismatch.html \ $(NULL) diff --git a/content/canvas/test/webgl/non-conf-tests/driver-info.js b/content/canvas/test/webgl/non-conf-tests/driver-info.js new file mode 100644 index 000000000000..de2a483ddd3d --- /dev/null +++ b/content/canvas/test/webgl/non-conf-tests/driver-info.js @@ -0,0 +1,125 @@ +DriverInfo = (function() { + // --------------------------------------------------------------------------- + // Debug info handling + + function defaultInfoFunc(str) { + console.log('Info: ' + str); + } + + var gInfoFunc = defaultInfoFunc; + function setInfoFunc(func) { + gInfoFunc = func; + } + + function info(str) { + gInfoFunc(str); + } + + // --------------------------------------------------------------------------- + // OS and driver identification + // Stolen from content/canvas/test/webgl/test_webgl_conformance_test_suite.html + function detectDriverInfo() { + const Cc = SpecialPowers.Cc; + const Ci = SpecialPowers.Ci; + var doc = Cc["@mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser).parseFromString("", "text/html"); + + var canvas = doc.createElement("canvas"); + canvas.width = 1; + canvas.height = 1; + + var type = ""; + var gl; + try { + gl = canvas.getContext("experimental-webgl"); + } catch(e) { + ok(false, "Failed to create a WebGL context for getting driver info."); + return ["", ""] + } + var ext = gl.getExtension("WEBGL_debug_renderer_info"); + // this extension is unconditionally available to chrome. No need to check. + + var webglRenderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL); + var webglVendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL); + return [webglVendor, webglRenderer]; + } + + var OS = { + WINDOWS: 'windows', + MAC: 'mac', + LINUX: 'linux', + ANDROID: 'android', + }; + + var DRIVER = { + MESA: 'mesa', + NVIDIA: 'nvidia', + ANDROID_X86_EMULATOR: 'android x86 emulator', + }; + + var kOS = null; + var kOSVersion = null; + var kDriver = null; + + if (navigator.platform.indexOf('Win') == 0) { + kOS = OS.WINDOWS; + + // code borrowed from browser/modules/test/browser_taskbar_preview.js + var version = SpecialPowers.Services.sysinfo.getProperty('version'); + kOSVersion = parseFloat(version); + // Version 6.0 is Vista, 6.1 is 7. + + } else if (navigator.platform.indexOf('Mac') == 0) { + kOS = OS.MAC; + + var versionMatch = /Mac OS X (\d+.\d+)/.exec(navigator.userAgent); + kOSVersion = versionMatch ? parseFloat(versionMatch[1]) : null; + + } else if (navigator.appVersion.indexOf('Android') != -1) { + kOS = OS.ANDROID; + // From layout/tools/reftest/reftest.js: + kOSVersion = SpecialPowers.Services.sysinfo.getProperty('version'); + + } else if (navigator.platform.indexOf('Linux') == 0) { + // Must be checked after android, as android also has a 'Linux' platform string. + kOS = OS.LINUX; + } + + var glVendor, glRenderer; + [glVendor, glRenderer] = detectDriverInfo(); + info('GL vendor: ' + glVendor); + info('GL renderer: ' + glRenderer); + + if (glRenderer.contains('llvmpipe')) { + kDriver = DRIVER.MESA; + } else if (glRenderer.contains('Android Emulator')) { + kGLDriver = DRIVER.ANDROID_X86_EMULATOR; + } else if (glVendor.contains('NVIDIA')) { + kDriver = DRIVER.NVIDIA; + } + + if (kOS) { + info('OS detected as: ' + kOS); + info(' Version: ' + kOSVersion); + } else { + info('OS not detected.'); + info(' `platform`: ' + navigator.platform); + info(' `appVersion`: ' + navigator.appVersion); + info(' `userAgent`: ' + navigator.userAgent); + } + if (kDriver) { + info('GL driver detected as: ' + kDriver); + } else { + info('GL driver not detected.'); + } + + return { + setInfoFunc: setInfoFunc, + + OS: OS, + DRIVER: DRIVER, + getOS: function() { return kOS; }, + getDriver: function() { return kDriver; }, + getOSVersion: function() { return kOSVersion; }, + }; +})(); + diff --git a/content/canvas/test/webgl/non-conf-tests/test_webgl_available.html b/content/canvas/test/webgl/non-conf-tests/test_webgl_available.html new file mode 100644 index 000000000000..1640b0a0f85d --- /dev/null +++ b/content/canvas/test/webgl/non-conf-tests/test_webgl_available.html @@ -0,0 +1,37 @@ + + + +WebGL test: Check that WebGL works (or not) if it should (or should not). + + + + + + + + + + + diff --git a/content/canvas/test/webgl/non-conf-tests/test_webgl_conformance.html b/content/canvas/test/webgl/non-conf-tests/test_webgl_conformance.html index aad40652d938..a0c3af289f88 100644 --- a/content/canvas/test/webgl/non-conf-tests/test_webgl_conformance.html +++ b/content/canvas/test/webgl/non-conf-tests/test_webgl_conformance.html @@ -1,14 +1,17 @@ + + WebGL test: 'webgl' context request + + - + + diff --git a/content/canvas/test/webgl/non-conf-tests/webgl-util.js b/content/canvas/test/webgl/non-conf-tests/webgl-util.js new file mode 100644 index 000000000000..4621adc93b3c --- /dev/null +++ b/content/canvas/test/webgl/non-conf-tests/webgl-util.js @@ -0,0 +1,114 @@ +WebGLUtil = (function() { + // --------------------------------------------------------------------------- + // Error handling + + function defaultErrorFunc(str) { + console.log('Error: ' + str); + } + + var gErrorFunc = defaultErrorFunc; + function setErrorFunc(func) { + gErrorFunc = func; + } + + function error(str) { + gErrorFunc(str); + } + + // --------------------------------------------------------------------------- + // WebGL helpers + + function getWebGL(canvasId, requireConformant) { + // `requireConformant` will default to falsey if it is not supplied. + + var canvas = document.getElementById(canvasId); + + var gl = null; + try { + gl = canvas.getContext('webgl'); + } catch(e) {} + + if (!gl && !requireConformant) { + try { + gl = canvas.getContext('experimental-webgl'); + } catch(e) {} + } + + if (!gl) { + error('WebGL context could not be retrieved from \'' + canvasId + '\'.'); + return null; + } + + return gl; + } + + function getContentFromElem(elem) { + var str = ""; + var k = elem.firstChild; + while (k) { + if (k.nodeType == 3) + str += k.textContent; + + k = k.nextSibling; + } + + return str; + } + + // Returns a valid shader, or null on errors. + function createShaderById(gl, id) { + var elem = document.getElementById(id); + if (!elem) { + error('Failed to create shader from non-existent id \'' + id + '\'.'); + return null; + } + + var src = getContentById(id); + + var shader; + if (elem.type == "x-shader/x-fragment") { + shader = gl.createShader(gl.FRAGMENT_SHADER); + } else if (shaderScript.type == "x-shader/x-vertex") { + shader = gl.createShader(gl.VERTEX_SHADER); + } else { + error('Bad MIME type for shader \'' + id + '\': ' + elem.type + '.'); + return null; + } + + gl.shaderSource(shader, str); + gl.compileShader(shader); + + return shader; + } + + function createProgramByIds(gl, vsId, fsId) { + var vs = createShaderById(gl, vsId); + var fs = createShaderById(gl, fsId); + if (!vs || !fs) + return null; + + var prog = gl.createProgram(); + gl.attachShader(prog, vs); + gl.attachShader(prog, fs); + gl.linkProgram(prog); + + if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) { + var str = "Shader program linking failed:\n"; + str += "Shader program info log:\n" + gl.getProgramInfoLog(prog) + "\n\n"; + str += "Vert shader log:\n" + gl.getShaderInfoLog(vs) + "\n\n"; + str += "Frag shader log:\n" + gl.getShaderInfoLog(fs); + error(str); + return null; + } + + return prog; + } + + return { + setErrorFunc: setErrorFunc, + + getWebGL: getWebGL, + createShaderById: createShaderById, + createProgramByIds: createProgramByIds, + }; +})();