expando-loss-2.html (10891B)
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 <!DOCTYPE html> 7 <html> 8 <head> 9 <meta charset="utf-8"> 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 <title>WebGL 2 Object Expandos Conformance Test</title> 14 </head> 15 <body> 16 <div id="description"></div> 17 <div id="console"></div> 18 <canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas> 19 <script> 20 "use strict"; 21 description("This test verifies that WebGL object expandos are preserved across garbage collections."); 22 23 var wtu = WebGLTestUtils; 24 var canvas = document.getElementById("canvas"); 25 var gl = wtu.create3DContext(canvas, {antialias: false}, 2); 26 27 // Helpers that set expandos and verify they are set to the correct value. 28 var expandoValue = "WebGL is awesome!" 29 function setTestExpandos(instance, extra) { 30 instance.expando1 = expandoValue; 31 instance.expando2 = { subvalue : expandoValue }; 32 instance.expando_extra = extra; 33 } 34 function verifyTestExpandos(instance, msg, extra) { 35 assertMsg(instance.expando1 === expandoValue, msg + ": Expect basic expando to survive despite GC."); 36 assertMsg(instance.expando2 && instance.expando2.subvalue === expandoValue, msg + ": Expect subobject expando to survive despite GC."); 37 assertMsg(instance.expando_extra === extra, msg + ": Expect extra expando to survive despite GC."); 38 } 39 40 // Tests that we don't get expando loss for bound resources where the 41 // only remaining reference is internal to WebGL 42 function testBasicBindings() { 43 debug('Basic Bindings'); 44 45 // Test data that describes how to create, bind, and retrieve an object off of the context 46 var glProt = Object.getPrototypeOf(gl); 47 var simpleData = [ 48 { 49 typeName: 'WebGLSampler', 50 creationFn: glProt.createSampler, 51 bindFn: glProt.bindSampler, 52 bindConstant: 0, 53 retrieveConstant: glProt.SAMPLER_BINDING, 54 name: "SAMPLER_BINDING", 55 }, 56 { 57 typeName: 'WebGLTransformFeedback', 58 creationFn: glProt.createTransformFeedback, 59 bindFn: glProt.bindTransformFeedback, 60 bindConstant: glProt.TRANSFORM_FEEDBACK, 61 retrieveConstant: glProt.TRANSFORM_FEEDBACK_BINDING, 62 name: "TRANSFORM_FEEDBACK_BINDING", 63 }, 64 { 65 typeName: 'WebGLVertexArrayObject', 66 creationFn: glProt.createVertexArray, 67 bindFn: glProt.bindVertexArray, 68 bindConstant: null, 69 retrieveConstant: glProt.VERTEX_ARRAY_BINDING, 70 name: "VERTEX_ARRAY_BINDING", 71 }, 72 { 73 typeName: 'WebGLTexture', 74 creationFn: glProt.createTexture, 75 bindFn: glProt.bindTexture, 76 bindConstant: glProt.TEXTURE_3D, 77 retrieveConstant: glProt.TEXTURE_BINDING_3D, 78 name: "TEXTURE_BINDING_3D", 79 }, 80 { 81 typeName: 'WebGLTexture', 82 creationFn: glProt.createTexture, 83 bindFn: glProt.bindTexture, 84 bindConstant: glProt.TEXTURE_2D_ARRAY, 85 retrieveConstant: glProt.TEXTURE_BINDING_2D_ARRAY, 86 name: "TEXTURE_BINDING_2D_ARRAY", 87 }, 88 { 89 typeName: 'WebGLFramebuffer', 90 creationFn: glProt.createFramebuffer, 91 bindFn: glProt.bindFramebuffer, 92 bindConstant: glProt.READ_FRAMEBUFFER, 93 retrieveConstant: glProt.READ_FRAMEBUFFER_BINDING, 94 name: "READ_FRAMEBUFFER_BINDING", 95 }, 96 { 97 typeName: 'WebGLFramebuffer', 98 creationFn: glProt.createFramebuffer, 99 bindFn: glProt.bindFramebuffer, 100 bindConstant: glProt.DRAW_FRAMEBUFFER, 101 retrieveConstant: glProt.DRAW_FRAMEBUFFER_BINDING, 102 name: "DRAW_FRAMEBUFFER_BINDING", 103 }, 104 { 105 typeName: 'WebGLBuffer', 106 creationFn: glProt.createBuffer, 107 bindFn: glProt.bindBuffer, 108 bindConstant: glProt.COPY_READ_BUFFER, 109 retrieveConstant: glProt.COPY_READ_BUFFER_BINDING, 110 name: "COPY_READ_BUFFER_BINDING", 111 }, 112 { 113 typeName: 'WebGLBuffer', 114 creationFn: glProt.createBuffer, 115 bindFn: glProt.bindBuffer, 116 bindConstant: glProt.COPY_WRITE_BUFFER, 117 retrieveConstant: glProt.COPY_WRITE_BUFFER_BINDING, 118 name: "COPY_WRITE_BUFFER_BINDING", 119 }, 120 { 121 typeName: 'WebGLBuffer', 122 creationFn: glProt.createBuffer, 123 bindFn: glProt.bindBuffer, 124 bindConstant: glProt.PIXEL_PACK_BUFFER, 125 retrieveConstant: glProt.PIXEL_PACK_BUFFER_BINDING, 126 name: "PIXEL_PACK_BUFFER_BINDING", 127 }, 128 { 129 typeName: 'WebGLBuffer', 130 creationFn: glProt.createBuffer, 131 bindFn: glProt.bindBuffer, 132 bindConstant: glProt.PIXEL_UNPACK_BUFFER, 133 retrieveConstant: glProt.PIXEL_UNPACK_BUFFER_BINDING, 134 name: "PIXEL_UNPACK_BUFFER_BINDING", 135 }, 136 { 137 typeName: 'WebGLBuffer', 138 creationFn: glProt.createBuffer, 139 bindFn: glProt.bindBuffer, 140 bindConstant: glProt.TRANSFORM_FEEDBACK_BUFFER, 141 retrieveConstant: glProt.TRANSFORM_FEEDBACK_BUFFER_BINDING, 142 name: "TRANSFORM_FEEDBACK_BUFFER_BINDING", 143 }, 144 { 145 typeName: 'WebGLBuffer', 146 creationFn: glProt.createBuffer, 147 bindFn: glProt.bindBuffer, 148 bindConstant: glProt.UNIFORM_BUFFER, 149 retrieveConstant: glProt.UNIFORM_BUFFER_BINDING, 150 name: "UNIFORM_BUFFER_BINDING", 151 }, 152 ]; 153 154 simpleData.forEach(function(test) { 155 var instance = test.creationFn.call(gl); 156 var msg = "getParameter(" + test.name + ")"; 157 setTestExpandos(instance); 158 159 if (test.bindConstant === null) { 160 test.bindFn.call(gl, instance); 161 } else { 162 test.bindFn.call(gl, test.bindConstant, instance); 163 } 164 assertMsg(instance === gl.getParameter(test.retrieveConstant), msg + " returns instance that was bound."); 165 166 // Garbage collect Javascript references. Remaining references should be internal to WebGL. 167 instance = null; 168 webglHarnessCollectGarbage(); 169 170 var retrievedObject = gl.getParameter(test.retrieveConstant); 171 verifyTestExpandos(retrievedObject, msg); 172 shouldBeType(retrievedObject, test.typeName); 173 debug(''); 174 }); 175 } 176 177 function testIndexedBindings() { 178 debug('Indexed Bindings'); 179 180 // Test data that describes how to create, bind, and retrieve an indexed object off of the context 181 var glProt = Object.getPrototypeOf(gl); 182 var simpleData = [ 183 { 184 typeName: 'WebGLBuffer', 185 creationFn: glProt.createBuffer, 186 bindFn: glProt.bindBufferBase, 187 indexMax: gl.getParameter(glProt.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS) - 1, 188 bindConstant: glProt.TRANSFORM_FEEDBACK_BUFFER, 189 retrieveConstant: glProt.TRANSFORM_FEEDBACK_BUFFER_BINDING, 190 name: "TRANSFORM_FEEDBACK_BUFFER_BINDING", 191 }, 192 { 193 typeName: 'WebGLBuffer', 194 creationFn: glProt.createBuffer, 195 bindFn: glProt.bindBufferBase, 196 indexMax: gl.getParameter(glProt.MAX_UNIFORM_BUFFER_BINDINGS) - 1, 197 bindConstant: glProt.UNIFORM_BUFFER, 198 retrieveConstant: glProt.UNIFORM_BUFFER_BINDING, 199 name: "UNIFORM_BUFFER_BINDING", 200 }, 201 ]; 202 203 simpleData.forEach(function(test) { 204 // This test sets all of the separate indexed bindings first, then 205 // tests them all. It puts a different extra expando on each indexed 206 // parameter so that we can ensure they're all distinct. 207 var instances = []; 208 for (var i = 0; i <= test.indexMax; i++) { 209 var instance = test.creationFn.call(gl); 210 var msg = "getIndexedParameter(" + test.name + ", " + i + ")"; 211 setTestExpandos(instance, i); 212 instances[i] = instance; 213 test.bindFn.call(gl, test.bindConstant, i, instance); 214 } 215 216 for (var i = 0; i <= test.indexMax; i++) { 217 var msg = "getIndexedParameter(" + test.name + ", " + i + ")"; 218 assertMsg(instances[i] === gl.getIndexedParameter(test.retrieveConstant, i), msg + " returns instance that was bound."); 219 } 220 221 // Garbage collect Javascript references. Remaining references should be internal to WebGL. 222 instances = null; 223 webglHarnessCollectGarbage(); 224 225 for (var i = 0; i <= test.indexMax; i++) { 226 var msg = "getIndexedParameter(" + test.name + ", " + i + ")"; 227 var retrievedObject = gl.getIndexedParameter(test.retrieveConstant, i); 228 verifyTestExpandos(retrievedObject, msg, i); 229 shouldBeType(retrievedObject, test.typeName); 230 debug(''); 231 } 232 }); 233 } 234 235 function testQueries() { 236 debug('Query'); 237 238 expandoValue = "First query"; 239 var query1 = gl.createQuery(); 240 setTestExpandos(query1); 241 gl.beginQuery(gl.ANY_SAMPLES_PASSED, query1); 242 243 expandoValue = "Second query"; 244 var query2 = gl.createQuery(); 245 setTestExpandos(query2); 246 gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query2); 247 248 249 assertMsg(query1 === gl.getQuery(gl.ANY_SAMPLES_PASSED, gl.CURRENT_QUERY), "CURRENT_QUERY returns instance that was bound."); 250 assertMsg(query2 === gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY), "CURRENT_QUERY returns instance that was bound."); 251 252 // Garbage collect Javascript references. Remaining references should be internal to WebGL. 253 query1 = null; 254 query2 = null; 255 webglHarnessCollectGarbage(); 256 257 var retrievedQuery1 = gl.getQuery(gl.ANY_SAMPLES_PASSED, gl.CURRENT_QUERY); 258 var retrievedQuery2 = gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY); 259 expandoValue = "First query"; 260 verifyTestExpandos(retrievedQuery1, "Query"); 261 shouldBeType(retrievedQuery1, 'WebGLQuery'); 262 263 expandoValue = "Second query"; 264 verifyTestExpandos(retrievedQuery2, "Query"); 265 shouldBeType(retrievedQuery2, 'WebGLQuery'); 266 267 gl.endQuery(gl.ANY_SAMPLES_PASSED); 268 gl.endQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); 269 270 debug(''); 271 } 272 273 // Run tests 274 testBasicBindings(); 275 testIndexedBindings(); 276 testQueries(); 277 278 // FYI: There's no need to test WebGLSync objects because there is no notion of an "active" sync, 279 // and thus no way to query them back out of the context. 280 281 var successfullyParsed = true; 282 </script> 283 <script src="../../js/js-test-post.js"></script> 284 </body> 285 </html>