293 lines
13 KiB
Nim
293 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
|
|
slice*: int32
|
|
data*: pointer
|
|
len*: int
|
|
row_len*: int
|
|
|
|
type KtxInfoParts* = object
|
|
info*: KtxInfo
|
|
parts*: seq[KtxPart]
|
|
|
|
{.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].int*100 or blk_size[1].int):
|
|
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].int*100 or blk_size[1].int):
|
|
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
|