@luma.gl/webgl 9.0.17 → 9.1.0-alpha.10

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 (144) hide show
  1. package/dist/adapter/converters/device-parameters.d.ts.map +1 -1
  2. package/dist/adapter/converters/device-parameters.js +30 -12
  3. package/dist/adapter/converters/texture-formats.d.ts +22 -16
  4. package/dist/adapter/converters/texture-formats.d.ts.map +1 -1
  5. package/dist/adapter/converters/texture-formats.js +39 -47
  6. package/dist/adapter/device-helpers/webgl-device-features.d.ts.map +1 -1
  7. package/dist/adapter/device-helpers/webgl-device-features.js +1 -2
  8. package/dist/adapter/device-helpers/webgl-device-limits.js +1 -1
  9. package/dist/adapter/helpers/webgl-texture-utils.d.ts +300 -0
  10. package/dist/adapter/helpers/webgl-texture-utils.d.ts.map +1 -0
  11. package/dist/adapter/helpers/webgl-texture-utils.js +370 -0
  12. package/dist/adapter/helpers/webgl-topology-utils.d.ts.map +1 -1
  13. package/dist/adapter/helpers/webgl-topology-utils.js +0 -4
  14. package/dist/adapter/resources/webgl-buffer.d.ts.map +1 -1
  15. package/dist/adapter/resources/webgl-buffer.js +2 -2
  16. package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
  17. package/dist/adapter/resources/webgl-command-buffer.js +6 -9
  18. package/dist/adapter/resources/webgl-framebuffer.d.ts +32 -5
  19. package/dist/adapter/resources/webgl-framebuffer.d.ts.map +1 -1
  20. package/dist/adapter/resources/webgl-framebuffer.js +42 -60
  21. package/dist/adapter/resources/webgl-render-pass.d.ts +3 -2
  22. package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
  23. package/dist/adapter/resources/webgl-render-pass.js +18 -7
  24. package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
  25. package/dist/adapter/resources/webgl-render-pipeline.js +46 -21
  26. package/dist/adapter/resources/webgl-shader.d.ts.map +1 -1
  27. package/dist/adapter/resources/webgl-shader.js +3 -3
  28. package/dist/adapter/resources/webgl-texture-view.d.ts +1 -1
  29. package/dist/adapter/resources/webgl-texture-view.d.ts.map +1 -1
  30. package/dist/adapter/resources/webgl-texture-view.js +1 -1
  31. package/dist/adapter/resources/webgl-texture.d.ts +76 -172
  32. package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
  33. package/dist/adapter/resources/webgl-texture.js +397 -511
  34. package/dist/adapter/resources/webgl-vertex-array.d.ts +3 -2
  35. package/dist/adapter/resources/webgl-vertex-array.d.ts.map +1 -1
  36. package/dist/adapter/resources/webgl-vertex-array.js +2 -2
  37. package/dist/adapter/webgl-adapter.d.ts +21 -0
  38. package/dist/adapter/webgl-adapter.d.ts.map +1 -0
  39. package/dist/adapter/webgl-adapter.js +91 -0
  40. package/dist/adapter/webgl-canvas-context.d.ts +3 -1
  41. package/dist/adapter/webgl-canvas-context.d.ts.map +1 -1
  42. package/dist/adapter/webgl-canvas-context.js +2 -0
  43. package/dist/adapter/webgl-device.d.ts +19 -30
  44. package/dist/adapter/webgl-device.d.ts.map +1 -1
  45. package/dist/adapter/webgl-device.js +35 -114
  46. package/dist/classic/accessor.d.ts +22 -1
  47. package/dist/classic/accessor.d.ts.map +1 -1
  48. package/dist/classic/accessor.js +1 -9
  49. package/dist/classic/clear.d.ts.map +1 -1
  50. package/dist/classic/clear.js +2 -5
  51. package/dist/classic/copy-and-blit.d.ts +3 -1
  52. package/dist/classic/copy-and-blit.d.ts.map +1 -1
  53. package/dist/classic/copy-and-blit.js +21 -18
  54. package/dist/classic/format-utils.d.ts.map +1 -1
  55. package/dist/classic/format-utils.js +0 -3
  56. package/dist/classic/typed-array-utils.d.ts +1 -1
  57. package/dist/classic/typed-array-utils.d.ts.map +1 -1
  58. package/dist/context/debug/spector-types.d.ts +1108 -0
  59. package/dist/context/debug/spector-types.d.ts.map +1 -0
  60. package/dist/context/debug/spector-types.js +697 -0
  61. package/dist/context/debug/spector.d.ts +12 -8
  62. package/dist/context/debug/spector.d.ts.map +1 -1
  63. package/dist/context/debug/spector.js +25 -18
  64. package/dist/context/debug/webgl-developer-tools.d.ts +1 -1
  65. package/dist/context/debug/webgl-developer-tools.d.ts.map +1 -1
  66. package/dist/context/debug/webgl-developer-tools.js +2 -5
  67. package/dist/context/parameters/webgl-parameter-tables.js +1 -1
  68. package/dist/context/polyfills/polyfill-webgl1-extensions.d.ts +9 -0
  69. package/dist/context/polyfills/polyfill-webgl1-extensions.d.ts.map +1 -0
  70. package/dist/context/polyfills/polyfill-webgl1-extensions.js +181 -0
  71. package/dist/context/state-tracker/webgl-state-tracker.d.ts +43 -0
  72. package/dist/context/state-tracker/webgl-state-tracker.d.ts.map +1 -0
  73. package/dist/context/state-tracker/{track-context-state.js → webgl-state-tracker.js} +46 -77
  74. package/dist/context/state-tracker/with-parameters.d.ts.map +1 -1
  75. package/dist/context/state-tracker/with-parameters.js +5 -4
  76. package/dist/dist.dev.js +1112 -1380
  77. package/dist/dist.min.js +2 -2
  78. package/dist/index.cjs +1122 -1284
  79. package/dist/index.cjs.map +4 -4
  80. package/dist/index.d.ts +3 -5
  81. package/dist/index.d.ts.map +1 -1
  82. package/dist/index.js +3 -5
  83. package/dist/utils/fill-array.d.ts +8 -0
  84. package/dist/utils/fill-array.d.ts.map +1 -0
  85. package/dist/utils/fill-array.js +26 -0
  86. package/dist/utils/load-script.d.ts +8 -0
  87. package/dist/utils/load-script.d.ts.map +1 -0
  88. package/dist/utils/load-script.js +26 -0
  89. package/dist/utils/split-uniforms-and-bindings.d.ts +9 -0
  90. package/dist/utils/split-uniforms-and-bindings.d.ts.map +1 -0
  91. package/dist/utils/split-uniforms-and-bindings.js +20 -0
  92. package/dist/utils/uid.d.ts +7 -0
  93. package/dist/utils/uid.d.ts.map +1 -0
  94. package/dist/utils/uid.js +14 -0
  95. package/package.json +6 -5
  96. package/src/adapter/converters/device-parameters.ts +31 -13
  97. package/src/adapter/converters/texture-formats.ts +51 -56
  98. package/src/adapter/device-helpers/webgl-device-features.ts +1 -2
  99. package/src/adapter/device-helpers/webgl-device-limits.ts +1 -1
  100. package/src/adapter/helpers/webgl-texture-utils.ts +484 -0
  101. package/src/adapter/helpers/webgl-topology-utils.ts +0 -4
  102. package/src/adapter/resources/webgl-buffer.ts +2 -2
  103. package/src/adapter/resources/webgl-command-buffer.ts +8 -10
  104. package/src/adapter/resources/webgl-framebuffer.ts +22 -56
  105. package/src/adapter/resources/webgl-render-pass.ts +21 -9
  106. package/src/adapter/resources/webgl-render-pipeline.ts +50 -24
  107. package/src/adapter/resources/webgl-shader.ts +4 -4
  108. package/src/adapter/resources/webgl-texture-view.ts +1 -3
  109. package/src/adapter/resources/webgl-texture.ts +445 -784
  110. package/src/adapter/resources/webgl-vertex-array.ts +8 -7
  111. package/src/adapter/webgl-adapter.ts +113 -0
  112. package/src/adapter/webgl-canvas-context.ts +4 -1
  113. package/src/adapter/webgl-device.ts +40 -151
  114. package/src/classic/accessor.ts +31 -11
  115. package/src/classic/clear.ts +3 -6
  116. package/src/classic/copy-and-blit.ts +32 -27
  117. package/src/classic/format-utils.ts +0 -3
  118. package/src/classic/typed-array-utils.ts +1 -1
  119. package/src/context/debug/spector-types.ts +1154 -0
  120. package/src/context/debug/spector.ts +40 -30
  121. package/src/context/debug/webgl-developer-tools.ts +3 -7
  122. package/src/context/parameters/webgl-parameter-tables.ts +3 -3
  123. package/src/context/polyfills/polyfill-webgl1-extensions.ts +202 -0
  124. package/src/context/state-tracker/{track-context-state.ts → webgl-state-tracker.ts} +57 -97
  125. package/src/context/state-tracker/with-parameters.ts +5 -4
  126. package/src/index.ts +5 -13
  127. package/src/utils/fill-array.ts +35 -0
  128. package/src/utils/load-script.ts +30 -0
  129. package/src/utils/split-uniforms-and-bindings.ts +31 -0
  130. package/src/utils/uid.ts +16 -0
  131. package/dist/adapter/objects/constants-to-keys.d.ts +0 -3
  132. package/dist/adapter/objects/constants-to-keys.d.ts.map +0 -1
  133. package/dist/adapter/objects/constants-to-keys.js +0 -22
  134. package/dist/adapter/objects/webgl-renderbuffer.d.ts +0 -43
  135. package/dist/adapter/objects/webgl-renderbuffer.d.ts.map +0 -1
  136. package/dist/adapter/objects/webgl-renderbuffer.js +0 -95
  137. package/dist/adapter/objects/webgl-resource.d.ts +0 -32
  138. package/dist/adapter/objects/webgl-resource.d.ts.map +0 -1
  139. package/dist/adapter/objects/webgl-resource.js +0 -114
  140. package/dist/context/state-tracker/track-context-state.d.ts +0 -22
  141. package/dist/context/state-tracker/track-context-state.d.ts.map +0 -1
  142. package/src/adapter/objects/constants-to-keys.ts +0 -27
  143. package/src/adapter/objects/webgl-renderbuffer.ts +0 -132
  144. package/src/adapter/objects/webgl-resource.ts +0 -183
