@luma.gl/webgl 9.1.0-alpha.1 → 9.1.0-alpha.9

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 (79) hide show
  1. package/dist/adapter/converters/device-parameters.d.ts.map +1 -1
  2. package/dist/adapter/converters/device-parameters.js +18 -11
  3. package/dist/adapter/converters/texture-formats.d.ts +1 -1
  4. package/dist/adapter/converters/texture-formats.d.ts.map +1 -1
  5. package/dist/adapter/converters/texture-formats.js +9 -16
  6. package/dist/adapter/device-helpers/webgl-device-features.d.ts.map +1 -1
  7. package/dist/adapter/device-helpers/webgl-device-features.js +0 -1
  8. package/dist/adapter/helpers/webgl-texture-utils.d.ts +4 -4
  9. package/dist/adapter/helpers/webgl-texture-utils.d.ts.map +1 -1
  10. package/dist/adapter/helpers/webgl-texture-utils.js +11 -9
  11. package/dist/adapter/resources/webgl-framebuffer.js +1 -1
  12. package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
  13. package/dist/adapter/resources/webgl-render-pass.js +17 -4
  14. package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
  15. package/dist/adapter/resources/webgl-render-pipeline.js +1 -1
  16. package/dist/adapter/resources/webgl-shader.js +1 -1
  17. package/dist/adapter/resources/webgl-texture.d.ts +2 -2
  18. package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
  19. package/dist/adapter/resources/webgl-texture.js +12 -27
  20. package/dist/adapter/resources/webgl-transform-feedback.js +1 -1
  21. package/dist/adapter/resources/webgl-vertex-array.d.ts.map +1 -1
  22. package/dist/adapter/resources/webgl-vertex-array.js +3 -0
  23. package/dist/adapter/webgl-adapter.d.ts +21 -0
  24. package/dist/adapter/webgl-adapter.d.ts.map +1 -0
  25. package/dist/adapter/webgl-adapter.js +91 -0
  26. package/dist/adapter/webgl-device.d.ts +15 -27
  27. package/dist/adapter/webgl-device.d.ts.map +1 -1
  28. package/dist/adapter/webgl-device.js +32 -112
  29. package/dist/classic/copy-and-blit.d.ts +1 -0
  30. package/dist/classic/copy-and-blit.d.ts.map +1 -1
  31. package/dist/classic/copy-and-blit.js +11 -10
  32. package/dist/context/debug/spector-types.d.ts +1108 -0
  33. package/dist/context/debug/spector-types.d.ts.map +1 -0
  34. package/dist/context/debug/spector-types.js +697 -0
  35. package/dist/context/debug/spector.d.ts +12 -8
  36. package/dist/context/debug/spector.d.ts.map +1 -1
  37. package/dist/context/debug/spector.js +23 -17
  38. package/dist/context/polyfills/polyfill-webgl1-extensions.d.ts +9 -0
  39. package/dist/context/polyfills/polyfill-webgl1-extensions.d.ts.map +1 -0
  40. package/dist/context/polyfills/polyfill-webgl1-extensions.js +181 -0
  41. package/dist/context/state-tracker/webgl-state-tracker.d.ts +43 -0
  42. package/dist/context/state-tracker/webgl-state-tracker.d.ts.map +1 -0
  43. package/dist/context/state-tracker/{track-context-state.js → webgl-state-tracker.js} +44 -74
  44. package/dist/context/state-tracker/with-parameters.d.ts.map +1 -1
  45. package/dist/context/state-tracker/with-parameters.js +5 -4
  46. package/dist/dist.dev.js +341 -234
  47. package/dist/dist.min.js +2 -2
  48. package/dist/index.cjs +344 -236
  49. package/dist/index.cjs.map +4 -4
  50. package/dist/index.d.ts +3 -1
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +3 -2
  53. package/dist/utils/uid.d.ts +7 -0
  54. package/dist/utils/uid.d.ts.map +1 -0
  55. package/dist/utils/uid.js +14 -0
  56. package/package.json +3 -3
  57. package/src/adapter/converters/device-parameters.ts +18 -12
  58. package/src/adapter/converters/texture-formats.ts +12 -20
  59. package/src/adapter/device-helpers/webgl-device-features.ts +0 -1
  60. package/src/adapter/helpers/webgl-texture-utils.ts +12 -9
  61. package/src/adapter/resources/webgl-framebuffer.ts +1 -1
  62. package/src/adapter/resources/webgl-render-pass.ts +17 -4
  63. package/src/adapter/resources/webgl-render-pipeline.ts +2 -1
  64. package/src/adapter/resources/webgl-shader.ts +1 -1
  65. package/src/adapter/resources/webgl-texture.ts +17 -27
  66. package/src/adapter/resources/webgl-transform-feedback.ts +1 -1
  67. package/src/adapter/resources/webgl-vertex-array.ts +3 -0
  68. package/src/adapter/webgl-adapter.ts +113 -0
  69. package/src/adapter/webgl-device.ts +32 -135
  70. package/src/classic/copy-and-blit.ts +14 -9
  71. package/src/context/debug/spector-types.ts +1154 -0
  72. package/src/context/debug/spector.ts +38 -29
  73. package/src/context/polyfills/polyfill-webgl1-extensions.ts +202 -0
  74. package/src/context/state-tracker/{track-context-state.ts → webgl-state-tracker.ts} +55 -94
  75. package/src/context/state-tracker/with-parameters.ts +5 -4
  76. package/src/index.ts +5 -7
  77. package/src/utils/uid.ts +16 -0
  78. package/dist/context/state-tracker/track-context-state.d.ts +0 -22
  79. package/dist/context/state-tracker/track-context-state.d.ts.map +0 -1
