@gjsify/webgl 0.3.12 → 0.3.14

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 +312 -293
  2. package/lib/esm/conformance/buffers.spec.js +217 -200
  3. package/lib/esm/conformance/context.spec.js +295 -295
  4. package/lib/esm/conformance/programs.spec.js +458 -445
  5. package/lib/esm/conformance/rendering-basic.spec.js +134 -128
  6. package/lib/esm/conformance/rendering.spec.js +502 -400
  7. package/lib/esm/conformance/setup.js +42 -31
  8. package/lib/esm/conformance/state.spec.js +360 -343
  9. package/lib/esm/conformance/textures.spec.js +330 -338
  10. package/lib/esm/conformance/uniforms.spec.js +465 -309
  11. package/lib/esm/conformance-test.js +24 -22
  12. package/lib/esm/extensions/ext-blend-minmax.js +16 -16
  13. package/lib/esm/extensions/ext-color-buffer-float.js +10 -11
  14. package/lib/esm/extensions/ext-color-buffer-half-float.js +10 -11
  15. package/lib/esm/extensions/ext-texture-filter-anisotropic.js +16 -16
  16. package/lib/esm/extensions/oes-element-index-unit.js +11 -12
  17. package/lib/esm/extensions/oes-standard-derivatives.js +15 -15
  18. package/lib/esm/extensions/oes-texture-float-linear.js +11 -12
  19. package/lib/esm/extensions/oes-texture-float.js +11 -12
  20. package/lib/esm/extensions/oes-texture-half-float.js +17 -17
  21. package/lib/esm/extensions/stackgl-destroy-context.js +10 -10
  22. package/lib/esm/extensions/stackgl-resize-drawing-buffer.js +10 -10
  23. package/lib/esm/html-canvas-element.js +64 -64
  24. package/lib/esm/index.js +29 -26
  25. package/lib/esm/linkable.js +49 -49
  26. package/lib/esm/test-utils.js +158 -107
  27. package/lib/esm/test.js +8 -4
  28. package/lib/esm/types/index.js +5 -5
  29. package/lib/esm/utils.js +164 -187
  30. package/lib/esm/webgl-active-info.js +10 -9
  31. package/lib/esm/webgl-bridge.js +162 -147
  32. package/lib/esm/webgl-buffer.js +17 -15
  33. package/lib/esm/webgl-context-attributes.js +23 -22
  34. package/lib/esm/webgl-context-base.js +3039 -3351
  35. package/lib/esm/webgl-drawing-buffer-wrapper.js +10 -9
  36. package/lib/esm/webgl-framebuffer.js +108 -106
  37. package/lib/esm/webgl-program.js +25 -23
  38. package/lib/esm/webgl-query.js +15 -13
  39. package/lib/esm/webgl-renderbuffer.js +23 -21
  40. package/lib/esm/webgl-rendering-context.js +173 -187
  41. package/lib/esm/webgl-sampler.js +15 -13
  42. package/lib/esm/webgl-shader-precision-format.js +10 -9
  43. package/lib/esm/webgl-shader.js +23 -21
  44. package/lib/esm/webgl-sync.js +15 -13
  45. package/lib/esm/webgl-texture-unit.js +12 -11
  46. package/lib/esm/webgl-texture.js +21 -19
  47. package/lib/esm/webgl-transform-feedback.js +15 -13
  48. package/lib/esm/webgl-uniform-location.js +14 -13
  49. package/lib/esm/webgl-vertex-array-object.js +20 -18
  50. package/lib/esm/webgl-vertex-attribute.js +149 -145
  51. package/lib/esm/webgl1.spec.js +1039 -650
  52. package/lib/esm/webgl2-rendering-context.js +1210 -1273
  53. package/lib/esm/webgl2.spec.js +1284 -1252
  54. package/package.json +9 -9
  55. package/lib/esm/@types/glsl-tokenizer/index.d.js +0 -0
@@ -1,152 +1,167 @@
1
+ import { HTMLCanvasElement } from "./html-canvas-element.js";
1
2
  import GObject from "gi://GObject";
2
3
  import GLib from "gi://GLib?version=2.0";
3
4
  import Gtk from "gi://Gtk?version=4.0";
