@luma.gl/test-utils 9.1.9 → 9.2.0-alpha.2

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