1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
# basisu_wasm.py
import wasmtime
import ctypes
import sys
sys.path.append("basisu_py") # our shared .py files
from constants import *
class BasisuWasm:
def __init__(self, path):
self.path = path
self.engine = None
self.store = None
self.memory = None
self.exports = None
# -----------------------------------------------
# Internal helper: build WASI + Wasmtime engine
# -----------------------------------------------
def _init_engine(self):
self.engine = wasmtime.Engine()
self.store = wasmtime.Store(self.engine)
wasi = wasmtime.WasiConfig()
wasi.argv = ["basisu"]
wasi.inherit_stdout()
wasi.inherit_stderr()
self.store.set_wasi(wasi)
return wasi
# -----------------------------------------------
# Create linker and instantiate WASM module
# -----------------------------------------------
def load(self):
self._init_engine()
module = wasmtime.Module.from_file(self.engine, self.path)
linker = wasmtime.Linker(self.engine)
linker.define_wasi()
instance = linker.instantiate(self.store, module)
self.exports = instance.exports(self.store)
self.memory = self.exports["memory"]
if "bu_init" in self.exports:
self.exports["bu_init"](self.store)
print("WASM loaded:", self.path)
# -----------------------------------------------
# Read/write WASM linear memory via ctypes
# -----------------------------------------------
def _wasm_buf(self):
raw_ptr = self.memory.data_ptr(self.store)
length = self.memory.data_len(self.store)
addr = ctypes.addressof(raw_ptr.contents)
return (ctypes.c_ubyte * length).from_address(addr)
# -----------------------------------------------
# Exported API accessors
# -----------------------------------------------
def init(self):
return self.exports["bu_init"](self.store)
def version(self):
return self.exports["bu_get_version"](self.store)
def alloc(self, size):
return self.exports["bu_alloc"](self.store, size)
def free(self, ptr):
return self.exports["bu_free"](self.store, ptr)
def new_params(self):
return self.exports["bu_new_comp_params"](self.store)
def delete_params(self, ptr):
return self.exports["bu_delete_comp_params"](self.store, ptr)
def set_image_rgba32(self, params, image_index, img_ptr, w, h, pitch):
return self.exports["bu_comp_params_set_image_rgba32"](
self.store, params, image_index, img_ptr, w, h, pitch
)
def set_image_float_rgba(self, params, image_index, img_ptr, w, h, pitch):
return self.exports["bu_comp_params_set_image_float_rgba"](
self.store, params, image_index, img_ptr, w, h, pitch
)
# Normally quality_level controls the quality.
# If quality_level==-1, then rdo_quality (a low-level parameter) directly
# controls each codec's quality setting. Normally set to 0.
def compress_texture_lowlevel(self, params,
tex_format,
quality_level,
effort_level,
flags_and_quality,
rdo_quality):
return self.exports["bu_compress_texture"](
self.store,
params,
tex_format,
quality_level,
effort_level,
flags_and_quality,
rdo_quality
)
def compress(self, params,
tex_format=BasisTexFormat.cUASTC_LDR_4x4,
quality=BasisQuality.MAX,
effort=BasisEffort.DEFAULT,
flags=BasisFlags.NONE,
rdo_quality=0.0):
return bool(self.compress_texture_lowlevel(
params,
tex_format,
quality,
effort,
flags,
rdo_quality
))
def get_comp_data_ofs(self, params):
return self.exports["bu_comp_params_get_comp_data_ofs"](self.store, params)
def get_comp_data_size(self, params):
return self.exports["bu_comp_params_get_comp_data_size"](self.store, params)
# -----------------------------------------------
# Copy bytes into WASM memory
# -----------------------------------------------
def write_bytes(self, wasm_ptr, data: bytes):
buf = self._wasm_buf()
buf[wasm_ptr:wasm_ptr+len(data)] = data
# -----------------------------------------------
# Read bytes from WASM memory
# -----------------------------------------------
def read_bytes(self, wasm_ptr, size):
buf = self._wasm_buf()
return bytes(buf[wasm_ptr:wasm_ptr+size])
|