# HG changeset patch # User Morris Tseng Bug 709490 - WorkerCanvas: WIP Part 3 - Tests diff --git a/dom/canvas/test/mochitest.ini b/dom/canvas/test/mochitest.ini index 9b4e922ff..8d7db1d 100644 --- a/dom/canvas/test/mochitest.ini +++ b/dom/canvas/test/mochitest.ini @@ -16,16 +16,18 @@ support-files = image_red.png image_redtransparent.png image_rgrg-256x256.png image_rrgg-256x256.png image_transparent.png image_transparent50.png image_yellow.png image_yellow75.png + workercanvas.js + workercanvas_neuter.js [test_2d.clearRect.image.offscreen.html] [test_2d.clip.winding.html] [test_2d.composite.canvas.color-burn.html] skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662 [test_2d.composite.canvas.color-dodge.html] skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662 [test_2d.composite.canvas.color.html] @@ -240,8 +242,18 @@ skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && toolkit != 'gonk') [test_toDataURL_lowercase_ascii.html] [test_toDataURL_parameters.html] [test_windingRuleUndefined.html] [test_2d.fillText.gradient.html] skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # bug 1040965 [test_2d_composite_canvaspattern_setTransform.html] [test_createPattern_broken.html] [test_setlinedash.html] +[test_workercanvas_basic_webgl.html] +tags = workercanvas +[test_workercanvas_neuter.html] +tags = workercanvas +[test_workercanvas_many.html] +tags = workercanvas +[test_workercanvas_sizechange.html] +tags = workercanvas +[test_workercanvas_subworker.html] +tags = workercanvas diff --git a/dom/canvas/test/test_workercanvas_basic_webgl.html b/dom/canvas/test/test_workercanvas_basic_webgl.html new file mode 100644 index 0000000..140ec47 --- /dev/null +++ b/dom/canvas/test/test_workercanvas_basic_webgl.html @@ -0,0 +1,51 @@ + + + +WebGL in WorkerCanvas + + + + + + + + diff --git a/dom/canvas/test/test_workercanvas_many.html b/dom/canvas/test/test_workercanvas_many.html new file mode 100644 index 0000000..252ea34 --- /dev/null +++ b/dom/canvas/test/test_workercanvas_many.html @@ -0,0 +1,64 @@ + + + +WebGL in WorkerCanvas + + + + +
+
+
+
+
+
+
+
+ + + diff --git a/dom/canvas/test/test_workercanvas_neuter.html b/dom/canvas/test/test_workercanvas_neuter.html new file mode 100644 index 0000000..00f3e82 --- /dev/null +++ b/dom/canvas/test/test_workercanvas_neuter.html @@ -0,0 +1,69 @@ + + + +WorkerCanvas: Test neutering + + + + + + + + diff --git a/dom/canvas/test/test_workercanvas_sizechange.html b/dom/canvas/test/test_workercanvas_sizechange.html new file mode 100644 index 0000000..22ce840 --- /dev/null +++ b/dom/canvas/test/test_workercanvas_sizechange.html @@ -0,0 +1,44 @@ + + + +WebGL in WorkerCanvas + + + + + + + + diff --git a/dom/canvas/test/test_workercanvas_subworker.html b/dom/canvas/test/test_workercanvas_subworker.html new file mode 100644 index 0000000..5564d33 --- /dev/null +++ b/dom/canvas/test/test_workercanvas_subworker.html @@ -0,0 +1,76 @@ + + + +WorkerCanvas: Test subworkers + + + + +
+
+
+
+
+
+
+
+
+
+ + + + diff --git a/dom/canvas/test/workercanvas.js b/dom/canvas/test/workercanvas.js new file mode 100644 index 0000000..f284c65 --- /dev/null +++ b/dom/canvas/test/workercanvas.js @@ -0,0 +1,251 @@ + +/* WebWorker for test_workercanvas_*.html */ + +function ok(expect, msg) { + postMessage({type: "test", result: !!expect, name: msg}); +} + +function todo(msg) { + postMessage({type: "todo", name: msg}); +} + +function finish() { + postMessage({type: "finish"}); +} + +//-------------------------------------------------------------------- +// WebGL Drawing Functions +//-------------------------------------------------------------------- + +function createDrawFunc(canvas) { + + var gl; + + try { + gl = canvas.getContext("webgl"); + } catch (e) {} + + if (!gl) { + todo("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); + if (!vs || !fs) + return null; + + 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 */ +onmessage = function(evt) { + + var test = evt.data.test; + var canvas = evt.data.canvas; + + if (test != "subworker") { + ok(canvas, "Canvas successfully transfered to worker"); + ok(canvas.getContext, "Canvas has getContext"); + + ok(canvas.width == 64, "WorkerCanvas width should be 64"); + ok(canvas.height == 64, "WorkerCanvas 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 WorkerCanvas from sub workers + //------------------------------------------------------------------------ + else if (test == "subworker") { + /* subworker tests take a list of tests to run on children */ + var stillRunning = 0; + evt.data.subtests.forEach(function (subtest) { + ++stillRunning; + var subworker = new Worker('workercanvas.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") + return [].concat.apply([], t.subtests.map(findTransferables)); + return [t.canvas]; + }; + + subworker.postMessage(subtest, findTransferables(subtest)); + }); + } +}; diff --git a/dom/canvas/test/workercanvas_neuter.js b/dom/canvas/test/workercanvas_neuter.js new file mode 100644 index 0000000..748e5ba --- /dev/null +++ b/dom/canvas/test/workercanvas_neuter.js @@ -0,0 +1,2 @@ + +/* empty worker for test_workercanvas_disable.html */