tor-browser

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

context-lost.html (15855B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4 <meta charset="utf-8">
      5 <!--
      6 Copyright (c) 2019 The Khronos Group Inc.
      7 Use of this source code is governed by an MIT-style license that can be
      8 found in the LICENSE.txt file.
      9 -->
     10 <link rel="stylesheet" href="../../resources/js-test-style.css"/>
     11 <script src="../../js/js-test-pre.js"></script>
     12 <script src="../../js/webgl-test-utils.js"></script>
     13 <script>
     14 "use strict";
     15 var wtu;
     16 var canvas;
     17 var gl;
     18 var shouldGenerateGLError;
     19 var extensionName;
     20 var extension;
     21 
     22 var buffer;
     23 var framebuffer;
     24 var program;
     25 var renderbuffer;
     26 var shader;
     27 var texture;
     28 var uniformLocation;
     29 var arrayBuffer;
     30 var arrayBufferView
     31 var image;
     32 var video;
     33 var canvas2d;
     34 var ctx2d;
     35 var imageData;
     36 var float32array;
     37 var int32array;
     38 var OES_vertex_array_object;
     39 var vertexArrayObject;
     40 
     41 var secondCanvas;
     42 var secondGL;
     43 
     44 function init()
     45 {
     46    wtu = WebGLTestUtils;
     47    canvas = document.getElementById("canvas");
     48    gl = wtu.create3DContext(canvas);
     49    secondCanvas = document.getElementById("canvas2");
     50    secondGL = wtu.create3DContext(secondCanvas);
     51    shouldGenerateGLError = wtu.shouldGenerateGLError;
     52 
     53    description("Tests behavior under a lost context");
     54 
     55    // call testValidContext() before checking for the extension, because this is where we check
     56    // for the isContextLost() method, which we want to do regardless of the extension's presence.
     57    testValidContext();
     58 
     59    extensionName = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_lose_context");
     60    if (!extensionName) {
     61        debug("Could not find WEBGL_lose_context extension");
     62        finishTest();
     63        return false;
     64    }
     65    extension = gl.getExtension(extensionName);
     66 
     67    // need an extension that exposes new API methods.
     68    OES_vertex_array_object = wtu.getExtensionWithKnownPrefixes(gl, "OES_vertex_array_object");
     69 
     70    canvas.addEventListener("webglcontextlost", testLostContext, false);
     71 
     72    // We need to initialize |uniformLocation| before losing context.
     73    // Otherwise gl.getUniform() when context is lost will throw.
     74    uniformLocation = gl.getUniformLocation(program, "tex");
     75    loseContext();
     76 }
     77 
     78 function loseContext()
     79 {
     80    debug("");
     81    debug("Lose context");
     82 
     83    // Note: this will cause the context to be lost, but the
     84    // webglcontextlost event listener to be queued.
     85    extension.loseContext();
     86    debug("");
     87 }
     88 
     89 function testValidContext()
     90 {
     91    debug("Test valid context");
     92 
     93    shouldBeFalse("gl.isContextLost()");
     94 
     95    arrayBuffer = new ArrayBuffer(4);
     96    arrayBufferView = new Int8Array(arrayBuffer);
     97 
     98    // Generate resources for testing.
     99    buffer = gl.createBuffer();
    100    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    101    framebuffer = gl.createFramebuffer();
    102    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
    103    program = wtu.setupSimpleTextureProgram(gl);
    104    renderbuffer = gl.createRenderbuffer();
    105    gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
    106    shader = gl.createShader(gl.VERTEX_SHADER);
    107    texture = gl.createTexture();
    108    gl.bindTexture(gl.TEXTURE_2D, texture);
    109    shouldBe("gl.getError()", "gl.NO_ERROR");
    110 
    111    // Test is queries that will later be false
    112    shouldGenerateGLError(gl, gl.NO_ERROR, "gl.enable(gl.BLEND)");
    113    shouldBeTrue("gl.isBuffer(buffer)");
    114    shouldBeTrue("gl.isEnabled(gl.BLEND)");
    115    shouldBeTrue("gl.isFramebuffer(framebuffer)");
    116    shouldBeTrue("gl.isProgram(program)");
    117    shouldBeTrue("gl.isRenderbuffer(renderbuffer)");
    118    shouldBeTrue("gl.isShader(shader)");
    119    shouldBeTrue("gl.isTexture(texture)");
    120 
    121    if (OES_vertex_array_object) {
    122      vertexArrayObject = OES_vertex_array_object.createVertexArrayOES();
    123      shouldBe("gl.getError()", "gl.NO_ERROR");
    124      shouldBeTrue("OES_vertex_array_object.isVertexArrayOES(vertexArrayObject)");
    125    }
    126 }
    127 
    128 function testGLNOErrorFunctions(tests) {
    129  tests.forEach(function(test) {
    130      shouldGenerateGLError(gl, gl.NO_ERROR, test);
    131  });
    132 }
    133 
    134 function testFunctionsThatReturnNULL(tests) {
    135  tests.forEach(function(test) {
    136      shouldBeNull(test);
    137  });
    138 }
    139 
    140 function testUploadingLostContextToTexture() {
    141  debug("Testing uploading a canvas with a lost WebGL context to a texture");
    142  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors at beginning");
    143  let texture = secondGL.createTexture();
    144  secondGL.bindTexture(secondGL.TEXTURE_2D, texture);
    145  secondGL.texImage2D(secondGL.TEXTURE_2D, 0, secondGL.RGBA, secondGL.RGBA, secondGL.UNSIGNED_BYTE, canvas);
    146  wtu.glErrorShouldBe(secondGL, [secondGL.INVALID_OPERATION, secondGL.NO_ERROR], "Should not crash when uploading canvas with lost WebGL context to a texture");
    147 }
    148 
    149 function testLostContext()
    150 {
    151    debug("Test lost context");
    152 
    153    // Functions with special return values.
    154    shouldBeTrue("gl.isContextLost()");
    155    shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL");
    156    shouldBe("gl.getError()", "gl.NO_ERROR");
    157    shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_UNSUPPORTED");
    158    shouldBe("gl.getAttribLocation(program, 'u_modelViewProjMatrix')", "-1");
    159    shouldBe("gl.getVertexAttribOffset(0, gl.VERTEX_ATTRIB_ARRAY_POINTER)", "0");
    160 
    161    // Attempt resize of lost context should succeed, still lost.
    162    gl.canvas.width = gl.canvas.width; // Try to hit any same-size resize path.
    163    shouldBeTrue("gl.isContextLost()");
    164 
    165    const newSize = gl.canvas.width + 1;
    166    gl.canvas.width = newSize;
    167    shouldBe("gl.canvas.width", newSize);
    168    shouldBeTrue("gl.isContextLost()");
    169 
    170    // Test the extension itself.
    171    shouldGenerateGLError(gl, gl.INVALID_OPERATION, "extension.loseContext()");
    172 
    173    image = document.createElement("img");
    174    video = document.createElement("video");
    175    canvas2d = document.createElement("canvas");
    176    ctx2d = canvas2d.getContext("2d");
    177    imageData = ctx2d.createImageData(1, 1);
    178    float32array = new Float32Array(1);
    179    int32array = new Int32Array(1);
    180 
    181    // Functions returning void should return immediately.
    182    // This is untestable, but we can at least be sure they cause no errors
    183    // and the codepaths are exercised.
    184    var voidTests = [
    185        "gl.activeTexture(gl.TEXTURE0)",
    186        "gl.attachShader(program, shader)",
    187        "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)",
    188        "gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer)",
    189        "gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer)",
    190        "gl.bindTexture(gl.TEXTURE_2D, texture)",
    191        "gl.blendColor(1.0, 1.0, 1.0, 1.0)",
    192        "gl.blendEquation(gl.FUNC_ADD)",
    193        "gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD)",
    194        "gl.blendFunc(gl.ONE, gl.ONE)",
    195        "gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE)",
    196        "gl.bufferData(gl.ARRAY_BUFFER, 0, gl.STATIC_DRAW)",
    197        "gl.bufferData(gl.ARRAY_BUFFER, arrayBufferView, gl.STATIC_DRAW)",
    198        "gl.bufferData(gl.ARRAY_BUFFER, arrayBuffer, gl.STATIC_DRAW)",
    199        "gl.bufferSubData(gl.ARRAY_BUFFRE, 0, arrayBufferView)",
    200        "gl.bufferSubData(gl.ARRAY_BUFFRE, 0, arrayBuffer)",
    201        "gl.clear(gl.COLOR_BUFFER_BIT)",
    202        "gl.clearColor(1, 1, 1, 1)",
    203        "gl.clearDepth(1)",
    204        "gl.clearStencil(0)",
    205        "gl.colorMask(1, 1, 1, 1)",
    206        "gl.compileShader(shader)",
    207        "gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 0, 0, 0)",
    208        "gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 0, 0)",
    209        "gl.cullFace(gl.FRONT)",
    210        "gl.deleteBuffer(buffer)",
    211        "gl.deleteFramebuffer(framebuffer)",
    212        "gl.deleteProgram(program)",
    213        "gl.deleteRenderbuffer(renderbuffer)",
    214        "gl.deleteShader(shader)",
    215        "gl.deleteTexture(texture)",
    216        "gl.depthFunc(gl.NEVER)",
    217        "gl.depthMask(0)",
    218        "gl.depthRange(0, 1)",
    219        "gl.detachShader(program, shader)",
    220        "gl.disable(gl.BLEND)",
    221        "gl.disableVertexAttribArray(0)",
    222        "gl.drawArrays(gl.POINTS, 0, 0)",
    223        "gl.drawElements(gl.POINTS, 0, gl.UNSIGNED_SHORT, 0)",
    224        "gl.enable(gl.BLEND)",
    225        "gl.enableVertexAttribArray(0)",
    226        "gl.finish()",
    227        "gl.flush()",
    228        "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer)",
    229        "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0)",
    230        "gl.frontFace(gl.CW)",
    231        "gl.generateMipmap(gl.TEXTURE_2D)",
    232        "gl.hint(gl.GENERATE_MIPMAP_HINT, gl.FASTEST)",
    233        "gl.lineWidth(0)",
    234        "gl.linkProgram(program)",
    235        "gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0)",
    236        "gl.polygonOffset(0, 0)",
    237        "gl.readPixels(0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)",
    238        "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0)",
    239        "gl.sampleCoverage(0, 0)",
    240        "gl.scissor(0, 0, 0, 0)",
    241        "gl.shaderSource(shader, '')",
    242        "gl.stencilFunc(gl.NEVER, 0, 0)",
    243        "gl.stencilFuncSeparate(gl.FRONT, gl.NEVER, 0, 0)",
    244        "gl.stencilMask(0)",
    245        "gl.stencilMaskSeparate(gl.FRONT, 0)",
    246        "gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP)",
    247        "gl.stencilOpSeparate(gl.FRONT, gl.KEEP, gl.KEEP, gl.KEEP)",
    248        "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)",
    249        "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imageData)",
    250        "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image)",
    251        "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d)",
    252        "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video)",
    253        "gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)",
    254        "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)",
    255        "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)",
    256        "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, imageData)",
    257        "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, image)",
    258        "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d)",
    259        "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, video)",
    260        "gl.uniform1f(uniformLocation, 0)",
    261        "gl.uniform1fv(uniformLocation, float32array)",
    262        "gl.uniform1fv(uniformLocation, [0])",
    263        "gl.uniform1i(uniformLocation, 0)",
    264        "gl.uniform1iv(uniformLocation, int32array)",
    265        "gl.uniform1iv(uniformLocation, [0])",
    266        "gl.uniform2f(uniformLocation, 0, 0)",
    267        "gl.uniform2fv(uniformLocation, float32array)",
    268        "gl.uniform2fv(uniformLocation, [0, 0])",
    269        "gl.uniform2i(uniformLocation, 0, 0)",
    270        "gl.uniform2iv(uniformLocation, int32array)",
    271        "gl.uniform2iv(uniformLocation, [0, 0])",
    272        "gl.uniform3f(uniformLocation, 0, 0, 0)",
    273        "gl.uniform3fv(uniformLocation, float32array)",
    274        "gl.uniform3fv(uniformLocation, [0, 0, 0])",
    275        "gl.uniform3i(uniformLocation, 0, 0, 0)",
    276        "gl.uniform3iv(uniformLocation, int32array)",
    277        "gl.uniform3iv(uniformLocation, [0, 0, 0])",
    278        "gl.uniform4f(uniformLocation, 0, 0, 0, 0)",
    279        "gl.uniform4fv(uniformLocation, float32array)",
    280        "gl.uniform4fv(uniformLocation, [0, 0, 0, 0])",
    281        "gl.uniform4i(uniformLocation, 0, 0, 0, 0)",
    282        "gl.uniform4iv(uniformLocation, int32array)",
    283        "gl.uniform4iv(uniformLocation, [0, 0, 0, 0])",
    284        "gl.uniformMatrix2fv(uniformLocation, false, float32array)",
    285        "gl.uniformMatrix2fv(uniformLocation, false, [0, 0, 0, 0])",
    286        "gl.uniformMatrix3fv(uniformLocation, false, float32array)",
    287        "gl.uniformMatrix3fv(uniformLocation, false, [0, 0, 0, 0, 0, 0, 0, 0, 0])",
    288        "gl.uniformMatrix4fv(uniformLocation, false, float32array)",
    289        "gl.uniformMatrix4fv(uniformLocation, false, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])",
    290        "gl.useProgram(program)",
    291        "gl.validateProgram(program)",
    292        "gl.vertexAttrib1f(0, 0)",
    293        "gl.vertexAttrib1fv(0, float32array)",
    294        "gl.vertexAttrib1fv(0, [0])",
    295        "gl.vertexAttrib2f(0, 0, 0)",
    296        "gl.vertexAttrib2fv(0, float32array)",
    297        "gl.vertexAttrib2fv(0, [0, 0])",
    298        "gl.vertexAttrib3f(0, 0, 0, 0)",
    299        "gl.vertexAttrib3fv(0, float32array)",
    300        "gl.vertexAttrib3fv(0, [0, 0, 0])",
    301        "gl.vertexAttrib4f(0, 0, 0, 0, 0)",
    302        "gl.vertexAttrib4fv(0, float32array)",
    303        "gl.vertexAttrib4fv(0, [0, 0, 0, 0])",
    304        "gl.vertexAttribPointer(0, 0, gl.FLOAT, false, 0, 0)",
    305        "gl.viewport(0, 0, 0, 0)",
    306    ];
    307    testGLNOErrorFunctions(voidTests);
    308 
    309    // Functions return nullable values should all return null.
    310    var nullTests = [
    311        "gl.getActiveAttrib(program, 0)",
    312        "gl.getActiveUniform(program, 0)",
    313        "gl.getAttachedShaders(program)",
    314        "gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE)",
    315        "gl.getContextAttributes()",
    316        "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)",
    317        "gl.getParameter(gl.CURRENT_PROGRAM)",
    318        "gl.getProgramInfoLog(program)",
    319        "gl.getProgramParameter(program, gl.LINK_STATUS)",
    320        "gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)",
    321        "gl.getShaderInfoLog(shader)",
    322        "gl.getShaderParameter(shader, gl.SHADER_TYPE)",
    323        "gl.getShaderSource(shader)",
    324        "gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S)",
    325        "gl.getUniform(program, uniformLocation)",
    326        "gl.getUniformLocation(program, 'vPosition')",
    327        "gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)",
    328        "gl.getSupportedExtensions()",
    329        "gl.getExtension('" + extensionName + "')",
    330    ];
    331    testFunctionsThatReturnNULL(nullTests);
    332 
    333    [
    334      [() => gl.createBuffer(), x => gl.bindBuffer(gl.ARRAY_BUFFER, x), x => gl.isBuffer(x)],
    335      [() => gl.createFramebuffer(), x => gl.bindFramebuffer(gl.FRAMEBUFFER, x), x => gl.isFramebuffer(x)],
    336      [() => gl.createProgram(), x => undefined, x => gl.isProgram(x)],
    337      [() => gl.createRenderbuffer(), x => gl.bindRenderbuffer(gl.RENDERBUFFER, x), x => gl.isRenderbuffer(x)],
    338      [() => gl.createShader(gl.VERTEX_SHADER), x => undefined, x => gl.isShader(x)],
    339      [() => gl.createTexture(), x => gl.bindTexture(gl.TEXTURE_2D, x), x => gl.isTexture(x)],
    340    ].forEach(([fn_create, fn_bind, fn_is]) => {
    341      const x = fn_create();
    342      assertMsg(x, `${fn_create.toString()} -> non-null`);
    343      assertMsg(fn_is(x) === false, `[before bind] ${fn_is.toString()} -> false`);
    344      fn_bind(x);
    345      fn_bind(null);
    346      assertMsg(fn_is(x) === false, `[after bind] ${fn_is.toString()} -> false`);
    347    });
    348 
    349    // "Is" queries should all return false.
    350    shouldBeFalse("gl.isEnabled(gl.BLEND)");
    351 
    352    shouldBe("gl.getError()", "gl.NO_ERROR");
    353 
    354    // test extensions
    355    if (OES_vertex_array_object) {
    356      testGLNOErrorFunctions(
    357        [
    358          "OES_vertex_array_object.bindVertexArrayOES(vertexArrayObject)",
    359          "OES_vertex_array_object.isVertexArrayOES(vertexArrayObject)",
    360          "OES_vertex_array_object.deleteVertexArrayOES(vertexArrayObject)",
    361        ]);
    362 
    363      [
    364        [() => OES_vertex_array_object.createVertexArrayOES(), x => OES_vertex_array_object.isVertexArrayOES(x), x => OES_vertex_array_object.isVertexArrayOES(x)],
    365      ].forEach(([fn_create, fn_bind, fn_is]) => {
    366        const x = fn_create();
    367        assertMsg(x, `${fn_create.toString()} -> non-null`);
    368        assertMsg(fn_is(x) === false, `[before bind] ${fn_is.toString()} -> false`);
    369        fn_bind(x);
    370        fn_bind(null);
    371        assertMsg(fn_is(x) === false, `[after bind] ${fn_is.toString()} -> false`);
    372      });
    373    }
    374 
    375    testUploadingLostContextToTexture();
    376 
    377    debug("");
    378 
    379    finishTest();
    380 }
    381 
    382 </script>
    383 </head>
    384 <body onload="init()">
    385 <div id="description"></div>
    386 <div id="console"></div>
    387 <canvas id="canvas">
    388 <canvas id="canvas2">
    389 </body>
    390 </html>