@gjsify/webgl 0.0.4 → 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 -31
- 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 -13
- 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 -39937
- package/test.gjs.js.meta.json +0 -1
- package/tmp/.tsbuildinfo +0 -1
- package/tsconfig.json +0 -38
- package/tsconfig.types.json +0 -7
package/lib/esm/index.spec.js
CHANGED
|
@@ -1,144 +1,653 @@
|
|
|
1
|
-
import { describe, it, expect } from "@gjsify/unit";
|
|
2
|
-
import {
|
|
1
|
+
import { describe, it, expect, beforeEach, on } from "@gjsify/unit";
|
|
2
|
+
import { CanvasWebGLWidget } from "@gjsify/webgl";
|
|
3
|
+
import {
|
|
4
|
+
makeProgram,
|
|
5
|
+
drawTriangle,
|
|
6
|
+
readPixel,
|
|
7
|
+
pixelClose,
|
|
8
|
+
makeTestFBO,
|
|
9
|
+
destroyTestFBO,
|
|
10
|
+
makeTestFBOWithDepth,
|
|
11
|
+
destroyTestFBOWithDepth
|
|
12
|
+
} from "./test-utils.js";
|
|
3
13
|
import GLib from "@girs/glib-2.0";
|
|
4
14
|
import Gtk from "@girs/gtk-4.0";
|
|
5
|
-
import Gio from "@girs/gio-2.0";
|
|
6
15
|
const GL_CONSTANT_NAMES = ["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"];
|
|
7
16
|
var index_spec_default = async () => {
|
|
8
|
-
|
|
9
|
-
let win;
|
|
10
|
-
let glArea;
|
|
11
|
-
let canvas;
|
|
12
|
-
let ctx;
|
|
13
|
-
if (GLib.getenv("CI") || GLib.getenv("GITHUB_ACTIONS") || GLib.getenv("TRAVIS") || GLib.getenv("CIRCLECI") || GLib.getenv("GITLAB_CI")) {
|
|
14
|
-
console.info("Skipping webgl tests on CI");
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
const initApp = async () => {
|
|
17
|
+
await on("Display", async () => {
|
|
18
18
|
Gtk.init();
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
win.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
19
|
+
let glArea;
|
|
20
|
+
let gl;
|
|
21
|
+
const readyLoop = new GLib.MainLoop(null, false);
|
|
22
|
+
const win = new Gtk.Window({});
|
|
23
|
+
win.set_default_size(200, 200);
|
|
24
|
+
glArea = new CanvasWebGLWidget();
|
|
25
|
+
glArea.onReady((_c, g) => {
|
|
26
|
+
gl = g;
|
|
27
|
+
readyLoop.quit();
|
|
28
|
+
});
|
|
29
|
+
win.set_child(glArea);
|
|
30
|
+
win.present();
|
|
31
|
+
const giveUpId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1e4, () => {
|
|
32
|
+
readyLoop.quit();
|
|
33
|
+
return GLib.SOURCE_REMOVE;
|
|
34
|
+
});
|
|
35
|
+
readyLoop.run();
|
|
36
|
+
GLib.source_remove(giveUpId);
|
|
37
|
+
if (!gl) {
|
|
38
|
+
console.warn("WebGL context not available after 10s \u2014 skipping tests");
|
|
39
|
+
win.destroy();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
glArea.make_current();
|
|
43
|
+
await describe("WebGLRenderingContext constants", async () => {
|
|
44
|
+
beforeEach(async () => {
|
|
37
45
|
glArea.make_current();
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
});
|
|
47
|
+
await it("should have all standard WebGL constants as numbers", async () => {
|
|
48
|
+
for (const name of GL_CONSTANT_NAMES) {
|
|
49
|
+
const value = gl?.[name];
|
|
50
|
+
expect(typeof value).toBe("number");
|
|
51
|
+
if (name === "NONE" || name === "ZERO" || name === "NO_ERROR" || name === "POINTS") {
|
|
52
|
+
expect(value === 0).toBeTruthy();
|
|
53
|
+
} else {
|
|
54
|
+
expect(value > 0).toBeTruthy();
|
|
55
|
+
}
|
|
41
56
|
}
|
|
42
|
-
resolve(glArea);
|
|
43
57
|
});
|
|
44
58
|
});
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
await describe("Buffers", async () => {
|
|
60
|
+
beforeEach(async () => {
|
|
61
|
+
glArea.make_current();
|
|
62
|
+
});
|
|
63
|
+
await it("createBuffer returns a WebGLBuffer", async () => {
|
|
64
|
+
const buf = gl.createBuffer();
|
|
65
|
+
expect(buf).toBeDefined();
|
|
66
|
+
expect(buf).not.toBeNull();
|
|
67
|
+
});
|
|
68
|
+
await it("bindBuffer + bufferData with Float32Array", async () => {
|
|
69
|
+
const buf = gl.createBuffer();
|
|
70
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
|
|
71
|
+
const data = new Float32Array([1, 2, 3, 4]);
|
|
72
|
+
expect(() => gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW)).not.toThrow();
|
|
73
|
+
});
|
|
74
|
+
await it("getBufferParameter returns buffer size", async () => {
|
|
75
|
+
const buf = gl.createBuffer();
|
|
76
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
|
|
77
|
+
const data = new Float32Array([1, 2, 3, 4]);
|
|
78
|
+
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
|
|
79
|
+
const size = gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE);
|
|
80
|
+
expect(size).toBe(data.byteLength);
|
|
81
|
+
});
|
|
82
|
+
await it("bufferSubData updates buffer data", async () => {
|
|
83
|
+
const buf = gl.createBuffer();
|
|
84
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
|
|
85
|
+
const data = new Float32Array([1, 2, 3, 4]);
|
|
86
|
+
gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW);
|
|
87
|
+
expect(() => gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array([9, 9]))).not.toThrow();
|
|
88
|
+
});
|
|
89
|
+
await it("deleteBuffer cleans up", async () => {
|
|
90
|
+
const buf = gl.createBuffer();
|
|
91
|
+
expect(() => gl.deleteBuffer(buf)).not.toThrow();
|
|
92
|
+
});
|
|
57
93
|
});
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
94
|
+
await describe("Shaders", async () => {
|
|
95
|
+
beforeEach(async () => {
|
|
96
|
+
glArea.make_current();
|
|
97
|
+
});
|
|
98
|
+
const vertSrc = "attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); }";
|
|
99
|
+
const fragSrc = "void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }";
|
|
100
|
+
await it("createShader returns a WebGLShader", async () => {
|
|
101
|
+
const shader = gl.createShader(gl.VERTEX_SHADER);
|
|
102
|
+
expect(shader).toBeDefined();
|
|
103
|
+
expect(shader).not.toBeNull();
|
|
104
|
+
});
|
|
105
|
+
await it("vertex shader compiles successfully", async () => {
|
|
106
|
+
const shader = gl.createShader(gl.VERTEX_SHADER);
|
|
107
|
+
gl.shaderSource(shader, vertSrc);
|
|
108
|
+
gl.compileShader(shader);
|
|
109
|
+
const status = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
|
|
110
|
+
if (!status) {
|
|
111
|
+
console.error("Vertex shader log:", gl.getShaderInfoLog(shader));
|
|
112
|
+
}
|
|
113
|
+
expect(status).toBeTruthy();
|
|
114
|
+
});
|
|
115
|
+
await it("fragment shader compiles successfully", async () => {
|
|
116
|
+
const shader = gl.createShader(gl.FRAGMENT_SHADER);
|
|
117
|
+
gl.shaderSource(shader, fragSrc);
|
|
118
|
+
gl.compileShader(shader);
|
|
119
|
+
const status = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
|
|
120
|
+
if (!status) {
|
|
121
|
+
console.error("Fragment shader log:", gl.getShaderInfoLog(shader));
|
|
122
|
+
}
|
|
123
|
+
expect(status).toBeTruthy();
|
|
124
|
+
});
|
|
125
|
+
await it("program links successfully", async () => {
|
|
126
|
+
const vert = gl.createShader(gl.VERTEX_SHADER);
|
|
127
|
+
gl.shaderSource(vert, vertSrc);
|
|
128
|
+
gl.compileShader(vert);
|
|
129
|
+
const frag = gl.createShader(gl.FRAGMENT_SHADER);
|
|
130
|
+
gl.shaderSource(frag, fragSrc);
|
|
131
|
+
gl.compileShader(frag);
|
|
132
|
+
const prog = gl.createProgram();
|
|
133
|
+
gl.attachShader(prog, vert);
|
|
134
|
+
gl.attachShader(prog, frag);
|
|
135
|
+
gl.linkProgram(prog);
|
|
136
|
+
const status = gl.getProgramParameter(prog, gl.LINK_STATUS);
|
|
137
|
+
if (!status) {
|
|
138
|
+
console.error("Program log:", gl.getProgramInfoLog(prog));
|
|
139
|
+
}
|
|
140
|
+
expect(status).toBeTruthy();
|
|
141
|
+
});
|
|
63
142
|
});
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
143
|
+
await describe("Textures", async () => {
|
|
144
|
+
beforeEach(async () => {
|
|
145
|
+
glArea.make_current();
|
|
146
|
+
});
|
|
147
|
+
await it("createTexture returns a WebGLTexture", async () => {
|
|
148
|
+
const tex = gl.createTexture();
|
|
149
|
+
expect(tex).toBeDefined();
|
|
150
|
+
expect(tex).not.toBeNull();
|
|
151
|
+
});
|
|
152
|
+
await it("bindTexture + texImage2D with Uint8Array", async () => {
|
|
153
|
+
const tex = gl.createTexture();
|
|
154
|
+
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
155
|
+
const pixels = new Uint8Array([255, 0, 0, 255]);
|
|
156
|
+
expect(() => gl.texImage2D(
|
|
157
|
+
gl.TEXTURE_2D,
|
|
158
|
+
0,
|
|
159
|
+
gl.RGBA,
|
|
160
|
+
1,
|
|
161
|
+
1,
|
|
162
|
+
0,
|
|
163
|
+
gl.RGBA,
|
|
164
|
+
gl.UNSIGNED_BYTE,
|
|
165
|
+
pixels
|
|
166
|
+
)).not.toThrow();
|
|
167
|
+
});
|
|
168
|
+
await it("texParameteri sets filter params without error", async () => {
|
|
169
|
+
const tex = gl.createTexture();
|
|
170
|
+
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
171
|
+
expect(() => {
|
|
172
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
173
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
174
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
175
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
176
|
+
}).not.toThrow();
|
|
177
|
+
});
|
|
178
|
+
await it("deleteTexture cleans up", async () => {
|
|
179
|
+
const tex = gl.createTexture();
|
|
180
|
+
expect(() => gl.deleteTexture(tex)).not.toThrow();
|
|
181
|
+
});
|
|
80
182
|
});
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
183
|
+
await describe("Draw", async () => {
|
|
184
|
+
beforeEach(async () => {
|
|
185
|
+
glArea.make_current();
|
|
186
|
+
});
|
|
187
|
+
await it("clearColor + clear does not throw", async () => {
|
|
188
|
+
expect(() => {
|
|
189
|
+
gl.clearColor(0, 0, 0, 1);
|
|
190
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
191
|
+
}).not.toThrow();
|
|
192
|
+
expect(gl.getError()).toBe(gl.NO_ERROR);
|
|
193
|
+
});
|
|
194
|
+
await it("viewport does not throw", async () => {
|
|
195
|
+
expect(() => gl.viewport(0, 0, 200, 200)).not.toThrow();
|
|
196
|
+
});
|
|
197
|
+
await it("drawArrays (triangle) produces no GL error", async () => {
|
|
198
|
+
const vertSrc = "attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); }";
|
|
199
|
+
const fragSrc = "void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }";
|
|
200
|
+
const vert = gl.createShader(gl.VERTEX_SHADER);
|
|
201
|
+
gl.shaderSource(vert, vertSrc);
|
|
202
|
+
gl.compileShader(vert);
|
|
203
|
+
const frag = gl.createShader(gl.FRAGMENT_SHADER);
|
|
204
|
+
gl.shaderSource(frag, fragSrc);
|
|
205
|
+
gl.compileShader(frag);
|
|
206
|
+
const prog = gl.createProgram();
|
|
207
|
+
gl.attachShader(prog, vert);
|
|
208
|
+
gl.attachShader(prog, frag);
|
|
209
|
+
gl.linkProgram(prog);
|
|
210
|
+
gl.useProgram(prog);
|
|
211
|
+
const buf = gl.createBuffer();
|
|
212
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
|
|
213
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, 0, 0, -1, 1, 1]), gl.STATIC_DRAW);
|
|
214
|
+
const loc = gl.getAttribLocation(prog, "position");
|
|
215
|
+
gl.enableVertexAttribArray(loc);
|
|
216
|
+
gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
|
|
217
|
+
gl.clearColor(0, 0, 0, 1);
|
|
218
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
219
|
+
expect(() => gl.drawArrays(gl.TRIANGLES, 0, 3)).not.toThrow();
|
|
220
|
+
expect(gl.getError()).toBe(gl.NO_ERROR);
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
await describe("Extensions", async () => {
|
|
224
|
+
beforeEach(async () => {
|
|
225
|
+
glArea.make_current();
|
|
226
|
+
});
|
|
227
|
+
await it("OES_texture_float is supported", async () => {
|
|
228
|
+
const ext = gl.getExtension("OES_texture_float");
|
|
229
|
+
expect(ext).not.toBeNull();
|
|
230
|
+
});
|
|
231
|
+
await it("OES_standard_derivatives is supported", async () => {
|
|
232
|
+
const ext = gl.getExtension("OES_standard_derivatives");
|
|
233
|
+
expect(ext).not.toBeNull();
|
|
234
|
+
});
|
|
235
|
+
await it("OES_element_index_uint is supported", async () => {
|
|
236
|
+
const ext = gl.getExtension("OES_element_index_uint");
|
|
237
|
+
expect(ext).not.toBeNull();
|
|
238
|
+
});
|
|
239
|
+
await it("getSupportedExtensions returns an array", async () => {
|
|
240
|
+
const exts = gl.getSupportedExtensions();
|
|
241
|
+
expect(Array.isArray(exts)).toBeTruthy();
|
|
242
|
+
expect((exts?.length ?? 0) > 0).toBeTruthy();
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
await describe("Gwebgl.WebGLRenderingContext native bindings", async () => {
|
|
246
|
+
beforeEach(async () => {
|
|
247
|
+
glArea.make_current();
|
|
248
|
+
});
|
|
249
|
+
await it("getParameterb returns a boolean", async () => {
|
|
250
|
+
const res = gl?._native.getParameterb(gl?.BLEND);
|
|
251
|
+
expect(typeof res).toBe("boolean");
|
|
252
|
+
});
|
|
253
|
+
await it("getParameterbv returns an array of booleans", async () => {
|
|
254
|
+
const results = gl?._native.getParameterbv(gl?.COLOR_WRITEMASK, 16);
|
|
255
|
+
expect(Array.isArray(results)).toBeTruthy();
|
|
256
|
+
if (Array.isArray(results)) {
|
|
257
|
+
for (const r of results) expect(typeof r).toBe("boolean");
|
|
92
258
|
}
|
|
93
|
-
}
|
|
259
|
+
});
|
|
260
|
+
await it("getParameterf returns a float", async () => {
|
|
261
|
+
const result = gl?._native.getParameterf(gl?.SAMPLE_COVERAGE_VALUE);
|
|
262
|
+
expect(typeof result).toBe("number");
|
|
263
|
+
});
|
|
264
|
+
await it("getParameterfv returns an array of floats", async () => {
|
|
265
|
+
const results = gl?._native.getParameterfv(gl?.DEPTH_RANGE, 8);
|
|
266
|
+
expect(Array.isArray(results)).toBeTruthy();
|
|
267
|
+
if (Array.isArray(results)) {
|
|
268
|
+
for (const r of results) expect(typeof r).toBe("number");
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
await it("getParameteri returns an integer", async () => {
|
|
272
|
+
const result = gl?._native.getParameteri(gl?.ARRAY_BUFFER_BINDING);
|
|
273
|
+
expect(typeof result).toBe("number");
|
|
274
|
+
});
|
|
275
|
+
await it("getParameteriv returns an array of integers", async () => {
|
|
276
|
+
const results = gl?._native.getParameteriv(gl?.MAX_VIEWPORT_DIMS, 8);
|
|
277
|
+
expect(Array.isArray(results)).toBeTruthy();
|
|
278
|
+
if (Array.isArray(results)) {
|
|
279
|
+
for (const r of results) expect(typeof r).toBe("number");
|
|
280
|
+
}
|
|
281
|
+
});
|
|
94
282
|
});
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
283
|
+
await describe("simple-shader rendering", async () => {
|
|
284
|
+
beforeEach(async () => {
|
|
285
|
+
glArea.make_current();
|
|
286
|
+
});
|
|
287
|
+
const VS = "attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); }";
|
|
288
|
+
const FS = "void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }";
|
|
289
|
+
await it("renders a green triangle \u2014 all pixels (0,255,0,255)", async () => {
|
|
290
|
+
const fbo = makeTestFBO(gl, 8, 8);
|
|
291
|
+
gl.clearColor(0, 0, 0, 1);
|
|
292
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
293
|
+
const prog = makeProgram(gl, VS, FS);
|
|
294
|
+
expect(gl.getProgramParameter(prog, gl.LINK_STATUS)).toBeTruthy();
|
|
295
|
+
gl.useProgram(prog);
|
|
296
|
+
drawTriangle(gl);
|
|
297
|
+
expect(gl.getError()).toBe(gl.NO_ERROR);
|
|
298
|
+
const pixels = new Uint8Array(fbo.width * fbo.height * 4);
|
|
299
|
+
gl.readPixels(0, 0, fbo.width, fbo.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
|
300
|
+
let allGreen = true;
|
|
301
|
+
for (let i = 0; i < pixels.length; i += 4) {
|
|
302
|
+
if (pixels[i] !== 0 || pixels[i + 1] !== 255 || pixels[i + 2] !== 0 || pixels[i + 3] !== 255) {
|
|
303
|
+
allGreen = false;
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
109
306
|
}
|
|
110
|
-
|
|
307
|
+
expect(allGreen).toBeTruthy();
|
|
308
|
+
gl.deleteProgram(prog);
|
|
309
|
+
destroyTestFBO(gl, fbo);
|
|
310
|
+
});
|
|
111
311
|
});
|
|
112
|
-
await
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
312
|
+
await describe("clearColor", async () => {
|
|
313
|
+
beforeEach(async () => {
|
|
314
|
+
glArea.make_current();
|
|
315
|
+
});
|
|
316
|
+
await it("clears to black (0,0,0,0)", async () => {
|
|
317
|
+
const fbo = makeTestFBO(gl);
|
|
318
|
+
gl.clearColor(0, 0, 0, 0);
|
|
319
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
320
|
+
const p = readPixel(gl, 0, 0);
|
|
321
|
+
destroyTestFBO(gl, fbo);
|
|
322
|
+
expect(p[0]).toBe(0);
|
|
323
|
+
expect(p[1]).toBe(0);
|
|
324
|
+
expect(p[2]).toBe(0);
|
|
325
|
+
expect(p[3]).toBe(0);
|
|
326
|
+
});
|
|
327
|
+
await it("clears to white (255,255,255,255)", async () => {
|
|
328
|
+
const fbo = makeTestFBO(gl);
|
|
329
|
+
gl.clearColor(1, 1, 1, 1);
|
|
330
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
331
|
+
const p = readPixel(gl, 0, 0);
|
|
332
|
+
destroyTestFBO(gl, fbo);
|
|
333
|
+
expect(p[0]).toBe(255);
|
|
334
|
+
expect(p[1]).toBe(255);
|
|
335
|
+
expect(p[2]).toBe(255);
|
|
336
|
+
expect(p[3]).toBe(255);
|
|
337
|
+
});
|
|
338
|
+
await it("clears to green (0,255,0,255)", async () => {
|
|
339
|
+
const fbo = makeTestFBO(gl);
|
|
340
|
+
gl.clearColor(0, 1, 0, 1);
|
|
341
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
342
|
+
const p = readPixel(gl, 0, 0);
|
|
343
|
+
destroyTestFBO(gl, fbo);
|
|
344
|
+
expect(p[0]).toBe(0);
|
|
345
|
+
expect(p[1]).toBe(255);
|
|
346
|
+
expect(p[2]).toBe(0);
|
|
347
|
+
expect(p[3]).toBe(255);
|
|
348
|
+
});
|
|
349
|
+
await it("clears to magenta (255,0,255,255)", async () => {
|
|
350
|
+
const fbo = makeTestFBO(gl);
|
|
351
|
+
gl.clearColor(1, 0, 1, 1);
|
|
352
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
353
|
+
const p = readPixel(gl, 0, 0);
|
|
354
|
+
destroyTestFBO(gl, fbo);
|
|
355
|
+
expect(p[0]).toBe(255);
|
|
356
|
+
expect(p[1]).toBe(0);
|
|
357
|
+
expect(p[2]).toBe(255);
|
|
358
|
+
expect(p[3]).toBe(255);
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
await describe("blending", async () => {
|
|
362
|
+
beforeEach(async () => {
|
|
363
|
+
glArea.make_current();
|
|
364
|
+
});
|
|
365
|
+
const VS_BLEND = [
|
|
366
|
+
"precision mediump float;",
|
|
367
|
+
"attribute vec2 position;",
|
|
368
|
+
"void main() { gl_Position = vec4(position, 0.0, 1.0); }"
|
|
369
|
+
].join("\n");
|
|
370
|
+
const blendTests = [
|
|
371
|
+
{
|
|
372
|
+
name: "ADD ONE ONE",
|
|
373
|
+
equn: gl.FUNC_ADD,
|
|
374
|
+
func1: gl.ONE,
|
|
375
|
+
func2: gl.ONE,
|
|
376
|
+
dstColor: [0.5, 0.5, 0.5, 1],
|
|
377
|
+
srcColor: [0.5, 0.5, 0.5, 1],
|
|
378
|
+
expected: [255, 255, 255, 255]
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
name: "ADD ONE ZERO",
|
|
382
|
+
equn: gl.FUNC_ADD,
|
|
383
|
+
func1: gl.ONE,
|
|
384
|
+
func2: gl.ZERO,
|
|
385
|
+
dstColor: [0.5, 0.5, 0.5, 0.5],
|
|
386
|
+
srcColor: [0.2, 0.2, 0.2, 1],
|
|
387
|
+
expected: [51, 51, 51, 255]
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
name: "ADD ZERO SRC_COLOR",
|
|
391
|
+
equn: gl.FUNC_ADD,
|
|
392
|
+
func1: gl.ZERO,
|
|
393
|
+
func2: gl.SRC_COLOR,
|
|
394
|
+
dstColor: [0.8, 0.8, 0.8, 1],
|
|
395
|
+
srcColor: [0.5, 0.5, 0.5, 0.5],
|
|
396
|
+
expected: [102, 102, 102, 128]
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
name: "ADD DST_COLOR ZERO",
|
|
400
|
+
equn: gl.FUNC_ADD,
|
|
401
|
+
func1: gl.DST_COLOR,
|
|
402
|
+
func2: gl.ZERO,
|
|
403
|
+
dstColor: [0.8, 0.8, 0.8, 1],
|
|
404
|
+
srcColor: [0.5, 0.5, 0.5, 0.5],
|
|
405
|
+
expected: [102, 102, 102, 128]
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
name: "ADD SRC_ALPHA ONE_MINUS_SRC_ALPHA",
|
|
409
|
+
equn: gl.FUNC_ADD,
|
|
410
|
+
func1: gl.SRC_ALPHA,
|
|
411
|
+
func2: gl.ONE_MINUS_SRC_ALPHA,
|
|
412
|
+
dstColor: [0.5, 0, 0.5, 1],
|
|
413
|
+
srcColor: [0.5, 1, 0, 0.5],
|
|
414
|
+
expected: [127, 127, 64, 191]
|
|
124
415
|
}
|
|
416
|
+
];
|
|
417
|
+
for (const tc of blendTests) {
|
|
418
|
+
const { name, equn, func1, func2, dstColor, srcColor, expected } = tc;
|
|
419
|
+
const FS_BLEND = [
|
|
420
|
+
"precision mediump float;",
|
|
421
|
+
`void main() { gl_FragColor = vec4(${srcColor[0]},${srcColor[1]},${srcColor[2]},${srcColor[3]}); }`
|
|
422
|
+
].join("\n");
|
|
423
|
+
await it(name, async () => {
|
|
424
|
+
const fbo = makeTestFBO(gl);
|
|
425
|
+
gl.clearColor(dstColor[0], dstColor[1], dstColor[2], dstColor[3]);
|
|
426
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
427
|
+
const prog = makeProgram(gl, VS_BLEND, FS_BLEND);
|
|
428
|
+
gl.useProgram(prog);
|
|
429
|
+
gl.enable(gl.BLEND);
|
|
430
|
+
gl.blendEquation(equn);
|
|
431
|
+
gl.blendFunc(func1, func2);
|
|
432
|
+
drawTriangle(gl);
|
|
433
|
+
expect(gl.getError()).toBe(gl.NO_ERROR);
|
|
434
|
+
gl.disable(gl.BLEND);
|
|
435
|
+
const p = readPixel(gl, 0, 0);
|
|
436
|
+
gl.deleteProgram(prog);
|
|
437
|
+
destroyTestFBO(gl, fbo);
|
|
438
|
+
expect(pixelClose(p, expected)).toBeTruthy();
|
|
439
|
+
});
|
|
125
440
|
}
|
|
126
441
|
});
|
|
127
|
-
await
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
442
|
+
await describe("drawElements (indexed drawing)", async () => {
|
|
443
|
+
beforeEach(async () => {
|
|
444
|
+
glArea.make_current();
|
|
445
|
+
});
|
|
446
|
+
await it("draws a quad via index buffer \u2014 all pixels green", async () => {
|
|
447
|
+
const fbo = makeTestFBO(gl, 8, 8);
|
|
448
|
+
const VS = "attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); }";
|
|
449
|
+
const FS = "void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }";
|
|
450
|
+
gl.clearColor(1, 0, 0, 1);
|
|
451
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
452
|
+
const prog = makeProgram(gl, VS, FS);
|
|
453
|
+
gl.useProgram(prog);
|
|
454
|
+
const vbuf = gl.createBuffer();
|
|
455
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, vbuf);
|
|
456
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
|
|
457
|
+
gl.enableVertexAttribArray(0);
|
|
458
|
+
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
|
|
459
|
+
const ebuf = gl.createBuffer();
|
|
460
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebuf);
|
|
461
|
+
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 2, 1, 3]), gl.STATIC_DRAW);
|
|
462
|
+
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
|
|
463
|
+
expect(gl.getError()).toBe(gl.NO_ERROR);
|
|
464
|
+
const pixels = new Uint8Array(fbo.width * fbo.height * 4);
|
|
465
|
+
gl.readPixels(0, 0, fbo.width, fbo.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
|
466
|
+
let allGreen = true;
|
|
467
|
+
for (let i = 0; i < pixels.length; i += 4) {
|
|
468
|
+
if (pixels[i] !== 0 || pixels[i + 1] !== 255 || pixels[i + 2] !== 0 || pixels[i + 3] !== 255) {
|
|
469
|
+
allGreen = false;
|
|
470
|
+
break;
|
|
471
|
+
}
|
|
139
472
|
}
|
|
140
|
-
|
|
473
|
+
expect(allGreen).toBeTruthy();
|
|
474
|
+
gl.disableVertexAttribArray(0);
|
|
475
|
+
gl.deleteBuffer(vbuf);
|
|
476
|
+
gl.deleteBuffer(ebuf);
|
|
477
|
+
gl.deleteProgram(prog);
|
|
478
|
+
destroyTestFBO(gl, fbo);
|
|
479
|
+
});
|
|
480
|
+
});
|
|
481
|
+
await describe("readPixels", async () => {
|
|
482
|
+
beforeEach(async () => {
|
|
483
|
+
glArea.make_current();
|
|
484
|
+
});
|
|
485
|
+
await it("RGBA + UNSIGNED_BYTE returns correct data size", async () => {
|
|
486
|
+
const fbo = makeTestFBO(gl, 4, 4);
|
|
487
|
+
gl.clearColor(1, 0, 0, 1);
|
|
488
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
489
|
+
const pixels = new Uint8Array(fbo.width * fbo.height * 4);
|
|
490
|
+
gl.readPixels(0, 0, fbo.width, fbo.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
|
491
|
+
expect(gl.getError()).toBe(gl.NO_ERROR);
|
|
492
|
+
expect(pixels.length).toBe(fbo.width * fbo.height * 4);
|
|
493
|
+
destroyTestFBO(gl, fbo);
|
|
494
|
+
});
|
|
495
|
+
await it("pixel values match the clear color", async () => {
|
|
496
|
+
const fbo = makeTestFBO(gl);
|
|
497
|
+
gl.clearColor(0, 0, 1, 1);
|
|
498
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
499
|
+
const p = readPixel(gl, 0, 0);
|
|
500
|
+
destroyTestFBO(gl, fbo);
|
|
501
|
+
expect(p[0]).toBe(0);
|
|
502
|
+
expect(p[1]).toBe(0);
|
|
503
|
+
expect(p[2]).toBe(255);
|
|
504
|
+
expect(p[3]).toBe(255);
|
|
505
|
+
});
|
|
506
|
+
await it("readPixels reads a single red pixel", async () => {
|
|
507
|
+
const fbo = makeTestFBO(gl);
|
|
508
|
+
gl.clearColor(1, 0, 0, 1);
|
|
509
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
510
|
+
const buf = new Uint8Array(4);
|
|
511
|
+
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
|
|
512
|
+
destroyTestFBO(gl, fbo);
|
|
513
|
+
expect(buf[0]).toBe(255);
|
|
514
|
+
expect(buf[1]).toBe(0);
|
|
515
|
+
expect(buf[2]).toBe(0);
|
|
516
|
+
expect(buf[3]).toBe(255);
|
|
517
|
+
});
|
|
518
|
+
});
|
|
519
|
+
await describe("depth buffer", async () => {
|
|
520
|
+
beforeEach(async () => {
|
|
521
|
+
glArea.make_current();
|
|
522
|
+
});
|
|
523
|
+
await it("depth test (LESS) \u2014 nearer triangle occludes farther one", async () => {
|
|
524
|
+
const VS = [
|
|
525
|
+
"attribute vec2 position;",
|
|
526
|
+
"uniform float depth;",
|
|
527
|
+
"void main() { gl_Position = vec4(position, depth, 1.0); }"
|
|
528
|
+
].join("\n");
|
|
529
|
+
const FS = [
|
|
530
|
+
"precision mediump float;",
|
|
531
|
+
"uniform vec4 color;",
|
|
532
|
+
"void main() { gl_FragColor = color; }"
|
|
533
|
+
].join("\n");
|
|
534
|
+
const fbo = makeTestFBOWithDepth(gl, 4, 4);
|
|
535
|
+
gl.clearColor(0, 0, 0, 1);
|
|
536
|
+
gl.clearDepth(1);
|
|
537
|
+
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
538
|
+
gl.enable(gl.DEPTH_TEST);
|
|
539
|
+
gl.depthFunc(gl.LESS);
|
|
540
|
+
const prog = makeProgram(gl, VS, FS);
|
|
541
|
+
gl.useProgram(prog);
|
|
542
|
+
gl.uniform1f(gl.getUniformLocation(prog, "depth"), 0);
|
|
543
|
+
gl.uniform4f(gl.getUniformLocation(prog, "color"), 1, 0, 0, 1);
|
|
544
|
+
drawTriangle(gl);
|
|
545
|
+
gl.uniform1f(gl.getUniformLocation(prog, "depth"), 0.5);
|
|
546
|
+
gl.uniform4f(gl.getUniformLocation(prog, "color"), 0, 0, 1, 1);
|
|
547
|
+
drawTriangle(gl);
|
|
548
|
+
expect(gl.getError()).toBe(gl.NO_ERROR);
|
|
549
|
+
gl.disable(gl.DEPTH_TEST);
|
|
550
|
+
const p = readPixel(gl, 0, 0);
|
|
551
|
+
gl.deleteProgram(prog);
|
|
552
|
+
destroyTestFBOWithDepth(gl, fbo);
|
|
553
|
+
expect(p[0]).toBe(255);
|
|
554
|
+
expect(p[1]).toBe(0);
|
|
555
|
+
expect(p[2]).toBe(0);
|
|
556
|
+
});
|
|
557
|
+
});
|
|
558
|
+
await describe("uniform1fv regression", async () => {
|
|
559
|
+
beforeEach(async () => {
|
|
560
|
+
glArea.make_current();
|
|
561
|
+
});
|
|
562
|
+
const VS_U1FV = [
|
|
563
|
+
"attribute vec2 position;",
|
|
564
|
+
"void main() { gl_Position = vec4(position, 0.0, 1.0); }"
|
|
565
|
+
].join("\n");
|
|
566
|
+
await it("uniform1fv sets a float uniform and affects rendering", async () => {
|
|
567
|
+
const FS = [
|
|
568
|
+
"precision mediump float;",
|
|
569
|
+
"uniform float uRed;",
|
|
570
|
+
"void main() { gl_FragColor = vec4(uRed, 0.0, 0.0, 1.0); }"
|
|
571
|
+
].join("\n");
|
|
572
|
+
const prog = makeProgram(gl, VS_U1FV, FS);
|
|
573
|
+
expect(gl.getProgramParameter(prog, gl.LINK_STATUS)).toBeTruthy();
|
|
574
|
+
gl.useProgram(prog);
|
|
575
|
+
const loc = gl.getUniformLocation(prog, "uRed");
|
|
576
|
+
expect(loc).not.toBeNull();
|
|
577
|
+
gl.uniform1fv(loc, new Float32Array([1]));
|
|
578
|
+
expect(gl.getError()).toBe(gl.NO_ERROR);
|
|
579
|
+
const fbo = makeTestFBO(gl, 4, 4);
|
|
580
|
+
gl.clearColor(0, 0, 0, 1);
|
|
581
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
582
|
+
drawTriangle(gl);
|
|
583
|
+
const p = readPixel(gl, 0, 0);
|
|
584
|
+
destroyTestFBO(gl, fbo);
|
|
585
|
+
expect(p[0]).toBe(255);
|
|
586
|
+
expect(p[1]).toBe(0);
|
|
587
|
+
expect(p[2]).toBe(0);
|
|
588
|
+
gl.deleteProgram(prog);
|
|
589
|
+
});
|
|
590
|
+
await it("uniform1fv sets each array element individually", async () => {
|
|
591
|
+
const FS_ARR = [
|
|
592
|
+
"precision mediump float;",
|
|
593
|
+
"uniform float uWeights[3];",
|
|
594
|
+
"void main() { gl_FragColor = vec4(uWeights[0], uWeights[1], uWeights[2], 1.0); }"
|
|
595
|
+
].join("\n");
|
|
596
|
+
const prog = makeProgram(gl, VS_U1FV, FS_ARR);
|
|
597
|
+
expect(gl.getProgramParameter(prog, gl.LINK_STATUS)).toBeTruthy();
|
|
598
|
+
gl.useProgram(prog);
|
|
599
|
+
const loc0 = gl.getUniformLocation(prog, "uWeights[0]");
|
|
600
|
+
const loc1 = gl.getUniformLocation(prog, "uWeights[1]");
|
|
601
|
+
const loc2 = gl.getUniformLocation(prog, "uWeights[2]");
|
|
602
|
+
expect(loc0).not.toBeNull();
|
|
603
|
+
expect(loc1).not.toBeNull();
|
|
604
|
+
expect(loc2).not.toBeNull();
|
|
605
|
+
gl.uniform1fv(loc0, new Float32Array([0]));
|
|
606
|
+
gl.uniform1fv(loc1, new Float32Array([1]));
|
|
607
|
+
gl.uniform1fv(loc2, new Float32Array([0]));
|
|
608
|
+
expect(gl.getError()).toBe(gl.NO_ERROR);
|
|
609
|
+
const fbo = makeTestFBO(gl, 4, 4);
|
|
610
|
+
gl.clearColor(0, 0, 0, 1);
|
|
611
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
612
|
+
drawTriangle(gl);
|
|
613
|
+
const p = readPixel(gl, 0, 0);
|
|
614
|
+
destroyTestFBO(gl, fbo);
|
|
615
|
+
expect(p[0]).toBe(0);
|
|
616
|
+
expect(p[1]).toBe(255);
|
|
617
|
+
expect(p[2]).toBe(0);
|
|
618
|
+
gl.deleteProgram(prog);
|
|
619
|
+
});
|
|
620
|
+
});
|
|
621
|
+
await describe("linkProgram with inactive attributes", async () => {
|
|
622
|
+
beforeEach(async () => {
|
|
623
|
+
glArea.make_current();
|
|
624
|
+
});
|
|
625
|
+
await it("links a program whose vertex shader declares but does not use an attribute", async () => {
|
|
626
|
+
const VS = [
|
|
627
|
+
"attribute vec2 position;",
|
|
628
|
+
"attribute vec3 unused;",
|
|
629
|
+
"void main() { gl_Position = vec4(position, 0.0, 1.0); }"
|
|
630
|
+
].join("\n");
|
|
631
|
+
const FS = [
|
|
632
|
+
"precision mediump float;",
|
|
633
|
+
"void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }"
|
|
634
|
+
].join("\n");
|
|
635
|
+
const prog = makeProgram(gl, VS, FS);
|
|
636
|
+
expect(gl.getProgramParameter(prog, gl.LINK_STATUS)).toBeTruthy();
|
|
637
|
+
expect(gl.getError()).toBe(gl.NO_ERROR);
|
|
638
|
+
gl.useProgram(prog);
|
|
639
|
+
const fbo = makeTestFBO(gl, 4, 4);
|
|
640
|
+
gl.clearColor(0, 0, 0, 1);
|
|
641
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
642
|
+
drawTriangle(gl);
|
|
643
|
+
expect(gl.getError()).toBe(gl.NO_ERROR);
|
|
644
|
+
const p = readPixel(gl, 0, 0);
|
|
645
|
+
destroyTestFBO(gl, fbo);
|
|
646
|
+
expect(p[1]).toBe(255);
|
|
647
|
+
gl.deleteProgram(prog);
|
|
648
|
+
});
|
|
141
649
|
});
|
|
650
|
+
win.destroy();
|
|
142
651
|
});
|
|
143
652
|
};
|
|
144
653
|
export {
|