@gjsify/webgl 0.0.3 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -6
- package/lib/esm/canvas-webgl-widget.js +116 -0
- package/lib/esm/html-canvas-element.js +31 -50
- package/lib/esm/index.js +7 -0
- package/lib/esm/index.spec.js +629 -120
- package/lib/esm/test-utils.js +87 -0
- package/lib/esm/test.js +5 -1
- package/lib/esm/utils.js +1 -1
- package/lib/esm/webgl-active-info.js +2 -2
- package/lib/esm/webgl-buffer.js +2 -3
- package/lib/esm/webgl-context-attributes.js +2 -3
- package/lib/esm/webgl-framebuffer.js +3 -4
- package/lib/esm/webgl-program.js +2 -3
- package/lib/esm/webgl-query.js +15 -0
- package/lib/esm/webgl-renderbuffer.js +2 -3
- package/lib/esm/webgl-rendering-context.js +105 -101
- package/lib/esm/webgl-sampler.js +15 -0
- package/lib/esm/webgl-shader-precision-format.js +2 -3
- package/lib/esm/webgl-shader.js +2 -3
- package/lib/esm/webgl-sync.js +15 -0
- package/lib/esm/webgl-texture.js +2 -3
- package/lib/esm/webgl-transform-feedback.js +15 -0
- package/lib/esm/webgl-uniform-location.js +2 -3
- package/lib/esm/webgl-vertex-array-object.js +21 -0
- package/lib/esm/webgl2-rendering-context.js +591 -0
- package/lib/esm/webgl2.spec.js +578 -0
- package/lib/types/canvas-webgl-widget.d.ts +509 -0
- package/lib/types/extensions/ext-blend-minmax.d.ts +2 -2
- package/lib/types/extensions/ext-texture-filter-anisotropic.d.ts +2 -2
- package/lib/types/extensions/oes-element-index-unit.d.ts +2 -2
- package/lib/types/extensions/oes-standard-derivatives.d.ts +2 -2
- package/lib/types/extensions/oes-texture-float-linear.d.ts +2 -2
- package/lib/types/extensions/oes-texture-float.d.ts +2 -2
- package/lib/types/extensions/stackgl-destroy-context.d.ts +3 -3
- package/lib/types/extensions/stackgl-resize-drawing-buffer.d.ts +3 -3
- package/lib/types/html-canvas-element.d.ts +19 -30
- package/lib/types/index.d.ts +7 -0
- package/lib/types/test-utils.d.ts +45 -0
- package/lib/types/types/extension.d.ts +2 -2
- package/lib/types/utils.d.ts +14 -15
- package/lib/types/webgl-active-info.d.ts +1 -2
- package/lib/types/webgl-buffer.d.ts +5 -6
- package/lib/types/webgl-context-attributes.d.ts +1 -2
- package/lib/types/webgl-framebuffer.d.ts +4 -5
- package/lib/types/webgl-program.d.ts +4 -5
- package/lib/types/webgl-query.d.ts +7 -0
- package/lib/types/webgl-renderbuffer.d.ts +4 -5
- package/lib/types/webgl-rendering-context.d.ts +15 -12
- package/lib/types/webgl-sampler.d.ts +7 -0
- package/lib/types/webgl-shader-precision-format.d.ts +1 -2
- package/lib/types/webgl-shader.d.ts +4 -5
- package/lib/types/webgl-sync.d.ts +7 -0
- package/lib/types/webgl-texture-unit.d.ts +3 -3
- package/lib/types/webgl-texture.d.ts +6 -7
- package/lib/types/webgl-transform-feedback.d.ts +7 -0
- package/lib/types/webgl-uniform-location.d.ts +3 -4
- package/lib/types/webgl-vertex-array-object.d.ts +9 -0
- package/lib/types/webgl-vertex-attribute.d.ts +5 -5
- package/lib/types/webgl2-rendering-context.d.ts +124 -0
- package/package.json +27 -26
- package/prebuilds/linux-aarch64/Gwebgl-0.1.typelib +0 -0
- package/prebuilds/linux-aarch64/libgwebgl.so +0 -0
- package/prebuilds/linux-x86_64/Gwebgl-0.1.typelib +0 -0
- package/prebuilds/linux-x86_64/libgwebgl.so +0 -0
- package/lib/cjs/@types/glsl-tokenizer/index.d.js +0 -0
- package/lib/cjs/extensions/ext-blend-minmax.js +0 -18
- package/lib/cjs/extensions/ext-texture-filter-anisotropic.js +0 -18
- package/lib/cjs/extensions/oes-element-index-unit.js +0 -14
- package/lib/cjs/extensions/oes-standard-derivatives.js +0 -17
- package/lib/cjs/extensions/oes-texture-float-linear.js +0 -14
- package/lib/cjs/extensions/oes-texture-float.js +0 -14
- package/lib/cjs/extensions/stackgl-destroy-context.js +0 -12
- package/lib/cjs/extensions/stackgl-resize-drawing-buffer.js +0 -12
- package/lib/cjs/html-canvas-element.js +0 -70
- package/lib/cjs/index.js +0 -18
- package/lib/cjs/index.spec.js +0 -146
- package/lib/cjs/linkable.js +0 -50
- package/lib/cjs/test.js +0 -3
- package/lib/cjs/types/constructor.js +0 -0
- package/lib/cjs/types/extension.js +0 -0
- package/lib/cjs/types/index.js +0 -5
- package/lib/cjs/types/typed-array.js +0 -0
- package/lib/cjs/types/webgl-constants.js +0 -0
- package/lib/cjs/types/webgl-context-attribute-options.js +0 -0
- package/lib/cjs/utils.js +0 -212
- package/lib/cjs/webgl-active-info.js +0 -10
- package/lib/cjs/webgl-buffer.js +0 -18
- package/lib/cjs/webgl-context-attributes.js +0 -24
- package/lib/cjs/webgl-drawing-buffer-wrapper.js +0 -10
- package/lib/cjs/webgl-framebuffer.js +0 -109
- package/lib/cjs/webgl-program.js +0 -26
- package/lib/cjs/webgl-renderbuffer.js +0 -24
- package/lib/cjs/webgl-rendering-context.js +0 -3343
- package/lib/cjs/webgl-shader-precision-format.js +0 -11
- package/lib/cjs/webgl-shader.js +0 -23
- package/lib/cjs/webgl-texture-unit.js +0 -12
- package/lib/cjs/webgl-texture.js +0 -22
- package/lib/cjs/webgl-uniform-location.js +0 -15
- package/lib/cjs/webgl-vertex-attribute.js +0 -147
- package/meson.build +0 -39
- package/src/test/app.vala +0 -60
- package/src/ts/@types/glsl-tokenizer/index.d.ts +0 -18
- package/src/ts/extensions/angle-instanced-arrays.ts.off +0 -232
- package/src/ts/extensions/ext-blend-minmax.ts +0 -18
- package/src/ts/extensions/ext-texture-filter-anisotropic.ts +0 -18
- package/src/ts/extensions/oes-element-index-unit.ts +0 -14
- package/src/ts/extensions/oes-standard-derivatives.ts +0 -17
- package/src/ts/extensions/oes-texture-float-linear.ts +0 -14
- package/src/ts/extensions/oes-texture-float.ts +0 -14
- package/src/ts/extensions/oes-vertex-array-object.ts.off +0 -128
- package/src/ts/extensions/stackgl-destroy-context.ts +0 -12
- package/src/ts/extensions/stackgl-resize-drawing-buffer.ts +0 -14
- package/src/ts/extensions/webgl-draw-buffers.ts.off +0 -107
- package/src/ts/html-canvas-element.ts +0 -98
- package/src/ts/index.spec.ts +0 -186
- package/src/ts/index.ts +0 -21
- package/src/ts/linkable.ts +0 -55
- package/src/ts/test.ts +0 -6
- package/src/ts/types/constructor.ts +0 -3
- package/src/ts/types/extension.ts +0 -3
- package/src/ts/types/index.ts +0 -26
- package/src/ts/types/typed-array.ts +0 -1
- package/src/ts/types/webgl-constants.ts +0 -300
- package/src/ts/types/webgl-context-attribute-options.ts +0 -12
- package/src/ts/utils.ts +0 -266
- package/src/ts/webgl-active-info.ts +0 -13
- package/src/ts/webgl-buffer.ts +0 -21
- package/src/ts/webgl-context-attributes.ts +0 -24
- package/src/ts/webgl-drawing-buffer-wrapper.ts +0 -10
- package/src/ts/webgl-framebuffer.ts +0 -133
- package/src/ts/webgl-program.ts +0 -30
- package/src/ts/webgl-renderbuffer.ts +0 -28
- package/src/ts/webgl-rendering-context.ts +0 -4050
- package/src/ts/webgl-shader-precision-format.ts +0 -12
- package/src/ts/webgl-shader.ts +0 -29
- package/src/ts/webgl-texture-unit.ts +0 -16
- package/src/ts/webgl-texture.ts +0 -27
- package/src/ts/webgl-uniform-location.ts +0 -18
- package/src/ts/webgl-vertex-attribute.ts +0 -169
- package/src/vala/handle-types.vala +0 -23
- package/src/vala/webgl-rendering-context-base.vala +0 -1265
- package/src/vala/webgl-rendering-context.vala +0 -265
- package/src/vapi/epoxy.vapi +0 -14558
- package/src/vapi/glesv2.vapi +0 -670
- package/test.gjs.js +0 -39972
- package/test.gjs.js.meta.json +0 -1
- package/tmp/.tsbuildinfo +0 -1
- package/tsconfig.json +0 -38
- package/tsconfig.types.json +0 -7
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, on } from "@gjsify/unit";
|
|
2
|
+
import { WebGL2RenderingContext as OurWebGL2RenderingContext, CanvasWebGLWidget } from "@gjsify/webgl";
|
|
3
|
+
import {
|
|
4
|
+
makeProgram,
|
|
5
|
+
drawTriangle,
|
|
6
|
+
readPixel,
|
|
7
|
+
makeTestFBO,
|
|
8
|
+
destroyTestFBO
|
|
9
|
+
} from "./test-utils.js";
|
|
10
|
+
import GLib from "@girs/glib-2.0";
|
|
11
|
+
import Gtk from "@girs/gtk-4.0";
|
|
12
|
+
var webgl2_spec_default = async () => {
|
|
13
|
+
await on("Display", async () => {
|
|
14
|
+
Gtk.init();
|
|
15
|
+
let glArea;
|
|
16
|
+
let gl2;
|
|
17
|
+
const readyLoop = new GLib.MainLoop(null, false);
|
|
18
|
+
const win = new Gtk.Window({});
|
|
19
|
+
win.set_default_size(200, 200);
|
|
20
|
+
glArea = new CanvasWebGLWidget();
|
|
21
|
+
glArea.onReady((c, _g) => {
|
|
22
|
+
gl2 = c.getContext("webgl2");
|
|
23
|
+
readyLoop.quit();
|
|
24
|
+
});
|
|
25
|
+
win.set_child(glArea);
|
|
26
|
+
win.present();
|
|
27
|
+
const giveUpId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1e4, () => {
|
|
28
|
+
readyLoop.quit();
|
|
29
|
+
return GLib.SOURCE_REMOVE;
|
|
30
|
+
});
|
|
31
|
+
readyLoop.run();
|
|
32
|
+
GLib.source_remove(giveUpId);
|
|
33
|
+
if (!gl2) {
|
|
34
|
+
console.warn("WebGL2 context not available \u2014 skipping WebGL2 tests");
|
|
35
|
+
win.destroy();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
glArea.make_current();
|
|
39
|
+
await describe("WebGL2 context", async () => {
|
|
40
|
+
beforeEach(async () => {
|
|
41
|
+
glArea.make_current();
|
|
42
|
+
});
|
|
43
|
+
await it('getContext("webgl2") returns a WebGL2RenderingContext', async () => {
|
|
44
|
+
expect(gl2).toBeInstanceOf(OurWebGL2RenderingContext);
|
|
45
|
+
});
|
|
46
|
+
await it('VERSION is "WebGL 2.0"', async () => {
|
|
47
|
+
expect(gl2.getParameter(gl2.VERSION)).toBe("WebGL 2.0");
|
|
48
|
+
});
|
|
49
|
+
await it('SHADING_LANGUAGE_VERSION is "WebGL GLSL ES 3.00"', async () => {
|
|
50
|
+
expect(gl2.getParameter(gl2.SHADING_LANGUAGE_VERSION)).toBe("WebGL GLSL ES 3.00");
|
|
51
|
+
});
|
|
52
|
+
await it("drawingBufferWidth and drawingBufferHeight are positive", async () => {
|
|
53
|
+
expect(gl2.drawingBufferWidth > 0).toBeTruthy();
|
|
54
|
+
expect(gl2.drawingBufferHeight > 0).toBeTruthy();
|
|
55
|
+
});
|
|
56
|
+
await it("getError() returns NO_ERROR initially", async () => {
|
|
57
|
+
expect(gl2.getError()).toBe(gl2.NO_ERROR);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
await describe("GLSL ES 3.00 compilation", async () => {
|
|
61
|
+
beforeEach(async () => {
|
|
62
|
+
glArea.make_current();
|
|
63
|
+
});
|
|
64
|
+
const VS300 = [
|
|
65
|
+
"#version 300 es",
|
|
66
|
+
"in vec2 position;",
|
|
67
|
+
"void main() { gl_Position = vec4(position, 0.0, 1.0); }"
|
|
68
|
+
].join("\n");
|
|
69
|
+
const FS300 = [
|
|
70
|
+
"#version 300 es",
|
|
71
|
+
"precision mediump float;",
|
|
72
|
+
"out vec4 fragColor;",
|
|
73
|
+
"void main() { fragColor = vec4(0.0, 1.0, 0.0, 1.0); }"
|
|
74
|
+
].join("\n");
|
|
75
|
+
await it("#version 300 es vertex shader compiles", async () => {
|
|
76
|
+
const sh = gl2.createShader(gl2.VERTEX_SHADER);
|
|
77
|
+
gl2.shaderSource(sh, VS300);
|
|
78
|
+
gl2.compileShader(sh);
|
|
79
|
+
if (!gl2.getShaderParameter(sh, gl2.COMPILE_STATUS)) {
|
|
80
|
+
console.error("VS300 log:", gl2.getShaderInfoLog(sh));
|
|
81
|
+
}
|
|
82
|
+
expect(gl2.getShaderParameter(sh, gl2.COMPILE_STATUS)).toBeTruthy();
|
|
83
|
+
gl2.deleteShader(sh);
|
|
84
|
+
});
|
|
85
|
+
await it("#version 300 es fragment shader compiles", async () => {
|
|
86
|
+
const sh = gl2.createShader(gl2.FRAGMENT_SHADER);
|
|
87
|
+
gl2.shaderSource(sh, FS300);
|
|
88
|
+
gl2.compileShader(sh);
|
|
89
|
+
if (!gl2.getShaderParameter(sh, gl2.COMPILE_STATUS)) {
|
|
90
|
+
console.error("FS300 log:", gl2.getShaderInfoLog(sh));
|
|
91
|
+
}
|
|
92
|
+
expect(gl2.getShaderParameter(sh, gl2.COMPILE_STATUS)).toBeTruthy();
|
|
93
|
+
gl2.deleteShader(sh);
|
|
94
|
+
});
|
|
95
|
+
await it("#version 300 es program links and renders green", async () => {
|
|
96
|
+
const prog = makeProgram(gl2, VS300, FS300);
|
|
97
|
+
if (!gl2.getProgramParameter(prog, gl2.LINK_STATUS)) {
|
|
98
|
+
console.error("Program300 log:", gl2.getProgramInfoLog(prog));
|
|
99
|
+
}
|
|
100
|
+
expect(gl2.getProgramParameter(prog, gl2.LINK_STATUS)).toBeTruthy();
|
|
101
|
+
const fbo = makeTestFBO(gl2, 4, 4);
|
|
102
|
+
gl2.clearColor(0, 0, 0, 1);
|
|
103
|
+
gl2.clear(gl2.COLOR_BUFFER_BIT);
|
|
104
|
+
gl2.useProgram(prog);
|
|
105
|
+
drawTriangle(gl2);
|
|
106
|
+
expect(gl2.getError()).toBe(gl2.NO_ERROR);
|
|
107
|
+
const p = readPixel(gl2, 0, 0);
|
|
108
|
+
destroyTestFBO(gl2, fbo);
|
|
109
|
+
expect(p[0]).toBe(0);
|
|
110
|
+
expect(p[1]).toBe(255);
|
|
111
|
+
expect(p[2]).toBe(0);
|
|
112
|
+
expect(p[3]).toBe(255);
|
|
113
|
+
gl2.deleteProgram(prog);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
await describe("VAO", async () => {
|
|
117
|
+
beforeEach(async () => {
|
|
118
|
+
glArea.make_current();
|
|
119
|
+
});
|
|
120
|
+
await it("createVertexArray returns a non-null object", async () => {
|
|
121
|
+
const vao = gl2.createVertexArray();
|
|
122
|
+
expect(vao).not.toBeNull();
|
|
123
|
+
expect(vao).toBeDefined();
|
|
124
|
+
gl2.deleteVertexArray(vao);
|
|
125
|
+
});
|
|
126
|
+
await it("isVertexArray is true after creation, false after deletion", async () => {
|
|
127
|
+
const vao = gl2.createVertexArray();
|
|
128
|
+
gl2.bindVertexArray(vao);
|
|
129
|
+
expect(gl2.isVertexArray(vao)).toBeTruthy();
|
|
130
|
+
gl2.bindVertexArray(null);
|
|
131
|
+
gl2.deleteVertexArray(vao);
|
|
132
|
+
expect(gl2.isVertexArray(vao)).toBeFalsy();
|
|
133
|
+
});
|
|
134
|
+
await it("VAO preserves vertex attribute state", async () => {
|
|
135
|
+
const VS = [
|
|
136
|
+
"#version 300 es",
|
|
137
|
+
"in vec2 position;",
|
|
138
|
+
"void main() { gl_Position = vec4(position,0.0,1.0); }"
|
|
139
|
+
].join("\n");
|
|
140
|
+
const FS = [
|
|
141
|
+
"#version 300 es",
|
|
142
|
+
"precision mediump float;",
|
|
143
|
+
"out vec4 c;",
|
|
144
|
+
"void main() { c = vec4(0.0,1.0,0.0,1.0); }"
|
|
145
|
+
].join("\n");
|
|
146
|
+
const prog = makeProgram(gl2, VS, FS);
|
|
147
|
+
gl2.useProgram(prog);
|
|
148
|
+
const fbo = makeTestFBO(gl2, 4, 4);
|
|
149
|
+
const vao = gl2.createVertexArray();
|
|
150
|
+
gl2.bindVertexArray(vao);
|
|
151
|
+
const buf = gl2.createBuffer();
|
|
152
|
+
gl2.bindBuffer(gl2.ARRAY_BUFFER, buf);
|
|
153
|
+
gl2.bufferData(gl2.ARRAY_BUFFER, new Float32Array([-2, -2, -2, 4, 4, -2]), gl2.STREAM_DRAW);
|
|
154
|
+
gl2.enableVertexAttribArray(0);
|
|
155
|
+
gl2.vertexAttribPointer(0, 2, gl2.FLOAT, false, 0, 0);
|
|
156
|
+
gl2.bindVertexArray(null);
|
|
157
|
+
gl2.bindVertexArray(vao);
|
|
158
|
+
gl2.clearColor(0, 0, 0, 1);
|
|
159
|
+
gl2.clear(gl2.COLOR_BUFFER_BIT);
|
|
160
|
+
gl2.drawArrays(gl2.TRIANGLES, 0, 3);
|
|
161
|
+
expect(gl2.getError()).toBe(gl2.NO_ERROR);
|
|
162
|
+
const p = readPixel(gl2, 0, 0);
|
|
163
|
+
destroyTestFBO(gl2, fbo);
|
|
164
|
+
expect(p[1]).toBe(255);
|
|
165
|
+
gl2.bindVertexArray(null);
|
|
166
|
+
gl2.deleteVertexArray(vao);
|
|
167
|
+
gl2.deleteBuffer(buf);
|
|
168
|
+
gl2.deleteProgram(prog);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
await describe("getBufferSubData", async () => {
|
|
172
|
+
beforeEach(async () => {
|
|
173
|
+
glArea.make_current();
|
|
174
|
+
});
|
|
175
|
+
await it("reads back float data written with bufferData", async () => {
|
|
176
|
+
const src = new Float32Array([1, 2, 3, 4]);
|
|
177
|
+
const buf = gl2.createBuffer();
|
|
178
|
+
gl2.bindBuffer(gl2.ARRAY_BUFFER, buf);
|
|
179
|
+
gl2.bufferData(gl2.ARRAY_BUFFER, src, gl2.STATIC_READ);
|
|
180
|
+
const dst = new Float32Array(4);
|
|
181
|
+
gl2.getBufferSubData(gl2.ARRAY_BUFFER, 0, dst);
|
|
182
|
+
expect(gl2.getError()).toBe(gl2.NO_ERROR);
|
|
183
|
+
expect(dst[0]).toBe(1);
|
|
184
|
+
expect(dst[1]).toBe(2);
|
|
185
|
+
expect(dst[2]).toBe(3);
|
|
186
|
+
expect(dst[3]).toBe(4);
|
|
187
|
+
gl2.deleteBuffer(buf);
|
|
188
|
+
});
|
|
189
|
+
await it("reads a sub-range correctly", async () => {
|
|
190
|
+
const src = new Float32Array([10, 20, 30, 40]);
|
|
191
|
+
const buf = gl2.createBuffer();
|
|
192
|
+
gl2.bindBuffer(gl2.ARRAY_BUFFER, buf);
|
|
193
|
+
gl2.bufferData(gl2.ARRAY_BUFFER, src, gl2.STATIC_READ);
|
|
194
|
+
const dst = new Float32Array(2);
|
|
195
|
+
gl2.getBufferSubData(gl2.ARRAY_BUFFER, 8, dst);
|
|
196
|
+
expect(dst[0]).toBe(30);
|
|
197
|
+
expect(dst[1]).toBe(40);
|
|
198
|
+
gl2.deleteBuffer(buf);
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
await describe("sync objects", async () => {
|
|
202
|
+
beforeEach(async () => {
|
|
203
|
+
glArea.make_current();
|
|
204
|
+
});
|
|
205
|
+
await it("fenceSync returns a non-null sync", async () => {
|
|
206
|
+
const sync = gl2.fenceSync(gl2.SYNC_GPU_COMMANDS_COMPLETE, 0);
|
|
207
|
+
expect(sync).not.toBeNull();
|
|
208
|
+
gl2.deleteSync(sync);
|
|
209
|
+
expect(gl2.getError()).toBe(gl2.NO_ERROR);
|
|
210
|
+
});
|
|
211
|
+
await it("isSync is true before deletion, false after", async () => {
|
|
212
|
+
const sync = gl2.fenceSync(gl2.SYNC_GPU_COMMANDS_COMPLETE, 0);
|
|
213
|
+
expect(gl2.isSync(sync)).toBeTruthy();
|
|
214
|
+
gl2.deleteSync(sync);
|
|
215
|
+
expect(gl2.isSync(sync)).toBeFalsy();
|
|
216
|
+
});
|
|
217
|
+
await it("clientWaitSync returns TIMEOUT_EXPIRED or CONDITION_SATISFIED", async () => {
|
|
218
|
+
const sync = gl2.fenceSync(gl2.SYNC_GPU_COMMANDS_COMPLETE, 0);
|
|
219
|
+
gl2.flush();
|
|
220
|
+
const result = gl2.clientWaitSync(sync, 0, 0);
|
|
221
|
+
const valid = result === gl2.TIMEOUT_EXPIRED || result === gl2.CONDITION_SATISFIED || result === gl2.ALREADY_SIGNALED;
|
|
222
|
+
expect(valid).toBeTruthy();
|
|
223
|
+
gl2.deleteSync(sync);
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
await describe("uint uniforms", async () => {
|
|
227
|
+
beforeEach(async () => {
|
|
228
|
+
glArea.make_current();
|
|
229
|
+
});
|
|
230
|
+
const VS_U = [
|
|
231
|
+
"#version 300 es",
|
|
232
|
+
"in vec2 position;",
|
|
233
|
+
"void main() { gl_Position = vec4(position,0.0,1.0); }"
|
|
234
|
+
].join("\n");
|
|
235
|
+
const FS_U = [
|
|
236
|
+
"#version 300 es",
|
|
237
|
+
"precision mediump float;",
|
|
238
|
+
"uniform uint uR; uniform uint uG; uniform uint uB;",
|
|
239
|
+
"out vec4 c;",
|
|
240
|
+
"void main() { c = vec4(float(uR)/255.0, float(uG)/255.0, float(uB)/255.0, 1.0); }"
|
|
241
|
+
].join("\n");
|
|
242
|
+
await it("uniform1ui sets an unsigned int uniform", async () => {
|
|
243
|
+
const prog = makeProgram(gl2, VS_U, FS_U);
|
|
244
|
+
expect(gl2.getProgramParameter(prog, gl2.LINK_STATUS)).toBeTruthy();
|
|
245
|
+
gl2.useProgram(prog);
|
|
246
|
+
const locR = gl2.getUniformLocation(prog, "uR");
|
|
247
|
+
const locG = gl2.getUniformLocation(prog, "uG");
|
|
248
|
+
const locB = gl2.getUniformLocation(prog, "uB");
|
|
249
|
+
gl2.uniform1ui(locR, 0);
|
|
250
|
+
gl2.uniform1ui(locG, 255);
|
|
251
|
+
gl2.uniform1ui(locB, 0);
|
|
252
|
+
expect(gl2.getError()).toBe(gl2.NO_ERROR);
|
|
253
|
+
expect(gl2.getUniform(prog, locR)).toBe(0);
|
|
254
|
+
expect(gl2.getUniform(prog, locG)).toBe(255);
|
|
255
|
+
gl2.deleteProgram(prog);
|
|
256
|
+
});
|
|
257
|
+
await it("uniform2ui, uniform3ui, uniform4ui set without error", async () => {
|
|
258
|
+
const FS2 = [
|
|
259
|
+
"#version 300 es",
|
|
260
|
+
"precision mediump float;",
|
|
261
|
+
"uniform uvec2 u2; uniform uvec3 u3; uniform uvec4 u4;",
|
|
262
|
+
"out vec4 c;",
|
|
263
|
+
"void main() { c = vec4(float(u2.x), float(u3.x), float(u4.x), 1.0)/255.0; }"
|
|
264
|
+
].join("\n");
|
|
265
|
+
const prog = makeProgram(gl2, VS_U, FS2);
|
|
266
|
+
gl2.useProgram(prog);
|
|
267
|
+
gl2.uniform2ui(gl2.getUniformLocation(prog, "u2"), 1, 2);
|
|
268
|
+
gl2.uniform3ui(gl2.getUniformLocation(prog, "u3"), 1, 2, 3);
|
|
269
|
+
gl2.uniform4ui(gl2.getUniformLocation(prog, "u4"), 1, 2, 3, 4);
|
|
270
|
+
expect(gl2.getError()).toBe(gl2.NO_ERROR);
|
|
271
|
+
gl2.deleteProgram(prog);
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
await describe("non-square matrix uniforms", async () => {
|
|
275
|
+
beforeEach(async () => {
|
|
276
|
+
glArea.make_current();
|
|
277
|
+
});
|
|
278
|
+
const VS_M = [
|
|
279
|
+
"#version 300 es",
|
|
280
|
+
"in vec2 position;",
|
|
281
|
+
"void main() { gl_Position = vec4(position,0.0,1.0); }"
|
|
282
|
+
].join("\n");
|
|
283
|
+
await it("uniformMatrix2x3fv sets a mat2x3 without error", async () => {
|
|
284
|
+
const FS = [
|
|
285
|
+
"#version 300 es",
|
|
286
|
+
"precision mediump float;",
|
|
287
|
+
"uniform mat2x3 m; out vec4 c;",
|
|
288
|
+
"void main() { c = vec4(m[0][0], m[0][1], m[0][2], 1.0); }"
|
|
289
|
+
].join("\n");
|
|
290
|
+
const prog = makeProgram(gl2, VS_M, FS);
|
|
291
|
+
gl2.useProgram(prog);
|
|
292
|
+
gl2.uniformMatrix2x3fv(
|
|
293
|
+
gl2.getUniformLocation(prog, "m"),
|
|
294
|
+
false,
|
|
295
|
+
new Float32Array([1, 0, 0, 0, 1, 0])
|
|
296
|
+
);
|
|
297
|
+
expect(gl2.getError()).toBe(gl2.NO_ERROR);
|
|
298
|
+
gl2.deleteProgram(prog);
|
|
299
|
+
});
|
|
300
|
+
await it("uniformMatrix3x2fv sets a mat3x2 without error", async () => {
|
|
301
|
+
const FS = [
|
|
302
|
+
"#version 300 es",
|
|
303
|
+
"precision mediump float;",
|
|
304
|
+
"uniform mat3x2 m; out vec4 c;",
|
|
305
|
+
"void main() { c = vec4(m[0][0], m[0][1], 0.0, 1.0); }"
|
|
306
|
+
].join("\n");
|
|
307
|
+
const prog = makeProgram(gl2, VS_M, FS);
|
|
308
|
+
gl2.useProgram(prog);
|
|
309
|
+
gl2.uniformMatrix3x2fv(
|
|
310
|
+
gl2.getUniformLocation(prog, "m"),
|
|
311
|
+
false,
|
|
312
|
+
new Float32Array([1, 0, 0, 1, 0, 0])
|
|
313
|
+
);
|
|
314
|
+
expect(gl2.getError()).toBe(gl2.NO_ERROR);
|
|
315
|
+
gl2.deleteProgram(prog);
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
await describe("Uniform Buffer Objects", async () => {
|
|
319
|
+
beforeEach(async () => {
|
|
320
|
+
glArea.make_current();
|
|
321
|
+
});
|
|
322
|
+
await it("getUniformBlockIndex + uniformBlockBinding works", async () => {
|
|
323
|
+
const VS = [
|
|
324
|
+
"#version 300 es",
|
|
325
|
+
"layout(std140) uniform Params { vec4 color; };",
|
|
326
|
+
"in vec2 position;",
|
|
327
|
+
"out vec4 vColor;",
|
|
328
|
+
"void main() { vColor = color; gl_Position = vec4(position,0.0,1.0); }"
|
|
329
|
+
].join("\n");
|
|
330
|
+
const FS = [
|
|
331
|
+
"#version 300 es",
|
|
332
|
+
"precision mediump float;",
|
|
333
|
+
"in vec4 vColor; out vec4 c;",
|
|
334
|
+
"void main() { c = vColor; }"
|
|
335
|
+
].join("\n");
|
|
336
|
+
const prog = makeProgram(gl2, VS, FS);
|
|
337
|
+
expect(gl2.getProgramParameter(prog, gl2.LINK_STATUS)).toBeTruthy();
|
|
338
|
+
const idx = gl2.getUniformBlockIndex(prog, "Params");
|
|
339
|
+
expect(idx).not.toBe(gl2.INVALID_INDEX);
|
|
340
|
+
gl2.uniformBlockBinding(prog, idx, 0);
|
|
341
|
+
expect(gl2.getError()).toBe(gl2.NO_ERROR);
|
|
342
|
+
const ubo = gl2.createBuffer();
|
|
343
|
+
gl2.bindBuffer(gl2.UNIFORM_BUFFER, ubo);
|
|
344
|
+
gl2.bufferData(gl2.UNIFORM_BUFFER, new Float32Array([0, 1, 0, 1]), gl2.STATIC_DRAW);
|
|
345
|
+
gl2.bindBufferBase(gl2.UNIFORM_BUFFER, 0, ubo);
|
|
346
|
+
const fbo = makeTestFBO(gl2, 4, 4);
|
|
347
|
+
gl2.useProgram(prog);
|
|
348
|
+
gl2.clearColor(0, 0, 0, 1);
|
|
349
|
+
gl2.clear(gl2.COLOR_BUFFER_BIT);
|
|
350
|
+
drawTriangle(gl2);
|
|
351
|
+
expect(gl2.getError()).toBe(gl2.NO_ERROR);
|
|
352
|
+
const p = readPixel(gl2, 0, 0);
|
|
353
|
+
destroyTestFBO(gl2, fbo);
|
|
354
|
+
expect(p[1]).toBe(255);
|
|
355
|
+
gl2.deleteBuffer(ubo);
|
|
356
|
+
gl2.deleteProgram(prog);
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
await describe("instanced drawing", async () => {
|
|
360
|
+
beforeEach(async () => {
|
|
361
|
+
glArea.make_current();
|
|
362
|
+
});
|
|
363
|
+
await it("drawArraysInstanced renders without error", async () => {
|
|
364
|
+
const VS = [
|
|
365
|
+
"#version 300 es",
|
|
366
|
+
"in vec2 position;",
|
|
367
|
+
"void main() { gl_Position = vec4(position,0.0,1.0); }"
|
|
368
|
+
].join("\n");
|
|
369
|
+
const FS = [
|
|
370
|
+
"#version 300 es",
|
|
371
|
+
"precision mediump float;",
|
|
372
|
+
"out vec4 c;",
|
|
373
|
+
"void main() { c = vec4(0.0,1.0,0.0,1.0); }"
|
|
374
|
+
].join("\n");
|
|
375
|
+
const prog = makeProgram(gl2, VS, FS);
|
|
376
|
+
gl2.useProgram(prog);
|
|
377
|
+
const fbo = makeTestFBO(gl2, 4, 4);
|
|
378
|
+
const buf = gl2.createBuffer();
|
|
379
|
+
gl2.bindBuffer(gl2.ARRAY_BUFFER, buf);
|
|
380
|
+
gl2.bufferData(gl2.ARRAY_BUFFER, new Float32Array([-2, -2, -2, 4, 4, -2]), gl2.STREAM_DRAW);
|
|
381
|
+
gl2.enableVertexAttribArray(0);
|
|
382
|
+
gl2.vertexAttribPointer(0, 2, gl2.FLOAT, false, 0, 0);
|
|
383
|
+
gl2.vertexAttribDivisor(0, 0);
|
|
384
|
+
gl2.clearColor(0, 0, 0, 1);
|
|
385
|
+
gl2.clear(gl2.COLOR_BUFFER_BIT);
|
|
386
|
+
gl2.drawArraysInstanced(gl2.TRIANGLES, 0, 3, 1);
|
|
387
|
+
expect(gl2.getError()).toBe(gl2.NO_ERROR);
|
|
388
|
+
const p = readPixel(gl2, 0, 0);
|
|
389
|
+
destroyTestFBO(gl2, fbo);
|
|
390
|
+
expect(p[1]).toBe(255);
|
|
391
|
+
gl2.disableVertexAttribArray(0);
|
|
392
|
+
gl2.deleteBuffer(buf);
|
|
393
|
+
gl2.deleteProgram(prog);
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
await describe("drawBuffers (MRT)", async () => {
|
|
397
|
+
beforeEach(async () => {
|
|
398
|
+
glArea.make_current();
|
|
399
|
+
});
|
|
400
|
+
await it("drawBuffers with 2 COLOR_ATTACHMENTs renders to both", async () => {
|
|
401
|
+
const VS = [
|
|
402
|
+
"#version 300 es",
|
|
403
|
+
"in vec2 position;",
|
|
404
|
+
"void main() { gl_Position = vec4(position,0.0,1.0); }"
|
|
405
|
+
].join("\n");
|
|
406
|
+
const FS = [
|
|
407
|
+
"#version 300 es",
|
|
408
|
+
"precision mediump float;",
|
|
409
|
+
"layout(location=0) out vec4 c0;",
|
|
410
|
+
"layout(location=1) out vec4 c1;",
|
|
411
|
+
"void main() { c0 = vec4(1.0,0.0,0.0,1.0); c1 = vec4(0.0,0.0,1.0,1.0); }"
|
|
412
|
+
].join("\n");
|
|
413
|
+
const prog = makeProgram(gl2, VS, FS);
|
|
414
|
+
expect(gl2.getProgramParameter(prog, gl2.LINK_STATUS)).toBeTruthy();
|
|
415
|
+
const fb = gl2.createFramebuffer();
|
|
416
|
+
gl2.bindFramebuffer(gl2.FRAMEBUFFER, fb);
|
|
417
|
+
const tex0 = gl2.createTexture();
|
|
418
|
+
gl2.bindTexture(gl2.TEXTURE_2D, tex0);
|
|
419
|
+
gl2.texImage2D(gl2.TEXTURE_2D, 0, gl2.RGBA, 4, 4, 0, gl2.RGBA, gl2.UNSIGNED_BYTE, null);
|
|
420
|
+
gl2.framebufferTexture2D(gl2.FRAMEBUFFER, gl2.COLOR_ATTACHMENT0, gl2.TEXTURE_2D, tex0, 0);
|
|
421
|
+
const tex1 = gl2.createTexture();
|
|
422
|
+
gl2.bindTexture(gl2.TEXTURE_2D, tex1);
|
|
423
|
+
gl2.texImage2D(gl2.TEXTURE_2D, 0, gl2.RGBA, 4, 4, 0, gl2.RGBA, gl2.UNSIGNED_BYTE, null);
|
|
424
|
+
gl2.framebufferTexture2D(gl2.FRAMEBUFFER, gl2.COLOR_ATTACHMENT1, gl2.TEXTURE_2D, tex1, 0);
|
|
425
|
+
const status = gl2.checkFramebufferStatus(gl2.FRAMEBUFFER);
|
|
426
|
+
if (status !== gl2.FRAMEBUFFER_COMPLETE) {
|
|
427
|
+
console.warn("MRT framebuffer not complete:", status);
|
|
428
|
+
gl2.bindFramebuffer(gl2.FRAMEBUFFER, null);
|
|
429
|
+
gl2.deleteFramebuffer(fb);
|
|
430
|
+
gl2.deleteTexture(tex0);
|
|
431
|
+
gl2.deleteTexture(tex1);
|
|
432
|
+
gl2.deleteProgram(prog);
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
gl2.drawBuffers([gl2.COLOR_ATTACHMENT0, gl2.COLOR_ATTACHMENT1]);
|
|
436
|
+
gl2.viewport(0, 0, 4, 4);
|
|
437
|
+
gl2.clearColor(0, 0, 0, 1);
|
|
438
|
+
gl2.clear(gl2.COLOR_BUFFER_BIT);
|
|
439
|
+
gl2.useProgram(prog);
|
|
440
|
+
drawTriangle(gl2);
|
|
441
|
+
expect(gl2.getError()).toBe(gl2.NO_ERROR);
|
|
442
|
+
gl2.readBuffer(gl2.COLOR_ATTACHMENT0);
|
|
443
|
+
const p0 = readPixel(gl2, 0, 0);
|
|
444
|
+
expect(p0[0]).toBe(255);
|
|
445
|
+
expect(p0[1]).toBe(0);
|
|
446
|
+
gl2.readBuffer(gl2.COLOR_ATTACHMENT1);
|
|
447
|
+
const p1 = readPixel(gl2, 0, 0);
|
|
448
|
+
expect(p1[0]).toBe(0);
|
|
449
|
+
expect(p1[2]).toBe(255);
|
|
450
|
+
gl2.bindFramebuffer(gl2.FRAMEBUFFER, null);
|
|
451
|
+
gl2.deleteFramebuffer(fb);
|
|
452
|
+
gl2.deleteTexture(tex0);
|
|
453
|
+
gl2.deleteTexture(tex1);
|
|
454
|
+
gl2.deleteProgram(prog);
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
await describe("3D texture", async () => {
|
|
458
|
+
beforeEach(async () => {
|
|
459
|
+
glArea.make_current();
|
|
460
|
+
});
|
|
461
|
+
await it("createTexture + TEXTURE_3D binding works", async () => {
|
|
462
|
+
const tex = gl2.createTexture();
|
|
463
|
+
expect(tex).not.toBeNull();
|
|
464
|
+
gl2.bindTexture(gl2.TEXTURE_3D, tex);
|
|
465
|
+
expect(gl2.getError()).toBe(gl2.NO_ERROR);
|
|
466
|
+
gl2.deleteTexture(tex);
|
|
467
|
+
});
|
|
468
|
+
await it("texImage3D uploads a 2\xD72\xD72 RGBA texture without error", async () => {
|
|
469
|
+
const tex = gl2.createTexture();
|
|
470
|
+
gl2.bindTexture(gl2.TEXTURE_3D, tex);
|
|
471
|
+
gl2.texParameteri(gl2.TEXTURE_3D, gl2.TEXTURE_MIN_FILTER, gl2.NEAREST);
|
|
472
|
+
gl2.texParameteri(gl2.TEXTURE_3D, gl2.TEXTURE_MAG_FILTER, gl2.NEAREST);
|
|
473
|
+
gl2.texParameteri(gl2.TEXTURE_3D, gl2.TEXTURE_WRAP_S, gl2.CLAMP_TO_EDGE);
|
|
474
|
+
gl2.texParameteri(gl2.TEXTURE_3D, gl2.TEXTURE_WRAP_T, gl2.CLAMP_TO_EDGE);
|
|
475
|
+
gl2.texParameteri(gl2.TEXTURE_3D, gl2.TEXTURE_WRAP_R, gl2.CLAMP_TO_EDGE);
|
|
476
|
+
const data = new Uint8Array(2 * 2 * 2 * 4).fill(128);
|
|
477
|
+
gl2.texImage3D(gl2.TEXTURE_3D, 0, gl2.RGBA, 2, 2, 2, 0, gl2.RGBA, gl2.UNSIGNED_BYTE, data);
|
|
478
|
+
expect(gl2.getError()).toBe(gl2.NO_ERROR);
|
|
479
|
+
gl2.deleteTexture(tex);
|
|
480
|
+
});
|
|
481
|
+
await it("texStorage3D allocates storage without error", async () => {
|
|
482
|
+
const tex = gl2.createTexture();
|
|
483
|
+
gl2.bindTexture(gl2.TEXTURE_3D, tex);
|
|
484
|
+
gl2.texStorage3D(gl2.TEXTURE_3D, 1, gl2.RGBA8, 4, 4, 4);
|
|
485
|
+
expect(gl2.getError()).toBe(gl2.NO_ERROR);
|
|
486
|
+
gl2.deleteTexture(tex);
|
|
487
|
+
});
|
|
488
|
+
});
|
|
489
|
+
await describe("transform feedback", async () => {
|
|
490
|
+
beforeEach(async () => {
|
|
491
|
+
glArea.make_current();
|
|
492
|
+
});
|
|
493
|
+
await it("captures vertex shader output via transform feedback", async () => {
|
|
494
|
+
const VS_TF = [
|
|
495
|
+
"#version 300 es",
|
|
496
|
+
"in float inVal;",
|
|
497
|
+
"out float outVal;",
|
|
498
|
+
"void main() { outVal = inVal * 2.0; gl_Position = vec4(0.0); }"
|
|
499
|
+
].join("\n");
|
|
500
|
+
const FS_TF = [
|
|
501
|
+
"#version 300 es",
|
|
502
|
+
"precision mediump float;",
|
|
503
|
+
"out vec4 c;",
|
|
504
|
+
"void main() { c = vec4(0.0); }"
|
|
505
|
+
].join("\n");
|
|
506
|
+
const vert = gl2.createShader(gl2.VERTEX_SHADER);
|
|
507
|
+
gl2.shaderSource(vert, VS_TF);
|
|
508
|
+
gl2.compileShader(vert);
|
|
509
|
+
if (!gl2.getShaderParameter(vert, gl2.COMPILE_STATUS)) {
|
|
510
|
+
console.error("TF VS:", gl2.getShaderInfoLog(vert));
|
|
511
|
+
}
|
|
512
|
+
const frag = gl2.createShader(gl2.FRAGMENT_SHADER);
|
|
513
|
+
gl2.shaderSource(frag, FS_TF);
|
|
514
|
+
gl2.compileShader(frag);
|
|
515
|
+
const prog = gl2.createProgram();
|
|
516
|
+
gl2.attachShader(prog, vert);
|
|
517
|
+
gl2.attachShader(prog, frag);
|
|
518
|
+
gl2.transformFeedbackVaryings(prog, ["outVal"], gl2.SEPARATE_ATTRIBS);
|
|
519
|
+
gl2.linkProgram(prog);
|
|
520
|
+
if (!gl2.getProgramParameter(prog, gl2.LINK_STATUS)) {
|
|
521
|
+
console.error("TF prog:", gl2.getProgramInfoLog(prog));
|
|
522
|
+
}
|
|
523
|
+
expect(gl2.getProgramParameter(prog, gl2.LINK_STATUS)).toBeTruthy();
|
|
524
|
+
const inBuf = gl2.createBuffer();
|
|
525
|
+
gl2.bindBuffer(gl2.ARRAY_BUFFER, inBuf);
|
|
526
|
+
gl2.bufferData(gl2.ARRAY_BUFFER, new Float32Array([1, 2, 3, 4]), gl2.STATIC_DRAW);
|
|
527
|
+
const attribLoc = gl2.getAttribLocation(prog, "inVal");
|
|
528
|
+
gl2.enableVertexAttribArray(attribLoc);
|
|
529
|
+
gl2.vertexAttribPointer(attribLoc, 1, gl2.FLOAT, false, 0, 0);
|
|
530
|
+
const outBuf = gl2.createBuffer();
|
|
531
|
+
gl2.bindBuffer(gl2.TRANSFORM_FEEDBACK_BUFFER, outBuf);
|
|
532
|
+
gl2.bufferData(gl2.TRANSFORM_FEEDBACK_BUFFER, 4 * 4, gl2.STATIC_READ);
|
|
533
|
+
const tf = gl2.createTransformFeedback();
|
|
534
|
+
gl2.bindTransformFeedback(gl2.TRANSFORM_FEEDBACK, tf);
|
|
535
|
+
gl2.bindBufferBase(gl2.TRANSFORM_FEEDBACK_BUFFER, 0, outBuf);
|
|
536
|
+
const fbo = makeTestFBO(gl2, 1, 1);
|
|
537
|
+
gl2.useProgram(prog);
|
|
538
|
+
gl2.enable(gl2.RASTERIZER_DISCARD);
|
|
539
|
+
gl2.beginTransformFeedback(gl2.POINTS);
|
|
540
|
+
gl2.drawArrays(gl2.POINTS, 0, 4);
|
|
541
|
+
gl2.endTransformFeedback();
|
|
542
|
+
gl2.disable(gl2.RASTERIZER_DISCARD);
|
|
543
|
+
expect(gl2.getError()).toBe(gl2.NO_ERROR);
|
|
544
|
+
gl2.bindTransformFeedback(gl2.TRANSFORM_FEEDBACK, null);
|
|
545
|
+
destroyTestFBO(gl2, fbo);
|
|
546
|
+
const result = new Float32Array(4);
|
|
547
|
+
gl2.bindBuffer(gl2.TRANSFORM_FEEDBACK_BUFFER, outBuf);
|
|
548
|
+
gl2.getBufferSubData(gl2.TRANSFORM_FEEDBACK_BUFFER, 0, result);
|
|
549
|
+
expect(result[0]).toBe(2);
|
|
550
|
+
expect(result[1]).toBe(4);
|
|
551
|
+
expect(result[2]).toBe(6);
|
|
552
|
+
expect(result[3]).toBe(8);
|
|
553
|
+
gl2.disableVertexAttribArray(attribLoc);
|
|
554
|
+
gl2.deleteBuffer(inBuf);
|
|
555
|
+
gl2.deleteBuffer(outBuf);
|
|
556
|
+
gl2.deleteTransformFeedback(tf);
|
|
557
|
+
gl2.deleteProgram(prog);
|
|
558
|
+
});
|
|
559
|
+
});
|
|
560
|
+
await describe("getStringi", async () => {
|
|
561
|
+
beforeEach(async () => {
|
|
562
|
+
glArea.make_current();
|
|
563
|
+
});
|
|
564
|
+
await it("getStringi(EXTENSIONS, 0) returns a string", async () => {
|
|
565
|
+
const numExts = gl2.getParameter(gl2.NUM_EXTENSIONS);
|
|
566
|
+
if (numExts > 0) {
|
|
567
|
+
const ext = gl2.getStringi(gl2.EXTENSIONS, 0);
|
|
568
|
+
expect(typeof ext).toBe("string");
|
|
569
|
+
expect(ext.length > 0).toBeTruthy();
|
|
570
|
+
}
|
|
571
|
+
});
|
|
572
|
+
});
|
|
573
|
+
win.destroy();
|
|
574
|
+
});
|
|
575
|
+
};
|
|
576
|
+
export {
|
|
577
|
+
webgl2_spec_default as default
|
|
578
|
+
};
|