@luma.gl/core 9.1.0-beta.8 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/adapter/canvas-context.d.ts +30 -73
  2. package/dist/adapter/canvas-context.d.ts.map +1 -1
  3. package/dist/adapter/canvas-context.js +97 -203
  4. package/dist/adapter/canvas-context.js.map +1 -1
  5. package/dist/adapter/device.d.ts +3 -24
  6. package/dist/adapter/device.d.ts.map +1 -1
  7. package/dist/adapter/device.js +10 -22
  8. package/dist/adapter/device.js.map +1 -1
  9. package/dist/adapter/luma.js +1 -1
  10. package/dist/adapter/luma.js.map +1 -1
  11. package/dist/adapter/resources/render-pipeline.d.ts +1 -6
  12. package/dist/adapter/resources/render-pipeline.d.ts.map +1 -1
  13. package/dist/adapter/resources/render-pipeline.js +4 -2
  14. package/dist/adapter/resources/render-pipeline.js.map +1 -1
  15. package/dist/adapter/resources/vertex-array.d.ts +2 -4
  16. package/dist/adapter/resources/vertex-array.d.ts.map +1 -1
  17. package/dist/adapter/resources/vertex-array.js +6 -3
  18. package/dist/adapter/resources/vertex-array.js.map +1 -1
  19. package/dist/dist.dev.js +115 -210
  20. package/dist/dist.min.js +6 -6
  21. package/dist/gpu-type-utils/texture-format-table.js +1 -1
  22. package/dist/gpu-type-utils/texture-format-table.js.map +1 -1
  23. package/dist/gpu-type-utils/texture-formats.d.ts +2 -2
  24. package/dist/gpu-type-utils/texture-formats.d.ts.map +1 -1
  25. package/dist/index.cjs +117 -206
  26. package/dist/index.cjs.map +3 -3
  27. package/package.json +2 -2
  28. package/src/adapter/canvas-context.ts +122 -272
  29. package/src/adapter/device.ts +15 -50
  30. package/src/adapter/resources/render-pipeline.ts +12 -18
  31. package/src/adapter/resources/vertex-array.ts +9 -8
  32. package/src/gpu-type-utils/texture-format-table.ts +1 -1
  33. package/src/gpu-type-utils/texture-formats.ts +1 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luma.gl/core",
3
- "version": "9.1.0-beta.8",
3
+ "version": "9.1.0",
4
4
  "description": "The luma.gl core Device API",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -46,5 +46,5 @@
46
46
  "@probe.gl/stats": "^4.0.8",
47
47
  "@types/offscreencanvas": "^2019.6.4"
48
48
  },
49
- "gitHead": "10846580c7a10c4cc48de01a4e5259cc0a00c249"
49
+ "gitHead": "e5cb5a93674bc7cc571c26dee4d2aef841fdff7f"
50
50
  }
@@ -7,12 +7,10 @@ import type {Device} from './device';
7
7
  import type {Framebuffer} from './resources/framebuffer';
8
8
  import {log} from '../utils/log';
9
9
  import {uid} from '../utils/uid';
10
- import type {DepthStencilTextureFormat} from '../gpu-type-utils/texture-formats';
10
+ import type {TextureFormat} from '../gpu-type-utils/texture-formats';
11
11
 
12
12
  /** Properties for a CanvasContext */
