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.
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>
16 <div id=
"description"></div>
17 <div id=
"console"></div>
18 <canvas id=
"canvas" width=
"8" height=
"8" style=
"width: 8px; height: 8px;"></canvas>
21 description("This test verifies that WebGL object expandos are preserved across garbage collections.");
23 var wtu
= WebGLTestUtils
;
24 var canvas
= document
.getElementById("canvas");
25 var gl
= wtu
.create3DContext(canvas
, {antialias
: false}, 2);
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
;
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.");
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');
45 // Test data that describes how to create, bind, and retrieve an object off of the context
46 var glProt
= Object
.getPrototypeOf(gl
);
49 typeName
: 'WebGLSampler',
50 creationFn
: glProt
.createSampler
,
51 bindFn
: glProt
.bindSampler
,
53 retrieveConstant
: glProt
.SAMPLER_BINDING
,
54 name
: "SAMPLER_BINDING",
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",
65 typeName
: 'WebGLVertexArrayObject',
66 creationFn
: glProt
.createVertexArray
,
67 bindFn
: glProt
.bindVertexArray
,
69 retrieveConstant
: glProt
.VERTEX_ARRAY_BINDING
,
70 name
: "VERTEX_ARRAY_BINDING",
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",
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",
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",
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",
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",
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",
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",
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",
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",
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",
154 simpleData
.forEach(function(test
) {
155 var instance
= test
.creationFn
.call(gl
);
156 var msg
= "getParameter(" + test
.name
+ ")";
157 setTestExpandos(instance
);
159 if (test
.bindConstant
=== null) {
160 test
.bindFn
.call(gl
, instance
);
162 test
.bindFn
.call(gl
, test
.bindConstant
, instance
);
164 assertMsg(instance
=== gl
.getParameter(test
.retrieveConstant
), msg
+ " returns instance that was bound.");
166 // Garbage collect Javascript references. Remaining references should be internal to WebGL.
168 webglHarnessCollectGarbage();
170 var retrievedObject
= gl
.getParameter(test
.retrieveConstant
);
171 verifyTestExpandos(retrievedObject
, msg
);
172 shouldBeType(retrievedObject
, test
.typeName
);
177 function testIndexedBindings() {
178 debug('Indexed Bindings');
180 // Test data that describes how to create, bind, and retrieve an indexed object off of the context
181 var glProt
= Object
.getPrototypeOf(gl
);
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",
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",
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.
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
);
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.");
221 // Garbage collect Javascript references. Remaining references should be internal to WebGL.
223 webglHarnessCollectGarbage();
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
);
235 function testQueries() {
238 expandoValue
= "First query";
239 var query1
= gl
.createQuery();
240 setTestExpandos(query1
);
241 gl
.beginQuery(gl
.ANY_SAMPLES_PASSED
, query1
);
243 expandoValue
= "Second query";
244 var query2
= gl
.createQuery();
245 setTestExpandos(query2
);
246 gl
.beginQuery(gl
.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
, query2
);
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.");
252 // Garbage collect Javascript references. Remaining references should be internal to WebGL.
255 webglHarnessCollectGarbage();
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');
263 expandoValue
= "Second query";
264 verifyTestExpandos(retrievedQuery2
, "Query");
265 shouldBeType(retrievedQuery2
, 'WebGLQuery');
267 gl
.endQuery(gl
.ANY_SAMPLES_PASSED
);
268 gl
.endQuery(gl
.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
);
275 testIndexedBindings();
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.
281 var successfullyParsed
= true;
283 <script src=
"../../js/js-test-post.js"></script>