<!DOCTYPE HTML> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>WebGL test: CaptureStream()</title> <script src="/tests/SimpleTest/SimpleTest.js"></script> <link rel="stylesheet" href="/tests/SimpleTest/test.css"> <script src="captureStream_common.js"> <script src="driver-info.js"></script> <script src="webgl-util.js"></script> <script id="vs" type="x-shader/x-vertex"> attribute vec2 aVertCoord; void main(void) { gl_Position = vec4(aVertCoord, 0.0, 1.0); } </script> <script id="fs" type="x-shader/x-fragment"> precision mediump float; uniform vec4 uColor; void main(void) { gl_FragColor = uColor; } </script> <body> <script> // Globals. Initialized during beginTest(). var c; // Canvas element captured by streams. var gl; // WebGLContext of |c|. var h; // CaptureStreamTestHelper holding utility test functions. var vauto; // Video element with captureStream stream in automatic mode. var vmanual; // Video element with captureStream stream in manual (fps 0) mode. var vrate; // Video element with captureStream stream with fixed frame rate. /* Fails the test if there was a GL error */ function checkGLError(info) { var error = gl.getError(); // Comparing strings for sake of log output in hex format. is("0x" + error.toString(16), "0x0", "WebGL error [" + info + "]"); } function checkClearColorInitialRed() { info("Checking that clearing to red works for first frame."); h.clearColor(c, h.red); vauto.srcObject = c.captureStream(); vmanual.srcObject = c.captureStream(0); vrate.srcObject = c.captureStream(10); ok(h.isPixel(h.getPixel(vauto), h.blackTransparent, 0, "vauto should not be drawn to before stable state")); ok(h.isPixel(h.getPixel(vrate), h.blackTransparent, 0, "vrate should not be drawn to before stable state")); ok(h.isPixel(h.getPixel(vmanual), h.blackTransparent, 0, "vmanual should not be drawn to before stable state")); return Promise.resolve() .then(() => h.waitForPixelColor(vauto, h.red, 0, "should become red automatically")) .then(() => h.waitForPixelColor(vrate, h.red, 0, "should become red automatically")) .then(() => h.waitForPixelColor(vmanual, h.red, 0, "should become red when we get to stable " + "state (first frame)")) } function checkDrawColorGreen() { info("Checking that drawing green results in green video frames."); var drawing = h.startDrawing(h.drawColor.bind(h, c, h.green)); checkGLError('after DrawColor'); return Promise.resolve() .then(() => h.waitForPixelColor(vauto, h.green, 0, "should become green automatically")) .then(() => h.waitForPixelColor(vrate, h.green, 0, "should become green automatically")) .then(() => h.waitForPixelColor(vmanual, h.red, 0, "should still be red")) .then(() => h.requestFrame(vmanual)) .then(() => h.waitForPixelColor(vmanual, h.green, 0, "should become green after requstFrame()")) .then(() => drawing.stop()); } function checkClearColorRed() { info("Checking that clearing to red works."); var drawing = h.startDrawing(h.clearColor.bind(h, c, h.red)); return Promise.resolve() .then(() => h.waitForPixelColor(vauto, h.red, 0, "should become red automatically")) .then(() => h.waitForPixelColor(vrate, h.red, 0, "should become red automatically")) .then(() => h.waitForPixelColor(vmanual, h.green, 0, "should still be green")) .then(() => h.requestFrame(vmanual)) .then(() => h.waitForPixelColor(vmanual, h.red, 0, "should become red after requestFrame()")) .then(() => drawing.stop()); } function checkRequestFrameOrderGuarantee() { info("Checking that requestFrame() immediately after a draw " + "call results in the expected frame seen in the stream."); return Promise.resolve() .then(() => h.waitForPixelColor(vmanual, h.red, 0, "should still be red")) .then(() => h.drawColor(c, h.green)) // 1. Draw canvas green .then(() => h.requestFrame(vmanual)) // 2. Immediately request a frame .then(() => h.waitForPixelColor(vmanual, h.green, 0, "should become green after call order test")) } function checkEndedOnStop() { let promises = [vauto, vmanual, vrate].map(elem => { elem.srcObject.getTracks()[0].stop(); return new Promise(resolve => elem.addEventListener("ended", function endedListener(event) { ok(true, "Element " + elem.id + " ended."); resolve(); elem.removeEventListener("ended", endedListener); })); }); return Promise.all(promises); } function finish() { ok(true, 'Test complete.'); SimpleTest.finish(); } function beginTest() { h = new CaptureStreamTestHelperWebGL(); c = h.createAndAppendElement('canvas', 'c'); vauto = h.createAndAppendElement('video', 'vauto'); vmanual = h.createAndAppendElement('video', 'vmanual'); vrate = h.createAndAppendElement('video', 'vrate'); gl = WebGLUtil.getWebGL('c', false); if (!gl) { todo(false, 'WebGL is unavailable.'); finish(); return; } function errorFunc(str) { ok(false, 'Error: ' + str); } WebGLUtil.setErrorFunc(errorFunc); WebGLUtil.setWarningFunc(errorFunc); gl.disable(gl.DEPTH_TEST); prog = WebGLUtil.createProgramByIds(gl, 'vs', 'fs'); if (!prog) { ok(false, 'Program linking should succeed.'); return; } // Setup vertex coordinates for drawing a rectangle across the whole canvas. prog.aVertCoord = gl.getAttribLocation(prog, "aVertCoord"); ok(prog.aVertCoord >= 0, '`aVertCoord` 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); gl.useProgram(prog); gl.enableVertexAttribArray(prog.aVertCoord); gl.vertexAttribPointer(prog.aVertCoord, 2, gl.FLOAT, false, 0, 0); // Setup the helper with a pointer to how to change fragment color. var uColorLocation = gl.getUniformLocation(prog, "uColor"); h.setFragmentColorLocation(uColorLocation); checkGLError('after setup'); // Run tests. Promise.resolve() .then(checkClearColorInitialRed) .then(checkDrawColorGreen) .then(checkClearColorRed) .then(checkRequestFrameOrderGuarantee) .then(checkEndedOnStop) .then(finish); } SimpleTest.waitForExplicitFinish(); beginTest(); </script>