diff --git a/dom/canvas/test/mochitest.ini b/dom/canvas/test/mochitest.ini index ffee4bbb26d..12b23e2df38 100644 --- a/dom/canvas/test/mochitest.ini +++ b/dom/canvas/test/mochitest.ini @@ -27,6 +27,9 @@ support-files = imagebitmap_on_worker.js imagebitmap_structuredclone.js imagebitmap_structuredclone_iframe.html + offscreencanvas.js + offscreencanvas_neuter.js + offscreencanvas_serviceworker_inner.html [test_2d.clearRect.image.offscreen.html] [test_2d.clip.winding.html] @@ -261,3 +264,18 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # bug 1040965 [test_createPattern_broken.html] [test_setlinedash.html] [test_filter.html] +[test_offscreencanvas_basic_webgl.html] +tags = offscreencanvas +[test_offscreencanvas_sharedworker.html] +tags = offscreencanvas +[test_offscreencanvas_serviceworker.html] +tags = offscreencanvas +skip-if = buildapp == 'b2g' +[test_offscreencanvas_neuter.html] +tags = offscreencanvas +[test_offscreencanvas_many.html] +tags = offscreencanvas +[test_offscreencanvas_sizechange.html] +tags = offscreencanvas +[test_offscreencanvas_subworker.html] +tags = offscreencanvas diff --git a/dom/canvas/test/offscreencanvas.js b/dom/canvas/test/offscreencanvas.js new file mode 100644 index 00000000000..584954c3ef7 --- /dev/null +++ b/dom/canvas/test/offscreencanvas.js @@ -0,0 +1,274 @@ +/* WebWorker for test_offscreencanvas_*.html */ +var port = null; + +function ok(expect, msg) { + if (port) { + port.postMessage({type: "test", result: !!expect, name: msg}); + } else { + postMessage({type: "test", result: !!expect, name: msg}); + } +} + +function finish() { + if (port) { + port.postMessage({type: "finish"}); + } else { + postMessage({type: "finish"}); + } +} + +//-------------------------------------------------------------------- +// WebGL Drawing Functions +//-------------------------------------------------------------------- +function createDrawFunc(canvas) { + var gl; + + try { + gl = canvas.getContext("experimental-webgl"); + } catch (e) {} + + if (!gl) { + ok(false, "WebGL is unavailable"); + return null; + } + + var vertSrc = "attribute vec2 position; \ + void main(void) { \ + gl_Position = vec4(position, 0.0, 1.0); \ + }"; + + var fragSrc = "precision mediump float; \ + void main(void) { \ + gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); \ + }"; + + // Returns a valid shader, or null on errors. + var createShader = function(src, t) { + var shader = gl.createShader(t); + + gl.shaderSource(shader, src); + gl.compileShader(shader); + + return shader; + }; + + var createProgram = function(vsSrc, fsSrc) { + var vs = createShader(vsSrc, gl.VERTEX_SHADER); + var fs = createShader(fsSrc, gl.FRAGMENT_SHADER); + + var prog = gl.createProgram(); + gl.attachShader(prog, vs); + gl.attachShader(prog, fs); + gl.linkProgram(prog); + + if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) { + var str = "Shader program linking failed:"; + str += "\nShader program info log:\n" + gl.getProgramInfoLog(prog); + str += "\n\nVert shader log:\n" + gl.getShaderInfoLog(vs); + str += "\n\nFrag shader log:\n" + gl.getShaderInfoLog(fs); + console.log(str); + ok(false, "Shader program linking failed"); + return null; + } + + return prog; + }; + + gl.disable(gl.DEPTH_TEST); + + var program = createProgram(vertSrc, fragSrc); + ok(program, "Creating shader program"); + + program.positionAttr = gl.getAttribLocation(program, "position"); + ok(program.positionAttr >= 0, "position attribute should be valid"); + + var vertCoordArr = new Float32Array([ + -1, -1, + 1, -1, + -1, 1, + 1, 1, + ]); + var vertCoordBuff = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vertCoordBuff); + gl.bufferData(gl.ARRAY_BUFFER, vertCoordArr, gl.STATIC_DRAW); + + var checkGLError = function(prefix, refValue) { + if (!refValue) { + refValue = 0; + } + + var error = gl.getError(); + ok(error == refValue, + prefix + 'gl.getError should be 0x' + refValue.toString(16) + + ', was 0x' + error.toString(16) + '.'); + }; + + var testPixel = function(x, y, refData, infoString) { + var pixel = new Uint8Array(4); + gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); + + var pixelMatches = pixel[0] == refData[0] && + pixel[1] == refData[1] && + pixel[2] == refData[2] && + pixel[3] == refData[3]; + ok(pixelMatches, infoString); + }; + + var preDraw = function(prefix) { + gl.clearColor(1.0, 0.0, 0.0, 1.0); + gl.clear(gl.COLOR_BUFFER_BIT); + + testPixel(0, 0, [255, 0, 0, 255], prefix + 'Should be red before drawing.'); + }; + + var postDraw = function(prefix) { + testPixel(0, 0, [0, 255, 0, 255], prefix + 'Should be green after drawing.'); + }; + + gl.useProgram(program); + gl.enableVertexAttribArray(program.position); + gl.vertexAttribPointer(program.position, 2, gl.FLOAT, false, 0, 0); + + // Start drawing + checkGLError('after setup'); + + return function(prefix) { + if (prefix) { + prefix = "[" + prefix + "] "; + } else { + prefix = ""; + } + + gl.viewport(0, 0, canvas.width, canvas.height); + + preDraw(prefix); + gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); + postDraw(prefix); + checkGLError(prefix); + }; +} + +/* entry point */ +function entryFunction(testStr, subtests, offscreenCanvas) { + var test = testStr; + var canvas = offscreenCanvas; + + if (test != "subworker") { + ok(canvas, "Canvas successfully transfered to worker"); + ok(canvas.getContext, "Canvas has getContext"); + + ok(canvas.width == 64, "OffscreenCanvas width should be 64"); + ok(canvas.height == 64, "OffscreenCanvas height should be 64"); + } + + var draw; + + //------------------------------------------------------------------------ + // Basic WebGL test + //------------------------------------------------------------------------ + if (test == "webgl") { + draw = createDrawFunc(canvas); + if (!draw) { + finish(); + return; + } + + var count = 0; + var iid = setInterval(function() { + if (count++ > 20) { + clearInterval(iid); + ok(true, "Worker is done"); + finish(); + return; + } + draw("loop " +count); + }, 0); + } + //------------------------------------------------------------------------ + // Canvas Size Change from Worker + //------------------------------------------------------------------------ + else if (test == "webgl_changesize") { + draw = createDrawFunc(canvas); + if (!draw) { + finish(); + return; + } + + draw("64x64"); + + setTimeout(function() { + canvas.width = 128; + canvas.height = 128; + draw("Increased to 128x128"); + + setTimeout(function() { + canvas.width = 32; + canvas.width = 32; + draw("Decreased to 32x32"); + + setTimeout(function() { + canvas.width = 64; + canvas.height = 64; + draw("Increased to 64x64"); + + ok(true, "Worker is done"); + finish(); + }, 0); + }, 0); + }, 0); + } + //------------------------------------------------------------------------ + // Using OffscreenCanvas from sub workers + //------------------------------------------------------------------------ + else if (test == "subworker") { + /* subworker tests take a list of tests to run on children */ + var stillRunning = 0; + subtests.forEach(function (subtest) { + ++stillRunning; + var subworker = new Worker('offscreencanvas.js'); + subworker.onmessage = function(evt) { + /* report finish to parent when all children are finished */ + if (evt.data.type == "finish") { + subworker.terminate(); + if (--stillRunning == 0) { + ok(true, "Worker is done"); + finish(); + } + return; + } + /* relay all other messages to parent */ + postMessage(evt.data); + }; + + var findTransferables = function(t) { + if (t.test == "subworker") { + var result = []; + t.subtests.forEach(function(test) { + result = result.concat(findTransferables(test)); + }); + + return result; + } else { + return [t.canvas]; + } + }; + + subworker.postMessage(subtest, findTransferables(subtest)); + }); + } +}; + +onmessage = function(evt) { + port = evt.ports[0]; + entryFunction(evt.data.test, evt.data.subtests, evt.data.canvas); +}; + +onconnect = function(evt) { + port = evt.ports[0]; + + port.addEventListener('message', function(evt) { + entryFunction(evt.data.test, evt.data.subtests, evt.data.canvas); + }); + + port.start(); +}; diff --git a/dom/canvas/test/offscreencanvas_neuter.js b/dom/canvas/test/offscreencanvas_neuter.js new file mode 100644 index 00000000000..30648d740a1 --- /dev/null +++ b/dom/canvas/test/offscreencanvas_neuter.js @@ -0,0 +1 @@ +/* empty worker for test_offscreencanvas_disable.html */ diff --git a/dom/canvas/test/offscreencanvas_serviceworker_inner.html b/dom/canvas/test/offscreencanvas_serviceworker_inner.html new file mode 100644 index 00000000000..b153f9524a1 --- /dev/null +++ b/dom/canvas/test/offscreencanvas_serviceworker_inner.html @@ -0,0 +1,32 @@ + + + +WebGL in OffscreenCanvas + + + + + + diff --git a/dom/canvas/test/test_offscreencanvas_basic_webgl.html b/dom/canvas/test/test_offscreencanvas_basic_webgl.html new file mode 100644 index 00000000000..dd3ac21e748 --- /dev/null +++ b/dom/canvas/test/test_offscreencanvas_basic_webgl.html @@ -0,0 +1,48 @@ + + + +WebGL in OffscreenCanvas + + + + + + + + diff --git a/dom/canvas/test/test_offscreencanvas_many.html b/dom/canvas/test/test_offscreencanvas_many.html new file mode 100644 index 00000000000..6bf2680c50b --- /dev/null +++ b/dom/canvas/test/test_offscreencanvas_many.html @@ -0,0 +1,67 @@ + + + +WebGL in OffscreenCanvas + + + + + + + + diff --git a/dom/canvas/test/test_offscreencanvas_neuter.html b/dom/canvas/test/test_offscreencanvas_neuter.html new file mode 100644 index 00000000000..2af080c7c1e --- /dev/null +++ b/dom/canvas/test/test_offscreencanvas_neuter.html @@ -0,0 +1,78 @@ + + + +OffscreenCanvas: Test neutering + + + + + + + + diff --git a/dom/canvas/test/test_offscreencanvas_serviceworker.html b/dom/canvas/test/test_offscreencanvas_serviceworker.html new file mode 100644 index 00000000000..c5cfb93db1a --- /dev/null +++ b/dom/canvas/test/test_offscreencanvas_serviceworker.html @@ -0,0 +1,46 @@ + + + +WebGL in OffscreenCanvas + + + + + + + diff --git a/dom/canvas/test/test_offscreencanvas_sharedworker.html b/dom/canvas/test/test_offscreencanvas_sharedworker.html new file mode 100644 index 00000000000..28d7ce37c8a --- /dev/null +++ b/dom/canvas/test/test_offscreencanvas_sharedworker.html @@ -0,0 +1,47 @@ + + + +WebGL in OffscreenCanvas + + + + + + + + diff --git a/dom/canvas/test/test_offscreencanvas_sizechange.html b/dom/canvas/test/test_offscreencanvas_sizechange.html new file mode 100644 index 00000000000..cecbac34834 --- /dev/null +++ b/dom/canvas/test/test_offscreencanvas_sizechange.html @@ -0,0 +1,41 @@ + + + +WebGL in OffscreenCanvas + + + + + + + + diff --git a/dom/canvas/test/test_offscreencanvas_subworker.html b/dom/canvas/test/test_offscreencanvas_subworker.html new file mode 100644 index 00000000000..b3fbae821c9 --- /dev/null +++ b/dom/canvas/test/test_offscreencanvas_subworker.html @@ -0,0 +1,90 @@ + + + +OffscreenCanvas: Test subworkers + + + + + + + +