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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/adapter/converters/sampler-parameters.js +6 -4
  2. package/dist/adapter/converters/texture-formats.d.ts +49 -11
  3. package/dist/adapter/converters/texture-formats.d.ts.map +1 -1
  4. package/dist/adapter/converters/texture-formats.js +150 -160
  5. package/dist/adapter/helpers/format-utils.d.ts.map +1 -1
  6. package/dist/adapter/helpers/format-utils.js +6 -0
  7. package/dist/adapter/helpers/webgl-texture-utils.d.ts +10 -8
  8. package/dist/adapter/helpers/webgl-texture-utils.d.ts.map +1 -1
  9. package/dist/adapter/helpers/webgl-texture-utils.js +46 -32
  10. package/dist/adapter/resources/webgl-command-buffer.d.ts +59 -2
  11. package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
  12. package/dist/adapter/resources/webgl-command-buffer.js +72 -16
  13. package/dist/adapter/resources/webgl-command-encoder.d.ts.map +1 -1
  14. package/dist/adapter/resources/webgl-command-encoder.js +3 -0
  15. package/dist/adapter/resources/webgl-external-texture.js +14 -0
  16. package/dist/adapter/resources/webgl-framebuffer.d.ts.map +1 -1
  17. package/dist/adapter/resources/webgl-framebuffer.js +1 -2
  18. package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
  19. package/dist/adapter/resources/webgl-render-pass.js +38 -20
  20. package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
  21. package/dist/adapter/resources/webgl-render-pipeline.js +6 -5
  22. package/dist/adapter/resources/webgl-shader.js +1 -1
  23. package/dist/adapter/resources/webgl-texture.d.ts +8 -14
  24. package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
  25. package/dist/adapter/resources/webgl-texture.js +119 -208
  26. package/dist/adapter/webgl-adapter.js +1 -1
  27. package/dist/adapter/webgl-device.d.ts +7 -1
  28. package/dist/adapter/webgl-device.d.ts.map +1 -1
  29. package/dist/adapter/webgl-device.js +22 -10
  30. package/dist/context/debug/webgl-developer-tools.d.ts +1 -0
  31. package/dist/context/debug/webgl-developer-tools.d.ts.map +1 -1
  32. package/dist/context/debug/webgl-developer-tools.js +4 -2
  33. package/dist/context/helpers/create-browser-context.d.ts.map +1 -1
  34. package/dist/context/helpers/create-browser-context.js +17 -3
  35. package/dist/dist.dev.js +226 -272
  36. package/dist/dist.min.js +2 -2
  37. package/dist/index.cjs +220 -269
  38. package/dist/index.cjs.map +3 -3
  39. package/package.json +4 -4
  40. package/src/adapter/converters/sampler-parameters.ts +6 -4
  41. package/src/adapter/converters/texture-formats.ts +171 -177
  42. package/src/adapter/helpers/format-utils.ts +6 -0
  43. package/src/adapter/helpers/webgl-texture-utils.ts +66 -45
  44. package/src/adapter/resources/webgl-command-buffer.ts +108 -24
  45. package/src/adapter/resources/webgl-command-encoder.ts +6 -0
  46. package/src/adapter/resources/webgl-external-texture.ts +14 -0
  47. package/src/adapter/resources/webgl-framebuffer.ts +1 -2
  48. package/src/adapter/resources/webgl-render-pass.ts +44 -23
  49. package/src/adapter/resources/webgl-render-pipeline.ts +6 -5
  50. package/src/adapter/resources/webgl-shader.ts +1 -1
  51. package/src/adapter/resources/webgl-texture.ts +126 -235
  52. package/src/adapter/webgl-adapter.ts +1 -1
  53. package/src/adapter/webgl-device.ts +23 -10
  54. package/src/context/debug/webgl-developer-tools.ts +5 -2
  55. package/src/context/helpers/create-browser-context.ts +18 -3
