tor-browser

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

framebuffer-to-texture.html (7614B)


      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 
      7 <!DOCTYPE html>
      8 <html>
      9 <head>
     10 <meta charset="utf-8">
     11 <title>WebGL framebuffer to texture conformance test.</title>
     12 <link rel="stylesheet" href="../../resources/js-test-style.css"/>
     13 <script src="../../js/js-test-pre.js"></script>
     14 <script src="../../js/webgl-test-utils.js"> </script>
     15 </head>
     16 <body>
     17 <canvas id="canvas"></canvas>
     18 <div id="description"></div>
     19 <div id="console"></div>
     20 <script>
     21 "use strict";
     22 description("Test resolving and copying the framebuffer to a texture, and drawing the result.");
     23 debug('Reduced test case for <a href="http://anglebug.com/6972">http://anglebug.com/6972</a>');
     24 
     25 // Reproduces two behaviors:
     26 //
     27 // 1) The initial draw disappearing entirely from the default back
     28 // buffer. The current test case does not show this behavior
     29 // independently from the other, but a previous iteration, with the
     30 // textured quad scaled to half size and translated (-0.5, -0.5), did.
     31 //
     32 // 2) With Metal debug layers and load/store validation turned on on
     33 // Intel Macs, the transparent area of the texture prior to the bug
     34 // fix was magenta = undefined. Similar behavior would presumably
     35 // reproduce on M1 hardware without debug layers or validation.
     36 
     37 const size = 64;
     38 const halfSize = size / 2;
     39 const green = [ 0, 255, 0, 255 ];
     40 const transparent = [ 0, 0, 0, 0 ];
     41 
     42 let wtu = WebGLTestUtils;
     43 let canvas = document.getElementById("canvas");
     44 canvas.width = size;
     45 canvas.height = size;
     46 
     47 let gl = wtu.create3DContext("canvas", {
     48    // Antialiasing is crucial for reproducing the bug.
     49    antialias: true,
     50    // Depth testing is not.
     51    depth: false,
     52 }, 2);
     53 
     54 function allocateTexture(sz) {
     55    let texture = gl.createTexture();
     56    gl.bindTexture(gl.TEXTURE_2D, texture);
     57    gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, sz, sz);
     58    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
     59    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
     60    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
     61    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
     62    gl.bindTexture(gl.TEXTURE_2D, null);
     63    return texture;
     64 }
     65 
     66 // Allocate destination texture
     67 let destTexture = allocateTexture(halfSize);
     68 
     69 // Set up half-size solid color quad in center
     70 let colorQuadVAO = gl.createVertexArray();
     71 gl.bindVertexArray(colorQuadVAO);
     72 let colorQuadProgram = wtu.setupColorQuad(gl, 0, { scale: 0.5 });
     73 
     74 // Setup textured quad covering the entire renderable area
     75 let quadVAO = gl.createVertexArray();
     76 gl.bindVertexArray(quadVAO);
     77 let quadProgram = wtu.setupTexturedQuad(gl, 0, 1);
     78 gl.useProgram(quadProgram);
     79 let quadTexLoc = gl.getUniformLocation(quadProgram, "tex");
     80 gl.uniform1i(quadTexLoc, 0);
     81 
     82 gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
     83 gl.activeTexture(gl.TEXTURE0); // To match quadTexLoc=0
     84 
     85 function runTest() {
     86    gl.clearColor(0, 0, 0, 0);
     87    gl.clear(gl.COLOR_BUFFER_BIT);
     88    gl.disable(gl.BLEND);
     89    gl.bindVertexArray(colorQuadVAO);
     90    gl.useProgram(colorQuadProgram);
     91    wtu.drawUByteColorQuad(gl, [ 0, 255, 0, 255 ]);
     92 
     93    gl.bindTexture(gl.TEXTURE_2D, destTexture);
     94    // Copy the upper right corner of the framebuffer to the texture.
     95    gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, halfSize, halfSize, halfSize, halfSize);
     96    gl.bindTexture(gl.TEXTURE_2D, null);
     97    gl.useProgram(quadProgram);
     98    gl.enable(gl.BLEND);
     99    gl.bindVertexArray(quadVAO);
    100    gl.bindTexture(gl.TEXTURE_2D, destTexture);
    101    // Magnify and blend this texture over the current framebuffer.
    102    wtu.drawUnitQuad(gl);
    103 }
    104 
    105 function runUserDefinedFBOTest() {
    106    let fbo1 = gl.createFramebuffer();
    107    let fbo2 = gl.createFramebuffer();
    108    let rb = gl.createRenderbuffer();
    109    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo1);
    110    gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
    111    gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA8, size, size);
    112    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
    113    wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, [ gl.FRAMEBUFFER_COMPLETE ]);
    114 
    115    let tex = allocateTexture(size, size);
    116    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2);
    117    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
    118    wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, [ gl.FRAMEBUFFER_COMPLETE ]);
    119 
    120    // Same rendering steps as in the default-framebuffer test, with appropriate framebuffer blits interspersed.
    121    gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo1);
    122    gl.clearColor(0, 0, 0, 0);
    123    gl.clear(gl.COLOR_BUFFER_BIT);
    124    gl.disable(gl.BLEND);
    125    gl.bindVertexArray(colorQuadVAO);
    126    gl.useProgram(colorQuadProgram);
    127    wtu.drawUByteColorQuad(gl, [ 0, 255, 0, 255 ]);
    128 
    129    gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo1);
    130    gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo2);
    131    gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST);
    132    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2);
    133 
    134    gl.bindTexture(gl.TEXTURE_2D, destTexture);
    135    // Copy the upper right corner of the framebuffer to the texture.
    136    gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, halfSize, halfSize, halfSize, halfSize);
    137    gl.bindTexture(gl.TEXTURE_2D, null);
    138 
    139    gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo1);
    140 
    141    gl.useProgram(quadProgram);
    142    gl.enable(gl.BLEND);
    143    gl.bindVertexArray(quadVAO);
    144    gl.bindTexture(gl.TEXTURE_2D, destTexture);
    145    // Magnify and blend this texture over the current framebuffer.
    146    wtu.drawUnitQuad(gl);
    147 
    148    gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo1);
    149    gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo2);
    150    gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST);
    151    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2);
    152 
    153    // No longer easy to put these results on the canvas, because it's
    154    // antialiased and we can't blitFramebuffer to it. Let's assume
    155    // that if failures occur, they'll be straightforward to debug.
    156 }
    157 
    158 function checkRenderingResults(prefix) {
    159    // Center quad should be rendered correctly.
    160    wtu.checkCanvasRect(gl,
    161                        halfSize / 2 + 1, halfSize / 2 + 1,
    162                        halfSize - 2, halfSize - 2,
    163                        green,
    164                        prefix + ": center quad should be green");
    165 
    166    // Overlapping lower-left quad should be green as well.
    167    wtu.checkCanvasRect(gl,
    168                        1, 1,
    169                        halfSize - 2, halfSize - 2,
    170                        green,
    171                        prefix + ": lower left quad should be green");
    172 
    173    // Leftmost area above the lower-left quad should be transparent.
    174    wtu.checkCanvasRect(gl,
    175                        1, halfSize + 1,
    176                        halfSize / 2 - 2, halfSize / 2 - 2,
    177                        transparent,
    178                        prefix + ": leftmost area above lower left quad should be transparent");
    179 
    180    // Bottommost area to the right of the lower-left quad should be transparent.
    181    wtu.checkCanvasRect(gl,
    182                        halfSize + 1, 1,
    183                        halfSize / 2 - 2, halfSize / 2 - 2,
    184                        transparent,
    185                        prefix + ": bottommost area to the right of lower left quad should be transparent");
    186 }
    187 
    188 runTest();
    189 checkRenderingResults("default back buffer");
    190 
    191 runUserDefinedFBOTest();
    192 checkRenderingResults("user-defined framebuffer");
    193 
    194 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors at the end of the test.");
    195 
    196 finishTest();
    197 
    198 var successfullyParsed = true;
    199 </script>
    200 </body>
    201 </html>