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 }