offscreencanvas.js (10211B)
1 /* WebWorker for test_offscreencanvas_*.html */ 2 (function () { 3 var port = null; 4 5 function isInWorker() { 6 try { 7 return !(self instanceof Window); 8 } catch (e) { 9 return true; 10 } 11 } 12 13 function postMessageGeneral(data) { 14 if (isInWorker()) { 15 if (port) { 16 port.postMessage(data); 17 } else { 18 postMessage(data); 19 } 20 } else { 21 postMessage(data, "*"); 22 } 23 } 24 25 function ok(expect, msg) { 26 postMessageGeneral({ type: "test", result: !!expect, name: msg }); 27 } 28 29 function finish() { 30 postMessageGeneral({ type: "finish" }); 31 } 32 33 function drawCount(count) { 34 postMessageGeneral({ type: "draw", count }); 35 } 36 37 function sendBlob(blob) { 38 postMessageGeneral({ type: "blob", blob }); 39 } 40 41 function sendImageBitmap(img) { 42 if (port) { 43 port.postMessage({ type: "imagebitmap", bitmap: img }); 44 } else { 45 postMessage({ type: "imagebitmap", bitmap: img }); 46 } 47 } 48 49 //-------------------------------------------------------------------- 50 // WebGL Drawing Functions 51 //-------------------------------------------------------------------- 52 function createDrawFunc(canvas) { 53 var gl; 54 55 try { 56 gl = canvas.getContext("webgl"); 57 } catch (e) {} 58 59 if (!gl) { 60 ok(false, "WebGL is unavailable"); 61 return null; 62 } 63 64 var vertSrc = 65 "attribute vec2 position; \ 66 void main(void) { \ 67 gl_Position = vec4(position, 0.0, 1.0); \ 68 }"; 69 70 var fragSrc = 71 "precision mediump float; \ 72 void main(void) { \ 73 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); \ 74 }"; 75 76 // Returns a valid shader, or null on errors. 77 var createShader = function (src, t) { 78 var shader = gl.createShader(t); 79 80 gl.shaderSource(shader, src); 81 gl.compileShader(shader); 82 83 return shader; 84 }; 85 86 var createProgram = function (vsSrc, fsSrc) { 87 var vs = createShader(vsSrc, gl.VERTEX_SHADER); 88 var fs = createShader(fsSrc, gl.FRAGMENT_SHADER); 89 90 var prog = gl.createProgram(); 91 gl.attachShader(prog, vs); 92 gl.attachShader(prog, fs); 93 gl.linkProgram(prog); 94 95 if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) { 96 var str = "Shader program linking failed:"; 97 str += "\nShader program info log:\n" + gl.getProgramInfoLog(prog); 98 str += "\n\nVert shader log:\n" + gl.getShaderInfoLog(vs); 99 str += "\n\nFrag shader log:\n" + gl.getShaderInfoLog(fs); 100 console.log(str); 101 ok(false, "Shader program linking failed"); 102 return null; 103 } 104 105 return prog; 106 }; 107 108 gl.disable(gl.DEPTH_TEST); 109 110 var program = createProgram(vertSrc, fragSrc); 111 ok(program, "Creating shader program"); 112 113 program.positionAttr = gl.getAttribLocation(program, "position"); 114 ok(program.positionAttr >= 0, "position attribute should be valid"); 115 116 var vertCoordArr = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]); 117 var vertCoordBuff = gl.createBuffer(); 118 gl.bindBuffer(gl.ARRAY_BUFFER, vertCoordBuff); 119 gl.bufferData(gl.ARRAY_BUFFER, vertCoordArr, gl.STATIC_DRAW); 120 121 var checkGLError = function (prefix, refValue) { 122 if (!refValue) { 123 refValue = 0; 124 } 125 126 var error = gl.getError(); 127 ok( 128 error == refValue, 129 prefix + 130 "gl.getError should be 0x" + 131 refValue.toString(16) + 132 ", was 0x" + 133 error.toString(16) + 134 "." 135 ); 136 }; 137 138 var testPixel = function (x, y, refData, infoString) { 139 var pixel = new Uint8Array(4); 140 gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); 141 142 var pixelMatches = 143 pixel[0] == refData[0] && 144 pixel[1] == refData[1] && 145 pixel[2] == refData[2] && 146 pixel[3] == refData[3]; 147 ok(pixelMatches, infoString); 148 }; 149 150 var preDraw = function (prefix) { 151 gl.clearColor(1.0, 0.0, 0.0, 1.0); 152 gl.clear(gl.COLOR_BUFFER_BIT); 153 154 testPixel( 155 0, 156 0, 157 [255, 0, 0, 255], 158 prefix + "Should be red before drawing." 159 ); 160 }; 161 162 var postDraw = function (prefix) { 163 testPixel( 164 0, 165 0, 166 [0, 255, 0, 255], 167 prefix + "Should be green after drawing." 168 ); 169 }; 170 171 gl.useProgram(program); 172 gl.enableVertexAttribArray(program.position); 173 gl.vertexAttribPointer(program.position, 2, gl.FLOAT, false, 0, 0); 174 175 // Start drawing 176 checkGLError("after setup"); 177 178 return function (prefix, needCommitFrame) { 179 if (prefix) { 180 prefix = "[" + prefix + "] "; 181 } else { 182 prefix = ""; 183 } 184 185 gl.viewport(0, 0, canvas.width, canvas.height); 186 checkGLError(prefix + "[viewport]"); 187 188 preDraw(prefix); 189 checkGLError(prefix + "[predraw]"); 190 gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 191 checkGLError(prefix + "[drawarrays]"); 192 postDraw(prefix); 193 checkGLError(prefix + "[postdraw]"); 194 if (needCommitFrame) { 195 gl.commit(); 196 checkGLError(prefix + "[commit]"); 197 } 198 checkGLError(prefix); 199 }; 200 } 201 202 /* entry point */ 203 function entryFunction(testStr, subtests, offscreenCanvas) { 204 var test = testStr; 205 var canvas = offscreenCanvas; 206 if (test == "webgl_imagebitmap") { 207 canvas = new OffscreenCanvas(64, 64); 208 } 209 210 if (test != "subworker") { 211 ok(canvas, "Canvas successfully transfered to worker"); 212 ok(canvas.getContext, "Canvas has getContext"); 213 214 ok(canvas.width == 64, "OffscreenCanvas width should be 64"); 215 ok(canvas.height == 64, "OffscreenCanvas height should be 64"); 216 } 217 218 var draw; 219 220 //------------------------------------------------------------------------ 221 // Basic WebGL test 222 //------------------------------------------------------------------------ 223 if (test == "webgl") { 224 draw = createDrawFunc(canvas); 225 if (!draw) { 226 finish(); 227 return; 228 } 229 230 var count = 0; 231 var iid = setInterval(function () { 232 if (count++ > 20) { 233 clearInterval(iid); 234 ok(true, "Worker is done"); 235 finish(); 236 return; 237 } 238 draw("loop " + count, true); 239 }, 0); 240 } 241 //------------------------------------------------------------------------ 242 // Test dynamic fallback 243 //------------------------------------------------------------------------ 244 else if (test == "webgl_fallback") { 245 draw = createDrawFunc(canvas); 246 if (!draw) { 247 return; 248 } 249 250 var count = 0; 251 var iid = setInterval(function () { 252 ++count; 253 draw("loop " + count, true); 254 drawCount(count); 255 }, 0); 256 } 257 //------------------------------------------------------------------------ 258 // Test toBlob 259 //------------------------------------------------------------------------ 260 else if (test == "webgl_toblob") { 261 draw = createDrawFunc(canvas); 262 if (!draw) { 263 return; 264 } 265 266 draw("", false); 267 canvas.toBlob().then(function (blob) { 268 sendBlob(blob); 269 }); 270 } 271 //------------------------------------------------------------------------ 272 // Test toImageBitmap 273 //------------------------------------------------------------------------ 274 else if (test == "webgl_imagebitmap") { 275 draw = createDrawFunc(canvas); 276 if (!draw) { 277 return; 278 } 279 280 draw("", false); 281 var imgBitmap = canvas.transferToImageBitmap(); 282 sendImageBitmap(imgBitmap); 283 } 284 //------------------------------------------------------------------------ 285 // Canvas Size Change from Worker 286 //------------------------------------------------------------------------ 287 else if (test == "webgl_changesize") { 288 draw = createDrawFunc(canvas); 289 if (!draw) { 290 finish(); 291 return; 292 } 293 294 draw("64x64", true); 295 296 setTimeout(function () { 297 canvas.width = 128; 298 canvas.height = 128; 299 draw("Increased to 128x128", true); 300 301 setTimeout(function () { 302 canvas.width = 32; 303 canvas.width = 32; 304 draw("Decreased to 32x32", true); 305 306 setTimeout(function () { 307 canvas.width = 64; 308 canvas.height = 64; 309 draw("Increased to 64x64", true); 310 311 ok(true, "Worker is done"); 312 finish(); 313 }, 0); 314 }, 0); 315 }, 0); 316 } 317 //------------------------------------------------------------------------ 318 // Using OffscreenCanvas from sub workers 319 //------------------------------------------------------------------------ 320 else if (test == "subworker") { 321 /* subworker tests take a list of tests to run on children */ 322 var stillRunning = 0; 323 subtests.forEach(function (subtest) { 324 ++stillRunning; 325 var subworker = new Worker("offscreencanvas.js"); 326 subworker.onmessage = function (evt) { 327 /* report finish to parent when all children are finished */ 328 if (evt.data.type == "finish") { 329 subworker.terminate(); 330 if (--stillRunning == 0) { 331 ok(true, "Worker is done"); 332 finish(); 333 } 334 return; 335 } 336 /* relay all other messages to parent */ 337 postMessage(evt.data); 338 }; 339 340 var findTransferables = function (t) { 341 if (t.test == "subworker") { 342 var result = []; 343 t.subtests.forEach(function (subWorkerTest) { 344 result = result.concat(findTransferables(subWorkerTest)); 345 }); 346 347 return result; 348 } else { 349 return [t.canvas]; 350 } 351 }; 352 353 subworker.postMessage(subtest, findTransferables(subtest)); 354 }); 355 } 356 } 357 358 onmessage = function (evt) { 359 port = evt.ports[0]; 360 entryFunction(evt.data.test, evt.data.subtests, evt.data.canvas); 361 }; 362 363 onconnect = function (evt) { 364 port = evt.ports[0]; 365 366 port.addEventListener("message", function (event) { 367 entryFunction(event.data.test, event.data.subtests, event.data.canvas); 368 }); 369 370 port.start(); 371 }; 372 373 if (!isInWorker()) { 374 window.entryFunction = entryFunction; 375 } 376 })();