Skip to content

Commit

Permalink
[#1182] further code revamping/reorganization to prepare for compress…
Browse files Browse the repository at this point in the history
…ed texture support
  • Loading branch information
obiot committed Mar 23, 2024
1 parent 7c51ffd commit 1e46345
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 78 deletions.
49 changes: 49 additions & 0 deletions src/loader/parsers/compressed_textures/compressed_image.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { parseDDS } from "./parseDDS.js";
import { parseKTX } from "./parseKTX.js";
import { parseKTX2 } from "./parseKTX2.js";
import { parsePVR } from "./parsePVR.js";
import { parsePKM } from "./parsePKM.js";
import * as event from "../../../system/event.js";

let _renderer;

// gracefully capture a reference to the active renderer without adding more cyclic redundancy
event.once(event.VIDEO_INIT, (renderer) => {
_renderer = renderer;
});


export function parseCompressedImage(arrayBuffer, imgExt) {
let texture;

// check if the current renderer is WebGL
if (_renderer.type.includes("WebGL")) {
switch (imgExt) {
// Compressed texture
case "dds":
texture = parseDDS(arrayBuffer);
break;
case "pvr":
texture = parsePVR(arrayBuffer);
break;
case "pkm":
texture = parsePKM(arrayBuffer);
break;
case "ktx":
texture = parseKTX(arrayBuffer);
break;
case "ktx2":
texture = parseKTX2(arrayBuffer);
break;
}
}

if (typeof texture !== "undefined") {
if (_renderer.hasSupportedCompressedFormats(texture.format)) {
console.log("Compressed texture format supported: " + texture.format);
return texture;
}
}

throw ("unsupported texture format:" + imgExt + texture ? " (" + texture.format + ")" : "");
}
124 changes: 123 additions & 1 deletion src/loader/parsers/compressed_textures/parsePVR.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,127 @@
/*
const COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00;
const COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01;
const COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02;
const COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03;
const COMPRESSED_RGB_ETC1_WEBGL = 0x8D64;
const PVR_HEADER_LENGTH = 13; // The header length in 32 bit ints.
//const PVR_MAGIC = 0x03525650; //0x50565203;
// Offsets into the header array.
//const PVR_HEADER_MAGIC = 0;
const PVR_HEADER_FORMAT = 2;
const PVR_HEADER_HEIGHT = 6;
const PVR_HEADER_WIDTH = 7;
const PVR_HEADER_MIPMAPCOUNT = 11;
const PVR_HEADER_METADATA = 12;
const PVR_FORMAT_2BPP_RGB = 0;
const PVR_FORMAT_2BPP_RGBA = 1;
const PVR_FORMAT_4BPP_RGB = 2;
const PVR_FORMAT_4BPP_RGBA = 3;
//const PVR_COLOR_SPACE = 4;
const PVR_FORMAT_ETC1 = 6;
const PVR_FORMAT_DXT1 = 7;
const PVR_FORMAT_DXT3 = 9;
const PVR_FORMAT_DXT5 = 5;
const COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0;
//const COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
const COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;
const COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;
const PVR_TO_WEBGL_FORMAT = {
[PVR_FORMAT_2BPP_RGB] : COMPRESSED_RGB_PVRTC_2BPPV1_IMG,
[PVR_FORMAT_2BPP_RGBA] : COMPRESSED_RGBA_PVRTC_2BPPV1_IMG,
[PVR_FORMAT_4BPP_RGB] : COMPRESSED_RGB_PVRTC_4BPPV1_IMG,
[PVR_FORMAT_4BPP_RGBA] : COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,
[PVR_FORMAT_ETC1] : COMPRESSED_RGB_ETC1_WEBGL,
[PVR_FORMAT_DXT1] : COMPRESSED_RGB_S3TC_DXT1_EXT,
[PVR_FORMAT_DXT3] : COMPRESSED_RGBA_S3TC_DXT3_EXT,
[PVR_FORMAT_DXT5] : COMPRESSED_RGBA_S3TC_DXT5_EXT
};
function levelBufferSize(format, width, height) {
switch (format) {
case COMPRESSED_RGB_S3TC_DXT1_EXT:
case COMPRESSED_RGB_ETC1_WEBGL:
return ((width + 3) >> 2) * ((height + 3) >> 2) * 8;
case COMPRESSED_RGBA_S3TC_DXT3_EXT:
case COMPRESSED_RGBA_S3TC_DXT5_EXT:
return ((width + 3) >> 2) * ((height + 3) >> 2) * 16;
case COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
case COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
return Math.floor((Math.max(width, 8) * Math.max(height, 8) * 4 + 7) / 8);
case COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
case COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
return Math.floor((Math.max(width, 16) * Math.max(height, 8) * 2 + 7) / 8);
default:
return 0;
}
}
*/

// parse and return the compressed texture
export function parsePVR(/*data, formats*/) {
export function parsePVR() {

throw new Error("unsupported format");

/*
// Create a new DataView from the data
let header = new Uint32Array(data, 0, PVR_HEADER_LENGTH);
//console.log(header);
// VERSION
//const version = header[PVR_HEADER_FORMAT];
//const versionMatch = version === PVR_MAGIC;
// PIXEL_FORMAT_INDEX
const pvrFormat = PVR_TO_WEBGL_FORMAT[header[PVR_HEADER_FORMAT]] || -1;
const width = header[PVR_HEADER_WIDTH];
const height = header[PVR_HEADER_HEIGHT];
const dataOffset = header[PVR_HEADER_METADATA] + 52;
//const colorSpace = header[PVR_COLOR_SPACE];
const mipmapCount = header[PVR_HEADER_MIPMAPCOUNT];
var image = new Uint8Array(data, dataOffset);
var mipmaps = new Array(mipmapCount);
var offset = 0;
var levelWidth = width;
var levelHeight = height;
for (var i = 0; i < mipmapCount; i++)
{
var levelSize = levelBufferSize(pvrFormat, levelWidth, levelHeight);
mipmaps[i] = {
data: new Uint8Array(image.buffer, image.byteOffset + offset, levelSize),
width: levelWidth,
height: levelHeight
};
levelWidth = Math.max(1, levelWidth >> 1);
levelHeight = Math.max(1, levelHeight >> 1);
offset += levelSize;
}
return {
mipmaps: mipmaps,
width: width,
height: height,
format: pvrFormat,
compressed: true,
generateMipmap: false
};
*/
}
78 changes: 20 additions & 58 deletions src/loader/parsers/image.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,7 @@
import { imgList } from "../cache.js";
import { fetchData } from "./fetchdata.js";
import * as fileUtil from "./../../utils/file.js";
import * as event from "../../system/event.js";
import { parseDDS } from "./compressed_textures/parseDDS.js";
import { parseKTX } from "./compressed_textures/parseKTX.js";
import { parseKTX2 } from "./compressed_textures/parseKTX2.js";
import { parsePVR } from "./compressed_textures/parsePVR.js";
import { parsePKM } from "./compressed_textures/parsePKM.js";

let _renderer;

// gracefully capture a reference to the active renderer without adding more cyclic redundancy
event.once(event.VIDEO_INIT, (renderer) => {
_renderer = renderer;
});
import { parseCompressedImage } from "./compressed_textures/compressed_image.js";

/**
* parse/preload an image
Expand All @@ -38,62 +26,36 @@ export function preloadImage(img, onload, onerror, settings) {
}

let sources = Array.isArray(img.src) ? img.src : [img.src];
let isFormatSupported = false;

for (const imgPath of sources) {
const imgExt = fileUtil.getExtension(imgPath);
let isFormatSupported = false;

// switch case will stop as soon as a first format is detected
// loop will stop as soon as a first supported format is detected
switch (imgExt) {
// Compressed texture
case "dds":
case "pvr":
case "pkm":
case "ktx":
case "ktx2":
// check if the current renderer is WebGL
if (_renderer.type.includes("WebGL")) {
fetchData(imgPath, "arrayBuffer", settings)
.then(arrayBuffer => {
let texture;
try {
const textureFormats = _renderer.getSupportedCompressedTextureFormats();
switch (imgExt) {
// Compressed texture
case "dds":
texture = parseDDS(arrayBuffer, textureFormats);
break;
case "pvr":
texture = parsePVR(arrayBuffer, textureFormats);
break;
case "pkm":
texture = parsePKM(arrayBuffer, textureFormats);
break;
case "ktx":
texture = parseKTX(arrayBuffer, textureFormats);
break;
case "ktx2":
texture = parseKTX2(arrayBuffer, textureFormats);
break;
}
texture.isCompressed = true;
imgList[img.name] = texture;
isFormatSupported = true;
if (typeof onload === "function") {
// callback
onload();
}
} catch (error) {
// if parse function throw an error;
}
})
.catch(error => {
if (typeof onerror === "function") {
// file cannot be loaded
onerror(error);
fetchData(imgPath, "arrayBuffer", settings)
.then(arrayBuffer => {
try {
imgList[img.name] = parseCompressedImage(arrayBuffer, imgExt);
isFormatSupported = true;
if (typeof onload === "function") {
// callback
onload();
}
});
}
} catch (e) {
// parseCompressedImage will throw an error if a format is not supported or badly formatted
}
}).catch(error => {
if (typeof onerror === "function") {
// file cannot be loaded
onerror(error);
}
});
break;

// SVG file
Expand Down
19 changes: 0 additions & 19 deletions src/video/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ import Path2D from "./../geometries/path2d.js";
import Vector2d from "../math/vector2.js";
import CanvasRenderTarget from "./rendertarget/canvasrendertarget.js";

// list of supported compressed texture formats
let supportedCompressedTextureFormats;

/**
* @classdesc
* a base renderer object
Expand Down Expand Up @@ -191,22 +188,6 @@ export default class Renderer {
return this.currentBlendMode;
}

getSupportedCompressedTextureFormats() {
if (typeof supportedCompressedTextureFormats === "undefined") {
const gl = this.gl;
supportedCompressedTextureFormats = {
astc: gl.getExtension("WEBGL_compressed_texture_astc") || this._gl.getExtension("WEBKIT_WEBGL_compressed_texture_astc"),
bptc: gl.getExtension("EXT_texture_compression_bptc") || this._gl.getExtension("WEBKIT_EXT_texture_compression_bptc"),
s3tc: gl.getExtension("WEBGL_compressed_texture_s3tc") || this._gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc"),
s3tc_srgb: gl.getExtension("WEBGL_compressed_texture_s3tc_srgb") || this._gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc_srgb"),
pvrtc: gl.getExtension("WEBGL_compressed_texture_pvrtc") || this._gl.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc"),
etc1: gl.getExtension("WEBGL_compressed_texture_etc1") || this._gl.getExtension("WEBKIT_WEBGL_compressed_texture_etc1"),
etc2: gl.getExtension("WEBGL_compressed_texture_etc") || gl.getExtension("WEBKIT_WEBGL_compressed_texture_etc") || gl.getExtension("WEBGL_compressed_texture_es3_0")
};
}
return supportedCompressedTextureFormats;
}

/**
* Returns the 2D Context object of the given Canvas<br>
* Also configures anti-aliasing and blend modes based on constructor options.
Expand Down
40 changes: 40 additions & 0 deletions src/video/webgl/webgl_renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import * as event from "./../../system/event.js";
import pool from "./../../system/pooling.js";
import { isPowerOfTwo } from "./../../math/math.js";

// list of supported compressed texture formats
let supportedCompressedTextureFormats;

/**
* @classdesc
* a WebGL renderer object
Expand Down Expand Up @@ -184,6 +187,43 @@ export default class WebGLRenderer extends Renderer {
return this.renderTarget.WebGLVersion;
}

/**
* return the list of supported compressed texture formats
* @return {Object}
*/
getSupportedCompressedTextureFormats() {
if (typeof supportedCompressedTextureFormats === "undefined") {
const gl = this.gl;
supportedCompressedTextureFormats = {
astc: gl.getExtension("WEBGL_compressed_texture_astc") || this._gl.getExtension("WEBKIT_WEBGL_compressed_texture_astc"),
bptc: gl.getExtension("EXT_texture_compression_bptc") || this._gl.getExtension("WEBKIT_EXT_texture_compression_bptc"),
s3tc: gl.getExtension("WEBGL_compressed_texture_s3tc") || this._gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc"),
s3tc_srgb: gl.getExtension("WEBGL_compressed_texture_s3tc_srgb") || this._gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc_srgb"),
pvrtc: gl.getExtension("WEBGL_compressed_texture_pvrtc") || this._gl.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc"),
etc1: gl.getExtension("WEBGL_compressed_texture_etc1") || this._gl.getExtension("WEBKIT_WEBGL_compressed_texture_etc1"),
etc2: gl.getExtension("WEBGL_compressed_texture_etc") || gl.getExtension("WEBKIT_WEBGL_compressed_texture_etc") || gl.getExtension("WEBGL_compressed_texture_es3_0")
};
}
return supportedCompressedTextureFormats;
}

/**
* return true if the given compressed texture format is supported
* @param {Number} format
* @returns
*/
hasSupportedCompressedFormats(format) {
const supportedFormats = this.getSupportedCompressedTextureFormats();
for (var supportedFormat in supportedFormats) {
for (var extension in supportedFormats[supportedFormat]) {
if (format === supportedFormats[supportedFormat][extension]) {
return true;
}
}
}
return false;
}

/**
* Reset context state
*/
Expand Down

0 comments on commit 1e46345

Please sign in to comment.