@gjsify/webgl 0.3.16 → 0.3.17

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.
Files changed (55) hide show
  1. package/lib/esm/conformance/attribs.spec.js +3 -315
  2. package/lib/esm/conformance/buffers.spec.js +1 -220
  3. package/lib/esm/conformance/context.spec.js +3 -302
  4. package/lib/esm/conformance/programs.spec.js +3 -477
  5. package/lib/esm/conformance/rendering-basic.spec.js +3 -141
  6. package/lib/esm/conformance/rendering.spec.js +7 -514
  7. package/lib/esm/conformance/setup.js +1 -47
  8. package/lib/esm/conformance/state.spec.js +1 -365
  9. package/lib/esm/conformance/textures.spec.js +3 -337
  10. package/lib/esm/conformance/uniforms.spec.js +1 -484
  11. package/lib/esm/conformance-test.js +1 -25
  12. package/lib/esm/extensions/ext-blend-minmax.js +1 -18
  13. package/lib/esm/extensions/ext-color-buffer-float.js +1 -12
  14. package/lib/esm/extensions/ext-color-buffer-half-float.js +1 -12
  15. package/lib/esm/extensions/ext-texture-filter-anisotropic.js +1 -18
  16. package/lib/esm/extensions/oes-element-index-unit.js +1 -13
  17. package/lib/esm/extensions/oes-standard-derivatives.js +1 -17
  18. package/lib/esm/extensions/oes-texture-float-linear.js +1 -13
  19. package/lib/esm/extensions/oes-texture-float.js +1 -13
  20. package/lib/esm/extensions/oes-texture-half-float.js +1 -19
  21. package/lib/esm/extensions/stackgl-destroy-context.js +1 -12
  22. package/lib/esm/extensions/stackgl-resize-drawing-buffer.js +1 -12
  23. package/lib/esm/html-canvas-element.js +1 -65
  24. package/lib/esm/index.js +1 -33
  25. package/lib/esm/linkable.js +1 -50
  26. package/lib/esm/test-utils.js +4 -186
  27. package/lib/esm/test.js +1 -11
  28. package/lib/esm/types/index.js +1 -5
  29. package/lib/esm/utils.js +1 -201
  30. package/lib/esm/webgl-active-info.js +1 -11
  31. package/lib/esm/webgl-bridge.js +1 -167
  32. package/lib/esm/webgl-buffer.js +1 -19
  33. package/lib/esm/webgl-context-attributes.js +1 -24
  34. package/lib/esm/webgl-context-base.js +8 -3069
  35. package/lib/esm/webgl-drawing-buffer-wrapper.js +1 -11
  36. package/lib/esm/webgl-framebuffer.js +1 -110
  37. package/lib/esm/webgl-program.js +1 -27
  38. package/lib/esm/webgl-query.js +1 -17
  39. package/lib/esm/webgl-renderbuffer.js +1 -25
  40. package/lib/esm/webgl-rendering-context.js +1 -175
  41. package/lib/esm/webgl-sampler.js +1 -17
  42. package/lib/esm/webgl-shader-precision-format.js +1 -11
  43. package/lib/esm/webgl-shader.js +1 -25
  44. package/lib/esm/webgl-sync.js +1 -17
  45. package/lib/esm/webgl-texture-unit.js +1 -13
  46. package/lib/esm/webgl-texture.js +1 -23
  47. package/lib/esm/webgl-transform-feedback.js +1 -17
  48. package/lib/esm/webgl-uniform-location.js +1 -15
  49. package/lib/esm/webgl-vertex-array-object.js +1 -23
  50. package/lib/esm/webgl-vertex-attribute.js +1 -151
  51. package/lib/esm/webgl1.spec.js +10 -1044
  52. package/lib/esm/webgl2-rendering-context.js +1 -1218
  53. package/lib/esm/webgl2.spec.js +45 -1288
  54. package/lib/types/webgl-bridge.d.ts +9 -9
  55. package/package.json +9 -9
