mach/libs/basisu/src/encoder.zig
2022-08-29 05:59:52 -07:00

225 lines
7.1 KiB
Zig

const std = @import("std");
const b = @import("encoder/binding.zig");
const BasisTextureFormat = @import("main.zig").BasisTextureFormat;
const testing = std.testing;
/// Must be called before encoding anything
pub fn init_encoder() void {
b.basisu_encoder_init();
}
pub const Compressor = struct {
pub const Error = error{
InitializationFailed,
ValidationFailed,
EncodingUASTCFailed,
CannotReadSourceImages,
FrontendFault,
FrontendExtractionFailed,
BackendFault,
CannotCreateBasisFile,
CannotWriteOutput,
UASTCRDOPostProcessFailed,
CannotCreateKTX2File,
};
handle: *b.Compressor,
pub fn init(params: CompressorParams) error{Unknown}!Compressor {
return Compressor{
.handle = if (b.compressor_init(params.handle)) |v| v else return error.Unknown,
};
}
pub fn deinit(self: Compressor) void {
b.compressor_deinit(self.handle);
}
pub fn process(self: Compressor) Error!void {
return switch (b.compressor_process(self.handle)) {
0 => {},
1 => error.InitializationFailed,
2 => error.CannotReadSourceImages,
3 => error.ValidationFailed,
4 => error.EncodingUASTCFailed,
5 => error.FrontendFault,
6 => error.FrontendExtractionFailed,
7 => error.BackendFault,
8 => error.CannotCreateBasisFile,
9 => error.UASTCRDOPostProcessFailed,
10 => error.CannotCreateKTX2File,
else => unreachable,
};
}
/// output will be freed with `Compressor.deinit`
pub fn output(self: Compressor) []const u8 {
return b.compressor_get_output(self.handle)[0..b.compressor_get_output_size(self.handle)];
}
pub fn outputBitsPerTexel(self: Compressor) f64 {
return b.compressor_get_output_bits_per_texel(self.handle);
}
pub fn anyImageHasAlpha(self: Compressor) bool {
return b.compressor_get_any_source_image_has_alpha(self.handle);
}
};
pub const CompressorParams = struct {
handle: *b.CompressorParams,
pub fn init(threads_count: u32) CompressorParams {
const h = CompressorParams{ .handle = b.compressor_params_init() };
h.setStatusOutput(false);
b.compressor_params_set_thread_count(h.handle, threads_count);
return h;
}
pub fn deinit(self: CompressorParams) void {
b.compressor_params_deinit(self.handle);
}
pub fn clear(self: CompressorParams) void {
b.compressor_params_clear(self.handle);
}
pub fn setStatusOutput(self: CompressorParams, enable_output: bool) void {
b.compressor_params_set_status_output(self.handle, enable_output);
}
/// `level` ranges from [1, 255]
pub fn setQualityLevel(self: CompressorParams, level: u8) void {
b.compressor_params_set_quality_level(self.handle, level);
}
pub fn getPackUASTCFlags(self: CompressorParams) PackUASTCFlags {
return @bitCast(PackUASTCFlags, b.compressor_params_get_pack_uastc_flags(self.handle));
}
pub fn setPackUASTCFlags(self: CompressorParams, flags: PackUASTCFlags) void {
b.compressor_params_set_pack_uastc_flags(self.handle, @bitCast(u32, flags));
}
pub fn setBasisFormat(self: CompressorParams, format: BasisTextureFormat) void {
b.compressor_params_set_uastc(self.handle, switch (format) {
.etc1s => false,
.uastc4x4 => true,
});
}
pub fn setColorSpace(self: CompressorParams, color_space: ColorSpace) void {
b.compressor_params_set_perceptual(self.handle, switch (color_space) {
.linear => false,
.srgb => true,
});
}
pub fn setMipColorSpace(self: CompressorParams, color_space: ColorSpace) void {
b.compressor_params_set_mip_srgb(self.handle, switch (color_space) {
.linear => false,
.srgb => true,
});
}
/// Disable selector RDO, for faster compression but larger files.
/// Enabled by default
pub fn setSelectorRDO(self: CompressorParams, enable: bool) void {
b.compressor_params_set_no_selector_rdo(self.handle, !enable);
}
/// Enabled by default
pub fn setEndpointRDO(self: CompressorParams, enable: bool) void {
b.compressor_params_set_no_endpoint_rdo(self.handle, !enable);
}
pub fn setRDO_UASTC(self: CompressorParams, enable: bool) void {
b.compressor_params_set_rdo_uastc(self.handle, enable);
}
pub fn setRDO_UASTCQualityScalar(self: CompressorParams, quality: f32) void {
b.compressor_params_set_rdo_uastc_quality_scalar(self.handle, quality);
}
pub fn setGenerateMipMaps(self: CompressorParams, enable: bool) void {
b.compressor_params_set_generate_mipmaps(self.handle, enable);
}
pub fn setMipSmallestDimension(self: CompressorParams, smallest_dimension: i32) void {
b.compressor_params_set_mip_smallest_dimension(self.handle, smallest_dimension);
}
/// Resizes sources list and creates a new Image in case index is out of bounds
pub fn getImageSource(self: CompressorParams, index: u32) Image {
return .{ .handle = b.compressor_params_get_or_create_source_image(self.handle, index) };
}
pub fn resizeImageSource(self: CompressorParams, new_size: u32) void {
b.compressor_params_resize_source_image_list(self.handle, new_size);
}
pub fn clearImageSource(self: CompressorParams) void {
b.compressor_params_clear_source_image_list(self.handle);
}
};
pub const Image = struct {
handle: *b.Image,
pub fn fill(self: Image, data: []const u8, w: u32, h: u32, channels: u3) void {
b.compressor_image_fill(self.handle, data.ptr, w, h, channels);
}
pub fn resize(self: Image, w: u32, h: u32, p: ?u32) void {
b.compressor_image_resize(self.handle, w, h, p orelse std.math.maxInt(u32));
}
pub fn width(self: Image) u32 {
return b.compressor_image_get_width(self.handle);
}
pub fn height(self: Image) u32 {
return b.compressor_image_get_height(self.handle);
}
pub fn pitch(self: Image) u32 {
return b.compressor_image_get_pitch(self.handle);
}
pub fn totalPixels(self: Image) u32 {
return b.compressor_image_get_total_pixels(self.handle);
}
pub fn blockWidth(self: Image, w: u32) u32 {
return (self.width() + (w - 1)) / w;
}
pub fn blockHeight(self: Image, h: u32) u32 {
return (self.height() + (h - 1)) / h;
}
pub fn totalBlocks(self: Image, w: u32, h: u32) u32 {
return self.blockWidth(w) * self.blockHeight(h);
}
};
pub const PackUASTCFlags = packed struct {
fastest: bool = false,
faster: bool = false,
default: bool = false,
slower: bool = false,
verySlow: bool = false,
favor_uastc_error: bool = false,
favor_bc7_error: bool = false,
_padding: u1 = 0,
etc1_faster_hints: bool = false,
etc1_fastest_hints: bool = false,
etc1_disable_flip_and_individual: bool = false,
favor_simpler_modes: bool = false,
_padding0: u20 = 0,
};
pub const ColorSpace = enum {
linear,
srgb,
};