@@ -2,56 +2,64 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import {log, loadScript} from '@luma.gl/core';
5
+ import {log} from '@luma.gl/core';
6
+ import {loadScript} from '../../utils/load-script';
7
+
8
+ import {Spector} from './spector-types';
6
9
 
7
10
  /** Spector debug initialization options */
8
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;
9
16
  /** Canvas to monitor */
10
- canvas?: HTMLCanvasElement | OffscreenCanvas;
11
- /** Whether debug is enabled. Auto-detected if ommitted */
12
- debug?: boolean;
13
- /** Whether spector is disabled */
14
- spector?: boolean | string | object;
15
- };
16
-
17
- const DEFAULT_SPECTOR_PROPS: SpectorProps = {
18
- spector: log.get('spector') || log.get('spectorjs')
17
+ gl?: WebGL2RenderingContext;
19
18
  };
20
19
 
21
- // https://github.com/BabylonJS/Spector.js#basic-usage
22
- const SPECTOR_CDN_URL = 'https://cdn.jsdelivr.net/npm/spectorjs@0.9.30/dist/spector.bundle.js';
23
20
  const LOG_LEVEL = 1;
24
21
 
25
- let spector: any = null;
22
+ let spector: Spector = null;
26
23
  let initialized: boolean = false;
27
24
 
