# License of this file: # Consider this file an extension of dds-ktx.h (2-clause BSD) type KtxInfo* = object width*, height*, depth*: int32 num_layers*, num_mipmaps*: int32 is_cubemap*, has_alpha*, is_sRGB*: bool is_bc*, is_astc*: bool internal_format*: int32 type KtxPart* = object width*, height*: int32 layer*, face*, mip_level*: int32 slice*: int32 data*: pointer len*: int row_len*: int {.compile:("impl.c","-I.").} type ddsktx_format = enum DDSKTX_FORMAT_BC1, ## DXT1 DDSKTX_FORMAT_BC2, ## DXT3 DDSKTX_FORMAT_BC3, ## DXT5 DDSKTX_FORMAT_BC4, ## ATI1 DDSKTX_FORMAT_BC5, ## ATI2 DDSKTX_FORMAT_BC6H, ## BC6H DDSKTX_FORMAT_BC7, ## BC7 DDSKTX_FORMAT_ETC1, ## ETC1 RGB8 DDSKTX_FORMAT_ETC2, ## ETC2 RGB8 DDSKTX_FORMAT_ETC2A, ## ETC2 RGBA8 DDSKTX_FORMAT_ETC2A1, ## ETC2 RGB8A1 DDSKTX_FORMAT_PTC12, ## PVRTC1 RGB 2bpp DDSKTX_FORMAT_PTC14, ## PVRTC1 RGB 4bpp DDSKTX_FORMAT_PTC12A, ## PVRTC1 RGBA 2bpp DDSKTX_FORMAT_PTC14A, ## PVRTC1 RGBA 4bpp DDSKTX_FORMAT_PTC22, ## PVRTC2 RGBA 2bpp DDSKTX_FORMAT_PTC24, ## PVRTC2 RGBA 4bpp DDSKTX_FORMAT_ATC, ## ATC RGB 4BPP DDSKTX_FORMAT_ATCE, ## ATCE RGBA 8 BPP explicit alpha DDSKTX_FORMAT_ATCI, ## ATCI RGBA 8 BPP interpolated alpha DDSKTX_FORMAT_ASTC4x4, ## ASTC 4x4 8.00 BPP DDSKTX_FORMAT_ASTC5x4, ## ASTC 5x4 6.40 BPP DDSKTX_FORMAT_ASTC5x5, ## ASTC 5x5 5.12 BPP DDSKTX_FORMAT_ASTC6x5, ## ASTC 6x5 4.27 BPP DDSKTX_FORMAT_ASTC6x6, ## ASTC 6x6 3.56 BPP DDSKTX_FORMAT_ASTC8x5, ## ASTC 8x5 3.20 BPP DDSKTX_FORMAT_ASTC8x6, ## ASTC 8x6 2.67 BPP DDSKTX_FORMAT_ASTC10x5, ## ASTC 10x5 2.56 BPP DDSKTX_FORMAT_ASTC10x6, ## ASTC 10x6 2.13 BPP DDSKTX_FORMAT_ASTC8x8, ## ASTC 8x8 2.00 BPP DDSKTX_FORMAT_ASTC10x8, ## ASTC 10x8 1.60 BPP DDSKTX_FORMAT_ASTC10x10, ## ASTC 10x10 1.28 BPP DDSKTX_FORMAT_ASTC12x10, ## ASTC 12x10 1.07 BPP DDSKTX_FORMAT_ASTC12x12, ## ASTC 12x12 0.89 BPP DDSKTX_FORMAT_COMPRESSED, DDSKTX_FORMAT_A8, DDSKTX_FORMAT_R8, DDSKTX_FORMAT_RGBA8, DDSKTX_FORMAT_RGBA8S, DDSKTX_FORMAT_RG16, DDSKTX_FORMAT_RGB8, DDSKTX_FORMAT_R16, DDSKTX_FORMAT_R32F, DDSKTX_FORMAT_R16F, DDSKTX_FORMAT_RG16F, DDSKTX_FORMAT_RG16S, DDSKTX_FORMAT_RGBA16F, DDSKTX_FORMAT_RGBA16, DDSKTX_FORMAT_BGRA8, DDSKTX_FORMAT_RGB10A2, DDSKTX_FORMAT_RG11B10F, DDSKTX_FORMAT_RG8, DDSKTX_FORMAT_RG8S, DDSKTX_FORMAT_COUNT type ddsktx_texture_info = object data_offset: cint size_bytes: cint format: ddsktx_format flags: cuint width: cint height: cint depth: cint num_layers: cint num_mips: cint bpp: cint metadata_offset: cint metadata_size: cint type ddsktx_sub_data = object buff: pointer width: cint height: cint size_bytes: cint row_pitch_bytes: cint type ddsktx_error = object msg: array[256, char] {.push importc, cdecl.} proc ddsktx_parse(tc: var ddsktx_texture_info, file_data: pointer, size: cint, err: var ddsktx_error): bool proc ddsktx_get_sub(tex: var ddsktx_texture_info, buff: var ddsktx_sub_data, file_data: pointer, size, array_idx, slice_face_idx, mip_idx: cint): void # proc ddsktx_format_str(format: ddsktx_format): cstring # proc ddsktx_format_compressed(format: ddsktx_format): bool {.pop.} const GL_COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0'i32 const GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1'i32 const GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2'i32 const GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3'i32 const GL_COMPRESSED_SRGB_S3TC_DXT1_EXT = 0x8C4C'i32 const GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT = 0x8C4D'i32 const GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT = 0x8C4E'i32 const GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT = 0x8C4F'i32 const GL_COMPRESSED_RGBA_BPTC_UNORM_EXT = 0x8E8C'i32 const GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT = 0x8E8D'i32 # const GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT = 0x8E8E'i32 # const GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT = 0x8E8F'i32 const GL_COMPRESSED_RGBA_ASTC_4x4_KHR = 0x93B0'i32 const GL_COMPRESSED_RGBA_ASTC_5x4_KHR = 0x93B1'i32 const GL_COMPRESSED_RGBA_ASTC_5x5_KHR = 0x93B2'i32 const GL_COMPRESSED_RGBA_ASTC_6x5_KHR = 0x93B3'i32 const GL_COMPRESSED_RGBA_ASTC_6x6_KHR = 0x93B4'i32 const GL_COMPRESSED_RGBA_ASTC_8x5_KHR = 0x93B5'i32 const GL_COMPRESSED_RGBA_ASTC_8x6_KHR = 0x93B6'i32 const GL_COMPRESSED_RGBA_ASTC_8x8_KHR = 0x93B7'i32 const GL_COMPRESSED_RGBA_ASTC_10x5_KHR = 0x93B8'i32 const GL_COMPRESSED_RGBA_ASTC_10x6_KHR = 0x93B9'i32 const GL_COMPRESSED_RGBA_ASTC_10x8_KHR = 0x93BA'i32 const GL_COMPRESSED_RGBA_ASTC_10x10_KHR = 0x93BB'i32 const GL_COMPRESSED_RGBA_ASTC_12x10_KHR = 0x93BC'i32 const GL_COMPRESSED_RGBA_ASTC_12x12_KHR = 0x93BD'i32 const GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR = 0x93D0'i32 const GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR = 0x93D1'i32 const GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR = 0x93D2'i32 const GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR = 0x93D3'i32 const GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR = 0x93D4'i32 const GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR = 0x93D5'i32 const GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR = 0x93D6'i32 const GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR = 0x93D7'i32 const GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR = 0x93D8'i32 const GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR = 0x93D9'i32 const GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR = 0x93DA'i32 const GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR = 0x93DB'i32 const GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR = 0x93DC'i32 const GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR = 0x93DD'i32 import std/bitops, std/options export options type TexFlags = enum FlagCubemap FlagSrgb FlagAlpha FlagDds FlagKtx FlagVolume proc GetDdsKtxInfo*(p: pointer, len: int, is_sRGB = false): Option[KtxInfo] = var tc: ddsktx_texture_info var err: ddsktx_error if ddsktx_parse(tc, p, len.cint, err): let is_cubemap = cast[int8](tc.flags).testBit FlagCubemap.int8 let is_sRGB = is_sRGB or cast[int8](tc.flags).testBit FlagSrgb.int8 let has_alpha = cast[int8](tc.flags).testBit FlagAlpha.int8 let is_bc = tc.format >= DDSKTX_FORMAT_BC1 and tc.format <= DDSKTX_FORMAT_BC7 let is_astc = tc.format >= DDSKTX_FORMAT_ASTC4x4 and tc.format <= DDSKTX_FORMAT_ASTC12x12 let internal_format = if is_sRGB: case tc.format: of DDSKTX_FORMAT_BC1: if has_alpha: GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT else: GL_COMPRESSED_SRGB_S3TC_DXT1_EXT of DDSKTX_FORMAT_BC3: GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT of DDSKTX_FORMAT_BC5: GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT of DDSKTX_FORMAT_BC7: GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT of DDSKTX_FORMAT_ASTC4x4: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR of DDSKTX_FORMAT_ASTC5x4: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR of DDSKTX_FORMAT_ASTC5x5: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR of DDSKTX_FORMAT_ASTC6x5: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR of DDSKTX_FORMAT_ASTC6x6: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR of DDSKTX_FORMAT_ASTC8x5: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR of DDSKTX_FORMAT_ASTC8x6: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR of DDSKTX_FORMAT_ASTC10x5: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR of DDSKTX_FORMAT_ASTC10x6: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR of DDSKTX_FORMAT_ASTC8x8: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR of DDSKTX_FORMAT_ASTC10x8: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR of DDSKTX_FORMAT_ASTC10x10: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR of DDSKTX_FORMAT_ASTC12x10: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR of DDSKTX_FORMAT_ASTC12x12: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR else: 0 else: case tc.format: of DDSKTX_FORMAT_BC1: if has_alpha: GL_COMPRESSED_RGBA_S3TC_DXT1_EXT else: GL_COMPRESSED_RGB_S3TC_DXT1_EXT of DDSKTX_FORMAT_BC3: GL_COMPRESSED_RGBA_S3TC_DXT3_EXT of DDSKTX_FORMAT_BC5: GL_COMPRESSED_RGBA_S3TC_DXT5_EXT of DDSKTX_FORMAT_BC7: GL_COMPRESSED_RGBA_BPTC_UNORM_EXT of DDSKTX_FORMAT_ASTC4x4: GL_COMPRESSED_RGBA_ASTC_4x4_KHR of DDSKTX_FORMAT_ASTC5x4: GL_COMPRESSED_RGBA_ASTC_5x4_KHR of DDSKTX_FORMAT_ASTC5x5: GL_COMPRESSED_RGBA_ASTC_5x5_KHR of DDSKTX_FORMAT_ASTC6x5: GL_COMPRESSED_RGBA_ASTC_6x5_KHR of DDSKTX_FORMAT_ASTC6x6: GL_COMPRESSED_RGBA_ASTC_6x6_KHR of DDSKTX_FORMAT_ASTC8x5: GL_COMPRESSED_RGBA_ASTC_8x5_KHR of DDSKTX_FORMAT_ASTC8x6: GL_COMPRESSED_RGBA_ASTC_8x6_KHR of DDSKTX_FORMAT_ASTC10x5: GL_COMPRESSED_RGBA_ASTC_10x5_KHR of DDSKTX_FORMAT_ASTC10x6: GL_COMPRESSED_RGBA_ASTC_10x6_KHR of DDSKTX_FORMAT_ASTC8x8: GL_COMPRESSED_RGBA_ASTC_8x8_KHR of DDSKTX_FORMAT_ASTC10x8: GL_COMPRESSED_RGBA_ASTC_10x8_KHR of DDSKTX_FORMAT_ASTC10x10: GL_COMPRESSED_RGBA_ASTC_10x10_KHR of DDSKTX_FORMAT_ASTC12x10: GL_COMPRESSED_RGBA_ASTC_12x10_KHR of DDSKTX_FORMAT_ASTC12x12: GL_COMPRESSED_RGBA_ASTC_12x12_KHR else: 0 assert internal_format != 0, "Unsupported format" return some(KtxInfo( width: tc.width, height: tc.height, depth: tc.depth, num_layers: tc.num_layers, num_mipmaps: tc.num_mips, is_cubemap: is_cubemap, has_alpha: has_alpha, is_sRGB: is_sRGB, is_bc: is_bc, is_astc: is_astc, internal_format: internalformat, )) proc ParseDdsKtx*(p: pointer, len: int): seq[KtxPart] = var tc: ddsktx_texture_info var err: ddsktx_error if ddsktx_parse(tc, p, len.cint, err): let num_faces = if cast[int8](tc.flags).testBit FlagCubemap.int8: 6'i32 else: 1'i32 var sd: ddsktx_sub_data for layer in 0 ..< tc.num_layers: for face in 0 ..< num_faces: for mip in 0 ..< tc.num_mips: for slice in 0 ..< tc.depth: let slice_face = slice + face*tc.depth ddsktx_get_sub(tc, sd, p, len.cint, layer, slice_face, mip) result.add KtxPart( width: sd.width, height: sd.height, layer: layer, face: face, mip_level: mip, data: sd.buff, len: sd.size_bytes, row_len: sd.row_pitch_bytes, ) else: let err_msg = $cast[cstring](err.msg.addr) raise ValueError.newException err_msg func get_ASTC_internal_format*(blk_size: (SomeInteger,SomeInteger), is_sRGB: bool): int32 = result = if is_sRGB: case blk_size[0]*100 or blk_size[1]: of 04_04: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR of 05_04: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR of 05_05: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR of 06_05: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR of 06_06: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR of 08_05: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR of 08_06: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR of 10_05: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR of 10_06: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR of 08_08: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR of 10_08: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR of 10_10: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR of 12_10: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR of 12_12: GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR else: 0'i32 else: case blk_size[0]*100 or blk_size[1]: of 04_04: GL_COMPRESSED_RGBA_ASTC_4x4_KHR of 05_04: GL_COMPRESSED_RGBA_ASTC_5x4_KHR of 05_05: GL_COMPRESSED_RGBA_ASTC_5x5_KHR of 06_05: GL_COMPRESSED_RGBA_ASTC_6x5_KHR of 06_06: GL_COMPRESSED_RGBA_ASTC_6x6_KHR of 08_05: GL_COMPRESSED_RGBA_ASTC_8x5_KHR of 08_06: GL_COMPRESSED_RGBA_ASTC_8x6_KHR of 10_05: GL_COMPRESSED_RGBA_ASTC_10x5_KHR of 10_06: GL_COMPRESSED_RGBA_ASTC_10x6_KHR of 08_08: GL_COMPRESSED_RGBA_ASTC_8x8_KHR of 10_08: GL_COMPRESSED_RGBA_ASTC_10x8_KHR of 10_10: GL_COMPRESSED_RGBA_ASTC_10x10_KHR of 12_10: GL_COMPRESSED_RGBA_ASTC_12x10_KHR of 12_12: GL_COMPRESSED_RGBA_ASTC_12x12_KHR else: 0'i32 assert result != 0, "Invalid ASTC block size " & $blk_size