@loaders.gl/textures 4.4.0-alpha.9 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/README.md +197 -1
  2. package/dist/basis-loader.d.ts +15 -10
  3. package/dist/basis-loader.d.ts.map +1 -1
  4. package/dist/basis-loader.js +0 -1
  5. package/dist/basis-loader.js.map +1 -1
  6. package/dist/basis-worker-node.js +797 -9971
  7. package/dist/basis-worker.js +300 -145
  8. package/dist/compressed-texture-loader.d.ts +0 -4
  9. package/dist/compressed-texture-loader.d.ts.map +1 -1
  10. package/dist/compressed-texture-loader.js +0 -1
  11. package/dist/compressed-texture-loader.js.map +1 -1
  12. package/dist/compressed-texture-worker.js +1110 -358
  13. package/dist/crunch-loader.d.ts +1 -5
  14. package/dist/crunch-loader.d.ts.map +1 -1
  15. package/dist/crunch-loader.js +1 -3
  16. package/dist/crunch-loader.js.map +1 -1
  17. package/dist/crunch-worker.js +168 -87
  18. package/dist/dist.dev.js +2647 -670
  19. package/dist/dist.min.js +1 -2
  20. package/dist/index.cjs +1642 -428
  21. package/dist/index.cjs.map +4 -4
  22. package/dist/index.d.ts +13 -4
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +6 -3
  25. package/dist/index.js.map +1 -1
  26. package/dist/ktx2-basis-writer-worker-node.js +444 -9763
  27. package/dist/ktx2-basis-writer-worker.js +13 -3
  28. package/dist/lib/composite-image/image-texture-cube.d.ts +47 -0
  29. package/dist/lib/composite-image/image-texture-cube.d.ts.map +1 -0
  30. package/dist/lib/composite-image/image-texture-cube.js +42 -0
  31. package/dist/lib/composite-image/image-texture-cube.js.map +1 -0
  32. package/dist/lib/composite-image/parse-composite-image.d.ts +43 -0
  33. package/dist/lib/composite-image/parse-composite-image.d.ts.map +1 -0
  34. package/dist/lib/composite-image/parse-composite-image.js +437 -0
  35. package/dist/lib/composite-image/parse-composite-image.js.map +1 -0
  36. package/dist/lib/encoders/encode-ktx2-basis-texture.d.ts.map +1 -1
  37. package/dist/lib/encoders/encode-ktx2-basis-texture.js +2 -1
  38. package/dist/lib/encoders/encode-ktx2-basis-texture.js.map +1 -1
  39. package/dist/lib/gl-extensions.d.ts +166 -58
  40. package/dist/lib/gl-extensions.d.ts.map +1 -1
  41. package/dist/lib/gl-extensions.js +177 -66
  42. package/dist/lib/gl-extensions.js.map +1 -1
  43. package/dist/lib/gl-types.d.ts +4 -0
  44. package/dist/lib/gl-types.d.ts.map +1 -0
  45. package/dist/lib/gl-types.js +5 -0
  46. package/dist/lib/gl-types.js.map +1 -0
  47. package/dist/lib/parsers/crunch-module-loader.d.ts +2 -2
  48. package/dist/lib/parsers/crunch-module-loader.d.ts.map +1 -1
  49. package/dist/lib/parsers/crunch-module-loader.js.map +1 -1
  50. package/dist/lib/parsers/parse-basis.d.ts +24 -2
  51. package/dist/lib/parsers/parse-basis.d.ts.map +1 -1
  52. package/dist/lib/parsers/parse-basis.js +262 -64
  53. package/dist/lib/parsers/parse-basis.js.map +1 -1
  54. package/dist/lib/parsers/parse-crunch.d.ts.map +1 -1
  55. package/dist/lib/parsers/parse-crunch.js +6 -6
  56. package/dist/lib/parsers/parse-crunch.js.map +1 -1
  57. package/dist/lib/parsers/parse-dds.d.ts.map +1 -1
  58. package/dist/lib/parsers/parse-dds.js +10 -11
  59. package/dist/lib/parsers/parse-dds.js.map +1 -1
  60. package/dist/lib/parsers/parse-hdr.d.ts +21 -0
  61. package/dist/lib/parsers/parse-hdr.d.ts.map +1 -0
  62. package/dist/lib/parsers/parse-hdr.js +305 -0
  63. package/dist/lib/parsers/parse-hdr.js.map +1 -0
  64. package/dist/lib/parsers/parse-ktx.d.ts.map +1 -1
  65. package/dist/lib/parsers/parse-ktx.js +10 -3
  66. package/dist/lib/parsers/parse-ktx.js.map +1 -1
  67. package/dist/lib/parsers/parse-pvr.d.ts.map +1 -1
  68. package/dist/lib/parsers/parse-pvr.js +31 -74
  69. package/dist/lib/parsers/parse-pvr.js.map +1 -1
  70. package/dist/lib/texture-api/generate-url.d.ts.map +1 -1
  71. package/dist/lib/texture-api/generate-url.js +2 -10
  72. package/dist/lib/texture-api/generate-url.js.map +1 -1
  73. package/dist/lib/texture-api/load-image-array.d.ts +6 -3
  74. package/dist/lib/texture-api/load-image-array.d.ts.map +1 -1
  75. package/dist/lib/texture-api/load-image-array.js +5 -3
  76. package/dist/lib/texture-api/load-image-array.js.map +1 -1
  77. package/dist/lib/texture-api/load-image-cube.d.ts +7 -11
  78. package/dist/lib/texture-api/load-image-cube.d.ts.map +1 -1
  79. package/dist/lib/texture-api/load-image-cube.js +8 -20
  80. package/dist/lib/texture-api/load-image-cube.js.map +1 -1
  81. package/dist/lib/texture-api/load-image.d.ts +6 -3
  82. package/dist/lib/texture-api/load-image.d.ts.map +1 -1
  83. package/dist/lib/texture-api/load-image.js +8 -4
  84. package/dist/lib/texture-api/load-image.js.map +1 -1
  85. package/dist/lib/texture-api/texture-api-types.d.ts +13 -0
  86. package/dist/lib/texture-api/texture-api-types.d.ts.map +1 -1
  87. package/dist/lib/utils/detect-supported-texture-formats.d.ts +14 -0
  88. package/dist/lib/utils/detect-supported-texture-formats.d.ts.map +1 -0
  89. package/dist/lib/utils/detect-supported-texture-formats.js +197 -0
  90. package/dist/lib/utils/detect-supported-texture-formats.js.map +1 -0
  91. package/dist/lib/utils/extract-mipmap-images.d.ts +6 -2
  92. package/dist/lib/utils/extract-mipmap-images.d.ts.map +1 -1
  93. package/dist/lib/utils/extract-mipmap-images.js +13 -2
  94. package/dist/lib/utils/extract-mipmap-images.js.map +1 -1
  95. package/dist/lib/utils/ktx-format-helper.d.ts +9 -1
  96. package/dist/lib/utils/ktx-format-helper.d.ts.map +1 -1
  97. package/dist/lib/utils/ktx-format-helper.js +76 -109
  98. package/dist/lib/utils/ktx-format-helper.js.map +1 -1
  99. package/dist/lib/utils/texture-format-map.d.ts +10 -0
  100. package/dist/lib/utils/texture-format-map.d.ts.map +1 -0
  101. package/dist/lib/utils/texture-format-map.js +87 -0
  102. package/dist/lib/utils/texture-format-map.js.map +1 -0
  103. package/dist/lib/utils/version.js +1 -1
  104. package/dist/lib/utils/version.js.map +1 -1
  105. package/dist/npy-loader.d.ts +2 -2
  106. package/dist/npy-worker.js +1 -1
  107. package/dist/radiance-hdr-loader.d.ts +25 -0
  108. package/dist/radiance-hdr-loader.d.ts.map +1 -0
  109. package/dist/radiance-hdr-loader.js +23 -0
  110. package/dist/radiance-hdr-loader.js.map +1 -0
  111. package/dist/texture-array-loader.d.ts +25 -0
  112. package/dist/texture-array-loader.d.ts.map +1 -0
  113. package/dist/texture-array-loader.js +24 -0
  114. package/dist/texture-array-loader.js.map +1 -0
  115. package/dist/texture-cube-array-loader.d.ts +25 -0
  116. package/dist/texture-cube-array-loader.d.ts.map +1 -0
  117. package/dist/texture-cube-array-loader.js +24 -0
  118. package/dist/texture-cube-array-loader.js.map +1 -0
  119. package/dist/texture-cube-loader.d.ts +25 -0
  120. package/dist/texture-cube-loader.d.ts.map +1 -0
  121. package/dist/texture-cube-loader.js +24 -0
  122. package/dist/texture-cube-loader.js.map +1 -0
  123. package/dist/texture-loader.d.ts +25 -0
  124. package/dist/texture-loader.d.ts.map +1 -0
  125. package/dist/texture-loader.js +24 -0
  126. package/dist/texture-loader.js.map +1 -0
  127. package/dist/workers/crunch-worker.d.ts +1 -3
  128. package/dist/workers/crunch-worker.d.ts.map +1 -1
  129. package/package.json +6 -6
  130. package/src/basis-loader.ts +19 -9
  131. package/src/compressed-texture-loader.ts +0 -3
  132. package/src/crunch-loader.ts +1 -5
  133. package/src/index.ts +21 -4
  134. package/src/lib/composite-image/image-texture-cube.ts +49 -0
  135. package/src/lib/composite-image/parse-composite-image.ts +699 -0
  136. package/src/lib/encoders/encode-ktx2-basis-texture.ts +2 -1
  137. package/src/lib/gl-extensions.ts +188 -81
  138. package/src/lib/gl-types.ts +136 -0
  139. package/src/lib/parsers/crunch-module-loader.ts +4 -4
  140. package/src/lib/parsers/parse-basis.ts +326 -62
  141. package/src/lib/parsers/parse-crunch.ts +11 -8
  142. package/src/lib/parsers/parse-dds.ts +11 -12
  143. package/src/lib/parsers/parse-hdr.ts +426 -0
  144. package/src/lib/parsers/parse-ktx.ts +13 -3
  145. package/src/lib/parsers/parse-pvr.ts +33 -75
  146. package/src/lib/texture-api/generate-url.ts +2 -12
  147. package/src/lib/texture-api/load-image-array.ts +15 -6
  148. package/src/lib/texture-api/load-image-cube.ts +20 -34
  149. package/src/lib/texture-api/load-image.ts +19 -8
  150. package/src/lib/texture-api/texture-api-types.ts +15 -0
  151. package/src/lib/utils/detect-supported-texture-formats.ts +210 -0
  152. package/src/lib/utils/extract-mipmap-images.ts +23 -4
  153. package/src/lib/utils/ktx-format-helper.ts +135 -111
  154. package/src/lib/utils/texture-format-map.ts +162 -0
  155. package/src/radiance-hdr-loader.ts +36 -0
  156. package/src/texture-array-loader.ts +46 -0
  157. package/src/texture-cube-array-loader.ts +49 -0
  158. package/src/texture-cube-loader.ts +46 -0
  159. package/src/texture-loader.ts +49 -0
  160. package/dist/lib/utils/texture-formats.d.ts +0 -8
  161. package/dist/lib/utils/texture-formats.d.ts.map +0 -1
  162. package/dist/lib/utils/texture-formats.js +0 -51
  163. package/dist/lib/utils/texture-formats.js.map +0 -1
  164. package/src/lib/utils/texture-formats.ts +0 -59
