2 Copyright (c) 2022 The Khronos Group Inc.
3 Use of this source code is governed by an MIT-style license that can be
4 found in the LICENSE.txt file.
10 <title>Upload texture from video into srgb internalformats
</title>
11 <link rel=
"stylesheet" href=
"../../../resources/js-test-style.css"/>
12 <script src=
"../../../js/js-test-pre.js"></script>
13 <script src=
"../../../js/webgl-test-utils.js"></script>
16 <div id=
"description"></div>
17 <div id=
"console"></div>
20 <canvas id=
"e_rgba" width=
"300" height=
"200"></canvas>
21 0x7f:
<canvas id=
"e_rgba_color" width=
"30" height=
"200"></canvas>
27 <canvas id=
"e_srgb8" width=
"300" height=
"200"></canvas>
28 0x7f:
<canvas id=
"e_srgb8_color" width=
"30" height=
"200"></canvas>
34 <canvas id=
"e_srgb8_alpha8" width=
"300" height=
"200"></canvas>
35 0x7f:
<canvas id=
"e_srgb8_alpha8_color" width=
"30" height=
"200"></canvas>
36 <div>GL.SRGB8_ALPHA8
</div>
40 const wtu
= WebGLTestUtils
;
43 const DATA_URL_FOR_720p_png_bt709_bt709_tv_yuv420p_vp9_webm
= '\
44 data:video/webm;base64,GkXfo59ChoEBQveBAULygQRC84EIQoKEd2VibUKHgQJChYECGFOAZwEA\
45 AAAAAAMBEU2bdLpNu4tTq4QVSalmU6yBoU27i1OrhBZUrmtTrIHGTbuMU6uEElTDZ1OsggElTbuMU6u\
46 EHFO7a1OsggLr7AEAAAAAAABZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
47 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmoCrXsYMPQ\
48 kBNgIRMYXZmV0GETGF2ZkSJiEBEAAAAAAAAFlSua9quAQAAAAAAAFHXgQFzxYgAAAAAAAAAAZyBACK1\
49 nIN1bmSGhVZfVlA5g4EBI+ODhAJiWgDgAQAAAAAAAB6wggUAuoIC0JqBAlWwkFW6gQFVsYEBVbuBAVW\
50 5gQESVMNn43NzAQAAAAAAAFljwItjxYgAAAAAAAAAAWfIAQAAAAAAABxFo4dFTkNPREVSRIePTGF2Yy\
51 BsaWJ2cHgtdnA5Z8iiRaOIRFVSQVRJT05Eh5QwMDowMDowMC4wNDAwMDAwMDAAAB9DtnVBWOeBAKNBU\
52 oEAAICCSYNCQE/wLPYAOCQcGAAYAFB/N9H/HZUjnnscu9GvIJt3936AAAAAACh4E4g/fJ8GmILlgmQ6\
53 iUMwWlrCvdZpJAjY24ONeWCZEIrug5k4YTeAAAAAaXgTiD98nwaYguWCZDq6Zy9PLtRqFgTRRWpDzEC\
54 RrKr8wtgzCibnQJwWtOOaHH9ZRjl4+aOQHHoHk/YUdplRSYiwuJO6LIyUXumq92uzm/wLAqBN0N9kRR\
55 evcxyTv6VcsFqLJ5W5INE4AAAAAGN4E3vgaWsaGceNeWlTmlA/W7BnrSNUEx9X/o/hlK8PPDCgN5Kpw\
56 0gRJkKtiMQMtYO7DQAUWLnf3+GjIUUj4hiAGdY+FNLJIdswhZLCeSDQfqV1btKL/ns57OfXQc0R3HFz\
57 YyB4E3vgaWsaGceNeWjppQzBaWtIcWVNbYO5ARh7kHkq6WBosnlbkfoAHFO7a5G7j7OBALeK94EB8YI\
60 function invoke(fn
) { return fn(); }
63 const video
= document
.createElement("video");
64 video
.src
= DATA_URL_FOR_720p_png_bt709_bt709_tv_yuv420p_vp9_webm
;
65 if (!video
.canPlayType('video/webm')) {
66 debug('Browser can not play webm videos. Skipping test.');
73 video
.crossOrigin
= "anonymous";
77 debug('Browser could not play this specific video. Skipping test.');
82 function renderTex(canvas
, fn_tex_image
) {
83 const gl
= canvas
.gl
= wtu
.create3DContext(canvas
);
86 attribute float a_VertexID;
89 float id = a_VertexID;
90 v_uv.x = mod(id, 2.0);
93 v_uv.y = mod(id, 2.0);
94 gl_Position = vec4(2.0 * v_uv - 1.0, 0, 1);
98 precision mediump float;
99 uniform sampler2D tex;
102 gl_FragColor = texture2D(tex, v_uv);
105 const program
= gl
.createProgram();
106 let shader
= gl
.createShader(gl
.VERTEX_SHADER
);
107 gl
.shaderSource(shader
, vs
);
108 gl
.compileShader(shader
);
109 gl
.attachShader(program
, shader
);
110 shader
= gl
.createShader(gl
.FRAGMENT_SHADER
);
111 gl
.shaderSource(shader
, fs
);
112 gl
.compileShader(shader
);
113 gl
.attachShader(program
, shader
);
114 gl
.bindAttribLocation(program
, 0, 'a_VertexID');
115 gl
.linkProgram(program
);
116 gl
.useProgram(program
);
117 if (gl
.getError()) throw 'Error during linking';
119 const vbuf
= gl
.createBuffer();
120 gl
.bindBuffer(gl
.ARRAY_BUFFER
, vbuf
);
121 gl
.bufferData(gl
.ARRAY_BUFFER
, new Float32Array([0,1,2,3]), gl
.STATIC_DRAW
);
122 gl
.enableVertexAttribArray(0);
123 gl
.vertexAttribPointer(0, 1, gl
.FLOAT
, false, 0, 0);
125 const texture
= gl
.createTexture();
126 gl
.bindTexture(gl
.TEXTURE_2D
, texture
);
127 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_WRAP_S
, gl
.CLAMP_TO_EDGE
);
128 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_WRAP_T
, gl
.CLAMP_TO_EDGE
);
129 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_MIN_FILTER
, gl
.LINEAR
);
131 const draw = function() {
132 //requestAnimationFrame(draw);
134 gl
.drawArrays(gl
.TRIANGLE_STRIP
, 0, 4);
138 if (gl
.getError()) throw 'Error during drawing';
141 const GL
= WebGL2RenderingContext
;
142 const COLOR_DATA
= new Uint8Array([127, 127, 127, 255]);
144 function internalformat_webgl1or2(gl
, internalformat_name
) {
145 let internalformat
= gl
[internalformat_name
];
146 if (!internalformat
) {
147 const ext
= gl
.getExtension('EXT_srgb');
149 testPassed('EXT_srgb not supported. (ok!)');
152 switch (internalformat_name
) {
154 internalformat
= ext
.SRGB_EXT
;
157 internalformat
= ext
.SRGB_ALPHA_EXT
;
160 throw internalformat_name
;
163 return internalformat
;
166 function begin(e_video
, e_color
, internalformat_name
, unpackformat
) {
167 renderTex(e_video
, gl
=> {
168 const internalformat
= internalformat_webgl1or2(gl
, internalformat_name
);
170 unpackformat
= internalformat
; // Must match in webgl1.
172 gl
.texImage2D(GL
.TEXTURE_2D
, 0, internalformat
,
173 unpackformat
, GL
.UNSIGNED_BYTE
, video
);
175 renderTex(e_color
, gl
=> {
176 const internalformat
= internalformat_webgl1or2(gl
, internalformat_name
);
178 unpackformat
= internalformat
; // Must match in webgl1.
180 gl
.texImage2D(GL
.TEXTURE_2D
, 0, internalformat
, 1, 1, 0,
181 unpackformat
, GL
.UNSIGNED_BYTE
, COLOR_DATA
);
185 begin(e_rgba
, e_rgba_color
, 'RGBA', GL
.RGBA
);
186 begin(e_srgb8
, e_srgb8_color
, 'SRGB8', GL
.RGB
);
187 begin(e_srgb8_alpha8
, e_srgb8_alpha8_color
, 'SRGB8_ALPHA8', GL
.RGBA
);
191 const GREY50_COLOR_COORD
= {
195 const GREY50_TEX_COORD
= {
196 x
: e_rgba
.width
/2 + 1,
197 y
: e_rgba
.height
/2 + 1,
199 const fn_test
= (canvas
, coord
, data
) => {
200 wtu
.checkCanvasRect(canvas
.gl
, coord
.x
, coord
.y
, 1, 1, data
,
201 `${canvas.id} @${JSON.stringify(coord)}`);
206 fn_test(e_rgba_color
, GREY50_COLOR_COORD
, [0x7f, 0x7f, 0x7f, 0xff]);
207 fn_test(e_rgba
, GREY50_TEX_COORD
, [0x7f, 0x7f, 0x7f, 0xff]);
211 fn_test(e_srgb8_color
, GREY50_COLOR_COORD
, [0x36, 0x36, 0x36, 0xff]);
212 fn_test(e_srgb8
, GREY50_TEX_COORD
, [0x36, 0x36, 0x36, 0xff]);
215 debug('e_srgb8_alpha8');
216 fn_test(e_srgb8_alpha8_color
, GREY50_COLOR_COORD
, [0x36, 0x36, 0x36, 0xff]);
217 fn_test(e_srgb8_alpha8
, GREY50_TEX_COORD
, [0x36, 0x36, 0x36, 0xff]);
223 async function blobToDataURL(blob) {
224 const fr = new FileReader();
225 return await new Promise((yes, no) => {
226 fr.addEventListener('loadend', ev => {
228 return yes(fr.result);
232 fr.readAsDataURL(blob);
236 async function fetchDataUrl(url, wrapAt) {
237 const r = await fetch(url);
238 const b = await r.blob();
239 const durl = await blobToDataURL(b);
243 function wrapLines(str, wrapAt) {
247 lines.push(remaining.slice(0, wrapAt));
248 remaining = remaining.slice(wrapAt);
254 const url = '720p.png.bt709.bt709.tv.yuv420p.vp9.webm';
255 const ident = 'DATA_URL_FOR_' + url.replaceAll('.', '_');
256 const durl = await fetchDataUrl(url);
257 const lines = wrapLines(durl, 79);
258 console.log(ident, '= \'\\\n' + lines.join('\\\n') + '\';');