tor-browser

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

ext-disjoint-timer-query.html (15445B)


      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 EXT_disjoint_timer_query Conformance Tests</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 <canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
     19 <div id="console"></div>
     20 
     21 <script>
     22 "use strict";
     23 description("This test verifies the functionality of the EXT_disjoint_timer_query extension, if it is available.");
     24 
     25 var wtu = WebGLTestUtils;
     26 var canvas = document.getElementById("canvas");
     27 var gl = wtu.create3DContext(canvas);
     28 var gl2 = null;
     29 var ext = null;
     30 var ext2 = null;
     31 var query = null;
     32 var query2 = null;
     33 var elapsed_query = null;
     34 var timestamp_query1 = null;
     35 var timestamp_query2 = null;
     36 var availability_retry = 500;
     37 var timestamp_counter_bits = 0;
     38 
     39 if (!gl) {
     40    testFailed("WebGL context does not exist");
     41    finishTest();
     42 } else {
     43    testPassed("WebGL context exists");
     44 
     45    // Query the extension and store globally so shouldBe can access it
     46    ext = wtu.getExtensionWithKnownPrefixes(gl, "EXT_disjoint_timer_query");
     47    if (!ext) {
     48        testPassed("No EXT_disjoint_timer_query support -- this is legal");
     49        finishTest();
     50    } else {
     51        if (wtu.getDefault3DContextVersion() > 1) {
     52            testFailed("EXT_disjoint_timer_query must not be advertised on WebGL 2.0 contexts");
     53            finishTest();
     54        } else {
     55            runSanityTests();
     56 
     57            // Clear disjoint value.
     58            gl.getParameter(ext.GPU_DISJOINT_EXT);
     59 
     60            runElapsedTimeTest();
     61            timestamp_counter_bits = ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT);
     62            if (timestamp_counter_bits > 0) {
     63                runTimeStampTest();
     64            }
     65            verifyQueryResultsNotAvailable();
     66            verifyDeleteQueryBehavior();
     67            verifyDeleteQueryErrorBehavior();
     68 
     69            window.requestAnimationFrame(checkQueryResults);
     70        }
     71    }
     72 }
     73 
     74 function runSanityTests() {
     75    debug("");
     76    debug("Testing timer query expectations");
     77 
     78    shouldBe("ext.QUERY_COUNTER_BITS_EXT", "0x8864");
     79    shouldBe("ext.CURRENT_QUERY_EXT", "0x8865");
     80    shouldBe("ext.QUERY_RESULT_EXT", "0x8866");
     81    shouldBe("ext.QUERY_RESULT_AVAILABLE_EXT", "0x8867");
     82    shouldBe("ext.TIME_ELAPSED_EXT", "0x88BF");
     83    shouldBe("ext.TIMESTAMP_EXT", "0x8E28");
     84    shouldBe("ext.GPU_DISJOINT_EXT", "0x8FBB");
     85 
     86    shouldBe("ext.isQueryEXT(null)", "false");
     87 
     88    shouldBeTrue("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT) === null");
     89    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
     90    shouldBeTrue("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.QUERY_COUNTER_BITS_EXT) >= 30");
     91    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
     92 
     93    shouldBeTrue("ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.CURRENT_QUERY_EXT) === null");
     94    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
     95 
     96    // Certain drivers set timestamp counter bits to 0 as they don't support timestamps
     97    shouldBeTrue("ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT) >= 30 || " +
     98             "ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT) === 0");
     99    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    100 
    101    debug("");
    102    debug("Testing time elapsed query lifecycle");
    103    query = ext.createQueryEXT();
    104    shouldBe("ext.isQueryEXT(query)", "false");
    105    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Query creation must succeed.");
    106    shouldThrow("ext.beginQueryEXT(ext.TIMESTAMP_EXT, null)");
    107    ext.beginQueryEXT(ext.TIMESTAMP_EXT, query);
    108    wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Beginning a timestamp query should fail.");
    109    ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);
    110    shouldBe("ext.isQueryEXT(query)", "true");
    111    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Beginning an inactive time elapsed query should succeed.");
    112    ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);
    113    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Attempting to begin an active query should fail.");
    114    ext.getQueryObjectEXT(query, ext.QUERY_RESULT_AVAILABLE_EXT);
    115    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Fetching query result availability of an active query should fail.");
    116    ext.getQueryObjectEXT(query, ext.QUERY_RESULT_EXT);
    117    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Fetching query result of an active query should fail.");
    118    shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "query");
    119    ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
    120    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Ending an active time elapsed query should succeed.");
    121    shouldThrow("ext.getQueryObjectEXT(null, ext.QUERY_RESULT_AVAILABLE_EXT)");
    122    ext.getQueryObjectEXT(query, ext.QUERY_RESULT_AVAILABLE_EXT);
    123    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Fetching query result availability after query end should succeed.");
    124    ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
    125    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Attempting to end an inactive query should fail.");
    126    ext.queryCounterEXT(query, ext.TIMESTAMP_EXT);
    127    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should not be able to use time elapsed query to store a timestamp.");
    128    ext.deleteQueryEXT(query);
    129    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Query deletion must succeed.");
    130    ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);
    131    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Beginning a deleted query must fail.");
    132    ext.getQueryObjectEXT(query, ext.QUERY_RESULT_AVAILABLE_EXT);
    133    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Fetching query result availability after query deletion should fail.");
    134    shouldBe("ext.isQueryEXT(query)", "false");
    135 
    136    debug("");
    137    debug("Testing timestamp counter");
    138    query = ext.createQueryEXT();
    139    shouldThrow("ext.queryCounterEXT(null, ext.TIMESTAMP_EXT)");
    140    ext.queryCounterEXT(query, ext.TIMESTAMP_EXT);
    141    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Timestamp counter queries should work.");
    142    ext.deleteQueryEXT(query);
    143    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    144 
    145    debug("");
    146    debug("Performing parameter sanity checks");
    147    gl.getParameter(ext.TIMESTAMP_EXT);
    148    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "getParameter timestamp calls should work.");
    149    gl.getParameter(ext.GPU_DISJOINT_EXT);
    150    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "getParameter disjoint calls should work.");
    151 
    152    debug("");
    153    debug("Testing current query conditions");
    154    query = ext.createQueryEXT();
    155    query2 = ext.createQueryEXT();
    156    shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "null");
    157    ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);
    158    shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "query");
    159    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    160 
    161    debug("");
    162    debug("Testing failed begin query should not change the current query.");
    163    ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query2);
    164    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Beginning an elapsed query without ending should fail.");
    165    shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "query");
    166    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    167 
    168    debug("");
    169    debug("Testing beginning a timestamp query is invalid and should not change the elapsed query.");
    170    ext.beginQueryEXT(ext.TIMESTAMP_EXT, query2)
    171    wtu.glErrorShouldBe(gl, gl.INVALID_ENUM);
    172    shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "query");
    173    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    174 
    175    debug("");
    176    debug("Testing timestamp queries end immediately so are never current.");
    177    ext.queryCounterEXT(query2, ext.TIMESTAMP_EXT);
    178    shouldBe("ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.CURRENT_QUERY_EXT)", "null");
    179    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    180 
    181    debug("");
    182    debug("Testing ending the query should clear the current query.");
    183    ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
    184    shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "null");
    185    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    186 
    187    debug("");
    188    debug("Testing beginning a elapsed query using a timestamp query should fail and not affect current query.")
    189    ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query2);
    190    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Switching query targets should fail.");
    191    shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "null");
    192    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    193 
    194    ext.deleteQueryEXT(query);
    195    ext.deleteQueryEXT(query2);
    196 
    197    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors at end of sanity tests");
    198 }
    199 
    200 function runElapsedTimeTest() {
    201    debug("");
    202    debug("Testing elapsed time query");
    203 
    204    elapsed_query = ext.createQueryEXT();
    205    ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, elapsed_query);
    206    gl.clearColor(0, 0, 1, 1);
    207    gl.clear(gl.COLOR_BUFFER_BIT);
    208    ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
    209    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Time elapsed query should have no errors");
    210 }
    211 
    212 function runTimeStampTest() {
    213    debug("");
    214    debug("Testing timestamp query");
    215 
    216    timestamp_query1 = ext.createQueryEXT();
    217    timestamp_query2 = ext.createQueryEXT();
    218    ext.queryCounterEXT(timestamp_query1, ext.TIMESTAMP_EXT);
    219    gl.clearColor(1, 0, 0, 1);
    220    gl.clear(gl.COLOR_BUFFER_BIT);
    221    ext.queryCounterEXT(timestamp_query2, ext.TIMESTAMP_EXT);
    222    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Timestamp queries should have no errors");
    223 }
    224 
    225 function verifyQueryResultsNotAvailable() {
    226    debug("");
    227    debug("Verifying queries' results don't become available too early");
    228 
    229    // Verify as best as possible that the implementation doesn't
    230    // allow a query's result to become available the same frame, by
    231    // spin-looping for some time and ensuring that none of the
    232    // queries' results become available.
    233    var startTime = Date.now();
    234    while (Date.now() - startTime < 2000) {
    235        gl.finish();
    236        if (ext.getQueryObjectEXT(elapsed_query, ext.QUERY_RESULT_AVAILABLE_EXT)) {
    237            testFailed("One of the queries' results became available too early");
    238            return;
    239        }
    240        if (timestamp_counter_bits > 0) {
    241            if (ext.getQueryObjectEXT(timestamp_query1, ext.QUERY_RESULT_AVAILABLE_EXT) ||
    242                ext.getQueryObjectEXT(timestamp_query2, ext.QUERY_RESULT_AVAILABLE_EXT)) {
    243                testFailed("One of the queries' results became available too early");
    244                return;
    245            }
    246        }
    247    }
    248 
    249    testPassed("Queries' results didn't become available in a spin loop");
    250 }
    251 
    252 function verifyDeleteQueryBehavior() {
    253    debug("");
    254    debug("Testing deleting an active query should end it.");
    255 
    256    // Use a new context for this test
    257    gl2 = wtu.create3DContext(null, null, 1);
    258    if (!gl2) return;
    259    ext2 = gl2.getExtension("EXT_disjoint_timer_query");
    260    if (!ext2) return;
    261 
    262    query = ext2.createQueryEXT();
    263    ext2.beginQueryEXT(ext2.TIME_ELAPSED_EXT, query);
    264    wtu.glErrorShouldBe(gl2, gl2.NONE, "The query began successfully");
    265    ext2.deleteQueryEXT(query);
    266    wtu.glErrorShouldBe(gl2, gl2.NONE, "Deletion of the active query succeeds");
    267    shouldBeNull("ext2.getQueryEXT(ext2.TIME_ELAPSED_EXT, ext2.CURRENT_QUERY_EXT)");
    268    shouldBeFalse("ext2.isQueryEXT(query)");
    269    query = ext2.createQueryEXT();
    270    ext2.beginQueryEXT(ext2.TIME_ELAPSED_EXT, query);
    271    wtu.glErrorShouldBe(gl2, gl2.NONE, "Beginning a new query succeeds");
    272    ext2.endQueryEXT(ext2.TIME_ELAPSED_EXT);
    273    ext2.deleteQueryEXT(query);
    274    wtu.glErrorShouldBe(gl2, gl2.NONE);
    275    query = null;
    276    ext2 = null;
    277    gl2 = null;
    278 }
    279 
    280 function verifyDeleteQueryErrorBehavior() {
    281    debug("");
    282    debug("Testing deleting a query created by another context.");
    283 
    284    // Use new contexts for this test
    285    gl2 = wtu.create3DContext(null, null, 1);
    286    var gl3 = wtu.create3DContext(null, null, 1);
    287    if (!gl2 || !gl3) return;
    288    ext2 = gl2.getExtension("EXT_disjoint_timer_query");
    289    var ext3 = gl3.getExtension("EXT_disjoint_timer_query");
    290    if (!ext2 || !ext3) return;
    291 
    292    query = ext2.createQueryEXT();
    293    ext2.beginQueryEXT(ext2.TIME_ELAPSED_EXT, query);
    294    ext3.deleteQueryEXT(query);
    295    wtu.glErrorShouldBe(gl3, gl3.INVALID_OPERATION);
    296    shouldBeTrue("ext2.isQueryEXT(query)");
    297    shouldBe("ext2.getQueryEXT(ext2.TIME_ELAPSED_EXT, ext2.CURRENT_QUERY_EXT)", "query");
    298    ext2.endQueryEXT(ext2.TIME_ELAPSED_EXT);
    299    ext2.deleteQueryEXT(query);
    300    wtu.glErrorShouldBe(gl2, gl2.NONE);
    301    query = null;
    302    ext2 = null;
    303    gl2 = null;
    304    gl3 = null;
    305 }
    306 
    307 function checkQueryResults() {
    308    if (availability_retry > 0) {
    309        // Make a reasonable attempt to wait for the queries' results to become available.
    310        if (!ext.getQueryObjectEXT(elapsed_query, ext.QUERY_RESULT_AVAILABLE_EXT) ||
    311            (timestamp_counter_bits > 0 && !ext.getQueryObjectEXT(timestamp_query2, ext.QUERY_RESULT_AVAILABLE_EXT))) {
    312            var error = gl.getError();
    313            if (error != gl.NO_ERROR) {
    314                testFailed("getQueryObjectEXT should have no errors: " + wtu.glEnumToString(gl, error));
    315                debug("");
    316                finishTest();
    317                return;
    318            }
    319            availability_retry--;
    320            window.requestAnimationFrame(checkQueryResults);
    321            return;
    322        }
    323    }
    324 
    325    debug("");
    326    debug("Testing query results");
    327 
    328    // Make sure queries are available.
    329    shouldBe("ext.getQueryObjectEXT(elapsed_query, ext.QUERY_RESULT_AVAILABLE_EXT)", "true");
    330    if (timestamp_counter_bits > 0) {
    331        shouldBe("ext.getQueryObjectEXT(timestamp_query1, ext.QUERY_RESULT_AVAILABLE_EXT)", "true");
    332        shouldBe("ext.getQueryObjectEXT(timestamp_query2, ext.QUERY_RESULT_AVAILABLE_EXT)", "true");
    333    }
    334 
    335    var disjoint_value = gl.getParameter(ext.GPU_DISJOINT_EXT);
    336    if (disjoint_value) {
    337        // Cannot validate results make sense, but this is okay.
    338        testPassed("Disjoint triggered.");
    339    } else {
    340        var elapsed_result = ext.getQueryObjectEXT(elapsed_query, ext.QUERY_RESULT_EXT);
    341        if (timestamp_counter_bits > 0) {
    342            var timestamp_result1 = ext.getQueryObjectEXT(timestamp_query1, ext.QUERY_RESULT_EXT);
    343            var timestamp_result2 = ext.getQueryObjectEXT(timestamp_query2, ext.QUERY_RESULT_EXT);
    344        }
    345        // Do some basic validity checking of the elapsed time query. There's no way it should
    346        // take more than about half a second for a no-op query.
    347        var halfSecondInNanos = 0.5 * 1000 * 1000 * 1000;
    348        if (elapsed_result < 0 || elapsed_result > halfSecondInNanos) {
    349            testFailed("Time elapsed query returned invalid data: " + elapsed_result);
    350        } else {
    351            testPassed("Time elapsed query results were valid.");
    352        }
    353 
    354        if (timestamp_counter_bits > 0) {
    355            if (timestamp_result1 <= 0 ||
    356                timestamp_result2 <= 0 ||
    357                timestamp_result2 <= timestamp_result1) {
    358                testFailed("Timestamp queries returned invalid data: timestamp_result1 = " +
    359                           timestamp_result1 + ", timestamp_result2 = " + timestamp_result2);
    360            } else {
    361                testPassed("Timestamp query results were valid.");
    362            }
    363        }
    364    }
    365 
    366    debug("");
    367    finishTest();
    368 }
    369 </script>
    370 </body>
    371 </html>