@luma.gl/test-utils 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 (36) hide show
  1. package/dist/create-test-device.d.ts +9 -8
  2. package/dist/create-test-device.d.ts.map +1 -1
  3. package/dist/create-test-device.js +46 -87
  4. package/dist/create-test-device.js.map +1 -1
  5. package/dist/deprecated/classic-animation-loop.js +1 -1
  6. package/dist/deprecated/classic-animation-loop.js.map +1 -1
  7. package/dist/index.cjs +1123 -1168
  8. package/dist/index.cjs.map +4 -4
  9. package/dist/index.d.ts +3 -2
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +3 -4
  12. package/dist/index.js.map +1 -1
  13. package/dist/null-device/null-canvas-context.d.ts +5 -3
  14. package/dist/null-device/null-canvas-context.d.ts.map +1 -1
  15. package/dist/null-device/null-canvas-context.js +21 -5
  16. package/dist/null-device/null-canvas-context.js.map +1 -1
  17. package/dist/null-device/null-device.d.ts +0 -3
  18. package/dist/null-device/null-device.d.ts.map +1 -1
  19. package/dist/null-device/null-device.js +1 -3
  20. package/dist/null-device/null-device.js.map +1 -1
  21. package/dist/test-runner.d.ts +1 -1
  22. package/dist/test-runner.d.ts.map +1 -1
  23. package/dist/test-runner.js +2 -3
  24. package/dist/test-runner.js.map +1 -1
  25. package/package.json +2 -2
  26. package/src/create-test-device.ts +46 -96
  27. package/src/deprecated/classic-animation-loop.ts +1 -1
  28. package/src/index.ts +4 -10
  29. package/src/null-device/null-canvas-context.ts +24 -7
  30. package/src/null-device/null-device.ts +1 -5
  31. package/src/test-runner.ts +2 -4
  32. package/dist/deprecated/sync-test-device.d.ts +0 -14
  33. package/dist/deprecated/sync-test-device.d.ts.map +0 -1
  34. package/dist/deprecated/sync-test-device.js +0 -32
  35. package/dist/deprecated/sync-test-device.js.map +0 -1
  36. package/src/deprecated/sync-test-device.ts +0 -35
package/dist/index.cjs CHANGED
@@ -27,1339 +27,1311 @@ __export(dist_exports, {
27
27
  createTestDevice: () => createTestDevice,
28
28
  deepCopy: () => deepCopy,
29
29
  getLeakedResources: () => getLeakedResources,
30
- getNullTestDevice: () => getNullTestDevice,
31
30
  getResourceCounts: () => getResourceCounts,
32
31
  getTestDevices: () => getTestDevices,
33
- getWebGLTestDevice: () => getWebGLTestDevice,
34
- getWebGPUTestDevice: () => getWebGPUTestDevice,
35
32
  nullAdapter: () => nullAdapter,
36
- webglDevice: () => webglDevice2
33
+ webglDevice: () => webglDevice,
34
+ webgpuDevice: () => webgpuDevice
37
35
  });
38
36
  module.exports = __toCommonJS(dist_exports);
39
37
 
40
38
  // dist/create-test-device.js
41
- var import_core17 = require("@luma.gl/core");
39
+ var import_core = require("@luma.gl/core");
42
40
  var import_webgl = require("@luma.gl/webgl");
43
41
  var import_webgpu = require("@luma.gl/webgpu");
