mscTranscoder.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import { Transcoder, sourceTextureFormat, transcodeTarget } from '../transcoder';
  2. import { KTX2FileReader, IKTX2_ImageDesc } from '../ktx2FileReader';
  3. import { WASMMemoryManager } from '../wasmMemoryManager';
  4. declare var MSC_TRANSCODER: any;
  5. declare function importScripts(...urls: string[]): void;
  6. /**
  7. * @hidden
  8. */
  9. export class MSCTranscoder extends Transcoder {
  10. /**
  11. * URL to use when loading the MSC transcoder
  12. */
  13. public static JSModuleURL = "https://preview.babylonjs.com/ktx2Transcoders/msc_basis_transcoder.js";
  14. /**
  15. * URL to use when loading the wasm module for the transcoder
  16. */
  17. public static WasmModuleURL = "https://preview.babylonjs.com/ktx2Transcoders/msc_basis_transcoder.wasm";
  18. public static UseFromWorkerThread = true;
  19. public static Name = "MSCTranscoder";
  20. public getName(): string {
  21. return MSCTranscoder.Name;
  22. }
  23. private _mscBasisTranscoderPromise: Promise<void>;
  24. private _mscBasisModule: any;
  25. private _getMSCBasisTranscoder(): Promise<void> {
  26. if (this._mscBasisTranscoderPromise) {
  27. return this._mscBasisTranscoderPromise;
  28. }
  29. this._mscBasisTranscoderPromise = WASMMemoryManager.LoadWASM(MSCTranscoder.WasmModuleURL).then((wasmBinary) => {
  30. if (MSCTranscoder.UseFromWorkerThread) {
  31. importScripts(MSCTranscoder.JSModuleURL);
  32. }
  33. return new Promise((resolve) => {
  34. MSC_TRANSCODER({ wasmBinary }).then((basisModule: any) => {
  35. basisModule.initTranscoders();
  36. this._mscBasisModule = basisModule;
  37. resolve();
  38. });
  39. });
  40. });
  41. return this._mscBasisTranscoderPromise;
  42. }
  43. public static CanTranscode(src: sourceTextureFormat, dst: transcodeTarget, isInGammaSpace: boolean): boolean {
  44. return true;
  45. }
  46. public transcode(src: sourceTextureFormat, dst: transcodeTarget, level: number, width: number, height: number, uncompressedByteLength: number, ktx2Reader: KTX2FileReader, imageDesc: IKTX2_ImageDesc | null, encodedData: Uint8Array): Promise<Uint8Array | null> {
  47. const isVideo = false;
  48. return this._getMSCBasisTranscoder().then(() => {
  49. const basisModule = this._mscBasisModule;
  50. const transcoder = src === sourceTextureFormat.UASTC4x4 ? new basisModule.UastcImageTranscoder() : new basisModule.BasisLzEtc1sImageTranscoder();
  51. const texFormat = src === sourceTextureFormat.UASTC4x4 ? basisModule.TextureFormat.UASTC4x4 : basisModule.TextureFormat.ETC1S;
  52. const imageInfo = new basisModule.ImageInfo(texFormat, width, height, level);
  53. const targetFormat = basisModule.TranscodeTarget[transcodeTarget[dst]]; // works because the labels of the sourceTextureFormat enum are the same than the property names used in TranscodeTarget!
  54. if (!basisModule.isFormatSupported(targetFormat, texFormat)) {
  55. throw new Error(`MSCTranscoder: Transcoding from "${sourceTextureFormat[src]}" to "${transcodeTarget[dst]}" not supported by current transcoder build.`);
  56. }
  57. let result: any;
  58. if (src === sourceTextureFormat.ETC1S) {
  59. const sgd = ktx2Reader.supercompressionGlobalData;
  60. transcoder.decodePalettes(sgd.endpointCount, sgd.endpointsData, sgd.selectorCount, sgd.selectorsData);
  61. transcoder.decodeTables(sgd.tablesData);
  62. imageInfo.flags = imageDesc!.imageFlags;
  63. imageInfo.rgbByteOffset = 0;
  64. imageInfo.rgbByteLength = imageDesc!.rgbSliceByteLength;
  65. imageInfo.alphaByteOffset = imageDesc!.alphaSliceByteOffset > 0 ? imageDesc!.rgbSliceByteLength : 0;
  66. imageInfo.alphaByteLength = imageDesc!.alphaSliceByteLength;
  67. result = transcoder.transcodeImage(targetFormat, encodedData, imageInfo, 0, isVideo);
  68. } else {
  69. imageInfo.flags = 0;
  70. imageInfo.rgbByteOffset = 0;
  71. imageInfo.rgbByteLength = uncompressedByteLength;
  72. imageInfo.alphaByteOffset = 0;
  73. imageInfo.alphaByteLength = 0;
  74. result = transcoder.transcodeImage(targetFormat, encodedData, imageInfo, 0, ktx2Reader.hasAlpha, isVideo);
  75. }
  76. if (result && result.transcodedImage !== undefined) {
  77. const textureData = result.transcodedImage.get_typed_memory_view().slice();
  78. result.transcodedImage.delete();
  79. return textureData;
  80. }
  81. return null;
  82. });
  83. }
  84. }