Bug 911346 - Add a test for WebGL context creation. - r=bjacob

This commit is contained in:
Jeff Gilbert 2013-09-27 19:12:12 -07:00
parent 1c4fa4c5a6
commit 492d0866b9
5 changed files with 321 additions and 3 deletions

View File

@ -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)

View File

@ -0,0 +1,139 @@
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
const Cc = SpecialPowers.Cc;
const Ci = SpecialPowers.Ci;
function detectDriverInfo() {
var doc = Cc["@mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser).parseFromString("<html/>", "text/html");
var canvas = doc.createElement("canvas");
canvas.width = 1;
canvas.height = 1;
var type = "";
var gl = null;
try {
gl = canvas.getContext("experimental-webgl");
} catch(e) {}
if (!gl) {
info('Failed to create WebGL context for querying driver info.');
throw 'WebGL failed';
}
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',
B2G: 'b2g',
};
var DRIVER = {
MESA: 'mesa',
NVIDIA: 'nvidia',
ANDROID_X86_EMULATOR: 'android x86 emulator',
};
var kOS = null;
var kOSVersion = null;
var kDriver = null;
// From reftest.js:
var runtime = Cc['@mozilla.org/xre/app-info;1'].getService(Ci.nsIXULRuntime);
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 (runtime.widgetToolkit == 'gonk') {
kOS = OS.B2G;
} 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;
}
try {
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')) {
kDriver = DRIVER.ANDROID_X86_EMULATOR;
} else if (glVendor.contains('NVIDIA')) {
kDriver = DRIVER.NVIDIA;
}
} catch (e) {
// detectDriverInfo is fallible where WebGL fails.
}
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; },
};
})();

View File

@ -0,0 +1,57 @@
<!DOCTYPE HTML>
<html>
<head>
<title>WebGL test: Check that WebGL works (or not) if it should (or should not).</title>
<script src="/MochiKit/MochiKit.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
<script src="webgl-util.js"></script>
<script src="driver-info.js"></script>
</head>
<body>
<canvas id="c"></canvas>
<script>
function test() {
ok(SpecialPowers.getBoolPref('webgl.force-enabled'), 'WebGL should be force-enabled.');
var shouldSucceed = true;
var shouldFail = false;
if (DriverInfo.getOS() == DriverInfo.OS.ANDROID &&
DriverInfo.getOSVersion() < 15)
{
// Consider 'random'. Actually, ARMv6 fails, and ARMv7 succeeds, but we have
// not been successful at determining this from JS. (see bug 917478)
shouldSucceed = false;
shouldFail = false;
}
if (DriverInfo.getOS() == DriverInfo.OS.B2G) {
// We don't run these mochitests on hardware with WebGL-capable hardware yet.
shouldSucceed = false;
shouldFail = true;
}
var gl = WebGLUtil.getWebGL('c');
if (shouldSucceed) {
ok(gl, 'Expected WebGL creation to succeed.');
}
if (shouldFail) {
ok(!gl, 'Expected WebGL creation to fail.');
}
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
var prefArrArr = [
['webgl.force-enabled', true]
];
var prefEnv = {'set': prefArrArr};
SpecialPowers.pushPrefEnv(prefEnv, test);
</script>
</body>
</html>

View File

@ -1,14 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<title>WebGL test: 'webgl' context request</title>
<script src="/MochiKit/MochiKit.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
<script src="webgl-util.js"></script>
</head>
<body>
<canvas id="c"></canvas>
<script>
var canvas = document.getElementById('c');
var gl = canvas.getContext('webgl');
var gl = WebGLUtil.getWebGL('c', true);
var isMobile = /Mobile/.test(navigator.userAgent);
var isTablet = /Tablet/.test(navigator.userAgent);
@ -23,4 +26,5 @@ if (shouldBeConformant) {
}
</script>
</body>
</html>

View File

@ -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,
};
})();