Mercurial > touhou
comparison python/src/glide/gr.rs @ 772:7492d384d122 default tip
Rust: Add a Glide renderer (2D only for now)
This is an experiment for a Rust renderer, iterating over the Python data using
pyo3. It requires --feature=glide to be passed to cargo build, doesn’t support
NPOT textures, text rendering, the background, or even msg faces, some of that
may come in a future changeset.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Mon, 05 Sep 2022 17:53:36 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
771:79c3f782dd41 | 772:7492d384d122 |
---|---|
1 use core::ptr::null; | |
2 | |
3 #[link(name = "glide2x")] | |
4 extern "C" { | |
5 fn grGlideInit(); | |
6 fn grGlideShutdown(); | |
7 fn grSstSelect(sst: u32); | |
8 fn grSstWinOpen(hwnd: u32, resolution: u32, refresh: u32, color_format: u32, origin_location: u32, num_buf: i32, num_aux_buf: i32); | |
9 fn grBufferSwap(interval: i32); | |
10 fn grBufferClear(color: u32, alpha: u8, depth: u16); | |
11 fn grTexCalcMemRequired(min: Lod, max: Lod, aspect: AspectRatio, format: TextureFormat) -> u32; | |
12 fn grTexDownloadMipMap(tmu: u32, start: u32, even_odd: EvenOdd, info: *const TexInfo); | |
13 fn grTexSource(tmu: u32, start: u32, even_odd: EvenOdd, info: &TexInfo); | |
14 fn grTexMinAddress(tmu: u32) -> u32; | |
15 fn grTexMaxAddress(tmu: u32) -> u32; | |
16 fn guAlphaSource(mode: AlphaSource) -> u32; | |
17 fn guColorCombineFunction(function: ColorCombineFnc) -> u32; | |
18 fn grTexCombineFunction(tmu: u32, function: TextureCombineFnc) -> u32; | |
19 fn grDrawTriangle(a: *const Vertex, b: *const Vertex, c: *const Vertex); | |
20 fn grAlphaBlendFunction(a: Blend, b: Blend, c: Blend, d: Blend); | |
21 } | |
22 | |
23 #[repr(i32)] | |
24 #[derive(Clone, Copy)] | |
25 pub enum Lod { | |
26 L256x256 = 0, | |
27 L128x128 = 1, | |
28 L64x64 = 2, | |
29 L32x32 = 3, | |
30 L16x16 = 4, | |
31 L8x8 = 5, | |
32 L4x4 = 6, | |
33 L2x2 = 7, | |
34 L1x1 = 8, | |
35 } | |
36 | |
37 #[repr(i32)] | |
38 #[derive(Clone, Copy)] | |
39 pub enum AspectRatio { | |
40 A8x1 = 0, | |
41 A4x1 = 1, | |
42 A2x1 = 2, | |
43 A1x1 = 3, | |
44 A1x2 = 4, | |
45 A1x4 = 5, | |
46 A1x8 = 6, | |
47 } | |
48 | |
49 fn lod_aspect_from_dimensions(dimensions: (u32, u32)) -> (Lod, AspectRatio) { | |
50 match dimensions { | |
51 (256, 256) => (Lod::L256x256, AspectRatio::A1x1), | |
52 (128, 128) => (Lod::L128x128, AspectRatio::A1x1), | |
53 (64, 64) => (Lod::L64x64, AspectRatio::A1x1), | |
54 (32, 32) => (Lod::L32x32, AspectRatio::A1x1), | |
55 (16, 16) => (Lod::L16x16, AspectRatio::A1x1), | |
56 (8, 8) => (Lod::L8x8, AspectRatio::A1x1), | |
57 (4, 4) => (Lod::L4x4, AspectRatio::A1x1), | |
58 (2, 2) => (Lod::L2x2, AspectRatio::A1x1), | |
59 (1, 1) => (Lod::L1x1, AspectRatio::A1x1), | |
60 (width, height) => todo!("NPOT texture size {width}×{height}"), | |
61 } | |
62 } | |
63 | |
64 #[repr(i32)] | |
65 #[derive(Clone, Copy, Debug)] | |
66 pub enum TextureFormat { | |
67 Rgb332 = 0, | |
68 Yiq422 = 1, | |
69 Alpha8 = 2, | |
70 Intensity8 = 3, | |
71 AlphaIntensity44 = 4, | |
72 P8 = 5, | |
73 Argb8332 = 8, | |
74 Ayiq8422 = 9, | |
75 Rgb565 = 10, | |
76 Argb1555 = 11, | |
77 Argb4444 = 12, | |
78 AlphaIntensity88 = 13, | |
79 Ap88 = 14, | |
80 } | |
81 | |
82 #[repr(C)] | |
83 pub struct TexInfo { | |
84 pub small_lod: Lod, | |
85 pub large_lod: Lod, | |
86 pub aspect: AspectRatio, | |
87 pub format: TextureFormat, | |
88 data: *const u8, | |
89 } | |
90 | |
91 impl TexInfo { | |
92 pub fn new(width: u32, height: u32, format: TextureFormat) -> TexInfo { | |
93 let (lod, aspect) = lod_aspect_from_dimensions((width, height)); | |
94 TexInfo { | |
95 small_lod: lod, | |
96 large_lod: lod, | |
97 aspect, | |
98 format, | |
99 data: null(), | |
100 } | |
101 } | |
102 | |
103 pub fn with_data(width: u32, height: u32, format: TextureFormat, data: &[u8]) -> TexInfo { | |
104 let (lod, aspect) = lod_aspect_from_dimensions((width, height)); | |
105 TexInfo { | |
106 small_lod: lod, | |
107 large_lod: lod, | |
108 aspect, | |
109 format, | |
110 data: data.as_ptr(), | |
111 } | |
112 } | |
113 } | |
114 | |
115 #[repr(C)] | |
116 pub struct Vertex { | |
117 x: f32, | |
118 y: f32, | |
119 z: f32, | |
120 r: f32, | |
121 g: f32, | |
122 b: f32, | |
123 ooz: f32, | |
124 a: f32, | |
125 oow: f32, | |
126 sow0: f32, | |
127 tow0: f32, | |
128 oow0: f32, | |
129 sow1: f32, | |
130 tow1: f32, | |
131 oow1: f32, | |
132 } | |
133 | |
134 impl Vertex { | |
135 pub fn new(x: f32, y: f32, sow: f32, tow: f32, color: u32) -> Vertex { | |
136 let z = 1.0; | |
137 let r = ((color >> 24) & 0xff) as f32; | |
138 let g = ((color >> 16) & 0xff) as f32; | |
139 let b = ((color >> 8) & 0xff) as f32; | |
140 let a = (color & 0xff) as f32; | |
141 let ooz = 1.0; | |
142 let oow = 1.0; | |
143 let sow0 = sow; | |
144 let tow0 = tow; | |
145 let oow0 = 1.0; | |
146 let sow1 = sow; | |
147 let tow1 = tow; | |
148 let oow1 = 1.0; | |
149 Vertex { | |
150 x, y, z, | |
151 r, g, b, | |
152 ooz, | |
153 a, | |
154 oow, | |
155 sow0, tow0, oow0, | |
156 sow1, tow1, oow1, | |
157 } | |
158 } | |
159 } | |
160 | |
161 pub fn glide_init() { | |
162 unsafe { grGlideInit() }; | |
163 } | |
164 | |
165 pub fn glide_shutdown() { | |
166 unsafe { grGlideShutdown() }; | |
167 } | |
168 | |
169 pub fn sst_select(sst: u32) { | |
170 unsafe { grSstSelect(sst) }; | |
171 } | |
172 | |
173 pub fn sst_win_open(width: u32, height: u32, refresh: u32) { | |
174 let resolution = match (width, height) { | |
175 (320, 200) => 0, | |
176 (320, 240) => 1, | |
177 (400, 256) => 2, | |
178 (512, 384) => 3, | |
179 (640, 200) => 4, | |
180 (640, 350) => 5, | |
181 (640, 400) => 6, | |
182 (640, 480) => 7, | |
183 _ => unreachable!("Unknown screen resolution {width}×{height}."), | |
184 }; | |
185 let refresh = match refresh { | |
186 60 => 0, | |
187 70 => 1, | |
188 72 => 2, | |
189 75 => 3, | |
190 80 => 4, | |
191 90 => 5, | |
192 100 => 6, | |
193 85 => 7, | |
194 120 => 8, | |
195 _ => unreachable!("Unknown refresh rate {refresh} Hz."), | |
196 }; | |
197 let color_format = 2; // RGBA | |
198 let origin_location = 0; // Upper Left | |
199 unsafe { grSstWinOpen(0, resolution, refresh, color_format, origin_location, 2, 0) }; | |
200 } | |
201 | |
202 pub fn buffer_swap(interval: i32) { | |
203 unsafe { grBufferSwap(interval) }; | |
204 } | |
205 | |
206 pub fn buffer_clear(color: u32, alpha: u8, depth: u16) { | |
207 unsafe { grBufferClear(color, alpha, depth) }; | |
208 } | |
209 | |
210 pub fn tex_calc_mem_required(small_lod: Lod, large_lod: Lod, aspect: AspectRatio, format: TextureFormat) -> u32 { | |
211 unsafe { grTexCalcMemRequired(small_lod, large_lod, aspect, format) } | |
212 } | |
213 | |
214 pub fn tex_download_mip_map(tmu: u32, start: u32, even_odd: EvenOdd, info: &TexInfo) { | |
215 unsafe { grTexDownloadMipMap(tmu, start, even_odd, info) }; | |
216 } | |
217 | |
218 pub fn tex_source(tmu: u32, start: u32, even_odd: EvenOdd, info: &TexInfo) { | |
219 unsafe { grTexSource(tmu, start, even_odd, info) }; | |
220 } | |
221 | |
222 pub fn tex_min_address(tmu: u32) -> u32 { | |
223 unsafe { grTexMinAddress(tmu) } | |
224 } | |
225 | |
226 pub fn tex_max_address(tmu: u32) -> u32 { | |
227 unsafe { grTexMaxAddress(tmu) } | |
228 } | |
229 | |
230 pub fn alpha_source(mode: AlphaSource) { | |
231 unsafe { guAlphaSource(mode) }; | |
232 } | |
233 | |
234 pub fn color_combine_function(function: ColorCombineFnc) { | |
235 unsafe { guColorCombineFunction(function) }; | |
236 } | |
237 | |
238 pub fn tex_combine_function(tmu: u32, function: TextureCombineFnc) { | |
239 unsafe { grTexCombineFunction(tmu, function) }; | |
240 } | |
241 | |
242 pub fn alpha_blend_function(a: Blend, b: Blend, c: Blend, d: Blend) { | |
243 unsafe { grAlphaBlendFunction(a, b, c, d) }; | |
244 } | |
245 | |
246 #[repr(i32)] | |
247 pub enum EvenOdd { | |
248 Even = 0, | |
249 Odd = 1, | |
250 Both = 2, | |
251 } | |
252 | |
253 #[repr(i32)] | |
254 pub enum Blend { | |
255 Zero = 0, | |
256 SrcAlpha = 1, | |
257 SrcColor = 2, | |
258 DstAlpha = 3, | |
259 One = 4, | |
260 OneMinusSrcAlpha = 5, | |
261 OneMinusSrcColor = 6, | |
262 OneMinusDstAlpha = 7, | |
263 AlphaSaturate = 15, | |
264 } | |
265 | |
266 #[repr(i32)] | |
267 pub enum AlphaSource { | |
268 CcAlpha = 0, | |
269 IteratedAlpha = 1, | |
270 TextureAlpha = 2, | |
271 TextureAlphaTimesIteratedAlpha = 3, | |
272 } | |
273 | |
274 #[repr(i32)] | |
275 pub enum ColorCombineFnc { | |
276 Zero = 0, | |
277 Ccrgb = 1, | |
278 Itrgb = 2, | |
279 ItrgbDelta0 = 3, | |
280 DecalTexture = 4, | |
281 TextureTimesCcrgb = 5, | |
282 TextureTimesItrgb = 6, | |
283 TextureTimesItrgbDelta0 = 7, | |
284 TextureTimesItrgbAddAlpha = 8, | |
285 TextureTimesAlpha = 9, | |
286 TextureTimesAlphaAddItrgb = 10, | |
287 TextureAddItrgb = 11, | |
288 TextureSubItrgb = 12, | |
289 CcrgbBlendItrgbOnTexalpha = 13, | |
290 DiffSpecA = 14, | |
291 DiffSpecB = 15, | |
292 One = 16, | |
293 } | |
294 | |
295 #[repr(i32)] | |
296 pub enum TextureCombineFnc { | |
297 Zero = 0, | |
298 Decal = 1, | |
299 Other = 2, | |
300 Add = 3, | |
301 Multiply = 4, | |
302 Subtract = 5, | |
303 Detail = 6, | |
304 DetailOther = 7, | |
305 TrilinearOdd = 8, | |
306 TrilinearEven = 9, | |
307 One = 10, | |
308 } | |
309 | |
310 pub fn draw_triangle(a: &Vertex, b: &Vertex, c: &Vertex) { | |
311 unsafe { grDrawTriangle(a, b, c) }; | |
312 } |