28
25
  declare global {
26
+ // @ts-ignore
29
27
  // eslint-disable-next-line no-var
30
- var SPECTOR: any;
28
+ var SPECTOR: Spector;
31
29
  }
32
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
+
33
40
  /** Loads spector from CDN if not already installed */
34
- export async function loadSpectorJS(props?: SpectorProps) {
41
+ export async function loadSpectorJS(props: {spectorUrl?: string}): Promise<void> {
35
42
  if (!globalThis.SPECTOR) {
36
43
  try {
37
- await loadScript(SPECTOR_CDN_URL);
44
+ await loadScript(props.spectorUrl || DEFAULT_SPECTOR_PROPS.spectorUrl);
38
45
  } catch (error) {
39
46
  log.warn(String(error));
40
47
  }
41
48
  }
42
49
  }
43
50
 
44
- export function initializeSpectorJS(props?: SpectorProps) {
51
+ export function initializeSpectorJS(props: SpectorProps): Spector | null {
45
52
  props = {...DEFAULT_SPECTOR_PROPS, ...props};
46
- if (!props?.spector) {
53
+ if (!props.debugWithSpectorJS) {
47
54
  return null;
48
55
  }
49
56
 
50
- if (!spector && globalThis.SPECTOR) {
51
- log.probe(LOG_LEVEL, 'SPECTOR found and initialized')();
52
- 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();
53
61
  if (globalThis.luma) {
54
- globalThis.luma.spector = spector;
62
+ (globalThis.luma as any).spector = spector;
55
63
  }
56
64
  }
57
65
 
@@ -73,20 +81,22 @@ export function initializeSpectorJS(props?: SpectorProps) {
73
81
  // Use undocumented Spector API to open the UI with our capture
74
82
  // See https://github.com/BabylonJS/Spector.js/blob/767ad1195a25b85a85c381f400eb50a979239eca/src/spector.ts#L124
75
83
  spector?.getResultUI();
84
+ // @ts-expect-error private
76
85
  spector?.resultView.display();
86
+ // @ts-expect-error private
77
87
  spector?.resultView.addCapture(capture);
78
88
  });
79
89
  }
80
90
 
81
- if (props?.canvas) {
82
- // @ts-expect-error If spector is specified as a canvas id, only monitor that canvas
83
- if (typeof props.spector === 'string' && props.spector !== props.canvas.id) {
84
- return spector;
85
- }
86
-
91
+ if (props.gl) {
87
92
  // capture startup
88
- // spector?.captureCanvas(props?.canvas);
89
- 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
+
90
100
  new Promise(resolve => setTimeout(resolve, 2000)).then(_ => {
91
101
  log.info('Spector capture stopped after 2 seconds')();
92
102
  spector?.stopCapture();
@@ -2,10 +2,11 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import {log, loadScript} from '@luma.gl/core';
5
+ import {log} from '@luma.gl/core';
6
6
  // Rename constant to prevent inlining. We need the full set of constants for generating debug strings.
7
7
  import {GL as GLEnum} from '@luma.gl/constants';
8
8
  import {isBrowser} from '@probe.gl/env';
9
+ import {loadScript} from '../../utils/load-script';
9
10
 
10
11
  const WEBGL_DEBUG_CDN_URL = 'https://unpkg.com/webgl-debug@2.0.1/index.js';
11
12
 
@@ -58,12 +59,7 @@ export async function loadWebGLDeveloperTools(): Promise<void> {
58
59
  export function makeDebugContext(
59
60
  gl: WebGL2RenderingContext,
60
61
  props: DebugContextProps = {}
61
- ): WebGL2RenderingContext | null {
62
- // Return null to ensure we don't try to create a context in this case (TODO what case is that?)
63
- if (!gl) {
64
- return null;
65
- }
66
-
62
+ ): WebGL2RenderingContext {
67
63
  return props.debug ? getDebugContext(gl, props) : getRealContext(gl);
68
64
  }
69
65
 
@@ -100,7 +100,7 @@ const pixelStorei = (gl: WebGL2RenderingContext, value: number | boolean, key: G
100
100
 
101
101
  const bindFramebuffer = (gl: WebGL2RenderingContext, value: unknown, key: GL) => {
102
102
  const target = key === GL.FRAMEBUFFER_BINDING ? GL.DRAW_FRAMEBUFFER : GL.READ_FRAMEBUFFER;
103
- return gl.bindFramebuffer(target, value);
103
+ return gl.bindFramebuffer(target, value as WebGLFramebuffer);
104
104
  };
105
105
 
106
106
  const bindBuffer = (gl: WebGL2RenderingContext, value: unknown, key: GL) => {
@@ -113,7 +113,7 @@ const bindBuffer = (gl: WebGL2RenderingContext, value: unknown, key: GL) => {
113
113
  };
114
114
  const glTarget = bindingMap[key];
115
115
 
116
- gl.bindBuffer(glTarget, value);
116
+ gl.bindBuffer(glTarget as number, value as WebGLBuffer | null);
117
117
  };
118
118
 
119
119
  // Utility
@@ -304,7 +304,7 @@ export const GL_PARAMETER_SETTERS = {
304
304
  gl.polygonOffset(...value),
305
305
 
306
306
  sampleCoverage: (gl: WebGL2RenderingContext, value: [number, boolean?]) =>
307
- gl.sampleCoverage(...value),
307
+ gl.sampleCoverage(value[0], value[1] || false),
308
308
 
309
309
  scissorTest: (gl: WebGL2RenderingContext, value) =>
310
310
  value ? gl.enable(GL.SCISSOR_TEST) : gl.disable(GL.SCISSOR_TEST),
@@ -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,38 +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
7
- import {assert} from '@luma.gl/core';
5
+ import {setGLParameters, getGLParameters} from '../parameters/unified-parameter-api';
6
+ import {deepArrayEqual} from './deep-array-equal';
8
7
  import {
9
8
  GL_PARAMETER_DEFAULTS,
10
9
  GL_HOOKED_SETTERS,
11
10
  NON_CACHE_PARAMETERS
12
11
  } from '../parameters/webgl-parameter-tables';
13
- import {setGLParameters, getGLParameters} from '../parameters/unified-parameter-api';
14
- import {deepArrayEqual} from './deep-array-equal';
15
12
 
16
- // 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
+ }
17
24
 
18
- /* eslint-disable no-shadow */
19
- class GLState {
20
25
  gl: WebGL2RenderingContext;
21
26
  program: unknown = null;
22
27
  stateStack: object[] = [];
23
28
  enable = true;
24
- cache: Record<string, any>;
29
+ cache: Record<string, any> = null!;
25
30
  log;
26
31
 
32
+ protected initialized = false;
33
+
27
34
  constructor(
28
35
  gl: WebGL2RenderingContext,
29
- {
30
- copyState = false, // Copy cache from params (slow) or initialize from WebGL defaults (fast)
31
- log = () => {} // Logging function, called when gl parameter change calls are actually issued
32
- } = {}
36
+ props?: {
37
+ log; // Logging function, called when gl parameter change calls are actually issued
38
+ }
33
39
  ) {
34
40
  this.gl = gl;
35
- this.cache = copyState ? getGLParameters(gl) : Object.assign({}, GL_PARAMETER_DEFAULTS);
36
- this.log = log;
41
+ this.log = props?.log || (() => {});
37
42
 
38
43
  this._updateCache = this._updateCache.bind(this);
39
44
  Object.seal(this);
@@ -44,7 +49,7 @@ class GLState {
44
49
  }
45
50
 
46
51
  pop() {
47
- assert(this.stateStack.length > 0);
52
+ // assert(this.stateStack.length > 0);
48
53
  // Use the saved values in the state stack to restore parameters
49
54
  const oldValues = this.stateStack[this.stateStack.length - 1];
50
55
  setGLParameters(this.gl, oldValues);
@@ -52,6 +57,38 @@ class GLState {
52
57
  this.stateStack.pop();
53
58
  }
54
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
+
55
92
  /**
56
93
  // interceptor for context set functions - update our cache and our stack
57
94
  // values (Object) - the key values for this setter
@@ -66,7 +103,7 @@ class GLState {
66
103
  this.stateStack.length > 0 ? this.stateStack[this.stateStack.length - 1] : null;
67
104
 
68
105
  for (const key in values) {
69
- assert(key !== undefined);
106
+ // assert(key !== undefined);
70
107
  const value = values[key];
71
108
  const cached = this.cache[key];
72
109
  // Check that value hasn't already been shadowed
@@ -90,83 +127,6 @@ class GLState {
90
127
  }
91
128
  }
92
129
 
93
- function getContextState(gl: WebGL2RenderingContext): GLState {
94
- // @ts-expect-error
95
- return gl.state as GLState;
96
- }
97
-
98
- // PUBLIC API
99
-
100
- /**
101
- * Initialize WebGL state caching on a context
102
- * can be called multiple times to enable/disable
103
- *
104
- * @note After calling this function, context state will be cached
105
- * gl.state.push() and gl.state.pop() will be available for saving,
106
- * temporarily modifying, and then restoring state.
107
- */
108
- export function trackContextState(
109
- gl: WebGL2RenderingContext,
110
- options?: {
111
- enable?: boolean;
112
- copyState?: boolean;
113
- log?: any;
114
- }
115
- ): WebGL2RenderingContext {
116
- const {enable = true, copyState} = options;
117
- assert(copyState !== undefined);
118
- // @ts-expect-error
119
- if (!gl.state) {
120
- // @ts-ignore
121
- // const {polyfillContext} = global_;
122
- // if (polyfillContext) {
123
- // polyfillContext(gl);
124
- // }
125
-
126
- // Create a state cache
127
- // @ts-expect-error
128
- gl.state = new GLState(gl, {copyState});
129
-
130
- installProgramSpy(gl);
131
-
132
- // intercept all setter functions in the table
133
- for (const key in GL_HOOKED_SETTERS) {
134
- const setter = GL_HOOKED_SETTERS[key];
135
- installSetterSpy(gl, key, setter);
136
- }
137
-
138
- // intercept all getter functions in the table
139
- installGetterOverride(gl, 'getParameter');
140
- installGetterOverride(gl, 'isEnabled');
141
- }
142
-
143
- const glState = getContextState(gl);
144
- glState.enable = enable;
145
-
146
- return gl;
147
- }
148
-
149
- /**
150
- * Saves current WebGL context state onto an internal per-context stack
151
- */
152
- export function pushContextState(gl: WebGL2RenderingContext): void {
153
- let glState = getContextState(gl);
154
- if (!glState) {
155
- trackContextState(gl, {copyState: false});
156
- glState = getContextState(gl);
157
- }
158
- glState.push();
159
- }
160
-
161
- /**
162
- * Restores previously saved WebGL context state
163
- */
164
- export function popContextState(gl: WebGL2RenderingContext): void {
165
- const glState = getContextState(gl);
166
- assert(glState);
167
- glState.pop();
168
- }
169
-
170
130
  // HELPER FUNCTIONS - INSTALL GET/SET INTERCEPTORS (SPYS) ON THE CONTEXT
171
131
 
172
132
  /**
@@ -186,7 +146,7 @@ function installGetterOverride(gl: WebGL2RenderingContext, functionName: string)
186
146
  return originalGetterFunc(pname);
187
147
  }
188
148
 
189
- const glState = getContextState(gl);
149
+ const glState = WebGLStateTracker.get(gl);
190
150
  if (!(pname in glState.cache)) {
191
151
  // WebGL limits are not prepopulated in the cache, call the original getter when first queried.
192
152
  glState.cache[pname] = originalGetterFunc(pname);
@@ -230,7 +190,7 @@ function installSetterSpy(gl: WebGL2RenderingContext, functionName: string, sett
230
190
  gl[functionName] = function set(...params) {
231
191
  // Update the value
232
192
  // Call the setter with the state cache and the params so that it can store the parameters
233
- const glState = getContextState(gl);
193
+ const glState = WebGLStateTracker.get(gl);
234
194
  // eslint-disable-next-line @typescript-eslint/unbound-method
235
195
  const {valueChanged, oldValue} = setter(glState._updateCache, ...params);
236
196
 
@@ -258,7 +218,7 @@ function installProgramSpy(gl: WebGL2RenderingContext): void {
258
218
  const originalUseProgram = gl.useProgram.bind(gl);
259
219
 
260
220
  gl.useProgram = function useProgramLuma(handle) {
261
- const glState = getContextState(gl);
221
+ const glState = WebGLStateTracker.get(gl);
262
222
  if (glState.program !== handle) {
263
223
  originalUseProgram(handle);
264
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,11 +12,14 @@
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
 
18
22
  // WebGL Resource classes
19
- export {WebGLResource, WebGLResource as WEBGLResource} from './adapter/objects/webgl-resource';
20
23
  export {WEBGLBuffer} from './adapter/resources/webgl-buffer';
21
24
  export {WEBGLTexture} from './adapter/resources/webgl-texture';
22
25
  // export {WEBGLExternalTexture} from './adapter/resources/webgl-external-texture';
@@ -44,23 +47,12 @@ export {setDeviceParameters, withDeviceParameters} from './adapter/converters/de
44
47
 
45
48
  // HELPERS - EXPERIMENTAL
46
49
  export {getShaderLayout} from './adapter/helpers/get-shader-layout';
47
- export {convertGLToTextureFormat} from './adapter/converters/texture-formats';
48
-
49
- // Internal WebGL classes
50
- export type {RenderbufferProps as _RenderbufferProps} from './adapter/objects/webgl-renderbuffer';
51
- export {WEBGLRenderbuffer as _WEBGLRenderbuffer} from './adapter/objects/webgl-renderbuffer';
50
+ export {WebGLStateTracker} from './context/state-tracker/webgl-state-tracker';
52
51
 
53
52
  // TEST EXPORTS
54
53
  export {TEXTURE_FORMATS as _TEXTURE_FORMATS} from './adapter/converters/texture-formats';
55
54
 
56
55
  // DEPRECATED TEST EXPORTS
57
- // State tracking
58
- export {
59
- trackContextState,
60
- pushContextState,
61
- popContextState
62
- } from './context/state-tracker/track-context-state';
63
-
64
56
  export {
65
57
  resetGLParameters,
66
58
  setGLParameters,