4
- import { HTMLCanvasElement as OurHTMLCanvasElement } from "./html-canvas-element.js";
5
5
  import { attachEventControllers } from "@gjsify/event-bridge";
6
6
  import { Event } from "@gjsify/dom-events";
7
- const WebGLBridge = GObject.registerClass(
8
- { GTypeName: "GjsifyWebGLBridge" },
9
- class WebGLBridge2 extends Gtk.GLArea {
10
- constructor(params) {
11
- super(params);
12
- this._canvas = null;
13
- this._readyCallbacks = [];
14
- this._resizeCallbacks = [];
15
- this._renderTag = null;
16
- this._tickCallbackId = null;
17
- this._frameCallback = null;
18
- // Time origin in microseconds (GLib monotonic clock).
19
- // Both requestAnimationFrame timestamps and performance.now() are
20
- // relative to this origin, matching the browser DOMHighResTimeStamp spec.
21
- this._timeOrigin = GLib.get_monotonic_time();
22
- this.set_use_es(true);
23
- this.set_required_version(3, 2);
24
- this.set_has_depth_buffer(true);
25
- this.set_has_stencil_buffer(true);
26
- attachEventControllers(this, () => this._canvas, { captureKeys: true });
27
- this._tickCallbackId = this.add_tick_callback((_widget, _frameClock) => {
28
- if (this._frameCallback !== null) {
29
- this.queue_render();
30
- }
31
- return GLib.SOURCE_CONTINUE;
32
- });
33
- const initId = this.connect("render", () => {
34
- this.disconnect(initId);
35
- this.make_current();
36
- this._canvas = new OurHTMLCanvasElement(this);
37
- if (globalThis.document?.body) {
38
- globalThis.document.body.appendChild(this._canvas);
39
- }
40
- this._canvas.getContext("webgl2");
41
- const gl = this._canvas.getContext("webgl");
42
- if (gl) {
43
- for (const cb of this._readyCallbacks) {
44
- cb(this._canvas, gl);
45
- }
46
- this._readyCallbacks = [];
47
- }
48
- this._renderTag = this.connect("render", (_widget) => {
49
- if (this._frameCallback !== null) {
50
- const time = (GLib.get_monotonic_time() - this._timeOrigin) / 1e3;
51
- if (globalThis.__GJSIFY_DEBUG_RAF === true) {
52
- console.log(`[rAF] frame callback fires t=${time.toFixed(1)}`);
53
- }
54
- const cb = this._frameCallback;
55
- this._frameCallback = null;
56
- cb(time);
57
- }
58
- return true;
59
- });
60
- return true;
61
- });
62
- this.connect("resize", () => {
63
- const width = this.get_allocated_width();
64
- const height = this.get_allocated_height();
65
- if (this._canvas) {
66
- this._canvas.dispatchEvent(new Event("resize"));
67
- }
68
- for (const cb of this._resizeCallbacks) {
69
- cb(width, height);
70
- }
71
- if (this._frameCallback) {
72
- this.requestAnimationFrame(this._frameCallback);
73
- }
74
- });
75
- this.connect("unrealize", () => {
76
- if (this._renderTag !== null) {
77
- this.disconnect(this._renderTag);
78
- this._renderTag = null;
79
- }
80
- if (this._tickCallbackId !== null) {
81
- this.remove_tick_callback(this._tickCallbackId);
82
- this._tickCallbackId = null;
83
- }
84
- this._canvas = null;
85
- });
86
- }
87
- /** The HTMLCanvasElement wrapping this GLArea. Available after the first render. */
88
- get canvas() {
89
- return this._canvas;
90
- }
91
- /**
92
- * Registers a callback to be called once the WebGL context is ready.
93
- * If the context is already available, the callback fires synchronously.
94
- */
95
- onReady(cb) {
96
- if (this._canvas) {
97
- const gl = this._canvas.getContext("webgl");
98
- if (gl) {
99
- cb(this._canvas, gl);
100
- return;
101
- }
102
- }
103
- this._readyCallbacks.push(cb);
104
- }
105
- /**
106
- * @deprecated Use `onReady()` instead.
107
- */
108
- onWebGLReady(cb) {
109
- this.onReady(cb);
110
- }
111
- /**
112
- * Register a callback invoked whenever the GTK widget is resized.
113
- * The callback fires alongside the native 'resize' GObject signal and
114
- * after the DOM 'resize' event has been dispatched on the canvas.
115
- * Canvas buffer dimensions are NOT automatically updated — consumers
116
- * should set `canvas.width`/`canvas.height` themselves if desired.
117
- */
118
- onResize(cb) {
119
- this._resizeCallbacks.push(cb);
120
- }
121
- /**
122
- * Schedules a single animation frame callback, matching the browser `requestAnimationFrame` API.
123
- * Backed by a persistent GTK frame clock tick callback (vsync-synced) + a persistent GLArea
124
- * render signal handler. Both are installed once at construction / first render respectively,
125
- * eliminating per-frame GLib.Source allocation and GObject signal connect/disconnect overhead.
126
- * Returns 0 (handle — cancel via cancelAnimationFrame clears the pending callback).
127
- */
128
- requestAnimationFrame(cb) {
129
- this._frameCallback = cb;
130
- this.queue_render();
131
- return 0;
132
- }
133
- /**
134
- * Sets browser globals (`requestAnimationFrame`, `performance`) so that
135
- * browser-targeted code (e.g. Three.js) works unchanged on GJS.
136
- */
137
- installGlobals() {
138
- globalThis.requestAnimationFrame = (cb) => this.requestAnimationFrame(cb);
139
- globalThis.cancelAnimationFrame = (_id) => {
140
- this._frameCallback = null;
141
- };
142
- const timeOrigin = this._timeOrigin;
143
- globalThis.performance = {
144
- now: () => (GLib.get_monotonic_time() - timeOrigin) / 1e3,
145
- timeOrigin: Date.now()
146
- };
147
- }
148
- }
149
- );
150
- export {
151
- WebGLBridge
152
- };
7
+
8
+ //#region src/ts/webgl-bridge.ts
9
+ /**
10
+ * A `Gtk.GLArea` subclass that handles WebGL bootstrapping:
11
+ * - Sets up OpenGL ES 3.2 context, depth buffer, stencil buffer
12
+ * - Creates an `HTMLCanvasElement` wrapping the GLArea on first render
13
+ * - Fires `onReady()` callbacks with (canvas, gl) once the context is available
14
+ * - Provides `requestAnimationFrame()` backed by GTK frame clock (vsync) + render signal
15
+ * - `installGlobals()` sets `globalThis.requestAnimationFrame` and `globalThis.performance`
16
+ *
17
+ * Usage:
18
+ * ```ts
19
+ * const widget = new WebGLBridge();
20
+ * widget.installGlobals(); // sets globalThis.requestAnimationFrame
21
+ * widget.onReady((canvas, gl) => {
22
+ * gl.clearColor(0, 0, 0, 1);
23
+ * // requestAnimationFrame is now available globally
24
+ * });
25
+ * window.set_child(widget);
26
+ * ```
27
+ */
28
+ const WebGLBridge = GObject.registerClass({ GTypeName: "GjsifyWebGLBridge" }, class WebGLBridge extends Gtk.GLArea {
29
+ constructor(params) {
30
+ super(params);
31
+ this._canvas = null;
32
+ this._readyCallbacks = [];
33
+ this._resizeCallbacks = [];
34
+ this._renderTag = null;
35
+ this._tickCallbackId = null;
36
+ this._frameCallback = null;
37
+ this._timeOrigin = GLib.get_monotonic_time();
38
+ this.set_use_es(true);
39
+ this.set_required_version(3, 2);
40
+ this.set_has_depth_buffer(true);
41
+ this.set_has_stencil_buffer(true);
42
+ attachEventControllers(this, () => this._canvas, { captureKeys: true });
43
+ this._tickCallbackId = this.add_tick_callback((_widget, _frameClock) => {
44
+ if (this._frameCallback !== null) {
45
+ this.queue_render();
46
+ }
47
+ return GLib.SOURCE_CONTINUE;
48
+ });
49
+ const initId = this.connect("render", () => {
50
+ this.disconnect(initId);
51
+ this.make_current();
52
+ this._canvas = new HTMLCanvasElement(this);
53
+ if (globalThis.document?.body) {
54
+ globalThis.document.body.appendChild(this._canvas);
55
+ }
56
+ this._canvas.getContext("webgl2");
57
+ const gl = this._canvas.getContext("webgl");
58
+ if (gl) {
59
+ for (const cb of this._readyCallbacks) {
60
+ cb(this._canvas, gl);
61
+ }
62
+ this._readyCallbacks = [];
63
+ }
64
+ this._renderTag = this.connect("render", (_widget) => {
65
+ if (this._frameCallback !== null) {
66
+ const time = (GLib.get_monotonic_time() - this._timeOrigin) / 1e3;
67
+ if (globalThis.__GJSIFY_DEBUG_RAF === true) {
68
+ console.log(`[rAF] frame callback fires t=${time.toFixed(1)}`);
69
+ }
70
+ const cb = this._frameCallback;
71
+ this._frameCallback = null;
72
+ cb(time);
73
+ }
74
+ return true;
75
+ });
76
+ return true;
77
+ });
78
+ this.connect("resize", () => {
79
+ const width = this.get_allocated_width();
80
+ const height = this.get_allocated_height();
81
+ if (this._canvas) {
82
+ this._canvas.dispatchEvent(new Event("resize"));
83
+ }
84
+ for (const cb of this._resizeCallbacks) {
85
+ cb(width, height);
86
+ }
87
+ if (this._frameCallback) {
88
+ this.requestAnimationFrame(this._frameCallback);
89
+ }
90
+ });
91
+ this.connect("unrealize", () => {
92
+ if (this._renderTag !== null) {
93
+ this.disconnect(this._renderTag);
94
+ this._renderTag = null;
95
+ }
96
+ if (this._tickCallbackId !== null) {
97
+ this.remove_tick_callback(this._tickCallbackId);
98
+ this._tickCallbackId = null;
99
+ }
100
+ this._canvas = null;
101
+ });
102
+ }
103
+ /** The HTMLCanvasElement wrapping this GLArea. Available after the first render. */
104
+ get canvas() {
105
+ return this._canvas;
106
+ }
107
+ /**
108
+ * Registers a callback to be called once the WebGL context is ready.
109
+ * If the context is already available, the callback fires synchronously.
110
+ */
111
+ onReady(cb) {
112
+ if (this._canvas) {
113
+ const gl = this._canvas.getContext("webgl");
114
+ if (gl) {
115
+ cb(this._canvas, gl);
116
+ return;
117
+ }
118
+ }
119
+ this._readyCallbacks.push(cb);
120
+ }
121
+ /**
122
+ * @deprecated Use `onReady()` instead.
123
+ */
124
+ onWebGLReady(cb) {
125
+ this.onReady(cb);
126
+ }
127
+ /**
128
+ * Register a callback invoked whenever the GTK widget is resized.
129
+ * The callback fires alongside the native 'resize' GObject signal and
130
+ * after the DOM 'resize' event has been dispatched on the canvas.
131
+ * Canvas buffer dimensions are NOT automatically updated — consumers
132
+ * should set `canvas.width`/`canvas.height` themselves if desired.
133
+ */
134
+ onResize(cb) {
135
+ this._resizeCallbacks.push(cb);
136
+ }
137
+ /**
138
+ * Schedules a single animation frame callback, matching the browser `requestAnimationFrame` API.
139
+ * Backed by a persistent GTK frame clock tick callback (vsync-synced) + a persistent GLArea
140
+ * render signal handler. Both are installed once at construction / first render respectively,
141
+ * eliminating per-frame GLib.Source allocation and GObject signal connect/disconnect overhead.
142
+ * Returns 0 (handle — cancel via cancelAnimationFrame clears the pending callback).
143
+ */
144
+ requestAnimationFrame(cb) {
145
+ this._frameCallback = cb;
146
+ this.queue_render();
147
+ return 0;
148
+ }
149
+ /**
150
+ * Sets browser globals (`requestAnimationFrame`, `performance`) so that
151
+ * browser-targeted code (e.g. Three.js) works unchanged on GJS.
152
+ */
153
+ installGlobals() {
154
+ globalThis.requestAnimationFrame = (cb) => this.requestAnimationFrame(cb);
155
+ globalThis.cancelAnimationFrame = (_id) => {
156
+ this._frameCallback = null;
157
+ };
158
+ const timeOrigin = this._timeOrigin;
159
+ globalThis.performance = {
160
+ now: () => (GLib.get_monotonic_time() - timeOrigin) / 1e3,
161
+ timeOrigin: Date.now()
162
+ };
163
+ }
164
+ });
165
+
166
+ //#endregion
167
+ export { WebGLBridge };
@@ -1,17 +1,19 @@
1
1
  import { Linkable } from "./linkable.js";
