tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

texture-srgb-upload.html (8736B)


      1 <!--
      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.
      5 -->
      6 <!DOCTYPE html>
      7 <html>
      8 <head>
      9 <meta charset=utf-8>
     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>
     14 </head>
     15 <body>
     16    <div id="description"></div>
     17    <div id="console"></div>
     18    <div>
     19        Video:
     20        <canvas id="e_rgba" width="300" height="200"></canvas>
     21        0x7f: <canvas id="e_rgba_color" width="30" height="200"></canvas>
     22        <div>GL.RGBA</div>
     23    </div>
     24    <hr>
     25    <div>
     26        Video:
     27        <canvas id="e_srgb8" width="300" height="200"></canvas>
     28        0x7f: <canvas id="e_srgb8_color" width="30" height="200"></canvas>
     29        <div>GL.SRGB8</div>
     30    </div>
     31    <hr>
     32    <div>
     33        Video:
     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>
     37    </div>
     38 <script>
     39 "use strict";
     40 const wtu = WebGLTestUtils;
     41 description();
     42 
     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\
     58 BjfCBAw==';
     59 
     60 function invoke(fn) { return fn(); }
     61 
     62 invoke(async () => {
     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.');
     67        finishTest();
     68        return;
     69    }
     70 
     71    video.muted = true;
     72    video.loop = true;
     73    video.crossOrigin = "anonymous";
     74    try {
     75        await video.play();
     76    } catch (e) {
     77        debug('Browser could not play this specific video. Skipping test.');
     78        finishTest();
     79        return;
     80    }
     81 
     82    function renderTex(canvas, fn_tex_image) {
     83        const gl = canvas.gl = wtu.create3DContext(canvas);
     84 
     85        const vs = `
     86 attribute float a_VertexID;
     87 varying vec2 v_uv;
     88 void main() {
     89    float id = a_VertexID;
     90    v_uv.x = mod(id, 2.0);
     91    id -= v_uv.x;
     92    id /= 2.0;
     93    v_uv.y = mod(id, 2.0);
     94    gl_Position = vec4(2.0 * v_uv - 1.0, 0, 1);
     95 }`;
     96 
     97        const fs = `
     98 precision mediump float;
     99 uniform sampler2D tex;
    100 varying vec2 v_uv;
    101 void main() {
    102    gl_FragColor = texture2D(tex, v_uv);
    103 }`;
    104 
    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';
    118 
    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);
    124 
    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);
    130 
    131        const draw = function() {
    132            //requestAnimationFrame(draw);
    133            fn_tex_image(gl);
    134            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
    135        };
    136        draw();
    137 
    138        if (gl.getError()) throw 'Error during drawing';
    139    }
    140 
    141    const GL = WebGL2RenderingContext;
    142    const COLOR_DATA = new Uint8Array([127, 127, 127, 255]);
    143 
    144    function internalformat_webgl1or2(gl, internalformat_name) {
    145        let internalformat = gl[internalformat_name];
    146        if (!internalformat) {
    147            const ext = gl.getExtension('EXT_srgb');
    148            if (!ext) {
    149                testPassed('EXT_srgb not supported. (ok!)');
    150                return;
    151            }
    152            switch (internalformat_name) {
    153            case 'SRGB8':
    154                internalformat = ext.SRGB_EXT;
    155                break;
    156            case 'SRGB8_ALPHA8':
    157                internalformat = ext.SRGB_ALPHA_EXT;
    158                break;
    159            default:
    160                throw internalformat_name;
    161            }
    162        }
    163        return internalformat;
    164    }
    165 
    166    function begin(e_video, e_color, internalformat_name, unpackformat) {
    167        renderTex(e_video, gl => {
    168            const internalformat = internalformat_webgl1or2(gl, internalformat_name);
    169            if (!gl.SRGB8) {
    170                unpackformat = internalformat; // Must match in webgl1.
    171            }
    172            gl.texImage2D(GL.TEXTURE_2D, 0, internalformat,
    173                unpackformat, GL.UNSIGNED_BYTE, video);
    174        });
    175        renderTex(e_color, gl => {
    176            const internalformat = internalformat_webgl1or2(gl, internalformat_name);
    177            if (!gl.SRGB8) {
    178                unpackformat = internalformat; // Must match in webgl1.
    179            }
    180            gl.texImage2D(GL.TEXTURE_2D, 0, internalformat, 1, 1, 0,
    181                unpackformat, GL.UNSIGNED_BYTE, COLOR_DATA);
    182        });
    183    }
    184 
    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);
    188 
    189    // -
    190 
    191    const GREY50_COLOR_COORD = {
    192        x: 0,
    193        y: 0,
    194    };
    195    const GREY50_TEX_COORD = {
    196        x: e_rgba.width/2 + 1,
    197        y: e_rgba.height/2 + 1,
    198    };
    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)}`);
    202    }
    203 
    204    debug('');
    205    debug('e_rgba');
    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]);
    208 
    209    debug('');
    210    debug('e_srgb8');
    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]);
    213 
    214    debug('');
    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]);
    218 
    219    finishTest();
    220 });
    221 
    222 /*
    223 async function blobToDataURL(blob) {
    224    const fr = new FileReader();
    225    return await new Promise((yes, no) => {
    226        fr.addEventListener('loadend', ev => {
    227            if (fr.result) {
    228                return yes(fr.result);
    229            }
    230            return no(fr.error);
    231        });
    232        fr.readAsDataURL(blob);
    233    });
    234 }
    235 
    236 async function fetchDataUrl(url, wrapAt) {
    237    const r = await fetch(url);
    238    const b = await r.blob();
    239    const durl = await blobToDataURL(b);
    240    return durl;
    241 }
    242 
    243 function wrapLines(str, wrapAt) {
    244    const lines = [];
    245    let remaining = str;
    246    while (remaining) {
    247        lines.push(remaining.slice(0, wrapAt));
    248        remaining = remaining.slice(wrapAt);
    249    }
    250    return lines;
    251 }
    252 
    253 (async () => {
    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') + '\';');
    259 })();
    260 */
    261 </script>
    262 </body>
    263 </html>