tor-browser

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

webgl-specific-stencil-settings.html (11177B)


      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 <title>WebGL stencil mask/func front-state-back-state equality 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 <div id="description"></div>
     18 <div id="console"></div>
     19 
     20 <script>
     21 "use strict";
     22 var wtu = WebGLTestUtils;
     23 description("Tests that stencil mask/func are validated correctly when the front state and back state differ.");
     24 
     25 var gl;
     26 
     27 function checkDrawError(errIfMismatch) {
     28    wtu.shouldGenerateGLError(gl, errIfMismatch, "wtu.dummySetProgramAndDrawNothing(gl)");
     29 }
     30 
     31 function setStencilMask(mask) {
     32    wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilMaskSeparate(gl.FRONT, " + mask[0] + ")");
     33    wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilMaskSeparate(gl.BACK,  " + mask[1] + ")");
     34 }
     35 
     36 function testStencilMaskCase(mask, error) {
     37    setStencilMask(mask);
     38    // If an error is generated, it should be at draw time.
     39    checkDrawError(error);
     40 }
     41 
     42 function testStencilMask(errIfMismatch) {
     43    testStencilMaskCase([0, 256], gl.NO_ERROR);
     44    testStencilMaskCase([1, 256], errIfMismatch);
     45    testStencilMaskCase([1, 257], gl.NO_ERROR);
     46    testStencilMaskCase([1, 258], errIfMismatch);
     47    wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilMask(1023)", "resetting stencilMask");
     48 }
     49 
     50 function setStencilFunc(ref, mask) {
     51    wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilFuncSeparate(gl.FRONT, gl.ALWAYS, " + ref[0] + ", " + mask[0] + ")");
     52    wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilFuncSeparate(gl.BACK,  gl.ALWAYS, " + ref[1] + ", " + mask[1] + ")");
     53 }
     54 
     55 function testStencilFuncCase(ref, mask, error) {
     56    setStencilFunc(ref, mask);
     57    // If an error is generated, it should be at draw time.
     58    checkDrawError(error);
     59 }
     60 
     61 function testStencilFunc(errIfMismatch) {
     62    testStencilFuncCase([ 256,  257], [1023, 1023], gl.NO_ERROR);
     63    testStencilFuncCase([ 256,  254], [1023, 1023], errIfMismatch);
     64 
     65    testStencilFuncCase([  -1,    0], [1023, 1023], gl.NO_ERROR);
     66    testStencilFuncCase([  -1,  254], [1023, 1023], errIfMismatch);
     67 
     68    testStencilFuncCase([   0,    0], [   1,  257], gl.NO_ERROR);
     69    testStencilFuncCase([   0,    0], [   1,  258], errIfMismatch);
     70 
     71    testStencilFuncCase([   1,    1], [1024, 2048], gl.NO_ERROR);
     72    testStencilFuncCase([   1,    1], [2048, 1024], gl.NO_ERROR);
     73 
     74    testStencilFuncCase([  -1,   -1], [1023, 1023], gl.NO_ERROR);
     75    testStencilFuncCase([  -1,    0], [1023, 1023], gl.NO_ERROR);
     76    testStencilFuncCase([   0,   -1], [1023, 1023], gl.NO_ERROR);
     77    testStencilFuncCase([   0,    0], [1023, 1023], gl.NO_ERROR);
     78 
     79    testStencilFuncCase([  -1,  255], [1023, 1023], errIfMismatch);
     80    testStencilFuncCase([   0,  256], [1023, 1023], errIfMismatch);
     81    testStencilFuncCase([   0, 1024], [1023, 1023], errIfMismatch);
     82    testStencilFuncCase([   1,  257], [1023, 1023], errIfMismatch);
     83    testStencilFuncCase([ 255,   -1], [1023, 1023], errIfMismatch);
     84    testStencilFuncCase([ 256,    0], [1023, 1023], errIfMismatch);
     85    testStencilFuncCase([1024,    0], [1023, 1023], errIfMismatch);
     86    testStencilFuncCase([ 257,    1], [1023, 1023], errIfMismatch);
     87 
     88    wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.stencilFunc(gl.ALWAYS, 0, 1023)", "resetting stencilFunc");
     89 }
     90 
     91 //
     92 // Tests of the default framebuffer
     93 //
     94 
     95 debug("");
     96 
     97 debug("Testing default framebuffer with { stencil: true }");
     98 gl = wtu.create3DContext(undefined, { stencil: true });
     99 {
    100    gl.enable(gl.STENCIL_TEST);
    101    testStencilMaskCase([1, 256], gl.INVALID_OPERATION);
    102    testStencilFuncCase([256, 0], [1023, 1023], gl.INVALID_OPERATION);
    103 }
    104 
    105 debug("Testing default framebuffer with { stencil: false }");
    106 gl = wtu.create3DContext(undefined, { stencil: false });
    107 {
    108    // with { stencil: false }
    109    gl.enable(gl.STENCIL_TEST);
    110    testStencilMaskCase([1, 256], gl.NO_ERROR);
    111    testStencilFuncCase([256, 0], [1023, 1023], gl.NO_ERROR);
    112 }
    113 // (continue using this GL context for the other tests)
    114 
    115 //
    116 // Tests with a framebuffer object
    117 //
    118 
    119 const fb = gl.createFramebuffer();
    120 gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
    121 const colorRB = gl.createRenderbuffer();
    122 gl.bindRenderbuffer(gl.RENDERBUFFER, colorRB);
    123 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 1, 1);
    124 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRB);
    125 
    126 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "initial framebuffer setup")
    127 
    128 function runWithStencilSettings(haveDepthBuffer, haveStencilBuffer, enableStencilTest, fn) {
    129    let rbo = null;
    130    let attachment;
    131    if (haveDepthBuffer || haveStencilBuffer) {
    132        rbo = gl.createRenderbuffer();
    133        gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
    134 
    135        let internalformat;
    136        if (haveDepthBuffer && haveStencilBuffer) {
    137            internalformat = gl.DEPTH_STENCIL;
    138            attachment = gl.DEPTH_STENCIL_ATTACHMENT;
    139        } else if (haveDepthBuffer) {
    140            internalformat = gl.DEPTH_COMPONENT16;
    141            attachment = gl.DEPTH_ATTACHMENT;
    142        } else if (haveStencilBuffer) {
    143            internalformat = gl.STENCIL_INDEX8;
    144            attachment = gl.STENCIL_ATTACHMENT;
    145        }
    146        gl.renderbufferStorage(gl.RENDERBUFFER, internalformat, 1, 1);
    147        gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, rbo);
    148    }
    149    shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
    150    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "depth/stencil renderbuffer setup")
    151 
    152    if (enableStencilTest) {
    153        gl.enable(gl.STENCIL_TEST);
    154    } else {
    155        gl.disable(gl.STENCIL_TEST);
    156    }
    157 
    158    fn();
    159 
    160    if (rbo) {
    161        gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, null);
    162        gl.bindRenderbuffer(gl.RENDERBUFFER, null);
    163        gl.deleteRenderbuffer(rbo);
    164    }
    165 
    166    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "depth/stencil renderbuffer cleanup")
    167 }
    168 
    169 function testStencilSettings(haveDepthBuffer, haveStencilBuffer, enableStencilTest, errIfMismatch) {
    170    debug("");
    171    debug("With depthbuffer=" + haveDepthBuffer +
    172            ", stencilbuffer=" + haveStencilBuffer +
    173            ", stencilTest=" + enableStencilTest +
    174            ", expecting error=" + wtu.glEnumToString(gl, errIfMismatch) +
    175            " for mismatching mask or func settings.");
    176 
    177    runWithStencilSettings(haveDepthBuffer, haveStencilBuffer, enableStencilTest, () => {
    178        // Errors should be the same for both mask and func, because stencil test
    179        // and stencil write are always enabled/disabled in tandem.
    180        testStencilMask(errIfMismatch);
    181        testStencilFunc(errIfMismatch);
    182    });
    183 }
    184 
    185 debug("");
    186 debug("Base case checks:");
    187 testStencilMaskCase([0, 0], gl.NO_ERROR);
    188 testStencilFuncCase([0, 0], [1023, 1023], gl.NO_ERROR);
    189 
    190 //                  haveDepthBuffer
    191 //                  |      haveStencilBuffer
    192 //                  |      |      enableStencilTest
    193 //                  |      |      |      errIfMismatch
    194 testStencilSettings(false, false, false, gl.NO_ERROR);
    195 testStencilSettings( true, false, false, gl.NO_ERROR);
    196 testStencilSettings(false,  true, false, gl.NO_ERROR);
    197 testStencilSettings( true,  true, false, gl.NO_ERROR);
    198 
    199 testStencilSettings(false, false,  true, gl.NO_ERROR);
    200 testStencilSettings( true, false,  true, gl.NO_ERROR);
    201 testStencilSettings(false,  true,  true, gl.INVALID_OPERATION);
    202 testStencilSettings( true,  true,  true, gl.INVALID_OPERATION);
    203 
    204 //
    205 // Tests to make sure the stencil validation check, if cached, is invalidated correctly.
    206 //
    207 
    208 debug("");
    209 
    210 debug("Setup for stencil validation cache invalidation tests");
    211 setStencilMask([1, 258]);
    212 setStencilFunc([0, 256], [1023, 1023]);
    213 
    214 debug("Test with enabling/disabling stencil test");
    215 runWithStencilSettings(false, true, false, () => {
    216    checkDrawError(gl.NO_ERROR);
    217    gl.enable(gl.STENCIL_TEST);
    218    checkDrawError(gl.INVALID_OPERATION);
    219    gl.disable(gl.STENCIL_TEST);
    220    checkDrawError(gl.NO_ERROR);
    221 });
    222 
    223 debug("Test with swapping in a new FBO");
    224 runWithStencilSettings(false, false, true, () => {
    225    // no error with no stencil buffer
    226    checkDrawError(gl.NO_ERROR);
    227 
    228    // swap in a new FBO with a stencil buffer
    229    const fb2 = gl.createFramebuffer();
    230    gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
    231    gl.bindRenderbuffer(gl.RENDERBUFFER, colorRB);
    232    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorRB);
    233    const rbo = gl.createRenderbuffer();
    234    gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
    235    gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, 1, 1);
    236    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo);
    237    shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
    238    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    239 
    240    // this draw sholud detect the new fbo state
    241    checkDrawError(gl.INVALID_OPERATION);
    242 
    243    gl.deleteFramebuffer(fb2);
    244    gl.deleteRenderbuffer(rbo)
    245    gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
    246    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    247 });
    248 
    249 debug("Test with adding a stencil attachment");
    250 runWithStencilSettings(false, false, true, () => {
    251    // no error with no stencil buffer
    252    checkDrawError(gl.NO_ERROR);
    253 
    254    // add a stencil attachment
    255    const rbo = gl.createRenderbuffer();
    256    gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
    257    gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, 1, 1);
    258    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo);
    259    shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
    260    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    261 
    262    // this draw sholud detect the new fbo state
    263    checkDrawError(gl.INVALID_OPERATION);
    264 
    265    gl.deleteRenderbuffer(rbo)
    266    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    267 });
    268 
    269 debug("Test with reallocating the DEPTH_STENCIL attachment from depth to depth+stencil");
    270 runWithStencilSettings(false, false, true, () => {
    271    // attach a depth buffer to the DEPTH_STENCIL attachment
    272    const rbo = gl.createRenderbuffer();
    273    gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
    274    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 1, 1);
    275    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo);
    276    shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
    277    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    278 
    279    // this draw is invalid, but it still might trigger caching of the stencil validation
    280    checkDrawError(gl.INVALID_FRAMEBUFFER_OPERATION);
    281 
    282    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, 1, 1);
    283    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    284    // this draw sholud detect the new fbo state
    285    checkDrawError(gl.INVALID_OPERATION);
    286 
    287    gl.deleteRenderbuffer(rbo)
    288    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    289 });
    290 
    291 gl.deleteFramebuffer(fb);
    292 gl.deleteRenderbuffer(colorRB);
    293 
    294 var successfullyParsed = true;
    295 </script>
    296 
    297 <script src="../../js/js-test-post.js"></script>
    298 </body>
    299 </html>