@@ -2,11 +2,30 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
+ /* eslint-disable camelcase */
5
6
  /* eslint-disable indent */
6
- import type {TextureLevel} from '@loaders.gl/schema';
7
+ import type {TextureFormat, TextureLevel} from '@loaders.gl/schema';
8
+ import {extractLoadLibraryOptions} from '@loaders.gl/worker-utils';
7
9
  import {loadBasisEncoderModule, loadBasisTranscoderModule} from './basis-module-loader';
8
- import {GL_EXTENSIONS_CONSTANTS} from '../gl-extensions';
9
- import {getSupportedGPUTextureFormats} from '../utils/texture-formats';
10
+ import type {GLTextureFormat} from '../gl-types';
11
+ import {
12
+ GL_COMPRESSED_RED_GREEN_RGTC2_EXT,
13
+ GL_COMPRESSED_RED_RGTC1_EXT,
14
+ GL_COMPRESSED_RGB_ATC_WEBGL,
15
+ GL_COMPRESSED_RGB_ETC1_WEBGL,
16
+ GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG,
17
+ GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
18
+ GL_COMPRESSED_RGBA8_ETC2_EAC,
19
+ GL_COMPRESSED_RGBA_ASTC_4x4_KHR,
20
+ GL_COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL,
21
+ GL_COMPRESSED_RGBA_BPTC_UNORM_EXT,
22
+ GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,
23
+ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
24
+ GL_RGB565,
25
+ GL_RGBA4,
26
+ GL_RGBA8
27
+ } from '../gl-extensions';
28
+ import {detectSupportedTextureFormats} from '../utils/detect-supported-texture-formats';
10
29
  import {isKTX} from './parse-ktx';
