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
content / test / data / gpu / pixel_offscreenCanvas_webgl_commit_worker.html [blame]
<!DOCTYPE HTML>
<html>
<head>
<title>OffscreenCanvas webgl flow on worker thread: Two Canvases</title>
<style type="text/css">
.nomargin {
margin: 0px auto;
}
</style>
<script id="myWorker" type="text/worker">
/* This pixel test checks the following:
1. Whether submission of frames for multiple canvases happen about the same
time for OffscreenCanvas that are invoked in the same JS task.
2. Whether overdraw frame in one animation loop is handled well.
3. Whether the drawn webgl image is position upright.
Correct end result of this test: The left canvas shows a upright white
triangle on a green background and the right canvas shows dark-blue fill.
*/
var g_ctx1, g_ctx2;
var g_asyncCallbackNumber = 2;
self.onmessage = function(e) {
g_ctx1 = e.data.offscreenCanvas1.getContext("webgl");
g_ctx2 = e.data.offscreenCanvas2.getContext("webgl");
startTest();
}
function startTest() {
g_ctx1.clearColor(0, 1, 0, 1);
g_ctx1.clear(g_ctx1.COLOR_BUFFER_BIT);
requestAnimationFrame(() => {
g_ctx2.clearColor(0, 0, 1, 1);
g_ctx2.clear(g_ctx2.COLOR_BUFFER_BIT);
if (--g_asyncCallbackNumber == 0) self.postMessage("");
});
function drawTriangle(gl)
{
gl.clearColor(0, 1, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
var prog = gl.createProgram();
var vs = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vs, ['attribute vec2 pos;',
'void main() {',
' gl_Position = vec4(pos, 0., 1.);',
'}'].join('\n'));
gl.compileShader(vs);
if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {
throw 'failed to compiled shader';
}
gl.attachShader(prog, vs);
var fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fs, ['void main() {',
' gl_FragColor = vec4(1.);',
'}'].join('\n'));
gl.compileShader(fs);
if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {
throw 'failed to compiled shader';
}
gl.attachShader(prog, fs);
gl.linkProgram(prog);
if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) {
throw "Could not link the shader program!";
}
gl.useProgram(prog);
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-.5,0, 0,.5, .5,0]), gl.STATIC_DRAW);
var attr = gl.getAttribLocation(prog, 'pos');
gl.enableVertexAttribArray(attr);
gl.vertexAttribPointer(attr, 2, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3);
}
// Do something complex to g_ctx2.
drawTriangle(g_ctx2);
// This g_ctx2 must be resolved at about the same time as the first
// g_ctx1 above because they are in the same JS task, no matter how
// complex the drawing operation is.
requestAnimationFrame(() => {
drawTriangle(g_ctx1);
if (--g_asyncCallbackNumber == 0) {
self.postMessage("");
}
});
}
</script>
<script>
var g_swapsBeforeAck = 15;
function makeWorker(script) {
var blob = new Blob([script]);
return new Worker(URL.createObjectURL(blob));
}
function waitForFinish()
{
if (g_swapsBeforeAck == 0) {
domAutomationController.send("SUCCESS");
} else {
g_swapsBeforeAck--;
document.getElementById('container').style.zIndex = g_swapsBeforeAck + 1;
window.requestAnimationFrame(waitForFinish);
}
}
function main()
{
var offscreenCanvas1 = document.getElementById("canvas1").transferControlToOffscreen();
var offscreenCanvas2 = document.getElementById("canvas2").transferControlToOffscreen();
var worker = makeWorker(document.getElementById("myWorker").textContent);
worker.onmessage = function (e) {
waitForFinish();
};
worker.postMessage(
{offscreenCanvas1: offscreenCanvas1,
offscreenCanvas2: offscreenCanvas2},
[offscreenCanvas1, offscreenCanvas2]);
}
</script>
</head>
<body onload="main()">
<div style="position:relative; width:360px; height:200px; background-color:white">
</div>
<div id="container" style="position:absolute; top:0px; left:0px">
<canvas id="canvas1" width="180" height="200" class="nomargin"></canvas>
<canvas id="canvas2" width="180" height="200" class="nomargin"></canvas>
</div>
</body>
</html>