44
-
45
- // dist/null-device/null-adapter.js
46
- var import_core16 = require("@luma.gl/core");
47
-
48
- // dist/null-device/null-device.js
49
- var import_core15 = require("@luma.gl/core");
50
-
51
- // dist/null-device/null-device-info.js
52
- var NullDeviceInfo = {
53
- type: "unknown",
54
- gpu: "software",
55
- gpuType: "unknown",
56
- gpuBackend: "unknown",
57
- vendor: "no one",
58
- renderer: "none",
59
- version: "1.0",
60
- shadingLanguage: "glsl",
61
- shadingLanguageVersion: 300
62
- };
63
-
64
- // dist/null-device/null-device-features.js
65
- var import_core = require("@luma.gl/core");
66
- var NullDeviceLimits = class extends import_core.DeviceLimits {
67
- maxTextureDimension1D = 0;
68
- maxTextureDimension2D = 2048;
69
- maxTextureDimension3D = 256;
70
- maxTextureArrayLayers = 256;
71
- maxBindGroups = 0;
72
- maxDynamicUniformBuffersPerPipelineLayout = 0;
73
- maxDynamicStorageBuffersPerPipelineLayout = 0;
74
- maxSampledTexturesPerShaderStage = 8;
75
- maxSamplersPerShaderStage = 16;
76
- maxStorageBuffersPerShaderStage = 0;
77
- maxStorageTexturesPerShaderStage = 0;
78
- maxUniformBuffersPerShaderStage = 20;
79
- maxUniformBufferBindingSize = 16384;
80
- maxStorageBufferBindingSize = 0;
81
- minUniformBufferOffsetAlignment = 0;
82
- minStorageBufferOffsetAlignment = 0;
83
- maxVertexBuffers = 16;
84
- maxVertexAttributes = 16;
85
- maxVertexBufferArrayStride = 2048;
86
- maxInterStageShaderComponents = 60;
87
- maxComputeWorkgroupStorageSize = 0;
88
- maxComputeInvocationsPerWorkgroup = 0;
89
- maxComputeWorkgroupSizeX = 0;
90
- maxComputeWorkgroupSizeY = 0;
91
- maxComputeWorkgroupSizeZ = 0;
92
- maxComputeWorkgroupsPerDimension = 0;
42
+ var DEFAULT_CANVAS_CONTEXT_PROPS = {
43
+ width: 1,
44
+ height: 1
93
45
  };
46
+ function createTestDevice() {
47
+ try {
48
+ return new import_webgl.WebGLDevice({ createCanvasContext: DEFAULT_CANVAS_CONTEXT_PROPS, debugWebGL: true });
49
+ } catch (error) {
50
+ console.error(`Failed to created device: ${error.message}`);
51
+ debugger;
52
+ return null;
53
+ }
54
+ }
55
+ var webglDevice = createTestDevice();
56
+ var webglDeviceAsync;
57
+ var webgpuDevice;
58
+ var devicesCreated = false;
59
+ async function getTestDevices(type) {
60
+ if (!devicesCreated) {
61
+ devicesCreated = true;
62
+ try {
63
+ webgpuDevice = await import_core.luma.createDevice({
64
+ id: "webgpu-test-device",
65
+ type: "webgpu",
66
+ adapters: [import_webgpu.webgpuAdapter],
67
+ createCanvasContext: DEFAULT_CANVAS_CONTEXT_PROPS
68
+ });
69
+ } catch (error) {
70
+ import_core.log.error(String(error))();
71
+ }
72
+ try {
73
+ webglDeviceAsync = await import_core.luma.createDevice({
74
+ id: "webgl-test-device",
75
+ type: "webgl",
76
+ adapters: [import_webgl.webgl2Adapter],
77
+ createCanvasContext: DEFAULT_CANVAS_CONTEXT_PROPS,
78
+ debugWebGL: true
79
+ });
80
+ } catch (error) {
81
+ import_core.log.error(String(error))();
82
+ }
83
+ }
84
+ return [webglDeviceAsync, webgpuDevice].filter(Boolean).filter((device) => !type || type === device.type);
85
+ }
94
86
 
95
- // dist/null-device/null-canvas-context.js
96
- var import_core3 = require("@luma.gl/core");
97
-
98
- // dist/null-device/resources/null-framebuffer.js
87
+ // dist/deprecated/classic-animation-loop.js
99
88
  var import_core2 = require("@luma.gl/core");
100
- var NullFramebuffer = class extends import_core2.Framebuffer {
89
+ var import_engine = require("@luma.gl/engine");
90
+ var import_env = require("@probe.gl/env");
91
+ var import_webgl2 = require("@luma.gl/webgl");
92
+ var isPage = (0, import_env.isBrowser)() && typeof document !== "undefined";
93
+ function getHTMLCanvasElement(canvas) {
94
+ return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement ? canvas : null;
95
+ }
96
+ var statIdCounter = 0;
97
+ var DEFAULT_CLASSIC_ANIMATION_LOOP_PROPS = {
98
+ onCreateDevice: (props) => import_core2.luma.createDevice(props),
99
+ onCreateContext: void 0,
100
+ onAddHTML: void 0,
101
+ onInitialize: () => ({}),
102
+ onRender: () => {
103
+ },
104
+ onFinalize: () => {
105
+ },
106
+ onError: (error) => console.error(error),
107
+ // eslint-disable-line no-console
108
+ device: null,
109
+ // debug: true,
110
+ // view parameters
111
+ useDevicePixels: true,
112
+ autoResizeViewport: true,
113
+ autoResizeDrawingBuffer: true,
114
+ stats: import_core2.luma.stats.get(`animation-loop-${statIdCounter++}`),
115
+ // deprecated
116
+ // onCreateContext: (opts) => createGLContext(opts),
117
+ gl: void 0,
118
+ glOptions: {},
119
+ createFramebuffer: false
120
+ };
121
+ var ClassicAnimationLoop = class {
101
122
  device;
102
- colorAttachments = [];
103
- depthStencilAttachment = null;
104
- constructor(device, props) {
105
- super(device, props);
106
- this.device = device;
123
+ canvas;
124
+ props;
125
+ animationProps;
126
+ // framebuffer: ClassicFramebuffer = null;
127
+ timeline = null;
128
+ stats;
129
+ cpuTime;
130
+ gpuTime;
131
+ frameRate;
132
+ display;
133
+ needsRedraw = "initialized";
134
+ _initialized = false;
135
+ _running = false;
136
+ _animationFrameId = null;
137
+ _pageLoadPromise = null;
138
+ _nextFramePromise = null;
139
+ _resolveNextFrame = null;
140
+ _cpuStartTime = 0;
141
+ // _gpuTimeQuery: Query | null = null;
142
+ /** @deprecated */
143
+ gl;
144
+ /*
145
+ */
146
+ constructor(props = {}) {
147
+ this.props = { ...DEFAULT_CLASSIC_ANIMATION_LOOP_PROPS, ...props };
148
+ props = this.props;
149
+ let { useDevicePixels = true } = this.props;
150
+ if ("useDevicePixelRatio" in props) {
151
+ import_core2.log.deprecated("useDevicePixelRatio", "useDevicePixels")();
152
+ useDevicePixels = props.useDevicePixelRatio;
153
+ }
154
+ this.device = props.device;
155
+ this.gl = this.device && this.device.gl || props.gl;
156
+ this.stats = props.stats;
157
+ this.cpuTime = this.stats.get("CPU Time");
158
+ this.gpuTime = this.stats.get("GPU Time");
159
+ this.frameRate = this.stats.get("Frame Rate");
160
+ this.setProps({
161
+ autoResizeViewport: props.autoResizeViewport,
162
+ autoResizeDrawingBuffer: props.autoResizeDrawingBuffer,
163
+ useDevicePixels
164
+ });
165
+ this.start = this.start.bind(this);
166
+ this.stop = this.stop.bind(this);
167
+ this._onMousemove = this._onMousemove.bind(this);
168
+ this._onMouseleave = this._onMouseleave.bind(this);
107
169
  }
108
- updateAttachments() {
170
+ destroy() {
171
+ this.stop();
172
+ this._setDisplay(null);
109
173
  }
110
- };
111
-
112
- // dist/null-device/null-canvas-context.js
113
- var NullCanvasContext = class extends import_core3.CanvasContext {
114
- device;
115
- handle = null;
116
- presentationSize;
117
- _framebuffer = null;
118
- get [Symbol.toStringTag]() {
119
- return "NullCanvasContext";
174
+ /** @deprecated Use .destroy() */
175
+ delete() {
176
+ this.destroy();
120
177
  }
121
- constructor(device, props) {
122
- super(props);
123
- this.device = device;
124
- this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
125
- this.updateSize([this.drawingBufferWidth, this.drawingBufferHeight]);
178
+ setNeedsRedraw(reason) {
179
+ this.needsRedraw = this.needsRedraw || reason;
180
+ return this;
126
181
  }
127
- getCurrentFramebuffer() {
128
- this._framebuffer = this._framebuffer || new NullFramebuffer(this.device, { handle: null });
129
- return this._framebuffer;
182
+ setProps(props) {
183
+ if ("autoResizeViewport" in props) {
184
+ this.props.autoResizeViewport = props.autoResizeViewport;
185
+ }
186
+ if ("autoResizeDrawingBuffer" in props) {
187
+ this.props.autoResizeDrawingBuffer = props.autoResizeDrawingBuffer;
188
+ }
189
+ if ("useDevicePixels" in props) {
190
+ this.props.useDevicePixels = props.useDevicePixels;
191
+ }
192
+ return this;
130
193
  }
131
- /** Resizes and updates render targets if necessary */
132
- updateSize(size) {
194
+ start(opts = {}) {
195
+ this._start(opts);
196
+ return this;
133
197
  }
134
- resize(options) {
135
- throw new Error("not implemented");
198
+ /** Starts a render loop if not already running */
199
+ async _start(props) {
200
+ if (this._running) {
201
+ return this;
202
+ }
203
+ this._running = true;
204
+ try {
205
+ await this._getPageLoadPromise();
206
+ if (!this._running) {
207
+ return null;
208
+ }
209
+ let appContext;
210
+ if (!this._initialized) {
211
+ this._initialized = true;
212
+ await this._createDevice(props);
213
+ this._initialize(props);
214
+ appContext = await this.onInitialize(this.animationProps);
215
+ this._addCallbackData(appContext || {});
216
+ }
217
+ if (!this._running) {
218
+ return null;
219
+ }
220
+ if (appContext !== false) {
221
+ this._cancelAnimationFrame();
222
+ this._requestAnimationFrame();
223
+ }
224
+ return this;
225
+ } catch (error) {
226
+ this.props.onError(error);
227
+ return null;
228
+ }
136
229
  }
137
- commit() {
230
+ /** Explicitly draw a frame */
231
+ redraw() {
232
+ if (this.isContextLost()) {
233
+ return this;
234
+ }
235
+ this._beginTimers();
236
+ this._setupFrame();
237
+ this._updateCallbackData();
238
+ this._renderFrame(this.animationProps);
239
+ this._clearNeedsRedraw();
240
+ if (this._resolveNextFrame) {
241
+ this._resolveNextFrame(this);
242
+ this._nextFramePromise = null;
243
+ this._resolveNextFrame = null;
244
+ }
245
+ this._endTimers();
246
+ return this;
138
247
  }
139
- };
140
-
141
- // dist/null-device/resources/null-buffer.js
142
- var import_core4 = require("@luma.gl/core");
143
- var NullBuffer = class extends import_core4.Buffer {
144
- device;
145
- byteLength;
146
- constructor(device, props = {}) {
147
- super(device, props);
148
- this.device = device;
149
- const byteOffset = props.byteOffset || 0;
150
- const byteLength = props.byteLength ?? (props.data ? props.data.byteLength + byteOffset : 0);
151
- this.byteLength = byteLength;
152
- this.trackAllocatedMemory(byteLength);
248
+ // Stops a render loop if already running, finalizing
249
+ stop() {
250
+ if (this._running) {
251
+ this._finalizeCallbackData();
252
+ this._cancelAnimationFrame();
253
+ this._nextFramePromise = null;
254
+ this._resolveNextFrame = null;
255
+ this._running = false;
256
+ }
257
+ return this;
153
258
  }
154
- destroy() {
155
- if (!this.destroyed) {
156
- super.destroy();
157
- this.trackDeallocatedMemory();
259
+ attachTimeline(timeline) {
260
+ this.timeline = timeline;
261
+ return this.timeline;
262
+ }
263
+ detachTimeline() {
264
+ this.timeline = null;
265
+ }
266
+ waitForRender() {
267
+ this.setNeedsRedraw("waitForRender");
268
+ if (!this._nextFramePromise) {
269
+ this._nextFramePromise = new Promise((resolve) => {
270
+ this._resolveNextFrame = resolve;
271
+ });
158
272
  }
273
+ return this._nextFramePromise;
159
274
  }
160
- async readAsync(byteOffset = 0, byteLength) {
161
- byteLength = byteLength ?? this.byteLength - byteOffset;
162
- return new Uint8Array(byteLength);
275
+ async toDataURL() {
276
+ var _a;
277
+ this.setNeedsRedraw("toDataURL");
278
+ await this.waitForRender();
279
+ return (_a = getHTMLCanvasElement(this.gl.canvas)) == null ? void 0 : _a.toDataURL();
163
280
  }
164
- write(data, byteOffset = 0) {
281
+ isContextLost() {
282
+ return this.gl.isContextLost();
165
283
  }
166
- };
167
-
168
- // dist/null-device/resources/null-shader.js
169
- var import_core5 = require("@luma.gl/core");
170
- var NullShader = class extends import_core5.Shader {
171
- device;
172
- constructor(device, props) {
173
- super(device, props);
174
- this.device = device;
284
+ onCreateDevice(deviceProps) {
285
+ const { onCreateDevice } = this.props;
286
+ return onCreateDevice(deviceProps);
175
287
  }
176
- get asyncCompilationStatus() {
177
- return this.getCompilationInfo().then(() => "success");
288
+ onInitialize(animationProps) {
289
+ const { onInitialize } = this.props;
290
+ return onInitialize(animationProps);
178
291
  }
179
- async getCompilationInfo() {
180
- return [];
292
+ onRender(animationProps) {
293
+ const { onRender } = this.props;
294
+ return onRender(animationProps);
181
295
  }
182
- };
183
-
184
- // dist/null-device/resources/null-command-buffer.js
185
- var import_core6 = require("@luma.gl/core");
186
- var NullCommandEncoder = class extends import_core6.CommandEncoder {
187
- device;
188
- constructor(device, props) {
189
- super(device, props);
190
- this.device = device;
296
+ onFinalize(animationProps) {
297
+ const { onFinalize } = this.props;
298
+ return onFinalize(animationProps);
299
+ }
300
+ // DEPRECATED/REMOVED METHODS
301
+ /** @deprecated Use .onCreateDevice() */
302
+ onCreateContext(props) {
303
+ const { onCreateContext } = this.props;
304
+ return onCreateContext(props);
305
+ }
306
+ /** @deprecated */
307
+ getHTMLControlValue(id, defaultValue = 1) {
308
+ const element = document.getElementById(id);
309
+ return element ? Number(element.value) : defaultValue;
191
310
  }
192
- finish() {
311
+ // PRIVATE METHODS
312
+ _initialize(props) {
313
+ this._createFramebuffer();
314
+ this._startEventHandling();
315
+ this._initializeCallbackData();
316
+ this._updateCallbackData();
317
+ this._resizeCanvasDrawingBuffer();
318
+ this._resizeViewport();
193
319
  }
194
- copyBufferToBuffer(options) {
320
+ _getPageLoadPromise() {
321
+ if (!this._pageLoadPromise) {
322
+ this._pageLoadPromise = isPage ? new Promise((resolve, reject) => {
323
+ if (isPage && document.readyState === "complete") {
324
+ resolve(document);
325
+ return;
326
+ }
327
+ window.addEventListener("load", () => {
328
+ resolve(document);
329
+ });
330
+ }) : Promise.resolve({});
331
+ }
332
+ return this._pageLoadPromise;
195
333
  }
196
- copyBufferToTexture(options) {
334
+ _setDisplay(display) {
335
+ if (this.display) {
336
+ this.display.destroy();
337
+ this.display.animationLoop = null;
338
+ }
339
+ if (display) {
340
+ display.animationLoop = this;
341
+ }
342
+ this.display = display;
197
343
  }
198
- copyTextureToBuffer(options) {
344
+ _requestAnimationFrame() {
345
+ if (!this._running) {
346
+ return;
347
+ }
348
+ this._animationFrameId = (0, import_engine.requestAnimationFramePolyfill)(this._animationFrame.bind(this));
199
349
  }
200
- copyTextureToTexture(options) {
350
+ _cancelAnimationFrame() {
351
+ if (this._animationFrameId !== null) {
352
+ return;
353
+ }
354
+ (0, import_engine.cancelAnimationFramePolyfill)(this._animationFrameId);
355
+ this._animationFrameId = null;
201
356
  }
202
- pushDebugGroup(groupLabel) {
357
+ _animationFrame() {
358
+ if (!this._running) {
359
+ return;
360
+ }
361
+ this.redraw();
362
+ this._requestAnimationFrame();
203
363
  }
204
- popDebugGroup() {
364
+ // Called on each frame, can be overridden to call onRender multiple times
365
+ // to support e.g. stereoscopic rendering
366
+ _renderFrame(props) {
367
+ if (this.display) {
368
+ this.display._renderFrame(props);
369
+ return;
370
+ }
371
+ this.onRender(props);
205
372
  }
206
- insertDebugMarker(markerLabel) {
373
+ _clearNeedsRedraw() {
374
+ this.needsRedraw = null;
207
375
  }
208
- resolveQuerySet(querySet) {
376
+ _setupFrame() {
377
+ this._resizeCanvasDrawingBuffer();
378
+ this._resizeViewport();
379
+ this._resizeFramebuffer();
209
380
  }
210
- };
211
-
212
- // dist/null-device/resources/null-sampler.js
213
- var import_core7 = require("@luma.gl/core");
214
- var NullSampler = class extends import_core7.Sampler {
215
- device;
216
- constructor(device, props) {
217
- super(device, props);
218
- this.device = device;
381
+ /* eslint-disable @typescript-eslint/unbound-method */
382
+ // Initialize the object that will be passed to app callbacks
383
+ _initializeCallbackData() {
384
+ this.animationProps = {
385
+ device: this.device,
386
+ gl: this.gl,
387
+ stop: this.stop,
388
+ canvas: this.gl.canvas,
389
+ // Initial values
390
+ useDevicePixels: this.props.useDevicePixels,
391
+ needsRedraw: null,
392
+ // Animation props
393
+ startTime: Date.now(),
394
+ engineTime: 0,
395
+ tick: 0,
396
+ tock: 0,
397
+ timeline: this.timeline,
398
+ // @ts-ignore
399
+ animationLoop: this,
400
+ // Timeline time for back compatibility
401
+ time: 0,
402
+ // Experimental
403
+ _mousePosition: null,
404
+ // Event props
405
+ /** @deprecated */
406
+ // framebuffer: this.framebuffer,
407
+ /** @deprecated */
408
+ _timeline: this.timeline,
409
+ /** @deprecated */
410
+ _loop: this,
411
+ /** @deprecated */
412
+ _animationLoop: this
413
+ };
219
414
  }
220
- };
221
-
222
- // dist/null-device/resources/null-texture.js
223
- var import_core9 = require("@luma.gl/core");
224
-
225
- // dist/null-device/resources/null-texture-view.js
226
- var import_core8 = require("@luma.gl/core");
227
- var NullTextureView = class extends import_core8.TextureView {
228
- device;
229
- texture;
230
- constructor(device, props) {
231
- super(device, { ...import_core8.Texture.defaultProps, ...props });
232
- this.device = device;
233
- this.texture = props.texture;
415
+ // Update the context object that will be passed to app callbacks
416
+ _updateCallbackData() {
417
+ const { width, height, aspect } = this._getSizeAndAspect();
418
+ if (width !== this.animationProps.width || height !== this.animationProps.height) {
419
+ this.setNeedsRedraw("drawing buffer resized");
420
+ }
421
+ if (aspect !== this.animationProps.aspect) {
422
+ this.setNeedsRedraw("drawing buffer aspect changed");
423
+ }
424
+ this.animationProps.width = width;
425
+ this.animationProps.height = height;
426
+ this.animationProps.aspect = aspect;
427
+ this.animationProps.needsRedraw = this.needsRedraw;
428
+ this.animationProps.engineTime = Date.now() - this.animationProps.startTime;
429
+ if (this.timeline) {
430
+ this.timeline.update(this.animationProps.engineTime);
431
+ }
432
+ this.animationProps.tick = Math.floor(this.animationProps.time / 1e3 * 60);
433
+ this.animationProps.tock++;
434
+ this.animationProps.time = this.timeline ? this.timeline.getTime() : this.animationProps.engineTime;
234
435
  }
235
- };
236
-
237
- // dist/null-device/resources/null-texture.js
238
- var NullTexture = class extends import_core9.Texture {
239
- device;
240
- sampler;
241
- view;
242
- constructor(device, props) {
243
- super(device, props);
244
- const propsWithData = { ...this.props };
245
- propsWithData.data = props.data;
246
- this.device = device;
247
- this.initialize(propsWithData);
248
- Object.seal(this);
436
+ _finalizeCallbackData() {
437
+ this.onFinalize(this.animationProps);
249
438
  }
250
- destroy() {
251
- if (!this.destroyed) {
252
- super.destroy();
253
- this.trackDeallocatedMemory("Texture");
439
+ /** Add application's data to the app context object */
440
+ _addCallbackData(appContext) {
441
+ if (typeof appContext === "object" && appContext !== null) {
442
+ this.animationProps = Object.assign({}, this.animationProps, appContext);
254
443
  }
255
444
  }
256
- createView(props) {
257
- return new NullTextureView(this.device, { ...props, texture: this });
445
+ /** Either uses supplied or existing context, or calls provided callback to create one */
446
+ async _createDevice(props) {
447
+ const deviceProps = { ...this.props, ...props, ...this.props.glOptions };
448
+ this.device = await this.onCreateDevice(deviceProps);
449
+ this.gl = this.device.gl;
450
+ (0, import_webgl2.resetGLParameters)(this.gl);
451
+ this._createInfoDiv();
258
452
  }
259
- setTexture1DData(data) {
260
- throw new Error("not implemented");
453
+ _createInfoDiv() {
454
+ const canvas = getHTMLCanvasElement(this.gl.canvas);
455
+ if (canvas && this.props.onAddHTML) {
456
+ const wrapperDiv = document.createElement("div");
457
+ document.body.appendChild(wrapperDiv);
458
+ wrapperDiv.style.position = "relative";
459
+ const div = document.createElement("div");
460
+ div.style.position = "absolute";
461
+ div.style.left = "10px";
462
+ div.style.bottom = "10px";
463
+ div.style.width = "300px";
464
+ div.style.background = "white";
465
+ if (canvas) {
466
+ wrapperDiv.appendChild(canvas);
467
+ }
468
+ wrapperDiv.appendChild(div);
469
+ const html = this.props.onAddHTML(div);
470
+ if (html) {
471
+ div.innerHTML = html;
472
+ }
473
+ }
261
474
  }
262
- setTexture2DData(lodData, depth, target) {
263
- throw new Error("not implemented");
475
+ _getSizeAndAspect() {
476
+ const width = this.gl.drawingBufferWidth;
477
+ const height = this.gl.drawingBufferHeight;
478
+ let aspect = 1;
479
+ const canvas = getHTMLCanvasElement(this.gl.canvas);
480
+ if (canvas && canvas.clientHeight) {
481
+ aspect = canvas.clientWidth / canvas.clientHeight;
482
+ } else if (width > 0 && height > 0) {
483
+ aspect = width / height;
484
+ }
485
+ return { width, height, aspect };
264
486
  }
265
- setTexture3DData(lodData, depth, target) {
266
- throw new Error("not implemented");
487
+ /** Default viewport setup */
488
+ _resizeViewport() {
489
+ if (this.props.autoResizeViewport) {
490
+ this.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight);
491
+ }
267
492
  }
268
- setTextureCubeData(data, depth) {
269
- throw new Error("not implemented");
493
+ /**
494
+ * Resize the render buffer of the canvas to match canvas client size
495
+ * Optionally multiplying with devicePixel ratio
496
+ */
497
+ _resizeCanvasDrawingBuffer() {
498
+ if (this.props.autoResizeDrawingBuffer) {
499
+ this.device.canvasContext.resize({ useDevicePixels: this.props.useDevicePixels });
500
+ }
270
501
  }
271
- setTextureArrayData(data) {
272
- throw new Error("not implemented");
502
+ _beginTimers() {
503
+ this.frameRate.timeEnd();
504
+ this.frameRate.timeStart();
505
+ this.cpuTime.timeStart();
273
506
  }
274
- setTextureCubeArrayData(data) {
275
- throw new Error("not implemented");
507
+ _endTimers() {
508
+ this.cpuTime.timeEnd();
276
509
  }
277
- initialize(props = {}) {
278
- this.setSampler(props.sampler);
279
- this.view = new NullTextureView(this.device, {
280
- ...props,
281
- texture: this,
282
- mipLevelCount: 1,
283
- arrayLayerCount: 1
284
- });
285
- return this;
510
+ // Event handling
511
+ _startEventHandling() {
512
+ const { canvas } = this.gl;
513
+ if (canvas) {
514
+ canvas.addEventListener("mousemove", this._onMousemove);
515
+ canvas.addEventListener("mouseleave", this._onMouseleave);
516
+ }
286
517
  }
287
- setSampler(sampler = {}) {
288
- if (sampler instanceof NullSampler) {
289
- this.sampler = sampler;
290
- } else {
291
- this.sampler = new NullSampler(this.device, sampler);
518
+ _onMousemove(e) {
519
+ this.animationProps._mousePosition = [e.offsetX, e.offsetY];
520
+ }
521
+ _onMouseleave(e) {
522
+ this.animationProps._mousePosition = null;
523
+ }
524
+ // Deprecated
525
+ /** @deprecated */
526
+ _createFramebuffer() {
527
+ if (this.props.createFramebuffer) {
292
528
  }
293
- return this;
294
529
  }
295
- copyExternalImage(options) {
296
- this.trackDeallocatedMemory("Texture");
297
- const { image: data } = options;
298
- const bytesPerPixel = 4;
299
- this.trackAllocatedMemory(this.width * this.height * bytesPerPixel, "Texture");
300
- const width = options.width ?? data.width;
301
- const height = options.height ?? data.height;
302
- this.width = width;
303
- this.height = height;
304
- return { width, height };
530
+ /** @deprecated */
531
+ _resizeFramebuffer() {
305
532
  }
306
533
  };
307
534
 
308
- // dist/null-device/resources/null-render-pass.js
309
- var import_core10 = require("@luma.gl/core");
310
- var NullRenderPass = class extends import_core10.RenderPass {
311
- device;
312
- constructor(device, props) {
313
- super(device, props);
314
- this.device = device;
535
+ // dist/test-runner.js
536
+ var DEFAULT_TEST_CASE = {
537
+ name: "Unnamed test",
538
+ onInitialize: async () => {
539
+ },
540
+ onRender: ({ done }) => done(),
541
+ onFinalize: () => {
315
542
  }
316
- end() {
543
+ };
544
+ var DEFAULT_TEST_PROPS = {
545
+ width: void 0,
546
+ height: void 0,
547
+ // test lifecycle callback
548
+ onTestStart: (testCase) => console.log(`# ${testCase.name}`),
549
+ onTestPass: (testCase, result) => console.log(`ok ${testCase.name} passed`),
550
+ onTestFail: (testCase, error) => console.log(`not ok ${testCase.name} failed`),
551
+ // milliseconds to wait for each test case before aborting
552
+ timeout: 2e3,
553
+ maxFramesToRender: void 0,
554
+ imageDiffOptions: void 0
555
+ };
556
+ var TestRunner = class {
557
+ device = webglDevice;
558
+ props;
559
+ isRunning = false;
560
+ testOptions = { ...DEFAULT_TEST_PROPS };
561
+ _animationProps;
562
+ _animationLoop;
563
+ _testCases = [];
564
+ _testCaseData = null;
565
+ _currentTestCase;
566
+ _currentTestCaseStartTime;
567
+ _currentTestCaseStartTick;
568
+ // should be defined in snapshot-test-runner
569
+ isDiffing = false;
570
+ // @ts-expect-error
571
+ isHeadless = Boolean(window.browserTestDriver_isHeadless);
572
+ /**
573
+ * props
574
+ * AnimationLoop props
575
+ */
576
+ constructor(props = {}) {
577
+ this.props = props;
317
578
  }
318
- pushDebugGroup(groupLabel) {
579
+ /**
580
+ * Add testCase(s)
581
+ */
582
+ add(testCases) {
583
+ if (!Array.isArray(testCases)) {
584
+ testCases = [testCases];
585
+ }
586
+ for (const testCase of testCases) {
587
+ this._testCases.push(testCase);
588
+ }
589
+ return this;
319
590
  }
320
- popDebugGroup() {
591
+ /**
592
+ * Returns a promise that resolves when all the test cases are done
593
+ */
594
+ run(options = {}) {
595
+ this.testOptions = { ...this.testOptions, ...options };
596
+ return new Promise((resolve, reject) => {
597
+ this._animationLoop = new ClassicAnimationLoop({
598
+ ...this.props,
599
+ device: this.device,
600
+ onRender: this._onRender.bind(this),
601
+ onFinalize: () => {
602
+ this.isRunning = false;
603
+ resolve();
604
+ }
605
+ });
606
+ this._animationLoop.start(this.props);
607
+ this.isRunning = true;
608
+ this.isDiffing = false;
609
+ this._currentTestCase = null;
610
+ }).catch((error) => {
611
+ this._fail({ error: error.message });
612
+ });
321
613
  }
322
- insertDebugMarker(markerLabel) {
614
+ /* Lifecycle methods for subclassing */
615
+ initTestCase(testCase) {
616
+ const { animationLoop } = testCase;
617
+ if (animationLoop) {
618
+ testCase.onInitialize = animationLoop.props.onInitialize.bind(animationLoop);
619
+ testCase.onRender = animationLoop.props.onRender.bind(animationLoop);
620
+ testCase.onFinalize = animationLoop.props.onFinalize.bind(animationLoop);
621
+ }
622
+ for (const key in DEFAULT_TEST_CASE) {
623
+ testCase[key] = testCase[key] || DEFAULT_TEST_CASE[key];
624
+ }
323
625
  }
324
- setParameters(parameters = {}) {
626
+ shouldRender(animationProps) {
627
+ return true;
325
628
  }
326
- beginOcclusionQuery(queryIndex) {
629
+ assert(testCase) {
630
+ this._pass(testCase);
631
+ this._next();
327
632
  }
328
- endOcclusionQuery() {
633
+ /* Utilities */
634
+ _pass(result) {
635
+ this.testOptions.onTestPass(this._currentTestCase, result);
329
636
  }
330
- };
331
-
332
- // dist/null-device/resources/null-render-pipeline.js
333
- var import_core11 = require("@luma.gl/core");
334
- var NullRenderPipeline = class extends import_core11.RenderPipeline {
335
- device;
336
- vs;
337
- fs;
338
- uniforms = {};
339
- bindings = {};
340
- constructor(device, props) {
341
- super(device, props);
342
- this.device = device;
343
- this.vs = props.vs;
344
- this.fs = props.fs;
345
- this.shaderLayout = props.shaderLayout || {
346
- attributes: [],
347
- bindings: [],
348
- uniforms: []
349
- };
637
+ _fail(result) {
638
+ this.testOptions.onTestFail(this._currentTestCase, result);
350
639
  }
351
- setBindings(bindings) {
352
- Object.assign(this.bindings, bindings);
640
+ _next() {
641
+ this._nextTestCase();
353
642
  }
354
- setUniformsWebGL(uniforms) {
355
- Object.assign(this.uniforms, uniforms);
643
+ /* Private methods */
644
+ _onRender(animationProps) {
645
+ this._animationProps = animationProps;
646
+ const testCase = this._currentTestCase || this._nextTestCase();
647
+ if (!testCase) {
648
+ this._animationLoop.stop();
649
+ return;
650
+ }
651
+ let isDone = false;
652
+ const testCaseAnimationProps = {
653
+ ...animationProps,
654
+ ...this._testCaseData,
655
+ // tick/time starts from 0 for each test case
656
+ startTime: this._currentTestCaseStartTime,
657
+ time: animationProps.time - this._currentTestCaseStartTime,
658
+ tick: animationProps.tick - this._currentTestCaseStartTick,
659
+ // called by the test case when it is done rendering and ready for capture and diff
660
+ done: () => {
661
+ isDone = true;
662
+ }
663
+ };
664
+ if (this._testCaseData && this.shouldRender(testCaseAnimationProps)) {
665
+ testCase.onRender(testCaseAnimationProps);
666
+ }
667
+ const timeout = testCase.timeout || this.testOptions.timeout;
668
+ if (timeout && testCaseAnimationProps.time > timeout) {
669
+ isDone = true;
670
+ }
671
+ if (isDone) {
672
+ this.assert(testCase);
673
+ }
356
674
  }
357
- draw(options) {
358
- const { renderPass, vertexArray } = options;
359
- vertexArray.bindBeforeRender(renderPass);
360
- vertexArray.unbindAfterRender(renderPass);
361
- return true;
675
+ _nextTestCase() {
676
+ const animationProps = this._animationProps;
677
+ if (this._testCaseData) {
678
+ for (const key in this._testCaseData) {
679
+ const value = this._testCaseData[key];
680
+ if (value && value.delete) {
681
+ value.destroy();
682
+ }
683
+ }
684
+ this._currentTestCase.onFinalize(Object.assign({}, animationProps, this._testCaseData));
685
+ this.device.popState();
686
+ this._currentTestCase = null;
687
+ this._testCaseData = null;
688
+ }
689
+ const testCase = this._testCases.shift();
690
+ if (testCase) {
691
+ this._currentTestCase = testCase;
692
+ this._currentTestCaseStartTime = animationProps.time;
693
+ this._currentTestCaseStartTick = animationProps.tick;
694
+ this.initTestCase(testCase);
695
+ this.device.pushState();
696
+ const initProps = {
697
+ ...animationProps,
698
+ // tick/time starts from 0 for each test case
699
+ startTime: animationProps.time,
700
+ time: 0,
701
+ tick: 0
702
+ };
703
+ Promise.resolve(testCase.onInitialize(initProps)).then((userData) => {
704
+ this._testCaseData = userData || {};
705
+ });
706
+ this.testOptions.onTestStart(testCase);
707
+ }
708
+ return testCase;
362
709
  }
363
710
  };
364
711
 
365
- // dist/null-device/resources/null-vertex-array.js
366
- var import_core12 = require("@luma.gl/core");
367
- var NullVertexArray = class extends import_core12.VertexArray {
368
- device;
369
- // Create a VertexArray
370
- constructor(device, props) {
371
- super(device, props);
372
- this.device = device;
373
- }
374
- setIndexBuffer(indexBuffer) {
375
- this.indexBuffer = indexBuffer;
712
+ // dist/utils/get-bounding-box.js
713
+ function getBoundingBoxInPage(domElement) {
714
+ const bbox = domElement.getBoundingClientRect();
715
+ return {
716
+ x: window.scrollX + bbox.x,
717
+ y: window.scrollY + bbox.y,
718
+ width: bbox.width,
719
+ height: bbox.height
720
+ };
721
+ }
722
+
723
+ // dist/snapshot-test-runner.js
724
+ var SnapshotTestRunner = class extends TestRunner {
725
+ // should be defined here but hack access in TestRunner
726
+ // private isDiffing: boolean = false;
727
+ constructor(props) {
728
+ super(props);
729
+ this.testOptions.imageDiffOptions = {};
376
730
  }
377
- /** Set a location in vertex attributes array to a buffer, enables the location, sets divisor */
378
- setBuffer(location, attributeBuffer) {
379
- const attributeInfo = this.attributeInfos[location];
380
- if (!attributeInfo) {
381
- throw new Error(`Unknown attribute location ${location}`);
731
+ initTestCase(testCase) {
732
+ super.initTestCase(testCase);
733
+ if (!testCase.goldenImage) {
734
+ throw new Error(`Test case ${testCase.name} does not have golden image`);
382
735
  }
383
- this.attributes[location] = attributeBuffer;
384
- }
385
- bindBeforeRender() {
386
736
  }
387
- unbindAfterRender() {
737
+ shouldRender() {
738
+ return !this.isDiffing;
388
739
  }
389
- setConstantWebGL(location, value) {
740
+ async assert(testCase) {
741
+ var _a;
742
+ if (this.isDiffing) {
743
+ return;
744
+ }
745
+ this.isDiffing = true;
746
+ const canvas = (_a = this._animationProps) == null ? void 0 : _a.canvas;
747
+ if (!(canvas instanceof HTMLCanvasElement)) {
748
+ throw new Error("canvas");
749
+ }
750
+ const diffOptions = {
751
+ ...this.testOptions.imageDiffOptions,
752
+ ...testCase.imageDiffOptions,
753
+ goldenImage: testCase.goldenImage,
754
+ region: getBoundingBoxInPage(canvas)
755
+ };
756
+ const result = await globalThis.browserTestDriver_captureAndDiffScreen(diffOptions);
757
+ if (result.success) {
758
+ this._pass(result);
759
+ } else {
760
+ this._fail(result);
761
+ }
762
+ this.isDiffing = false;
763
+ this._next();
390
764
  }
391
765
  };
392
766
 
393
- // dist/null-device/resources/null-transform-feedback.js
394
- var import_core13 = require("@luma.gl/core");
395
- var NullTransformFeedback = class extends import_core13.TransformFeedback {
396
- device;
397
- layout;
398
- buffers = {};
399
- constructor(device, props) {
400
- super(device, props);
401
- this.device = device;
402
- this.layout = this.props.layout;
403
- if (props.buffers) {
404
- this.setBuffers(props.buffers);
405
- }
406
- Object.seal(this);
407
- }
408
- begin(topology = "point-list") {
767
+ // dist/performance-test-runner.js
768
+ var import_stats = require("@probe.gl/stats");
769
+ var PerformanceTestRunner = class extends TestRunner {
770
+ _stats = null;
771
+ _fps = null;
772
+ constructor(props) {
773
+ super(props);
774
+ Object.assign(this.testOptions, {
775
+ maxFramesToRender: 60,
776
+ targetFPS: 50
777
+ });
409
778
  }
410
- end() {
779
+ initTestCase(testCase) {
780
+ super.initTestCase(testCase);
781
+ this._stats = new import_stats.Stats({ id: testCase.name });
782
+ this._fps = this._stats.get("fps");
411
783
  }
412
- setBuffers(buffers) {
413
- this.buffers = {};
414
- for (const bufferName in buffers) {
415
- this.setBuffer(bufferName, buffers[bufferName]);
784
+ shouldRender(animationProps) {
785
+ var _a, _b;
786
+ (_a = this._fps) == null ? void 0 : _a.timeEnd();
787
+ (_b = this._fps) == null ? void 0 : _b.timeStart();
788
+ if (this._fps.count > this.testOptions.maxFramesToRender) {
789
+ animationProps.done();
416
790
  }
791
+ return true;
417
792
  }
418
- setBuffer(locationOrName, bufferOrRange) {
419
- this.buffers[locationOrName] = bufferOrRange;
420
- }
421
- getBuffer(locationOrName) {
422
- return this.buffers[locationOrName] || null;
793
+ assert(testCase) {
794
+ var _a, _b;
795
+ const targetFPS = testCase.targetFPS || this.testOptions.targetFPS;
796
+ const count = (_a = this._fps) == null ? void 0 : _a.count;
797
+ const fps = ((_b = this._fps) == null ? void 0 : _b.getHz()) || 0;
798
+ if (fps >= targetFPS) {
799
+ this._pass({ fps, framesRendered: count });
800
+ } else {
801
+ this._fail({ fps, framesRendered: count });
802
+ }
803
+ this._next();
423
804
  }
424
805
  };
425
806
 
426
- // dist/null-device/resources/null-query-set.js
427
- var import_core14 = require("@luma.gl/core");
428
- var NullQuerySet = class extends import_core14.QuerySet {
807
+ // dist/null-device/null-adapter.js
808
+ var import_core18 = require("@luma.gl/core");
809
+
810
+ // dist/null-device/null-device.js
811
+ var import_core17 = require("@luma.gl/core");
812
+
813
+ // dist/null-device/null-device-info.js
814
+ var NullDeviceInfo = {
815
+ type: "unknown",
816
+ gpu: "software",
817
+ gpuType: "unknown",
818
+ gpuBackend: "unknown",
819
+ vendor: "no one",
820
+ renderer: "none",
821
+ version: "1.0",
822
+ shadingLanguage: "glsl",
823
+ shadingLanguageVersion: 300
824
+ };
825
+
826
+ // dist/null-device/null-device-features.js
827
+ var import_core3 = require("@luma.gl/core");
828
+ var NullDeviceLimits = class extends import_core3.DeviceLimits {
829
+ maxTextureDimension1D = 0;
830
+ maxTextureDimension2D = 2048;
831
+ maxTextureDimension3D = 256;
832
+ maxTextureArrayLayers = 256;
833
+ maxBindGroups = 0;
834
+ maxDynamicUniformBuffersPerPipelineLayout = 0;
835
+ maxDynamicStorageBuffersPerPipelineLayout = 0;
836
+ maxSampledTexturesPerShaderStage = 8;
837
+ maxSamplersPerShaderStage = 16;
838
+ maxStorageBuffersPerShaderStage = 0;
839
+ maxStorageTexturesPerShaderStage = 0;
840
+ maxUniformBuffersPerShaderStage = 20;
841
+ maxUniformBufferBindingSize = 16384;
842
+ maxStorageBufferBindingSize = 0;
843
+ minUniformBufferOffsetAlignment = 0;
844
+ minStorageBufferOffsetAlignment = 0;
845
+ maxVertexBuffers = 16;
846
+ maxVertexAttributes = 16;
847
+ maxVertexBufferArrayStride = 2048;
848
+ maxInterStageShaderComponents = 60;
849
+ maxComputeWorkgroupStorageSize = 0;
850
+ maxComputeInvocationsPerWorkgroup = 0;
851
+ maxComputeWorkgroupSizeX = 0;
852
+ maxComputeWorkgroupSizeY = 0;
853
+ maxComputeWorkgroupSizeZ = 0;
854
+ maxComputeWorkgroupsPerDimension = 0;
855
+ };
856
+
857
+ // dist/null-device/null-canvas-context.js
858
+ var import_core5 = require("@luma.gl/core");
859
+
860
+ // dist/null-device/resources/null-framebuffer.js
861
+ var import_core4 = require("@luma.gl/core");
862
+ var NullFramebuffer = class extends import_core4.Framebuffer {
429
863
  device;
864
+ colorAttachments = [];
865
+ depthStencilAttachment = null;
430
866
  constructor(device, props) {
431
867
  super(device, props);
432
868
  this.device = device;
433
869
  }
434
- };
435
-
436
- // dist/null-device/null-device.js
437
- var NullDevice = class extends import_core15.Device {
438
- static isSupported() {
439
- return true;
440
- }
441
- type = "unknown";
442
- handle = null;
443
- preferredColorFormat = "rgba8unorm";
444
- preferredDepthFormat = "depth24plus";
445
- features = new import_core15.DeviceFeatures([], this.props._disabledFeatures);
446
- limits = new NullDeviceLimits();
447
- info = NullDeviceInfo;
448
- canvasContext;
449
- lost;
450
- constructor(props) {
451
- super({ ...props, id: props.id || "null-device" });
452
- const canvasContextProps = props.createCanvasContext === true ? {} : props.createCanvasContext;
453
- this.canvasContext = new NullCanvasContext(this, canvasContextProps);
454
- this.lost = new Promise((resolve) => {
455
- });
456
- }
457
- /**
458
- * Destroys the context
459
- * @note Has no effect for null contexts
460
- */
461
- destroy() {
462
- }
463
- get isLost() {
464
- return false;
465
- }
466
- // IMPLEMENTATION OF ABSTRACT DEVICE
467
- createCanvasContext(props) {
468
- return new NullCanvasContext(this, props);
469
- }
470
- createBuffer(props) {
471
- const newProps = this._normalizeBufferProps(props);
472
- return new NullBuffer(this, newProps);
473
- }
474
- getDefaultRenderPass() {
475
- return new NullRenderPass(this, {});
476
- }
477
- createTexture(props) {
478
- return new NullTexture(this, props);
479
- }
480
- createExternalTexture(props) {
481
- throw new Error("createExternalTexture() not implemented");
482
- }
483
- createSampler(props) {
484
- return new NullSampler(this, props);
485
- }
486
- createShader(props) {
487
- return new NullShader(this, props);
488
- }
489
- createFramebuffer(props) {
490
- return new NullFramebuffer(this, props);
491
- }
492
- createVertexArray(props) {
493
- return new NullVertexArray(this, props);
494
- }
495
- createTransformFeedback(props) {
496
- return new NullTransformFeedback(this, props);
497
- }
498
- createQuerySet(props) {
499
- return new NullQuerySet(this, props);
500
- }
501
- createRenderPipeline(props) {
502
- return new NullRenderPipeline(this, props);
503
- }
504
- beginRenderPass(props) {
505
- return new NullRenderPass(this, props);
506
- }
507
- createComputePipeline(props) {
508
- throw new Error("ComputePipeline not supported in WebGL");
509
- }
510
- beginComputePass(props) {
511
- throw new Error("ComputePass not supported in WebGL");
512
- }
513
- createCommandEncoder(props = {}) {
514
- return new NullCommandEncoder(this, props);
515
- }
516
- submit() {
517
- }
518
- setParametersWebGL(parameters) {
519
- }
520
- getParametersWebGL(parameters) {
521
- }
522
- withParametersWebGL(parameters, func) {
523
- const { nocatch = true } = parameters;
524
- let value;
525
- if (nocatch) {
526
- return func();
527
- }
528
- try {
529
- value = func();
530
- } catch {
531
- }
532
- return value;
533
- }
534
- _getDeviceSpecificTextureFormatCapabilities(format) {
535
- return format;
870
+ updateAttachments() {
536
871
  }
537
872
  };
538
873
 
539
- // dist/null-device/null-adapter.js
540
- var NullAdapter = class extends import_core16.Adapter {
541
- /** type of device's created by this adapter */
542
- type = "unknown";
543
- constructor() {
544
- super();
545
- NullDevice.adapter = this;
874
+ // dist/null-device/null-canvas-context.js
875
+ var NullCanvasContext = class extends import_core5.CanvasContext {
876
+ device;
877
+ format = "rgba8unorm";
878
+ depthStencilFormat = "depth24plus";
879
+ presentationSize;
880
+ _framebuffer = null;
881
+ get [Symbol.toStringTag]() {
882
+ return "NullCanvasContext";
546
883
  }
547
- /** Check if WebGPU is available */
548
- isSupported() {
549
- return true;
884
+ constructor(device, props) {
885
+ super(props);
886
+ this.device = device;
887
+ this.presentationSize = [-1, -1];
888
+ this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
889
+ this.update();
550
890
  }
551
- async attach(handle) {
552
- return new NullDevice({});
891
+ getCurrentFramebuffer() {
892
+ this.update();
893
+ this._framebuffer = this._framebuffer || new NullFramebuffer(this.device, { handle: null });
894
+ return this._framebuffer;
553
895
  }
554
- async create(props = {}) {
555
- return new NullDevice(props);
896
+ /** Resizes and updates render targets if necessary */
897
+ update() {
898
+ const size = this.getPixelSize();
899
+ const sizeChanged = size[0] !== this.presentationSize[0] || size[1] !== this.presentationSize[1];
900
+ if (sizeChanged) {
901
+ this.presentationSize = size;
902
+ this.resize();
903
+ }
556
904
  }
557
- };
558
- var nullAdapter = new NullAdapter();
559
-
560
- // dist/create-test-device.js
561
- var DEFAULT_CANVAS_CONTEXT_PROPS = {
562
- width: 1,
563
- height: 1
564
- };
565
- var withResolvers = () => {
566
- let resolve;
567
- let reject;
568
- const promise = new Promise((_resolve, _reject) => {
569
- resolve = _resolve;
570
- reject = _reject;
571
- });
572
- return { promise, resolve, reject };
573
- };
574
- var nullDevicePromise = makeNullTestDevice();
575
- var webglDevicePromise = makeWebGLTestDevice();
576
- var webgpuDevicePromise = makeWebGPUTestDevice();
577
- async function getTestDevices(types = ["webgl", "webgpu"]) {
578
- return [await getNullTestDevice(), await getWebGLTestDevice(), await getWebGPUTestDevice()].filter(Boolean).filter((device) => types.includes(device.type));
579
- }
580
- function getWebGPUTestDevice() {
581
- return webgpuDevicePromise;
582
- }
583
- async function getWebGLTestDevice() {
584
- return webglDevicePromise;
585
- }
586
- async function getNullTestDevice() {
587
- return nullDevicePromise;
588
- }
589
- async function makeWebGPUTestDevice() {
590
- const webgpuDeviceResolvers = withResolvers();
591
- try {
592
- const webgpuDevice = await import_core17.luma.createDevice({
593
- id: "webgpu-test-device",
594
- type: "webgpu",
595
- adapters: [import_webgpu.webgpuAdapter],
596
- createCanvasContext: DEFAULT_CANVAS_CONTEXT_PROPS,
597
- debug: true
598
- });
599
- webgpuDeviceResolvers.resolve(webgpuDevice);
600
- } catch (error) {
601
- import_core17.log.error(String(error))();
602
- webgpuDeviceResolvers.resolve(null);
905
+ resize(options) {
906
+ if (this.canvas) {
907
+ const devicePixelRatio = this.getDevicePixelRatio(options == null ? void 0 : options.useDevicePixels);
908
+ this.setDevicePixelRatio(devicePixelRatio, options);
909
+ return;
910
+ }
603
911
  }
604
- return webgpuDeviceResolvers.promise;
605
- }
606
- async function makeWebGLTestDevice() {
607
- const webglDeviceResolvers = withResolvers();
608
- try {
609
- const webglDevice3 = await import_core17.luma.createDevice({
610
- id: "webgl-test-device",
611
- type: "webgl",
612
- adapters: [import_webgl.webgl2Adapter],
613
- createCanvasContext: DEFAULT_CANVAS_CONTEXT_PROPS,
614
- debug: true,
615
- debugWebGL: true
616
- });
617
- webglDeviceResolvers.resolve(webglDevice3);
618
- } catch (error) {
619
- import_core17.log.error(String(error))();
620
- webglDeviceResolvers.resolve(null);
912
+ getDrawingBufferSize() {
913
+ return [this.width, this.height];
621
914
  }
622
- return webglDeviceResolvers.promise;
623
- }
624
- async function makeNullTestDevice() {
625
- const nullDeviceResolvers = withResolvers();
626
- try {
627
- const nullDevice = await import_core17.luma.createDevice({
628
- id: "null-test-device",
629
- type: "unknown",
630
- adapters: [nullAdapter],
631
- createCanvasContext: DEFAULT_CANVAS_CONTEXT_PROPS,
632
- debug: true,
633
- debugWebGL: true
634
- });
635
- nullDeviceResolvers.resolve(nullDevice);
636
- } catch (error) {
637
- import_core17.log.error(String(error))();
638
- nullDevicePromise = Promise.resolve(null);
915
+ commit() {
639
916
  }
640
- return nullDeviceResolvers.promise;
641
- }
642
-
643
- // dist/deprecated/classic-animation-loop.js
644
- var import_core18 = require("@luma.gl/core");
645
- var import_engine = require("@luma.gl/engine");
646
- var import_env = require("@probe.gl/env");
647
- var import_webgl2 = require("@luma.gl/webgl");
648
- var isPage = (0, import_env.isBrowser)() && typeof document !== "undefined";
649
- function getHTMLCanvasElement(canvas) {
650
- return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement ? canvas : null;
651
- }
652
- var statIdCounter = 0;
653
- var DEFAULT_CLASSIC_ANIMATION_LOOP_PROPS = {
654
- onCreateDevice: (props) => import_core18.luma.createDevice({ ...props, debug: true }),
655
- onCreateContext: void 0,
656
- onAddHTML: void 0,
657
- onInitialize: () => ({}),
658
- onRender: () => {
659
- },
660
- onFinalize: () => {
661
- },
662
- onError: (error) => console.error(error),
663
- // eslint-disable-line no-console
664
- device: null,
665
- // debug: true,
666
- // view parameters
667
- useDevicePixels: true,
668
- autoResizeViewport: true,
669
- autoResizeDrawingBuffer: true,
670
- stats: import_core18.luma.stats.get(`animation-loop-${statIdCounter++}`),
671
- // deprecated
672
- // onCreateContext: (opts) => createGLContext(opts),
673
- gl: void 0,
674
- glOptions: {},
675
- createFramebuffer: false
676
917
  };
677
- var ClassicAnimationLoop = class {
918
+
919
+ // dist/null-device/resources/null-buffer.js
920
+ var import_core6 = require("@luma.gl/core");
921
+ var NullBuffer = class extends import_core6.Buffer {
678
922
  device;
679
- canvas;
680
- props;
681
- animationProps;
682
- // framebuffer: ClassicFramebuffer = null;
683
- timeline = null;
684
- stats;
685
- cpuTime;
686
- gpuTime;
687
- frameRate;
688
- display;
689
- needsRedraw = "initialized";
690
- _initialized = false;
691
- _running = false;
692
- _animationFrameId = null;
693
- _pageLoadPromise = null;
694
- _nextFramePromise = null;
695
- _resolveNextFrame = null;
696
- _cpuStartTime = 0;
697
- // _gpuTimeQuery: Query | null = null;
698
- /** @deprecated */
699
- gl;
700
- /*
701
- */
702
- constructor(props = {}) {
703
- this.props = { ...DEFAULT_CLASSIC_ANIMATION_LOOP_PROPS, ...props };
704
- props = this.props;
705
- let { useDevicePixels = true } = this.props;
706
- if ("useDevicePixelRatio" in props) {
707
- import_core18.log.deprecated("useDevicePixelRatio", "useDevicePixels")();
708
- useDevicePixels = props.useDevicePixelRatio;
709
- }
710
- this.device = props.device;
711
- this.gl = this.device && this.device.gl || props.gl;
712
- this.stats = props.stats;
713
- this.cpuTime = this.stats.get("CPU Time");
714
- this.gpuTime = this.stats.get("GPU Time");
715
- this.frameRate = this.stats.get("Frame Rate");
716
- this.setProps({
717
- autoResizeViewport: props.autoResizeViewport,
718
- autoResizeDrawingBuffer: props.autoResizeDrawingBuffer,
719
- useDevicePixels
720
- });
721
- this.start = this.start.bind(this);
722
- this.stop = this.stop.bind(this);
723
- this._onMousemove = this._onMousemove.bind(this);
724
- this._onMouseleave = this._onMouseleave.bind(this);
923
+ byteLength;
924
+ constructor(device, props = {}) {
925
+ super(device, props);
926
+ this.device = device;
927
+ const byteOffset = props.byteOffset || 0;
928
+ const byteLength = props.byteLength ?? (props.data ? props.data.byteLength + byteOffset : 0);
929
+ this.byteLength = byteLength;
930
+ this.trackAllocatedMemory(byteLength);
725
931
  }
726
932
  destroy() {
727
- this.stop();
728
- this._setDisplay(null);
729
- }
730
- /** @deprecated Use .destroy() */
731
- delete() {
732
- this.destroy();
933
+ if (!this.destroyed) {
934
+ super.destroy();
935
+ this.trackDeallocatedMemory();
936
+ }
733
937
  }
734
- setNeedsRedraw(reason) {
735
- this.needsRedraw = this.needsRedraw || reason;
736
- return this;
938
+ async readAsync(byteOffset = 0, byteLength) {
939
+ byteLength = byteLength ?? this.byteLength - byteOffset;
940
+ return new Uint8Array(byteLength);
737
941
  }
738
- setProps(props) {
739
- if ("autoResizeViewport" in props) {
740
- this.props.autoResizeViewport = props.autoResizeViewport;
741
- }
742
- if ("autoResizeDrawingBuffer" in props) {
743
- this.props.autoResizeDrawingBuffer = props.autoResizeDrawingBuffer;
744
- }
745
- if ("useDevicePixels" in props) {
746
- this.props.useDevicePixels = props.useDevicePixels;
747
- }
748
- return this;
942
+ write(data, byteOffset = 0) {
749
943
  }
750
- start(opts = {}) {
751
- this._start(opts);
752
- return this;
944
+ };
945
+
946
+ // dist/null-device/resources/null-shader.js
947
+ var import_core7 = require("@luma.gl/core");
948
+ var NullShader = class extends import_core7.Shader {
949
+ device;
950
+ constructor(device, props) {
951
+ super(device, props);
952
+ this.device = device;
753
953
  }
754
- /** Starts a render loop if not already running */
755
- async _start(props) {
756
- if (this._running) {
757
- return this;
758
- }
759
- this._running = true;
760
- try {
761
- await this._getPageLoadPromise();
762
- if (!this._running) {
763
- return null;
764
- }
765
- let appContext;
766
- if (!this._initialized) {
767
- this._initialized = true;
768
- await this._createDevice(props);
769
- this._initialize(props);
770
- appContext = await this.onInitialize(this.animationProps);
771
- this._addCallbackData(appContext || {});
772
- }
773
- if (!this._running) {
774
- return null;
775
- }
776
- if (appContext !== false) {
777
- this._cancelAnimationFrame();
778
- this._requestAnimationFrame();
779
- }
780
- return this;
781
- } catch (error) {
782
- this.props.onError(error);
783
- return null;
784
- }
954
+ get asyncCompilationStatus() {
955
+ return this.getCompilationInfo().then(() => "success");
785
956
  }
786
- /** Explicitly draw a frame */
787
- redraw() {
788
- if (this.isContextLost()) {
789
- return this;
790
- }
791
- this._beginTimers();
792
- this._setupFrame();
793
- this._updateCallbackData();
794
- this._renderFrame(this.animationProps);
795
- this._clearNeedsRedraw();
796
- if (this._resolveNextFrame) {
797
- this._resolveNextFrame(this);
798
- this._nextFramePromise = null;
799
- this._resolveNextFrame = null;
800
- }
801
- this._endTimers();
802
- return this;
957
+ async getCompilationInfo() {
958
+ return [];
803
959
  }
804
- // Stops a render loop if already running, finalizing
805
- stop() {
806
- if (this._running) {
807
- this._finalizeCallbackData();
808
- this._cancelAnimationFrame();
809
- this._nextFramePromise = null;
810
- this._resolveNextFrame = null;
811
- this._running = false;
812
- }
813
- return this;
960
+ };
961
+
962
+ // dist/null-device/resources/null-command-buffer.js
963
+ var import_core8 = require("@luma.gl/core");
964
+ var NullCommandEncoder = class extends import_core8.CommandEncoder {
965
+ device;
966
+ constructor(device, props) {
967
+ super(device, props);
968
+ this.device = device;
814
969
  }
815
- attachTimeline(timeline) {
816
- this.timeline = timeline;
817
- return this.timeline;
970
+ finish() {
818
971
  }
819
- detachTimeline() {
820
- this.timeline = null;
972
+ copyBufferToBuffer(options) {
821
973
  }
822
- waitForRender() {
823
- this.setNeedsRedraw("waitForRender");
824
- if (!this._nextFramePromise) {
825
- this._nextFramePromise = new Promise((resolve) => {
826
- this._resolveNextFrame = resolve;
827
- });
828
- }
829
- return this._nextFramePromise;
974
+ copyBufferToTexture(options) {
830
975
  }
831
- async toDataURL() {
832
- var _a;
833
- this.setNeedsRedraw("toDataURL");
834
- await this.waitForRender();
835
- return (_a = getHTMLCanvasElement(this.gl.canvas)) == null ? void 0 : _a.toDataURL();
976
+ copyTextureToBuffer(options) {
836
977
  }
837
- isContextLost() {
838
- return this.gl.isContextLost();
978
+ copyTextureToTexture(options) {
839
979
  }
840
- onCreateDevice(deviceProps) {
841
- const { onCreateDevice } = this.props;
842
- return onCreateDevice(deviceProps);
980
+ pushDebugGroup(groupLabel) {
843
981
  }
844
- onInitialize(animationProps) {
845
- const { onInitialize } = this.props;
846
- return onInitialize(animationProps);
982
+ popDebugGroup() {
847
983
  }
848
- onRender(animationProps) {
849
- const { onRender } = this.props;
850
- return onRender(animationProps);
984
+ insertDebugMarker(markerLabel) {
851
985
  }
852
- onFinalize(animationProps) {
853
- const { onFinalize } = this.props;
854
- return onFinalize(animationProps);
986
+ resolveQuerySet(querySet) {
855
987
  }
856
- // DEPRECATED/REMOVED METHODS
857
- /** @deprecated Use .onCreateDevice() */
858
- onCreateContext(props) {
859
- const { onCreateContext } = this.props;
860
- return onCreateContext(props);
988
+ };
989
+
990
+ // dist/null-device/resources/null-sampler.js
991
+ var import_core9 = require("@luma.gl/core");
992
+ var NullSampler = class extends import_core9.Sampler {
993
+ device;
994
+ constructor(device, props) {
995
+ super(device, props);
996
+ this.device = device;
861
997
  }
862
- /** @deprecated */
863
- getHTMLControlValue(id, defaultValue = 1) {
864
- const element = document.getElementById(id);
865
- return element ? Number(element.value) : defaultValue;
998
+ };
999
+
1000
+ // dist/null-device/resources/null-texture.js
1001
+ var import_core11 = require("@luma.gl/core");
1002
+
1003
+ // dist/null-device/resources/null-texture-view.js
1004
+ var import_core10 = require("@luma.gl/core");
1005
+ var NullTextureView = class extends import_core10.TextureView {
1006
+ device;
1007
+ texture;
1008
+ constructor(device, props) {
1009
+ super(device, { ...import_core10.Texture.defaultProps, ...props });
1010
+ this.device = device;
1011
+ this.texture = props.texture;
866
1012
  }
867
- // PRIVATE METHODS
868
- _initialize(props) {
869
- this._createFramebuffer();
870
- this._startEventHandling();
871
- this._initializeCallbackData();
872
- this._updateCallbackData();
873
- this._resizeCanvasDrawingBuffer();
874
- this._resizeViewport();
1013
+ };
1014
+
1015
+ // dist/null-device/resources/null-texture.js
1016
+ var NullTexture = class extends import_core11.Texture {
1017
+ device;
1018
+ sampler;
1019
+ view;
1020
+ constructor(device, props) {
1021
+ super(device, props);
1022
+ const propsWithData = { ...this.props };
1023
+ propsWithData.data = props.data;
1024
+ this.device = device;
1025
+ this.initialize(propsWithData);
1026
+ Object.seal(this);
875
1027
  }
876
- _getPageLoadPromise() {
877
- if (!this._pageLoadPromise) {
878
- this._pageLoadPromise = isPage ? new Promise((resolve, reject) => {
879
- if (isPage && document.readyState === "complete") {
880
- resolve(document);
881
- return;
882
- }
883
- window.addEventListener("load", () => {
884
- resolve(document);
885
- });
886
- }) : Promise.resolve({});
1028
+ destroy() {
1029
+ if (!this.destroyed) {
1030
+ super.destroy();
1031
+ this.trackDeallocatedMemory("Texture");
887
1032
  }
888
- return this._pageLoadPromise;
889
1033
  }
890
- _setDisplay(display) {
891
- if (this.display) {
892
- this.display.destroy();
893
- this.display.animationLoop = null;
894
- }
895
- if (display) {
896
- display.animationLoop = this;
897
- }
898
- this.display = display;
1034
+ createView(props) {
1035
+ return new NullTextureView(this.device, { ...props, texture: this });
899
1036
  }
900
- _requestAnimationFrame() {
901
- if (!this._running) {
902
- return;
903
- }
904
- this._animationFrameId = (0, import_engine.requestAnimationFramePolyfill)(this._animationFrame.bind(this));
1037
+ setTexture1DData(data) {
1038
+ throw new Error("not implemented");
905
1039
  }
906
- _cancelAnimationFrame() {
907
- if (this._animationFrameId !== null) {
908
- return;
909
- }
910
- (0, import_engine.cancelAnimationFramePolyfill)(this._animationFrameId);
911
- this._animationFrameId = null;
1040
+ setTexture2DData(lodData, depth, target) {
1041
+ throw new Error("not implemented");
912
1042
  }
913
- _animationFrame() {
914
- if (!this._running) {
915
- return;
916
- }
917
- this.redraw();
918
- this._requestAnimationFrame();
1043
+ setTexture3DData(lodData, depth, target) {
1044
+ throw new Error("not implemented");
919
1045
  }
920
- // Called on each frame, can be overridden to call onRender multiple times
921
- // to support e.g. stereoscopic rendering
922
- _renderFrame(props) {
923
- if (this.display) {
924
- this.display._renderFrame(props);
925
- return;
1046
+ setTextureCubeData(data, depth) {
1047
+ throw new Error("not implemented");
1048
+ }
1049
+ setTextureArrayData(data) {
1050
+ throw new Error("not implemented");
1051
+ }
1052
+ setTextureCubeArrayData(data) {
1053
+ throw new Error("not implemented");
1054
+ }
1055
+ initialize(props = {}) {
1056
+ this.setSampler(props.sampler);
1057
+ this.view = new NullTextureView(this.device, {
1058
+ ...props,
1059
+ texture: this,
1060
+ mipLevelCount: 1,
1061
+ arrayLayerCount: 1
1062
+ });
1063
+ return this;
1064
+ }
1065
+ setSampler(sampler = {}) {
1066
+ if (sampler instanceof NullSampler) {
1067
+ this.sampler = sampler;
1068
+ } else {
1069
+ this.sampler = new NullSampler(this.device, sampler);
926
1070
  }
927
- this.onRender(props);
1071
+ return this;
928
1072
  }
929
- _clearNeedsRedraw() {
930
- this.needsRedraw = null;
1073
+ copyExternalImage(options) {
1074
+ this.trackDeallocatedMemory("Texture");
1075
+ const { image: data } = options;
1076
+ const bytesPerPixel = 4;
1077
+ this.trackAllocatedMemory(this.width * this.height * bytesPerPixel, "Texture");
1078
+ const width = options.width ?? data.width;
1079
+ const height = options.height ?? data.height;
1080
+ this.width = width;
1081
+ this.height = height;
1082
+ return { width, height };
931
1083
  }
932
- _setupFrame() {
933
- this._resizeCanvasDrawingBuffer();
934
- this._resizeViewport();
935
- this._resizeFramebuffer();
1084
+ };
1085
+
1086
+ // dist/null-device/resources/null-render-pass.js
1087
+ var import_core12 = require("@luma.gl/core");
1088
+ var NullRenderPass = class extends import_core12.RenderPass {
1089
+ device;
1090
+ constructor(device, props) {
1091
+ super(device, props);
1092
+ this.device = device;
936
1093
  }
937
- /* eslint-disable @typescript-eslint/unbound-method */
938
- // Initialize the object that will be passed to app callbacks
939
- _initializeCallbackData() {
940
- this.animationProps = {
941
- device: this.device,
942
- gl: this.gl,
943
- stop: this.stop,
944
- canvas: this.gl.canvas,
945
- // Initial values
946
- useDevicePixels: this.props.useDevicePixels,
947
- needsRedraw: null,
948
- // Animation props
949
- startTime: Date.now(),
950
- engineTime: 0,
951
- tick: 0,
952
- tock: 0,
953
- timeline: this.timeline,
954
- // @ts-ignore
955
- animationLoop: this,
956
- // Timeline time for back compatibility
957
- time: 0,
958
- // Experimental
959
- _mousePosition: null,
960
- // Event props
961
- /** @deprecated */
962
- // framebuffer: this.framebuffer,
963
- /** @deprecated */
964
- _timeline: this.timeline,
965
- /** @deprecated */
966
- _loop: this,
967
- /** @deprecated */
968
- _animationLoop: this
1094
+ end() {
1095
+ }
1096
+ pushDebugGroup(groupLabel) {
1097
+ }
1098
+ popDebugGroup() {
1099
+ }
1100
+ insertDebugMarker(markerLabel) {
1101
+ }
1102
+ setParameters(parameters = {}) {
1103
+ }
1104
+ beginOcclusionQuery(queryIndex) {
1105
+ }
1106
+ endOcclusionQuery() {
1107
+ }
1108
+ };
1109
+
1110
+ // dist/null-device/resources/null-render-pipeline.js
1111
+ var import_core13 = require("@luma.gl/core");
1112
+ var NullRenderPipeline = class extends import_core13.RenderPipeline {
1113
+ device;
1114
+ vs;
1115
+ fs;
1116
+ uniforms = {};
1117
+ bindings = {};
1118
+ constructor(device, props) {
1119
+ super(device, props);
1120
+ this.device = device;
1121
+ this.vs = props.vs;
1122
+ this.fs = props.fs;
1123
+ this.shaderLayout = props.shaderLayout || {
1124
+ attributes: [],
1125
+ bindings: [],
1126
+ uniforms: []
969
1127
  };
970
1128
  }
971
- // Update the context object that will be passed to app callbacks
972
- _updateCallbackData() {
973
- const { width, height, aspect } = this._getSizeAndAspect();
974
- if (width !== this.animationProps.width || height !== this.animationProps.height) {
975
- this.setNeedsRedraw("drawing buffer resized");
976
- }
977
- if (aspect !== this.animationProps.aspect) {
978
- this.setNeedsRedraw("drawing buffer aspect changed");
979
- }
980
- this.animationProps.width = width;
981
- this.animationProps.height = height;
982
- this.animationProps.aspect = aspect;
983
- this.animationProps.needsRedraw = this.needsRedraw;
984
- this.animationProps.engineTime = Date.now() - this.animationProps.startTime;
985
- if (this.timeline) {
986
- this.timeline.update(this.animationProps.engineTime);
987
- }
988
- this.animationProps.tick = Math.floor(this.animationProps.time / 1e3 * 60);
989
- this.animationProps.tock++;
990
- this.animationProps.time = this.timeline ? this.timeline.getTime() : this.animationProps.engineTime;
991
- }
992
- _finalizeCallbackData() {
993
- this.onFinalize(this.animationProps);
1129
+ setBindings(bindings) {
1130
+ Object.assign(this.bindings, bindings);
994
1131
  }
995
- /** Add application's data to the app context object */
996
- _addCallbackData(appContext) {
997
- if (typeof appContext === "object" && appContext !== null) {
998
- this.animationProps = Object.assign({}, this.animationProps, appContext);
999
- }
1132
+ setUniformsWebGL(uniforms) {
1133
+ Object.assign(this.uniforms, uniforms);
1000
1134
  }
1001
- /** Either uses supplied or existing context, or calls provided callback to create one */
1002
- async _createDevice(props) {
1003
- const deviceProps = { ...this.props, ...props, ...this.props.glOptions };
1004
- this.device = await this.onCreateDevice(deviceProps);
1005
- this.gl = this.device.gl;
1006
- (0, import_webgl2.resetGLParameters)(this.gl);
1007
- this._createInfoDiv();
1135
+ draw(options) {
1136
+ const { renderPass, vertexArray } = options;
1137
+ vertexArray.bindBeforeRender(renderPass);
1138
+ vertexArray.unbindAfterRender(renderPass);
1139
+ return true;
1008
1140
  }
1009
- _createInfoDiv() {
1010
- const canvas = getHTMLCanvasElement(this.gl.canvas);
1011
- if (canvas && this.props.onAddHTML) {
1012
- const wrapperDiv = document.createElement("div");
1013
- document.body.appendChild(wrapperDiv);
1014
- wrapperDiv.style.position = "relative";
1015
- const div = document.createElement("div");
1016
- div.style.position = "absolute";
1017
- div.style.left = "10px";
1018
- div.style.bottom = "10px";
1019
- div.style.width = "300px";
1020
- div.style.background = "white";
1021
- if (canvas) {
1022
- wrapperDiv.appendChild(canvas);
1023
- }
1024
- wrapperDiv.appendChild(div);
1025
- const html = this.props.onAddHTML(div);
1026
- if (html) {
1027
- div.innerHTML = html;
1028
- }
1029
- }
1141
+ };
1142
+
1143
+ // dist/null-device/resources/null-vertex-array.js
1144
+ var import_core14 = require("@luma.gl/core");
1145
+ var NullVertexArray = class extends import_core14.VertexArray {
1146
+ device;
1147
+ // Create a VertexArray
1148
+ constructor(device, props) {
1149
+ super(device, props);
1150
+ this.device = device;
1030
1151
  }
1031
- _getSizeAndAspect() {
1032
- const width = this.gl.drawingBufferWidth;
1033
- const height = this.gl.drawingBufferHeight;
1034
- let aspect = 1;
1035
- const canvas = getHTMLCanvasElement(this.gl.canvas);
1036
- if (canvas && canvas.clientHeight) {
1037
- aspect = canvas.clientWidth / canvas.clientHeight;
1038
- } else if (width > 0 && height > 0) {
1039
- aspect = width / height;
1040
- }
1041
- return { width, height, aspect };
1152
+ setIndexBuffer(indexBuffer) {
1153
+ this.indexBuffer = indexBuffer;
1042
1154
  }
1043
- /** Default viewport setup */
1044
- _resizeViewport() {
1045
- if (this.props.autoResizeViewport) {
1046
- this.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight);
1155
+ /** Set a location in vertex attributes array to a buffer, enables the location, sets divisor */
1156
+ setBuffer(location, attributeBuffer) {
1157
+ const attributeInfo = this.attributeInfos[location];
1158
+ if (!attributeInfo) {
1159
+ throw new Error(`Unknown attribute location ${location}`);
1047
1160
  }
1161
+ this.attributes[location] = attributeBuffer;
1048
1162
  }
1049
- /**
1050
- * Resize the render buffer of the canvas to match canvas client size
1051
- * Optionally multiplying with devicePixel ratio
1052
- */
1053
- _resizeCanvasDrawingBuffer() {
1054
- if (this.props.autoResizeDrawingBuffer) {
1055
- this.device.canvasContext.resize({ useDevicePixels: this.props.useDevicePixels });
1056
- }
1163
+ bindBeforeRender() {
1057
1164
  }
1058
- _beginTimers() {
1059
- this.frameRate.timeEnd();
1060
- this.frameRate.timeStart();
1061
- this.cpuTime.timeStart();
1165
+ unbindAfterRender() {
1062
1166
  }
1063
- _endTimers() {
1064
- this.cpuTime.timeEnd();
1167
+ setConstantWebGL(location, value) {
1065
1168
  }
1066
- // Event handling
1067
- _startEventHandling() {
1068
- const { canvas } = this.gl;
1069
- if (canvas) {
1070
- canvas.addEventListener("mousemove", this._onMousemove);
1071
- canvas.addEventListener("mouseleave", this._onMouseleave);
1169
+ };
1170
+
1171
+ // dist/null-device/resources/null-transform-feedback.js
1172
+ var import_core15 = require("@luma.gl/core");
1173
+ var NullTransformFeedback = class extends import_core15.TransformFeedback {
1174
+ device;
1175
+ layout;
1176
+ buffers = {};
1177
+ constructor(device, props) {
1178
+ super(device, props);
1179
+ this.device = device;
1180
+ this.layout = this.props.layout;
1181
+ if (props.buffers) {
1182
+ this.setBuffers(props.buffers);
1072
1183
  }
1184
+ Object.seal(this);
1073
1185
  }
1074
- _onMousemove(e) {
1075
- this.animationProps._mousePosition = [e.offsetX, e.offsetY];
1186
+ begin(topology = "point-list") {
1076
1187
  }
1077
- _onMouseleave(e) {
1078
- this.animationProps._mousePosition = null;
1188
+ end() {
1079
1189
  }
1080
- // Deprecated
1081
- /** @deprecated */
1082
- _createFramebuffer() {
1083
- if (this.props.createFramebuffer) {
1190
+ setBuffers(buffers) {
1191
+ this.buffers = {};
1192
+ for (const bufferName in buffers) {
1193
+ this.setBuffer(bufferName, buffers[bufferName]);
1084
1194
  }
1085
1195
  }
1086
- /** @deprecated */
1087
- _resizeFramebuffer() {
1196
+ setBuffer(locationOrName, bufferOrRange) {
1197
+ this.buffers[locationOrName] = bufferOrRange;
1198
+ }
1199
+ getBuffer(locationOrName) {
1200
+ return this.buffers[locationOrName] || null;
1088
1201
  }
1089
1202
  };
1090
1203
 
1091
- // dist/test-runner.js
1092
- var DEFAULT_TEST_CASE = {
1093
- name: "Unnamed test",
1094
- onInitialize: async () => {
1095
- },
1096
- onRender: ({ done }) => done(),
1097
- onFinalize: () => {
1204
+ // dist/null-device/resources/null-query-set.js
1205
+ var import_core16 = require("@luma.gl/core");
1206
+ var NullQuerySet = class extends import_core16.QuerySet {
1207
+ device;
1208
+ constructor(device, props) {
1209
+ super(device, props);
1210
+ this.device = device;
1098
1211
  }
1099
1212
  };
1100
- var DEFAULT_TEST_PROPS = {
1101
- width: void 0,
1102
- height: void 0,
1103
- // test lifecycle callback
1104
- onTestStart: (testCase) => console.log(`# ${testCase.name}`),
1105
- onTestPass: (testCase, result) => console.log(`ok ${testCase.name} passed`),
1106
- onTestFail: (testCase, error) => console.log(`not ok ${testCase.name} failed`),
1107
- // milliseconds to wait for each test case before aborting
1108
- timeout: 2e3,
1109
- maxFramesToRender: void 0,
1110
- imageDiffOptions: void 0
1111
- };
1112
- var TestRunner = class {
1113
- device = webglDevice;
1114
- props;
1115
- isRunning = false;
1116
- testOptions = { ...DEFAULT_TEST_PROPS };
1117
- _animationProps;
1118
- _animationLoop;
1119
- _testCases = [];
1120
- _testCaseData = null;
1121
- _currentTestCase;
1122
- _currentTestCaseStartTime;
1123
- _currentTestCaseStartTick;
1124
- // should be defined in snapshot-test-runner
1125
- isDiffing = false;
1126
- // @ts-expect-error
1127
- isHeadless = Boolean(window.browserTestDriver_isHeadless);
1128
- /**
1129
- * props
1130
- * AnimationLoop props
1131
- */
1132
- constructor(props = {}) {
1133
- this.props = props;
1213
+
1214
+ // dist/null-device/null-device.js
1215
+ var NullDevice = class extends import_core17.Device {
1216
+ static isSupported() {
1217
+ return true;
1218
+ }
1219
+ type = "unknown";
1220
+ features = new import_core17.DeviceFeatures([], this.props._disabledFeatures);
1221
+ limits = new NullDeviceLimits();
1222
+ info = NullDeviceInfo;
1223
+ canvasContext;
1224
+ lost;
1225
+ constructor(props) {
1226
+ super({ ...props, id: props.id || "null-device" });
1227
+ const canvasContextProps = props.createCanvasContext === true ? {} : props.createCanvasContext;
1228
+ this.canvasContext = new NullCanvasContext(this, canvasContextProps);
1229
+ this.lost = new Promise((resolve) => {
1230
+ });
1231
+ this.canvasContext.resize();
1134
1232
  }
1135
1233
  /**
1136
- * Add testCase(s)
1234
+ * Destroys the context
1235
+ * @note Has no effect for null contexts
1137
1236
  */
1138
- add(testCases) {
1139
- if (!Array.isArray(testCases)) {
1140
- testCases = [testCases];
1141
- }
1142
- for (const testCase of testCases) {
1143
- this._testCases.push(testCase);
1144
- }
1145
- return this;
1237
+ destroy() {
1238
+ }
1239
+ get isLost() {
1240
+ return false;
1241
+ }
1242
+ // IMPLEMENTATION OF ABSTRACT DEVICE
1243
+ createCanvasContext(props) {
1244
+ return new NullCanvasContext(this, props);
1245
+ }
1246
+ createBuffer(props) {
1247
+ const newProps = this._normalizeBufferProps(props);
1248
+ return new NullBuffer(this, newProps);
1249
+ }
1250
+ getDefaultRenderPass() {
1251
+ return new NullRenderPass(this, {});
1252
+ }
1253
+ createTexture(props) {
1254
+ return new NullTexture(this, props);
1255
+ }
1256
+ createExternalTexture(props) {
1257
+ throw new Error("createExternalTexture() not implemented");
1258
+ }
1259
+ createSampler(props) {
1260
+ return new NullSampler(this, props);
1146
1261
  }
1147
- /**
1148
- * Returns a promise that resolves when all the test cases are done
1149
- */
1150
- async run(options = {}) {
1151
- this.testOptions = { ...this.testOptions, ...options };
1152
- const device = await getWebGLTestDevice();
1153
- return new Promise((resolve, reject) => {
1154
- this._animationLoop = new ClassicAnimationLoop({
1155
- ...this.props,
1156
- device: this.device,
1157
- onRender: this._onRender.bind(this),
1158
- onFinalize: () => {
1159
- this.isRunning = false;
1160
- resolve();
1161
- }
1162
- });
1163
- this._animationLoop.start(this.props);
1164
- this.isRunning = true;
1165
- this.isDiffing = false;
1166
- this._currentTestCase = null;
1167
- }).catch((error) => {
1168
- this._fail({ error: error.message });
1169
- });
1262
+ createShader(props) {
1263
+ return new NullShader(this, props);
1170
1264
  }
1171
- /* Lifecycle methods for subclassing */
1172
- initTestCase(testCase) {
1173
- const { animationLoop } = testCase;
1174
- if (animationLoop) {
1175
- testCase.onInitialize = animationLoop.props.onInitialize.bind(animationLoop);
1176
- testCase.onRender = animationLoop.props.onRender.bind(animationLoop);
1177
- testCase.onFinalize = animationLoop.props.onFinalize.bind(animationLoop);
1178
- }
1179
- for (const key in DEFAULT_TEST_CASE) {
1180
- testCase[key] = testCase[key] || DEFAULT_TEST_CASE[key];
1181
- }
1265
+ createFramebuffer(props) {
1266
+ return new NullFramebuffer(this, props);
1182
1267
  }
1183
- shouldRender(animationProps) {
1184
- return true;
1268
+ createVertexArray(props) {
1269
+ return new NullVertexArray(this, props);
1185
1270
  }
1186
- assert(testCase) {
1187
- this._pass(testCase);
1188
- this._next();
1271
+ createTransformFeedback(props) {
1272
+ return new NullTransformFeedback(this, props);
1189
1273
  }
1190
- /* Utilities */
1191
- _pass(result) {
1192
- this.testOptions.onTestPass(this._currentTestCase, result);
1274
+ createQuerySet(props) {
1275
+ return new NullQuerySet(this, props);
1193
1276
  }
1194
- _fail(result) {
1195
- this.testOptions.onTestFail(this._currentTestCase, result);
1277
+ createRenderPipeline(props) {
1278
+ return new NullRenderPipeline(this, props);
1196
1279
  }
1197
- _next() {
1198
- this._nextTestCase();
1280
+ beginRenderPass(props) {
1281
+ return new NullRenderPass(this, props);
1199
1282
  }
1200
- /* Private methods */
1201
- _onRender(animationProps) {
1202
- this._animationProps = animationProps;
1203
- const testCase = this._currentTestCase || this._nextTestCase();
1204
- if (!testCase) {
1205
- this._animationLoop.stop();
1206
- return;
1207
- }
1208
- let isDone = false;
1209
- const testCaseAnimationProps = {
1210
- ...animationProps,
1211
- ...this._testCaseData,
1212
- // tick/time starts from 0 for each test case
1213
- startTime: this._currentTestCaseStartTime,
1214
- time: animationProps.time - this._currentTestCaseStartTime,
1215
- tick: animationProps.tick - this._currentTestCaseStartTick,
1216
- // called by the test case when it is done rendering and ready for capture and diff
1217
- done: () => {
1218
- isDone = true;
1219
- }
1220
- };
1221
- if (this._testCaseData && this.shouldRender(testCaseAnimationProps)) {
1222
- testCase.onRender(testCaseAnimationProps);
1223
- }
1224
- const timeout = testCase.timeout || this.testOptions.timeout;
1225
- if (timeout && testCaseAnimationProps.time > timeout) {
1226
- isDone = true;
1227
- }
1228
- if (isDone) {
1229
- this.assert(testCase);
1230
- }
1283
+ createComputePipeline(props) {
1284
+ throw new Error("ComputePipeline not supported in WebGL");
1231
1285
  }
1232
- _nextTestCase() {
1233
- const animationProps = this._animationProps;
1234
- if (this._testCaseData) {
1235
- for (const key in this._testCaseData) {
1236
- const value = this._testCaseData[key];
1237
- if (value && value.delete) {
1238
- value.destroy();
1239
- }
1240
- }
1241
- this._currentTestCase.onFinalize(Object.assign({}, animationProps, this._testCaseData));
1242
- this.device.popState();
1243
- this._currentTestCase = null;
1244
- this._testCaseData = null;
1245
- }
1246
- const testCase = this._testCases.shift();
1247
- if (testCase) {
1248
- this._currentTestCase = testCase;
1249
- this._currentTestCaseStartTime = animationProps.time;
1250
- this._currentTestCaseStartTick = animationProps.tick;
1251
- this.initTestCase(testCase);
1252
- this.device.pushState();
1253
- const initProps = {
1254
- ...animationProps,
1255
- // tick/time starts from 0 for each test case
1256
- startTime: animationProps.time,
1257
- time: 0,
1258
- tick: 0
1259
- };
1260
- Promise.resolve(testCase.onInitialize(initProps)).then((userData) => {
1261
- this._testCaseData = userData || {};
1262
- });
1263
- this.testOptions.onTestStart(testCase);
1264
- }
1265
- return testCase;
1286
+ beginComputePass(props) {
1287
+ throw new Error("ComputePass not supported in WebGL");
1266
1288
  }
1267
- };
1268
-
1269
- // dist/utils/get-bounding-box.js
1270
- function getBoundingBoxInPage(domElement) {
1271
- const bbox = domElement.getBoundingClientRect();
1272
- return {
1273
- x: window.scrollX + bbox.x,
1274
- y: window.scrollY + bbox.y,
1275
- width: bbox.width,
1276
- height: bbox.height
1277
- };
1278
- }
1279
-
1280
- // dist/snapshot-test-runner.js
1281
- var SnapshotTestRunner = class extends TestRunner {
1282
- // should be defined here but hack access in TestRunner
1283
- // private isDiffing: boolean = false;
1284
- constructor(props) {
1285
- super(props);
1286
- this.testOptions.imageDiffOptions = {};
1289
+ createCommandEncoder(props = {}) {
1290
+ return new NullCommandEncoder(this, props);
1287
1291
  }
1288
- initTestCase(testCase) {
1289
- super.initTestCase(testCase);
1290
- if (!testCase.goldenImage) {
1291
- throw new Error(`Test case ${testCase.name} does not have golden image`);
1292
- }
1292
+ submit() {
1293
1293
  }
1294
- shouldRender() {
1295
- return !this.isDiffing;
1294
+ setParametersWebGL(parameters) {
1296
1295
  }
1297
- async assert(testCase) {
1298
- var _a;
1299
- if (this.isDiffing) {
1300
- return;
1301
- }
1302
- this.isDiffing = true;
1303
- const canvas = (_a = this._animationProps) == null ? void 0 : _a.canvas;
1304
- if (!(canvas instanceof HTMLCanvasElement)) {
1305
- throw new Error("canvas");
1296
+ getParametersWebGL(parameters) {
1297
+ }
1298
+ withParametersWebGL(parameters, func) {
1299
+ const { nocatch = true } = parameters;
1300
+ let value;
1301
+ if (nocatch) {
1302
+ return func();
1306
1303
  }
1307
- const diffOptions = {
1308
- ...this.testOptions.imageDiffOptions,
1309
- ...testCase.imageDiffOptions,
1310
- goldenImage: testCase.goldenImage,
1311
- region: getBoundingBoxInPage(canvas)
1312
- };
1313
- const result = await globalThis.browserTestDriver_captureAndDiffScreen(diffOptions);
1314
- if (result.success) {
1315
- this._pass(result);
1316
- } else {
1317
- this._fail(result);
1304
+ try {
1305
+ value = func();
1306
+ } catch {
1318
1307
  }
1319
- this.isDiffing = false;
1320
- this._next();
1308
+ return value;
1309
+ }
1310
+ _getDeviceSpecificTextureFormatCapabilities(format) {
1311
+ return format;
1321
1312
  }
1322
1313
  };
1323
1314
 
1324
- // dist/performance-test-runner.js
1325
- var import_stats = require("@probe.gl/stats");
1326
- var PerformanceTestRunner = class extends TestRunner {
1327
- _stats = null;
1328
- _fps = null;
1329
- constructor(props) {
1330
- super(props);
1331
- Object.assign(this.testOptions, {
1332
- maxFramesToRender: 60,
1333
- targetFPS: 50
1334
- });
1335
- }
1336
- initTestCase(testCase) {
1337
- super.initTestCase(testCase);
1338
- this._stats = new import_stats.Stats({ id: testCase.name });
1339
- this._fps = this._stats.get("fps");
1315
+ // dist/null-device/null-adapter.js
1316
+ var NullAdapter = class extends import_core18.Adapter {
1317
+ /** type of device's created by this adapter */
1318
+ type = "unknown";
1319
+ constructor() {
1320
+ super();
1321
+ NullDevice.adapter = this;
1340
1322
  }
1341
- shouldRender(animationProps) {
1342
- var _a, _b;
1343
- (_a = this._fps) == null ? void 0 : _a.timeEnd();
1344
- (_b = this._fps) == null ? void 0 : _b.timeStart();
1345
- if (this._fps.count > this.testOptions.maxFramesToRender) {
1346
- animationProps.done();
1347
- }
1323
+ /** Check if WebGPU is available */
1324
+ isSupported() {
1348
1325
  return true;
1349
1326
  }
1350
- assert(testCase) {
1351
- var _a, _b;
1352
- const targetFPS = testCase.targetFPS || this.testOptions.targetFPS;
1353
- const count = (_a = this._fps) == null ? void 0 : _a.count;
1354
- const fps = ((_b = this._fps) == null ? void 0 : _b.getHz()) || 0;
1355
- if (fps >= targetFPS) {
1356
- this._pass({ fps, framesRendered: count });
1357
- } else {
1358
- this._fail({ fps, framesRendered: count });
1359
- }
1360
- this._next();
1327
+ async attach(handle) {
1328
+ return new NullDevice({});
1329
+ }
1330
+ async create(props = {}) {
1331
+ return new NullDevice(props);
1361
1332
  }
1362
1333
  };
1334
+ var nullAdapter = new NullAdapter();
1363
1335
 
1364
1336
  // dist/utils/check-type.js
1365
1337
  function checkType(value) {
@@ -1402,21 +1374,4 @@ function getLeakedResources(startCounts, endCounts) {
1402
1374
  }
1403
1375
  return leakedResources;
1404
1376
  }
1405
-
1406
- // dist/deprecated/sync-test-device.js
1407
- var import_webgl3 = require("@luma.gl/webgl");
1408
- var DEFAULT_CANVAS_CONTEXT_PROPS2 = {
1409
- width: 1,
1410
- height: 1
1411
- };
1412
- function createTestDevice() {
1413
- try {
1414
- return new import_webgl3.WebGLDevice({ createCanvasContext: DEFAULT_CANVAS_CONTEXT_PROPS2 });
1415
- } catch (error) {
1416
- console.error(`Failed to created device: ${error.message}`);
1417
- debugger;
1418
- return null;
1419
- }
1420
- }
1421
- var webglDevice2 = createTestDevice();
1422
1377
  //# sourceMappingURL=index.cjs.map