b=582053; integrate webgl confromance suite as mochitest, angle followup; r=bjacob

This commit is contained in:
Vladimir Vukicevic 2010-09-13 08:53:52 -07:00
parent 0209800a4b
commit 63702122bd
9 changed files with 164 additions and 195 deletions

View File

@ -310,11 +310,13 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
prefService->GetBoolPref("webgl.verbose", &verbose);
mVerbose = verbose;
// Get some prefs for some preferred/overriden things
PRBool forceOSMesa = PR_FALSE;
PRBool preferEGL = PR_FALSE;
prefService->GetBoolPref("webgl.force_osmesa", &forceOSMesa);
prefService->GetBoolPref("webgl.prefer_egl", &preferEGL);
if (!forceOSMesa) {
// Ask GfxInfo about what we should use
PRBool useOpenGL = PR_TRUE;
PRBool useANGLE = PR_TRUE;
@ -337,73 +339,68 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
}
}
#ifdef XP_WIN
// On Windows, we may have a choice of backends, including straight
// OpenGL, D3D through ANGLE via EGL, or straight EGL/GLES2.
// We don't differentiate the latter two yet, but we allow for
// a env var to try EGL first, instead of last.
bool preferEGL = PR_GetEnv("MOZ_WEBGL_PREFER_EGL") != nsnull;
// if we want EGL, try it first
if (!gl && preferEGL && useANGLE) {
gl = gl::GLContextProviderEGL::CreateOffscreen(gfxIntSize(width, height), format);
if (gl && !InitAndValidateGL()) {
gl = nsnull;
}
}
// if it failed, then try the default provider, whatever that is
if (!gl && useOpenGL) {
gl = gl::GLContextProvider::CreateOffscreen(gfxIntSize(width, height), format);
if (gl && !InitAndValidateGL()) {
gl = nsnull;
}
}
// if that failed, and we weren't already preferring EGL, try it now.
if (!gl && !preferEGL && useANGLE) {
gl = gl::GLContextProviderEGL::CreateOffscreen(gfxIntSize(width, height), format);
if (gl && !InitAndValidateGL()) {
gl = nsnull;
}
}
#else
// other platforms just use whatever the default is
if (!gl && useOpenGL) {
gl = gl::GLContextProvider::CreateOffscreen(gfxIntSize(width, height), format);
if (gl && !InitAndValidateGL()) {
gl = nsnull;
}
}
#endif
}
// last chance, try OSMesa
if (!gl) {
// if we're forcing osmesa, do it first
if (forceOSMesa) {
gl = gl::GLContextProviderOSMesa::CreateOffscreen(gfxIntSize(width, height), format);
if (gl) {
if (!InitAndValidateGL()) {
gl = nsnull;
} else {
// make sure we notify always in this case, because it's likely going to be
// painfully slow
LogMessage("WebGL: Using software rendering via OSMesa");
}
if (!gl || !InitAndValidateGL()) {
LogMessage("WebGL: OSMesa forced, but creating context failed -- aborting!");
return NS_ERROR_FAILURE;
}
LogMessage("WebGL: Using software rendering via OSMesa (THIS WILL BE SLOW)");
}
#ifdef XP_WIN
// On Windows, we may have a choice of backends, including straight
// OpenGL, D3D through ANGLE via EGL, or straight EGL/GLES2.
// We don't differentiate the latter two yet, but we allow for
// a env var to try EGL first, instead of last; there's also a pref,
// the env var being set overrides the pref
if (PR_GetEnv("MOZ_WEBGL_PREFER_EGL")) {
preferEGL = PR_TRUE;
}
// force opengl instead of EGL/ANGLE
if (PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL")) {
preferEGL = PR_FALSE;
useANGLE = PR_FALSE;
useOpenGL = PR_TRUE;
}
// if we want EGL, try it first
if (!gl && (preferEGL || useANGLE)) {
gl = gl::GLContextProviderEGL::CreateOffscreen(gfxIntSize(width, height), format);
if (gl && !InitAndValidateGL()) {
gl = nsnull;
}
}
if (!gl) {
if (forceOSMesa) {
LogMessage("WebGL: You set the webgl.force_osmesa preference to true, but OSMesa can't be found. "
"Either install OSMesa and let webgl.osmesalib point to it, "
"or set webgl.force_osmesa back to false.");
} else {
#ifdef XP_WIN
LogMessage("WebGL: Can't get a usable OpenGL context (also tried Direct3D via ANGLE)");
#else
LogMessage("WebGL: Can't get a usable OpenGL context");
#endif
// if it failed, then try the default provider, whatever that is
if (!gl && useOpenGL) {
gl = gl::GLContextProvider::CreateOffscreen(gfxIntSize(width, height), format);
if (gl && !InitAndValidateGL()) {
gl = nsnull;
}
}
// if that failed, and we weren't already preferring EGL, try it now.
if (!gl && !(preferEGL || useANGLE)) {
gl = gl::GLContextProviderEGL::CreateOffscreen(gfxIntSize(width, height), format);
if (gl && !InitAndValidateGL()) {
gl = nsnull;
}
}
#else
// other platforms just use whatever the default is
if (!gl && useOpenGL) {
gl = gl::GLContextProvider::CreateOffscreen(gfxIntSize(width, height), format);
if (gl && !InitAndValidateGL()) {
gl = nsnull;
}
}
#endif
if (!gl) {
LogMessage("WebGL: Can't get a usable WebGL context");
return NS_ERROR_FAILURE;
}

View File

@ -1411,10 +1411,9 @@ WebGLContext::GetConcreteObject(const char *info,
if (!(*aConcreteObject)->IsCompatibleWithContext(this)) {
// the object doesn't belong to this WebGLContext
if (generateErrors) {
if (generateErrors)
ErrorInvalidOperation("%s: object from different WebGL context (or older generation of this one) "
"passed as argument", info);
}
return PR_FALSE;
}
@ -1425,7 +1424,7 @@ WebGLContext::GetConcreteObject(const char *info,
return PR_TRUE;
} else {
if (generateErrors)
ErrorInvalidOperation("%s: deleted object passed as argument", info);
ErrorInvalidValue("%s: deleted object passed as argument", info);
return PR_FALSE;
}
}

View File

@ -2354,7 +2354,7 @@ WebGLContext::GetVertexAttribOffset(WebGLuint index, WebGLenum pname, WebGLuint
NS_IMETHODIMP
WebGLContext::Hint(WebGLenum target, WebGLenum mode)
{
return NS_OK;
return ErrorInvalidEnum("hint: invalid hint");
}
NS_IMETHODIMP

View File

@ -1,6 +1,5 @@
// files that end in .txt list other tests
// other lines are assumed to be .html files
conformance/00_testFIXME_list.txt
more/00_testFIXME_list.txt
// files that end in .txt list other tests
// other lines are assumed to be .html files
conformance/00_testFIXME_list.txt

View File

@ -394,16 +394,12 @@ function testConstructionWithNullBuffer(type, name) {
}
function shouldThrowIndexSizeErr(func, text) {
var errorText = text + " should throw INDEX_SIZE_ERR exception";
var errorText = text + " should throw an exception";
try {
func();
testFailed(errorText);
} catch (e) {
if (e.code != DOMException.INDEX_SIZE_ERR) {
testFailed(errorText);
} else {
testPassed(text + " threw INDEX_SIZE_ERR exception");
}
testPassed(text + " threw an exception");
}
}

View File

@ -60,7 +60,6 @@ function init()
gl = initWebGL("example", "vshader", "fshader", [ "vPosition", "texCoord0"],
[ 0, 0, 0, 1 ], 1);
gl = WebGLDebugUtils.makeDebugContext(gl);
gl.disable(gl.DEPTH_TEST);
gl.disable(gl.BLEND);
@ -125,7 +124,7 @@ function init()
var y = Math.floor(ii / 2);
gl.drawArrays(gl.TRIANGLES, 0, 6);
glErrorShouldBe(gl, gl.INVALID_OPERATION,
"drawing with 2 different targets on the same texture unit should generate INVALID_VALUE");
"drawing with 2 different targets on the same texture unit should generate error");
}
}

View File

@ -1,6 +1,3 @@
conformance/array-buffer-crash.html
conformance/array-buffer-view-crash.html
conformance/array-unit-tests.html
conformance/canvas-test.html
conformance/constants.html
conformance/context-attributes-alpha-depth-stencil-antialias.html
@ -8,18 +5,11 @@ conformance/context-attributes.html
conformance/context-type-test.html
conformance/framebuffer-object-attachment.html
conformance/get-active-test.html
conformance/gl-bind-attrib-location-test.html
conformance/gl-enum-tests.html
conformance/gl-get-active-attribute.html
conformance/gl-get-calls.html
conformance/gl-object-get-calls.html
conformance/gl-teximage.html
conformance/gl-unknown-uniform.html
conformance/glsl-2types-of-textures-on-same-unit.html
conformance/glsl-conformance.html
conformance/invalid-passed-params.html
conformance/methods.html
conformance/point-size.html
conformance/program-test.html
conformance/read-pixels-pack-alignment.html
conformance/tex-image-and-sub-image-2d-with-array-buffer-view.html
@ -28,7 +18,7 @@ conformance/tex-image-and-sub-image-2d-with-video.html
conformance/tex-image-with-format-and-type.html
conformance/tex-image-with-invalid-data.html
conformance/tex-input-validation.html
conformance/viewport-unchanged-upon-resize.html
conformance/texture-active-bind.html
more/conformance/constants.html
more/conformance/getContext.html
more/conformance/quickCheckAPI.html
@ -45,8 +35,6 @@ more/functions/readPixelsBadArgs.html
more/functions/texImage2DBadArgs.html
more/functions/texSubImage2DBadArgs.html
more/functions/texSubImage2DHTMLBadArgs.html
more/functions/uniformfBadArgs.html
more/functions/uniformiBadArgs.html
more/functions/uniformMatrixBadArgs.html
more/glsl/arrayOutOfBounds.html
conformance/renderbuffer-initialization.html

View File

@ -11,17 +11,6 @@ Mochitest version of the WebGL Conformance Test Suite
<script type="text/javascript" src="resources/webgl-test-harness.js"></script>
<script>
function occurencesCount(array, obj) {
var i = array.length;
var result = 0;
while (i--) {
if (array[i] === obj) {
++result;
}
}
return result;
}
/**
* This is copied from webgl-test-harness.js where it is defined as a private function, not accessible to us (argh!)
*
@ -50,59 +39,77 @@ var loadTextFileSynchronous = function(url) {
function start() {
function webglBranch() {
return Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService)
.getBranch("webgl.");
function prefSvc() {
var svc = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService).getBranch("");
return svc;
}
function setEnabledForAllSites(value) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
webglBranch().setBoolPref("enabled_for_all_sites", value);
prefSvc().setBoolPref("webgl.enabled_for_all_sites", value);
}
function getEnabledForAllSites() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
return webglBranch().getBoolPref("enabled_for_all_sites");
return prefSvc().getBoolPref("webgl.enabled_for_all_sites");
}
function setForceOSMesa(value) {
function setAnglePath(path) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
webglBranch().setBoolPref("force_osmesa", value);
if (path == null) {
try {
prefSvc().clearUserPref("gfx.angle.egl.path");
} catch (e) {
// ignore
}
return;
}
try {
var f = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
f.initWithPath(path);
prefSvc().setComplexValue("gfx.angle.egl.path", Components.interfaces.nsILocalFile, f);
} catch (e) {
// ignore -- the path is likely not valid, e.g. trying to use a path of "C:\libs" on non-windows boxes.
}
}
function getForceOSMesa() {
function getAnglePath() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
return webglBranch().getBoolPref("force_osmesa");
if (prefSvc().getPrefType("gfx.angle.egl.path") == Components.interfaces.nsIPrefBranch.PREF_INVALID)
return null;
return prefSvc().getComplexValue("gfx.angle.egl.path", Components.interfaces.nsILocalFile);
}
function getMochitestNativeGL() {
function getPreferEgl() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
return webglBranch().getBoolPref("mochitest_native_gl");
if (prefSvc().getPrefType("webgl.prefer_egl") == Components.interfaces.nsIPrefBranch.PREF_INVALID)
return null;
return prefSvc().getBoolPref("webgl.prefer_egl");
}
function setOSMesaLib(value) {
function setPreferEgl(val) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
webglBranch().setCharPref("osmesalib", value);
}
function getOSMesaLib() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
return webglBranch().getCharPref("osmesalib");
if (val == null) {
prefSvc().clearUserPref("webgl.prefer_egl");
return;
}
prefSvc().setBoolPref("webgl.prefer_egl", val);
}
function restoreOldPrefs() {
setEnabledForAllSites(saved_enabled_for_all_sites);
setForceOSMesa(saved_force_osmesa);
setOSMesaLib(saved_osmesalib);
setAnglePath(saved_angle_path);
setPreferEgl(saved_prefer_egl);
}
function forceOSMesaInThisTestRun() {
return timesTestSuiteAlreadyRun == 1 ? true : false;
}
function GLImplementationName() {
return forceOSMesaInThisTestRun() ? 'OSMesa' : 'default GL';
function getEnv(env) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var envsvc = Components.classes["@mozilla.org/process/environment;1"].getService(Components.interfaces.nsIEnvironment);
var val = envsvc.get(env);
if (val == "")
return null;
return val;
}
var reportType = WebGLTestHarnessModule.TestHarness.reportType;
@ -133,11 +140,11 @@ function start() {
};
Page.prototype.isExpectedToFullyPass = function() {
return occurencesCount(testsExpectedToFail, this.url) == 0;
return testsExpectedToFail.indexOf(this.url) == -1;
}
Page.prototype.errormsg = function(msg) {
return msg + ' (URL: ' + this.url + ', using ' + GLImplementationName() + ')';
return msg + ' (URL: ' + this.url + ')';
}
Page.prototype.addResult = function(msg, success) {
@ -193,26 +200,21 @@ function start() {
++this.totalTimeouts;
if (this.isExpectedToFullyPass()) {
ok(false, this.errormsg('Unexpected timeout in this test page'));
window.dump('WebGL test error: test page timeout: ' + this.url +
' (using ' + GLImplementationName() + ')\n');
window.dump('WebGL test error: test page timeout: ' + this.url + '\n');
}
} else if (this.totalSuccessful != this.totalTests) {
var css = 'testpagefail';
if (this.isExpectedToFullyPass()) {
window.dump('WebGL test error: test page failure: ' + this.url +
' (using ' + GLImplementationName() + ')\n');
window.dump('WebGL test error: test page failure: ' + this.url + '\n');
}
// failures have already been reported for the sub-tests
} else {
var css = 'testpagesuccess';
if (forceOSMesaInThisTestRun()) {
testsSuccessesWithOSMesa.push(this.url);
}
if (this.isExpectedToFullyPass()) {
ok(true, this.errormsg('Successful test page'));
}
window.dump('WebGL test page successful: ' + this.url +
' (using ' + GLImplementationName() + ')\n');
window.dump('WebGL test page successful: ' + this.url + '\n');
testsSuccessful.push(this.url);
}
this.elem.setAttribute('class', css);
this.totalsElem.textContent = msg;
@ -221,8 +223,7 @@ function start() {
var Reporter = function() {
this.localDoc = document;
this.fullResultsElem
= document.getElementById(forceOSMesaInThisTestRun() ? "results-osmesa" : "results-default");
this.fullResultsElem = document.getElementById("results-default");
this.resultElem = document.getElementById("results");
var node = this.localDoc.createTextNode('');
@ -256,7 +257,7 @@ function start() {
Reporter.prototype.startPage = function(url) {
var page = this.pagesByURL[url];
this.currentPage = page;
statusTextNode.textContent = 'Running (' + GLImplementationName() + '), URL: ' + url;
statusTextNode.textContent = 'Running URL: ' + url;
expectedtofailTextNode.textContent = testsExpectedToFail.length +
' test pages are expected to fail out of ' +
this.totalPages;
@ -318,21 +319,21 @@ function start() {
function doRunTests() {
var reporter = new Reporter();
if (!mochitestNativeGL && !forceOSMesaInThisTestRun()) {
var errmsg = "Disabled. By default, we don't run tests on native OpenGL as it can give inconsistent results. " +
"If you want to run tests on native OpenGL, set the preference webgl.mochitest_native_gl to true.";
reporter.fullResultsNode.textContent = errmsg;
reporter.completedCurrentTestSuiteRun();
return;
}
// set WebGL-related preferences needed to run WebGL tests
setEnabledForAllSites(true);
setForceOSMesa(forceOSMesaInThisTestRun());
// if this wasn't specified, then set it to our expected dir for the build
// machines
if (!saved_angle_path) {
// For windows test runners. For everyone else, it doesn't matter,
// we'll use ANGLE if it's installed according to the prefs.
setAnglePath("C:\\libs");
setPreferEgl(true);
}
// try to create a dummy WebGL context, just to catch context creation failures once here,
// rather than having them result in 100's of failures (one in each test page)
var canvas = document.getElementById(forceOSMesaInThisTestRun() ? "webglcheck-osmesa" : "webglcheck-default");
var canvas = document.getElementById("webglcheck-default");
var ctx = null;
try {
ctx = canvas.getContext("experimental-webgl");
@ -354,16 +355,7 @@ function start() {
// that the GL setup needs to be fixed in order for these tests to be actually run. The reason why we don't
// currently want to fail the test is that we want to be able to land this mochitest as soon as possible and
// just take care of the GL setups on the test machines afterwards.
var errmsg = "";
if (forceOSMesaInThisTestRun()) {
errmsg
= "Disabled, because a usable OSMesa was not found. " +
"Install the OSMesa library and let webgl.osmesalib point to it. " +
"This makes the WebGL tests run in a setup that is completely independent from your graphics hardware.";
} else {
errmsg
= "Disabled, because we were unable to create a WebGL context anyhow.";
}
var errmsg = "Disabled, because we were unable to create a WebGL context anyhow.";
reporter.fullResultsNode.textContent = errmsg;
todo(false, errmsg);
reporter.completedCurrentTestSuiteRun();
@ -371,33 +363,38 @@ function start() {
};
function runTestSuite() {
if (timesTestSuiteAlreadyRun == 2) {
for(var i = 0; i < testsExpectedToFail.length; ++i) {
if(occurencesCount(testsSuccessesWithOSMesa, testsExpectedToFail[i]) == 1) {
ok(false, 'The following test page is successful with OSMesa, ' +
'remove it from the list of failing pages: ' +
testsExpectedToFail[i]);
window.dump('WebGL test error: page must be removed from failing_tests.txt: ' +
testsExpectedToFail[i] + '\n');
if (timesTestSuiteAlreadyRun == 1) {
for (var i = 0; i < testsExpectedToFail.length; ++i) {
if (testsSuccessful.indexOf(testsExpectedToFail[i]) != -1) {
todo(false, 'Test expected to fail, but passed: ' + testsExpectedToFail[i]);
dump('Test expected to fail, but passed: ' + testsExpectedToFail[i] + '\n');
}
}
restoreOldPrefs();
statusTextNode.textContent = 'Finished';
SimpleTest.finish();
} else {
doRunTests();
return;
}
doRunTests();
};
SimpleTest.waitForExplicitFinish();
SimpleTest.requestLongerTimeout(2);
if (getEnv("MOZ_WEBGL_TEST_SUITE") == null) {
// webgl test suite is disabled unless the env var is set
todo(false, 'WebGL test suite is disabled!');
SimpleTest.finish();
return;
}
var timesTestSuiteAlreadyRun = 0;
var saved_enabled_for_all_sites = getEnabledForAllSites();
var saved_force_osmesa = getForceOSMesa();
var saved_osmesalib = getOSMesaLib();
var mochitestNativeGL = getMochitestNativeGL();
SimpleTest.waitForExplicitFinish();
SimpleTest.requestLongerTimeout(2);
var saved_angle_path = getAnglePath();
var saved_prefer_egl = getPreferEgl();
var statusElem = document.getElementById("status");
var statusTextNode = document.createTextNode('');
@ -408,7 +405,7 @@ function start() {
expectedtofailElem.appendChild(expectedtofailTextNode);
var testsExpectedToFail = loadTextFileSynchronous('failing_tests.txt').split('\n');
var testsSuccessesWithOSMesa = [];
var testsSuccessful = [];
runTestSuite();
}
@ -429,16 +426,7 @@ function start() {
<div style="border: 1px">
<b>Status:</b> <div><span id="status"></span></div><br />
<b>Results:</b>
<table>
<tr>
<td>With default GL:</td>
<td><div><span id="results-default"></span></div></td>
</tr>
<tr>
<td>With OSMesa:</td>
<td><div><span id="results-osmesa"></span></div></td>
</tr>
</table>
<div><span id="results-default"></span></div>
<br />
<div><span id="expectedtofail"></span></div>
</div>
@ -458,6 +446,5 @@ function start() {
</tr>
</table>
<canvas id="webglcheck-default" style="display: none;"></canvas>
<canvas id="webglcheck-osmesa" style="display: none;"></canvas>
</body>
</html>

View File

@ -519,7 +519,9 @@ public:
// any EGL contexts will always be GLESv2
SetIsGLES2(PR_TRUE);
#ifdef DEBUG
printf_stderr("Initializing context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY());
#endif
}
~GLContextEGL()
@ -532,7 +534,9 @@ public:
if (mGLWidget)
return;
#ifdef DEBUG
printf_stderr("Destroying context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY());
#endif
sEGLLibrary.fDestroyContext(EGL_DISPLAY(), mContext);
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), mSurface);