13
13
  export type CanvasContextProps = {
14
- /** Identifier, for debugging */
15
- id?: string;
16
14
  /** If a canvas not supplied, one will be created and added to the DOM. If a string, a canvas with that id will be looked up in the DOM */
17
15
  canvas?: HTMLCanvasElement | OffscreenCanvas | string | null;
18
16
  /** If new canvas is created, it will be created in the specified container, otherwise is appended as a child of document.body */
@@ -42,9 +40,8 @@ export type CanvasContextProps = {
42
40
  */
43
41
  export abstract class CanvasContext {
44
42
  static defaultProps: Required<CanvasContextProps> = {
45
- id: undefined!,
46
43
  canvas: null,
47
- width: 800,
44
+ width: 800, // width are height are only used by headless gl
48
45
  height: 600,
49
46
  useDevicePixels: true,
50
47
  autoResize: true,
@@ -55,41 +52,24 @@ export abstract class CanvasContext {
55
52
  };
56
53
 
57
54
  abstract readonly device: Device;
58
- abstract readonly handle: unknown;
59
55
  readonly id: string;
60
-
61
56
  readonly props: Required<CanvasContextProps>;
62
57
  readonly canvas: HTMLCanvasElement | OffscreenCanvas;
63
58
  readonly htmlCanvas?: HTMLCanvasElement;
64
59
  readonly offscreenCanvas?: OffscreenCanvas;
65
60
  readonly type: 'html-canvas' | 'offscreen-canvas' | 'node';
66
61
 
67
- protected _initializedResolvers = withResolvers<void>();
68
-
69
- /** Promise that resolved once the resize observer has updated the pixel size */
70
- initialized: Promise<void>;
71
- isInitialized: boolean = false;
72
-
73
- /** Visibility is automatically updated (via an IntersectionObserver) */
74
- isVisible: boolean = true;
75
-
76
- /** Device pixel ratio. Automatically updated via media queries */
77
- devicePixelRatio: number;
62
+ /** Format of returned textures: "bgra8unorm", "rgba8unorm" */
63
+ abstract readonly format: TextureFormat;
64
+ /** Default stencil format for depth textures */
65
+ abstract readonly depthStencilFormat: TextureFormat;
78
66
 
79
- /** Exact width of canvas in physical pixels (tracked by a ResizeObserver) */
80
- pixelWidth: number;
81
- /** Exact height of canvas in physical pixels (tracked by a ResizeObserver) */
82
- pixelHeight: number;
67
+ width: number = 1;
68
+ height: number = 1;
83
69
 
84
- /** Width of drawing buffer: automatically updated if props.autoResize is true */
85
- drawingBufferWidth: number;
86
- /** Height of drawing buffer: automatically updated if props.autoResize is true */
87
- drawingBufferHeight: number;
70
+ readonly resizeObserver: ResizeObserver | undefined;
88
71
 
89
- protected readonly _resizeObserver: ResizeObserver | undefined;
90
- protected readonly _intersectionObserver: IntersectionObserver | undefined;
91
-
92
- /** State used by luma.gl classes: TODO - remove */
72
+ /** State used by luma.gl classes: TODO - move to canvasContext*/
93
73
  readonly _canvasSizeInfo = {clientWidth: 0, clientHeight: 0, devicePixelRatio: 1};
94
74
 
95
75
  abstract get [Symbol.toStringTag](): string;
@@ -102,121 +82,61 @@ export abstract class CanvasContext {
102
82
  this.props = {...CanvasContext.defaultProps, ...props};
103
83
  props = this.props;
104
84
 
105
- this.initialized = this._initializedResolvers.promise;
106
-
107
- // Create a canvas element if needed
108
85
  if (!isBrowser()) {
86
+ this.id = 'node-canvas-context';
87
+ this.type = 'node';
88
+ this.width = this.props.width;
89
+ this.height = this.props.height;
109
90
  // TODO - does this prevent app from using jsdom style polyfills?
110
- this.canvas = {width: props.width || 1, height: props.height || 1} as OffscreenCanvas;
111
- } else if (!props.canvas) {
112
- this.canvas = createCanvasElement(props);
91
+ this.canvas = null!;
92
+ return;
93
+ }
94
+
95
+ if (!props.canvas) {
96
+ const canvas = createCanvas(props);
97
+ const container = getContainer(props?.container || null);
98
+ container.insertBefore(canvas, container.firstChild);
99
+
100
+ this.canvas = canvas;
101
+
102
+ if (!props?.visible) {
103
+ this.canvas.style.visibility = 'hidden';
104
+ }
113
105
  } else if (typeof props.canvas === 'string') {
114
106
  this.canvas = getCanvasFromDOM(props.canvas);
115
107
  } else {
116
108
  this.canvas = props.canvas;
117
109
  }
118
110
 
119
- if (typeof HTMLCanvasElement !== 'undefined' && this.canvas instanceof HTMLCanvasElement) {
120
- this.id = props.id || this.canvas.id;
111
+ if (this.canvas instanceof HTMLCanvasElement) {
112
+ this.id = this.canvas.id;
121
113
  this.type = 'html-canvas';
122
114
  this.htmlCanvas = this.canvas;
123
- } else if (typeof OffscreenCanvas !== 'undefined' && this.canvas instanceof OffscreenCanvas) {
124
- this.id = props.id || 'offscreen-canvas';
115
+ } else {
116
+ this.id = 'offscreen-canvas';
125
117
  this.type = 'offscreen-canvas';
126
118
  this.offscreenCanvas = this.canvas;
127
- } else {
128
- // TODO - Node.js support is currently untested (was used for headless-gl in luma v8)
129
- this.id = props.id || 'node-canvas-context';
130
- this.type = 'node';
131
119
  }
132
120
 
133
- // Initialize size variables (these will be updated by ResizeObserver)
134
- this.pixelWidth = this.canvas.width;
135
- this.pixelHeight = this.canvas.height;
136
- this.drawingBufferWidth = this.canvas.width;
137
- this.drawingBufferHeight = this.canvas.height;
138
- this.devicePixelRatio = globalThis.devicePixelRatio || 1;
139
-
140
- if (typeof HTMLCanvasElement !== 'undefined' && this.canvas instanceof HTMLCanvasElement) {
141
- // Track visibility changes
142
- this._intersectionObserver = new IntersectionObserver(entries =>
143
- this._handleIntersection(entries)
144
- );
145
- this._intersectionObserver.observe(this.canvas);
146
-
147
- // Track size changes
148
- this._resizeObserver = new ResizeObserver(entries => this._handleResize(entries));
149
- try {
150
- this._resizeObserver.observe(this.canvas, {box: 'device-pixel-content-box'});
151
- } catch {
152
- // Safari fallback
153
- this._resizeObserver.observe(this.canvas, {box: 'content-box'});
154
- }
155
-
156
- // Track device pixel ratio changes.
157
- // Defer call to after construction completes to ensure `this.device` is available.
158
- setTimeout(() => this._observeDevicePixelRatio(), 0);
121
+ // React to size changes
122
+ if (this.canvas instanceof HTMLCanvasElement && props.autoResize) {
123
+ this.resizeObserver = new ResizeObserver(entries => {
124
+ for (const entry of entries) {
125
+ if (entry.target === this.canvas) {
126
+ this.update();
127
+ }
128
+ }
129
+ });
130
+ this.resizeObserver.observe(this.canvas);
159
131
  }
160
132
  }
161
133
 
162
134
  /** Returns a framebuffer with properly resized current 'swap chain' textures */
163
- abstract getCurrentFramebuffer(options?: {
164
- depthStencilFormat?: DepthStencilTextureFormat | false;
165
- }): Framebuffer;
166
-
167
- // SIZE METHODS
168
-
169
- /**
170
- * Returns the size covered by the canvas in CSS pixels
171
- * @note This can be different from the actual device pixel size of a canvas due to DPR scaling, and rounding to integer pixels
172
- * @note This is independent of the canvas' internal drawing buffer size (.width, .height).
173
- */
174
- getCSSSize(): [number, number] {
175
- if (typeof HTMLCanvasElement !== 'undefined' && this.canvas instanceof HTMLCanvasElement) {
176
- return [this.canvas.clientWidth, this.canvas.clientHeight];
177
- }
178
- return [this.pixelWidth, this.pixelHeight];
179
- }
180
-
181
- /**
182
- * Returns the size covered by the canvas in actual device pixels.
183
- * @note This can be different from the 'CSS' size of a canvas due to DPR scaling, and rounding to integer pixels
184
- * @note This is independent of the canvas' internal drawing buffer size (.width, .height).
185
- */
186
- getPixelSize(): [number, number] {
187
- return [this.pixelWidth, this.pixelHeight];
188
- }
189
-
190
- /** Get the drawing buffer size (number of pixels GPU is rendering into, can be different from CSS size) */
191
- getDrawingBufferSize(): [number, number] {
192
- return [this.drawingBufferWidth, this.drawingBufferHeight];
193
- }
194
-
195
- /** Returns the biggest allowed framebuffer size. @todo Allow the application to limit this? */
196
- getMaxDrawingBufferSize(): [number, number] {
197
- const maxTextureDimension = this.device.limits.maxTextureDimension2D;
198
- return [maxTextureDimension, maxTextureDimension];
199
- }
200
-
201
- /** Update the canvas drawing buffer size. Called automatically if props.autoResize is true. */
202
- setDrawingBufferSize(width: number, height: number) {
203
- this.canvas.width = width;
204
- this.canvas.height = height;
205
-
206
- this.drawingBufferWidth = width;
207
- this.drawingBufferHeight = height;
208
- }
209
-
210
- /** @deprecated - TODO which values should we use for aspect */
211
- getAspect(): number {
212
- const [width, height] = this.getPixelSize();
213
- return width / height;
214
- }
135
+ abstract getCurrentFramebuffer(): Framebuffer;
215
136
 
216
137
  /**
217
- * Returns the current DPR (number of physical pixels per CSS pixel), if props.useDevicePixels is true
218
- * @note This can be a fractional (non-integer) number, e.g. when the user zooms in the browser.
219
- * @note This function handles the non-HTML canvas cases
138
+ * Returns the current DPR, if props.useDevicePixels is true
139
+ * Device refers to physical
220
140
  */
221
141
  getDevicePixelRatio(useDevicePixels?: boolean | number): number {
222
142
  if (typeof OffscreenCanvas !== 'undefined' && this.canvas instanceof OffscreenCanvas) {
@@ -238,6 +158,35 @@ export abstract class CanvasContext {
238
158
  return useDevicePixels;
239
159
  }
240
160
 
161
+ /**
162
+ * Returns the size of drawing buffer in device pixels.
163
+ * @note This can be different from the 'CSS' size of a canvas, and also from the
164
+ * canvas' internal drawing buffer size (.width, .height).
165
+ * This is the size required to cover the canvas, adjusted for DPR
166
+ */
167
+ getPixelSize(): [number, number] {
168
+ switch (this.type) {
169
+ case 'node':
170
+ return [this.width, this.height];
171
+ case 'offscreen-canvas':
172
+ return [this.canvas.width, this.canvas.height];
173
+ case 'html-canvas':
174
+ const dpr = this.getDevicePixelRatio();
175
+ const canvas = this.canvas as HTMLCanvasElement;
176
+ // If not attached to DOM client size can be 0
177
+ return canvas.parentElement
178
+ ? [canvas.clientWidth * dpr, canvas.clientHeight * dpr]
179
+ : [this.canvas.width, this.canvas.height];
180
+ default:
181
+ throw new Error(this.type);
182
+ }
183
+ }
184
+
185
+ getAspect(): number {
186
+ const [width, height] = this.getPixelSize();
187
+ return width / height;
188
+ }
189
+
241
190
  /**
242
191
  * Returns multiplier need to convert CSS size to Device size
243
192
  */
@@ -246,7 +195,8 @@ export abstract class CanvasContext {
246
195
  // For headless gl we might have used custom width and height
247
196
  // hence use cached clientWidth
248
197
  const [drawingBufferWidth] = this.getDrawingBufferSize();
249
- const {clientWidth} = this._canvasSizeInfo;
198
+ // _canvasSizeInfo may not be populated if `setDevicePixelRatio` is never called
199
+ const clientWidth = this._canvasSizeInfo.clientWidth || this.htmlCanvas?.clientWidth;
250
200
  return clientWidth ? drawingBufferWidth / clientWidth : 1;
251
201
  } catch {
252
202
  return 1;
@@ -270,114 +220,11 @@ export abstract class CanvasContext {
270
220
  return scalePixels(cssPixel, ratio, width, height, yInvert);
271
221
  }
272
222
 
273
- // SUBCLASS OVERRIDES
274
-
275
- /** Performs platform specific updates (WebGPU vs WebGL) */
276
- protected abstract updateSize(size: [width: number, height: number]): void;
277
-
278
- // IMPLEMENTATION
279
-
280
- /**
281
- * Allows subclass constructor to override the canvas id for auto created canvases.
282
- * This can really help when debugging DOM in apps that create multiple devices
283
- */
284
- protected _setAutoCreatedCanvasId(id: string) {
285
- if (this.htmlCanvas?.id === 'lumagl-auto-created-canvas') {
286
- this.htmlCanvas.id = id;
287
- }
288
- }
289
-
290
- /** reacts to our intersection observer */
291
- protected _handleIntersection(entries: IntersectionObserverEntry[]) {
292
- const entry = entries.find(entry_ => entry_.target === this.canvas);
293
- if (!entry) {
294
- return;
295
- }
296
- // TODO - store intersection rectangle?
297
- const isVisible = entry.isIntersecting;
298
- if (this.isVisible !== isVisible) {
299
- this.isVisible = isVisible;
300
- this.device.props.onVisibilityChange(this);
301
- }
302
- }
303
-
304
- /**
305
- * Reacts to an observed resize by using the most accurate pixel size information the browser can provide
306
- * @see https://web.dev/articles/device-pixel-content-box
307
- * @see https://webgpufundamentals.org/webgpu/lessons/webgpu-resizing-the-canvas.html
308
- */
309
- protected _handleResize(entries: ResizeObserverEntry[]) {
310
- const entry = entries.find(entry_ => entry_.target === this.canvas);
311
- if (!entry) {
312
- return;
313
- }
314
-
315
- // Use the most accurate drawing buffer size information the current browser can provide
316
- // Note: content box sizes are guaranteed to be integers
317
- // Note: Safari falls back to contentBoxSize
318
- const boxWidth =
319
- entry.devicePixelContentBoxSize?.[0].inlineSize ||
320
- entry.contentBoxSize[0].inlineSize * devicePixelRatio;
321
-
322
- const boxHeight =
323
- entry.devicePixelContentBoxSize?.[0].blockSize ||
324
- entry.contentBoxSize[0].blockSize * devicePixelRatio;
325
-
326
- // Update our drawing buffer size variables, saving the old values for logging
327
- const oldPixelSize = this.getPixelSize();
328
-
329
- // Make sure we don't overflow the maximum supported texture size
330
- const [maxPixelWidth, maxPixelHeight] = this.getMaxDrawingBufferSize();
331
- this.pixelWidth = Math.max(1, Math.min(boxWidth, maxPixelWidth));
332
- this.pixelHeight = Math.max(1, Math.min(boxHeight, maxPixelHeight));
333
-
334
- if (this.props.autoResize) {
335
- // Update the canvas drawing buffer size
336
- // TODO - This does not account for props.useDevicePixels
337
- this.setDrawingBufferSize(this.pixelWidth, this.pixelHeight);
338
-
339
- // Inform the subclass
340
- this.updateSize(this.getDrawingBufferSize());
341
- }
342
-
343
- // Resolve the initialized promise
344
- this._initializedResolvers.resolve();
345
- this.isInitialized = true;
346
-
347
- // Inform the device
348
- this.device.props.onResize(this, {oldPixelSize});
349
- }
350
-
351
- /** Monitor DPR changes */
352
- _observeDevicePixelRatio() {
353
- const oldRatio = this.devicePixelRatio;
354
- this.devicePixelRatio = window.devicePixelRatio;
355
-
356
- // Inform the device
357
- this.device.props.onDevicePixelRatioChange(this, {oldRatio});
358
- // Set up a one time query against the current resolution.
359
- matchMedia(`(resolution: ${this.devicePixelRatio}dppx)`).addEventListener(
360
- 'change',
361
- () => this._observeDevicePixelRatio(),
362
- {once: true}
363
- );
364
- }
365
-
366
- // DEPRECATED
367
-
368
- /** @deprecated Use canvasContext.setDrawingBufferSize()
369
- * Resizes the canvas. Note: Has no effect if props.autoResize is true */
370
- abstract resize(options?: {
371
- width?: number;
372
- height?: number;
373
- useDevicePixels?: boolean | number;
374
- }): void;
375
-
376
223
  /**
377
- * @deprecated Use devicePixelRatio to set canvas width and height
224
+ * Use devicePixelRatio to set canvas width and height
378
225
  * @note this is a raw port of luma.gl v8 code. Might be worth a review
379
226
  */
380
- _setDevicePixelRatio(
227
+ setDevicePixelRatio(
381
228
  devicePixelRatio: number,
382
229
  options: {width?: number; height?: number} = {}
383
230
  ): void {
@@ -437,11 +284,42 @@ export abstract class CanvasContext {
437
284
  }
438
285
  }
439
286
  }
287
+
288
+ // PRIVATE
289
+
290
+ /** @todo Major hack done to port the CSS methods above, base canvas context should not depend on WebGL */
291
+ getDrawingBufferSize(): [number, number] {
292
+ // @ts-expect-error This only works for WebGL
293
+ const gl = this.device.gl;
294
+ if (!gl) {
295
+ // use default device pixel ratio
296
+ throw new Error('canvas size');
297
+ }
298
+ return [gl.drawingBufferWidth, gl.drawingBufferHeight];
299
+ }
300
+
301
+ abstract resize(options?: {
302
+ width?: number;
303
+ height?: number;
304
+ useDevicePixels?: boolean | number;
305
+ }): void;
306
+
307
+ /** Perform platform specific updates (WebGPU vs WebGL) */
308
+ protected abstract update(): void;
309
+
310
+ /**
311
+ * Allows subclass constructor to override the canvas id for auto created canvases.
312
+ * This can really help when debugging DOM in apps that create multiple devices
313
+ */
314
+ protected _setAutoCreatedCanvasId(id: string) {
315
+ if (this.htmlCanvas?.id === 'lumagl-auto-created-canvas') {
316
+ this.htmlCanvas.id = id;
317
+ }
318
+ }
440
319
  }
441
320
 
442
321
  // HELPER FUNCTIONS
443
322
 
444
- /** Get a container element from a string or DOM element */
445
323
  function getContainer(container: HTMLElement | string | null): HTMLElement {
446
324
  if (typeof container === 'string') {
447
325
  const element = document.getElementById(container);
@@ -449,8 +327,7 @@ function getContainer(container: HTMLElement | string | null): HTMLElement {
449
327
  throw new Error(`${container} is not an HTML element`);
450
328
  }
451
329
  return element;
452
- }
453
- if (container) {
330
+ } else if (container) {
454
331
  return container;
455
332
  }
456
333
  return document.body;
@@ -459,37 +336,26 @@ function getContainer(container: HTMLElement | string | null): HTMLElement {
459
336
  /** Get a Canvas element from DOM id */
460
337
  function getCanvasFromDOM(canvasId: string): HTMLCanvasElement {
461
338
  const canvas = document.getElementById(canvasId);
462
- if (
463
- typeof canvas !== 'undefined' &&
464
- typeof HTMLCanvasElement !== 'undefined' &&
465
- !(canvas instanceof HTMLCanvasElement)
466
- ) {
339
+ if (!(canvas instanceof HTMLCanvasElement)) {
467
340
  throw new Error('Object is not a canvas element');
468
341
  }
469
- return canvas as HTMLCanvasElement;
342
+ return canvas;
470
343
  }
471
344
 
472
345
  /** Create a new canvas */
473
- function createCanvasElement(props: CanvasContextProps) {
346
+ function createCanvas(props: CanvasContextProps) {
474
347
  const {width, height} = props;
475
- const newCanvas = document.createElement('canvas');
476
- newCanvas.id = uid('lumagl-auto-created-canvas');
477
- newCanvas.width = width || 1;
478
- newCanvas.height = height || 1;
479
- newCanvas.style.width = Number.isFinite(width) ? `${width}px` : '100%';
480
- newCanvas.style.height = Number.isFinite(height) ? `${height}px` : '100%';
481
- if (!props?.visible) {
482
- newCanvas.style.visibility = 'hidden';
483
- }
484
- // Insert the canvas in the DOM
485
- const container = getContainer(props?.container || null);
486
- container.insertBefore(newCanvas, container.firstChild);
487
-
488
- return newCanvas;
348
+ const targetCanvas = document.createElement('canvas');
349
+ targetCanvas.id = uid('lumagl-auto-created-canvas');
350
+ targetCanvas.width = width || 1;
351
+ targetCanvas.height = height || 1;
352
+ targetCanvas.style.width = Number.isFinite(width) ? `${width}px` : '100%';
353
+ targetCanvas.style.height = Number.isFinite(height) ? `${height}px` : '100%';
354
+ return targetCanvas;
489
355
  }
490
356
 
491
357
  /**
492
- * Scales pixels linearly, handles edge cases
358
+ *
493
359
  * @param pixel
494
360
  * @param ratio
495
361
  * @param width
@@ -554,19 +420,3 @@ function scaleY(y: number, ratio: number, height: number, yInvert: boolean): num
554
420
  ? Math.max(0, height - 1 - Math.round(y * ratio))
555
421
  : Math.min(Math.round(y * ratio), height - 1);
556
422
  }
557
-
558
- // TODO - replace with Promise.withResolvers once we upgrade TS baseline
559
- function withResolvers<T>(): {
560
- promise: Promise<T>;
561
- resolve: (t: T) => void;
562
- reject: (error: Error) => void;
563
- } {
564
- let resolve: (t: T) => void;
565
- let reject: (error: Error) => void;
566
- const promise = new Promise<T>((_resolve, _reject) => {
567
- resolve = _resolve;
568
- reject = _reject;
569
- });
570
- // @ts-expect-error - in fact these are no used before initialized
571
- return {promise, resolve, reject};
572
- }
@@ -219,21 +219,12 @@ export type DeviceProps = {
219
219
  powerPreference?: 'default' | 'high-performance' | 'low-power';
220
220
  /** Hints that device creation should fail if no hardware GPU is available (if the system performance is "low"). */
221
221
  failIfMajorPerformanceCaveat?: boolean;
222
+ /** Error handling */
223
+ onError?: (error: Error) => unknown;
222
224
 
223
225
  /** WebGL specific: Properties passed through to WebGL2RenderingContext creation: `canvas.getContext('webgl2', props.webgl)` */
224
226
  webgl?: WebGLContextProps;
225
227
 
226
- // CALLBACKS
227
-
228
- /** Error handling - uncaught errors */
229
- onError?: (error: Error) => unknown;
230
- /** Called when the size of a canvas changes */
231
- onResize?: (ctx: CanvasContext, info: {oldPixelSize: [number, number]}) => unknown;
232
- /** Called when the visibility of a canvas changes */
233
- onVisibilityChange?: (ctx: CanvasContext) => unknown;
234
- /** Called when the device pixel ratio of a canvas changes */
235
- onDevicePixelRatioChange?: (ctx: CanvasContext, info: {oldRatio: number}) => unknown;
236
-
237
228
  // DEBUG SETTINGS
238
229
 
239
230
  /** Turn on implementation defined checks that slow down execution but help break where errors occur */
@@ -242,8 +233,6 @@ export type DeviceProps = {
242
233
  debugShaders?: 'never' | 'errors' | 'warnings' | 'always';
243
234
  /** Renders a small version of updated Framebuffers into the primary canvas context. Can be set in console luma.log.set('debug-framebuffers', true) */
244
235
  debugFramebuffers?: boolean;
245
- /** Traces resource caching, reuse, and destroys in the PipelineFactory */
246
- debugFactories?: boolean;
247
236
  /** WebGL specific - Trace WebGL calls (instruments WebGL2RenderingContext at the expense of performance). Can be set in console luma.log.set('debug-webgl', true) */
248
237
  debugWebGL?: boolean;
249
238
  /** WebGL specific - Initialize the SpectorJS WebGL debugger. Can be set in console luma.log.set('debug-spectorjs', true) */
@@ -259,12 +248,8 @@ export type DeviceProps = {
259
248
  _disabledFeatures?: Partial<Record<DeviceFeature, boolean>>;
260
249
  /** WebGL specific - Initialize all features on startup */
261
250
  _initializeFeatures?: boolean;
262
- /** Enable shader caching (via ShaderFactory) */
263
- _cacheShaders?: boolean;
264
- /** Enable shader caching (via PipelineFactory) */
265
- _cachePipelines?: boolean;
266
251
  /** Never destroy cached shaders and pipelines */
267
- _cacheDestroyPolicy?: 'unused' | 'never';
252
+ _factoryDestroyPolicy?: 'unused' | 'never';
268
253
  /** Resource default overrides */
269
254
  _resourceDefaults?: {
270
255
  texture?: Partial<TextureProps>;
@@ -308,35 +293,12 @@ export abstract class Device {
308
293
  powerPreference: 'high-performance',
309
294
  failIfMajorPerformanceCaveat: false,
310
295
  createCanvasContext: undefined!,
311
- // WebGL specific
312
- webgl: {},
313
296
 
314
297
  // Callbacks
315
298
  onError: (error: Error) => log.error(error.message)(),
316
- onResize: (context: CanvasContext, info: {oldPixelSize: [number, number]}) => {
317
- const [width, height] = context.getPixelSize();
318
- const [prevWidth, prevHeight] = info.oldPixelSize;
319
- log.log(1, `${context} Resized ${prevWidth}x${prevHeight} => ${width}x${height}px`)();
320
- },
321
- onVisibilityChange: (context: CanvasContext) =>
322
- log.log(1, `${context} Visibility changed ${context.isVisible}`)(),
323
- onDevicePixelRatioChange: (context: CanvasContext, info: {oldRatio: number}) =>
324
- log.log(1, `${context} DPR changed ${info.oldRatio} => ${context.devicePixelRatio}`)(),
325
-
326
- // Debug flags
327
- debug: log.get('debug') || undefined!,
328
- debugShaders: log.get('debug-shaders') || undefined!,
329
- debugFramebuffers: Boolean(log.get('debug-framebuffers')),
330
- debugFactories: Boolean(log.get('debug-factories')),
331
- debugWebGL: Boolean(log.get('debug-webgl')),
332
- debugSpectorJS: undefined!, // Note: log setting is queried by the spector.js code
333
- debugSpectorJSUrl: undefined!,
334
299
 
335
- // Experimental
336
300
  _requestMaxLimits: true,
337
- _cacheShaders: false,
338
- _cachePipelines: false,
339
- _cacheDestroyPolicy: 'unused',
301
+ _factoryDestroyPolicy: 'unused',
340
302
  // TODO - Change these after confirming things work as expected
341
303
  _initializeFeatures: true,
342
304
  _disabledFeatures: {
@@ -344,6 +306,16 @@ export abstract class Device {
344
306
  },
345
307
  _resourceDefaults: {},
346
308
 
309
+ // WebGL specific
310
+ webgl: {},
311
+
312
+ debug: log.get('debug') || undefined!,
313
+ debugShaders: log.get('debug-shaders') || undefined!,
314
+ debugFramebuffers: Boolean(log.get('debug-framebuffers')),
315
+ debugWebGL: Boolean(log.get('debug-webgl')),
316
+ debugSpectorJS: undefined!, // Note: log setting is queried by the spector.js code
317
+ debugSpectorJSUrl: undefined!,
318
+
347
319
  // INTERNAL
348
320
  _handle: undefined!
349
321
  };
@@ -361,8 +333,6 @@ export abstract class Device {
361
333
  readonly id: string;
362
334
  /** type of this device */
363
335
  abstract readonly type: 'webgl' | 'webgpu' | 'unknown';
364
- abstract readonly handle: unknown;
365
-
366
336
  /** A copy of the device props */
367
337
  readonly props: Required<DeviceProps>;
368
338
  /** Available for the application to store data on the device */
@@ -386,11 +356,6 @@ export abstract class Device {
386
356
  /** WebGPU style device limits */
387
357
  abstract get limits(): DeviceLimits;
388
358
 
389
- /** Optimal TextureFormat for displaying 8-bit depth, standard dynamic range content on this system. */
390
- abstract preferredColorFormat: 'rgba8unorm' | 'bgra8unorm';
391
- /** Default depth format used on this system */
392
- abstract preferredDepthFormat: 'depth16' | 'depth24plus' | 'depth32float';
393
-
394
359
  /** Determines what operations are supported on a texture format, checking against supported device features */
395
360
  getTextureFormatCapabilities(format: TextureFormat): DeviceTextureFormatCapabilities {
396
361
  const genericCapabilities = getTextureFormatCapabilities(format);
@@ -633,7 +598,7 @@ export abstract class Device {
633
598
  } else if (props.data instanceof Uint16Array) {
634
599
  newProps.indexType = 'uint16';
635
600
  } else {
636
- log.warn('indices buffer content must be of type uint16 or uint32')();
601
+ log.warn('indices buffer content must be of integer type')();
637
602
  }
638
603
  }
639
604
  return newProps;