@@ -5,54 +5,61 @@
5
5
  import {log} from '@luma.gl/core';
6
6
  import {loadScript} from '../../utils/load-script';
7
7
 
8
+ import {Spector} from './spector-types';
9
+
8
10
  /** Spector debug initialization options */
9
11
  type SpectorProps = {
12
+ /** Whether spector is enabled */
13
+ debugWithSpectorJS?: boolean;
14
+ /** URL to load spector script from. Typically a CDN URL */
15
+ spectorUrl?: string;
10
16
  /** Canvas to monitor */
11
- canvas?: HTMLCanvasElement | OffscreenCanvas;
12
- /** Whether debug is enabled. Auto-detected if ommitted */
13
- debug?: boolean;
14
- /** Whether spector is disabled */
15
- spector?: boolean | string | object;
16
- };
17
-
18
- const DEFAULT_SPECTOR_PROPS: SpectorProps = {
19
- spector: log.get('spector') || log.get('inspect')
17
+ gl?: WebGL2RenderingContext;
20
18
  };
21
19
 
22
- // https://github.com/BabylonJS/Spector.js#basic-usage
23
- const SPECTOR_CDN_URL = 'https://spectorcdn.babylonjs.com/spector.bundle.js';
24
20
  const LOG_LEVEL = 1;
25
21
 
26
- let spector: any = null;
22
+ let spector: Spector = null;
27
23
  let initialized: boolean = false;
28
24
 
29
25
  declare global {
26
+ // @ts-ignore
30
27
  // eslint-disable-next-line no-var
31
- var SPECTOR: any;
28
+ var SPECTOR: Spector;
32
29
  }
33
30
 
31
+ export const DEFAULT_SPECTOR_PROPS: Required<SpectorProps> = {
32
+ debugWithSpectorJS: log.get('spector') || log.get('spectorjs'),
33
+ // https://github.com/BabylonJS/Spector.js#basic-usage
34
+ // https://forum.babylonjs.com/t/spectorcdn-is-temporarily-off/48241
35
+ // spectorUrl: 'https://spectorcdn.babylonjs.com/spector.bundle.js';
36
+ spectorUrl: 'https://cdn.jsdelivr.net/npm/spectorjs@0.9.30/dist/spector.bundle.js',
37
+ gl: undefined!
38
+ };
39
+
34
40
  /** Loads spector from CDN if not already installed */
