@luma.gl/webgl 9.1.0-alpha.15 → 9.1.0-alpha.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/adapter/converters/device-parameters.d.ts +3 -3
  2. package/dist/adapter/converters/device-parameters.d.ts.map +1 -1
  3. package/dist/adapter/converters/sampler-parameters.js +6 -4
  4. package/dist/adapter/converters/texture-formats.d.ts +49 -11
  5. package/dist/adapter/converters/texture-formats.d.ts.map +1 -1
  6. package/dist/adapter/converters/texture-formats.js +150 -160
  7. package/dist/adapter/helpers/format-utils.d.ts.map +1 -1
  8. package/dist/adapter/helpers/format-utils.js +6 -0
  9. package/dist/adapter/helpers/webgl-texture-utils.d.ts +34 -30
  10. package/dist/adapter/helpers/webgl-texture-utils.d.ts.map +1 -1
  11. package/dist/adapter/helpers/webgl-texture-utils.js +52 -256
  12. package/dist/adapter/resources/webgl-command-buffer.d.ts +59 -2
  13. package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
  14. package/dist/adapter/resources/webgl-command-buffer.js +87 -31
  15. package/dist/adapter/resources/webgl-command-encoder.d.ts.map +1 -1
  16. package/dist/adapter/resources/webgl-command-encoder.js +3 -0
  17. package/dist/adapter/resources/webgl-external-texture.js +14 -0
  18. package/dist/adapter/resources/webgl-framebuffer.d.ts.map +1 -1
  19. package/dist/adapter/resources/webgl-framebuffer.js +1 -2
  20. package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
  21. package/dist/adapter/resources/webgl-render-pass.js +38 -20
  22. package/dist/adapter/resources/webgl-render-pipeline.d.ts +1 -1
  23. package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
  24. package/dist/adapter/resources/webgl-render-pipeline.js +30 -16
  25. package/dist/adapter/resources/webgl-shader.d.ts +1 -0
  26. package/dist/adapter/resources/webgl-shader.d.ts.map +1 -1
  27. package/dist/adapter/resources/webgl-shader.js +7 -5
  28. package/dist/adapter/resources/webgl-texture.d.ts +8 -14
  29. package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
  30. package/dist/adapter/resources/webgl-texture.js +119 -208
  31. package/dist/adapter/webgl-adapter.d.ts.map +1 -1
  32. package/dist/adapter/webgl-adapter.js +4 -10
  33. package/dist/adapter/webgl-device.d.ts +8 -3
  34. package/dist/adapter/webgl-device.d.ts.map +1 -1
  35. package/dist/adapter/webgl-device.js +53 -22
  36. package/dist/context/debug/spector-types.js +1 -1
  37. package/dist/context/debug/spector.d.ts +5 -5
  38. package/dist/context/debug/spector.d.ts.map +1 -1
  39. package/dist/context/debug/spector.js +6 -6
  40. package/dist/context/debug/webgl-developer-tools.d.ts +2 -3
  41. package/dist/context/debug/webgl-developer-tools.d.ts.map +1 -1
  42. package/dist/context/debug/webgl-developer-tools.js +6 -19
  43. package/dist/context/helpers/create-browser-context.d.ts +6 -22
  44. package/dist/context/helpers/create-browser-context.d.ts.map +1 -1
  45. package/dist/context/helpers/create-browser-context.js +40 -32
  46. package/dist/dist.dev.js +366 -400
  47. package/dist/dist.min.js +2 -2
  48. package/dist/index.cjs +341 -384
  49. package/dist/index.cjs.map +3 -3
  50. package/package.json +4 -4
  51. package/src/adapter/converters/device-parameters.ts +3 -3
  52. package/src/adapter/converters/sampler-parameters.ts +6 -4
  53. package/src/adapter/converters/texture-formats.ts +171 -177
  54. package/src/adapter/helpers/format-utils.ts +6 -0
  55. package/src/adapter/helpers/webgl-texture-utils.ts +99 -75
  56. package/src/adapter/resources/webgl-command-buffer.ts +124 -40
  57. package/src/adapter/resources/webgl-command-encoder.ts +6 -0
  58. package/src/adapter/resources/webgl-external-texture.ts +14 -0
  59. package/src/adapter/resources/webgl-framebuffer.ts +1 -2
  60. package/src/adapter/resources/webgl-render-pass.ts +44 -23
  61. package/src/adapter/resources/webgl-render-pipeline.ts +32 -16
  62. package/src/adapter/resources/webgl-shader.ts +8 -6
  63. package/src/adapter/resources/webgl-texture.ts +126 -235
  64. package/src/adapter/webgl-adapter.ts +4 -12
  65. package/src/adapter/webgl-device.ts +88 -48
  66. package/src/context/debug/spector-types.ts +1 -1
  67. package/src/context/debug/spector.ts +11 -11
  68. package/src/context/debug/webgl-developer-tools.ts +8 -31
  69. package/src/context/helpers/create-browser-context.ts +53 -63
