summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-mochitest/test_capture.html
blob: 1de9a2c0b130d39d1d157c8599abbcdc9e580a89 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
<!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>