tor-browser

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

blending.html (8308B)


      1 <!--
      2 Copyright (c) 2019 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 
      7 <!DOCTYPE html>
      8 <html>
      9 <head>
     10 <meta charset="utf-8">
     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 
     15 <script id="eVsSrc" type="text/plain">
     16 void main()
     17 {
     18    gl_PointSize = 1.0;
     19    gl_Position = vec4(0, 0, 0, 1);
     20 }
     21 </script>
     22 
     23 <script id="eFsSrc" type="text/plain">
     24 precision mediump float;
     25 uniform vec4 uColor;
     26 
     27 void main()
     28 {
     29    gl_FragColor = uColor;
     30 }
     31 </script>
     32 
     33 </head>
     34 <body>
     35 <div id="description"></div>
     36 <div id="console"></div>
     37 <script>
     38 "use strict";
     39 description('Blending tests');
     40 
     41 const wtu = WebGLTestUtils;
     42 
     43 function CreateContext() {
     44    const gl = wtu.create3DContext();
     45    gl.viewport(0, 0, 1, 1);
     46 
     47    gl.prog = wtu.setupProgram(gl, [eVsSrc.innerHTML, eFsSrc.innerHTML]);
     48    gl.prog.uColor = (() => {
     49        const loc = gl.getUniformLocation(gl.prog, 'uColor');
     50        return x => gl.uniform4fv(loc, x);
     51    })();
     52    gl.useProgram(gl.prog);
     53    gl.prog.uColor([1 / 255, 2 / 255, 3 / 255, 4 / 255]);
     54 
     55    gl.drawAndRead = type => {
     56        gl.drawArrays(gl.POINTS, 0, 1);
     57        let ret;
     58        if (type == gl.UNSIGNED_BYTE) {
     59            ret = new Uint8Array(4);
     60        } else if (type == gl.FLOAT) {
     61            ret = new Float32Array(4);
     62        }
     63        gl.readPixels(0, 0, 1, 1, gl.RGBA, type, ret);
     64        return ret;
     65    };
     66 
     67    gl.enable(gl.BLEND);
     68    gl.blendFunc(gl.CONSTANT_COLOR, gl.ZERO);
     69 
     70    return gl;
     71 }
     72 
     73 function CreateValidFb(gl, formats) {
     74    const fb = gl.createFramebuffer();
     75    gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
     76 
     77    for (let i in formats) {
     78        i = i|0; // Otherwise i is a string. :(
     79        const f = formats[i];
     80        if (!f)
     81            continue;
     82        if (f.length == 1) {
     83            const rb = gl.createRenderbuffer();
     84            gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
     85            gl.renderbufferStorage(gl.RENDERBUFFER, f[0], 1, 1);
     86            gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0+i,
     87                                       gl.RENDERBUFFER, rb);
     88            continue;
     89        }
     90        if (f.length == 3) {
     91            let internalFormat = f[0];
     92            if (internalFormat === undefined) {
     93                internalFormat = f[1];
     94            }
     95 
     96            const tex = gl.createTexture();
     97            gl.bindTexture(gl.TEXTURE_2D, tex);
     98            gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 1,1,0, f[1],f[2], null);
     99            gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0+i,
    100                                    gl.TEXTURE_2D, tex, 0);
    101            continue;
    102        }
    103        throw new Error('Invalid format length: ' + f);
    104    }
    105 
    106    const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
    107    if (status != gl.FRAMEBUFFER_COMPLETE) {
    108        gl.deleteFramebuffer(fb);
    109        return null;
    110    }
    111    return fb;
    112 }
    113 
    114 let was, fb;
    115 
    116 const TESTS = [
    117    () => {
    118        debug('');
    119        debug('Clamping of blendColor args:');
    120 
    121        const gl = wtu.create3DContext();
    122        if (!gl.texImage3D) { // WebGL 1.0
    123            // WebGL 1.0 clamps without EXT_color_buffer_half_float or WEBGL_color_buffer_float.
    124            gl.blendColor(1000, 1, 1, 1);
    125            const was = gl.getParameter(gl.BLEND_COLOR);
    126            expectArray(was, [1, 1, 1, 1]);
    127 
    128            const ext = gl.getExtension('EXT_color_buffer_half_float') ||
    129                        gl.getExtension('WEBGL_color_buffer_float');
    130            if (!ext) return;
    131        }
    132 
    133        // WebGL 2.0 or extended WebGL 1.0 may still clamp the value on store
    134        // when the underlying platform does the same.
    135        gl.blendColor(1000, 1, 1, 1);
    136        const was = gl.getParameter(gl.BLEND_COLOR);
    137        if (was[0] == 1000) {
    138            expectArray(was, [1000, 1, 1, 1]);
    139        } else {
    140            debug("Platform does not support unclamped blend color.")
    141            expectArray(was, [1, 1, 1, 1]);
    142        }
    143    },
    144    () => {
    145        debug('');
    146        debug('Blending for RGBA8:');
    147 
    148        const gl = CreateContext();
    149        fb = CreateValidFb(gl, [[gl.RGBA8, gl.RGBA, gl.UNSIGNED_BYTE]]);
    150        shouldBeNonNull('fb');
    151 
    152        // Regardless of the context version and enabled extensions,
    153        // the value will be clamped at draw time,
    154        gl.blendColor(10, 1, 1, 1);
    155        const was = gl.drawAndRead(gl.UNSIGNED_BYTE);
    156        expectArray(was, [1, 2, 3, 4]);
    157 
    158        if (gl.getExtension('EXT_color_buffer_half_float') ||
    159            gl.getExtension('WEBGL_color_buffer_float') ||
    160            gl.getExtension('EXT_color_buffer_float'))
    161        {
    162            debug('Enable floating-point color buffers and retest');
    163            gl.blendColor(1000, 1, 1, 1);
    164            const was = gl.drawAndRead(gl.UNSIGNED_BYTE);
    165            expectArray(was, [1, 2, 3, 4]);
    166        }
    167    },
    168    () => {
    169        debug('');
    170        debug('Blending for RGBA16F:');
    171 
    172        const gl = CreateContext();
    173 
    174        // Set the value before enabling the extension.
    175        // It must be clamped only on WebGL 1.0 contexts.
    176        gl.blendColor(10, 1, 1, 1);
    177        if (!gl.getExtension('EXT_color_buffer_half_float')) {
    178            testPassed('Missing ext EXT_color_buffer_half_float is optional, skipping.');
    179            return;
    180        }
    181        if (!gl.texImage3D) { // WebGL 1.0
    182            const ext = gl.getExtension('OES_texture_half_float');
    183            gl.HALF_FLOAT = ext.HALF_FLOAT_OES; // These aren't the same value, but this'll work.
    184        }
    185 
    186        fb = CreateValidFb(gl, [[gl.RGBA16F, gl.RGBA, gl.HALF_FLOAT]]);
    187        shouldBeNonNull('fb');
    188        gl.prog.uColor([1, 2, 3, 4]);
    189 
    190        let was = gl.drawAndRead(gl.FLOAT);
    191        if (!gl.texImage3D) { // WebGL 1.0
    192            expectArray(was, [1, 2, 3, 4]);
    193        } else {
    194            // Some WebGL 2.0 implementations may clamp the blend color anyway.
    195            const r = gl.getParameter(gl.BLEND_COLOR)[0];
    196            expectArray(was, [r, 2, 3, 4]);
    197        }
    198 
    199        // Re-set the value after the extension was enabled.
    200        gl.blendColor(100, 1, 1, 1);
    201        const r = gl.getParameter(gl.BLEND_COLOR)[0];
    202        was = gl.drawAndRead(gl.FLOAT);
    203        expectArray(was, [r, 2, 3, 4]);
    204    },
    205    () => {
    206        debug('');
    207        debug('Blending for RGBA32F:');
    208 
    209        const gl = CreateContext();
    210 
    211        // Set the value before enabling the extension.
    212        // It must be clamped only on WebGL 1.0 contexts.
    213        gl.blendColor(10, 1, 1, 1);
    214        if (gl.texImage3D) { // WebGL 2.0
    215            if (!gl.getExtension('EXT_color_buffer_float')) {
    216                testPassed('Missing ext EXT_color_buffer_float is optional, skipping.');
    217                return;
    218            }
    219        } else {
    220            if (!gl.getExtension('WEBGL_color_buffer_float')) {
    221                testPassed('Missing ext WEBGL_color_buffer_float is optional, skipping.');
    222                return;
    223            }
    224            gl.getExtension('OES_texture_float');
    225        }
    226        fb = CreateValidFb(gl, [[gl.RGBA32F, gl.RGBA, gl.FLOAT]]);
    227        shouldBeNonNull('fb');
    228        gl.prog.uColor([1, 2, 3, 4]);
    229 
    230        let was = gl.drawAndRead(gl.FLOAT);
    231        if (!gl.texImage3D) { // WebGL 1.0
    232            expectArray(was, [1, 2, 3, 4]);
    233        } else {
    234            // Some WebGL 2.0 implementations may clamp the blend color anyway.
    235            const r = gl.getParameter(gl.BLEND_COLOR)[0];
    236            expectArray(was, [r, 2, 3, 4]);
    237        }
    238 
    239        // Re-set the value after the extension was enabled.
    240        gl.blendColor(100, 1, 1, 1);
    241        const r = gl.getParameter(gl.BLEND_COLOR)[0];
    242        was = gl.drawAndRead(gl.FLOAT);
    243 
    244        if (!gl.getExtension('EXT_float_blend')) {
    245            wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, 'Should not be able to blend 32F formats.');
    246            return;
    247        }
    248        wtu.glErrorShouldBe(gl, 0, 'Should be able to blend 32F formats.');
    249        expectArray(was, [r, 2, 3, 4]);
    250    },
    251 ];
    252 
    253 async function Test() {
    254    for (const fn of TESTS) {
    255        await wtu.dispatchPromise(fn);
    256    }
    257    wtu.destroyAllContexts();
    258    finishTest();
    259 }
    260 
    261 Test();
    262 
    263 var successfullyParsed = true;
    264 </script>
    265 </body>
    266 </html>