// basis_wrappers.cpp - Simple C-style wrappers to the C++ transcoder for WebGL use. #include "basisu_transcoder.h" using namespace basist; typedef unsigned int uint; extern "C" { void basis_init(); void *basis_open(void *src, uint src_size); void basis_close(void *h); uint basis_get_has_alpha(void *h); uint basis_get_num_images(void *h); uint basis_get_num_levels(void *h, uint image_index); uint basis_get_image_width(void *h, uint image_index, uint level_index); uint basis_get_image_height(void *h, uint image_index, uint level_index); uint basis_get_image_transcoded_size_in_bytes(void *h, uint image_index, uint level_index, uint format); uint basis_start_transcoding(void *h); uint basis_stop_transcoding(void *h); uint basis_transcode_image(void *h, void *dst, uint dst_size_in_bytes, uint image_index, uint level_index, uint format, uint unused, uint get_alpha_for_opaque_formats); void basis_set_debug_flags(uint f) { basist::set_debug_flags(f); } uint basis_get_debug_flags() { return basist::get_debug_flags(); } } void basis_init() { basisu_transcoder_init(); } #define MAGIC 0xDEADBEE1 struct basis_file { int m_magic; basisu_transcoder m_transcoder; void *m_pFile; uint m_file_size; basis_file() : m_transcoder() { } }; void *basis_open(void *src, uint src_size) { if ((!src) || (!src_size)) return nullptr; basis_file *f = new basis_file; f->m_pFile = src; f->m_file_size = src_size; if (!f->m_transcoder.validate_header(f->m_pFile, f->m_file_size)) { delete f; return nullptr; } f->m_magic = MAGIC; return f; } void basis_close(void *h) { basis_file *f = static_cast(h); if (!f) return; assert(f->m_magic == MAGIC); if (f->m_magic != MAGIC) return; delete f; } uint basis_get_has_alpha(void *h) { basis_file *f = static_cast(h); if (!f) return 0; assert(f->m_magic == MAGIC); if (f->m_magic != MAGIC) return 0; basisu_image_level_info li; if (!f->m_transcoder.get_image_level_info(f->m_pFile, f->m_file_size, li, 0, 0)) return 0; return li.m_alpha_flag; } uint basis_get_num_images(void *h) { basis_file *f = static_cast(h); if (!f) return 0; assert(f->m_magic == MAGIC); if (f->m_magic != MAGIC) return 0; return f->m_transcoder.get_total_images(f->m_pFile, f->m_file_size); } uint basis_get_num_levels(void *h, uint image_index) { basis_file *f = static_cast(h); if (!f) return 0; assert(f->m_magic == MAGIC); if (f->m_magic != MAGIC) return 0; basisu_image_info ii; if (!f->m_transcoder.get_image_info(f->m_pFile, f->m_file_size, ii, image_index)) return 0; return ii.m_total_levels; } uint basis_get_image_width(void *h, uint image_index, uint level_index) { basis_file *f = static_cast(h); if (!f) return 0; assert(f->m_magic == MAGIC); if (f->m_magic != MAGIC) return 0; uint orig_width, orig_height, total_blocks; if (!f->m_transcoder.get_image_level_desc(f->m_pFile, f->m_file_size, image_index, level_index, orig_width, orig_height, total_blocks)) return 0; return orig_width; } uint basis_get_image_height(void *h, uint image_index, uint level_index) { basis_file *f = static_cast(h); if (!f) return 0; assert(f->m_magic == MAGIC); if (f->m_magic != MAGIC) return 0; uint orig_width, orig_height, total_blocks; if (!f->m_transcoder.get_image_level_desc(f->m_pFile, f->m_file_size, image_index, level_index, orig_width, orig_height, total_blocks)) return 0; return orig_height; } uint basis_get_image_transcoded_size_in_bytes(void *h, uint image_index, uint level_index, uint format) { basis_file *f = static_cast(h); if (!f) return 0; assert(f->m_magic == MAGIC); if (f->m_magic != MAGIC) return 0; if (format >= (int)transcoder_texture_format::cTFTotalTextureFormats) return 0; uint orig_width, orig_height, total_blocks; if (!f->m_transcoder.get_image_level_desc(f->m_pFile, f->m_file_size, image_index, level_index, orig_width, orig_height, total_blocks)) return 0; uint bytes_per_block_or_pixel = basis_get_bytes_per_block_or_pixel((transcoder_texture_format)format); if (basis_transcoder_format_is_uncompressed((transcoder_texture_format)format)) return orig_width * orig_height * bytes_per_block_or_pixel; return total_blocks * bytes_per_block_or_pixel; } uint basis_start_transcoding(void *h) { basis_file *f = static_cast(h); if (!f) return 0; assert(f->m_magic == MAGIC); if (f->m_magic != MAGIC) return 0; return f->m_transcoder.start_transcoding(f->m_pFile, f->m_file_size); } uint basis_stop_transcoding(void *h) { basis_file *f = static_cast(h); if (!f) return 0; assert(f->m_magic == MAGIC); if (f->m_magic != MAGIC) return 0; return f->m_transcoder.stop_transcoding(); } uint basis_transcode_image(void *h, void *dst, uint dst_size_in_bytes, uint image_index, uint level_index, uint format, uint unused, uint get_alpha_for_opaque_formats) { basis_file *f = static_cast(h); if (!f) return 0; assert(f->m_magic == MAGIC); if (f->m_magic != MAGIC) return 0; if (format >= (int)transcoder_texture_format::cTFTotalTextureFormats) return 0; uint bytes_per_block = basis_get_bytes_per_block_or_pixel((transcoder_texture_format)format); return f->m_transcoder.transcode_image_level(f->m_pFile, f->m_file_size, image_index, level_index, dst, dst_size_in_bytes / bytes_per_block, (basist::transcoder_texture_format)format, (get_alpha_for_opaque_formats ? (uint32_t)cDecodeFlagsTranscodeAlphaDataToOpaqueFormats : 0)); }