Index: conformance/extensions/webgl-shared-resources.html |
=================================================================== |
--- conformance/extensions/webgl-shared-resources.html (revision 0) |
+++ conformance/extensions/webgl-shared-resources.html (working copy) |
@@ -0,0 +1,862 @@ |
+<!-- |
+ |
+/* |
+** Copyright (c) 2013 The Khronos Group Inc. |
+** |
+** Permission is hereby granted, free of charge, to any person obtaining a |
+** copy of this software and/or associated documentation files (the |
+** "Materials"), to deal in the Materials without restriction, including |
+** without limitation the rights to use, copy, modify, merge, publish, |
+** distribute, sublicense, and/or sell copies of the Materials, and to |
+** permit persons to whom the Materials are furnished to do so, subject to |
+** the following conditions: |
+** |
+** The above copyright notice and this permission notice shall be included |
+** in all copies or substantial portions of the Materials. |
+** |
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. |
+*/ |
+ |
+--> |
+ |
+<!DOCTYPE html> |
+<html> |
+<head> |
+<meta charset="utf-8"> |
+<title>WebGL WEBGL_Shared_Resources Conformance Test</title> |
+<link rel="stylesheet" href="../../resources/js-test-style.css"/> |
+<script src="../../resources/desktop-gl-constants.js" type="text/javascript"></script> |
+<script src="../../resources/js-test-pre.js"></script> |
+<script src="../resources/webgl-test.js"></script> |
+<script src="../resources/webgl-test-utils.js"></script> |
+</head> |
+<body> |
+<script id="vshader" type="x-shader/x-vertex"> |
+attribute vec4 a_position; |
+void main() { |
+ gl_Position = a_position; |
+} |
+</script> |
+<script id="fshader" type="x-shader/x-fragment"> |
+precision mediump float; |
+uniform vec4 u_color; |
+void main() { |
+ gl_FragColor = u_color; |
+} |
+</script> |
+<style> |
+canvas { |
+ border: 1px solid black; |
+} |
+</style> |
+<canvas id="canvas1" width="64" height="64"> </canvas> |
+<canvas id="canvas2" width="64" height="64"> </canvas> |
+<div id="description"></div> |
+<div id="console"></div> |
+<script> |
+"use strict"; |
+description(); |
+ |
+var wtu = WebGLTestUtils; |
+var canvas1 = document.getElementById("canvas1"); |
+var gl = wtu.create3DContext(canvas1); |
+var gl2; |
+var ext = null; |
+var ext2; |
+var ext3; |
+var buf; |
+var elementBuf; |
+var tex; |
+var tex3; |
+var rb; |
+var fb; |
+var id; |
+var resource; |
+var shader; |
+var program; |
+var uniformLocation; |
+var acquiredFlag; |
+var shaderProgram; // acquired progam (never released) used for shader testing |
+var programShader; // acquired shader (never released) used for program testing |
+ |
+if (!gl) { |
+ testFailed("context does not exist"); |
+} else { |
+ testPassed("context exists"); |
+ |
+ // Run tests with extension disabled |
+ runTestDisabled(); |
+ |
+ // Query the extension and store globally so shouldBe can access it |
+ ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_shared_resources"); |
+ if (!ext) { |
+ testPassed("No WEBGL_shared_resources support -- this is legal"); |
+ runSupportedTest(false); |
+ finishTest(); |
+ } else { |
+ testPassed("Successfully enabled WEBGL_shared_resources extension"); |
+ |
+ runSupportedTest(true); |
+ runTestExtension(); |
+ } |
+} |
+ |
+function runSupportedTest(extensionEnabled) { |
+ var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_shared_resources"); |
+ if (name !== undefined) { |
+ if (extensionEnabled) { |
+ testPassed("WEBGL_shared_resources listed as supported and getExtension succeeded"); |
+ } else { |
+ testFailed("WEBGL_shared_resources listed as supported but getExtension failed"); |
+ } |
+ } else { |
+ if (extensionEnabled) { |
+ testFailed("WEBGL_shared_resources not listed as supported but getExtension succeeded"); |
+ } else { |
+ testPassed("WEBGL_shared_resources not listed as supported and getExtension failed -- this is legal"); |
+ } |
+ } |
+} |
+ |
+function runTestDisabled() { |
+ // There is no functionality accessable with this extension disabled. |
+} |
+ |
+function makeFailCallback(msg) { |
+ return function() { |
+ testFailed(msg); |
+ } |
+}; |
+ |
+ |
+function runTestExtension() { |
+ var canvas2 = document.getElementById("canvas2"); |
+ gl2 = wtu.create3DContext(canvas2, { group: ext.group }); |
+ ext2 = wtu.getExtensionWithKnownPrefixes(gl2, "WEBGL_shared_resources"); |
+ |
+ // Runs an array of functions. Expects each function takes a callback |
+ // it will call when finished. |
+ var runSequence = function(steps) { |
+ var stepNdx = 0; |
+ var runNextStep = function() { |
+ if (stepNdx < steps.length) { |
+ steps[stepNdx++](runNextStep); |
+ } |
+ }; |
+ runNextStep(); |
+ }; |
+ |
+ var bufferTests = { |
+ resourceType: "buffer", |
+ |
+ setupFunction: function() { |
+ buf = gl.createBuffer(); |
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf); |
+ gl.bufferData(gl.ARRAY_BUFFER, 16, gl.STATIC_DRAW); |
+ return buf; |
+ }, |
+ |
+ bindFunction: function(buf) { |
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf); |
+ }, |
+ |
+ implicitBindFunctions: function(expectedError) { |
+ shouldGenerateGLError(gl, expectedError, "gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0)"); |
+ }, |
+ |
+ modificationFunctions: function(expectedError) { |
+ shouldGenerateGLError(gl, expectedError, "gl.bufferData(gl.ARRAY_BUFFER, 16, gl.STATIC_DRAW)"); |
+ shouldGenerateGLError(gl, expectedError, "gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Uint8Array(4))"); |
+ }, |
+ |
+ queryFunctions: function(expectedError) { |
+ shouldGenerateGLError(gl, expectedError, "gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE)"); |
+ }, |
+ }; |
+ |
+ var programTests = { |
+ resourceType: "program", |
+ |
+ setupFunction: function() { |
+ // We need a valid a program with valid shaders to share because the only way to 'bind' |
+ // a program is to call gl.useProgram and you can't call gl.useProgram on an invalid program. |
+ program = wtu.setupProgram(gl, ["vshader", "fshader"]); |
+ programShader = gl.getAttachedShaders(program)[0]; |
+ uniformLocation = gl.getUniformLocation(program, "u_color"); |
+ return program; |
+ }, |
+ |
+ bindFunction: function(program) { |
+ gl.useProgram(program); |
+ }, |
+ |
+ implicitBindFunctions: function(expectedError) { |
+ }, |
+ |
+ modificationFunctions: function(expectedError) { |
+ if (expectedError == gl.NO_ERROR) { |
+ // Need to get a new location because we may have re-linked. |
+ uniformLocation = gl.getUniformLocation(program, 'u_color'); |
+ } |
+ shouldGenerateGLError(gl, expectedError, "gl.uniform4f(uniformLocation, 0, 1, 2, 3)"); |
+ shouldGenerateGLError(gl, expectedError, "gl.detachShader(program, programShader)"); |
+ shouldGenerateGLError(gl, expectedError, "gl.attachShader(program, programShader)"); |
+ shouldGenerateGLError(gl, expectedError, "gl.bindAttribLocation(program, 0, 'foo')"); |
+ shouldGenerateGLError(gl, expectedError, "gl.linkProgram(program)"); |
+ }, |
+ |
+ queryFunctions: function(expectedError) { |
+ shouldGenerateGLError(gl, expectedError, "gl.getProgramParameter(program, gl.LINK_STATUS)"); |
+ shouldGenerateGLError(gl, expectedError, "gl.getProgramInfoLog(program)"); |
+ shouldGenerateGLError(gl, expectedError, "gl.getAttachedShaders(program)"); |
+ shouldGenerateGLError(gl, expectedError, "gl.getAttribLocation(program, 'foo')"); |
+ shouldGenerateGLError(gl, expectedError, "gl.getUniformLocation(program, 'foo')"); |
+ shouldGenerateGLError(gl, expectedError, "gl.getActiveAttrib(program, 0)"); |
+ shouldGenerateGLError(gl, expectedError, "gl.getActiveUniform(program, 0)"); |
+ shouldGenerateGLError(gl, expectedError, "gl.getUniform(program, uniformLocation)"); |
+ }, |
+ }; |
+ |
+ var renderbufferTests = { |
+ resourceType: "renderbuffer", |
+ |
+ setupFunction: function() { |
+ rb = gl.createRenderbuffer(); |
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb); |
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16); |
+ fb = gl.createFramebuffer(); |
+ return rb; |
+ }, |
+ |
+ bindFunction: function(rb) { |
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb); |
+ }, |
+ |
+ implicitBindFunctions: function(expectedError) { |
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
+ shouldGenerateGLError(gl, expectedError, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb)"); |
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null); |
+ }, |
+ |
+ modificationFunctions: function(expectedError) { |
+ shouldGenerateGLError(gl, expectedError, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)"); |
+ }, |
+ |
+ queryFunctions: function(expectedError) { |
+ shouldGenerateGLError(gl, expectedError, "gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)"); |
+ }, |
+ }; |
+ |
+ |
+ var shaderTests = { |
+ resourceType: "shader", |
+ |
+ setupFunction: function() { |
+ var shaderSource = "Hello World"; |
+ shader = gl.createShader(gl.VERTEX_SHADER); |
+ gl.shaderSource(shader, shaderSource); |
+ shaderProgram = gl.createProgram(); |
+ gl.attachShader(shaderProgram, shader); |
+ return shader; |
+ }, |
+ |
+ bindFunction: function(shader) { |
+ gl.detachShader(shaderProgram, shader); // you can't attach if a shader is already attached. |
+ gl.attachShader(shaderProgram, shader); |
+ }, |
+ |
+ implicitBindFunctions: function(expectedError) { |
+ }, |
+ |
+ modificationFunctions: function(expectedError) { |
+ shouldGenerateGLError(gl, expectedError, "gl.shaderSource(shader, 'foo')"); |
+ shouldGenerateGLError(gl, expectedError, "gl.compileShader(shader)"); |
+ }, |
+ |
+ queryFunctions: function(expectedError) { |
+ shouldGenerateGLError(gl, expectedError, "gl.getShaderParameter(shader, gl.COMPILE_STATUS)"); |
+ shouldGenerateGLError(gl, expectedError, "gl.getShaderInfoLog(shader)"); |
+ }, |
+ }; |
+ |
+ var textureTests = { |
+ resourceType: "texture", |
+ |
+ setupFunction: function() { |
+ tex = gl.createTexture(); |
+ gl.bindTexture(gl.TEXTURE_2D, tex); |
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); |
+ return tex; |
+ }, |
+ |
+ bindFunction: function(tex) { |
+ gl.bindTexture(gl.TEXTURE_2D, tex); |
+ }, |
+ |
+ implicitBindFunctions: function(expectedError) { |
+ }, |
+ |
+ modificationFunctions: function(expectedError) { |
+ shouldGenerateGLError(gl, expectedError, "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT)"); |
+ shouldGenerateGLError(gl, expectedError, "gl.generateMipmap(gl.TEXTURE_2D)"); |
+ shouldGenerateGLError(gl, expectedError, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null)"); |
+ shouldGenerateGLError(gl, expectedError, "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))"); |
+ shouldGenerateGLError(gl, expectedError, "gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 16, 16, 0)"); |
+ shouldGenerateGLError(gl, expectedError, "gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 16, 16)"); |
+ // TODO: Add compressed texture test if extension exists? |
+ }, |
+ |
+ queryFunctions: function(expectedError) { |
+ shouldGenerateGLError(gl, expectedError, "gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S)"); |
+ }, |
+ }; |
+ |
+ var testResourceWithSingleContext = function(info, callback) { |
+ var resourceType = info.resourceType; |
+ |
+ debug("") |
+ debug("test " + resourceType); |
+ var resource = info.setupFunction(); |
+ ext.releaseSharedResource(resource); |
+ |
+ debug(""); |
+ debug("test " + resourceType + " functions can not be called on released " + resourceType); |
+ info.modificationFunctions(gl.INVALID_OPERATION); |
+ info.implicitBindFunctions(gl.INVALID_OPERATION); |
+ info.queryFunctions(gl.INVALID_OPERATION); |
+ |
+ debug(""); |
+ debug("test acquring " + resourceType); |
+ ext.acquireSharedResource(resource, ext.READ_ONLY, function() { |
+ debug(""); |
+ debug("test " + resourceType + " functions can not be called on READ_ONLY acquired " + resourceType + " that has not been bound"); |
+ info.queryFunctions(gl.INVALID_OPERATION); |
+ info.modificationFunctions(gl.INVALID_OPERATION); |
+ |
+ debug(""); |
+ debug("test query " + resourceType + " functions can be called on READ_ONLY acquired " + resourceType + " that has been bound but not " + resourceType + " modification functions"); |
+ info.bindFunction(resource); |
+ info.queryFunctions(gl.NO_ERROR); |
+ info.modificationFunctions(gl.INVALID_OPERATION); |
+ |
+ ext.releaseSharedResource(resource); |
+ ext.acquireSharedResource(resource, ext.EXCLUSIVE, function() { |
+ debug(""); |
+ debug("test " + resourceType + " functions can not be called on EXCLUSIVE acquired " + resourceType + " that has not been bound"); |
+ info.queryFunctions(gl.INVALID_OPERATION); |
+ info.modificationFunctions(gl.INVALID_OPERATION); |
+ |
+ debug(""); |
+ debug("test all " + resourceType + " functions can be called on EXCLUSIVE acquired " + resourceType + " that has been bound."); |
+ info.bindFunction(resource) |
+ info.queryFunctions(gl.NO_ERROR); |
+ info.modificationFunctions(gl.NO_ERROR); |
+ callback(); |
+ }); |
+ }); |
+ }; |
+ |
+ var makeSingleContextResourceTest = function(info) { |
+ return function(callback) { |
+ testResourceWithSingleContext(info, callback); |
+ }; |
+ }; |
+ |
+ var testCommonResourceFeatures = function(info, callback) { |
+ var type = info.resourceType.charAt(0).toUpperCase() + info.resourceType.slice(1); |
+ acquiredFlag = false; |
+ debug(""); |
+ debug("test common features of " + type); |
+ |
+ resource = info.setupFunction(); |
+ info.bindFunction(resource); |
+ |
+ debug("Test a deleted resource can still be acquired."); |
+ var checkAcquireAfterDelete = function() { |
+ debug("check Acquire After Delete"); |
+ shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.delete" + type + "(resource)"); |
+// TODO: fix spec then comment this in shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bind" + type + "(gl." + target + ", resource)"); // You can't bind a deleted resource |
+ shouldGenerateGLError(gl, gl.NO_ERROR, "ext.releaseSharedResource(resource)"); |
+ callback(); |
+ }; |
+ |
+ var checkDeleteExclusive = function() { |
+ debug("check delete EXLUSIVE"); |
+ shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.delete" + type + "(resource)"); |
+ info.bindFunction(resource); |
+ glErrorShouldBe(gl, gl.NO_ERROR, "no error deleting exclusively acquired resource"); |
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.delete" + type + "(resource)"); |
+ ext.releaseSharedResource(resource); |
+ ext.acquireSharedResource(resource, ext.EXCLUSIVE, checkAcquireAfterDelete); |
+ }; |
+ |
+ var checkDeleteReadOnly = function() { |
+ acquiredFlag = true; |
+ debug("check delete READ_ONLY"); |
+ shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.delete" + type + "(resource)"); |
+ info.bindFunction(resource); |
+ glErrorShouldBe(gl, gl.NO_ERROR, "no error bind read only acquired resource"); |
+ shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.delete" + type + "(resource)"); // We're READ_ONLY so this should fail |
+ ext.releaseSharedResource(resource); |
+ ext.acquireSharedResource(resource, ext.EXCLUSIVE, checkDeleteExclusive); |
+ }; |
+ |
+ debug("Test you can't have 2 outstanding requests for the same resource."); |
+ ext.releaseSharedResource(resource); |
+ ext.acquireSharedResource(resource, ext.READ_ONLY, checkDeleteReadOnly); |
+ glErrorShouldBe(gl, gl.NO_ERROR, "should be no error from 1st acquire request"); |
+ ext.acquireSharedResource(resource, ext.READ_ONLY, checkDeleteReadOnly); |
+ glErrorShouldBe(gl, gl.INVALID_OPERATION, "should be INVALID_OPERATION from 2nd acquire request"); |
+ |
+ debug("Test acquire does not happen immediately on release (must exit current event)"); |
+ shouldBeTrue("acquiredFlag === false"); |
+ }; |
+ |
+ var makeCommonResourceFeatureTest = function(info) { |
+ return function(callback) { |
+ testCommonResourceFeatures(info, callback); |
+ }; |
+ }; |
+ |
+ // acquire multiple resources in multiple contexts. |
+ var acquireMultipleResources = function(extensions, resources, mode, callback) { |
+ var numNeeded = resources.length * extensions.length; |
+ |
+ var checkAcquire = function() { |
+ --numNeeded; |
+ if (numNeeded == 0) { |
+ callback(); |
+ } |
+ }; |
+ |
+ resources.forEach(function(resource) { |
+ extensions.forEach(function(ext) { |
+ ext.acquireSharedResource(resource, mode, checkAcquire); |
+ }); |
+ }); |
+ }; |
+ |
+ // release multiple resources in multiple contexts. |
+ var releaseMultipleResources = function(extensions, resources) { |
+ resources.forEach(function(resource) { |
+ extensions.forEach(function(ext) { |
+ ext.releaseSharedResource(resource); |
+ }); |
+ }); |
+ }; |
+ |
+ var testRendering = function(callback) { |
+ debug(""); |
+ debug("test rendering"); |
+ var positionLocation = 0; |
+ var texcoordLocation = 1; |
+ var program = wtu.setupSimpleTextureProgram(gl, positionLocation, texcoordLocation); |
+ var buffers = wtu.setupUnitQuad(gl, positionLocation, texcoordLocation); |
+ var rb = gl.createRenderbuffer(); |
+ var fb = gl.createFramebuffer(); |
+ |
+ var elementBuf = gl.createBuffer(); |
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuf); |
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 3, 4, 5]), gl.STATIC_DRAW); |
+ |
+ var width = 16; |
+ var height = 16; |
+ |
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb); |
+ gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, width, height); |
+ |
+ var destTex = gl.createTexture(); |
+ gl.bindTexture(gl.TEXTURE_2D, destTex); |
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); |
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); |
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); |
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); |
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); |
+ |
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb); |
+ // It's not clear if gl.RGBA4 must be framebuffer complete. |
+ var canCheckRenderbuffer = (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE); |
+ |
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, destTex, 0); |
+ glErrorShouldBe(gl, gl.NO_ERROR, "setup"); |
+ shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE"); |
+ |
+ var tex = gl.createTexture(); |
+ wtu.fillTexture(gl, tex, 1, 1, [0, 255, 0, 255]); |
+ |
+ if (!program) { |
+ testFailed("could not link program"); |
+ callback(); |
+ return; |
+ } |
+ |
+ var releaseAndAcquireResources = function(callback) { |
+ var resources = [buffers[0], buffers[1], tex, program, elementBuf]; |
+ releaseMultipleResources([ext], resources); |
+ acquireMultipleResources([ext, ext2], resources, ext.READ_ONLY, callback); |
+ }; |
+ |
+ var doRenderTest = function(callback) { |
+ debug("Test 2 contexts can render with read only resources."); |
+ |
+ shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)"); |
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffers[0]); |
+ shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)"); |
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffers[1]); |
+ shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)"); |
+ gl.bindTexture(gl.TEXTURE_2D, tex); |
+ shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)"); |
+ gl.useProgram(program); |
+ |
+ // Render to canvas1; |
+ debug("render with context 1"); |
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 0, 0, 0]); |
+ wtu.drawUnitQuad(gl); |
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 0, 255]); |
+ |
+ shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0)"); |
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuf); |
+ gl.clear(gl.COLOR_BUFFER_BIT); |
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0)"); |
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 0, 255]); |
+ |
+ // Render to canvas2; |
+ debug("render with context 2"); |
+ gl2.useProgram(program); |
+ |
+ gl2.bindBuffer(gl.ARRAY_BUFFER, buffers[0]); |
+ gl2.enableVertexAttribArray(positionLocation); |
+ gl2.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); |
+ gl2.bindBuffer(gl.ARRAY_BUFFER, buffers[1]); |
+ gl2.enableVertexAttribArray(texcoordLocation); |
+ gl2.vertexAttribPointer(texcoordLocation, 2, gl.FLOAT, false, 0, 0); |
+ |
+ gl2.bindTexture(gl.TEXTURE_2D, tex); |
+ |
+ wtu.checkCanvas(gl2, [0, 0, 0, 0]); |
+ wtu.drawUnitQuad(gl2); |
+ wtu.checkCanvas(gl2, [0, 255, 0, 255]); |
+ |
+ shouldGenerateGLError(gl2, gl2.INVALID_OPERATION, "gl2.drawElements(gl2.TRIANGLES, 6, gl2.UNSIGNED_SHORT, 0)"); |
+ gl2.bindBuffer(gl2.ELEMENT_ARRAY_BUFFER, elementBuf); |
+ gl2.clear(gl2.COLOR_BUFFER_BIT); |
+ shouldGenerateGLError(gl2, gl2.NO_ERROR, "gl2.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0)"); |
+ wtu.checkCanvas(gl2, [0, 255, 0, 255]); |
+ |
+ debug("Test you can't render to a framebuffer with a released texture"); |
+ ext.releaseSharedResource(destTex); |
+ shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)"); |
+ shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.clear(gl.COLOR_BUFFER_BIT)"); |
+ |
+ debug("Test you can't read from a framebuffer with a released texture"); |
+ shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))"); |
+ |
+ ext.acquireSharedResource(destTex, ext.READ_ONLY, callback); |
+ }; |
+ |
+ var checkReadOnlyTextureOnFramebuffer = function(callback) { |
+ debug(""); |
+ debug("test READ_ONLY texture attachment"); |
+ debug("Test we fail of we haven't bound again"); |
+ shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))"); |
+ shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE"); |
+ shouldBeTrue("gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE"); |
+ shouldBeTrue("gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE"); |
+ |
+ gl.activeTexture(gl.TEXTURE1); |
+ gl.bindTexture(gl.TEXTURE_2D, destTex); |
+ gl.activeTexture(gl.TEXTURE0); |
+ debug("Test we fail to draw because we're read only."); |
+ shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE"); |
+ shouldBeTrue("gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE"); |
+ shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)"); |
+ shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.clear(gl.COLOR_BUFFER_BIT)"); |
+ |
+ debug("Test we can read a READ_ONLY texture."); |
+ shouldBeTrue("gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE"); |
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))"); |
+ |
+ checkRenderbuffer(callback); |
+ }; |
+ |
+ var checkRenderbuffer = function(callback) { |
+ if (canCheckRenderbuffer) { |
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb); |
+ wtu.drawUnitQuad(gl); |
+ wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 0, 255]); |
+ |
+ debug("Test you can't render to a framebuffer with a released renderbuffer"); |
+ ext.releaseSharedResource(rb); |
+ shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)"); |
+ shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.clear(gl.COLOR_BUFFER_BIT)"); |
+ |
+ debug("Test you can't read from a framebuffer with a released renderbuffer"); |
+ shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))"); |
+ } |
+ |
+ ext.acquireSharedResource(rb, ext.READ_ONLY, callback); |
+ }; |
+ |
+ var checkReadOnlyRenderbufferOnFramebuffer = function(callback) { |
+ if (canCheckRenderbuffer) { |
+ debug(""); |
+ debug("test READ_ONLY renderbuffer attachment"); |
+ debug("Test we fail of we haven't bound again"); |
+ shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))"); |
+ shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE"); |
+ shouldBeTrue("gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE"); |
+ shouldBeTrue("gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE"); |
+ |
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb); |
+ debug("Test we fail to draw because we're read only."); |
+ shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)"); |
+ shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.clear(gl.COLOR_BUFFER_BIT)"); |
+ shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE"); |
+ shouldBeTrue("gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE"); |
+ |
+ debug("Test we can read a READ_ONLY renderbuffer."); |
+ shouldBeTrue("gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE"); |
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))"); |
+ } |
+ |
+ ext.releaseSharedResource(rb); |
+ ext.acquireSharedResource(rb, ext.READ_ONLY, callback); |
+ }; |
+ |
+ var checkRenderbufferBindsOnAttach = function(callback) { |
+ if (canCheckRenderbuffer) { |
+ debug(""); |
+ debug("Test we fail of we haven't bound again"); |
+ shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))"); |
+ |
+ debug("Test attaching a renderbuffer marks it as bound"); |
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb); |
+ |
+ debug("Test we can read a READ_ONLY renderbuffer."); |
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))"); |
+ } |
+ |
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, destTex, 0); |
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))"); |
+ ext.releaseSharedResource(destTex); |
+ ext.acquireSharedResource(destTex, ext.READ_ONLY, callback); |
+ }; |
+ |
+ var checkTextureBindsOnAttach = function(callback) { |
+ debug(""); |
+ debug("Test we fail of we haven't bound again"); |
+ shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))"); |
+ |
+ debug("Test attaching a texture marks it as bound"); |
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, destTex, 0); |
+ |
+ debug("Test we can read a READ_ONLY texture."); |
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4))"); |
+ |
+ callback(); |
+ }; |
+ |
+ var checkCanNotRenderWithReleasedProgram = function(callback) { |
+ debug(""); |
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null); |
+ |
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawArrays(gl.TRIANGLES, 0, 6)"); |
+ |
+ ext.releaseSharedResource(program); |
+ |
+ debug("Test we can't draw with a released program."); |
+ shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)"); |
+ |
+ ext.acquireSharedResource(program, ext.EXCLUSIVE, callback); |
+ ext2.releaseSharedResource(program); |
+ }; |
+ |
+ var checkCanNotRenderWithReleasedBuffer = function(callback) { |
+ debug(""); |
+ gl.useProgram(program); |
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawArrays(gl.TRIANGLES, 0, 6)"); |
+ |
+ ext.releaseSharedResource(buffers[0]); |
+ |
+ debug("Test we can't draw with a released buffer."); |
+ shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)"); |
+ |
+ ext.acquireSharedResource(buffers[0], ext.READ_ONLY, callback); |
+ }; |
+ |
+ var checkCanNotRenderWithReleasedTexture = function(callback) { |
+ debug(""); |
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffers[0]); |
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawArrays(gl.TRIANGLES, 0, 6)"); |
+ |
+ ext.releaseSharedResource(tex); |
+ |
+ debug("Test we can't draw with a released texture."); |
+ shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.drawArrays(gl.TRIANGLES, 0, 6)"); |
+ |
+ ext.acquireSharedResource(tex, ext.READ_ONLY, callback); |
+ }; |
+ |
+ var checkCanRenderWithReleasedShader = function(callback) { |
+ gl.bindTexture(gl.TEXTURE_2D, tex); |
+ var shaders = gl.getAttachedShaders(program); |
+ ext.releaseSharedResource(shaders[0]); |
+ |
+ debug(""); |
+ debug("Test we can draw with a released shader."); |
+ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawArrays(gl.TRIANGLES, 0, 6)"); |
+ callback(); |
+ }; |
+ |
+ runSequence( |
+ [ |
+ releaseAndAcquireResources, |
+ doRenderTest, |
+ checkReadOnlyTextureOnFramebuffer, |
+ checkReadOnlyRenderbufferOnFramebuffer, |
+ checkRenderbufferBindsOnAttach, |
+ checkTextureBindsOnAttach, |
+ checkCanNotRenderWithReleasedProgram, |
+ checkCanNotRenderWithReleasedBuffer, |
+ checkCanNotRenderWithReleasedTexture, |
+ checkCanRenderWithReleasedShader, |
+ callback, |
+ ]); |
+ }; |
+ |
+ var testMisc = function(callback) { |
+ debug(""); |
+ debug("Test you can't release a framebuffer"); |
+ // TODO: It's not clear what should happen here to me. |
+ //shouldThrow("ext.releaseSharedResource(fb)", "TypeError"); |
+ |
+ debug("") |
+ debug("Test you can compare sharegroups"); |
+ var gl3 = wtu.create3DContext(); |
+ ext3 = wtu.getExtensionWithKnownPrefixes(gl3, "WEBGL_shared_resources"); |
+ // TODO: comment in once this comparison works. |
+ //shouldBeTrue("ext.group == ext2.group"); |
+ shouldBeTrue("ext.group != ext3.group"); |
+ |
+ debug("Test you can't use resources from another different group."); |
+ tex3 = gl3.createTexture(); |
+ shouldGenerateGLError(gl, gl.INVALID_OPERATION, "ext.releaseSharedResource(tex3)"); |
+ shouldGenerateGLError(gl, gl.INVALID_OPERATION, "ext.acquireSharedResource(tex3, ext.READ_ONLY, makeFailCallback('should not be able to acquire resource from other context'))"); |
+ |
+ var failTest = function() { |
+ testFailed("cancelled callback was called"); |
+ }; |
+ |
+ var tex = gl.createTexture(); |
+ debug("test releasing from the wrong context. Should be a no-op"); |
+ shouldGenerateGLError(gl, gl.NO_ERROR, "ext2.releaseSharedResource(tex)"); |
+ |
+ id = ext2.acquireSharedResource(tex, ext.READ_ONLY, failTest); |
+ debug("test cancelling a request for which an event has not been posted"); |
+ ext2.cancelAcquireSharedResource(id); |
+ |
+ debug("test cancelling a request for which an event has already been posted"); |
+ ext.releaseSharedResource(tex); |
+ id = ext.acquireSharedResource(tex, ext.READ_ONLY, failTest); |
+ ext.cancelAcquireSharedResource(id); |
+ |
+ debug("test cancelling on the wrong context's extension is ignored"); |
+ id = ext2.acquireSharedResource(tex, ext.READ_ONLY, callback); |
+ shouldGenerateGLError(gl, gl.NO_ERROR, 'ext.cancelAcquireSharedResource(id)'); |
+ }; |
+ |
+ var testLostContext = function(callback) { |
+ var WEBGL_lose_context = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_lose_context"); |
+ if (!WEBGL_lose_context) { |
+ callback(); |
+ return; |
+ } |
+ |
+ var tex = gl.createTexture(); |
+ var tex2 = gl.createTexture(); |
+ |
+ var setupAcquire = function(callback) { |
+ var callbacksNeeded = 3; |
+ var waitForContextLostAndAcquire = function(e) { |
+ if (e && e.preventDefault) { |
+ e.preventDefault(); // allow context restore. |
+ } |
+ --callbacksNeeded; |
+ if (callbacksNeeded == 0) { |
+ callback(); |
+ } |
+ return false; |
+ }; |
+ |
+ debug(""); |
+ debug("Test extension still functions during context lost."); |
+ acquireMultipleResources([ext2], [tex, tex2], ext2.READ_ONLY, waitForContextLostAndAcquire); |
+ canvas1.addEventListener("webglcontextlost", waitForContextLostAndAcquire, false); |
+ canvas2.addEventListener("webglcontextlost", waitForContextLostAndAcquire, false); |
+ // Release one before context lost |
+ ext.releaseSharedResource(tex); |
+ WEBGL_lose_context.loseContext(); |
+ // Release one after context lost |
+ ext.releaseSharedResource(tex2); |
+ |
+ shouldBeTrue('gl.isContextLost()'); |
+ shouldBeTrue('gl2.isContextLost()'); |
+ }; |
+ |
+ var checkAcquireExt2 = function(callback) { |
+ testPassed("was able to acquire resources during context lost"); |
+ acquireMultipleResources([ext], [tex, tex2], ext.READ_ONLY, callback); |
+ }; |
+ |
+ var checkAcquireExt = function(callback) { |
+ testPassed("was able to request acquire resources during context lost"); |
+ canvas1.addEventListener("webglcontextrestored", callback, false); |
+ WEBGL_lose_context.restoreContext(); |
+ }; |
+ |
+ var passTest = function(callback) { |
+ testPassed("extension works during lost context"); |
+ callback(); |
+ }; |
+ |
+ runSequence( |
+ [ |
+ setupAcquire, |
+ checkAcquireExt2, |
+ checkAcquireExt, |
+ passTest, |
+ callback, |
+ ]); |
+ }; |
+ |
+ runSequence( |
+ [ |
+ makeCommonResourceFeatureTest(bufferTests), |
+ makeCommonResourceFeatureTest(programTests), |
+ makeCommonResourceFeatureTest(shaderTests), |
+ makeCommonResourceFeatureTest(renderbufferTests), |
+ makeCommonResourceFeatureTest(textureTests), |
+ makeSingleContextResourceTest(bufferTests), |
+ makeSingleContextResourceTest(programTests), |
+ makeSingleContextResourceTest(renderbufferTests), |
+ makeSingleContextResourceTest(shaderTests), |
+ makeSingleContextResourceTest(textureTests), |
+ testRendering, |
+ testMisc, |
+ testLostContext, |
+ finishTest, |
+ ]); |
+ |
+} |
+var successfullyParsed = true; |
+</script> |
+</body> |
+</html> |
+ |
Property changes on: conformance/extensions/webgl-shared-resources.html |
___________________________________________________________________ |
Added: svn:eol-style |
## -0,0 +1 ## |
+LF |
\ No newline at end of property |