OLD | NEW |
(Empty) | |
| 1 <!DOCTYPE html> |
| 2 <html> |
| 3 <head> |
| 4 <script src="../../../resources/testharness.js"></script> |
| 5 <script src="../../../resources/testharnessreport.js"></script> |
| 6 <script src="./resources/webgl-test.js"></script> |
| 7 <script src="./resources/webgl-test-utils-full.js"></script> |
| 8 </head> |
| 9 <body> |
| 10 |
| 11 <script id="myWorker" type="text/worker"> |
| 12 var canvas; |
| 13 var gl; |
| 14 var shouldGenerateGLError; |
| 15 var WEBGL_lose_context; |
| 16 var new_WEBGL_lose_context; |
| 17 var allowRestore; |
| 18 var contextLostEventFired; |
| 19 var contextRestoredEventFired; |
| 20 var OES_vertex_array_object; |
| 21 var old_OES_vertex_array_object; |
| 22 var OES_texture_float; |
| 23 var newExtension; |
| 24 // Purposely make all results true for easy testing |
| 25 var results = []; |
| 26 |
| 27 function compareGLError(glError, evalStr) |
| 28 { |
| 29 var exception; |
| 30 try { |
| 31 eval(evalStr); |
| 32 } catch (e) { |
| 33 exception = e; |
| 34 } |
| 35 if (exception) { |
| 36 return false; |
| 37 } else { |
| 38 if (gl.getError() == glError) |
| 39 return true; |
| 40 return false; |
| 41 } |
| 42 } |
| 43 |
| 44 function setupTest() |
| 45 { |
| 46 canvas = new OffscreenCanvas(10, 10); |
| 47 gl = canvas.getContext('webgl'); |
| 48 WEBGL_lose_context = gl.getExtension("WEBGL_lose_context"); |
| 49 if (!WEBGL_lose_context) |
| 50 return false; |
| 51 |
| 52 // Try to get a few extensions |
| 53 OES_vertex_array_object = gl.getExtension("OES_vertex_array_object"); |
| 54 OES_texture_float = gl.getExtension("OES_texture_float"); |
| 55 |
| 56 return true; |
| 57 } |
| 58 |
| 59 function reGetExtensionAndTestForProperty(gl, name, expectProperty) { |
| 60 newExtension = gl.getExtension(name); |
| 61 // NOTE: while getting a extension after context lost/restored is allowed to f
ail |
| 62 // for the purpose the conformance tests it is not. |
| 63 // |
| 64 // Hypothetically the user can switch GPUs live. For example on Windows, insta
ll 2 GPUs, |
| 65 // then in the control panen enable 1, disable the others and visa versa. Sinc
e the GPUs |
| 66 // have different capabilities one or the other may not support a particlar ex
tension. |
| 67 // |
| 68 // But, for the purpose of the conformance tests the context is expected to re
store |
| 69 // on the same GPU and therefore the extensions that succeeded previously shou
ld |
| 70 // succeed on restore. |
| 71 results.push(newExtension != null); |
| 72 if (expectProperty) { |
| 73 results.push(newExtension.webglTestProperty === true); |
| 74 } else { |
| 75 results.push(newExtension.webglTestProperty === undefined); |
| 76 } |
| 77 return newExtension; |
| 78 } |
| 79 |
| 80 function testLosingAndRestoringContext() |
| 81 { |
| 82 if (!setupTest()) { |
| 83 results.push(false); |
| 84 postMessage(results); |
| 85 } |
| 86 |
| 87 canvas.addEventListener("webglcontextlost", function(e) { |
| 88 testLostContext(e); |
| 89 // restore the context after this event has exited. |
| 90 setTimeout(function() { |
| 91 results.push(compareGLError(gl.NO_ERROR, "WEBGL_lose_context.restore
Context()")); |
| 92 // The context should still be lost. It will not get restored until
the |
| 93 // webglrestorecontext event is fired. |
| 94 results.push(gl.isContextLost()); |
| 95 results.push(gl.getError() == gl.NO_ERROR); |
| 96 // gl methods should still be no-ops |
| 97 results.push(compareGLError(gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D
, gl.TEXTURE_CUBE_MAP)")); |
| 98 }, 0); |
| 99 }); |
| 100 canvas.addEventListener("webglcontextrestored", function() { |
| 101 testRestoredContext(); |
| 102 self.postMessage(results); |
| 103 }); |
| 104 allowRestore = true; |
| 105 contextLostEventFired = false; |
| 106 contextRestoredEventFired = false; |
| 107 |
| 108 testOriginalContext(); |
| 109 WEBGL_lose_context.loseContext(); |
| 110 // The context should be lost immediately. |
| 111 results.push(gl.isContextLost()); |
| 112 results.push(gl.getError() == gl.CONTEXT_LOST_WEBGL); |
| 113 results.push(gl.getError() == gl.NO_ERROR); |
| 114 // gl methods should be no-ops |
| 115 results.push(compareGLError(gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEX
TURE_CUBE_MAP)")); |
| 116 // but the event should not have been fired. |
| 117 results.push(!contextLostEventFired); |
| 118 } |
| 119 |
| 120 function testOriginalContext() |
| 121 { |
| 122 results.push(!gl.isContextLost()); |
| 123 results.push(gl.getError() == gl.NO_ERROR); |
| 124 } |
| 125 |
| 126 function testLostContext(e) |
| 127 { |
| 128 results.push(!contextLostEventFired); |
| 129 contextLostEventFired = true; |
| 130 results.push(gl.isContextLost()); |
| 131 results.push(gl.getError() == gl.NO_ERROR); |
| 132 if (allowRestore) |
| 133 e.preventDefault(); |
| 134 } |
| 135 |
| 136 function testShouldNotRestoreContext(e) |
| 137 { |
| 138 testFailed("Should not restore the context unless preventDefault is called o
n the context lost event"); |
| 139 } |
| 140 |
| 141 function testOESTextureFloat() { |
| 142 if (OES_texture_float) { |
| 143 // Extension must still be lost. |
| 144 var tex = gl.createTexture(); |
| 145 gl.bindTexture(gl.TEXTURE_2D, tex); |
| 146 results.push(compareGLError(gl.INVALID_ENUM, "gl.texImage2D(gl.TEXTURE_2D, 0
, gl.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null)")); |
| 147 // Try re-enabling extension |
| 148 OES_texture_float = reGetExtensionAndTestForProperty(gl, "OES_texture_float"
, false); |
| 149 results.push(compareGLError(gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl
.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null)")); |
| 150 } |
| 151 } |
| 152 |
| 153 function testOESVertexArrayObject() { |
| 154 if (OES_vertex_array_object) { |
| 155 // Extension must still be lost. |
| 156 results.push(OES_vertex_array_object.createVertexArrayOES() == null); |
| 157 // Try re-enabling extension |
| 158 |
| 159 old_OES_vertex_array_object = OES_vertex_array_object; |
| 160 OES_vertex_array_object = reGetExtensionAndTestForProperty(gl, "OES_vertex_a
rray_object", false); |
| 161 results.push(OES_vertex_array_object.createVertexArrayOES() != null); |
| 162 results.push(old_OES_vertex_array_object.createVertexArrayOES() == null); |
| 163 } |
| 164 } |
| 165 |
| 166 function testExtensions() { |
| 167 testOESTextureFloat(); |
| 168 testOESVertexArrayObject(); |
| 169 } |
| 170 |
| 171 function testRestoredContext() |
| 172 { |
| 173 results.push(!contextRestoredEventFired); |
| 174 contextRestoredEventFired = true; |
| 175 results.push(!gl.isContextLost()); |
| 176 results.push(gl.getError() == gl.NO_ERROR); |
| 177 testExtensions(); |
| 178 } |
| 179 self.onmessage = function(e) { |
| 180 if (!setupTest()) { |
| 181 results.push(false); |
| 182 postMessage(results); |
| 183 } |
| 184 |
| 185 canvas.addEventListener("webglcontextlost", function(e) { |
| 186 testLostContext(e); |
| 187 // restore the context after this event has exited. |
| 188 setTimeout(function() { |
| 189 // we didn't call prevent default so we should not be able to restor
e the context |
| 190 results.push(compareGLError(gl.INVALID_OPERATION, "WEBGL_lose_contex
t.restoreContext()")); |
| 191 testLosingAndRestoringContext(); |
| 192 }, 0); |
| 193 }); |
| 194 canvas.addEventListener("webglcontextrestored", testShouldNotRestoreContext)
; |
| 195 allowRestore = false; |
| 196 contextLostEventFired = false; |
| 197 contextRestoredEventFired = false; |
| 198 |
| 199 testOriginalContext(); |
| 200 WEBGL_lose_context.loseContext(); |
| 201 // The context should be lost immediately. |
| 202 results.push(gl.isContextLost()); |
| 203 results.push(gl.getError() == gl.CONTEXT_LOST_WEBGL); |
| 204 results.push(gl.getError() == gl.NO_ERROR); |
| 205 // gl methods should be no-ops |
| 206 results.push(compareGLError(gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEX
TURE_CUBE_MAP)")); |
| 207 // but the event should not have been fired. |
| 208 results.push(!contextLostEventFired); |
| 209 }; |
| 210 |
| 211 </script> |
| 212 |
| 213 <script> |
| 214 function makeWorker(script) { |
| 215 var blob = new Blob([script]); |
| 216 return new Worker(URL.createObjectURL(blob)); |
| 217 } |
| 218 |
| 219 var t = async_test('Test that WebGL context restoration with OffscreenCanvas in
a worker'); |
| 220 var worker = makeWorker(document.getElementById("myWorker").textContent); |
| 221 worker.addEventListener('message', t.step_func_done(function(msg) { |
| 222 var results = msg.data; |
| 223 assert_equals(results.length, 33); |
| 224 for (var i = 0; i < results.length; i++) |
| 225 assert_equals(results[i], true); |
| 226 })); |
| 227 worker.postMessage("start"); |
| 228 </script> |
| 229 </body> |
| 230 </html> |
OLD | NEW |