@@ -58,29 +58,48 @@ export class WebGLDevice extends Device {
58
58
  //
59
59
  constructor(props) {
60
60
  super({ ...props, id: props.id || uid('webgl-device') });
61
+ // WebGL requires a canvas to be created before creating the context
62
+ if (!props.createCanvasContext) {
63
+ throw new Error('WebGLDevice requires props.createCanvasContext to be set');
64
+ }
65
+ const canvasContextProps = props.createCanvasContext === true ? {} : props.createCanvasContext;
61
66
  // If attaching to an already attached context, return the attached device
62
67
  // @ts-expect-error device is attached to context
63
- const device = props.gl?.device;
68
+ let device = canvasContextProps.canvas?.gl?.device;
64
69
  if (device) {
65
70
  throw new Error(`WebGL context already attached to device ${device.id}`);
66
71
  }
67
72
  // Create and instrument context
68
- const canvas = props.gl?.canvas || props.canvas;
69
- this.canvasContext = new WebGLCanvasContext(this, { ...props, canvas });
73
+ this.canvasContext = new WebGLCanvasContext(this, canvasContextProps);
70
74
  this.lost = new Promise(resolve => {
71
75
  this._resolveContextLost = resolve;
72
76
  });
73
- this.handle = createBrowserContext(this.canvasContext.canvas, {
74
- ...props,
77
+ const webglContextAttributes = { ...props.webgl };
78
+ // Copy props from CanvasContextProps
79
+ if (canvasContextProps.alphaMode === 'premultiplied') {
80
+ webglContextAttributes.premultipliedAlpha = true;
81
+ }
82
+ if (props.powerPreference !== undefined) {
83
+ webglContextAttributes.powerPreference = props.powerPreference;
84
+ }
85
+ const gl = createBrowserContext(this.canvasContext.canvas, {
75
86
  onContextLost: (event) => this._resolveContextLost?.({
76
87
  reason: 'destroyed',
77
88
  message: 'Entered sleep mode, or too many apps or browser tabs are using the GPU.'
78
- })
79
- });
80
- this.gl = this.handle;
81
- if (!this.handle) {
89
+ }),
90
+ // eslint-disable-next-line no-console
91
+ onContextRestored: (event) => console.log('WebGL context restored')
92
+ }, webglContextAttributes);
93
+ if (!gl) {
82
94
  throw new Error('WebGL context creation failed');
83
95
  }
96
+ // @ts-expect-error device is attached to context
97
+ device = gl.device;
98
+ if (device) {
99
+ throw new Error(`WebGL context already attached to device ${device.id}`);
100
+ }
101
+ this.handle = gl;
102
+ this.gl = gl;
84
103
  // Add spector debug instrumentation to context
85
104
  // We need to trust spector integration to decide if spector should be initialized
86
105
  // We also run spector instrumentation first, otherwise spector can clobber luma instrumentation.
@@ -91,8 +110,8 @@ export class WebGLDevice extends Device {
91
110
  // initialize luma Device fields
92
111
  this.info = getDeviceInfo(this.gl, this._extensions);
93
112
  this.limits = new WebGLDeviceLimits(this.gl);
94
- this.features = new WebGLDeviceFeatures(this.gl, this._extensions, this.props.disabledFeatures);
95
- if (this.props.initalizeFeatures) {
113
+ this.features = new WebGLDeviceFeatures(this.gl, this._extensions, this.props._disabledFeatures);
114
+ if (this.props._initializeFeatures) {
96
115
  this.features.initializeFeatures();
97
116
  }
98
117
  this.canvasContext.resize();
@@ -102,11 +121,14 @@ export class WebGLDevice extends Device {
102
121
  });
103
122
  glState.trackState(this.gl, { copyState: false });
104
123
  // DEBUG contexts: Add luma debug instrumentation to the context, force log level to at least 1
105
- if (props.debug) {
106
- this.gl = makeDebugContext(this.gl, { ...props, throwOnError: true });
107
- this.debug = true;
108
- log.level = Math.max(log.level, 1);
124
+ const debugWebGL = props.debugWebGL || props.debug;
125
+ const traceWebGL = props.debugWebGL;
126
+ if (debugWebGL) {
127
+ this.gl = makeDebugContext(this.gl, { debugWebGL, traceWebGL });
109
128
  log.warn('WebGL debug mode activated. Performance reduced.')();
129
+ if (props.debugWebGL) {
130
+ log.level = Math.max(log.level, 1);
131
+ }
110
132
  }
111
133
  }
112
134
  /**
@@ -131,7 +153,7 @@ export class WebGLDevice extends Device {
131
153
  throw new Error('WebGL only supports a single canvas');
132
154
  }
133
155
  createBuffer(props) {
134
- const newProps = this._getBufferProps(props);
156
+ const newProps = this._normalizeBufferProps(props);
135
157
  return new WEBGLBuffer(this, newProps);
136
158
  }
137
159
  createTexture(props) {
@@ -257,18 +279,27 @@ export class WebGLDevice extends Device {
257
279
  * Be aware that there are some duplicates especially for constants that are 0,
258
280
  * so this isn't guaranteed to return the right key in all cases.
259
281
  */
260
- getGLKey(value, gl) {
261
- // @ts-ignore expect-error depends on settings
262
- gl = gl || this.gl2 || this.gl;
282
+ getGLKey(value, options) {
263
283
  const number = Number(value);
264
- for (const key in gl) {
284
+ for (const key in this.gl) {
265
285
  // @ts-ignore expect-error depends on settings
266
- if (gl[key] === number) {
286
+ if (this.gl[key] === number) {
267
287
  return `GL.${key}`;
268
288
  }
269
289
  }
270
290
  // No constant found. Stringify the value and return it.
271
- return String(value);
291
+ return options?.emptyIfUnknown ? '' : String(value);
292
+ }
293
+ /**
294
+ * Returns a map with any GL.<KEY> constants mapped to strings, both for keys and values
295
+ */
296
+ getGLKeys(glParameters) {
297
+ const opts = { emptyIfUnknown: true };
298
+ return Object.entries(glParameters).reduce((keys, [key, value]) => {
299
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
300
+ keys[`${key}:${this.getGLKey(key, opts)}`] = `${value}:${this.getGLKey(value, opts)}`;
301
+ return keys;
302
+ }, {});
272
303
  }
273
304
  /** Store constants */
274
305
  _constants;
@@ -1,5 +1,5 @@
1
1
  // Forked from https://github.com/BabylonJS/Spector.js/blob/master/dist/spector.d.ts
2
- /* eslint-disable camelcase */
2
+ /* eslint-disable camelcase, no-shadow */
3
3
  var LogLevel;
4
4
  (function (LogLevel) {
5
5
  LogLevel[LogLevel["noLog"] = 0] = "noLog";
@@ -1,10 +1,10 @@
1
- import { Spector } from "./spector-types.js";
1
+ import type { Spector } from "./spector-types.js";
2
2
  /** Spector debug initialization options */
3
3
  type SpectorProps = {
4
- /** Whether spector is enabled */
5
- debugWithSpectorJS?: boolean;
4
+ /** Whether spector.js is enabled */
5
+ debugSpectorJS?: boolean;
6
6
  /** URL to load spector script from. Typically a CDN URL */
7
- spectorUrl?: string;
7
+ debugSpectorJSUrl?: string;
8
8
  /** Canvas to monitor */
9
9
  gl?: WebGL2RenderingContext;
10
10
  };
@@ -14,7 +14,7 @@ declare global {
14
14
  export declare const DEFAULT_SPECTOR_PROPS: Required<SpectorProps>;
15
15
  /** Loads spector from CDN if not already installed */
16
16
  export declare function loadSpectorJS(props: {
17
- spectorUrl?: string;
17
+ debugSpectorJSUrl?: string;
18
18
  }): Promise<void>;
19
19
  export declare function initializeSpectorJS(props: SpectorProps): Spector | null;
20
20
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"spector.d.ts","sourceRoot":"","sources":["../../../src/context/debug/spector.ts"],"names":[],"mappings":"AAOA,OAAO,EAAC,OAAO,EAAC,2BAAwB;AAExC,2CAA2C;AAC3C,KAAK,YAAY,GAAG;IAClB,iCAAiC;IACjC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wBAAwB;IACxB,EAAE,CAAC,EAAE,sBAAsB,CAAC;CAC7B,CAAC;AAOF,OAAO,CAAC,MAAM,CAAC;IAGb,IAAI,OAAO,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,YAAY,CAOxD,CAAC;AAEF,sDAAsD;AACtD,wBAAsB,aAAa,CAAC,KAAK,EAAE;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ/E;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,GAAG,IAAI,CAyDvE"}
1
+ {"version":3,"file":"spector.d.ts","sourceRoot":"","sources":["../../../src/context/debug/spector.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,OAAO,EAAC,2BAAwB;AAE7C,2CAA2C;AAC3C,KAAK,YAAY,GAAG;IAClB,oCAAoC;IACpC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,2DAA2D;IAC3D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,wBAAwB;IACxB,EAAE,CAAC,EAAE,sBAAsB,CAAC;CAC7B,CAAC;AAOF,OAAO,CAAC,MAAM,CAAC;IAGb,IAAI,OAAO,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,YAAY,CAOxD,CAAC;AAEF,sDAAsD;AACtD,wBAAsB,aAAa,CAAC,KAAK,EAAE;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAQtF;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,GAAG,IAAI,CAyDvE"}
@@ -7,18 +7,18 @@ const LOG_LEVEL = 1;
7
7
  let spector = null;
8
8
  let initialized = false;
9
9
  export const DEFAULT_SPECTOR_PROPS = {
10
- debugWithSpectorJS: log.get('spector') || log.get('spectorjs'),
10
+ debugSpectorJS: log.get('debug-spectorjs'),
11
11
  // https://github.com/BabylonJS/Spector.js#basic-usage
12
12
  // https://forum.babylonjs.com/t/spectorcdn-is-temporarily-off/48241
13
13
  // spectorUrl: 'https://spectorcdn.babylonjs.com/spector.bundle.js';
14
- spectorUrl: 'https://cdn.jsdelivr.net/npm/spectorjs@0.9.30/dist/spector.bundle.js',
14
+ debugSpectorJSUrl: 'https://cdn.jsdelivr.net/npm/spectorjs@0.9.30/dist/spector.bundle.js',
15
15
  gl: undefined
16
16
  };
17
17
  /** Loads spector from CDN if not already installed */
18
18
  export async function loadSpectorJS(props) {
19
19
  if (!globalThis.SPECTOR) {
20
20
  try {
21
- await loadScript(props.spectorUrl || DEFAULT_SPECTOR_PROPS.spectorUrl);
21
+ await loadScript(props.debugSpectorJSUrl || DEFAULT_SPECTOR_PROPS.debugSpectorJSUrl);
22
22
  }
23
23
  catch (error) {
24
24
  log.warn(String(error));
@@ -27,13 +27,13 @@ export async function loadSpectorJS(props) {
27
27
  }
28
28
  export function initializeSpectorJS(props) {
29
29
  props = { ...DEFAULT_SPECTOR_PROPS, ...props };
30
- if (!props.debugWithSpectorJS) {
30
+ if (!props.debugSpectorJS) {
31
31
  return null;
32
32
  }
33
33
  if (!spector && globalThis.SPECTOR && !globalThis.luma?.spector) {
34
34
  log.probe(LOG_LEVEL, 'SPECTOR found and initialized. Start with `luma.spector.displayUI()`')();
35
- const { Spector } = globalThis.SPECTOR;
36
- spector = new Spector();
35
+ const { Spector: SpectorJS } = globalThis.SPECTOR;
36
+ spector = new SpectorJS();
37
37
  if (globalThis.luma) {
38
38
  globalThis.luma.spector = spector;
39
39
  }
@@ -1,7 +1,6 @@
1
1
  type DebugContextProps = {
2
- debug?: boolean;
3
- throwOnError?: boolean;
4
- break?: string[];
2
+ debugWebGL?: boolean;
3
+ traceWebGL?: boolean;
5
4
  };
6
5
  declare global {
7
6
  var WebGLDebugUtils: any;
@@ -1 +1 @@
1
- {"version":3,"file":"webgl-developer-tools.d.ts","sourceRoot":"","sources":["../../../src/context/debug/webgl-developer-tools.ts"],"names":[],"mappings":"AAYA,KAAK,iBAAiB,GAAG;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAoBF,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,eAAe,EAAE,GAAG,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC,CAO7D;AAID,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,sBAAsB,EAC1B,KAAK,GAAE,iBAAsB,GAC5B,sBAAsB,CAExB"}
1
+ {"version":3,"file":"webgl-developer-tools.d.ts","sourceRoot":"","sources":["../../../src/context/debug/webgl-developer-tools.ts"],"names":[],"mappings":"AAYA,KAAK,iBAAiB,GAAG;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAaF,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,eAAe,EAAE,GAAG,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC,CAO7D;AAID,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,sBAAsB,EAC1B,KAAK,GAAE,iBAAsB,GAC5B,sBAAsB,CAExB"}
@@ -29,7 +29,7 @@ export async function loadWebGLDeveloperTools() {
29
29
  // Returns (a potentially new) context with debug instrumentation turned off or on.
30
30
  // Note that this actually returns a new context
31
31
  export function makeDebugContext(gl, props = {}) {
32
- return props.debug ? getDebugContext(gl, props) : getRealContext(gl);
32
+ return props.debugWebGL || props.traceWebGL ? getDebugContext(gl, props) : getRealContext(gl);
33
33
  }
34
34
  // Returns the real context from either of the real/debug contexts
35
35
  function getRealContext(gl) {
@@ -88,35 +88,22 @@ function onGLError(props, err, functionName, args) {
88
88
  const message = `${errorMessage} in gl.${functionName}(${functionArgs})`;
89
89
  log.error(message)();
90
90
  debugger; // eslint-disable-line
91
- if (props.throwOnError) {
92
- throw new Error(message);
93
- }
91
+ // throw new Error(message);
94
92
  }
95
93
  // Don't generate function string until it is needed
96
94
  function onValidateGLFunc(props, functionName, functionArgs) {
97
95
  let functionString = '';
98
96
  if (log.level >= 1) {
99
97
  functionString = getFunctionString(functionName, functionArgs);
100
- log.log(1, functionString)();
101
- }
102
- // If array of breakpoint strings supplied, check if any of them is contained in current GLEnum function
103
- if (props.break && props.break.length > 0) {
104
- functionString = functionString || getFunctionString(functionName, functionArgs);
105
- const isBreakpoint = props.break.every((breakOn) => functionString.indexOf(breakOn) !== -1);
106
- if (isBreakpoint) {
107
- debugger; // eslint-disable-line
98
+ if (props.traceWebGL) {
99
+ log.log(1, functionString)();
108
100
  }
109
101
  }
110
102
  for (const arg of functionArgs) {
111
103
  if (arg === undefined) {
112
104
  functionString = functionString || getFunctionString(functionName, functionArgs);
113
- if (props.throwOnError) {
114
- throw new Error(`Undefined argument: ${functionString}`);
115
- }
116
- else {
117
- log.error(`Undefined argument: ${functionString}`)();
118
- debugger; // eslint-disable-line
119
- }
105
+ debugger; // eslint-disable-line
106
+ // throw new Error(`Undefined argument: ${functionString}`);
120
107
  }
121
108
  }
122
109
  }
@@ -1,35 +1,19 @@
1
1
  /**
2
2
  * ContextProps
3
3
  * @param onContextLost
4
- * @param onContextRestored
5
- *
6
- * BROWSER CONTEXT PARAMETERS
7
- * @param debug Instrument context (at the expense of performance).
8
- * @param alpha Default render target has an alpha buffer.
9
- * @param depth Default render target has a depth buffer of at least 16 bits.
10
- * @param stencil Default render target has a stencil buffer of at least 8 bits.
11
- * @param antialias Boolean that indicates whether or not to perform anti-aliasing.
12
- * @param premultipliedAlpha Boolean that indicates that the page compositor will assume the drawing buffer contains colors with pre-multiplied alpha.
13
- * @param preserveDrawingBuffer Default render target buffers will not be automatically cleared and will preserve their values until cleared or overwritten
14
- * @param failIfMajorPerformanceCaveat Do not create if the system performance is low.
4
+ * @param onContextRestored *
15
5
  */
16
6
  type ContextProps = {
17
- onContextLost?: (event: Event) => void;
18
- onContextRestored?: (event: Event) => void;
19
- alpha?: boolean;
20
- desynchronized?: boolean;
21
- antialias?: boolean;
22
- depth?: boolean;
23
- failIfMajorPerformanceCaveat?: boolean;
24
- powerPreference?: 'default' | 'high-performance' | 'low-power';
25
- premultipliedAlpha?: boolean;
26
- preserveDrawingBuffer?: boolean;
7
+ /** Called when a context is lost */
8
+ onContextLost: (event: Event) => void;
9
+ /** Called when a context is restored */
10
+ onContextRestored: (event: Event) => void;
27
11
  };
28
12
  /**
29
13
  * Create a WebGL context for a canvas
30
14
  * Note calling this multiple time on the same canvas does return the same context
31
15
  * @param canvas A canvas element or offscreen canvas
32
16
  */
33
- export declare function createBrowserContext(canvas: HTMLCanvasElement | OffscreenCanvas, props: ContextProps): WebGL2RenderingContext;
17
+ export declare function createBrowserContext(canvas: HTMLCanvasElement | OffscreenCanvas, props: ContextProps, webglContextAttributes: WebGLContextAttributes): WebGL2RenderingContext;
34
18
  export {};
35
19
  //# sourceMappingURL=create-browser-context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-browser-context.d.ts","sourceRoot":"","sources":["../../../src/context/helpers/create-browser-context.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AACH,KAAK,YAAY,GAAG;IAClB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACvC,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC3C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,eAAe,CAAC,EAAE,SAAS,GAAG,kBAAkB,GAAG,WAAW,CAAC;IAC/D,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,CAAC;AAUF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,iBAAiB,GAAG,eAAe,EAC3C,KAAK,EAAE,YAAY,GAClB,sBAAsB,CA+CxB"}
1
+ {"version":3,"file":"create-browser-context.d.ts","sourceRoot":"","sources":["../../../src/context/helpers/create-browser-context.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,KAAK,YAAY,GAAG;IAClB,oCAAoC;IACpC,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACtC,wCAAwC;IACxC,iBAAiB,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC3C,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,iBAAiB,GAAG,eAAe,EAC3C,KAAK,EAAE,YAAY,EACnB,sBAAsB,EAAE,sBAAsB,GAC7C,sBAAsB,CA4DxB"}
@@ -1,49 +1,57 @@
1
1
  // luma.gl
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
- const DEFAULT_CONTEXT_PROPS = {
5
- powerPreference: 'high-performance', // After all, most apps are using WebGL for performance reasons
6
- // eslint-disable-next-line no-console
7
- onContextLost: () => console.error('WebGL context lost'),
8
- // eslint-disable-next-line no-console
9
- onContextRestored: () => console.info('WebGL context restored')
10
- };
11
4
  /**
12
5
  * Create a WebGL context for a canvas
13
6
  * Note calling this multiple time on the same canvas does return the same context
14
7
  * @param canvas A canvas element or offscreen canvas
15
8
  */
16
- export function createBrowserContext(canvas, props) {
17
- props = { ...DEFAULT_CONTEXT_PROPS, ...props };
9
+ export function createBrowserContext(canvas, props, webglContextAttributes) {
18
10
  // Try to extract any extra information about why context creation failed
19
- let errorMessage = null;
20
- const onCreateError = error => (errorMessage = error.statusMessage || errorMessage);
21
- canvas.addEventListener('webglcontextcreationerror', onCreateError, false);
11
+ let errorMessage = '';
12
+ // const onCreateError = error => (errorMessage = error.statusMessage || errorMessage);
13
+ // Avoid multiple listeners?
14
+ // canvas.removeEventListener('webglcontextcreationerror', onCreateError, false);
15
+ // canvas.addEventListener('webglcontextcreationerror', onCreateError, false);
16
+ const webglProps = {
17
+ preserveDrawingBuffer: true,
18
+ // failIfMajorPerformanceCaveat: true,
19
+ ...webglContextAttributes
20
+ };
22
21
  // Create the desired context
23
22
  let gl = null;
24
- // props.failIfMajorPerformanceCaveat = true;
25
- // We require webgl2 context
26
- gl ||= canvas.getContext('webgl2', props);
27
- // Software GPU
28
- // props.failIfMajorPerformanceCaveat = false;
29
- // if (!gl && props.webgl1) {
30
- // gl = canvas.getContext('webgl', props);
31
- // }
32
- // TODO are we removing this listener before giving it a chance to fire?
33
- canvas.removeEventListener('webglcontextcreationerror', onCreateError, false);
34
- if (!gl) {
35
- throw new Error(`Failed to create WebGL context: ${errorMessage || 'Unknown error'}`);
23
+ // Create a webgl2 context
24
+ gl ||= canvas.getContext('webgl2', webglProps);
25
+ if (webglProps.failIfMajorPerformanceCaveat) {
26
+ errorMessage ||=
27
+ 'Only software GPU is available. Set `failIfMajorPerformanceCaveat: false` to allow.';
28
+ }
29
+ // Creation failed with failIfMajorPerformanceCaveat - Try a Software GPU
30
+ if (!gl && !webglContextAttributes.failIfMajorPerformanceCaveat) {
31
+ webglProps.failIfMajorPerformanceCaveat = false;
32
+ gl = canvas.getContext('webgl2', webglProps);
33
+ // @ts-expect-error
34
+ gl.luma ||= {};
35
+ // @ts-expect-error
36
+ gl.luma.softwareRenderer = true;
36
37
  }
37
- if (props.onContextLost) {
38
- // Carefully extract and wrap callbacks to prevent addEventListener from rebinding them.
39
- const { onContextLost } = props;
40
- canvas.addEventListener('webglcontextlost', (event) => onContextLost(event), false);
38
+ if (!gl) {
39
+ gl = canvas.getContext('webgl', {});
40
+ if (gl) {
41
+ gl = null;
42
+ errorMessage ||= 'Your browser only supports WebGL1';
43
+ }
41
44
  }
42
- if (props.onContextRestored) {
43
- // Carefully extract and wrap callbacks to prevent addEventListener from rebinding them.
44
- const { onContextRestored } = props;
45
- canvas.addEventListener('webglcontextrestored', (event) => onContextRestored(event), false);
45
+ if (!gl) {
46
+ errorMessage ||= 'Your browser does not support WebGL';
47
+ throw new Error(`Failed to create WebGL context: ${errorMessage}`);
46
48
  }
49
+ // Carefully extract and wrap callbacks to prevent addEventListener from rebinding them.
50
+ const { onContextLost, onContextRestored } = props;
51
+ canvas.addEventListener('webglcontextlost', (event) => onContextLost(event), false);
52
+ canvas.addEventListener('webglcontextrestored', (event) => onContextRestored(event), false);
53
+ // @ts-expect-error
54
+ gl.luma ||= {};
47
55
  return gl;
48
56
  }
49
57
  /* TODO - can we call this asynchronously to catch the error events?