@@ -1,1044 +1,10 @@
1
- import { destroyTestFBO, destroyTestFBOWithDepth, drawTriangle, makeProgram, makeTestFBO, makeTestFBOWithDepth, pixelClose, readPixel } from "./test-utils.js";
2
- import { beforeEach, describe, expect, it, on } from "@gjsify/unit";
3
- import { WebGLBridge } from "@gjsify/webgl";
4
- import GLib from "@girs/glib-2.0";
5
- import Gtk from "@girs/gtk-4.0";
6
-
7
- //#region src/ts/webgl1.spec.ts
8
- const GL_CONSTANT_NAMES = [
9
- "ACTIVE_ATTRIBUTES",
10
- "ACTIVE_TEXTURE",
11
- "ACTIVE_UNIFORMS",
12
- "ALIASED_LINE_WIDTH_RANGE",
13
- "ALIASED_POINT_SIZE_RANGE",
14
- "ALPHA",
15
- "ALPHA_BITS",
16
- "ALWAYS",
17
- "ARRAY_BUFFER",
18
- "ARRAY_BUFFER_BINDING",
19
- "ATTACHED_SHADERS",
20
- "BACK",
21
- "BLEND",
22
- "BLEND_COLOR",
23
- "BLEND_DST_ALPHA",
24
- "BLEND_DST_RGB",
25
- "BLEND_EQUATION",
26
- "BLEND_EQUATION_ALPHA",
27
- "BLEND_EQUATION_RGB",
28
- "BLEND_SRC_ALPHA",
29
- "BLEND_SRC_RGB",
30
- "BLUE_BITS",
31
- "BOOL",
32
- "BOOL_VEC2",
33
- "BOOL_VEC3",
34
- "BOOL_VEC4",
35
- "BROWSER_DEFAULT_WEBGL",
36
- "BUFFER_SIZE",
37
- "BUFFER_USAGE",
38
- "BYTE",
39
- "CCW",
40
- "CLAMP_TO_EDGE",
41
- "COLOR_ATTACHMENT0",
42
- "COLOR_BUFFER_BIT",
43
- "COLOR_CLEAR_VALUE",
44
- "COLOR_WRITEMASK",
45
- "COMPILE_STATUS",
46
- "COMPRESSED_TEXTURE_FORMATS",
47
- "CONSTANT_ALPHA",
48
- "CONSTANT_COLOR",
49
- "CONTEXT_LOST_WEBGL",
50
- "CULL_FACE",
51
- "CULL_FACE_MODE",
52
- "CURRENT_PROGRAM",
53
- "CURRENT_VERTEX_ATTRIB",
54
- "CW",
55
- "DECR",
56
- "DECR_WRAP",
57
- "DELETE_STATUS",
58
- "DEPTH_ATTACHMENT",
59
- "DEPTH_BITS",
60
- "DEPTH_BUFFER_BIT",
61
- "DEPTH_CLEAR_VALUE",
62
- "DEPTH_COMPONENT",
63
- "DEPTH_COMPONENT16",
64
- "DEPTH_FUNC",
65
- "DEPTH_RANGE",
66
- "DEPTH_STENCIL",
67
- "DEPTH_STENCIL_ATTACHMENT",
68
- "DEPTH_TEST",
69
- "DEPTH_WRITEMASK",
70
- "DITHER",
71
- "DONT_CARE",
72
- "DST_ALPHA",
73
- "DST_COLOR",
74
- "DYNAMIC_DRAW",
75
- "ELEMENT_ARRAY_BUFFER",
76
- "ELEMENT_ARRAY_BUFFER_BINDING",
77
- "EQUAL",
78
- "FASTEST",
79
- "FLOAT",
80
- "FLOAT_MAT2",
81
- "FLOAT_MAT3",
82
- "FLOAT_MAT4",
83
- "FLOAT_VEC2",
84
- "FLOAT_VEC3",
85
- "FLOAT_VEC4",
86
- "FRAGMENT_SHADER",
87
- "FRAMEBUFFER",
88
- "FRAMEBUFFER_ATTACHMENT_OBJECT_NAME",
89
- "FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE",
90
- "FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE",
91
- "FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL",
92
- "FRAMEBUFFER_BINDING",
93
- "FRAMEBUFFER_COMPLETE",
94
- "FRAMEBUFFER_INCOMPLETE_ATTACHMENT",
95
- "FRAMEBUFFER_INCOMPLETE_DIMENSIONS",
96
- "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT",
97
- "FRAMEBUFFER_UNSUPPORTED",
98
- "FRONT",
99
- "FRONT_AND_BACK",
100
- "FRONT_FACE",
101
- "FUNC_ADD",
102
- "FUNC_REVERSE_SUBTRACT",
103
- "FUNC_SUBTRACT",
104
- "GENERATE_MIPMAP_HINT",
105
- "GEQUAL",
106
- "GREATER",
107
- "GREEN_BITS",
108
- "HIGH_FLOAT",
109
- "HIGH_INT",
110
- "IMPLEMENTATION_COLOR_READ_FORMAT",
111
- "IMPLEMENTATION_COLOR_READ_TYPE",
112
- "INCR",
113
- "INCR_WRAP",
114
- "INT",
115
- "INT_VEC2",
116
- "INT_VEC3",
117
- "INT_VEC4",
118
- "INVALID_ENUM",
119
- "INVALID_FRAMEBUFFER_OPERATION",
120
- "INVALID_OPERATION",
121
- "INVALID_VALUE",
122
- "INVERT",
123
- "KEEP",
124
- "LEQUAL",
125
- "LESS",
126
- "LINEAR",
127
- "LINEAR_MIPMAP_LINEAR",
128
- "LINEAR_MIPMAP_NEAREST",
129
- "LINES",
130
- "LINE_LOOP",
131
- "LINE_STRIP",
132
- "LINE_WIDTH",
133
- "LINK_STATUS",
134
- "LOW_FLOAT",
135
- "LOW_INT",
136
- "LUMINANCE",
137
- "LUMINANCE_ALPHA",
138
- "MAX_COMBINED_TEXTURE_IMAGE_UNITS",
139
- "MAX_CUBE_MAP_TEXTURE_SIZE",
140
- "MAX_FRAGMENT_UNIFORM_VECTORS",
141
- "MAX_RENDERBUFFER_SIZE",
142
- "MAX_TEXTURE_IMAGE_UNITS",
143
- "MAX_TEXTURE_SIZE",
144
- "MAX_VARYING_VECTORS",
145
- "MAX_VERTEX_ATTRIBS",
146
- "MAX_VERTEX_TEXTURE_IMAGE_UNITS",
147
- "MAX_VERTEX_UNIFORM_VECTORS",
148
- "MAX_VIEWPORT_DIMS",
149
- "MEDIUM_FLOAT",
150
- "MEDIUM_INT",
151
- "MIRRORED_REPEAT",
152
- "NEAREST",
153
- "NEAREST_MIPMAP_LINEAR",
154
- "NEAREST_MIPMAP_NEAREST",
155
- "NEVER",
156
- "NICEST",
157
- "NONE",
158
- "NOTEQUAL",
159
- "NO_ERROR",
160
- "ONE",
161
- "ONE_MINUS_CONSTANT_ALPHA",
162
- "ONE_MINUS_CONSTANT_COLOR",
163
- "ONE_MINUS_DST_ALPHA",
164
- "ONE_MINUS_DST_COLOR",
165
- "ONE_MINUS_SRC_ALPHA",
166
- "ONE_MINUS_SRC_COLOR",
167
- "OUT_OF_MEMORY",
168
- "PACK_ALIGNMENT",
169
- "POINTS",
170
- "POLYGON_OFFSET_FACTOR",
171
- "POLYGON_OFFSET_FILL",
172
- "POLYGON_OFFSET_UNITS",
173
- "RED_BITS",
174
- "RENDERBUFFER",
175
- "RENDERBUFFER_ALPHA_SIZE",
176
- "RENDERBUFFER_BINDING",
177
- "RENDERBUFFER_BLUE_SIZE",
178
- "RENDERBUFFER_DEPTH_SIZE",
179
- "RENDERBUFFER_GREEN_SIZE",
180
- "RENDERBUFFER_HEIGHT",
181
- "RENDERBUFFER_INTERNAL_FORMAT",
182
- "RENDERBUFFER_RED_SIZE",
183
- "RENDERBUFFER_STENCIL_SIZE",
184
- "RENDERBUFFER_WIDTH",
185
- "RENDERER",
186
- "REPEAT",
187
- "REPLACE",
188
- "RGB",
189
- "RGB565",
190
- "RGB5_A1",
191
- "RGBA",
192
- "RGBA4",
193
- "SAMPLER_2D",
194
- "SAMPLER_CUBE",
195
- "SAMPLES",
196
- "SAMPLE_ALPHA_TO_COVERAGE",
197
- "SAMPLE_BUFFERS",
198
- "SAMPLE_COVERAGE",
199
- "SAMPLE_COVERAGE_INVERT",
200
- "SAMPLE_COVERAGE_VALUE",
201
- "SCISSOR_BOX",
202
- "SCISSOR_TEST",
203
- "SHADER_TYPE",
204
- "SHADING_LANGUAGE_VERSION",
205
- "SHORT",
206
- "SRC_ALPHA",
207
- "SRC_ALPHA_SATURATE",
208
- "SRC_COLOR",
209
- "STATIC_DRAW",
210
- "STENCIL_ATTACHMENT",
211
- "STENCIL_BACK_FAIL",
212
- "STENCIL_BACK_FUNC",
213
- "STENCIL_BACK_PASS_DEPTH_FAIL",
214
- "STENCIL_BACK_PASS_DEPTH_PASS",
215
- "STENCIL_BACK_REF",
216
- "STENCIL_BACK_VALUE_MASK",
217
- "STENCIL_BACK_WRITEMASK",
218
- "STENCIL_BITS",
219
- "STENCIL_BUFFER_BIT",
220
- "STENCIL_CLEAR_VALUE",
221
- "STENCIL_FAIL",
222
- "STENCIL_FUNC",
223
- "STENCIL_INDEX8",
224
- "STENCIL_PASS_DEPTH_FAIL",
225
- "STENCIL_PASS_DEPTH_PASS",
226
- "STENCIL_REF",
227
- "STENCIL_TEST",
228
- "STENCIL_VALUE_MASK",
229
- "STENCIL_WRITEMASK",
230
- "STREAM_DRAW",
231
- "SUBPIXEL_BITS",
232
- "TEXTURE",
233
- "TEXTURE0",
234
- "TEXTURE1",
235
- "TEXTURE10",
236
- "TEXTURE11",
237
- "TEXTURE12",
238
- "TEXTURE13",
239
- "TEXTURE14",
240
- "TEXTURE15",
241
- "TEXTURE16",
242
- "TEXTURE17",
243
- "TEXTURE18",
244
- "TEXTURE19",
245
- "TEXTURE2",
246
- "TEXTURE20",
247
- "TEXTURE21",
248
- "TEXTURE22",
249
- "TEXTURE23",
250
- "TEXTURE24",
251
- "TEXTURE25",
252
- "TEXTURE26",
253
- "TEXTURE27",
254
- "TEXTURE28",
255
- "TEXTURE29",
256
- "TEXTURE3",
257
- "TEXTURE30",
258
- "TEXTURE31",
259
- "TEXTURE4",
260
- "TEXTURE5",
261
- "TEXTURE6",
262
- "TEXTURE7",
263
- "TEXTURE8",
264
- "TEXTURE9",
265
- "TEXTURE_2D",
266
- "TEXTURE_BINDING_2D",
267
- "TEXTURE_BINDING_CUBE_MAP",
268
- "TEXTURE_CUBE_MAP",
269
- "TEXTURE_CUBE_MAP_NEGATIVE_X",
270
- "TEXTURE_CUBE_MAP_NEGATIVE_Y",
271
- "TEXTURE_CUBE_MAP_NEGATIVE_Z",
272
- "TEXTURE_CUBE_MAP_POSITIVE_X",
273
- "TEXTURE_CUBE_MAP_POSITIVE_Y",
274
- "TEXTURE_CUBE_MAP_POSITIVE_Z",
275
- "TEXTURE_MAG_FILTER",
276
- "TEXTURE_MIN_FILTER",
277
- "TEXTURE_WRAP_S",
278
- "TEXTURE_WRAP_T",
279
- "TRIANGLES",
280
- "TRIANGLE_FAN",
281
- "TRIANGLE_STRIP",
282
- "UNPACK_ALIGNMENT",
283
- "UNPACK_COLORSPACE_CONVERSION_WEBGL",
284
- "UNPACK_FLIP_Y_WEBGL",
285
- "UNPACK_PREMULTIPLY_ALPHA_WEBGL",
286
- "UNSIGNED_BYTE",
287
- "UNSIGNED_INT",
288
- "UNSIGNED_SHORT",
289
- "UNSIGNED_SHORT_4_4_4_4",
290
- "UNSIGNED_SHORT_5_5_5_1",
291
- "UNSIGNED_SHORT_5_6_5",
292
- "VALIDATE_STATUS",
293
- "VENDOR",
294
- "VERSION",
295
- "VERTEX_ATTRIB_ARRAY_BUFFER_BINDING",
296
- "VERTEX_ATTRIB_ARRAY_ENABLED",
297
- "VERTEX_ATTRIB_ARRAY_NORMALIZED",
298
- "VERTEX_ATTRIB_ARRAY_POINTER",
299
- "VERTEX_ATTRIB_ARRAY_SIZE",
300
- "VERTEX_ATTRIB_ARRAY_STRIDE",
301
- "VERTEX_ATTRIB_ARRAY_TYPE",
302
- "VERTEX_SHADER",
303
- "VIEWPORT",
304
- "ZERO"
305
- ];
306
- var webgl1_spec_default = async () => {
307
- await on("Display", async () => {
308
- Gtk.init();
309
- let glArea;
310
- let gl;
311
- const readyLoop = new GLib.MainLoop(null, false);
312
- const win = new Gtk.Window({});
313
- win.set_default_size(200, 200);
314
- glArea = new WebGLBridge();
315
- glArea.onReady((_c, g) => {
316
- gl = g;
317
- readyLoop.quit();
318
- });
319
- win.set_child(glArea);
320
- win.present();
321
- const giveUpId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1e4, () => {
322
- readyLoop.quit();
323
- return GLib.SOURCE_REMOVE;
324
- });
325
- readyLoop.run();
326
- GLib.source_remove(giveUpId);
327
- if (!gl) {
328
- console.warn("WebGL context not available after 10s — skipping tests");
329
- win.destroy();
330
- return;
331
- }
332
- glArea.make_current();
333
- await describe("WebGLRenderingContext constants", async () => {
334
- beforeEach(async () => {
335
- glArea.make_current();
336
- });
337
- await it("should have all standard WebGL constants as numbers", async () => {
338
- for (const name of GL_CONSTANT_NAMES) {
339
- const value = gl?.[name];
340
- expect(typeof value).toBe("number");
341
- if (name === "NONE" || name === "ZERO" || name === "NO_ERROR" || name === "POINTS") {
342
- expect(value === 0).toBeTruthy();
343
- } else {
344
- expect(value > 0).toBeTruthy();
345
- }
346
- }
347
- });
348
- });
349
- await describe("Buffers", async () => {
350
- beforeEach(async () => {
351
- glArea.make_current();
352
- });
353
- await it("createBuffer returns a WebGLBuffer", async () => {
354
- const buf = gl.createBuffer();
355
- expect(buf).toBeDefined();
356
- expect(buf).not.toBeNull();
357
- });
358
- await it("bindBuffer + bufferData with Float32Array", async () => {
359
- const buf = gl.createBuffer();
360
- gl.bindBuffer(gl.ARRAY_BUFFER, buf);
361
- const data = new Float32Array([
362
- 1,
363
- 2,
364
- 3,
365
- 4
366
- ]);
367
- expect(() => gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW)).not.toThrow();
368
- });
369
- await it("getBufferParameter returns buffer size", async () => {
370
- const buf = gl.createBuffer();
371
- gl.bindBuffer(gl.ARRAY_BUFFER, buf);
372
- const data = new Float32Array([
373
- 1,
374
- 2,
375
- 3,
376
- 4
377
- ]);
378
- gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
379
- const size = gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE);
380
- expect(size).toBe(data.byteLength);
381
- });
382
- await it("bufferSubData updates buffer data", async () => {
383
- const buf = gl.createBuffer();
384
- gl.bindBuffer(gl.ARRAY_BUFFER, buf);
385
- const data = new Float32Array([
386
- 1,
387
- 2,
388
- 3,
389
- 4
390
- ]);
391
- gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW);
392
- expect(() => gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array([9, 9]))).not.toThrow();
393
- });
394
- await it("deleteBuffer cleans up", async () => {
395
- const buf = gl.createBuffer();
396
- expect(() => gl.deleteBuffer(buf)).not.toThrow();
397
- });
398
- });
399
- await describe("Shaders", async () => {
400
- beforeEach(async () => {
401
- glArea.make_current();
402
- });
403
- const vertSrc = "attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); }";
404
- const fragSrc = "void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }";
405
- await it("createShader returns a WebGLShader", async () => {
406
- const shader = gl.createShader(gl.VERTEX_SHADER);
407
- expect(shader).toBeDefined();
408
- expect(shader).not.toBeNull();
409
- });
410
- await it("vertex shader compiles successfully", async () => {
411
- const shader = gl.createShader(gl.VERTEX_SHADER);
412
- gl.shaderSource(shader, vertSrc);
413
- gl.compileShader(shader);
414
- const status = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
415
- if (!status) {
416
- console.error("Vertex shader log:", gl.getShaderInfoLog(shader));
417
- }
418
- expect(status).toBeTruthy();
419
- });
420
- await it("fragment shader compiles successfully", async () => {
421
- const shader = gl.createShader(gl.FRAGMENT_SHADER);
422
- gl.shaderSource(shader, fragSrc);
423
- gl.compileShader(shader);
424
- const status = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
425
- if (!status) {
426
- console.error("Fragment shader log:", gl.getShaderInfoLog(shader));
427
- }
428
- expect(status).toBeTruthy();
429
- });
430
- await it("program links successfully", async () => {
431
- const vert = gl.createShader(gl.VERTEX_SHADER);
432
- gl.shaderSource(vert, vertSrc);
433
- gl.compileShader(vert);
434
- const frag = gl.createShader(gl.FRAGMENT_SHADER);
435
- gl.shaderSource(frag, fragSrc);
436
- gl.compileShader(frag);
437
- const prog = gl.createProgram();
438
- gl.attachShader(prog, vert);
439
- gl.attachShader(prog, frag);
440
- gl.linkProgram(prog);
441
- const status = gl.getProgramParameter(prog, gl.LINK_STATUS);
442
- if (!status) {
443
- console.error("Program log:", gl.getProgramInfoLog(prog));
444
- }
445
- expect(status).toBeTruthy();
446
- });
447
- });
448
- await describe("Textures", async () => {
449
- beforeEach(async () => {
450
- glArea.make_current();
451
- });
452
- await it("createTexture returns a WebGLTexture", async () => {
453
- const tex = gl.createTexture();
454
- expect(tex).toBeDefined();
455
- expect(tex).not.toBeNull();
456
- });
457
- await it("bindTexture + texImage2D with Uint8Array", async () => {
458
- const tex = gl.createTexture();
459
- gl.bindTexture(gl.TEXTURE_2D, tex);
460
- const pixels = new Uint8Array([
461
- 255,
462
- 0,
463
- 0,
464
- 255
465
- ]);
466
- expect(() => gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels)).not.toThrow();
467
- });
468
- await it("texParameteri sets filter params without error", async () => {
469
- const tex = gl.createTexture();
470
- gl.bindTexture(gl.TEXTURE_2D, tex);
471
- expect(() => {
472
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
473
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
474
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
475
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
476
- }).not.toThrow();
477
- });
478
- await it("deleteTexture cleans up", async () => {
479
- const tex = gl.createTexture();
480
- expect(() => gl.deleteTexture(tex)).not.toThrow();
481
- });
482
- });
483
- await describe("Draw", async () => {
484
- beforeEach(async () => {
485
- glArea.make_current();
486
- });
487
- await it("clearColor + clear does not throw", async () => {
488
- expect(() => {
489
- gl.clearColor(0, 0, 0, 1);
490
- gl.clear(gl.COLOR_BUFFER_BIT);
491
- }).not.toThrow();
492
- expect(gl.getError()).toBe(gl.NO_ERROR);
493
- });
494
- await it("viewport does not throw", async () => {
495
- expect(() => gl.viewport(0, 0, 200, 200)).not.toThrow();
496
- });
497
- await it("drawArrays (triangle) produces no GL error", async () => {
498
- const vertSrc = "attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); }";
499
- const fragSrc = "void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }";
500
- const vert = gl.createShader(gl.VERTEX_SHADER);
501
- gl.shaderSource(vert, vertSrc);
502
- gl.compileShader(vert);
503
- const frag = gl.createShader(gl.FRAGMENT_SHADER);
504
- gl.shaderSource(frag, fragSrc);
505
- gl.compileShader(frag);
506
- const prog = gl.createProgram();
507
- gl.attachShader(prog, vert);
508
- gl.attachShader(prog, frag);
509
- gl.linkProgram(prog);
510
- gl.useProgram(prog);
511
- const buf = gl.createBuffer();
512
- gl.bindBuffer(gl.ARRAY_BUFFER, buf);
513
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
514
- -1,
515
- 0,
516
- 0,
517
- -1,
518
- 1,
519
- 1
520
- ]), gl.STATIC_DRAW);
521
- const loc = gl.getAttribLocation(prog, "position");
522
- gl.enableVertexAttribArray(loc);
523
- gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
524
- gl.clearColor(0, 0, 0, 1);
525
- gl.clear(gl.COLOR_BUFFER_BIT);
526
- expect(() => gl.drawArrays(gl.TRIANGLES, 0, 3)).not.toThrow();
527
- expect(gl.getError()).toBe(gl.NO_ERROR);
528
- });
529
- });
530
- await describe("Extensions", async () => {
531
- beforeEach(async () => {
532
- glArea.make_current();
533
- });
534
- await it("OES_texture_float is supported", async () => {
535
- const ext = gl.getExtension("OES_texture_float");
536
- expect(ext).not.toBeNull();
537
- });
538
- await it("OES_standard_derivatives is supported", async () => {
539
- const ext = gl.getExtension("OES_standard_derivatives");
540
- expect(ext).not.toBeNull();
541
- });
542
- await it("OES_element_index_uint is supported", async () => {
543
- const ext = gl.getExtension("OES_element_index_uint");
544
- expect(ext).not.toBeNull();
545
- });
546
- await it("getSupportedExtensions returns an array", async () => {
547
- const exts = gl.getSupportedExtensions();
548
- expect(Array.isArray(exts)).toBeTruthy();
549
- expect((exts?.length ?? 0) > 0).toBeTruthy();
550
- });
551
- });
552
- await describe("Gwebgl.WebGLRenderingContext native bindings", async () => {
553
- beforeEach(async () => {
554
- glArea.make_current();
555
- });
556
- await it("getParameterb returns a boolean", async () => {
557
- const res = gl?._native.getParameterb(gl?.BLEND);
558
- expect(typeof res).toBe("boolean");
559
- });
560
- await it("getParameterbv returns an array of booleans", async () => {
561
- const results = gl?._native.getParameterbv(gl?.COLOR_WRITEMASK, 16);
562
- expect(Array.isArray(results)).toBeTruthy();
563
- if (Array.isArray(results)) {
564
- for (const r of results) expect(typeof r).toBe("boolean");
565
- }
566
- });
567
- await it("getParameterf returns a float", async () => {
568
- const result = gl?._native.getParameterf(gl?.SAMPLE_COVERAGE_VALUE);
569
- expect(typeof result).toBe("number");
570
- });
571
- await it("getParameterfv returns an array of floats", async () => {
572
- const results = gl?._native.getParameterfv(gl?.DEPTH_RANGE, 8);
573
- expect(Array.isArray(results)).toBeTruthy();
574
- if (Array.isArray(results)) {
575
- for (const r of results) expect(typeof r).toBe("number");
576
- }
577
- });
578
- await it("getParameteri returns an integer", async () => {
579
- const result = gl?._native.getParameteri(gl?.ARRAY_BUFFER_BINDING);
580
- expect(typeof result).toBe("number");
581
- });
582
- await it("getParameteriv returns an array of integers", async () => {
583
- const results = gl?._native.getParameteriv(gl?.MAX_VIEWPORT_DIMS, 8);
584
- expect(Array.isArray(results)).toBeTruthy();
585
- if (Array.isArray(results)) {
586
- for (const r of results) expect(typeof r).toBe("number");
587
- }
588
- });
589
- });
590
- await describe("simple-shader rendering", async () => {
591
- beforeEach(async () => {
592
- glArea.make_current();
593
- });
594
- const VS = "attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); }";
595
- const FS = "void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }";
596
- await it("renders a green triangle — all pixels (0,255,0,255)", async () => {
597
- const fbo = makeTestFBO(gl, 8, 8);
598
- gl.clearColor(0, 0, 0, 1);
599
- gl.clear(gl.COLOR_BUFFER_BIT);
600
- const prog = makeProgram(gl, VS, FS);
601
- expect(gl.getProgramParameter(prog, gl.LINK_STATUS)).toBeTruthy();
602
- gl.useProgram(prog);
603
- drawTriangle(gl);
604
- expect(gl.getError()).toBe(gl.NO_ERROR);
605
- const pixels = new Uint8Array(fbo.width * fbo.height * 4);
606
- gl.readPixels(0, 0, fbo.width, fbo.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
607
- let allGreen = true;
608
- for (let i = 0; i < pixels.length; i += 4) {
609
- if (pixels[i] !== 0 || pixels[i + 1] !== 255 || pixels[i + 2] !== 0 || pixels[i + 3] !== 255) {
610
- allGreen = false;
611
- break;
612
- }
613
- }
614
- expect(allGreen).toBeTruthy();
615
- gl.deleteProgram(prog);
616
- destroyTestFBO(gl, fbo);
617
- });
618
- });
619
- await describe("clearColor", async () => {
620
- beforeEach(async () => {
621
- glArea.make_current();
622
- });
623
- await it("clears to black (0,0,0,0)", async () => {
624
- const fbo = makeTestFBO(gl);
625
- gl.clearColor(0, 0, 0, 0);
626
- gl.clear(gl.COLOR_BUFFER_BIT);
627
- const p = readPixel(gl, 0, 0);
628
- destroyTestFBO(gl, fbo);
629
- expect(p[0]).toBe(0);
630
- expect(p[1]).toBe(0);
631
- expect(p[2]).toBe(0);
632
- expect(p[3]).toBe(0);
633
- });
634
- await it("clears to white (255,255,255,255)", async () => {
635
- const fbo = makeTestFBO(gl);
636
- gl.clearColor(1, 1, 1, 1);
637
- gl.clear(gl.COLOR_BUFFER_BIT);
638
- const p = readPixel(gl, 0, 0);
639
- destroyTestFBO(gl, fbo);
640
- expect(p[0]).toBe(255);
641
- expect(p[1]).toBe(255);
642
- expect(p[2]).toBe(255);
643
- expect(p[3]).toBe(255);
644
- });
645
- await it("clears to green (0,255,0,255)", async () => {
646
- const fbo = makeTestFBO(gl);
647
- gl.clearColor(0, 1, 0, 1);
648
- gl.clear(gl.COLOR_BUFFER_BIT);
649
- const p = readPixel(gl, 0, 0);
650
- destroyTestFBO(gl, fbo);
651
- expect(p[0]).toBe(0);
652
- expect(p[1]).toBe(255);
653
- expect(p[2]).toBe(0);
654
- expect(p[3]).toBe(255);
655
- });
656
- await it("clears to magenta (255,0,255,255)", async () => {
657
- const fbo = makeTestFBO(gl);
658
- gl.clearColor(1, 0, 1, 1);
659
- gl.clear(gl.COLOR_BUFFER_BIT);
660
- const p = readPixel(gl, 0, 0);
661
- destroyTestFBO(gl, fbo);
662
- expect(p[0]).toBe(255);
663
- expect(p[1]).toBe(0);
664
- expect(p[2]).toBe(255);
665
- expect(p[3]).toBe(255);
666
- });
667
- });
668
- await describe("blending", async () => {
669
- beforeEach(async () => {
670
- glArea.make_current();
671
- });
672
- const VS_BLEND = [
673
- "precision mediump float;",
674
- "attribute vec2 position;",
675
- "void main() { gl_Position = vec4(position, 0.0, 1.0); }"
676
- ].join("\n");
677
- const blendTests = [
678
- {
679
- name: "ADD ONE ONE",
680
- equn: gl.FUNC_ADD,
681
- func1: gl.ONE,
682
- func2: gl.ONE,
683
- dstColor: [
684
- .5,
685
- .5,
686
- .5,
687
- 1
688
- ],
689
- srcColor: [
690
- .5,
691
- .5,
692
- .5,
693
- 1
694
- ],
695
- expected: [
696
- 255,
697
- 255,
698
- 255,
699
- 255
700
- ]
701
- },
702
- {
703
- name: "ADD ONE ZERO",
704
- equn: gl.FUNC_ADD,
705
- func1: gl.ONE,
706
- func2: gl.ZERO,
707
- dstColor: [
708
- .5,
709
- .5,
710
- .5,
711
- .5
712
- ],
713
- srcColor: [
714
- .2,
715
- .2,
716
- .2,
717
- 1
718
- ],
719
- expected: [
720
- 51,
721
- 51,
722
- 51,
723
- 255
724
- ]
725
- },
726
- {
727
- name: "ADD ZERO SRC_COLOR",
728
- equn: gl.FUNC_ADD,
729
- func1: gl.ZERO,
730
- func2: gl.SRC_COLOR,
731
- dstColor: [
732
- .8,
733
- .8,
734
- .8,
735
- 1
736
- ],
737
- srcColor: [
738
- .5,
739
- .5,
740
- .5,
741
- .5
742
- ],
743
- expected: [
744
- 102,
745
- 102,
746
- 102,
747
- 128
748
- ]
749
- },
750
- {
751
- name: "ADD DST_COLOR ZERO",
752
- equn: gl.FUNC_ADD,
753
- func1: gl.DST_COLOR,
754
- func2: gl.ZERO,
755
- dstColor: [
756
- .8,
757
- .8,
758
- .8,
759
- 1
760
- ],
761
- srcColor: [
762
- .5,
763
- .5,
764
- .5,
765
- .5
766
- ],
767
- expected: [
768
- 102,
769
- 102,
770
- 102,
771
- 128
772
- ]
773
- },
774
- {
775
- name: "ADD SRC_ALPHA ONE_MINUS_SRC_ALPHA",
776
- equn: gl.FUNC_ADD,
777
- func1: gl.SRC_ALPHA,
778
- func2: gl.ONE_MINUS_SRC_ALPHA,
779
- dstColor: [
780
- .5,
781
- 0,
782
- .5,
783
- 1
784
- ],
785
- srcColor: [
786
- .5,
787
- 1,
788
- 0,
789
- .5
790
- ],
791
- expected: [
792
- 127,
793
- 127,
794
- 64,
795
- 191
796
- ]
797
- }
798
- ];
799
- for (const tc of blendTests) {
800
- const { name, equn, func1, func2, dstColor, srcColor, expected } = tc;
801
- const FS_BLEND = ["precision mediump float;", `void main() { gl_FragColor = vec4(${srcColor[0]},${srcColor[1]},${srcColor[2]},${srcColor[3]}); }`].join("\n");
802
- await it(name, async () => {
803
- const fbo = makeTestFBO(gl);
804
- gl.clearColor(dstColor[0], dstColor[1], dstColor[2], dstColor[3]);
805
- gl.clear(gl.COLOR_BUFFER_BIT);
806
- const prog = makeProgram(gl, VS_BLEND, FS_BLEND);
807
- gl.useProgram(prog);
808
- gl.enable(gl.BLEND);
809
- gl.blendEquation(equn);
810
- gl.blendFunc(func1, func2);
811
- drawTriangle(gl);
812
- expect(gl.getError()).toBe(gl.NO_ERROR);
813
- gl.disable(gl.BLEND);
814
- const p = readPixel(gl, 0, 0);
815
- gl.deleteProgram(prog);
816
- destroyTestFBO(gl, fbo);
817
- expect(pixelClose(p, expected)).toBeTruthy();
818
- });
819
- }
820
- });
821
- await describe("drawElements (indexed drawing)", async () => {
822
- beforeEach(async () => {
823
- glArea.make_current();
824
- });
825
- await it("draws a quad via index buffer — all pixels green", async () => {
826
- const fbo = makeTestFBO(gl, 8, 8);
827
- const VS = "attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); }";
828
- const FS = "void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }";
829
- gl.clearColor(1, 0, 0, 1);
830
- gl.clear(gl.COLOR_BUFFER_BIT);
831
- const prog = makeProgram(gl, VS, FS);
832
- gl.useProgram(prog);
833
- const vbuf = gl.createBuffer();
834
- gl.bindBuffer(gl.ARRAY_BUFFER, vbuf);
835
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
836
- -1,
837
- -1,
838
- 1,
839
- -1,
840
- -1,
841
- 1,
842
- 1,
843
- 1
844
- ]), gl.STATIC_DRAW);
845
- gl.enableVertexAttribArray(0);
846
- gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
847
- const ebuf = gl.createBuffer();
848
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebuf);
849
- gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([
850
- 0,
851
- 1,
852
- 2,
853
- 2,
854
- 1,
855
- 3
856
- ]), gl.STATIC_DRAW);
857
- gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
858
- expect(gl.getError()).toBe(gl.NO_ERROR);
859
- const pixels = new Uint8Array(fbo.width * fbo.height * 4);
860
- gl.readPixels(0, 0, fbo.width, fbo.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
861
- let allGreen = true;
862
- for (let i = 0; i < pixels.length; i += 4) {
863
- if (pixels[i] !== 0 || pixels[i + 1] !== 255 || pixels[i + 2] !== 0 || pixels[i + 3] !== 255) {
864
- allGreen = false;
865
- break;
866
- }
867
- }
868
- expect(allGreen).toBeTruthy();
869
- gl.disableVertexAttribArray(0);
870
- gl.deleteBuffer(vbuf);
871
- gl.deleteBuffer(ebuf);
872
- gl.deleteProgram(prog);
873
- destroyTestFBO(gl, fbo);
874
- });
875
- });
876
- await describe("readPixels", async () => {
877
- beforeEach(async () => {
878
- glArea.make_current();
879
- });
880
- await it("RGBA + UNSIGNED_BYTE returns correct data size", async () => {
881
- const fbo = makeTestFBO(gl, 4, 4);
882
- gl.clearColor(1, 0, 0, 1);
883
- gl.clear(gl.COLOR_BUFFER_BIT);
884
- const pixels = new Uint8Array(fbo.width * fbo.height * 4);
885
- gl.readPixels(0, 0, fbo.width, fbo.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
886
- expect(gl.getError()).toBe(gl.NO_ERROR);
887
- expect(pixels.length).toBe(fbo.width * fbo.height * 4);
888
- destroyTestFBO(gl, fbo);
889
- });
890
- await it("pixel values match the clear color", async () => {
891
- const fbo = makeTestFBO(gl);
892
- gl.clearColor(0, 0, 1, 1);
893
- gl.clear(gl.COLOR_BUFFER_BIT);
894
- const p = readPixel(gl, 0, 0);
895
- destroyTestFBO(gl, fbo);
896
- expect(p[0]).toBe(0);
897
- expect(p[1]).toBe(0);
898
- expect(p[2]).toBe(255);
899
- expect(p[3]).toBe(255);
900
- });
901
- await it("readPixels reads a single red pixel", async () => {
902
- const fbo = makeTestFBO(gl);
903
- gl.clearColor(1, 0, 0, 1);
904
- gl.clear(gl.COLOR_BUFFER_BIT);
905
- const buf = new Uint8Array(4);
906
- gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
907
- destroyTestFBO(gl, fbo);
908
- expect(buf[0]).toBe(255);
909
- expect(buf[1]).toBe(0);
910
- expect(buf[2]).toBe(0);
911
- expect(buf[3]).toBe(255);
912
- });
913
- });
914
- await describe("depth buffer", async () => {
915
- beforeEach(async () => {
916
- glArea.make_current();
917
- });
918
- await it("depth test (LESS) — nearer triangle occludes farther one", async () => {
919
- const VS = [
920
- "attribute vec2 position;",
921
- "uniform float depth;",
922
- "void main() { gl_Position = vec4(position, depth, 1.0); }"
923
- ].join("\n");
924
- const FS = [
925
- "precision mediump float;",
926
- "uniform vec4 color;",
927
- "void main() { gl_FragColor = color; }"
928
- ].join("\n");
929
- const fbo = makeTestFBOWithDepth(gl, 4, 4);
930
- gl.clearColor(0, 0, 0, 1);
931
- gl.clearDepth(1);
932
- gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
933
- gl.enable(gl.DEPTH_TEST);
934
- gl.depthFunc(gl.LESS);
935
- const prog = makeProgram(gl, VS, FS);
936
- gl.useProgram(prog);
937
- gl.uniform1f(gl.getUniformLocation(prog, "depth"), 0);
938
- gl.uniform4f(gl.getUniformLocation(prog, "color"), 1, 0, 0, 1);
939
- drawTriangle(gl);
940
- gl.uniform1f(gl.getUniformLocation(prog, "depth"), .5);
941
- gl.uniform4f(gl.getUniformLocation(prog, "color"), 0, 0, 1, 1);
942
- drawTriangle(gl);
943
- expect(gl.getError()).toBe(gl.NO_ERROR);
944
- gl.disable(gl.DEPTH_TEST);
945
- const p = readPixel(gl, 0, 0);
946
- gl.deleteProgram(prog);
947
- destroyTestFBOWithDepth(gl, fbo);
948
- expect(p[0]).toBe(255);
949
- expect(p[1]).toBe(0);
950
- expect(p[2]).toBe(0);
951
- });
952
- });
953
- await describe("uniform1fv regression", async () => {
954
- beforeEach(async () => {
955
- glArea.make_current();
956
- });
957
- const VS_U1FV = ["attribute vec2 position;", "void main() { gl_Position = vec4(position, 0.0, 1.0); }"].join("\n");
958
- await it("uniform1fv sets a float uniform and affects rendering", async () => {
959
- const FS = [
960
- "precision mediump float;",
961
- "uniform float uRed;",
962
- "void main() { gl_FragColor = vec4(uRed, 0.0, 0.0, 1.0); }"
963
- ].join("\n");
964
- const prog = makeProgram(gl, VS_U1FV, FS);
965
- expect(gl.getProgramParameter(prog, gl.LINK_STATUS)).toBeTruthy();
966
- gl.useProgram(prog);
967
- const loc = gl.getUniformLocation(prog, "uRed");
968
- expect(loc).not.toBeNull();
969
- gl.uniform1fv(loc, new Float32Array([1]));
970
- expect(gl.getError()).toBe(gl.NO_ERROR);
971
- const fbo = makeTestFBO(gl, 4, 4);
972
- gl.clearColor(0, 0, 0, 1);
973
- gl.clear(gl.COLOR_BUFFER_BIT);
974
- drawTriangle(gl);
975
- const p = readPixel(gl, 0, 0);
976
- destroyTestFBO(gl, fbo);
977
- expect(p[0]).toBe(255);
978
- expect(p[1]).toBe(0);
979
- expect(p[2]).toBe(0);
980
- gl.deleteProgram(prog);
981
- });
982
- await it("uniform1fv sets each array element individually", async () => {
983
- const FS_ARR = [
984
- "precision mediump float;",
985
- "uniform float uWeights[3];",
986
- "void main() { gl_FragColor = vec4(uWeights[0], uWeights[1], uWeights[2], 1.0); }"
987
- ].join("\n");
988
- const prog = makeProgram(gl, VS_U1FV, FS_ARR);
989
- expect(gl.getProgramParameter(prog, gl.LINK_STATUS)).toBeTruthy();
990
- gl.useProgram(prog);
991
- const loc0 = gl.getUniformLocation(prog, "uWeights[0]");
992
- const loc1 = gl.getUniformLocation(prog, "uWeights[1]");
993
- const loc2 = gl.getUniformLocation(prog, "uWeights[2]");
994
- expect(loc0).not.toBeNull();
995
- expect(loc1).not.toBeNull();
996
- expect(loc2).not.toBeNull();
997
- gl.uniform1fv(loc0, new Float32Array([0]));
998
- gl.uniform1fv(loc1, new Float32Array([1]));
999
- gl.uniform1fv(loc2, new Float32Array([0]));
1000
- expect(gl.getError()).toBe(gl.NO_ERROR);
1001
- const fbo = makeTestFBO(gl, 4, 4);
1002
- gl.clearColor(0, 0, 0, 1);
1003
- gl.clear(gl.COLOR_BUFFER_BIT);
1004
- drawTriangle(gl);
1005
- const p = readPixel(gl, 0, 0);
1006
- destroyTestFBO(gl, fbo);
1007
- expect(p[0]).toBe(0);
1008
- expect(p[1]).toBe(255);
1009
- expect(p[2]).toBe(0);
1010
- gl.deleteProgram(prog);
1011
- });
1012
- });
1013
- await describe("linkProgram with inactive attributes", async () => {
1014
- beforeEach(async () => {
1015
- glArea.make_current();
1016
- });
1017
- await it("links a program whose vertex shader declares but does not use an attribute", async () => {
1018
- const VS = [
1019
- "attribute vec2 position;",
1020
- "attribute vec3 unused;",
1021
- "void main() { gl_Position = vec4(position, 0.0, 1.0); }"
1022
- ].join("\n");
1023
- const FS = ["precision mediump float;", "void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }"].join("\n");
1024
- const prog = makeProgram(gl, VS, FS);
1025
- expect(gl.getProgramParameter(prog, gl.LINK_STATUS)).toBeTruthy();
1026
- expect(gl.getError()).toBe(gl.NO_ERROR);
1027
- gl.useProgram(prog);
1028
- const fbo = makeTestFBO(gl, 4, 4);
1029
- gl.clearColor(0, 0, 0, 1);
1030
- gl.clear(gl.COLOR_BUFFER_BIT);
1031
- drawTriangle(gl);
1032
- expect(gl.getError()).toBe(gl.NO_ERROR);
1033
- const p = readPixel(gl, 0, 0);
1034
- destroyTestFBO(gl, fbo);
1035
- expect(p[1]).toBe(255);
1036
- gl.deleteProgram(prog);
1037
- });
1038
- });
1039
- win.destroy();
1040
- });
1041
- };
1042
-
1043
- //#endregion
1044
- export { webgl1_spec_default as default };
1
+ import{destroyTestFBO as e,destroyTestFBOWithDepth as t,drawTriangle as n,makeProgram as r,makeTestFBO as i,makeTestFBOWithDepth as a,pixelClose as o,readPixel as s}from"./test-utils.js";import{beforeEach as c,describe as l,expect as u,it as d,on as f}from"@gjsify/unit";import{WebGLBridge as p}from"@gjsify/webgl";import m from"@girs/glib-2.0";import h from"@girs/gtk-4.0";const g=`ACTIVE_ATTRIBUTES.ACTIVE_TEXTURE.ACTIVE_UNIFORMS.ALIASED_LINE_WIDTH_RANGE.ALIASED_POINT_SIZE_RANGE.ALPHA.ALPHA_BITS.ALWAYS.ARRAY_BUFFER.ARRAY_BUFFER_BINDING.ATTACHED_SHADERS.BACK.BLEND.BLEND_COLOR.BLEND_DST_ALPHA.BLEND_DST_RGB.BLEND_EQUATION.BLEND_EQUATION_ALPHA.BLEND_EQUATION_RGB.BLEND_SRC_ALPHA.BLEND_SRC_RGB.BLUE_BITS.BOOL.BOOL_VEC2.BOOL_VEC3.BOOL_VEC4.BROWSER_DEFAULT_WEBGL.BUFFER_SIZE.BUFFER_USAGE.BYTE.CCW.CLAMP_TO_EDGE.COLOR_ATTACHMENT0.COLOR_BUFFER_BIT.COLOR_CLEAR_VALUE.COLOR_WRITEMASK.COMPILE_STATUS.COMPRESSED_TEXTURE_FORMATS.CONSTANT_ALPHA.CONSTANT_COLOR.CONTEXT_LOST_WEBGL.CULL_FACE.CULL_FACE_MODE.CURRENT_PROGRAM.CURRENT_VERTEX_ATTRIB.CW.DECR.DECR_WRAP.DELETE_STATUS.DEPTH_ATTACHMENT.DEPTH_BITS.DEPTH_BUFFER_BIT.DEPTH_CLEAR_VALUE.DEPTH_COMPONENT.DEPTH_COMPONENT16.DEPTH_FUNC.DEPTH_RANGE.DEPTH_STENCIL.DEPTH_STENCIL_ATTACHMENT.DEPTH_TEST.DEPTH_WRITEMASK.DITHER.DONT_CARE.DST_ALPHA.DST_COLOR.DYNAMIC_DRAW.ELEMENT_ARRAY_BUFFER.ELEMENT_ARRAY_BUFFER_BINDING.EQUAL.FASTEST.FLOAT.FLOAT_MAT2.FLOAT_MAT3.FLOAT_MAT4.FLOAT_VEC2.FLOAT_VEC3.FLOAT_VEC4.FRAGMENT_SHADER.FRAMEBUFFER.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL.FRAMEBUFFER_BINDING.FRAMEBUFFER_COMPLETE.FRAMEBUFFER_INCOMPLETE_ATTACHMENT.FRAMEBUFFER_INCOMPLETE_DIMENSIONS.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT.FRAMEBUFFER_UNSUPPORTED.FRONT.FRONT_AND_BACK.FRONT_FACE.FUNC_ADD.FUNC_REVERSE_SUBTRACT.FUNC_SUBTRACT.GENERATE_MIPMAP_HINT.GEQUAL.GREATER.GREEN_BITS.HIGH_FLOAT.HIGH_INT.IMPLEMENTATION_COLOR_READ_FORMAT.IMPLEMENTATION_COLOR_READ_TYPE.INCR.INCR_WRAP.INT.INT_VEC2.INT_VEC3.INT_VEC4.INVALID_ENUM.INVALID_FRAMEBUFFER_OPERATION.INVALID_OPERATION.INVALID_VALUE.INVERT.KEEP.LEQUAL.LESS.LINEAR.LINEAR_MIPMAP_LINEAR.LINEAR_MIPMAP_NEAREST.LINES.LINE_LOOP.LINE_STRIP.LINE_WIDTH.LINK_STATUS.LOW_FLOAT.LOW_INT.LUMINANCE.LUMINANCE_ALPHA.MAX_COMBINED_TEXTURE_IMAGE_UNITS.MAX_CUBE_MAP_TEXTURE_SIZE.MAX_FRAGMENT_UNIFORM_VECTORS.MAX_RENDERBUFFER_SIZE.MAX_TEXTURE_IMAGE_UNITS.MAX_TEXTURE_SIZE.MAX_VARYING_VECTORS.MAX_VERTEX_ATTRIBS.MAX_VERTEX_TEXTURE_IMAGE_UNITS.MAX_VERTEX_UNIFORM_VECTORS.MAX_VIEWPORT_DIMS.MEDIUM_FLOAT.MEDIUM_INT.MIRRORED_REPEAT.NEAREST.NEAREST_MIPMAP_LINEAR.NEAREST_MIPMAP_NEAREST.NEVER.NICEST.NONE.NOTEQUAL.NO_ERROR.ONE.ONE_MINUS_CONSTANT_ALPHA.ONE_MINUS_CONSTANT_COLOR.ONE_MINUS_DST_ALPHA.ONE_MINUS_DST_COLOR.ONE_MINUS_SRC_ALPHA.ONE_MINUS_SRC_COLOR.OUT_OF_MEMORY.PACK_ALIGNMENT.POINTS.POLYGON_OFFSET_FACTOR.POLYGON_OFFSET_FILL.POLYGON_OFFSET_UNITS.RED_BITS.RENDERBUFFER.RENDERBUFFER_ALPHA_SIZE.RENDERBUFFER_BINDING.RENDERBUFFER_BLUE_SIZE.RENDERBUFFER_DEPTH_SIZE.RENDERBUFFER_GREEN_SIZE.RENDERBUFFER_HEIGHT.RENDERBUFFER_INTERNAL_FORMAT.RENDERBUFFER_RED_SIZE.RENDERBUFFER_STENCIL_SIZE.RENDERBUFFER_WIDTH.RENDERER.REPEAT.REPLACE.RGB.RGB565.RGB5_A1.RGBA.RGBA4.SAMPLER_2D.SAMPLER_CUBE.SAMPLES.SAMPLE_ALPHA_TO_COVERAGE.SAMPLE_BUFFERS.SAMPLE_COVERAGE.SAMPLE_COVERAGE_INVERT.SAMPLE_COVERAGE_VALUE.SCISSOR_BOX.SCISSOR_TEST.SHADER_TYPE.SHADING_LANGUAGE_VERSION.SHORT.SRC_ALPHA.SRC_ALPHA_SATURATE.SRC_COLOR.STATIC_DRAW.STENCIL_ATTACHMENT.STENCIL_BACK_FAIL.STENCIL_BACK_FUNC.STENCIL_BACK_PASS_DEPTH_FAIL.STENCIL_BACK_PASS_DEPTH_PASS.STENCIL_BACK_REF.STENCIL_BACK_VALUE_MASK.STENCIL_BACK_WRITEMASK.STENCIL_BITS.STENCIL_BUFFER_BIT.STENCIL_CLEAR_VALUE.STENCIL_FAIL.STENCIL_FUNC.STENCIL_INDEX8.STENCIL_PASS_DEPTH_FAIL.STENCIL_PASS_DEPTH_PASS.STENCIL_REF.STENCIL_TEST.STENCIL_VALUE_MASK.STENCIL_WRITEMASK.STREAM_DRAW.SUBPIXEL_BITS.TEXTURE.TEXTURE0.TEXTURE1.TEXTURE10.TEXTURE11.TEXTURE12.TEXTURE13.TEXTURE14.TEXTURE15.TEXTURE16.TEXTURE17.TEXTURE18.TEXTURE19.TEXTURE2.TEXTURE20.TEXTURE21.TEXTURE22.TEXTURE23.TEXTURE24.TEXTURE25.TEXTURE26.TEXTURE27.TEXTURE28.TEXTURE29.TEXTURE3.TEXTURE30.TEXTURE31.TEXTURE4.TEXTURE5.TEXTURE6.TEXTURE7.TEXTURE8.TEXTURE9.TEXTURE_2D.TEXTURE_BINDING_2D.TEXTURE_BINDING_CUBE_MAP.TEXTURE_CUBE_MAP.TEXTURE_CUBE_MAP_NEGATIVE_X.TEXTURE_CUBE_MAP_NEGATIVE_Y.TEXTURE_CUBE_MAP_NEGATIVE_Z.TEXTURE_CUBE_MAP_POSITIVE_X.TEXTURE_CUBE_MAP_POSITIVE_Y.TEXTURE_CUBE_MAP_POSITIVE_Z.TEXTURE_MAG_FILTER.TEXTURE_MIN_FILTER.TEXTURE_WRAP_S.TEXTURE_WRAP_T.TRIANGLES.TRIANGLE_FAN.TRIANGLE_STRIP.UNPACK_ALIGNMENT.UNPACK_COLORSPACE_CONVERSION_WEBGL.UNPACK_FLIP_Y_WEBGL.UNPACK_PREMULTIPLY_ALPHA_WEBGL.UNSIGNED_BYTE.UNSIGNED_INT.UNSIGNED_SHORT.UNSIGNED_SHORT_4_4_4_4.UNSIGNED_SHORT_5_5_5_1.UNSIGNED_SHORT_5_6_5.VALIDATE_STATUS.VENDOR.VERSION.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING.VERTEX_ATTRIB_ARRAY_ENABLED.VERTEX_ATTRIB_ARRAY_NORMALIZED.VERTEX_ATTRIB_ARRAY_POINTER.VERTEX_ATTRIB_ARRAY_SIZE.VERTEX_ATTRIB_ARRAY_STRIDE.VERTEX_ATTRIB_ARRAY_TYPE.VERTEX_SHADER.VIEWPORT.ZERO`.split(`.`);var _=async()=>{await f(`Display`,async()=>{h.init();let f,_,v=new m.MainLoop(null,!1),y=new h.Window({});y.set_default_size(200,200),f=new p,f.onReady((e,t)=>{_=t,v.quit()}),y.set_child(f),y.present();let b=m.timeout_add(m.PRIORITY_DEFAULT,1e4,()=>(v.quit(),m.SOURCE_REMOVE));if(v.run(),m.source_remove(b),!_){console.warn(`WebGL context not available after 10s — skipping tests`),y.destroy();return}f.make_current(),await l(`WebGLRenderingContext constants`,async()=>{c(async()=>{f.make_current()}),await d(`should have all standard WebGL constants as numbers`,async()=>{for(let e of g){let t=_?.[e];u(typeof t).toBe(`number`),e===`NONE`||e===`ZERO`||e===`NO_ERROR`||e===`POINTS`?u(t===0).toBeTruthy():u(t>0).toBeTruthy()}})}),await l(`Buffers`,async()=>{c(async()=>{f.make_current()}),await d(`createBuffer returns a WebGLBuffer`,async()=>{let e=_.createBuffer();u(e).toBeDefined(),u(e).not.toBeNull()}),await d(`bindBuffer + bufferData with Float32Array`,async()=>{let e=_.createBuffer();_.bindBuffer(_.ARRAY_BUFFER,e);let t=new Float32Array([1,2,3,4]);u(()=>_.bufferData(_.ARRAY_BUFFER,t,_.STATIC_DRAW)).not.toThrow()}),await d(`getBufferParameter returns buffer size`,async()=>{let e=_.createBuffer();_.bindBuffer(_.ARRAY_BUFFER,e);let t=new Float32Array([1,2,3,4]);_.bufferData(_.ARRAY_BUFFER,t,_.STATIC_DRAW),u(_.getBufferParameter(_.ARRAY_BUFFER,_.BUFFER_SIZE)).toBe(t.byteLength)}),await d(`bufferSubData updates buffer data`,async()=>{let e=_.createBuffer();_.bindBuffer(_.ARRAY_BUFFER,e);let t=new Float32Array([1,2,3,4]);_.bufferData(_.ARRAY_BUFFER,t,_.DYNAMIC_DRAW),u(()=>_.bufferSubData(_.ARRAY_BUFFER,0,new Float32Array([9,9]))).not.toThrow()}),await d(`deleteBuffer cleans up`,async()=>{let e=_.createBuffer();u(()=>_.deleteBuffer(e)).not.toThrow()})}),await l(`Shaders`,async()=>{c(async()=>{f.make_current()});let e=`attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); }`,t=`void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }`;await d(`createShader returns a WebGLShader`,async()=>{let e=_.createShader(_.VERTEX_SHADER);u(e).toBeDefined(),u(e).not.toBeNull()}),await d(`vertex shader compiles successfully`,async()=>{let t=_.createShader(_.VERTEX_SHADER);_.shaderSource(t,e),_.compileShader(t);let n=_.getShaderParameter(t,_.COMPILE_STATUS);n||console.error(`Vertex shader log:`,_.getShaderInfoLog(t)),u(n).toBeTruthy()}),await d(`fragment shader compiles successfully`,async()=>{let e=_.createShader(_.FRAGMENT_SHADER);_.shaderSource(e,t),_.compileShader(e);let n=_.getShaderParameter(e,_.COMPILE_STATUS);n||console.error(`Fragment shader log:`,_.getShaderInfoLog(e)),u(n).toBeTruthy()}),await d(`program links successfully`,async()=>{let n=_.createShader(_.VERTEX_SHADER);_.shaderSource(n,e),_.compileShader(n);let r=_.createShader(_.FRAGMENT_SHADER);_.shaderSource(r,t),_.compileShader(r);let i=_.createProgram();_.attachShader(i,n),_.attachShader(i,r),_.linkProgram(i);let a=_.getProgramParameter(i,_.LINK_STATUS);a||console.error(`Program log:`,_.getProgramInfoLog(i)),u(a).toBeTruthy()})}),await l(`Textures`,async()=>{c(async()=>{f.make_current()}),await d(`createTexture returns a WebGLTexture`,async()=>{let e=_.createTexture();u(e).toBeDefined(),u(e).not.toBeNull()}),await d(`bindTexture + texImage2D with Uint8Array`,async()=>{let e=_.createTexture();_.bindTexture(_.TEXTURE_2D,e);let t=new Uint8Array([255,0,0,255]);u(()=>_.texImage2D(_.TEXTURE_2D,0,_.RGBA,1,1,0,_.RGBA,_.UNSIGNED_BYTE,t)).not.toThrow()}),await d(`texParameteri sets filter params without error`,async()=>{let e=_.createTexture();_.bindTexture(_.TEXTURE_2D,e),u(()=>{_.texParameteri(_.TEXTURE_2D,_.TEXTURE_MIN_FILTER,_.NEAREST),_.texParameteri(_.TEXTURE_2D,_.TEXTURE_MAG_FILTER,_.NEAREST),_.texParameteri(_.TEXTURE_2D,_.TEXTURE_WRAP_S,_.CLAMP_TO_EDGE),_.texParameteri(_.TEXTURE_2D,_.TEXTURE_WRAP_T,_.CLAMP_TO_EDGE)}).not.toThrow()}),await d(`deleteTexture cleans up`,async()=>{let e=_.createTexture();u(()=>_.deleteTexture(e)).not.toThrow()})}),await l(`Draw`,async()=>{c(async()=>{f.make_current()}),await d(`clearColor + clear does not throw`,async()=>{u(()=>{_.clearColor(0,0,0,1),_.clear(_.COLOR_BUFFER_BIT)}).not.toThrow(),u(_.getError()).toBe(_.NO_ERROR)}),await d(`viewport does not throw`,async()=>{u(()=>_.viewport(0,0,200,200)).not.toThrow()}),await d(`drawArrays (triangle) produces no GL error`,async()=>{let e=_.createShader(_.VERTEX_SHADER);_.shaderSource(e,`attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); }`),_.compileShader(e);let t=_.createShader(_.FRAGMENT_SHADER);_.shaderSource(t,`void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }`),_.compileShader(t);let n=_.createProgram();_.attachShader(n,e),_.attachShader(n,t),_.linkProgram(n),_.useProgram(n);let r=_.createBuffer();_.bindBuffer(_.ARRAY_BUFFER,r),_.bufferData(_.ARRAY_BUFFER,new Float32Array([-1,0,0,-1,1,1]),_.STATIC_DRAW);let i=_.getAttribLocation(n,`position`);_.enableVertexAttribArray(i),_.vertexAttribPointer(i,2,_.FLOAT,!1,0,0),_.clearColor(0,0,0,1),_.clear(_.COLOR_BUFFER_BIT),u(()=>_.drawArrays(_.TRIANGLES,0,3)).not.toThrow(),u(_.getError()).toBe(_.NO_ERROR)})}),await l(`Extensions`,async()=>{c(async()=>{f.make_current()}),await d(`OES_texture_float is supported`,async()=>{u(_.getExtension(`OES_texture_float`)).not.toBeNull()}),await d(`OES_standard_derivatives is supported`,async()=>{u(_.getExtension(`OES_standard_derivatives`)).not.toBeNull()}),await d(`OES_element_index_uint is supported`,async()=>{u(_.getExtension(`OES_element_index_uint`)).not.toBeNull()}),await d(`getSupportedExtensions returns an array`,async()=>{let e=_.getSupportedExtensions();u(Array.isArray(e)).toBeTruthy(),u((e?.length??0)>0).toBeTruthy()})}),await l(`Gwebgl.WebGLRenderingContext native bindings`,async()=>{c(async()=>{f.make_current()}),await d(`getParameterb returns a boolean`,async()=>{let e=_?._native.getParameterb(_?.BLEND);u(typeof e).toBe(`boolean`)}),await d(`getParameterbv returns an array of booleans`,async()=>{let e=_?._native.getParameterbv(_?.COLOR_WRITEMASK,16);if(u(Array.isArray(e)).toBeTruthy(),Array.isArray(e))for(let t of e)u(typeof t).toBe(`boolean`)}),await d(`getParameterf returns a float`,async()=>{let e=_?._native.getParameterf(_?.SAMPLE_COVERAGE_VALUE);u(typeof e).toBe(`number`)}),await d(`getParameterfv returns an array of floats`,async()=>{let e=_?._native.getParameterfv(_?.DEPTH_RANGE,8);if(u(Array.isArray(e)).toBeTruthy(),Array.isArray(e))for(let t of e)u(typeof t).toBe(`number`)}),await d(`getParameteri returns an integer`,async()=>{let e=_?._native.getParameteri(_?.ARRAY_BUFFER_BINDING);u(typeof e).toBe(`number`)}),await d(`getParameteriv returns an array of integers`,async()=>{let e=_?._native.getParameteriv(_?.MAX_VIEWPORT_DIMS,8);if(u(Array.isArray(e)).toBeTruthy(),Array.isArray(e))for(let t of e)u(typeof t).toBe(`number`)})}),await l(`simple-shader rendering`,async()=>{c(async()=>{f.make_current()}),await d(`renders a green triangle — all pixels (0,255,0,255)`,async()=>{let t=i(_,8,8);_.clearColor(0,0,0,1),_.clear(_.COLOR_BUFFER_BIT);let a=r(_,`attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); }`,`void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }`);u(_.getProgramParameter(a,_.LINK_STATUS)).toBeTruthy(),_.useProgram(a),n(_),u(_.getError()).toBe(_.NO_ERROR);let o=new Uint8Array(t.width*t.height*4);_.readPixels(0,0,t.width,t.height,_.RGBA,_.UNSIGNED_BYTE,o);let s=!0;for(let e=0;e<o.length;e+=4)if(o[e]!==0||o[e+1]!==255||o[e+2]!==0||o[e+3]!==255){s=!1;break}u(s).toBeTruthy(),_.deleteProgram(a),e(_,t)})}),await l(`clearColor`,async()=>{c(async()=>{f.make_current()}),await d(`clears to black (0,0,0,0)`,async()=>{let t=i(_);_.clearColor(0,0,0,0),_.clear(_.COLOR_BUFFER_BIT);let n=s(_,0,0);e(_,t),u(n[0]).toBe(0),u(n[1]).toBe(0),u(n[2]).toBe(0),u(n[3]).toBe(0)}),await d(`clears to white (255,255,255,255)`,async()=>{let t=i(_);_.clearColor(1,1,1,1),_.clear(_.COLOR_BUFFER_BIT);let n=s(_,0,0);e(_,t),u(n[0]).toBe(255),u(n[1]).toBe(255),u(n[2]).toBe(255),u(n[3]).toBe(255)}),await d(`clears to green (0,255,0,255)`,async()=>{let t=i(_);_.clearColor(0,1,0,1),_.clear(_.COLOR_BUFFER_BIT);let n=s(_,0,0);e(_,t),u(n[0]).toBe(0),u(n[1]).toBe(255),u(n[2]).toBe(0),u(n[3]).toBe(255)}),await d(`clears to magenta (255,0,255,255)`,async()=>{let t=i(_);_.clearColor(1,0,1,1),_.clear(_.COLOR_BUFFER_BIT);let n=s(_,0,0);e(_,t),u(n[0]).toBe(255),u(n[1]).toBe(0),u(n[2]).toBe(255),u(n[3]).toBe(255)})}),await l(`blending`,async()=>{c(async()=>{f.make_current()});let t=[`precision mediump float;`,`attribute vec2 position;`,`void main() { gl_Position = vec4(position, 0.0, 1.0); }`].join(`
2
+ `),a=[{name:`ADD ONE ONE`,equn:_.FUNC_ADD,func1:_.ONE,func2:_.ONE,dstColor:[.5,.5,.5,1],srcColor:[.5,.5,.5,1],expected:[255,255,255,255]},{name:`ADD ONE ZERO`,equn:_.FUNC_ADD,func1:_.ONE,func2:_.ZERO,dstColor:[.5,.5,.5,.5],srcColor:[.2,.2,.2,1],expected:[51,51,51,255]},{name:`ADD ZERO SRC_COLOR`,equn:_.FUNC_ADD,func1:_.ZERO,func2:_.SRC_COLOR,dstColor:[.8,.8,.8,1],srcColor:[.5,.5,.5,.5],expected:[102,102,102,128]},{name:`ADD DST_COLOR ZERO`,equn:_.FUNC_ADD,func1:_.DST_COLOR,func2:_.ZERO,dstColor:[.8,.8,.8,1],srcColor:[.5,.5,.5,.5],expected:[102,102,102,128]},{name:`ADD SRC_ALPHA ONE_MINUS_SRC_ALPHA`,equn:_.FUNC_ADD,func1:_.SRC_ALPHA,func2:_.ONE_MINUS_SRC_ALPHA,dstColor:[.5,0,.5,1],srcColor:[.5,1,0,.5],expected:[127,127,64,191]}];for(let c of a){let{name:a,equn:l,func1:f,func2:p,dstColor:m,srcColor:h,expected:g}=c,v=[`precision mediump float;`,`void main() { gl_FragColor = vec4(${h[0]},${h[1]},${h[2]},${h[3]}); }`].join(`
3
+ `);await d(a,async()=>{let a=i(_);_.clearColor(m[0],m[1],m[2],m[3]),_.clear(_.COLOR_BUFFER_BIT);let c=r(_,t,v);_.useProgram(c),_.enable(_.BLEND),_.blendEquation(l),_.blendFunc(f,p),n(_),u(_.getError()).toBe(_.NO_ERROR),_.disable(_.BLEND);let d=s(_,0,0);_.deleteProgram(c),e(_,a),u(o(d,g)).toBeTruthy()})}}),await l(`drawElements (indexed drawing)`,async()=>{c(async()=>{f.make_current()}),await d(`draws a quad via index buffer — all pixels green`,async()=>{let t=i(_,8,8);_.clearColor(1,0,0,1),_.clear(_.COLOR_BUFFER_BIT);let n=r(_,`attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); }`,`void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }`);_.useProgram(n);let a=_.createBuffer();_.bindBuffer(_.ARRAY_BUFFER,a),_.bufferData(_.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),_.STATIC_DRAW),_.enableVertexAttribArray(0),_.vertexAttribPointer(0,2,_.FLOAT,!1,0,0);let o=_.createBuffer();_.bindBuffer(_.ELEMENT_ARRAY_BUFFER,o),_.bufferData(_.ELEMENT_ARRAY_BUFFER,new Uint16Array([0,1,2,2,1,3]),_.STATIC_DRAW),_.drawElements(_.TRIANGLES,6,_.UNSIGNED_SHORT,0),u(_.getError()).toBe(_.NO_ERROR);let s=new Uint8Array(t.width*t.height*4);_.readPixels(0,0,t.width,t.height,_.RGBA,_.UNSIGNED_BYTE,s);let c=!0;for(let e=0;e<s.length;e+=4)if(s[e]!==0||s[e+1]!==255||s[e+2]!==0||s[e+3]!==255){c=!1;break}u(c).toBeTruthy(),_.disableVertexAttribArray(0),_.deleteBuffer(a),_.deleteBuffer(o),_.deleteProgram(n),e(_,t)})}),await l(`readPixels`,async()=>{c(async()=>{f.make_current()}),await d(`RGBA + UNSIGNED_BYTE returns correct data size`,async()=>{let t=i(_,4,4);_.clearColor(1,0,0,1),_.clear(_.COLOR_BUFFER_BIT);let n=new Uint8Array(t.width*t.height*4);_.readPixels(0,0,t.width,t.height,_.RGBA,_.UNSIGNED_BYTE,n),u(_.getError()).toBe(_.NO_ERROR),u(n.length).toBe(t.width*t.height*4),e(_,t)}),await d(`pixel values match the clear color`,async()=>{let t=i(_);_.clearColor(0,0,1,1),_.clear(_.COLOR_BUFFER_BIT);let n=s(_,0,0);e(_,t),u(n[0]).toBe(0),u(n[1]).toBe(0),u(n[2]).toBe(255),u(n[3]).toBe(255)}),await d(`readPixels reads a single red pixel`,async()=>{let t=i(_);_.clearColor(1,0,0,1),_.clear(_.COLOR_BUFFER_BIT);let n=new Uint8Array(4);_.readPixels(0,0,1,1,_.RGBA,_.UNSIGNED_BYTE,n),e(_,t),u(n[0]).toBe(255),u(n[1]).toBe(0),u(n[2]).toBe(0),u(n[3]).toBe(255)})}),await l(`depth buffer`,async()=>{c(async()=>{f.make_current()}),await d(`depth test (LESS) — nearer triangle occludes farther one`,async()=>{let e=[`attribute vec2 position;`,`uniform float depth;`,`void main() { gl_Position = vec4(position, depth, 1.0); }`].join(`
4
+ `),i=[`precision mediump float;`,`uniform vec4 color;`,`void main() { gl_FragColor = color; }`].join(`
5
+ `),o=a(_,4,4);_.clearColor(0,0,0,1),_.clearDepth(1),_.clear(_.COLOR_BUFFER_BIT|_.DEPTH_BUFFER_BIT),_.enable(_.DEPTH_TEST),_.depthFunc(_.LESS);let c=r(_,e,i);_.useProgram(c),_.uniform1f(_.getUniformLocation(c,`depth`),0),_.uniform4f(_.getUniformLocation(c,`color`),1,0,0,1),n(_),_.uniform1f(_.getUniformLocation(c,`depth`),.5),_.uniform4f(_.getUniformLocation(c,`color`),0,0,1,1),n(_),u(_.getError()).toBe(_.NO_ERROR),_.disable(_.DEPTH_TEST);let l=s(_,0,0);_.deleteProgram(c),t(_,o),u(l[0]).toBe(255),u(l[1]).toBe(0),u(l[2]).toBe(0)})}),await l(`uniform1fv regression`,async()=>{c(async()=>{f.make_current()});let t=[`attribute vec2 position;`,`void main() { gl_Position = vec4(position, 0.0, 1.0); }`].join(`
6
+ `);await d(`uniform1fv sets a float uniform and affects rendering`,async()=>{let a=[`precision mediump float;`,`uniform float uRed;`,`void main() { gl_FragColor = vec4(uRed, 0.0, 0.0, 1.0); }`].join(`
7
+ `),o=r(_,t,a);u(_.getProgramParameter(o,_.LINK_STATUS)).toBeTruthy(),_.useProgram(o);let c=_.getUniformLocation(o,`uRed`);u(c).not.toBeNull(),_.uniform1fv(c,new Float32Array([1])),u(_.getError()).toBe(_.NO_ERROR);let l=i(_,4,4);_.clearColor(0,0,0,1),_.clear(_.COLOR_BUFFER_BIT),n(_);let d=s(_,0,0);e(_,l),u(d[0]).toBe(255),u(d[1]).toBe(0),u(d[2]).toBe(0),_.deleteProgram(o)}),await d(`uniform1fv sets each array element individually`,async()=>{let a=[`precision mediump float;`,`uniform float uWeights[3];`,`void main() { gl_FragColor = vec4(uWeights[0], uWeights[1], uWeights[2], 1.0); }`].join(`
8
+ `),o=r(_,t,a);u(_.getProgramParameter(o,_.LINK_STATUS)).toBeTruthy(),_.useProgram(o);let c=_.getUniformLocation(o,`uWeights[0]`),l=_.getUniformLocation(o,`uWeights[1]`),d=_.getUniformLocation(o,`uWeights[2]`);u(c).not.toBeNull(),u(l).not.toBeNull(),u(d).not.toBeNull(),_.uniform1fv(c,new Float32Array([0])),_.uniform1fv(l,new Float32Array([1])),_.uniform1fv(d,new Float32Array([0])),u(_.getError()).toBe(_.NO_ERROR);let f=i(_,4,4);_.clearColor(0,0,0,1),_.clear(_.COLOR_BUFFER_BIT),n(_);let p=s(_,0,0);e(_,f),u(p[0]).toBe(0),u(p[1]).toBe(255),u(p[2]).toBe(0),_.deleteProgram(o)})}),await l(`linkProgram with inactive attributes`,async()=>{c(async()=>{f.make_current()}),await d(`links a program whose vertex shader declares but does not use an attribute`,async()=>{let t=[`attribute vec2 position;`,`attribute vec3 unused;`,`void main() { gl_Position = vec4(position, 0.0, 1.0); }`].join(`
9
+ `),a=[`precision mediump float;`,`void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }`].join(`
10
+ `),o=r(_,t,a);u(_.getProgramParameter(o,_.LINK_STATUS)).toBeTruthy(),u(_.getError()).toBe(_.NO_ERROR),_.useProgram(o);let c=i(_,4,4);_.clearColor(0,0,0,1),_.clear(_.COLOR_BUFFER_BIT),n(_),u(_.getError()).toBe(_.NO_ERROR);let l=s(_,0,0);e(_,c),u(l[1]).toBe(255),_.deleteProgram(o)})}),y.destroy()})};export{_ as default};