11
30
 
12
31
  // TODO - circular type import
@@ -34,60 +53,151 @@ export type BasisFormat =
34
53
  type BasisOutputOptions = {
35
54
  basisFormat: number;
36
55
  compressed: boolean;
37
- format?: number;
56
+ format?: GLTextureFormat;
57
+ textureFormat?: TextureFormat;
38
58
  };
39
59
 
40
- const OutputFormat: Record<string, BasisOutputOptions> = {
60
+ let basisTranscodingLock: Promise<void> = Promise.resolve();
61
+
62
+ export const BASIS_FORMAT_TO_OUTPUT_OPTIONS: Record<BasisFormat, BasisOutputOptions> = {
41
63
  etc1: {
42
64
  basisFormat: 0,
43
65
  compressed: true,
44
- format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_ETC1_WEBGL
66
+ format: GL_COMPRESSED_RGB_ETC1_WEBGL,
67
+ textureFormat: 'etc1-rgb-unorm-webgl'
68
+ },
69
+ etc2: {
70
+ basisFormat: 1,
71
+ compressed: true,
72
+ format: GL_COMPRESSED_RGBA8_ETC2_EAC,
73
+ textureFormat: 'etc2-rgba8unorm'
45
74
  },
46
- etc2: {basisFormat: 1, compressed: true},
47
75
  bc1: {
48
76
  basisFormat: 2,
49
77
  compressed: true,
50
- format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_S3TC_DXT1_EXT
78
+ format: GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
79
+ textureFormat: 'bc1-rgb-unorm-webgl'
51
80
  },
52
81
  bc3: {
53
82
  basisFormat: 3,
54
83
  compressed: true,
55
- format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_S3TC_DXT5_EXT
84
+ format: GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
85
+ textureFormat: 'bc3-rgba-unorm'
86
+ },
87
+ bc4: {
88
+ basisFormat: 4,
89
+ compressed: true,
90
+ format: GL_COMPRESSED_RED_RGTC1_EXT,
91
+ textureFormat: 'bc4-r-unorm'
92
+ },
93
+ bc5: {
94
+ basisFormat: 5,
95
+ compressed: true,
96
+ format: GL_COMPRESSED_RED_GREEN_RGTC2_EXT,
97
+ textureFormat: 'bc5-rg-unorm'
98
+ },
99
+ 'bc7-m6-opaque-only': {
100
+ basisFormat: 6,
101
+ compressed: true,
102
+ format: GL_COMPRESSED_RGBA_BPTC_UNORM_EXT,
103
+ textureFormat: 'bc7-rgba-unorm'
104
+ },
105
+ 'bc7-m5': {
106
+ basisFormat: 7,
107
+ compressed: true,
108
+ format: GL_COMPRESSED_RGBA_BPTC_UNORM_EXT,
109
+ textureFormat: 'bc7-rgba-unorm'
56
110
  },
57
- bc4: {basisFormat: 4, compressed: true},
58
- bc5: {basisFormat: 5, compressed: true},
59
- 'bc7-m6-opaque-only': {basisFormat: 6, compressed: true},
60
- 'bc7-m5': {basisFormat: 7, compressed: true},
61
111
  'pvrtc1-4-rgb': {
62
112
  basisFormat: 8,
63
113
  compressed: true,
64
- format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_PVRTC_4BPPV1_IMG
114
+ format: GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG,
115
+ textureFormat: 'pvrtc-rgb4unorm-webgl'
65
116
  },
66
117
  'pvrtc1-4-rgba': {
67
118
  basisFormat: 9,
68
119
  compressed: true,
69
- format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
120
+ format: GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,
121
+ textureFormat: 'pvrtc-rgba4unorm-webgl'
70
122
  },
71
123
  'astc-4x4': {
72
124
  basisFormat: 10,
73
125
  compressed: true,
74
- format: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_4X4_KHR
126
+ format: GL_COMPRESSED_RGBA_ASTC_4x4_KHR,
127
+ textureFormat: 'astc-4x4-unorm'
128
+ },
129
+ 'atc-rgb': {
130
+ basisFormat: 11,
131
+ compressed: true,
132
+ format: GL_COMPRESSED_RGB_ATC_WEBGL,
133
+ textureFormat: 'atc-rgb-unorm-webgl'
134
+ },
135
+ 'atc-rgba-interpolated-alpha': {
136
+ basisFormat: 12,
137
+ compressed: true,
138
+ format: GL_COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL,
139
+ textureFormat: 'atc-rgbai-unorm-webgl'
75
140
  },
76
- 'atc-rgb': {basisFormat: 11, compressed: true},
77
- 'atc-rgba-interpolated-alpha': {basisFormat: 12, compressed: true},
78
- rgba32: {basisFormat: 13, compressed: false},
79
- rgb565: {basisFormat: 14, compressed: false},
80
- bgr565: {basisFormat: 15, compressed: false},
81
- rgba4444: {basisFormat: 16, compressed: false}
141
+ rgba32: {
142
+ basisFormat: 13,
143
+ compressed: false,
144
+ format: GL_RGBA8,
145
+ textureFormat: 'rgba8unorm'
146
+ },
147
+ rgb565: {
148
+ basisFormat: 14,
149
+ compressed: false,
150
+ format: GL_RGB565,
151
+ textureFormat: 'rgb565unorm-webgl'
152
+ },
153
+ bgr565: {
154
+ basisFormat: 15,
155
+ compressed: false,
156
+ format: GL_RGB565,
157
+ textureFormat: 'rgb565unorm-webgl'
158
+ },
159
+ rgba4444: {
160
+ basisFormat: 16,
161
+ compressed: false,
162
+ format: GL_RGBA4,
163
+ textureFormat: 'rgba4unorm-webgl'
164
+ }
82
165
  };
83
166
 
167
+ export const BASIS_FORMATS = Object.freeze(
168
+ Object.keys(BASIS_FORMAT_TO_OUTPUT_OPTIONS) as BasisFormat[]
169
+ );
170
+
84
171
  export type ParseBasisOptions = {
85
172
  format: 'auto' | BasisFormat | {alpha: BasisFormat; noAlpha: BasisFormat};
86
- libraryPath?: string;
87
173
  containerFormat: 'auto' | 'ktx2' | 'basis';
88
174
  module: 'transcoder' | 'encoder';
175
+ supportedTextureFormats?: TextureFormat[];
89
176
  };
90
177
 
178
+ /**
179
+ * Serializes access to the Basis transcoder so concurrent callers do not enter the non-reentrant
180
+ * decoder path at the same time.
181
+ * @param transcode - Transcode operation to run with exclusive access.
182
+ * @returns The transcode result.
183
+ */
184
+ export async function withBasisTranscodingLock<T>(transcode: () => Promise<T> | T): Promise<T> {
185
+ const previousLock = basisTranscodingLock;
186
+ let releaseLock!: () => void;
187
+
188
+ basisTranscodingLock = new Promise((resolve) => {
189
+ releaseLock = resolve;
190
+ });
191
+
192
+ await previousLock;
193
+
194
+ try {
195
+ return await transcode();
196
+ } finally {
197
+ releaseLock();
198
+ }
199
+ }
200
+
91
201
  /**
92
202
  * parse data with a Binomial Basis_Universal module
93
203
  * @param data
@@ -99,29 +209,33 @@ export async function parseBasis(
99
209
  data: ArrayBuffer,
100
210
  options: BasisLoaderOptions = {}
101
211
  ): Promise<TextureLevel[][]> {
102
- if (!options.basis?.containerFormat || options.basis.containerFormat === 'auto') {
103
- if (isKTX(data)) {
104
- const fileConstructors = await loadBasisEncoderModule(options?.core || {});
105
- return parseKTX2File(fileConstructors.KTX2File, data, options);
106
- }
107
- const {BasisFile} = await loadBasisTranscoderModule(options?.core || {});
108
- return parseBasisFile(BasisFile, data, options);
109
- }
110
- switch (options.basis.module) {
111
- case 'encoder':
112
- const fileConstructors = await loadBasisEncoderModule(options?.core || {});
113
- switch (options.basis.containerFormat) {
114
- case 'ktx2':
115
- return parseKTX2File(fileConstructors.KTX2File, data, options);
116
- case 'basis':
117
- default:
118
- return parseBasisFile(fileConstructors.BasisFile, data, options);
212
+ const loadLibraryOptions = extractLoadLibraryOptions(options);
213
+
214
+ return await withBasisTranscodingLock(async () => {
215
+ if (!options.basis?.containerFormat || options.basis.containerFormat === 'auto') {
216
+ if (isKTX(data)) {
217
+ const fileConstructors = await loadBasisEncoderModule(loadLibraryOptions);
218
+ return parseKTX2File(fileConstructors.KTX2File, data, options);
119
219
  }
120
- case 'transcoder':
121
- default:
122
- const {BasisFile} = await loadBasisTranscoderModule(options.core || {});
220
+ const {BasisFile} = await loadBasisTranscoderModule(loadLibraryOptions);
123
221
  return parseBasisFile(BasisFile, data, options);
124
- }
222
+ }
223
+ switch (options.basis.module) {
224
+ case 'encoder':
225
+ const fileConstructors = await loadBasisEncoderModule(loadLibraryOptions);
226
+ switch (options.basis.containerFormat) {
227
+ case 'ktx2':
228
+ return parseKTX2File(fileConstructors.KTX2File, data, options);
229
+ case 'basis':
230
+ default:
231
+ return parseBasisFile(fileConstructors.BasisFile, data, options);
232
+ }
233
+ case 'transcoder':
234
+ default:
235
+ const {BasisFile} = await loadBasisTranscoderModule(loadLibraryOptions);
236
+ return parseBasisFile(BasisFile, data, options);
237
+ }
238
+ });
125
239
  }
126
240
 
127
241
  /**
@@ -185,7 +299,7 @@ function transcodeImage(
185
299
  const hasAlpha = basisFile.getHasAlpha(/* imageIndex, levelIndex */);