35
- export async function loadSpectorJS(props?: SpectorProps) {
41
+ export async function loadSpectorJS(props: {spectorUrl?: string}): Promise<void> {
36
42
  if (!globalThis.SPECTOR) {
37
43
  try {
38
- await loadScript(SPECTOR_CDN_URL);
44
+ await loadScript(props.spectorUrl || DEFAULT_SPECTOR_PROPS.spectorUrl);
39
45
  } catch (error) {
40
46
  log.warn(String(error));
41
47
  }
42
48
  }
43
49
  }
44
50
 
45
- export function initializeSpectorJS(props?: SpectorProps) {
51
+ export function initializeSpectorJS(props: SpectorProps): Spector | null {
46
52
  props = {...DEFAULT_SPECTOR_PROPS, ...props};
47
- if (!props?.spector) {
53
+ if (!props.debugWithSpectorJS) {
48
54
  return null;
49
55
  }
50
56
 
51
- if (!spector && globalThis.SPECTOR) {
52
- log.probe(LOG_LEVEL, 'SPECTOR found and initialized')();
53
- spector = new globalThis.SPECTOR.Spector();
57
+ if (!spector && globalThis.SPECTOR && !globalThis.luma?.spector) {
58
+ log.probe(LOG_LEVEL, 'SPECTOR found and initialized. Start with `luma.spector.displayUI()`')();
59
+ const {Spector} = globalThis.SPECTOR as any;
60
+ spector = new Spector();
54
61
  if (globalThis.luma) {
55
- globalThis.luma.spector = spector;
62
+ (globalThis.luma as any).spector = spector;
56
63
  }
57
64
  }
58
65
 
@@ -74,20 +81,22 @@ export function initializeSpectorJS(props?: SpectorProps) {
74
81
  // Use undocumented Spector API to open the UI with our capture
75
82
  // See https://github.com/BabylonJS/Spector.js/blob/767ad1195a25b85a85c381f400eb50a979239eca/src/spector.ts#L124
76
83
  spector?.getResultUI();
84
+ // @ts-expect-error private
77
85
  spector?.resultView.display();
86
+ // @ts-expect-error private
78
87
  spector?.resultView.addCapture(capture);
79
88
  });
80
89
  }
81
90
 
82
- if (props?.canvas) {
83
- // @ts-expect-error If spector is specified as a canvas id, only monitor that canvas
84
- if (typeof props.spector === 'string' && props.spector !== props.canvas.id) {
85
- return spector;
86
- }
87
-
91
+ if (props.gl) {
88
92
  // capture startup
89
- // spector?.captureCanvas(props?.canvas);
90
- spector?.startCapture(props?.canvas, 500); // 500 commands
93
+ const gl = props.gl;
94
+ // @ts-expect-error
95
+ const device = gl.device;
96
+ spector?.startCapture(props.gl, 500); // 500 commands
97
+ // @ts-expect-error
98
+ gl.device = device;
99
+
91
100
  new Promise(resolve => setTimeout(resolve, 2000)).then(_ => {
92
101
  log.info('Spector capture stopped after 2 seconds')();
93
102
  spector?.stopCapture();
@@ -0,0 +1,202 @@
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ // Goal is to make WebGL2 contexts look like WebGL1
6
+ // @note Partly inspired by with some older code from the `regl` library
7
+
8
+ /* eslint-disable camelcase */
9
+
10
+ import {GL} from '@luma.gl/constants';
11
+
12
+ // webgl1 extensions natively supported by webgl2
13
+ const WEBGL1_STATIC_EXTENSIONS = {
14
+ WEBGL_depth_texture: {
15
+ UNSIGNED_INT_24_8_WEBGL: GL.UNSIGNED_INT_24_8
16
+ } as const satisfies WEBGL_depth_texture,
17
+ OES_element_index_uint: {} as const satisfies OES_element_index_uint,
18
+ OES_texture_float: {} as const satisfies OES_texture_float,
19
+ OES_texture_half_float: {
20
+ // @ts-expect-error different numbers?
21
+ HALF_FLOAT_OES: GL.HALF_FLOAT
22
+ } as const satisfies OES_texture_half_float,
23
+ EXT_color_buffer_float: {} as const satisfies EXT_color_buffer_float,
24
+ OES_standard_derivatives: {
25
+ FRAGMENT_SHADER_DERIVATIVE_HINT_OES: GL.FRAGMENT_SHADER_DERIVATIVE_HINT
26
+ } as const satisfies OES_standard_derivatives,
27
+ EXT_frag_depth: {} as const satisfies EXT_frag_depth,
28
+ EXT_blend_minmax: {
29
+ MIN_EXT: GL.MIN,
30
+ MAX_EXT: GL.MAX
31
+ } as const satisfies EXT_blend_minmax,
32
+ EXT_shader_texture_lod: {} as const satisfies EXT_shader_texture_lod
33
+ };
34
+
35
+ const getWEBGL_draw_buffers = (gl: WebGL2RenderingContext) =>
36
+ ({
37
+ drawBuffersWEBGL(buffers: number[]) {
38
+ return gl.drawBuffers(buffers);
39
+ },
40
+ COLOR_ATTACHMENT0_WEBGL: GL.COLOR_ATTACHMENT0,
41
+ COLOR_ATTACHMENT1_WEBGL: GL.COLOR_ATTACHMENT1,
42
+ COLOR_ATTACHMENT2_WEBGL: GL.COLOR_ATTACHMENT2,
43
+ COLOR_ATTACHMENT3_WEBGL: GL.COLOR_ATTACHMENT3
44
+ }) as const satisfies Partial<WEBGL_draw_buffers>; // - too many fields
45
+
46
+ const getOES_vertex_array_object = (gl: WebGL2RenderingContext) =>
47
+ ({
48
+ VERTEX_ARRAY_BINDING_OES: GL.VERTEX_ARRAY_BINDING,
49
+ createVertexArrayOES() {
50
+ return gl.createVertexArray();
51
+ },
52
+ deleteVertexArrayOES(vertexArray: WebGLVertexArrayObject): void {
53
+ return gl.deleteVertexArray(vertexArray);
54
+ },
55
+ isVertexArrayOES(vertexArray: WebGLVertexArrayObject): boolean {
56
+ return gl.isVertexArray(vertexArray);
57
+ },
58
+ bindVertexArrayOES(vertexArray: WebGLVertexArrayObject): void {
59
+ return gl.bindVertexArray(vertexArray);
60
+ }
61
+ }) as const satisfies OES_vertex_array_object;
62
+
63
+ const getANGLE_instanced_arrays = (gl: WebGL2RenderingContext) =>
64
+ ({
65
+ VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE: 0x88fe,
66
+ drawArraysInstancedANGLE(...args) {
67
+ return gl.drawArraysInstanced(...args);
68
+ },
69
+ drawElementsInstancedANGLE(...args) {
70
+ return gl.drawElementsInstanced(...args);
71
+ },
72
+ vertexAttribDivisorANGLE(...args) {
73
+ return gl.vertexAttribDivisor(...args);
74
+ }
75
+ }) as const satisfies ANGLE_instanced_arrays;
76
+
77
+ /**
78
+ * Make browser return WebGL2 contexts even if WebGL1 contexts are requested
79
+ * @param enforce
80
+ * @returns
81
+ */
82
+ export function enforceWebGL2(enforce: boolean = true): void {
83
+ const prototype = HTMLCanvasElement.prototype as any;
84
+ if (!enforce && prototype.originalGetContext) {
85
+ // Reset the original getContext function
86
+ prototype.getContext = prototype.originalGetContext;
87
+ prototype.originalGetContext = undefined;
88
+ return;
89
+ }
90
+
91
+ // Store the original getContext function
92
+ prototype.originalGetContext = prototype.getContext;
93
+
94
+ // Override the getContext function
95
+ prototype.getContext = function (contextId: string, options?: WebGLContextAttributes) {
96
+ // Attempt to force WebGL2 for all WebGL1 contexts
97
+ if (contextId === 'webgl' || contextId === 'experimental-webgl') {
98
+ const context = this.originalGetContext('webgl2', options) as WebGL2RenderingContext;
99
+ // Work around test mocking
100
+ if (context instanceof HTMLElement) {
101
+ polyfillWebGL1Extensions(context);
102
+ }
103
+ return context;
104
+ }
105
+ // For any other type, return the original context
106
+ return this.originalGetContext(contextId, options);
107
+ };
108
+ }
109
+
110
+ /** Install WebGL1-only extensions on WebGL2 contexts */
111
+ export function polyfillWebGL1Extensions(gl: WebGL2RenderingContext): void {
112
+ // Enable, to support float and half-float textures
113
+ gl.getExtension('EXT_color_buffer_float');
114
+
115
+ // WebGL1 extensions implemented using WebGL2 APIs
116
+ const boundExtensions = {
117
+ ...WEBGL1_STATIC_EXTENSIONS,
118
+ WEBGL_disjoint_timer_query: gl.getExtension('EXT_disjoint_timer_query_webgl2'),
119
+ WEBGL_draw_buffers: getWEBGL_draw_buffers(gl),
120
+ OES_vertex_array_object: getOES_vertex_array_object(gl),
121
+ ANGLE_instanced_arrays: getANGLE_instanced_arrays(gl)
122
+ };
123
+
124
+ // Override gl.getExtension
125
+ // eslint-disable-next-line @typescript-eslint/unbound-method
126
+ const originalGetExtension = gl.getExtension;
127
+ gl.getExtension = function (extensionName: string) {
128
+ const ext = originalGetExtension.call(gl, extensionName);
129
+ if (ext) {
130
+ return ext;
131
+ }
132
+
133
+ // Injected extensions
134
+ if (extensionName in boundExtensions) {
135
+ return boundExtensions[extensionName];
136
+ }
137
+
138
+ return null;
139
+ };
140
+
141
+ // Override gl.getSupportedExtensions
142
+ // eslint-disable-next-line @typescript-eslint/unbound-method
143
+ const originalGetSupportedExtensions = gl.getSupportedExtensions;
144
+ gl.getSupportedExtensions = function (): string[] | null {
145
+ const extensions = originalGetSupportedExtensions.apply(gl) || [];
146
+ return extensions?.concat(Object.keys(boundExtensions));
147
+ };
148
+ }
149
+
150
+ // Update unsized WebGL1 formats to sized WebGL2 formats
151
+ // todo move to texture format file
152
+ // export function getInternalFormat(gl: WebGL2RenderingContext, format: GL, type: GL): GL {
153
+ // // webgl2 texture formats
154
+ // // https://webgl2fundamentals.org/webgl/lessons/webgl-data-textures.html
155
+ // switch (format) {
156
+ // case GL.DEPTH_COMPONENT:
157
+ // return GL.DEPTH_COMPONENT24;
158
+ // case GL.DEPTH_STENCIL:
159
+ // return GL.DEPTH24_STENCIL8;
160
+ // case GL.RGBA:
161
+ // return type === GL.HALF_FLOAT ? GL.RGBA16F : GL.RGBA32F;
162
+ // case GL.RGB:
163
+ // return type === GL.HALF_FLOAT ? GL.RGB16F : GL.RGB32F;
164
+ // default:
165
+ // return format;
166
+ // }
167
+ // }
168
+
169
+ /*
170
+ // texture type to update on the fly
171
+ export function getTextureType(gl: WebGL2RenderingContext, type: GL): GL {
172
+ if (type === HALF_FLOAT_OES) {
173
+ return GL.HALF_FLOAT;
174
+ }
175
+ return type;
176
+ }
177
+
178
+ // And texImage2D to convert the internalFormat to webgl2.
179
+ const webgl2 = this;
180
+ const origTexImage = gl.texImage2D;
181
+ gl.texImage2D = function (target, miplevel, iformat, a, typeFor6, c, d, typeFor9, f) {
182
+ if (arguments.length == 6) {
183
+ var ifmt = webgl2.getInternalFormat(gl, iformat, typeFor6);
184
+ origTexImage.apply(gl, [target, miplevel, ifmt, a, webgl.getTextureType(gl, typeFor6), c]);
185
+ } else {
186
+ // arguments.length == 9
187
+ var ifmt = webgl2.getInternalFormat(gl, iformat, typeFor9);
188
+ origTexImage.apply(gl, [
189
+ target,
190
+ miplevel,
191
+ ifmt,
192
+ a,
193
+ typeFor6,
194
+ c,
195
+ d,
196
+ webgl2.getTextureType(gl, typeFor9),
197
+ f
198
+ ]);
199
+ }
200
+ };
201
+ };
202
+ */
@@ -2,37 +2,43 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- // Support for listening to context state changes and intercepting state queries
6
- // NOTE: this system does not handle buffer bindings
5
+ import {setGLParameters, getGLParameters} from '../parameters/unified-parameter-api';
6
+ import {deepArrayEqual} from './deep-array-equal';
7
7
  import {
8
8
  GL_PARAMETER_DEFAULTS,
9
9
  GL_HOOKED_SETTERS,
10
10
  NON_CACHE_PARAMETERS
11
11
  } from '../parameters/webgl-parameter-tables';
12
- import {setGLParameters, getGLParameters} from '../parameters/unified-parameter-api';
13
- import {deepArrayEqual} from './deep-array-equal';
14
12
 
15
- // HELPER CLASS - GLState
13
+ // HELPER CLASS - WebGLStateTracker
14
+
15
+ /**
16
+ * Support for listening to context state changes and intercepting state queries
17
+ * NOTE: this system does not handle buffer bindings
18
+ */
19
+ export class WebGLStateTracker {
20
+ static get(gl: WebGL2RenderingContext): WebGLStateTracker {
21
+ // @ts-expect-error
22
+ return gl.state as WebGLStateTracker;
23
+ }
16
24
 
17
- /* eslint-disable no-shadow */
18
- class GLState {
19
25
  gl: WebGL2RenderingContext;
20
26
  program: unknown = null;
21
27
  stateStack: object[] = [];
22
28
  enable = true;
23
- cache: Record<string, any>;
29
+ cache: Record<string, any> = null!;
24
30
  log;
25
31
 
32
+ protected initialized = false;
33
+
26
34
  constructor(
27
35
  gl: WebGL2RenderingContext,
28
- {
29
- copyState = false, // Copy cache from params (slow) or initialize from WebGL defaults (fast)
30
- log = () => {} // Logging function, called when gl parameter change calls are actually issued
31
- } = {}
36
+ props?: {
37
+ log; // Logging function, called when gl parameter change calls are actually issued
38
+ }
32
39
  ) {
33
40
  this.gl = gl;
34
- this.cache = copyState ? getGLParameters(gl) : Object.assign({}, GL_PARAMETER_DEFAULTS);
35
- this.log = log;
41
+ this.log = props?.log || (() => {});
36
42
 
37
43
  this._updateCache = this._updateCache.bind(this);
38
44
  Object.seal(this);
@@ -51,6 +57,38 @@ class GLState {
51
57
  this.stateStack.pop();
52
58
  }
53
59
 
60
+ /**
61
+ * Initialize WebGL state caching on a context
62
+ * can be called multiple times to enable/disable
63
+ *
64
+ * @note After calling this function, context state will be cached
65
+ * .push() and .pop() will be available for saving,
66
+ * temporarily modifying, and then restoring state.
67
+ */
68
+ trackState(gl: WebGL2RenderingContext, options?: {copyState?: boolean}): void {
69
+ this.cache = options.copyState ? getGLParameters(gl) : Object.assign({}, GL_PARAMETER_DEFAULTS);
70
+
71
+ if (this.initialized) {
72
+ throw new Error('WebGLStateTracker');
73
+ }
74
+ this.initialized = true;
75
+
76
+ // @ts-expect-error
77
+ this.gl.state = this;
78
+
79
+ installProgramSpy(gl);
80
+
81
+ // intercept all setter functions in the table
82
+ for (const key in GL_HOOKED_SETTERS) {
83
+ const setter = GL_HOOKED_SETTERS[key];
84
+ installSetterSpy(gl, key, setter);
85
+ }
86
+
87
+ // intercept all getter functions in the table
88
+ installGetterOverride(gl, 'getParameter');
89
+ installGetterOverride(gl, 'isEnabled');
90
+ }
91
+
54
92
  /**
55
93
  // interceptor for context set functions - update our cache and our stack
56
94
  // values (Object) - the key values for this setter
@@ -89,83 +127,6 @@ class GLState {
89
127
  }
90
128
  }
91
129
 
92
- function getContextState(gl: WebGL2RenderingContext): GLState {
93
- // @ts-expect-error
94
- return gl.state as GLState;
95
- }
96
-
97
- // PUBLIC API
98
-
99
- /**
100
- * Initialize WebGL state caching on a context
101
- * can be called multiple times to enable/disable
102
- *
103
- * @note After calling this function, context state will be cached
104
- * gl.state.push() and gl.state.pop() will be available for saving,
105
- * temporarily modifying, and then restoring state.
106
- */
107
- export function trackContextState(
108
- gl: WebGL2RenderingContext,
109
- options?: {
110
- enable?: boolean;
111
- copyState?: boolean;
112
- log?: any;
113
- }
114
- ): WebGL2RenderingContext {
115
- const {enable = true, copyState} = options || {};
116
- // assert(copyState !== undefined);
117
- // @ts-expect-error
118
- if (!gl.state) {
119
- // @ts-ignore
120
- // const {polyfillContext} = global_;
121
- // if (polyfillContext) {
122
- // polyfillContext(gl);
123
- // }
124
-
125
- // Create a state cache
126
- // @ts-expect-error
127
- gl.state = new GLState(gl, {copyState});
128
-
129
- installProgramSpy(gl);
130
-
131
- // intercept all setter functions in the table
132
- for (const key in GL_HOOKED_SETTERS) {
133
- const setter = GL_HOOKED_SETTERS[key];
134
- installSetterSpy(gl, key, setter);
135
- }
136
-
137
- // intercept all getter functions in the table
138
- installGetterOverride(gl, 'getParameter');
139
- installGetterOverride(gl, 'isEnabled');
140
- }
141
-
142
- const glState = getContextState(gl);
143
- glState.enable = enable;
144
-
145
- return gl;
146
- }
147
-
148
- /**
149
- * Saves current WebGL context state onto an internal per-context stack
150
- */
151
- export function pushContextState(gl: WebGL2RenderingContext): void {
152
- let glState = getContextState(gl);
153
- if (!glState) {
154
- trackContextState(gl, {copyState: false});
155
- glState = getContextState(gl);
156
- }
157
- glState.push();
158
- }
159
-
160
- /**
161
- * Restores previously saved WebGL context state
162
- */
163
- export function popContextState(gl: WebGL2RenderingContext): void {
164
- const glState = getContextState(gl);
165
- // assert(glState);
166
- glState.pop();
167
- }
168
-
169
130
  // HELPER FUNCTIONS - INSTALL GET/SET INTERCEPTORS (SPYS) ON THE CONTEXT
170
131
 
171
132
  /**
@@ -185,7 +146,7 @@ function installGetterOverride(gl: WebGL2RenderingContext, functionName: string)
185
146
  return originalGetterFunc(pname);
186
147
  }
187
148
 
188
- const glState = getContextState(gl);
149
+ const glState = WebGLStateTracker.get(gl);
189
150
  if (!(pname in glState.cache)) {
190
151
  // WebGL limits are not prepopulated in the cache, call the original getter when first queried.
191
152
  glState.cache[pname] = originalGetterFunc(pname);
@@ -229,7 +190,7 @@ function installSetterSpy(gl: WebGL2RenderingContext, functionName: string, sett
229
190
  gl[functionName] = function set(...params) {
230
191
  // Update the value
231
192
  // Call the setter with the state cache and the params so that it can store the parameters
232
- const glState = getContextState(gl);
193
+ const glState = WebGLStateTracker.get(gl);
233
194
  // eslint-disable-next-line @typescript-eslint/unbound-method
234
195
  const {valueChanged, oldValue} = setter(glState._updateCache, ...params);
235
196
 
@@ -257,7 +218,7 @@ function installProgramSpy(gl: WebGL2RenderingContext): void {
257
218
  const originalUseProgram = gl.useProgram.bind(gl);
258
219
 
259
220
  gl.useProgram = function useProgramLuma(handle) {
260
- const glState = getContextState(gl);
221
+ const glState = WebGLStateTracker.get(gl);
261
222
  if (glState.program !== handle) {
262
223
  originalUseProgram(handle);
263
224
  glState.program = handle;
@@ -3,7 +3,7 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
5
  import {GLParameters, setGLParameters} from '../parameters/unified-parameter-api';
6
- import {pushContextState, popContextState} from './track-context-state';
6
+ import {WebGLStateTracker} from './webgl-state-tracker';
7
7
 
8
8
  /**
9
9
  * Execute a function with a set of temporary WebGL parameter overrides
@@ -25,7 +25,8 @@ export function withGLParameters(
25
25
 
26
26
  const {nocatch = true} = parameters;
27
27
 
28
- pushContextState(gl);
28
+ const webglState = WebGLStateTracker.get(gl);
29
+ webglState.push();
29
30
  setGLParameters(gl, parameters);
30
31
 
31
32
  // Setup is done, call the function
@@ -34,13 +35,13 @@ export function withGLParameters(
34
35
  if (nocatch) {
35
36
  // Avoid try catch to minimize stack size impact for safe execution paths
36
37
  value = func(gl);
37
- popContextState(gl);
38
+ webglState.pop();
38
39
  } else {
39
40
  // Wrap in a try-catch to ensure that parameters are restored on exceptions
40
41
  try {
41
42
  value = func(gl);
42
43
  } finally {
43
- popContextState(gl);
44
+ webglState.pop();
44
45
  }
45
46
  }
46
47
 
package/src/index.ts CHANGED
@@ -12,6 +12,10 @@
12
12
  export type {WebGLDeviceLimits} from './adapter/device-helpers/webgl-device-limits';
13
13
 
14
14
  // WebGL adapter classes
15
+ export {webgl2Adapter} from './adapter/webgl-adapter';
16
+ export type {WebGLAdapter} from './adapter/webgl-adapter';
17
+
18
+ // WebGL Device classes
15
19
  export {WebGLDevice} from './adapter/webgl-device';
16
20
  export {WebGLCanvasContext} from './adapter/webgl-canvas-context';
17
21
 
@@ -43,18 +47,12 @@ export {setDeviceParameters, withDeviceParameters} from './adapter/converters/de
43
47
 
44
48
  // HELPERS - EXPERIMENTAL
45
49
  export {getShaderLayout} from './adapter/helpers/get-shader-layout';
50
+ export {WebGLStateTracker} from './context/state-tracker/webgl-state-tracker';
46
51
 
47
52
  // TEST EXPORTS
48
53
  export {TEXTURE_FORMATS as _TEXTURE_FORMATS} from './adapter/converters/texture-formats';
49
54
 
50
55
  // DEPRECATED TEST EXPORTS
51
- // State tracking
52
- export {
53
- trackContextState,
54
- pushContextState,
55
- popContextState
56
- } from './context/state-tracker/track-context-state';
57
-
58
56
  export {
59
57
  resetGLParameters,
60
58
  setGLParameters,
@@ -0,0 +1,16 @@
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ const uidCounters: Record<string, number> = {};
6
+
7
+ /**
8
+ * Returns a UID.
9
+ * @param id= - Identifier base name
10
+ * @return uid
11
+ **/
12
+ export function uid(id: string = 'id'): string {
13
+ uidCounters[id] = uidCounters[id] || 1;
14
+ const count = uidCounters[id]++;
15
+ return `${id}-${count}`;
16
+ }
@@ -1,22 +0,0 @@
1
- /**
2
- * Initialize WebGL state caching on a context
3
- * can be called multiple times to enable/disable
4
- *
5
- * @note After calling this function, context state will be cached
6
- * gl.state.push() and gl.state.pop() will be available for saving,
7
- * temporarily modifying, and then restoring state.
8
- */
9
- export declare function trackContextState(gl: WebGL2RenderingContext, options?: {
10
- enable?: boolean;
11
- copyState?: boolean;
12
- log?: any;
13
- }): WebGL2RenderingContext;
14
- /**
15
- * Saves current WebGL context state onto an internal per-context stack
16
- */
17
- export declare function pushContextState(gl: WebGL2RenderingContext): void;
18
- /**
19
- * Restores previously saved WebGL context state
20
- */
21
- export declare function popContextState(gl: WebGL2RenderingContext): void;
22
- //# sourceMappingURL=track-context-state.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"track-context-state.d.ts","sourceRoot":"","sources":["../../../src/context/state-tracker/track-context-state.ts"],"names":[],"mappings":"AAkGA;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,sBAAsB,EAC1B,OAAO,CAAC,EAAE;IACR,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,CAAC,EAAE,GAAG,CAAC;CACX,GACA,sBAAsB,CAgCxB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,sBAAsB,GAAG,IAAI,CAOjE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,sBAAsB,GAAG,IAAI,CAIhE"}