File: basisu_wasm.py

package info (click to toggle)
basis-universal 2.0.2-3
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 216,436 kB
  • sloc: cpp: 163,224; ansic: 51,368; python: 2,824; javascript: 2,637; lisp: 1,026; sh: 161; makefile: 17
file content (148 lines) | stat: -rw-r--r-- 4,904 bytes parent folder | download
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])