myou-engine/libs/dds_ktx/dds_ktx.nim

288 lines
13 KiB
Nim

# 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
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: (int,int), 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