2
- class WebGLBuffer extends Linkable {
3
- constructor(_, ctx) {
4
- super(_);
5
- this._size = 0;
6
- this._elements = new Uint8Array(0);
7
- this._ctx = ctx;
8
- }
9
- _performDelete() {
10
- const ctx = this._ctx;
11
- delete ctx._buffers[this._ | 0];
12
- ctx._gl.deleteBuffer(this._);
13
- }
14
- }
15
- export {
16
- WebGLBuffer
2
+
3
+ //#region src/ts/webgl-buffer.ts
4
+ var WebGLBuffer = class extends Linkable {
5
+ constructor(_, ctx) {
6
+ super(_);
7
+ this._size = 0;
8
+ this._elements = new Uint8Array(0);
9
+ this._ctx = ctx;
10
+ }
11
+ _performDelete() {
12
+ const ctx = this._ctx;
13
+ delete ctx._buffers[this._ | 0];
14
+ ctx._gl.deleteBuffer(this._);
15
+ }
17
16
  };
17
+
18
+ //#endregion
19
+ export { WebGLBuffer };
@@ -1,23 +1,24 @@
1
- class WebGLContextAttributes {
2
- constructor(alpha, depth, stencil, antialias, premultipliedAlpha, preserveDrawingBuffer, preferLowPowerToHighPerformance, failIfMajorPerformanceCaveat) {
3
- this.alpha = alpha;
4
- this.depth = depth;
5
- this.stencil = stencil;
6
- this.antialias = antialias;
7
- this.premultipliedAlpha = premultipliedAlpha;
8
- this.preserveDrawingBuffer = preserveDrawingBuffer;
9
- this.preferLowPowerToHighPerformance = preferLowPowerToHighPerformance;
10
- this.failIfMajorPerformanceCaveat = failIfMajorPerformanceCaveat;
11
- this.alpha = alpha;
12
- this.depth = depth;
13
- this.stencil = stencil;
14
- this.antialias = antialias;
15
- this.premultipliedAlpha = premultipliedAlpha;
16
- this.preserveDrawingBuffer = preserveDrawingBuffer;
17
- this.preferLowPowerToHighPerformance = preferLowPowerToHighPerformance;
18
- this.failIfMajorPerformanceCaveat = failIfMajorPerformanceCaveat;
19
- }
20
- }
21
- export {
22
- WebGLContextAttributes
1
+ //#region src/ts/webgl-context-attributes.ts
2
+ var WebGLContextAttributes = class {
3
+ constructor(alpha, depth, stencil, antialias, premultipliedAlpha, preserveDrawingBuffer, preferLowPowerToHighPerformance, failIfMajorPerformanceCaveat) {
4
+ this.alpha = alpha;
5
+ this.depth = depth;
6
+ this.stencil = stencil;
7
+ this.antialias = antialias;
8
+ this.premultipliedAlpha = premultipliedAlpha;
9
+ this.preserveDrawingBuffer = preserveDrawingBuffer;
10
+ this.preferLowPowerToHighPerformance = preferLowPowerToHighPerformance;
11
+ this.failIfMajorPerformanceCaveat = failIfMajorPerformanceCaveat;
12
+ this.alpha = alpha;
13
+ this.depth = depth;
14
+ this.stencil = stencil;
15
+ this.antialias = antialias;
16
+ this.premultipliedAlpha = premultipliedAlpha;
17
+ this.preserveDrawingBuffer = preserveDrawingBuffer;
18
+ this.preferLowPowerToHighPerformance = preferLowPowerToHighPerformance;
19
+ this.failIfMajorPerformanceCaveat = failIfMajorPerformanceCaveat;
20
+ }
23
21
  };
22
+
23
+ //#endregion
24
+ export { WebGLContextAttributes };