|
1 <!DOCTYPE html> |
|
2 <html> |
|
3 <head> |
|
4 <link rel="stylesheet" href="../../resources/js-test-style.css"/> |
|
5 <script src="../../resources/js-test-pre.js"></script> |
|
6 <script src="../resources/webgl-test.js"></script> |
|
7 <script src="../resources/webgl-test-utils.js"></script> |
|
8 <script> |
|
9 var wtu; |
|
10 var canvas; |
|
11 var gl; |
|
12 var shouldGenerateGLError; |
|
13 var extensionNames = [ |
|
14 "WEBKIT_WEBGL_lose_context", |
|
15 "MOZ_WEBGL_lose_context", |
|
16 ]; |
|
17 var extensionName; |
|
18 var extension; |
|
19 |
|
20 var buffer; |
|
21 var framebuffer; |
|
22 var program; |
|
23 var renderbuffer; |
|
24 var shader; |
|
25 var texture; |
|
26 var uniformLocation; |
|
27 var arrayBuffer; |
|
28 var arrayBufferView |
|
29 var image; |
|
30 var video; |
|
31 var canvas2d; |
|
32 var ctx2d; |
|
33 var imageData; |
|
34 var float32array; |
|
35 var int32array; |
|
36 |
|
37 function init() |
|
38 { |
|
39 wtu = WebGLTestUtils; |
|
40 canvas = document.getElementById("canvas"); |
|
41 gl = wtu.create3DContext(canvas); |
|
42 shouldGenerateGLError = wtu.shouldGenerateGLError; |
|
43 |
|
44 description("Tests behavior under a lost context"); |
|
45 |
|
46 if (window.initNonKhronosFramework) { |
|
47 window.initNonKhronosFramework(true); |
|
48 } |
|
49 |
|
50 // call testValidContext() before checking for the extension, because this is where we check |
|
51 // for the isContextLost() method, which we want to do regardless of the extension's presence. |
|
52 testValidContext(); |
|
53 |
|
54 for (var ii = 0; ii < extensionNames.length; ++ii) { |
|
55 extension = gl.getExtension(extensionNames[ii]); |
|
56 if (extension) { |
|
57 extensionName = extensionNames[ii]; |
|
58 break; |
|
59 } |
|
60 } |
|
61 if (!extension) { |
|
62 debug("Could not find lose_context extension under the following names: " + extensionNames.join(" ")); |
|
63 finishTest(); |
|
64 return false; |
|
65 } |
|
66 |
|
67 canvas.addEventListener("webglcontextlost", testLostContext, false); |
|
68 |
|
69 loseContext(); |
|
70 } |
|
71 |
|
72 function loseContext() |
|
73 { |
|
74 debug(""); |
|
75 debug("Lose context"); |
|
76 |
|
77 // Note: this will cause the context to be lost, but the |
|
78 // webglcontextlost event listener to be queued. |
|
79 extension.loseContext(); |
|
80 debug(""); |
|
81 } |
|
82 |
|
83 function testValidContext() |
|
84 { |
|
85 debug("Test valid context"); |
|
86 |
|
87 shouldBeFalse("gl.isContextLost()"); |
|
88 |
|
89 arrayBuffer = new ArrayBuffer(4); |
|
90 arrayBufferView = new Int8Array(arrayBuffer); |
|
91 |
|
92 // Generate resources for testing. |
|
93 buffer = gl.createBuffer(); |
|
94 gl.bindBuffer(gl.ARRAY_BUFFER, buffer); |
|
95 framebuffer = gl.createFramebuffer(); |
|
96 gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); |
|
97 program = wtu.setupSimpleTextureProgram(gl); |
|
98 renderbuffer = gl.createRenderbuffer(); |
|
99 gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer); |
|
100 shader = gl.createShader(gl.VERTEX_SHADER); |
|
101 texture = gl.createTexture(); |
|
102 gl.bindTexture(gl.TEXTURE_2D, texture); |
|
103 shouldBe("gl.getError()", "gl.NO_ERROR"); |
|
104 |
|
105 // Test is queries that will later be false |
|
106 shouldGenerateGLError(gl, gl.NO_ERROR, "gl.enable(gl.BLEND)"); |
|
107 shouldBeTrue("gl.isBuffer(buffer)"); |
|
108 shouldBeTrue("gl.isEnabled(gl.BLEND)"); |
|
109 shouldBeTrue("gl.isFramebuffer(framebuffer)"); |
|
110 shouldBeTrue("gl.isProgram(program)"); |
|
111 shouldBeTrue("gl.isRenderbuffer(renderbuffer)"); |
|
112 shouldBeTrue("gl.isShader(shader)"); |
|
113 shouldBeTrue("gl.isTexture(texture)"); |
|
114 } |
|
115 |
|
116 function testLostContext() |
|
117 { |
|
118 debug("Test lost context"); |
|
119 |
|
120 // Functions with special return values. |
|
121 shouldBeTrue("gl.isContextLost()"); |
|
122 shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL"); |
|
123 shouldBe("gl.getError()", "gl.NO_ERROR"); |
|
124 shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_UNSUPPORTED"); |
|
125 shouldBe("gl.getAttribLocation(program, 'u_modelViewProjMatrix')", "-1"); |
|
126 shouldBe("gl.getVertexAttribOffset(0, gl.VERTEX_ATTRIB_ARRAY_POINTER)", "0"); |
|
127 |
|
128 // Test the extension itself. |
|
129 shouldGenerateGLError(gl, gl.INVALID_OPERATION, "extension.loseContext()"); |
|
130 |
|
131 image = document.createElement("img"); |
|
132 video = document.createElement("video"); |
|
133 canvas2d = document.createElement("canvas"); |
|
134 ctx2d = canvas2d.getContext("2d"); |
|
135 imageData = ctx2d.createImageData(1, 1); |
|
136 float32array = new Float32Array(1); |
|
137 int32array = new Int32Array(1); |
|
138 |
|
139 // Functions returning void should return immediately. |
|
140 // This is untestable, but we can at least be sure they cause no errors |
|
141 // and the codepaths are exercised. |
|
142 var voidTests = [ |
|
143 "gl.activeTexture(gl.TEXTURE0)", |
|
144 "gl.attachShader(program, shader)", |
|
145 "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)", |
|
146 "gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer)", |
|
147 "gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer)", |
|
148 "gl.bindTexture(gl.TEXTURE_2D, texture)", |
|
149 "gl.blendColor(1.0, 1.0, 1.0, 1.0)", |
|
150 "gl.blendEquation(gl.FUNC_ADD)", |
|
151 "gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD)", |
|
152 "gl.blendFunc(gl.ONE, gl.ONE)", |
|
153 "gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE)", |
|
154 "gl.bufferData(gl.ARRAY_BUFFER, 0, gl.STATIC_DRAW)", |
|
155 "gl.bufferData(gl.ARRAY_BUFFER, arrayBufferView, gl.STATIC_DRAW)", |
|
156 "gl.bufferData(gl.ARRAY_BUFFER, arrayBuffer, gl.STATIC_DRAW)", |
|
157 "gl.bufferSubData(gl.ARRAY_BUFFRE, 0, arrayBufferView)", |
|
158 "gl.bufferSubData(gl.ARRAY_BUFFRE, 0, arrayBuffer)", |
|
159 "gl.clear(gl.COLOR_BUFFER_BIT)", |
|
160 "gl.clearColor(1, 1, 1, 1)", |
|
161 "gl.clearDepth(1)", |
|
162 "gl.clearStencil(0)", |
|
163 "gl.colorMask(1, 1, 1, 1)", |
|
164 "gl.compileShader(shader)", |
|
165 "gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 0, 0, 0)", |
|
166 "gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 0, 0)", |
|
167 "gl.cullFace(gl.FRONT)", |
|
168 "gl.deleteBuffer(buffer)", |
|
169 "gl.deleteFramebuffer(framebuffer)", |
|
170 "gl.deleteProgram(program)", |
|
171 "gl.deleteRenderbuffer(renderbuffer)", |
|
172 "gl.deleteShader(shader)", |
|
173 "gl.deleteTexture(texture)", |
|
174 "gl.depthFunc(gl.NEVER)", |
|
175 "gl.depthMask(0)", |
|
176 "gl.depthRange(0, 1)", |
|
177 "gl.detachShader(program, shader)", |
|
178 "gl.disable(gl.BLEND)", |
|
179 "gl.disableVertexAttribArray(0)", |
|
180 "gl.drawArrays(gl.POINTS, 0, 0)", |
|
181 "gl.drawElements(gl.POINTS, 0, gl.UNSIGNED_SHORT, 0)", |
|
182 "gl.enable(gl.BLEND)", |
|
183 "gl.enableVertexAttribArray(0)", |
|
184 "gl.finish()", |
|
185 "gl.flush()", |
|
186 "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer)", |
|
187 "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0)", |
|
188 "gl.frontFace(gl.CW)", |
|
189 "gl.generateMipmap(gl.TEXTURE_2D)", |
|
190 "gl.hint(gl.GENERATE_MIPMAP_HINT, gl.FASTEST)", |
|
191 "gl.lineWidth(0)", |
|
192 "gl.linkProgram(program)", |
|
193 "gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0)", |
|
194 "gl.polygonOffset(0, 0)", |
|
195 "gl.readPixels(0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)", |
|
196 "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0)", |
|
197 "gl.sampleCoverage(0, 0)", |
|
198 "gl.scissor(0, 0, 0, 0)", |
|
199 "gl.shaderSource(shader, '')", |
|
200 "gl.stencilFunc(gl.NEVER, 0, 0)", |
|
201 "gl.stencilFuncSeparate(gl.FRONT, gl.NEVER, 0, 0)", |
|
202 "gl.stencilMask(0)", |
|
203 "gl.stencilMaskSeparate(gl.FRONT, 0)", |
|
204 "gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP)", |
|
205 "gl.stencilOpSeparate(gl.FRONT, gl.KEEP, gl.KEEP, gl.KEEP)", |
|
206 "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)", |
|
207 "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imageData)", |
|
208 "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image)", |
|
209 "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas)", |
|
210 "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video)", |
|
211 "gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)", |
|
212 "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)", |
|
213 "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)", |
|
214 "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, imageData)", |
|
215 "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, image)", |
|
216 "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, canvas)", |
|
217 "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, video)", |
|
218 "gl.uniform1f(uniformLocation, 0)", |
|
219 "gl.uniform1fv(uniformLocation, float32array)", |
|
220 "gl.uniform1fv(uniformLocation, [0])", |
|
221 "gl.uniform1i(uniformLocation, 0)", |
|
222 "gl.uniform1iv(uniformLocation, int32array)", |
|
223 "gl.uniform1iv(uniformLocation, [0])", |
|
224 "gl.uniform2f(uniformLocation, 0, 0)", |
|
225 "gl.uniform2fv(uniformLocation, float32array)", |
|
226 "gl.uniform2fv(uniformLocation, [0, 0])", |
|
227 "gl.uniform2i(uniformLocation, 0, 0)", |
|
228 "gl.uniform2iv(uniformLocation, int32array)", |
|
229 "gl.uniform2iv(uniformLocation, [0, 0])", |
|
230 "gl.uniform3f(uniformLocation, 0, 0, 0)", |
|
231 "gl.uniform3fv(uniformLocation, float32array)", |
|
232 "gl.uniform3fv(uniformLocation, [0, 0, 0])", |
|
233 "gl.uniform3i(uniformLocation, 0, 0, 0)", |
|
234 "gl.uniform3iv(uniformLocation, int32array)", |
|
235 "gl.uniform3iv(uniformLocation, [0, 0, 0])", |
|
236 "gl.uniform4f(uniformLocation, 0, 0, 0, 0)", |
|
237 "gl.uniform4fv(uniformLocation, float32array)", |
|
238 "gl.uniform4fv(uniformLocation, [0, 0, 0, 0])", |
|
239 "gl.uniform4i(uniformLocation, 0, 0, 0, 0)", |
|
240 "gl.uniform4iv(uniformLocation, int32array)", |
|
241 "gl.uniform4iv(uniformLocation, [0, 0, 0, 0])", |
|
242 "gl.uniformMatrix2fv(uniformLocation, false, float32array)", |
|
243 "gl.uniformMatrix2fv(uniformLocation, false, [0, 0, 0, 0])", |
|
244 "gl.uniformMatrix3fv(uniformLocation, false, float32array)", |
|
245 "gl.uniformMatrix3fv(uniformLocation, false, [0, 0, 0, 0, 0, 0, 0, 0, 0])", |
|
246 "gl.uniformMatrix4fv(uniformLocation, false, float32array)", |
|
247 "gl.uniformMatrix4fv(uniformLocation, false, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])", |
|
248 "gl.useProgram(program)", |
|
249 "gl.validateProgram(program)", |
|
250 "gl.vertexAttrib1f(0, 0)", |
|
251 "gl.vertexAttrib1fv(0, float32array)", |
|
252 "gl.vertexAttrib1fv(0, [0])", |
|
253 "gl.vertexAttrib2f(0, 0, 0)", |
|
254 "gl.vertexAttrib2fv(0, float32array)", |
|
255 "gl.vertexAttrib2fv(0, [0, 0])", |
|
256 "gl.vertexAttrib3f(0, 0, 0, 0)", |
|
257 "gl.vertexAttrib3fv(0, float32array)", |
|
258 "gl.vertexAttrib3fv(0, [0, 0, 0])", |
|
259 "gl.vertexAttrib4f(0, 0, 0, 0, 0)", |
|
260 "gl.vertexAttrib4fv(0, float32array)", |
|
261 "gl.vertexAttrib4fv(0, [0, 0, 0, 0])", |
|
262 "gl.vertexAttribPointer(0, 0, gl.FLOAT, false, 0, 0)", |
|
263 "gl.viewport(0, 0, 0, 0)", |
|
264 ]; |
|
265 for (var i = 0; i < voidTests.length; ++i) { |
|
266 shouldGenerateGLError(gl, gl.NO_ERROR, voidTests[i]); |
|
267 } |
|
268 |
|
269 // Functions return nullable values should all return null. |
|
270 var nullTests = [ |
|
271 "gl.createBuffer()", |
|
272 "gl.createFramebuffer()", |
|
273 "gl.createProgram()", |
|
274 "gl.createRenderbuffer()", |
|
275 "gl.createShader(gl.GL_VERTEX_SHADER)", |
|
276 "gl.createTexture()", |
|
277 "gl.getActiveAttrib(program, 0)", |
|
278 "gl.getActiveUniform(program, 0)", |
|
279 "gl.getAttachedShaders(program)", |
|
280 "gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE)", |
|
281 // Disabled pending test suite issue: |
|
282 // "gl.getContextAttributes()", |
|
283 "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", |
|
284 "gl.getParameter(gl.CURRENT_PROGRAM)", |
|
285 "gl.getProgramInfoLog(program)", |
|
286 "gl.getProgramParameter(program, gl.LINK_STATUS)", |
|
287 "gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)", |
|
288 "gl.getShaderInfoLog(shader)", |
|
289 "gl.getShaderParameter(shader, gl.SHADER_TYPE)", |
|
290 "gl.getShaderSource(shader)", |
|
291 "gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S)", |
|
292 "gl.getUniform(program, uniformLocation)", |
|
293 "gl.getUniformLocation(program, 'vPosition')", |
|
294 "gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)", |
|
295 "gl.getSupportedExtensions()", |
|
296 "gl.getExtension('" + extensionName + "')", |
|
297 ]; |
|
298 for (var i = 0; i < nullTests.length; ++i) { |
|
299 shouldBeNull(nullTests[i]); |
|
300 } |
|
301 |
|
302 // "Is" queries should all return false. |
|
303 shouldBeFalse("gl.isBuffer(buffer)"); |
|
304 shouldBeFalse("gl.isEnabled(gl.BLEND)"); |
|
305 shouldBeFalse("gl.isFramebuffer(framebuffer)"); |
|
306 shouldBeFalse("gl.isProgram(program)"); |
|
307 shouldBeFalse("gl.isRenderbuffer(renderbuffer)"); |
|
308 shouldBeFalse("gl.isShader(shader)"); |
|
309 shouldBeFalse("gl.isTexture(texture)"); |
|
310 |
|
311 shouldBe("gl.getError()", "gl.NO_ERROR"); |
|
312 |
|
313 debug(""); |
|
314 |
|
315 finishTest(); |
|
316 } |
|
317 |
|
318 </script> |
|
319 </head> |
|
320 <body onload="init()"> |
|
321 <div id="description"></div> |
|
322 <div id="console"></div> |
|
323 <canvas id="canvas"> |
|
324 </body> |
|
325 </html> |