package/dist/index.cjs CHANGED
@@ -720,7 +720,7 @@ function installProgramSpy(gl) {
720
720
 
721
721
  // dist/context/helpers/create-browser-context.js
722
722
  function createBrowserContext(canvas, props, webglContextAttributes) {
723
- const errorMessage = null;
723
+ let errorMessage = "";
724
724
  const webglProps = {
725
725
  preserveDrawingBuffer: true,
726
726
  // failIfMajorPerformanceCaveat: true,
@@ -728,18 +728,30 @@ function createBrowserContext(canvas, props, webglContextAttributes) {
728
728
  };
729
729
  let gl = null;
730
730
  gl ||= canvas.getContext("webgl2", webglProps);
731
+ if (webglProps.failIfMajorPerformanceCaveat) {
732
+ errorMessage ||= "Only software GPU is available. Set `failIfMajorPerformanceCaveat: false` to allow.";
733
+ }
731
734
  if (!gl && !webglContextAttributes.failIfMajorPerformanceCaveat) {
732
735
  webglProps.failIfMajorPerformanceCaveat = false;
733
- gl = canvas.getContext("webgl", webglProps);
736
+ gl = canvas.getContext("webgl2", webglProps);
734
737
  gl.luma ||= {};
735
738
  gl.luma.softwareRenderer = true;
736
739
  }
737
740
  if (!gl) {
738
- throw new Error(`Failed to create WebGL context: ${errorMessage || "Unknown error"}`);
741
+ gl = canvas.getContext("webgl", {});
742
+ if (gl) {
743
+ gl = null;
744
+ errorMessage ||= "Your browser only supports WebGL1";
745
+ }
746
+ }
747
+ if (!gl) {
748
+ errorMessage ||= "Your browser does not support WebGL";
749
+ throw new Error(`Failed to create WebGL context: ${errorMessage}`);
739
750
  }
740
751
  const { onContextLost, onContextRestored } = props;
741
752
  canvas.addEventListener("webglcontextlost", (event) => onContextLost(event), false);
742
753
  canvas.addEventListener("webglcontextrestored", (event) => onContextRestored(event), false);
754
+ gl.luma ||= {};
743
755
  return gl;
744
756
  }
745
757
 
@@ -975,7 +987,7 @@ var TEXTURE_FORMATS = {
975
987
  // 64-bit formats
976
988
  "rg32uint": { gl: 33340, b: 8, c: 2, rb: true },
977
989
  "rg32sint": { gl: 33339, b: 8, c: 2, rb: true },
978
- "rg32float": { gl: 33328, b: 8, c: 2, render: float32_renderable, filter: float32_filterable, rb: true },
990
+ "rg32float": { gl: 33328, b: 8, c: 2, render: false, filter: float32_filterable, rb: true },
979
991
  "rgba16uint": { gl: 36214, b: 8, c: 4, rb: true },
980
992
  "rgba16sint": { gl: 36232, b: 8, c: 4, rb: true },
981
993
  "rgba16float": { gl: 34842, b: 8, c: 4, render: float16_renderable, filter: float16_filterable },
@@ -1136,36 +1148,35 @@ function isTextureFormatSupported(gl, format, extensions) {
1136
1148
  return true;
1137
1149
  }
1138
1150
  function isTextureFormatFilterable(gl, format, extensions) {
1139
- if (!isTextureFormatSupported(gl, format, extensions)) {
1140
- return false;
1141
- }
1142
- if (format.startsWith("depth") || format.startsWith("stencil")) {
1143
- return false;
1144
- }
1145
- try {
1146
- const decoded = (0, import_core.decodeTextureFormat)(format);
1147
- if (decoded.signed) {
1148
- return false;
1149
- }
1150
- } catch {
1151
- return false;
1152
- }
1153
- if (format.endsWith("32float")) {
1154
- return Boolean(getWebGLExtension(gl, "OES_texture_float_linear, extensions", extensions));
1155
- }
1156
- if (format.endsWith("16float")) {
1157
- return Boolean(getWebGLExtension(gl, "OES_texture_half_float_linear, extensions", extensions));
1158
- }
1159
- return true;
1151
+ return getTextureFormatSupportWebGL(gl, format, extensions).filterable || false;
1160
1152
  }
1161
1153
  function isTextureFormatRenderable(gl, format, extensions) {
1162
- if (!isTextureFormatSupported(gl, format, extensions)) {
1163
- return false;
1164
- }
1165
- if (typeof format === "number") {
1166
- return false;
1167
- }
1168
- return true;
1154
+ return getTextureFormatSupportWebGL(gl, format, extensions).renderable || false;
1155
+ }
1156
+ function getTextureFormatSupportWebGL(gl, format, extensions) {
1157
+ const formatInto = (0, import_core.decodeTextureFormat)(format);
1158
+ if (!formatInto) {
1159
+ return { supported: false };
1160
+ }
1161
+ const webglFormatInfo = TEXTURE_FORMATS[format];
1162
+ if (!webglFormatInfo) {
1163
+ return { supported: false };
1164
+ }
1165
+ let supported = webglFormatInfo.gl !== void 0;
1166
+ supported = supported && checkTextureFeature(gl, webglFormatInfo.f, extensions);
1167
+ const isDepthStencil = format.startsWith("depth") || format.startsWith("stencil");
1168
+ const isSigned = formatInto == null ? void 0 : formatInto.signed;
1169
+ const renderable = supported && !isSigned && webglFormatInfo.render && checkTextureFeature(gl, webglFormatInfo.render, extensions);
1170
+ const filterable = supported && !isDepthStencil && !isSigned && webglFormatInfo.filter && checkTextureFeature(gl, webglFormatInfo.filter, extensions);
1171
+ return {
1172
+ supported,
1173
+ renderable,
1174
+ filterable,
1175
+ blendable: false,
1176
+ // TODO,
1177
+ storable: false
1178
+ // TODO
1179
+ };
1169
1180
  }
1170
1181
  function getTextureFormatWebGL(format) {
1171
1182
  var _a;
@@ -1443,7 +1454,7 @@ var WEBGLFramebuffer = class extends import_core4.Framebuffer {
1443
1454
  const attachmentPoint = getDepthStencilAttachmentWebGL(this.depthStencilAttachment.props.format);
1444
1455
  this._attachTextureView(attachmentPoint, this.depthStencilAttachment);
1445
1456
  }
1446
- if (this.props.check !== false) {
1457
+ if (this.device.props.debug) {
1447
1458
  const status = this.gl.checkFramebufferStatus(36160);
1448
1459
  if (status !== 36053) {
1449
1460
  throw new Error(`Framebuffer ${_getFrameBufferStatus(status)}`);
@@ -1669,7 +1680,7 @@ async function loadWebGLDeveloperTools() {
1669
1680
  }
1670
1681
  }
1671
1682
  function makeDebugContext(gl, props = {}) {
1672
- return props.debugWebGL ? getDebugContext(gl, props) : getRealContext(gl);
1683
+ return props.debugWebGL || props.traceWebGL ? getDebugContext(gl, props) : getRealContext(gl);
1673
1684
  }
1674
1685
  function getRealContext(gl) {
1675
1686
  const data = getWebGLContextData(gl);
@@ -1719,7 +1730,9 @@ function onValidateGLFunc(props, functionName, functionArgs) {
1719
1730
  let functionString = "";
1720
1731
  if (import_core7.log.level >= 1) {
1721
1732
  functionString = getFunctionString(functionName, functionArgs);
1722
- import_core7.log.log(1, functionString)();
1733
+ if (props.traceWebGL) {
1734
+ import_core7.log.log(1, functionString)();
1735
+ }
1723
1736
  }
1724
1737
  for (const arg of functionArgs) {
1725
1738
  if (arg === void 0) {
@@ -1960,7 +1973,7 @@ ${source}`;
1960
1973
  const { gl } = this.device;
1961
1974
  gl.shaderSource(this.handle, source);
1962
1975
  gl.compileShader(this.handle);
1963
- if (import_core9.log.level === 0) {
1976
+ if (!this.device.props.debug) {
1964
1977
  this.compilationStatus = "pending";
1965
1978
  return;
1966
1979
  }
@@ -2304,15 +2317,17 @@ function convertMaxFilterMode(maxFilter) {
2304
2317
  return 9729;
2305
2318
  }
2306
2319
  }
2307
- function convertMinFilterMode(minFilter, mipmapFilter) {
2320
+ function convertMinFilterMode(minFilter, mipmapFilter = "none") {
2308
2321
  if (!mipmapFilter) {
2309
2322
  return convertMaxFilterMode(minFilter);
2310
2323
  }
2311
- switch (minFilter) {
2324
+ switch (mipmapFilter) {
2325
+ case "none":
2326
+ return convertMaxFilterMode(minFilter);
2312
2327
  case "nearest":
2313
- return mipmapFilter === "nearest" ? 9984 : 9986;
2328
+ return minFilter === "nearest" ? 9984 : 9986;
2314
2329
  case "linear":
2315
- return mipmapFilter === "nearest" ? 9985 : 9987;
2330
+ return minFilter === "nearest" ? 9985 : 9987;
2316
2331
  }
2317
2332
  }
2318
2333
 
@@ -2466,14 +2481,20 @@ function glFormatToComponents(format) {
2466
2481
  case 6406:
2467
2482
  case 33326:
2468
2483
  case 6403:
2484
+ case 36244:
2469
2485
  return 1;
2486
+ case 33339:
2487
+ case 33340:
2470
2488
  case 33328:
2489
+ case 33320:
2471
2490
  case 33319:
2472
2491
  return 2;
2473
2492
  case 6407:
2493
+ case 36248:
2474
2494
  case 34837:
2475
2495
  return 3;
2476
2496
  case 6408:
2497
+ case 36249:
2477
2498
  case 34836:
2478
2499
  return 4;
2479
2500
  default:
@@ -2515,22 +2536,25 @@ function copyExternalImageToMipLevel(gl, handle, image, options) {
2515
2536
  const { x = 0, y = 0, z = 0 } = options;
2516
2537
  const { glFormat, glType } = options;
2517
2538
  const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
2518
- switch (dimension) {
2519
- case "2d-array":
2520
- case "3d":
2521
- gl.bindTexture(glTarget, handle);
2522
- gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
2523
- gl.bindTexture(glTarget, null);
2524
- break;
2525
- case "2d":
2526
- case "cube":
2527
- gl.bindTexture(glTarget, handle);
2528
- gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
2529
- gl.bindTexture(glTarget, null);
2530
- break;
2531
- default:
2532
- throw new Error(dimension);
2533
- }
2539
+ const glParameters = options.flipY ? { [37440]: true } : {};
2540
+ withGLParameters(gl, glParameters, () => {
2541
+ switch (dimension) {
2542
+ case "2d-array":
2543
+ case "3d":
2544
+ gl.bindTexture(glTarget, handle);
2545
+ gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
2546
+ gl.bindTexture(glTarget, null);
2547
+ break;
2548
+ case "2d":
2549
+ case "cube":
2550
+ gl.bindTexture(glTarget, handle);
2551
+ gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
2552
+ gl.bindTexture(glTarget, null);
2553
+ break;
2554
+ default:
2555
+ throw new Error(dimension);
2556
+ }
2557
+ });
2534
2558
  }
2535
2559
  function copyCPUDataToMipLevel(gl, typedArray, options) {
2536
2560
  const { dimension, width, height, depth = 0, mipLevel = 0, byteOffset = 0 } = options;
@@ -2579,11 +2603,11 @@ function getWebGLCubeFaceTarget(glTarget, dimension, level) {
2579
2603
  return dimension === "cube" ? 34069 + level : glTarget;
2580
2604
  }
2581
2605
  function readPixelsToArray(source, options) {
2582
- var _a, _b, _c, _d, _e, _f;
2606
+ var _a;
2583
2607
  const {
2584
2608
  sourceX = 0,
2585
2609
  sourceY = 0,
2586
- sourceAttachment = 36064
2610
+ sourceAttachment = 0
2587
2611
  // TODO - support gl.readBuffer
2588
2612
  } = options || {};
2589
2613
  let {
@@ -2597,16 +2621,21 @@ function readPixelsToArray(source, options) {
2597
2621
  } = options || {};
2598
2622
  const { framebuffer, deleteFramebuffer } = getFramebuffer(source);
2599
2623
  const { gl, handle } = framebuffer;
2600
- const attachment = sourceAttachment - 36064;
2601
2624
  sourceWidth ||= framebuffer.width;
2602
2625
  sourceHeight ||= framebuffer.height;
2603
- sourceDepth = ((_b = (_a = framebuffer.colorAttachments[attachment]) == null ? void 0 : _a.texture) == null ? void 0 : _b.depth) || 1;
2604
- sourceFormat ||= ((_d = (_c = framebuffer.colorAttachments[attachment]) == null ? void 0 : _c.texture) == null ? void 0 : _d.glFormat) || 6408;
2605
- sourceType ||= ((_f = (_e = framebuffer.colorAttachments[attachment]) == null ? void 0 : _e.texture) == null ? void 0 : _f.glType) || 5121;
2626
+ const texture = (_a = framebuffer.colorAttachments[sourceAttachment]) == null ? void 0 : _a.texture;
2627
+ if (!texture) {
2628
+ throw new Error(`Invalid framebuffer attachment ${sourceAttachment}`);
2629
+ }
2630
+ sourceDepth = (texture == null ? void 0 : texture.depth) || 1;
2631
+ sourceFormat ||= (texture == null ? void 0 : texture.glFormat) || 6408;
2632
+ sourceType ||= (texture == null ? void 0 : texture.glType) || 5121;
2606
2633
  target2 = getPixelArray(target2, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
2607
2634
  sourceType = sourceType || getGLTypeFromTypedArray(target2);
2608
2635
  const prevHandle = gl.bindFramebuffer(36160, handle);
2636
+ gl.readBuffer(36064 + sourceAttachment);
2609
2637
  gl.readPixels(sourceX, sourceY, sourceWidth, sourceHeight, sourceFormat, sourceType, target2);
2638
+ gl.readBuffer(36064);
2610
2639
  gl.bindFramebuffer(36160, prevHandle || null);
2611
2640
  if (deleteFramebuffer) {
2612
2641
  framebuffer.destroy();
@@ -2660,38 +2689,19 @@ function toFramebuffer(texture, props) {
2660
2689
  });
2661
2690
  return framebuffer;
2662
2691
  }
2663
- function getPixelArray(pixelArray, type, format, width, height, depth) {
2692
+ function getPixelArray(pixelArray, glType, glFormat, width, height, depth) {
2664
2693
  if (pixelArray) {
2665
2694
  return pixelArray;
2666
2695
  }
2667
- type = type || 5121;
2668
- const ArrayType = getTypedArrayFromGLType(type, { clamped: false });
2669
- const components = glFormatToComponents(format);
2696
+ glType ||= 5121;
2697
+ const ArrayType = getTypedArrayFromGLType(glType, { clamped: false });
2698
+ const components = glFormatToComponents(glFormat);
2670
2699
  return new ArrayType(width * height * components);
2671
2700
  }
2672
2701
 
2673
2702
  // dist/adapter/resources/webgl-texture.js
2674
- function normalizeTextureData(data, options) {
2675
- let lodArray;
2676
- if (ArrayBuffer.isView(data)) {
2677
- lodArray = [
2678
- {
2679
- // ts-expect-error does data really need to be Uint8ClampedArray?
2680
- data,
2681
- width: options.width,
2682
- height: options.height
2683
- // depth: options.depth
2684
- }
2685
- ];
2686
- } else if (!Array.isArray(data)) {
2687
- lodArray = [data];
2688
- } else {
2689
- lodArray = data;
2690
- }
2691
- return lodArray;
2692
- }
2693
2703
  var WEBGLTexture = class extends import_core14.Texture {
2694
- MAX_ATTRIBUTES;
2704
+ // readonly MAX_ATTRIBUTES: number;
2695
2705
  device;
2696
2706
  gl;
2697
2707
  handle;
@@ -2699,8 +2709,12 @@ var WEBGLTexture = class extends import_core14.Texture {
2699
2709
  // TODO - currently unused in WebGL. Create dummy sampler?
2700
2710
  view = void 0;
2701
2711
  // TODO - currently unused in WebGL. Create dummy view?
2702
- mipmaps = false;
2712
+ mipmaps;
2713
+ // Texture type
2714
+ /** Whether the internal format is compressed */
2715
+ compressed;
2703
2716
  /**
2717
+ * The WebGL target corresponding to the texture type
2704
2718
  * @note `target` cannot be modified by bind:
2705
2719
  * textures are special because when you first bind them to a target,
2706
2720
  * When you first bind a texture as a GL_TEXTURE_2D, you are saying that this texture is a 2D texture.
@@ -2709,122 +2723,79 @@ var WEBGLTexture = class extends import_core14.Texture {
2709
2723
  * attempting to bind it as GL_TEXTURE_3D will give rise to a run-time error
2710
2724
  */
2711
2725
  glTarget;
2712
- // Texture type
2713
2726
  /** The WebGL format - essentially channel structure */
2714
2727
  glFormat;
2715
2728
  /** The WebGL data format - the type of each channel */
2716
2729
  glType;
2717
2730
  /** The WebGL constant corresponding to the WebGPU style constant in format */
2718
2731
  glInternalFormat;
2719
- /** Whether the internal format is compressed */
2720
- compressed;
2721
- // data;
2722
- // inherited props
2723
- // dimension: ...
2724
- // format: GLTextureTarget;
2725
- // width: number = undefined;
2726
- // height: number = undefined;
2727
- // depth: number = undefined;
2728
2732
  // state
2729
- /** Texture binding slot */
2733
+ /** Texture binding slot - TODO - move to texture view? */
2730
2734
  textureUnit = 0;
2731
- /** For automatically updating video */
2732
- _video = null;
2733
2735
  constructor(device, props) {
2734
- props = import_core14.Texture._fixProps(props);
2735
- super(device, { ...import_core14.Texture.defaultProps, ...props, data: void 0 });
2736
+ super(device, props);
2737
+ const propsWithData = { ...this.props };
2738
+ propsWithData.data = props.data;
2736
2739
  this.device = device;
2737
2740
  this.gl = this.device.gl;
2738
2741
  this.glTarget = getWebGLTextureTarget(this.props.dimension);
2739
- const format = getTextureFormatWebGL(this.props.format);
2740
- this.glInternalFormat = format.internalFormat;
2741
- this.glFormat = format.format;
2742
- this.glType = format.type;
2743
- this.compressed = format.compressed;
2744
- if (typeof HTMLVideoElement !== "undefined" && props.data instanceof HTMLVideoElement && // @ts-expect-error
2745
- props.data.readyState < HTMLVideoElement.HAVE_METADATA) {
2746
- const video = props.data;
2747
- this._video = null;
2748
- video.addEventListener("loadeddata", () => this.initialize(props));
2749
- }
2750
- this.initialize({ ...this.props, data: props.data });
2742
+ const formatInfo = getTextureFormatWebGL(this.props.format);
2743
+ this.glInternalFormat = formatInfo.internalFormat;
2744
+ this.glFormat = formatInfo.format;
2745
+ this.glType = formatInfo.type;
2746
+ this.compressed = formatInfo.compressed;
2747
+ this.mipmaps = Boolean(this.props.mipmaps);
2748
+ this._initialize(propsWithData);
2751
2749
  Object.seal(this);
2752
2750
  }
2753
2751
  /**
2754
2752
  * Initialize texture with supplied props
2755
2753
  */
2756
2754
  // eslint-disable-next-line max-statements
2757
- initialize(props = {}) {
2755
+ _initialize(propsWithData) {
2758
2756
  this.handle = this.props.handle || this.gl.createTexture();
2759
- this.device.setSpectorMetadata(this.handle, { ...this.props, data: typeof this.props.data });
2760
- const data = props.data;
2761
- let { width, height } = props;
2757
+ this.device.setSpectorMetadata(this.handle, { ...this.props, data: propsWithData.data });
2758
+ let { width, height } = propsWithData;
2762
2759
  if (!width || !height) {
2763
- const textureSize = import_core14.Texture.getTextureDataSize(data);
2760
+ const textureSize = import_core14.Texture.getTextureDataSize(propsWithData.data);
2764
2761
  width = (textureSize == null ? void 0 : textureSize.width) || 1;
2765
2762
  height = (textureSize == null ? void 0 : textureSize.height) || 1;
2766
2763
  }
2767
2764
  this.width = width;
2768
2765
  this.height = height;
2769
- this.depth = props.depth;
2770
- this.setSampler(props.sampler);
2766
+ this.depth = propsWithData.depth;
2767
+ this.setSampler(propsWithData.sampler);
2771
2768
  this.view = new WEBGLTextureView(this.device, { ...this.props, texture: this });
2772
2769
  this.bind();
2773
- if (!this.props.data) {
2774
- initializeTextureStorage(this.gl, this.mipLevels, this);
2775
- }
2776
- if (props.data) {
2777
- switch (props.dimension) {
2770
+ initializeTextureStorage(this.gl, this.mipLevels, this);
2771
+ if (propsWithData.data) {
2772
+ switch (propsWithData.dimension) {
2778
2773
  case "1d":
2779
- this.setTexture1DData(props.data);
2774
+ this.setTexture1DData(propsWithData.data);
2780
2775
  break;
2781
2776
  case "2d":
2782
- this.setTexture2DData(props.data);
2777
+ this.setTexture2DData(propsWithData.data);
2783
2778
  break;
2784
2779
  case "3d":
2785
- this.setTexture3DData(props.data);
2780
+ this.setTexture3DData(propsWithData.data);
2786
2781
  break;
2787
2782
  case "cube":
2788
- this.setTextureCubeData(props.data);
2783
+ this.setTextureCubeData(propsWithData.data);
2789
2784
  break;
2790
2785
  case "2d-array":
2791
- this.setTextureArrayData(props.data);
2786
+ this.setTextureArrayData(propsWithData.data);
2792
2787
  break;
2793
2788
  case "cube-array":
2794
- this.setTextureCubeArrayData(props.data);
2789
+ this.setTextureCubeArrayData(propsWithData.data);
2795
2790
  break;
2796
2791
  default:
2797
- throw new Error(props.dimension);
2792
+ throw new Error(propsWithData.dimension);
2798
2793
  }
2799
2794
  }
2800
- this.mipmaps = Boolean(props.mipmaps);
2801
2795
  if (this.mipmaps) {
2802
2796
  this.generateMipmap();
2803
2797
  }
2804
2798
  }
2805
- /*
2806
- initializeCube(props?: TextureProps): void {
2807
- const {mipmaps = true} = props; // , parameters = {} as Record<GL, any>} = props;
2808
-
2809
- // Store props for accessors
2810
- // this.props = props;
2811
-
2812
- // @ts-expect-error
2813
- this.setCubeMapData(props).then(() => {
2814
- // TODO - should genMipmap() be called on the cubemap or on the faces?
2815
- // TODO - without generateMipmap() cube textures do not work at all!!! Why?
2816
- if (mipmaps) {
2817
- this.generateMipmap(props);
2818
- }
2819
-
2820
- this.setSampler(props.sampler);
2821
-
2822
- // v8 compatibility?
2823
- // const {parameters = {} as Record<GL, any>} = props;
2824
- // this._setSamplerParameters(parameters);
2825
- });
2826
- }
2827
- */
2828
2799
  destroy() {
2829
2800
  if (this.handle) {
2830
2801
  this.gl.deleteTexture(this.handle);
@@ -2833,9 +2804,6 @@ var WEBGLTexture = class extends import_core14.Texture {
2833
2804
  this.destroyed = true;
2834
2805
  }
2835
2806
  }
2836
- toString() {
2837
- return `Texture(${this.id},${this.width}x${this.height})`;
2838
- }
2839
2807
  createView(props) {
2840
2808
  return new WEBGLTextureView(this.device, { ...props, texture: this });
2841
2809
  }
@@ -2851,33 +2819,33 @@ var WEBGLTexture = class extends import_core14.Texture {
2851
2819
  const parameters = convertSamplerParametersToWebGL(samplerProps);
2852
2820
  this._setSamplerParameters(parameters);
2853
2821
  }
2854
- /** Update external texture (video frame or canvas) */
2855
- update() {
2856
- import_core14.log.warn("Texture.update() not implemented");
2857
- }
2858
2822
  // Call to regenerate mipmaps after modifying texture(s)
2859
2823
  generateMipmap(params = {}) {
2860
- if (!this.props.data) {
2861
- return;
2824
+ if (!this.device.isTextureFormatRenderable(this.props.format) || !this.device.isTextureFormatFilterable(this.props.format)) {
2825
+ import_core14.log.warn(`${this} is not renderable or filterable, may not be able to generate mipmaps`)();
2826
+ }
2827
+ try {
2828
+ this.gl.bindTexture(this.glTarget, this.handle);
2829
+ withGLParameters(this.gl, params, () => {
2830
+ this.gl.generateMipmap(this.glTarget);
2831
+ });
2832
+ } catch (error) {
2833
+ import_core14.log.warn(`Error generating mipmap for ${this}: ${error.message}`)();
2834
+ } finally {
2835
+ this.gl.bindTexture(this.glTarget, null);
2862
2836
  }
2863
- this.mipmaps = true;
2864
- this.gl.bindTexture(this.glTarget, this.handle);
2865
- withGLParameters(this.gl, params, () => {
2866
- this.gl.generateMipmap(this.glTarget);
2867
- });
2868
- this.gl.bindTexture(this.glTarget, null);
2869
2837
  }
2870
2838
  // Image Data Setters
2871
2839
  copyExternalImage(options) {
2872
2840
  const size = import_core14.Texture.getExternalImageSize(options.image);
2873
2841
  const opts = { ...import_core14.Texture.defaultCopyExternalImageOptions, ...size, ...options };
2874
- const { image, depth, mipLevel, x, y, z } = opts;
2842
+ const { image, depth, mipLevel, x, y, z, flipY } = opts;
2875
2843
  let { width, height } = opts;
2876
2844
  const { dimension, glTarget, glFormat, glInternalFormat, glType } = this;
2877
2845
  width = Math.min(width, size.width - x);
2878
2846
  height = Math.min(height, size.height - y);
2879
2847
  if (options.sourceX || options.sourceY) {
2880
- throw new Error("WebGL does not yet support sourceX/sourceY in copyExternalImage; requires copyTexSubImage2D from a framebuffer");
2848
+ throw new Error("WebGL does not support sourceX/sourceY)");
2881
2849
  }
2882
2850
  copyExternalImageToMipLevel(this.device.gl, this.handle, image, {
2883
2851
  dimension,
@@ -2891,7 +2859,8 @@ var WEBGLTexture = class extends import_core14.Texture {
2891
2859
  glFormat,
2892
2860
  glInternalFormat,
2893
2861
  glType,
2894
- glTarget
2862
+ glTarget,
2863
+ flipY
2895
2864
  });
2896
2865
  return { width: opts.width, height: opts.height };
2897
2866
  }
@@ -2901,7 +2870,7 @@ var WEBGLTexture = class extends import_core14.Texture {
2901
2870
  /** Set a simple texture */
2902
2871
  setTexture2DData(lodData, depth = 0) {
2903
2872
  this.bind();
2904
- const lodArray = normalizeTextureData(lodData, this);
2873
+ const lodArray = import_core14.Texture.normalizeTextureData(lodData, this);
2905
2874
  if (lodArray.length > 1 && this.props.mipmaps !== false) {
2906
2875
  import_core14.log.warn(`Texture ${this.id} mipmap and multiple LODs.`)();
2907
2876
  }
@@ -2963,6 +2932,11 @@ var WEBGLTexture = class extends import_core14.Texture {
2963
2932
  const faceDepth = import_core14.Texture.CubeFaces.indexOf(face);
2964
2933
  this.setTexture2DData(lodData, faceDepth);
2965
2934
  }
2935
+ // DEPRECATED METHODS
2936
+ /** Update external texture (video frame or canvas) @deprecated Use ExternalTexture */
2937
+ update() {
2938
+ throw new Error("Texture.update() not implemented. Use ExternalTexture");
2939
+ }
2966
2940
  // INTERNAL METHODS
2967
2941
  /** @todo update this method to accept LODs */
2968
2942
  setImageDataForFace(options) {
@@ -3006,7 +2980,7 @@ var WEBGLTexture = class extends import_core14.Texture {
3006
2980
  * Sets sampler parameters on texture
3007
2981
  */
3008
2982
  _setSamplerParameters(parameters) {
3009
- import_core14.log.log(1, "texture sampler parameters", parameters)();
2983
+ import_core14.log.log(1, `${this.id} sampler parameters`, this.device.getGLKeys(parameters))();
3010
2984
  this.gl.bindTexture(this.glTarget, this.handle);
3011
2985
  for (const [pname, pvalue] of Object.entries(parameters)) {
3012
2986
  const param = Number(pname);
@@ -3035,61 +3009,6 @@ var WEBGLTexture = class extends import_core14.Texture {
3035
3009
  }
3036
3010
  this.gl.bindTexture(this.glTarget, null);
3037
3011
  }
3038
- // CLASSIC
3039
- /*
3040
- setCubeMapData(options: {
3041
- width: number;
3042
- height: number;
3043
- data: Record<GL, Texture2DData> | Record<TextureCubeFace, Texture2DData>;
3044
- format?: any;
3045
- type?: any;
3046
- /** @deprecated Use .data *
3047
- pixels: any;
3048
- }): void {
3049
- const {gl} = this;
3050
-
3051
- const {width, height, pixels, data, format = GL.RGBA, type = GL.UNSIGNED_BYTE} = options;
3052
-
3053
- // pixel data (imageDataMap) is an Object from Face to Image or Promise.
3054
- // For example:
3055
- // {
3056
- // GL.TEXTURE_CUBE_MAP_POSITIVE_X : Image-or-Promise,
3057
- // GL.TEXTURE_CUBE_MAP_NEGATIVE_X : Image-or-Promise,
3058
- // ... }
3059
- // To provide multiple level-of-details (LODs) this can be Face to Array
3060
- // of Image or Promise, like this
3061
- // {
3062
- // GL.TEXTURE_CUBE_MAP_POSITIVE_X : [Image-or-Promise-LOD-0, Image-or-Promise-LOD-1],
3063
- // GL.TEXTURE_CUBE_MAP_NEGATIVE_X : [Image-or-Promise-LOD-0, Image-or-Promise-LOD-1],
3064
- // ... }
3065
-
3066
- const imageDataMap = this._getImageDataMap(pixels || data);
3067
-
3068
- const resolvedFaces = WEBGLTexture.FACES.map(face => {
3069
- const facePixels = imageDataMap[face];
3070
- return Array.isArray(facePixels) ? facePixels : [facePixels];
3071
- });
3072
- this.bind();
3073
-
3074
- WEBGLTexture.FACES.forEach((face, index) => {
3075
- if (resolvedFaces[index].length > 1 && this.props.mipmaps !== false) {
3076
- // If the user provides multiple LODs, then automatic mipmap
3077
- // generation generateMipmap() should be disabled to avoid overwritting them.
3078
- log.warn(`${this.id} has mipmap and multiple LODs.`)();
3079
- }
3080
- resolvedFaces[index].forEach((image, lodLevel) => {
3081
- // TODO: adjust width & height for LOD!
3082
- if (width && height) {
3083
- gl.texImage2D(face, lodLevel, format, width, height, 0 /* border*, format, type, image);
3084
- } else {
3085
- gl.texImage2D(face, lodLevel, format, format, type, image);
3086
- }
3087
- });
3088
- });
3089
-
3090
- this.unbind();
3091
- }
3092
- */
3093
3012
  // INTERNAL SETTERS
3094
3013
  /**
3095
3014
  * Copy a region of data from a CPU memory buffer into this texture.
@@ -3101,7 +3020,8 @@ var WEBGLTexture = class extends import_core14.Texture {
3101
3020
  ...this,
3102
3021
  depth,
3103
3022
  mipLevel,
3104
- glTarget
3023
+ glTarget,
3024
+ flipY: this.props.flipY
3105
3025
  });
3106
3026
  return;
3107
3027
  }
@@ -3143,10 +3063,6 @@ var WEBGLTexture = class extends import_core14.Texture {
3143
3063
  // dist/adapter/resources/webgl-render-pass.js
3144
3064
  var import_core15 = require("@luma.gl/core");
3145
3065
  var import_constants17 = require("@luma.gl/constants");
3146
- var GL_DEPTH_BUFFER_BIT = 256;
3147
- var GL_STENCIL_BUFFER_BIT = 1024;
3148
- var GL_COLOR_BUFFER_BIT = 16384;
3149
- var GL_COLOR = 6144;
3150
3066
  var COLOR_CHANNELS = [1, 2, 4, 8];
3151
3067
  var WEBGLRenderPass = class extends import_core15.RenderPass {
3152
3068
  device;
@@ -3168,6 +3084,12 @@ var WEBGLRenderPass = class extends import_core15.RenderPass {
3168
3084
  }
3169
3085
  this.device.pushState();
3170
3086
  this.setParameters({ viewport, ...this.props.parameters });
3087
+ if (this.props.framebuffer) {
3088
+ const drawBuffers = this.props.framebuffer.colorAttachments.map((_, i) => 36064 + i);
3089
+ this.device.gl.drawBuffers(drawBuffers);
3090
+ } else {
3091
+ this.device.gl.drawBuffers([1029]);
3092
+ }
3171
3093
  this.clear();
3172
3094
  }
3173
3095
  end() {
@@ -3231,19 +3153,30 @@ var WEBGLRenderPass = class extends import_core15.RenderPass {
3231
3153
  * Optionally clears depth, color and stencil buffers based on parameters
3232
3154
  */
3233
3155
  clear() {
3156
+ const DEFAULT_CLEAR_COLOR = [0, 0, 0, 1];
3157
+ const DEFAULT_CLEAR_DEPTH = 1;
3158
+ const DEFAULT_CLEAR_STENCIL = 0;
3234
3159
  const glParameters = { ...this.glParameters };
3235
3160
  let clearMask = 0;
3236
- if (this.props.clearColor !== false) {
3237
- clearMask |= GL_COLOR_BUFFER_BIT;
3238
- glParameters.clearColor = this.props.clearColor;
3161
+ if (this.props.clearColors) {
3162
+ this.props.clearColors.forEach((color, drawBufferIndex) => {
3163
+ if (color) {
3164
+ this.clearColorBuffer(drawBufferIndex, color);
3165
+ }
3166
+ });
3167
+ }
3168
+ if (this.props.clearColor !== false && this.props.clearColors === void 0) {
3169
+ clearMask |= 16384;
3170
+ const clearColor = this.props.clearColor === true ? DEFAULT_CLEAR_COLOR : this.props.clearColor;
3171
+ glParameters.clearColor = clearColor;
3239
3172
  }
3240
3173
  if (this.props.clearDepth !== false) {
3241
- clearMask |= GL_DEPTH_BUFFER_BIT;
3242
- glParameters.clearDepth = this.props.clearDepth;
3174
+ clearMask |= 256;
3175
+ glParameters.clearDepth = this.props.clearDepth === true ? DEFAULT_CLEAR_DEPTH : this.props.clearDepth;
3243
3176
  }
3244
3177
  if (this.props.clearStencil !== false) {
3245
- clearMask |= GL_STENCIL_BUFFER_BIT;
3246
- glParameters.clearStencil = this.props.clearStencil;
3178
+ clearMask |= 1024;
3179
+ glParameters.clearStencil = this.props.clearStencil === true ? DEFAULT_CLEAR_STENCIL : this.props.clearStencil;
3247
3180
  }
3248
3181
  if (clearMask !== 0) {
3249
3182
  withGLParameters(this.device.gl, glParameters, () => {
@@ -3257,16 +3190,22 @@ var WEBGLRenderPass = class extends import_core15.RenderPass {
3257
3190
  clearColorBuffer(drawBuffer = 0, value = [0, 0, 0, 0]) {
3258
3191
  withGLParameters(this.device.gl, { framebuffer: this.props.framebuffer }, () => {
3259
3192
  switch (value.constructor) {
3193
+ case Int8Array:
3194
+ case Int16Array:
3260
3195
  case Int32Array:
3261
- this.device.gl.clearBufferiv(GL_COLOR, drawBuffer, value);
3196
+ this.device.gl.clearBufferiv(6144, drawBuffer, value);
3262
3197
  break;
3198
+ case Uint8Array:
3199
+ case Uint8ClampedArray:
3200
+ case Uint16Array:
3263
3201
  case Uint32Array:
3264
- this.device.gl.clearBufferuiv(GL_COLOR, drawBuffer, value);
3202
+ this.device.gl.clearBufferuiv(6144, drawBuffer, value);
3265
3203
  break;
3266
3204
  case Float32Array:
3267
- default:
3268
- this.device.gl.clearBufferfv(GL_COLOR, drawBuffer, value);
3205
+ this.device.gl.clearBufferfv(6144, drawBuffer, value);
3269
3206
  break;
3207
+ default:
3208
+ throw new Error("clearColorBuffer: color must be typed array");
3270
3209
  }
3271
3210
  });
3272
3211
  }
@@ -3970,11 +3909,6 @@ var WEBGLRenderPipeline = class extends import_core16.RenderPipeline {
3970
3909
  texturesRenderable = false;
3971
3910
  }
3972
3911
  }
3973
- for (const [, texture] of Object.entries(this.bindings)) {
3974
- if (texture instanceof WEBGLTexture) {
3975
- texture.update();
3976
- }
3977
- }
3978
3912
  return texturesRenderable;
3979
3913
  }
3980
3914
  /** Apply any bindings (before each draw call) */
@@ -4101,6 +4035,8 @@ var WEBGLCommandBuffer = class extends import_core17.CommandBuffer {
4101
4035
  case "copy-texture-to-texture":
4102
4036
  _copyTextureToTexture(this.device, command.options);
4103
4037
  break;
4038
+ default:
4039
+ throw new Error(command.name);
4104
4040
  }
4105
4041
  }
4106
4042
  }
@@ -4279,6 +4215,9 @@ var WEBGLCommandEncoder = class extends import_core18.CommandEncoder {
4279
4215
  copyTextureToTexture(options) {
4280
4216
  this.commandBuffer.commands.push({ name: "copy-texture-to-texture", options });
4281
4217
  }
4218
+ // clearTexture(options: ClearTextureOptions): void {
4219
+ // this.commandBuffer.commands.push({name: 'copy-texture-to-texture', options});
4220
+ // }
4282
4221
  pushDebugGroup(groupLabel) {
4283
4222
  }
4284
4223
  popDebugGroup() {
@@ -4793,9 +4732,9 @@ var WEBGLQuerySet = class extends import_core21.QuerySet {
4793
4732
 
4794
4733
  // dist/deprecated/clear.js
4795
4734
  var import_core22 = require("@luma.gl/core");
4796
- var GL_DEPTH_BUFFER_BIT2 = 256;
4797
- var GL_STENCIL_BUFFER_BIT2 = 1024;
4798
- var GL_COLOR_BUFFER_BIT2 = 16384;
4735
+ var GL_DEPTH_BUFFER_BIT = 256;
4736
+ var GL_STENCIL_BUFFER_BIT = 1024;
4737
+ var GL_COLOR_BUFFER_BIT = 16384;
4799
4738
  function clear(device, options) {
4800
4739
  import_core22.log.warn("clear will be removed in next minor release");
4801
4740
  const { framebuffer = null, color = null, depth = null, stencil = null } = options || {};
@@ -4805,19 +4744,19 @@ function clear(device, options) {
4805
4744
  }
4806
4745
  let clearFlags = 0;
4807
4746
  if (color) {
4808
- clearFlags |= GL_COLOR_BUFFER_BIT2;
4747
+ clearFlags |= GL_COLOR_BUFFER_BIT;
4809
4748
  if (color !== true) {
4810
4749
  parameters.clearColor = color;
4811
4750
  }
4812
4751
  }
4813
4752
  if (depth) {
4814
- clearFlags |= GL_DEPTH_BUFFER_BIT2;
4753
+ clearFlags |= GL_DEPTH_BUFFER_BIT;
4815
4754
  if (depth !== true) {
4816
4755
  parameters.clearDepth = depth;
4817
4756
  }
4818
4757
  }
4819
4758
  if (stencil) {
4820
- clearFlags |= GL_STENCIL_BUFFER_BIT2;
4759
+ clearFlags |= GL_STENCIL_BUFFER_BIT;
4821
4760
  if (depth !== true) {
4822
4761
  parameters.clearStencil = depth;
4823
4762
  }
@@ -4912,11 +4851,14 @@ var WebGLDevice = class extends import_core23.Device {
4912
4851
  log: (...args) => import_core23.log.log(1, ...args)()
4913
4852
  });
4914
4853
  glState.trackState(this.gl, { copyState: false });
4915
- if (props.debugWebGL) {
4916
- this.gl = makeDebugContext(this.gl, { ...props });
4917
- this.debug = true;
4918
- import_core23.log.level = Math.max(import_core23.log.level, 1);
4854
+ const debugWebGL = props.debugWebGL || props.debug;
4855
+ const traceWebGL = props.debugWebGL;
4856
+ if (debugWebGL) {
4857
+ this.gl = makeDebugContext(this.gl, { debugWebGL, traceWebGL });
4919
4858
  import_core23.log.warn("WebGL debug mode activated. Performance reduced.")();
4859
+ if (props.debugWebGL) {
4860
+ import_core23.log.level = Math.max(import_core23.log.level, 1);
4861
+ }
4920
4862
  }
4921
4863
  }
4922
4864
  /**
@@ -5066,15 +5008,24 @@ var WebGLDevice = class extends import_core23.Device {
5066
5008
  * Be aware that there are some duplicates especially for constants that are 0,
5067
5009
  * so this isn't guaranteed to return the right key in all cases.
5068
5010
  */
5069
- getGLKey(value, gl) {
5070
- gl = gl || this.gl2 || this.gl;
5011
+ getGLKey(value, options) {
5071
5012
  const number = Number(value);
5072
- for (const key in gl) {
5073
- if (gl[key] === number) {
5013
+ for (const key in this.gl) {
5014
+ if (this.gl[key] === number) {
5074
5015
  return `GL.${key}`;
5075
5016
  }
5076
5017
  }
5077
- return String(value);
5018
+ return (options == null ? void 0 : options.emptyIfUnknown) ? "" : String(value);
5019
+ }
5020
+ /**
5021
+ * Returns a map with any GL.<KEY> constants mapped to strings, both for keys and values
5022
+ */
5023
+ getGLKeys(glParameters) {
5024
+ const opts = { emptyIfUnknown: true };
5025
+ return Object.entries(glParameters).reduce((keys, [key, value]) => {
5026
+ keys[`${key}:${this.getGLKey(key, opts)}`] = `${value}:${this.getGLKey(value, opts)}`;
5027
+ return keys;
5028
+ }, {});
5078
5029
  }
5079
5030
  /** Store constants */
5080
5031
  _constants;
@@ -5291,7 +5242,7 @@ var WebGLAdapter = class extends import_core24.Adapter {
5291
5242
  async create(props = {}) {
5292
5243
  import_core24.log.groupCollapsed(LOG_LEVEL2, "WebGLDevice created")();
5293
5244
  const promises = [];
5294
- if (props.debugWebGL) {
5245
+ if (props.debugWebGL || props.debug) {
5295
5246
  promises.push(loadWebGLDeveloperTools());
5296
5247
  }
5297
5248
  if (props.debugSpectorJS) {