summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/js/tests/canvas-tests-utils.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/tests/canvas-tests-utils.js825
1 files changed, 825 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/canvas-tests-utils.js b/dom/canvas/test/webgl-conf/checkout/js/tests/canvas-tests-utils.js
new file mode 100644
index 0000000000..7c30104379
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/canvas-tests-utils.js
@@ -0,0 +1,825 @@
+/*
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+*/
+
+// Some variables that will be used in this file
+var canvas;
+var gl;
+var OES_vertex_array_object;
+var uniformLocation;
+var extension;
+var buffer;
+var framebuffer;
+var program;
+var renderbuffer;
+var shader;
+var texture;
+var arrayBuffer;
+var arrayBufferView;
+var vertexArrayObject;
+var imageData;
+var float32array;
+var int32array;
+
+var OES_texture_float;
+var new_WEBGL_lose_context;
+var allowRestore;
+var contextLostEventFired;
+var contextRestoredEventFired;
+var newExtension;
+
+function compareGLError(glError, evalStr) {
+ var exception;
+ try {
+ eval(evalStr);
+ } catch (e) {
+ exception = e;
+ }
+ if (exception) {
+ return false;
+ } else {
+ if (gl.getError() == glError)
+ return true;
+ return false;
+ }
+}
+
+function contextCreation(contextType) {
+ canvas = new OffscreenCanvas(10, 10);
+ gl = canvas.getContext(contextType);
+
+ if (contextType == 'webgl') {
+ if (gl instanceof WebGLRenderingContext)
+ return true;
+ return false;
+ } else if (contextType == 'webgl2') {
+ if (gl instanceof WebGL2RenderingContext)
+ return true;
+ return false;
+ } else {
+ return false;
+ }
+}
+
+function transferredOffscreenCanvasCreation(placeholder, width, height) {
+ placeholder.width = width;
+ placeholder.height = height;
+ return placeholder.transferControlToOffscreen();
+}
+
+function assertWidthAndHeight(entity, entityName, width, height) {
+ if (entity.width == width && entity.height == height) {
+ testPassed("The width and height of " + entityName + " are correct.");
+ return;
+ }
+ var errMsg = "";
+ if (entity.width != width) {
+ errMsg += "The width of " + entityName + " is " + entity.width + " while expected value is " + width + ". ";
+ }
+ if (entity.height != height) {
+ errMsg += "The height of " + entityName + " is " + entity.height + " while expected value is " + height + ". ";
+ }
+ testFailed(errMsg);
+}
+
+var webgl1Methods = [
+ "getContextAttributes",
+ "activeTexture",
+ "attachShader",
+ "bindAttribLocation",
+ "bindBuffer",
+ "bindFramebuffer",
+ "bindRenderbuffer",
+ "bindTexture",
+ "blendColor",
+ "blendEquation",
+ "blendEquationSeparate",
+ "blendFunc",
+ "blendFuncSeparate",
+ "bufferData",
+ "bufferSubData",
+ "checkFramebufferStatus",
+ "clear",
+ "clearColor",
+ "clearDepth",
+ "clearStencil",
+ "colorMask",
+ "compileShader",
+ "compressedTexImage2D",
+ "compressedTexSubImage2D",
+ "copyTexImage2D",
+ "copyTexSubImage2D",
+ "createBuffer",
+ "createFramebuffer",
+ "createProgram",
+ "createRenderbuffer",
+ "createShader",
+ "createTexture",
+ "cullFace",
+ "deleteBuffer",
+ "deleteFramebuffer",
+ "deleteProgram",
+ "deleteRenderbuffer",
+ "deleteShader",
+ "deleteTexture",
+ "depthFunc",
+ "depthMask",
+ "depthRange",
+ "detachShader",
+ "disable",
+ "disableVertexAttribArray",
+ "drawArrays",
+ "drawElements",
+ "enable",
+ "enableVertexAttribArray",
+ "finish",
+ "flush",
+ "framebufferRenderbuffer",
+ "framebufferTexture2D",
+ "frontFace",
+ "generateMipmap",
+ "getActiveAttrib",
+ "getActiveUniform",
+ "getAttachedShaders",
+ "getAttribLocation",
+ "getParameter",
+ "getBufferParameter",
+ "getError",
+ "getExtension",
+ "getFramebufferAttachmentParameter",
+ "getProgramParameter",
+ "getProgramInfoLog",
+ "getRenderbufferParameter",
+ "getShaderParameter",
+ "getShaderInfoLog",
+ "getShaderPrecisionFormat",
+ "getShaderSource",
+ "getSupportedExtensions",
+ "getTexParameter",
+ "getUniform",
+ "getUniformLocation",
+ "getVertexAttrib",
+ "getVertexAttribOffset",
+ "hint",
+ "isBuffer",
+ "isContextLost",
+ "isEnabled",
+ "isFramebuffer",
+ "isProgram",
+ "isRenderbuffer",
+ "isShader",
+ "isTexture",
+ "lineWidth",
+ "linkProgram",
+ "pixelStorei",
+ "polygonOffset",
+ "readPixels",
+ "renderbufferStorage",
+ "sampleCoverage",
+ "scissor",
+ "shaderSource",
+ "stencilFunc",
+ "stencilFuncSeparate",
+ "stencilMask",
+ "stencilMaskSeparate",
+ "stencilOp",
+ "stencilOpSeparate",
+ "texImage2D",
+ "texParameterf",
+ "texParameteri",
+ "texSubImage2D",
+ "uniform1f",
+ "uniform1fv",
+ "uniform1i",
+ "uniform1iv",
+ "uniform2f",
+ "uniform2fv",
+ "uniform2i",
+ "uniform2iv",
+ "uniform3f",
+ "uniform3fv",
+ "uniform3i",
+ "uniform3iv",
+ "uniform4f",
+ "uniform4fv",
+ "uniform4i",
+ "uniform4iv",
+ "uniformMatrix2fv",
+ "uniformMatrix3fv",
+ "uniformMatrix4fv",
+ "useProgram",
+ "validateProgram",
+ "vertexAttrib1f",
+ "vertexAttrib1fv",
+ "vertexAttrib2f",
+ "vertexAttrib2fv",
+ "vertexAttrib3f",
+ "vertexAttrib3fv",
+ "vertexAttrib4f",
+ "vertexAttrib4fv",
+ "vertexAttribPointer",
+ "viewport",
+];
+
+var webgl2Methods = [
+ "getBufferSubData",
+ "copyBufferSubData",
+ "blitFramebuffer",
+ "framebufferTextureLayer",
+ "getInternalformatParameter",
+ "invalidateFramebuffer",
+ "invalidateSubFramebuffer",
+ "readBuffer",
+ "renderbufferStorageMultisample",
+ "texImage3D",
+ "texStorage2D",
+ "texStorage3D",
+ "texSubImage3D",
+ "copyTexSubImage3D",
+ "compressedTexImage3D",
+ "compressedTexSubImage3D",
+ "getFragDataLocation",
+ "uniform1ui",
+ "uniform2ui",
+ "uniform3ui",
+ "uniform4ui",
+ "uniform1uiv",
+ "uniform2uiv",
+ "uniform3uiv",
+ "uniform4uiv",
+ "uniformMatrix2x3fv",
+ "uniformMatrix3x2fv",
+ "uniformMatrix2x4fv",
+ "uniformMatrix4x2fv",
+ "uniformMatrix3x4fv",
+ "uniformMatrix4x3fv",
+ "vertexAttribI4i",
+ "vertexAttribI4iv",
+ "vertexAttribI4ui",
+ "vertexAttribI4uiv",
+ "vertexAttribIPointer",
+ "vertexAttribDivisor",
+ "drawArraysInstanced",
+ "drawElementsInstanced",
+ "drawRangeElements",
+ "drawBuffers",
+ "clearBufferiv",
+ "clearBufferuiv",
+ "clearBufferfv",
+ "clearBufferfi",
+ "createQuery",
+ "deleteQuery",
+ "isQuery",
+ "beginQuery",
+ "endQuery",
+ "getQuery",
+ "getQueryParameter",
+ "createSampler",
+ "deleteSampler",
+ "isSampler",
+ "bindSampler",
+ "samplerParameteri",
+ "samplerParameterf",
+ "getSamplerParameter",
+ "fenceSync",
+ "isSync",
+ "deleteSync",
+ "clientWaitSync",
+ "waitSync",
+ "getSyncParameter",
+ "createTransformFeedback",
+ "deleteTransformFeedback",
+ "isTransformFeedback",
+ "bindTransformFeedback",
+ "beginTransformFeedback",
+ "endTransformFeedback",
+ "transformFeedbackVaryings",
+ "getTransformFeedbackVarying",
+ "pauseTransformFeedback",
+ "resumeTransformFeedback",
+ "bindBufferBase",
+ "bindBufferRange",
+ "getIndexedParameter",
+ "getUniformIndices",
+ "getActiveUniforms",
+ "getUniformBlockIndex",
+ "getActiveUniformBlockParameter",
+ "getActiveUniformBlockName",
+ "uniformBlockBinding",
+ "createVertexArray",
+ "deleteVertexArray",
+ "isVertexArray",
+ "bindVertexArray",
+];
+
+function assertFunction(v, f) {
+ try {
+ if (typeof v[f] != "function") {
+ return false;
+ } else {
+ return true;
+ }
+ } catch(e) {
+ return false;
+ }
+}
+
+function testAPIs(contextType) {
+ canvas = new OffscreenCanvas(10, 10);
+ gl = canvas.getContext(contextType);
+ var passed = true;
+ var methods;
+ if (contextType == 'webgl')
+ methods = webgl1Methods;
+ else
+ methods = webgl1Methods.concat(webgl2Methods);
+ for (var i=0; i<methods.length; i++) {
+ var r = assertFunction(gl, methods[i]);
+ passed = passed && r;
+ }
+
+ methods.push(...["makeXRCompatible"]);
+ var extended = false;
+ for (var i in gl) {
+ if (typeof gl[i] == "function" && methods.indexOf(i) == -1) {
+ if (!extended) {
+ extended = true;
+ }
+ }
+ }
+
+ if (!passed || extended)
+ return false;
+ return true;
+}
+
+var simpleTextureVertexShader = [
+ 'attribute vec4 vPosition;',
+ 'attribute vec2 texCoord0;',
+ 'varying vec2 texCoord;',
+ 'void main() {',
+ ' gl_Position = vPosition;',
+ ' texCoord = texCoord0;',
+ '}'].join('\n');
+
+var simpleTextureFragmentShader = [
+ 'precision mediump float;',
+ 'uniform sampler2D tex;',
+ 'varying vec2 texCoord;',
+ 'void main() {',
+ ' gl_FragData[0] = texture2D(tex, texCoord);',
+ '}'].join('\n');
+
+function getShader(gl, shaderStr, type)
+{
+ var shader = gl.createShader(type);
+ gl.shaderSource(shader, shaderStr);
+ gl.compileShader(shader);
+
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
+ return null;
+ return shader;
+}
+
+function setupProgram(gl, shaders, opt_attribs, opt_locations)
+{
+ var vertexShader = getShader(gl, simpleTextureVertexShader, gl.VERTEX_SHADER);
+ var fragmentShader = getShader(gl, simpleTextureFragmentShader, gl.FRAGMENT_SHADER);
+ var program = gl.createProgram();
+ gl.attachShader(program, vertexShader);
+ gl.attachShader(program, fragmentShader);
+
+ if (opt_attribs) {
+ for (var ii = 0; ii < opt_attribs.length; ++ii) {
+ gl.bindAttribLocation(
+ program,
+ opt_locations ? opt_locations[ii] : ii,
+ opt_attribs[ii]);
+ }
+ }
+ gl.linkProgram(program);
+
+ // Check the link status
+ var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
+ if (!linked) {
+ // something went wrong with the link
+ gl.deleteProgram(program);
+ return null;
+ }
+ gl.useProgram(program);
+ return program;
+}
+
+function setupSimpleTextureProgram(gl, opt_positionLocation, opt_texcoordLocation)
+{
+ opt_positionLocation = opt_positionLocation || 0;
+ opt_texcoordLocation = opt_texcoordLocation || 1;
+ return setupProgram(gl,
+ [simpleTextureVertexShader, simpleTextureFragmentShader],
+ ['vPosition', 'texCoord0'],
+ [opt_positionLocation, opt_texcoordLocation]);
+}
+
+function testLostContextWithoutRestore()
+{
+ // Functions with special return values.
+ if (!gl.isContextLost())
+ return false;
+
+ if (gl.getError() != gl.CONTEXT_LOST_WEBGL)
+ return false;
+ if (gl.getError() != gl.NO_ERROR)
+ return false;
+
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_UNSUPPORTED ||
+ gl.getAttribLocation(program, 'u_modelViewProjMatrix') != -1 ||
+ gl.getVertexAttribOffset(0, gl.VERTEX_ATTRIB_ARRAY_POINTER) != 0)
+ return false;
+
+ // Test the extension itself.
+ if (!compareGLError(gl.INVALID_OPERATION, "extension.loseContext()"))
+ return false;
+
+ imageData = new ImageData(1, 1);
+ float32array = new Float32Array(1);
+ int32array = new Int32Array(1);
+
+ // Functions returning void should return immediately.
+ // This is untestable, but we can at least be sure they cause no errors
+ // and the codepaths are exercised.
+ if (!compareGLError(gl.NO_ERROR, "gl.activeTexture(gl.TEXTURE0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.attachShader(program, shader)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, texture)") ||
+ !compareGLError(gl.NO_ERROR, "gl.blendColor(1.0, 1.0, 1.0, 1.0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.blendEquation(gl.FUNC_ADD)") ||
+ !compareGLError(gl.NO_ERROR, "gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD)") ||
+ !compareGLError(gl.NO_ERROR, "gl.blendFunc(gl.ONE, gl.ONE)") ||
+ !compareGLError(gl.NO_ERROR, "gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bufferData(gl.ARRAY_BUFFER, 0, gl.STATIC_DRAW)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bufferData(gl.ARRAY_BUFFER, arrayBufferView, gl.STATIC_DRAW)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bufferData(gl.ARRAY_BUFFER, arrayBuffer, gl.STATIC_DRAW)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bufferSubData(gl.ARRAY_BUFFRE, 0, arrayBufferView)") ||
+ !compareGLError(gl.NO_ERROR, "gl.bufferSubData(gl.ARRAY_BUFFRE, 0, arrayBuffer)") ||
+ !compareGLError(gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)") ||
+ !compareGLError(gl.NO_ERROR, "gl.clearColor(1, 1, 1, 1)") ||
+ !compareGLError(gl.NO_ERROR, "gl.clearDepth(1)") ||
+ !compareGLError(gl.NO_ERROR, "gl.clearStencil(0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.colorMask(1, 1, 1, 1)") ||
+ !compareGLError(gl.NO_ERROR, "gl.compileShader(shader)") ||
+ !compareGLError(gl.NO_ERROR, "gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.cullFace(gl.FRONT)") ||
+ !compareGLError(gl.NO_ERROR, "gl.deleteBuffer(buffer)") ||
+ !compareGLError(gl.NO_ERROR, "gl.deleteFramebuffer(framebuffer)") ||
+ !compareGLError(gl.NO_ERROR, "gl.deleteProgram(program)") ||
+ !compareGLError(gl.NO_ERROR, "gl.deleteRenderbuffer(renderbuffer)") ||
+ !compareGLError(gl.NO_ERROR, "gl.deleteShader(shader)") ||
+ !compareGLError(gl.NO_ERROR, "gl.deleteTexture(texture)") ||
+ !compareGLError(gl.NO_ERROR, "gl.depthFunc(gl.NEVER)") ||
+ !compareGLError(gl.NO_ERROR, "gl.depthMask(0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.depthRange(0, 1)") ||
+ !compareGLError(gl.NO_ERROR, "gl.detachShader(program, shader)") ||
+ !compareGLError(gl.NO_ERROR, "gl.disable(gl.BLEND)") ||
+ !compareGLError(gl.NO_ERROR, "gl.disableVertexAttribArray(0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.drawArrays(gl.POINTS, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.drawElements(gl.POINTS, 0, gl.UNSIGNED_SHORT, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.enable(gl.BLEND)") ||
+ !compareGLError(gl.NO_ERROR, "gl.enableVertexAttribArray(0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.finish()") ||
+ !compareGLError(gl.NO_ERROR, "gl.flush()") ||
+ !compareGLError(gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer)") ||
+ !compareGLError(gl.NO_ERROR, "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.frontFace(gl.CW)") ||
+ !compareGLError(gl.NO_ERROR, "gl.generateMipmap(gl.TEXTURE_2D)") ||
+ !compareGLError(gl.NO_ERROR, "gl.hint(gl.GENERATE_MIPMAP_HINT, gl.FASTEST)") ||
+ !compareGLError(gl.NO_ERROR, "gl.lineWidth(0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.linkProgram(program)") ||
+ !compareGLError(gl.NO_ERROR, "gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.polygonOffset(0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.readPixels(0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)") ||
+ !compareGLError(gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.sampleCoverage(0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.scissor(0, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.shaderSource(shader, '')") ||
+ !compareGLError(gl.NO_ERROR, "gl.stencilFunc(gl.NEVER, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.stencilFuncSeparate(gl.FRONT, gl.NEVER, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.stencilMask(0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.stencilMaskSeparate(gl.FRONT, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP)") ||
+ !compareGLError(gl.NO_ERROR, "gl.stencilOpSeparate(gl.FRONT, gl.KEEP, gl.KEEP, gl.KEEP)") ||
+ !compareGLError(gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)") ||
+ !compareGLError(gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imageData)") ||
+ !compareGLError(gl.NO_ERROR, "gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)") ||
+ !compareGLError(gl.NO_ERROR, "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)") ||
+ !compareGLError(gl.NO_ERROR, "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)") ||
+ !compareGLError(gl.NO_ERROR, "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, imageData)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform1f(uniformLocation, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform1fv(uniformLocation, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform1fv(uniformLocation, [0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform1i(uniformLocation, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform1iv(uniformLocation, int32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform1iv(uniformLocation, [0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform2f(uniformLocation, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform2fv(uniformLocation, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform2fv(uniformLocation, [0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform2i(uniformLocation, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform2iv(uniformLocation, int32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform2iv(uniformLocation, [0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform3f(uniformLocation, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform3fv(uniformLocation, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform3fv(uniformLocation, [0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform3i(uniformLocation, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform3iv(uniformLocation, int32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform3iv(uniformLocation, [0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform4f(uniformLocation, 0, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform4fv(uniformLocation, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform4fv(uniformLocation, [0, 0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform4i(uniformLocation, 0, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform4iv(uniformLocation, int32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniform4iv(uniformLocation, [0, 0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniformMatrix2fv(uniformLocation, false, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniformMatrix2fv(uniformLocation, false, [0, 0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniformMatrix3fv(uniformLocation, false, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniformMatrix3fv(uniformLocation, false, [0, 0, 0, 0, 0, 0, 0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniformMatrix4fv(uniformLocation, false, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.uniformMatrix4fv(uniformLocation, false, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.useProgram(program)") ||
+ !compareGLError(gl.NO_ERROR, "gl.validateProgram(program)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib1f(0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib1fv(0, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib1fv(0, [0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib2f(0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib2fv(0, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib2fv(0, [0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib3f(0, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib3fv(0, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib3fv(0, [0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib4f(0, 0, 0, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib4fv(0, float32array)") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttrib4fv(0, [0, 0, 0, 0])") ||
+ !compareGLError(gl.NO_ERROR, "gl.vertexAttribPointer(0, 0, gl.FLOAT, false, 0, 0)") ||
+ !compareGLError(gl.NO_ERROR, "gl.viewport(0, 0, 0, 0)"))
+ return false;
+
+ // Functions return nullable values should all return null.
+ if (gl.createBuffer() != null ||
+ gl.createFramebuffer() != null ||
+ gl.createProgram() != null ||
+ gl.createRenderbuffer() != null ||
+ gl.createShader(gl.GL_VERTEX_SHADER) != null ||
+ gl.createTexture() != null ||
+ gl.getActiveAttrib(program, 0) != null ||
+ gl.getActiveUniform(program, 0) != null ||
+ gl.getAttachedShaders(program) != null ||
+ gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE) != null ||
+ gl.getContextAttributes() != null ||
+ gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) != null ||
+ gl.getParameter(gl.CURRENT_PROGRAM) != null ||
+ gl.getProgramInfoLog(program) != null ||
+ gl.getProgramParameter(program, gl.LINK_STATUS) != null ||
+ gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH) != null ||
+ gl.getShaderInfoLog(shader) != null ||
+ gl.getShaderParameter(shader, gl.SHADER_TYPE) != null ||
+ gl.getShaderSource(shader) != null ||
+ gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S) != null ||
+ gl.getUniform(program, uniformLocation) != null ||
+ gl.getUniformLocation(program, 'vPosition') != null ||
+ gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) != null ||
+ gl.getSupportedExtensions() != null ||
+ gl.getExtension("WEBGL_lose_context") != null)
+ return false;
+
+ // "Is" queries should all return false.
+ if (gl.isBuffer(buffer) || gl.isEnabled(gl.BLEND) || gl.isFramebuffer(framebuffer) ||
+ gl.isProgram(program) || gl.isRenderbuffer(renderbuffer) || gl.isShader(shader) ||
+ gl.isTexture(texture))
+ return false;
+
+ if (gl.getError() != gl.NO_ERROR)
+ return false;
+
+ // test extensions
+ if (OES_vertex_array_object) {
+ if (!compareGLError(gl.NO_ERROR, "OES_vertex_array_object.bindVertexArrayOES(vertexArrayObject)") ||
+ !compareGLError(gl.NO_ERROR, "OES_vertex_array_object.isVertexArrayOES(vertexArrayObject)") ||
+ !compareGLError(gl.NO_ERROR, "OES_vertex_array_object.deleteVertexArrayOES(vertexArrayObject)"))
+ return false;
+ if (OES_vertex_array_object.createVertexArrayOES() != null)
+ return false;
+ }
+ return true;
+}
+function testValidContext()
+{
+ if (gl.isContextLost())
+ return false;
+
+ arrayBuffer = new ArrayBuffer(4);
+ arrayBufferView = new Int8Array(arrayBuffer);
+
+ // Generate resources for testing.
+ buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ framebuffer = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+ program = setupSimpleTextureProgram(gl);
+ renderbuffer = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+ shader = gl.createShader(gl.VERTEX_SHADER);
+ texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ if (gl.getError() != gl.NO_ERROR)
+ return false;
+
+ // Test is queries that will later be false
+ if (!compareGLError(gl.NO_ERROR, "gl.enable(gl.BLEND)"))
+ return false;
+ if (!gl.isBuffer(buffer) || !gl.isEnabled(gl.BLEND) || !gl.isFramebuffer(framebuffer) ||
+ !gl.isProgram(program) || !gl.isRenderbuffer(renderbuffer) || !gl.isShader(shader) ||
+ !gl.isTexture(texture))
+ return false;
+
+ if (OES_vertex_array_object) {
+ vertexArrayObject = OES_vertex_array_object.createVertexArrayOES();
+ if (gl.getError() != gl.NO_ERROR)
+ return false;
+ if (!OES_vertex_array_object.isVertexArrayOES(vertexArrayObject))
+ return false;
+ }
+ return true;
+}
+
+function setupTest()
+{
+ canvas = new OffscreenCanvas(10, 10);
+ gl = canvas.getContext('webgl');
+ WEBGL_lose_context = gl.getExtension("WEBGL_lose_context");
+ if (!WEBGL_lose_context)
+ return false;
+
+ // Try to get a few extensions
+ OES_vertex_array_object = gl.getExtension("OES_vertex_array_object");
+ OES_texture_float = gl.getExtension("OES_texture_float");
+
+ return true;
+}
+
+function testOriginalContext()
+{
+ if (gl.isContextLost())
+ return false;
+ if (gl.getError() != gl.NO_ERROR)
+ return false;
+ return true;
+}
+
+function testLostContext(e)
+{
+ if (contextLostEventFired)
+ return false;
+ contextLostEventFired = true;
+ if (!gl.isContextLost())
+ return false;
+ if (gl.getError() != gl.NO_ERROR)
+ return false;
+ if (allowRestore)
+ e.preventDefault();
+ return true;
+}
+
+function testLosingAndRestoringContext()
+{
+ return new Promise(function(resolve, reject) {
+ if (!setupTest())
+ reject("Test failed");
+
+ canvas.addEventListener("webglcontextlost", function(e) {
+ if (!testLostContext(e))
+ reject("Test failed");
+ // restore the context after this event has exited.
+ setTimeout(function() {
+ if (!compareGLError(gl.NO_ERROR, "WEBGL_lose_context.restoreContext()"))
+ reject("Test failed");
+ // The context should still be lost. It will not get restored until the
+ // webglrestorecontext event is fired.
+ if (!gl.isContextLost())
+ reject("Test failed");
+ if (gl.getError() != gl.NO_ERROR)
+ reject("Test failed");
+ // gl methods should still be no-ops
+ if (!compareGLError(gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)"))
+ reject("Test failed");
+ }, 0);
+ });
+ canvas.addEventListener("webglcontextrestored", function() {
+ if (!testRestoredContext())
+ reject("Test failed");
+ else
+ resolve("Test passed");
+ });
+ allowRestore = true;
+ contextLostEventFired = false;
+ contextRestoredEventFired = false;
+
+ if (!testOriginalContext())
+ reject("Test failed");
+ WEBGL_lose_context.loseContext();
+ // The context should be lost immediately.
+ if (!gl.isContextLost())
+ reject("Test failed");
+ if (gl.getError() != gl.CONTEXT_LOST_WEBGL)
+ reject("Test failed");
+ if (gl.getError() != gl.NO_ERROR)
+ reject("Test failed");
+ // gl methods should be no-ops
+ if (!compareGLError(gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)"))
+ reject("Test failed");
+ // but the event should not have been fired.
+ if (contextLostEventFired)
+ reject("Test failed");
+ });
+}
+
+function reGetExtensionAndTestForProperty(gl, name, expectProperty) {
+ var newExtension = gl.getExtension(name);
+ // NOTE: while getting a extension after context lost/restored is allowed to fail
+ // for the purpose the conformance tests it is not.
+ //
+ // Hypothetically the user can switch GPUs live. For example on Windows, install 2 GPUs,
+ // then in the control panen enable 1, disable the others and visa versa. Since the GPUs
+ // have different capabilities one or the other may not support a particlar extension.
+ //
+ // But, for the purpose of the conformance tests the context is expected to restore
+ // on the same GPU and therefore the extensions that succeeded previously should
+ // succeed on restore.
+ if (newExtension == null)
+ return false;
+ if (expectProperty) {
+ if (!(newExtension.webglTestProperty === true))
+ return false;
+ } else {
+ if (!(newExtension.webglTestProperty === undefined))
+ return false;
+ }
+ return newExtension;
+}
+
+
+function testOESTextureFloat() {
+ if (OES_texture_float) {
+ // Extension must still be lost.
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ if (!compareGLError(gl.INVALID_ENUM, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null)"))
+ return false;
+ // Try re-enabling extension
+ OES_texture_float = reGetExtensionAndTestForProperty(gl, "OES_texture_float", false);
+ if (!compareGLError(gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null)"))
+ return false;
+ return true;
+ }
+}
+
+function testOESVertexArrayObject() {
+ if (OES_vertex_array_object) {
+ // Extension must still be lost.
+ if (OES_vertex_array_object.createVertexArrayOES() != null)
+ return false;
+ // Try re-enabling extension
+
+ var old_OES_vertex_array_object = OES_vertex_array_object;
+ OES_vertex_array_object = reGetExtensionAndTestForProperty(gl, "OES_vertex_array_object", false);
+ if (OES_vertex_array_object.createVertexArrayOES() == null)
+ return false;
+ if (old_OES_vertex_array_object.createVertexArrayOES() != null)
+ return false;
+ return true;
+ }
+}
+
+function testExtensions() {
+ if (!testOESTextureFloat() || !testOESVertexArrayObject())
+ return false;
+ return true;
+}
+
+function testRestoredContext()
+{
+ if (contextRestoredEventFired)
+ return false;
+ contextRestoredEventFired = true;
+ if (gl.isContextLost())
+ return false;
+ if (gl.getError() != gl.NO_ERROR)
+ return false;
+
+ if (!testExtensions())
+ return false;
+ return true;
+}
+