186
300
 
187
301
  // Check options for output format etc
188
- const {compressed, format, basisFormat} = getBasisOptions(options, hasAlpha);
302
+ const {compressed, format, basisFormat, textureFormat} = getBasisOptions(options, hasAlpha);
189
303
 
190
304
  const decodedSize = basisFile.getImageTranscodedSizeInBytes(imageIndex, levelIndex, basisFormat);
191
305
  const decodedData = new Uint8Array(decodedSize);
@@ -196,11 +310,13 @@ function transcodeImage(
196
310
 
197
311
  return {
198
312
  // standard loaders.gl image category payload
313
+ shape: 'texture-level',
199
314
  width,
200
315
  height,
201
316
  data: decodedData,
202
317
  compressed,
203
- format,
318
+ ...(format !== undefined ? {format} : {}),
319
+ ...(textureFormat !== undefined ? {textureFormat} : {}),
204
320
 
205
321
  // Additional fields
206
322
  // Add levelSize field.
@@ -251,7 +367,7 @@ function transcodeKTX2Image(
251
367
  const {alphaFlag, height, width} = ktx2File.getImageLevelInfo(levelIndex, 0, 0);
252
368
 
253
369
  // Check options for output format etc
254
- const {compressed, format, basisFormat} = getBasisOptions(options, alphaFlag);
370
+ const {compressed, format, basisFormat, textureFormat} = getBasisOptions(options, alphaFlag);
255
371
 
256
372
  const decodedSize = ktx2File.getImageTranscodedSizeInBytes(
257
373
  levelIndex,
@@ -278,15 +394,17 @@ function transcodeKTX2Image(
278
394
 
279
395
  return {
280
396
  // standard loaders.gl image category payload
397
+ shape: 'texture-level',
281
398
  width,
282
399
  height,
283
400
  data: decodedData,
284
401
  compressed,
402
+ ...(format !== undefined ? {format} : {}),
403
+ ...(textureFormat !== undefined ? {textureFormat} : {}),
285
404
 
286
405
  // Additional fields
287
406
  levelSize: decodedSize,
288
- hasAlpha: alphaFlag,
289
- format
407
+ hasAlpha: alphaFlag
290
408
  };
291
409
  }
292
410
 
@@ -297,16 +415,21 @@ function transcodeKTX2Image(
297
415
  * @returns BasisFormat data
298
416
  */
299
417
  function getBasisOptions(options: BasisLoaderOptions, hasAlpha: boolean): BasisOutputOptions {
300
- // TODO - any
301
- let format: any = options.basis?.format;
418
+ let format = options.basis?.format || 'auto';
302
419
  if (format === 'auto') {
303
- format = selectSupportedBasisFormat();
420
+ format = options.basis?.supportedTextureFormats
421
+ ? selectSupportedBasisFormat(options.basis.supportedTextureFormats)
422
+ : selectSupportedBasisFormat();
304
423
  }
305
424
  if (typeof format === 'object') {
306
425
  format = hasAlpha ? format.alpha : format.noAlpha;
307
426
  }
308
- format = format.toLowerCase();
309
- return OutputFormat[format];
427
+ const normalizedFormat = format.toLowerCase() as BasisFormat;
428
+ const basisOutputOptions = BASIS_FORMAT_TO_OUTPUT_OPTIONS[normalizedFormat];
429
+ if (!basisOutputOptions) {
430
+ throw new Error(`Unknown Basis format ${format}`);
431
+ }
432
+ return basisOutputOptions;
310
433
  }
311
434
 
312
435
  /**
@@ -318,24 +441,165 @@ export function selectSupportedBasisFormat():
318
441
  | {
319
442
  alpha: BasisFormat;
320
443
  noAlpha: BasisFormat;
321
- } {
322
- const supportedFormats = getSupportedGPUTextureFormats();
323
- if (supportedFormats.has('astc')) {
444
+ };
445
+ export function selectSupportedBasisFormat(supportedTextureFormats?: Iterable<TextureFormat>):
446
+ | BasisFormat
447
+ | {
448
+ alpha: BasisFormat;
449
+ noAlpha: BasisFormat;
450
+ };
451
+ export function selectSupportedBasisFormat(
452
+ supportedTextureFormats: Iterable<TextureFormat> = detectSupportedTextureFormats()
453
+ ): BasisFormat | {alpha: BasisFormat; noAlpha: BasisFormat} {
454
+ const textureFormats = new Set(supportedTextureFormats);
455
+
456
+ if (hasSupportedTextureFormat(textureFormats, ['astc-4x4-unorm', 'astc-4x4-unorm-srgb'])) {
324
457
  return 'astc-4x4';
325
- } else if (supportedFormats.has('dxt')) {
458
+ } else if (hasSupportedTextureFormat(textureFormats, ['bc7-rgba-unorm', 'bc7-rgba-unorm-srgb'])) {
459
+ return {
460
+ alpha: 'bc7-m5',
461
+ noAlpha: 'bc7-m6-opaque-only'
462
+ };
463
+ } else if (
464
+ hasSupportedTextureFormat(textureFormats, [
465
+ 'bc1-rgb-unorm-webgl',
466
+ 'bc1-rgb-unorm-srgb-webgl',
467
+ 'bc1-rgba-unorm',
468
+ 'bc1-rgba-unorm-srgb',
469
+ 'bc2-rgba-unorm',
470
+ 'bc2-rgba-unorm-srgb',
471
+ 'bc3-rgba-unorm',
472
+ 'bc3-rgba-unorm-srgb'
473
+ ])
474
+ ) {
326
475
  return {
327
476
  alpha: 'bc3',
328
477
  noAlpha: 'bc1'
329
478
  };
330
- } else if (supportedFormats.has('pvrtc')) {
479
+ } else if (
480
+ hasSupportedTextureFormat(textureFormats, [
481
+ 'pvrtc-rgb4unorm-webgl',
482
+ 'pvrtc-rgba4unorm-webgl',
483
+ 'pvrtc-rgb2unorm-webgl',
484
+ 'pvrtc-rgba2unorm-webgl'
485
+ ])
486
+ ) {
331
487
  return {
332
488
  alpha: 'pvrtc1-4-rgba',
333
489
  noAlpha: 'pvrtc1-4-rgb'
334
490
  };
335
- } else if (supportedFormats.has('etc1')) {
336
- return 'etc1';
337
- } else if (supportedFormats.has('etc2')) {
491
+ } else if (
492
+ hasSupportedTextureFormat(textureFormats, [
493
+ 'etc2-rgb8unorm',
494
+ 'etc2-rgb8unorm-srgb',
495
+ 'etc2-rgb8a1unorm',
496
+ 'etc2-rgb8a1unorm-srgb',
497
+ 'etc2-rgba8unorm',
498
+ 'etc2-rgba8unorm-srgb',
499
+ 'eac-r11unorm',
500
+ 'eac-r11snorm',
501
+ 'eac-rg11unorm',
502
+ 'eac-rg11snorm'
503
+ ])
504
+ ) {
338
505
  return 'etc2';
506
+ } else if (textureFormats.has('etc1-rgb-unorm-webgl')) {
507
+ return 'etc1';
508
+ } else if (
509
+ hasSupportedTextureFormat(textureFormats, [
510
+ 'atc-rgb-unorm-webgl',
511
+ 'atc-rgba-unorm-webgl',
512
+ 'atc-rgbai-unorm-webgl'
513
+ ])
514
+ ) {
515
+ return {
516
+ alpha: 'atc-rgba-interpolated-alpha',
517
+ noAlpha: 'atc-rgb'
518
+ };
339
519
  }
340
520
  return 'rgb565';
341
521
  }
522
+
523
+ export function getSupportedBasisFormats(
524
+ supportedTextureFormats: Iterable<TextureFormat> = detectSupportedTextureFormats()
525
+ ): BasisFormat[] {
526
+ const textureFormats = new Set(supportedTextureFormats);
527
+ const basisFormats: BasisFormat[] = [];
528
+
529
+ if (hasSupportedTextureFormat(textureFormats, ['astc-4x4-unorm', 'astc-4x4-unorm-srgb'])) {
530
+ basisFormats.push('astc-4x4');
531
+ }
532
+ if (
533
+ hasSupportedTextureFormat(textureFormats, [
534
+ 'bc1-rgb-unorm-webgl',
535
+ 'bc1-rgb-unorm-srgb-webgl',
536
+ 'bc1-rgba-unorm',
537
+ 'bc1-rgba-unorm-srgb',
538
+ 'bc2-rgba-unorm',
539
+ 'bc2-rgba-unorm-srgb',
540
+ 'bc3-rgba-unorm',
541
+ 'bc3-rgba-unorm-srgb'
542
+ ])
543
+ ) {
544
+ basisFormats.push('bc1', 'bc3');
545
+ }
546
+ if (hasSupportedTextureFormat(textureFormats, ['bc4-r-unorm', 'bc4-r-snorm'])) {
547
+ basisFormats.push('bc4');
548
+ }
549
+ if (hasSupportedTextureFormat(textureFormats, ['bc5-rg-unorm', 'bc5-rg-snorm'])) {
550
+ basisFormats.push('bc5');
551
+ }
552
+ if (hasSupportedTextureFormat(textureFormats, ['bc7-rgba-unorm', 'bc7-rgba-unorm-srgb'])) {
553
+ basisFormats.push('bc7-m5', 'bc7-m6-opaque-only');
554
+ }
555
+ if (
556
+ hasSupportedTextureFormat(textureFormats, [
557
+ 'pvrtc-rgb4unorm-webgl',
558
+ 'pvrtc-rgba4unorm-webgl',
559
+ 'pvrtc-rgb2unorm-webgl',
560
+ 'pvrtc-rgba2unorm-webgl'
561
+ ])
562
+ ) {
563
+ basisFormats.push('pvrtc1-4-rgb', 'pvrtc1-4-rgba');
564
+ }
565
+ if (
566
+ hasSupportedTextureFormat(textureFormats, [
567
+ 'etc2-rgb8unorm',
568
+ 'etc2-rgb8unorm-srgb',
569
+ 'etc2-rgb8a1unorm',
570
+ 'etc2-rgb8a1unorm-srgb',
571
+ 'etc2-rgba8unorm',
572
+ 'etc2-rgba8unorm-srgb',
573
+ 'eac-r11unorm',
574
+ 'eac-r11snorm',
575
+ 'eac-rg11unorm',
576
+ 'eac-rg11snorm'
577
+ ])
578
+ ) {
579
+ basisFormats.push('etc2');
580
+ }
581
+ if (textureFormats.has('etc1-rgb-unorm-webgl')) {
582
+ basisFormats.push('etc1');
583
+ }
584
+ if (
585
+ hasSupportedTextureFormat(textureFormats, [
586
+ 'atc-rgb-unorm-webgl',
587
+ 'atc-rgba-unorm-webgl',
588
+ 'atc-rgbai-unorm-webgl'
589
+ ])
590
+ ) {
591
+ basisFormats.push('atc-rgb', 'atc-rgba-interpolated-alpha');
592
+ }
593
+
594
+ basisFormats.push('rgba32', 'rgb565', 'bgr565', 'rgba4444');
595
+ return basisFormats;
596
+ }
597
+
598
+ function hasSupportedTextureFormat(
599
+ supportedTextureFormats: Set<TextureFormat>,
600
+ candidateTextureFormats: TextureFormat[]
601
+ ): boolean {
602
+ return candidateTextureFormats.some((textureFormat) =>
603
+ supportedTextureFormats.has(textureFormat)
604
+ );
605
+ }
@@ -2,10 +2,10 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import type {TextureLevel} from '@loaders.gl/schema';
5
+ import type {TextureFormat, TextureLevel} from '@loaders.gl/schema';
6
6
  import {loadCrunchModule} from './crunch-module-loader';
7
- import {GL_EXTENSIONS_CONSTANTS} from '../gl-extensions';
8
7
  import {assert} from '@loaders.gl/loader-utils';
8
+ import {extractLoadLibraryOptions} from '@loaders.gl/worker-utils';
9
9
  import {getDxt1LevelSize, getDxtXLevelSize} from './parse-dds';
10
10
  import {extractMipmapImages} from '../utils/extract-mipmap-images';
11
11
 
@@ -22,17 +22,20 @@ const CRN_FORMAT = {
22
22
  };
23
23
 
24
24
  /** Mapping of Crunch formats to DXT formats. */
25
- const DXT_FORMAT_MAP = {
25
+ const DXT_FORMAT_MAP: Record<
26
+ number,
27
+ {textureFormat: TextureFormat; sizeFunction: (width: number, height: number) => number}
28
+ > = {
26
29
  [CRN_FORMAT.cCRNFmtDXT1]: {
27
- pixelFormat: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_S3TC_DXT1_EXT,
30
+ textureFormat: 'bc1-rgb-unorm-webgl',
28
31
  sizeFunction: getDxt1LevelSize
29
32
  },
30
33
  [CRN_FORMAT.cCRNFmtDXT3]: {
31
- pixelFormat: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_S3TC_DXT3_EXT,
34
+ textureFormat: 'bc2-rgba-unorm',
32
35
  sizeFunction: getDxtXLevelSize
33
36
  },
34
37
  [CRN_FORMAT.cCRNFmtDXT5]: {
35
- pixelFormat: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_S3TC_DXT5_EXT,
38
+ textureFormat: 'bc3-rgba-unorm',
36
39
  sizeFunction: getDxtXLevelSize
37
40
  }
38
41
  };
@@ -47,7 +50,7 @@ let dst: number;
47
50
  * @returns Promise of Array of the texture levels
48
51
  */
49
52
  export async function parseCrunch(data, options: any): Promise<TextureLevel[]> {
50
- const crunchModule = await loadCrunchModule(options);
53
+ const crunchModule = await loadCrunchModule(extractLoadLibraryOptions(options));
51
54
 
52
55
  // Copy the contents of the arrayBuffer into emscriptens heap.
53
56
  const srcSize = data.byteLength;
@@ -95,7 +98,7 @@ export async function parseCrunch(data, options: any): Promise<TextureLevel[]> {
95
98
  width,
96
99
  height,
97
100
  sizeFunction,
98
- internalFormat: DXT_FORMAT_MAP[format].pixelFormat
101
+ textureFormat: DXT_FORMAT_MAP[format].textureFormat
99
102
  });
100
103
  }
101
104
 
@@ -2,9 +2,8 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import type {TextureLevel} from '@loaders.gl/schema';
5
+ import type {TextureFormat, TextureLevel} from '@loaders.gl/schema';
6
6
  import {assert} from '@loaders.gl/loader-utils';
7
- import {GL_EXTENSIONS_CONSTANTS} from '../gl-extensions';
8
7
  import {extractMipmapImages} from '../utils/extract-mipmap-images';
9
8
 
10
9
  const DDS_CONSTANTS = {
@@ -22,13 +21,13 @@ const DDS_CONSTANTS = {
22
21
  DDPF_FOURCC: 0x4
23
22
  };
24
23
 
25
- const DDS_PIXEL_FORMATS: Record<string, number> = {
26
- DXT1: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_S3TC_DXT1_EXT,
27
- DXT3: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_S3TC_DXT3_EXT,
28
- DXT5: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_S3TC_DXT5_EXT,
29
- 'ATC ': GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_ATC_WEBGL,
30
- ATCA: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL,
31
- ATCI: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL
24
+ const DDS_TEXTURE_FORMATS: Record<string, TextureFormat> = {
25
+ DXT1: 'bc1-rgb-unorm-webgl',
26
+ DXT3: 'bc2-rgba-unorm',
27
+ DXT5: 'bc3-rgba-unorm',
28
+ 'ATC ': 'atc-rgb-unorm-webgl',
29
+ ATCA: 'atc-rgba-unorm-webgl',
30
+ ATCI: 'atc-rgbai-unorm-webgl'
32
31
  };
33
32
 
34
33
  const getATCLevelSize = getDxt1LevelSize;
@@ -68,9 +67,9 @@ export function parseDDS(data: ArrayBuffer): TextureLevel[] {
68
67
  'DDS: Unsupported format, must contain a FourCC code'
69
68
  );
70
69
  const fourCC = int32ToFourCC(pixelFormatNumber);
71
- const internalFormat = DDS_PIXEL_FORMATS[fourCC];
70
+ const textureFormat = DDS_TEXTURE_FORMATS[fourCC];
72
71
  const sizeFunction = DDS_SIZE_FUNCTIONS[fourCC];
73
- assert(internalFormat && sizeFunction, `DDS: Unknown pixel format ${pixelFormatNumber}`);
72
+ assert(textureFormat && sizeFunction, `DDS: Unknown pixel format ${pixelFormatNumber}`);
74
73
 
75
74
  let mipMapLevels = 1;
76
75
  if (header[DDS_CONSTANTS.HEADER_FLAGS_INDEX] & DDS_CONSTANTS.DDSD_MIPMAPCOUNT) {
@@ -86,7 +85,7 @@ export function parseDDS(data: ArrayBuffer): TextureLevel[] {
86
85
  width,
87
86
  height,
88
87
  sizeFunction,
89
- internalFormat
88
+ textureFormat
90
89
  });
91
90
  }
92
91