"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const three_module = require("../../../build/three.module.js");
const WorkerPool = require("../utils/WorkerPool.js");
const ktxParse_module = require("../libs/ktx-parse.module.js");
const zstddec_module = require("../libs/zstddec.module.js");
const _taskCache = /* @__PURE__ */ new WeakMap();
let _activeLoaders = 0;
let _zstd;
class KTX2Loader extends three_module.Loader {
  constructor(manager) {
    super(manager);
    this.transcoderPath = "";
    this.transcoderBinary = null;
    this.transcoderPending = null;
    this.workerPool = new WorkerPool.WorkerPool();
    this.workerSourceURL = "";
    this.workerConfig = null;
    if (typeof MSC_TRANSCODER !== "undefined") {
      console.warn(
        'THREE.KTX2Loader: Please update to latest "basis_transcoder". "msc_basis_transcoder" is no longer supported in three.js r125+.'
      );
    }
  }
  setTranscoderPath(path) {
    this.transcoderPath = path;
    return this;
  }
  setWorkerLimit(num) {
    this.workerPool.setWorkerLimit(num);
    return this;
  }
  detectSupport(renderer) {
    if (renderer.isWebGPURenderer === true) {
      this.workerConfig = {
        astcSupported: renderer.hasFeature("texture-compression-astc"),
        etc1Supported: false,
        etc2Supported: renderer.hasFeature("texture-compression-etc2"),
        dxtSupported: renderer.hasFeature("texture-compression-bc"),
        bptcSupported: false,
        pvrtcSupported: false
      };
    } else {
      this.workerConfig = {
        astcSupported: renderer.extensions.has("WEBGL_compressed_texture_astc"),
        etc1Supported: renderer.extensions.has("WEBGL_compressed_texture_etc1"),
        etc2Supported: renderer.extensions.has("WEBGL_compressed_texture_etc"),
        dxtSupported: renderer.extensions.has("WEBGL_compressed_texture_s3tc"),
        bptcSupported: renderer.extensions.has("EXT_texture_compression_bptc"),
        pvrtcSupported: renderer.extensions.has("WEBGL_compressed_texture_pvrtc") || renderer.extensions.has("WEBKIT_WEBGL_compressed_texture_pvrtc")
      };
      if (renderer.capabilities.isWebGL2) {
        this.workerConfig.etc1Supported = false;
      }
    }
    return this;
  }
  init() {
    if (!this.transcoderPending) {
      const jsLoader = new three_module.FileLoader(this.manager);
      jsLoader.setPath(this.transcoderPath);
      jsLoader.setWithCredentials(this.withCredentials);
      const jsContent = jsLoader.loadAsync("basis_transcoder.js");
      const binaryLoader = new three_module.FileLoader(this.manager);
      binaryLoader.setPath(this.transcoderPath);
      binaryLoader.setResponseType("arraybuffer");
      binaryLoader.setWithCredentials(this.withCredentials);
      const binaryContent = binaryLoader.loadAsync("basis_transcoder.wasm");
      this.transcoderPending = Promise.all([jsContent, binaryContent]).then(([jsContent2, binaryContent2]) => {
        const fn = KTX2Loader.BasisWorker.toString();
        const body = [
          "/* constants */",
          "let _EngineFormat = " + JSON.stringify(KTX2Loader.EngineFormat),
          "let _TranscoderFormat = " + JSON.stringify(KTX2Loader.TranscoderFormat),
          "let _BasisFormat = " + JSON.stringify(KTX2Loader.BasisFormat),
          "/* basis_transcoder.js */",
          jsContent2,
          "/* worker */",
          fn.substring(fn.indexOf("{") + 1, fn.lastIndexOf("}"))
        ].join("\n");
        this.workerSourceURL = URL.createObjectURL(new Blob([body]));
        this.transcoderBinary = binaryContent2;
        this.workerPool.setWorkerCreator(() => {
          const worker = new Worker(this.workerSourceURL);
          const transcoderBinary = this.transcoderBinary.slice(0);
          worker.postMessage({ type: "init", config: this.workerConfig, transcoderBinary }, [transcoderBinary]);
          return worker;
        });
      });
      if (_activeLoaders > 0) {
        console.warn(
          "THREE.KTX2Loader: Multiple active KTX2 loaders may cause performance issues. Use a single KTX2Loader instance, or call .dispose() on old instances."
        );
      }
      _activeLoaders++;
    }
    return this.transcoderPending;
  }
  load(url, onLoad, onProgress, onError) {
    if (this.workerConfig === null) {
      throw new Error("THREE.KTX2Loader: Missing initialization with `.detectSupport( renderer )`.");
    }
    const loader = new three_module.FileLoader(this.manager);
    loader.setResponseType("arraybuffer");
    loader.setWithCredentials(this.withCredentials);
    loader.load(url, (buffer) => {
      if (_taskCache.has(buffer)) {
        const cachedTask = _taskCache.get(buffer);
        return cachedTask.promise.then(onLoad).catch(onError);
      }
      this._createTexture(buffer).then((texture) => onLoad ? onLoad(texture) : null).catch(onError);
    }, onProgress, onError);
  }
  _createTextureFrom(transcodeResult, container) {
    const { faces, width, height, format, type, error, dfdTransferFn, dfdFlags } = transcodeResult;
    if (type === "error")
      return Promise.reject(error);
    let texture;
    if (container.faceCount === 6) {
      texture = new three_module.CompressedTexture();
      texture.image = faces;
      texture.format = format;
      texture.type = three_module.UnsignedByteType;
    } else {
      const mipmaps = faces[0].mipmaps;
      texture = container.layerCount > 1 ? new three_module.CompressedArrayTexture(mipmaps, width, height, container.layerCount, format, three_module.UnsignedByteType) : new three_module.CompressedTexture(mipmaps, width, height, format, three_module.UnsignedByteType);
    }
    texture.minFilter = faces[0].mipmaps.length === 1 ? three_module.LinearFilter : three_module.LinearMipmapLinearFilter;
    texture.magFilter = three_module.LinearFilter;
    texture.generateMipmaps = false;
    texture.needsUpdate = true;
    texture.colorSpace = dfdTransferFn === ktxParse_module.KHR_DF_TRANSFER_SRGB ? three_module.SRGBColorSpace : three_module.NoColorSpace;
    texture.premultiplyAlpha = !!(dfdFlags & ktxParse_module.KHR_DF_FLAG_ALPHA_PREMULTIPLIED);
    return texture;
  }
  /**
   * @param {ArrayBuffer} buffer
   * @param {object?} config
   * @return {Promise<CompressedTexture|CompressedArrayTexture|DataTexture|Data3DTexture>}
   */
  async _createTexture(buffer, config = {}) {
    const container = ktxParse_module.read(new Uint8Array(buffer));
    if (container.vkFormat !== ktxParse_module.VK_FORMAT_UNDEFINED) {
      const mipmaps = [];
      const pendings = [];
      for (let levelIndex = 0; levelIndex < container.levels.length; levelIndex++) {
        pendings.push(createDataTexture(container, levelIndex).then(function(dataTexture) {
          mipmaps[levelIndex] = dataTexture;
        }));
      }
      await Promise.all(pendings);
      const texture = mipmaps[0];
      texture.mipmaps = mipmaps.map((dt) => {
        return {
          data: dt.source.data,
          width: dt.source.data.width,
          height: dt.source.data.height,
          depth: dt.source.data.depth
        };
      });
      return texture;
    }
    const taskConfig = config;
    const texturePending = this.init().then(() => {
      return this.workerPool.postMessage({ type: "transcode", buffer, taskConfig }, [buffer]);
    }).then((e) => this._createTextureFrom(e.data, container));
    _taskCache.set(buffer, { promise: texturePending });
    return texturePending;
  }
  dispose() {
    this.workerPool.dispose();
    if (this.workerSourceURL)
      URL.revokeObjectURL(this.workerSourceURL);
    _activeLoaders--;
    return this;
  }
}
KTX2Loader.BasisFormat = {
  ETC1S: 0,
  UASTC_4x4: 1
};
KTX2Loader.TranscoderFormat = {
  ETC1: 0,
  ETC2: 1,
  BC1: 2,
  BC3: 3,
  BC4: 4,
  BC5: 5,
  BC7_M6_OPAQUE_ONLY: 6,
  BC7_M5: 7,
  PVRTC1_4_RGB: 8,
  PVRTC1_4_RGBA: 9,
  ASTC_4x4: 10,
  ATC_RGB: 11,
  ATC_RGBA_INTERPOLATED_ALPHA: 12,
  RGBA32: 13,
  RGB565: 14,
  BGR565: 15,
  RGBA4444: 16
};
KTX2Loader.EngineFormat = {
  RGBAFormat: three_module.RGBAFormat,
  RGBA_ASTC_4x4_Format: three_module.RGBA_ASTC_4x4_Format,
  RGBA_BPTC_Format: three_module.RGBA_BPTC_Format,
  RGBA_ETC2_EAC_Format: three_module.RGBA_ETC2_EAC_Format,
  RGBA_PVRTC_4BPPV1_Format: three_module.RGBA_PVRTC_4BPPV1_Format,
  RGBA_S3TC_DXT5_Format: three_module.RGBA_S3TC_DXT5_Format,
  RGB_ETC1_Format: three_module.RGB_ETC1_Format,
  RGB_ETC2_Format: three_module.RGB_ETC2_Format,
  RGB_PVRTC_4BPPV1_Format: three_module.RGB_PVRTC_4BPPV1_Format,
  RGB_S3TC_DXT1_Format: three_module.RGB_S3TC_DXT1_Format
};
KTX2Loader.BasisWorker = function() {
  let config;
  let transcoderPending;
  let BasisModule;
  const EngineFormat = _EngineFormat;
  const TranscoderFormat = _TranscoderFormat;
  const BasisFormat = _BasisFormat;
  self.addEventListener("message", function(e) {
    const message = e.data;
    switch (message.type) {
      case "init":
        config = message.config;
        init(message.transcoderBinary);
        break;
      case "transcode":
        transcoderPending.then(() => {
          try {
            const { faces, buffers, width, height, hasAlpha, format, dfdTransferFn, dfdFlags } = transcode(message.buffer);
            self.postMessage({ type: "transcode", id: message.id, faces, width, height, hasAlpha, format, dfdTransferFn, dfdFlags }, buffers);
          } catch (error) {
            console.error(error);
            self.postMessage({ type: "error", id: message.id, error: error.message });
          }
        });
        break;
    }
  });
  function init(wasmBinary) {
    transcoderPending = new Promise((resolve) => {
      BasisModule = { wasmBinary, onRuntimeInitialized: resolve };
      BASIS(BasisModule);
    }).then(() => {
      BasisModule.initializeBasis();
      if (BasisModule.KTX2File === void 0) {
        console.warn("THREE.KTX2Loader: Please update Basis Universal transcoder.");
      }
    });
  }
  function transcode(buffer) {
    const ktx2File = new BasisModule.KTX2File(new Uint8Array(buffer));
    function cleanup() {
      ktx2File.close();
      ktx2File.delete();
    }
    if (!ktx2File.isValid()) {
      cleanup();
      throw new Error("THREE.KTX2Loader:	Invalid or unsupported .ktx2 file");
    }
    const basisFormat = ktx2File.isUASTC() ? BasisFormat.UASTC_4x4 : BasisFormat.ETC1S;
    const width = ktx2File.getWidth();
    const height = ktx2File.getHeight();
    const layerCount = ktx2File.getLayers() || 1;
    const levelCount = ktx2File.getLevels();
    const faceCount = ktx2File.getFaces();
    const hasAlpha = ktx2File.getHasAlpha();
    const dfdTransferFn = ktx2File.getDFDTransferFunc();
    const dfdFlags = ktx2File.getDFDFlags();
    const { transcoderFormat, engineFormat } = getTranscoderFormat(basisFormat, width, height, hasAlpha);
    if (!width || !height || !levelCount) {
      cleanup();
      throw new Error("THREE.KTX2Loader:	Invalid texture");
    }
    if (!ktx2File.startTranscoding()) {
      cleanup();
      throw new Error("THREE.KTX2Loader: .startTranscoding failed");
    }
    const faces = [];
    const buffers = [];
    for (let face = 0; face < faceCount; face++) {
      const mipmaps = [];
      for (let mip = 0; mip < levelCount; mip++) {
        const layerMips = [];
        let mipWidth, mipHeight;
        for (let layer = 0; layer < layerCount; layer++) {
          const levelInfo = ktx2File.getImageLevelInfo(mip, layer, face);
          if (face === 0 && mip === 0 && layer === 0 && (levelInfo.origWidth % 4 !== 0 || levelInfo.origHeight % 4 !== 0)) {
            console.warn("THREE.KTX2Loader: ETC1S and UASTC textures should use multiple-of-four dimensions.");
          }
          if (levelCount > 1) {
            mipWidth = levelInfo.origWidth;
            mipHeight = levelInfo.origHeight;
          } else {
            mipWidth = levelInfo.width;
            mipHeight = levelInfo.height;
          }
          const dst = new Uint8Array(ktx2File.getImageTranscodedSizeInBytes(mip, layer, 0, transcoderFormat));
          const status = ktx2File.transcodeImage(dst, mip, layer, face, transcoderFormat, 0, -1, -1);
          if (!status) {
            cleanup();
            throw new Error("THREE.KTX2Loader: .transcodeImage failed.");
          }
          layerMips.push(dst);
        }
        const mipData = concat(layerMips);
        mipmaps.push({ data: mipData, width: mipWidth, height: mipHeight });
        buffers.push(mipData.buffer);
      }
      faces.push({ mipmaps, width, height, format: engineFormat });
    }
    cleanup();
    return { faces, buffers, width, height, hasAlpha, format: engineFormat, dfdTransferFn, dfdFlags };
  }
  const FORMAT_OPTIONS = [
    {
      if: "astcSupported",
      basisFormat: [BasisFormat.UASTC_4x4],
      transcoderFormat: [TranscoderFormat.ASTC_4x4, TranscoderFormat.ASTC_4x4],
      engineFormat: [EngineFormat.RGBA_ASTC_4x4_Format, EngineFormat.RGBA_ASTC_4x4_Format],
      priorityETC1S: Infinity,
      priorityUASTC: 1,
      needsPowerOfTwo: false
    },
    {
      if: "bptcSupported",
      basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
      transcoderFormat: [TranscoderFormat.BC7_M5, TranscoderFormat.BC7_M5],
      engineFormat: [EngineFormat.RGBA_BPTC_Format, EngineFormat.RGBA_BPTC_Format],
      priorityETC1S: 3,
      priorityUASTC: 2,
      needsPowerOfTwo: false
    },
    {
      if: "dxtSupported",
      basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
      transcoderFormat: [TranscoderFormat.BC1, TranscoderFormat.BC3],
      engineFormat: [EngineFormat.RGB_S3TC_DXT1_Format, EngineFormat.RGBA_S3TC_DXT5_Format],
      priorityETC1S: 4,
      priorityUASTC: 5,
      needsPowerOfTwo: false
    },
    {
      if: "etc2Supported",
      basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
      transcoderFormat: [TranscoderFormat.ETC1, TranscoderFormat.ETC2],
      engineFormat: [EngineFormat.RGB_ETC2_Format, EngineFormat.RGBA_ETC2_EAC_Format],
      priorityETC1S: 1,
      priorityUASTC: 3,
      needsPowerOfTwo: false
    },
    {
      if: "etc1Supported",
      basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
      transcoderFormat: [TranscoderFormat.ETC1],
      engineFormat: [EngineFormat.RGB_ETC1_Format],
      priorityETC1S: 2,
      priorityUASTC: 4,
      needsPowerOfTwo: false
    },
    {
      if: "pvrtcSupported",
      basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
      transcoderFormat: [TranscoderFormat.PVRTC1_4_RGB, TranscoderFormat.PVRTC1_4_RGBA],
      engineFormat: [EngineFormat.RGB_PVRTC_4BPPV1_Format, EngineFormat.RGBA_PVRTC_4BPPV1_Format],
      priorityETC1S: 5,
      priorityUASTC: 6,
      needsPowerOfTwo: true
    }
  ];
  const ETC1S_OPTIONS = FORMAT_OPTIONS.sort(function(a, b) {
    return a.priorityETC1S - b.priorityETC1S;
  });
  const UASTC_OPTIONS = FORMAT_OPTIONS.sort(function(a, b) {
    return a.priorityUASTC - b.priorityUASTC;
  });
  function getTranscoderFormat(basisFormat, width, height, hasAlpha) {
    let transcoderFormat;
    let engineFormat;
    const options = basisFormat === BasisFormat.ETC1S ? ETC1S_OPTIONS : UASTC_OPTIONS;
    for (let i = 0; i < options.length; i++) {
      const opt = options[i];
      if (!config[opt.if])
        continue;
      if (!opt.basisFormat.includes(basisFormat))
        continue;
      if (hasAlpha && opt.transcoderFormat.length < 2)
        continue;
      if (opt.needsPowerOfTwo && !(isPowerOfTwo(width) && isPowerOfTwo(height)))
        continue;
      transcoderFormat = opt.transcoderFormat[hasAlpha ? 1 : 0];
      engineFormat = opt.engineFormat[hasAlpha ? 1 : 0];
      return { transcoderFormat, engineFormat };
    }
    console.warn("THREE.KTX2Loader: No suitable compressed texture format found. Decoding to RGBA32.");
    transcoderFormat = TranscoderFormat.RGBA32;
    engineFormat = EngineFormat.RGBAFormat;
    return { transcoderFormat, engineFormat };
  }
  function isPowerOfTwo(value) {
    if (value <= 2)
      return true;
    return (value & value - 1) === 0 && value !== 0;
  }
  function concat(arrays) {
    if (arrays.length === 1)
      return arrays[0];
    let totalByteLength = 0;
    for (let i = 0; i < arrays.length; i++) {
      const array = arrays[i];
      totalByteLength += array.byteLength;
    }
    const result = new Uint8Array(totalByteLength);
    let byteOffset = 0;
    for (let i = 0; i < arrays.length; i++) {
      const array = arrays[i];
      result.set(array, byteOffset);
      byteOffset += array.byteLength;
    }
    return result;
  }
};
const FORMAT_MAP = {
  [ktxParse_module.VK_FORMAT_R32G32B32A32_SFLOAT]: three_module.RGBAFormat,
  [ktxParse_module.VK_FORMAT_R16G16B16A16_SFLOAT]: three_module.RGBAFormat,
  [ktxParse_module.VK_FORMAT_R8G8B8A8_UNORM]: three_module.RGBAFormat,
  [ktxParse_module.VK_FORMAT_R8G8B8A8_SRGB]: three_module.RGBAFormat,
  [ktxParse_module.VK_FORMAT_R32G32_SFLOAT]: three_module.RGFormat,
  [ktxParse_module.VK_FORMAT_R16G16_SFLOAT]: three_module.RGFormat,
  [ktxParse_module.VK_FORMAT_R8G8_UNORM]: three_module.RGFormat,
  [ktxParse_module.VK_FORMAT_R8G8_SRGB]: three_module.RGFormat,
  [ktxParse_module.VK_FORMAT_R32_SFLOAT]: three_module.RedFormat,
  [ktxParse_module.VK_FORMAT_R16_SFLOAT]: three_module.RedFormat,
  [ktxParse_module.VK_FORMAT_R8_SRGB]: three_module.RedFormat,
  [ktxParse_module.VK_FORMAT_R8_UNORM]: three_module.RedFormat
};
const TYPE_MAP = {
  [ktxParse_module.VK_FORMAT_R32G32B32A32_SFLOAT]: three_module.FloatType,
  [ktxParse_module.VK_FORMAT_R16G16B16A16_SFLOAT]: three_module.HalfFloatType,
  [ktxParse_module.VK_FORMAT_R8G8B8A8_UNORM]: three_module.UnsignedByteType,
  [ktxParse_module.VK_FORMAT_R8G8B8A8_SRGB]: three_module.UnsignedByteType,
  [ktxParse_module.VK_FORMAT_R32G32_SFLOAT]: three_module.FloatType,
  [ktxParse_module.VK_FORMAT_R16G16_SFLOAT]: three_module.HalfFloatType,
  [ktxParse_module.VK_FORMAT_R8G8_UNORM]: three_module.UnsignedByteType,
  [ktxParse_module.VK_FORMAT_R8G8_SRGB]: three_module.UnsignedByteType,
  [ktxParse_module.VK_FORMAT_R32_SFLOAT]: three_module.FloatType,
  [ktxParse_module.VK_FORMAT_R16_SFLOAT]: three_module.HalfFloatType,
  [ktxParse_module.VK_FORMAT_R8_SRGB]: three_module.UnsignedByteType,
  [ktxParse_module.VK_FORMAT_R8_UNORM]: three_module.UnsignedByteType
};
const COLOR_SPACE_MAP = {
  [ktxParse_module.VK_FORMAT_R8G8B8A8_SRGB]: three_module.SRGBColorSpace,
  [ktxParse_module.VK_FORMAT_R8G8_SRGB]: three_module.SRGBColorSpace,
  [ktxParse_module.VK_FORMAT_R8_SRGB]: three_module.SRGBColorSpace
};
async function createDataTexture(container, levelIndex = 0) {
  const { vkFormat } = container;
  const pixelWidth = Math.max(1, container.pixelWidth >> levelIndex);
  const pixelHeight = Math.max(1, container.pixelHeight >> levelIndex);
  const pixelDepth = Math.max(1, container.pixelDepth >> levelIndex);
  if (FORMAT_MAP[vkFormat] === void 0) {
    throw new Error("THREE.KTX2Loader: Unsupported vkFormat.");
  }
  const level = container.levels[levelIndex];
  let levelData;
  let view;
  if (container.supercompressionScheme === ktxParse_module.KHR_SUPERCOMPRESSION_NONE) {
    levelData = level.levelData;
  } else if (container.supercompressionScheme === ktxParse_module.KHR_SUPERCOMPRESSION_ZSTD) {
    if (!_zstd) {
      _zstd = new Promise(async (resolve) => {
        const zstd = new zstddec_module.ZSTDDecoder();
        await zstd.init();
        resolve(zstd);
      });
    }
    levelData = (await _zstd).decode(level.levelData, level.uncompressedByteLength);
  } else {
    throw new Error("THREE.KTX2Loader: Unsupported supercompressionScheme.");
  }
  if (TYPE_MAP[vkFormat] === three_module.FloatType) {
    view = new Float32Array(
      levelData.buffer,
      levelData.byteOffset,
      levelData.byteLength / Float32Array.BYTES_PER_ELEMENT
    );
  } else if (TYPE_MAP[vkFormat] === three_module.HalfFloatType) {
    view = new Uint16Array(
      levelData.buffer,
      levelData.byteOffset,
      levelData.byteLength / Uint16Array.BYTES_PER_ELEMENT
    );
  } else {
    view = levelData;
  }
  const texture = pixelDepth === 0 ? new three_module.DataTexture(view, pixelWidth, pixelHeight) : new three_module.Data3DTexture(view, pixelWidth, pixelHeight, pixelDepth);
  texture.type = TYPE_MAP[vkFormat];
  texture.format = FORMAT_MAP[vkFormat];
  texture.colorSpace = COLOR_SPACE_MAP[vkFormat] || three_module.NoColorSpace;
  texture.needsUpdate = true;
  return Promise.resolve(texture);
}
exports.KTX2Loader = KTX2Loader;
//# sourceMappingURL=KTX2Loader.js.map
