pixi-basis-ktx2
Version:
Loader for the *.basis & *.ktx2 supercompressed texture file format. This package also ships with the transcoder!
119 lines • 5.51 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TranscoderWorkerWrapperKTX2 = TranscoderWorkerWrapperKTX2;
/**
* This wraps the transcoder web-worker functionality; it can be converted into a string to get the source code. It expects
* you to prepend the transcoder JavaScript code so that the `BASIS` namespace is available.
*
* The transcoder worker responds to two types of messages: "init" and "transcode". You must always send the first "init"
* {@link IInitializeTranscoderMessage} message with the WebAssembly binary; if the transcoder is successfully initialized,
* the web-worker will respond by sending another {@link ITranscodeResponse} message with `success: true`.
* @ignore
*/
function TranscoderWorkerWrapperKTX2() {
let KTX2Binding;
const messageHandlers = {
init: (message) => {
if (!self.BASIS) {
console.warn('jsSource was not prepended?');
return {
type: 'init',
success: false,
};
}
void self.BASIS({ wasmBinary: message.wasmSource }).then((basisLibrary) => {
basisLibrary.initializeBasis();
KTX2Binding = basisLibrary;
self.postMessage({
type: 'init',
success: true,
});
});
return null;
},
transcode(message) {
const basisData = message.basisData;
const BASIS = KTX2Binding;
const data = basisData;
const ktx2File = new BASIS.KTX2File(data);
const imageCount = ktx2File.getLevels() * Math.max(1, ktx2File.getLayers()) * ktx2File.getFaces();
let levels = ktx2File.getLevels();
const layers = ktx2File.getLayers();
const faces = ktx2File.getFaces();
const hasAlpha = ktx2File.getHasAlpha();
const basisFormat = hasAlpha ? message.rgbaFormat : message.rgbFormat;
const basisFallbackFormat = 14; // BASIS_FORMATS.cTFRGB565 (cannot import values into web-worker!)
const imageArray = new Array(imageCount);
let fallbackMode = false;
if (!ktx2File.startTranscoding()) {
ktx2File.close();
ktx2File.delete();
return {
type: 'transcode',
requestID: message.requestID,
success: false,
};
}
for (let i = 0; i < levels; i++) {
const imageResource = {
imageID: i,
levelArray: new Array(),
};
for (let j = 0; j < Math.max(1, layers); j++) {
for (let k = 0; k < faces; k++) {
const imageLevelInfo = ktx2File.getImageLevelInfo(i, j, k);
const width = imageLevelInfo.width;
const height = imageLevelInfo.height;
const format = !fallbackMode ? basisFormat : basisFallbackFormat;
const byteSize = ktx2File.getImageTranscodedSizeInBytes(i, j, k, format);
// Level 0 is texture's actual width, height
if (j === 0) {
const alignedWidth = (width + 3) & ~3;
const alignedHeight = (height + 3) & ~3;
imageResource.width = alignedWidth;
imageResource.height = alignedHeight;
}
const imageBuffer = new Uint8Array(byteSize);
if (!ktx2File.transcodeImage(imageBuffer, i, j, k, format, false, -1, -1)) {
if (fallbackMode) {
// We failed in fallback mode as well!
console.error(`Basis failed to transcode image ${i}, level ${j}!`);
return { type: 'transcode', requestID: message.requestID, success: false };
}
/* eslint-disable-next-line max-len */
console.warn(`Basis failed to transcode image ${i}, level ${j}! Retrying to an uncompressed texture format!`);
i = -1;
levels = 1;
fallbackMode = true;
break;
}
imageResource.levelArray.push({
levelID: j,
levelWidth: width,
levelHeight: height,
levelBuffer: imageBuffer,
});
}
}
imageArray[i] = imageResource;
}
ktx2File.close();
ktx2File.delete();
return {
type: 'transcode',
requestID: message.requestID,
success: true,
basisFormat: !fallbackMode ? basisFormat : basisFallbackFormat,
imageArray,
};
},
};
self.onmessage = (e) => {
const msg = e.data;
const response = messageHandlers[msg.type](msg);
if (response) {
self.postMessage(response);
}
};
}
//# sourceMappingURL=TranscoderWorkerWrapperKTX2.js.map