diff 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
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/python/src/glide/gr.rs
@@ -0,0 +1,312 @@
+use core::ptr::null;
+
+#[link(name = "glide2x")]
+extern "C" {
+    fn grGlideInit();
+    fn grGlideShutdown();
+    fn grSstSelect(sst: u32);
+    fn grSstWinOpen(hwnd: u32, resolution: u32, refresh: u32, color_format: u32, origin_location: u32, num_buf: i32, num_aux_buf: i32);
+    fn grBufferSwap(interval: i32);
+    fn grBufferClear(color: u32, alpha: u8, depth: u16);
+    fn grTexCalcMemRequired(min: Lod, max: Lod, aspect: AspectRatio, format: TextureFormat) -> u32;
+    fn grTexDownloadMipMap(tmu: u32, start: u32, even_odd: EvenOdd, info: *const TexInfo);
+    fn grTexSource(tmu: u32, start: u32, even_odd: EvenOdd, info: &TexInfo);
+    fn grTexMinAddress(tmu: u32) -> u32;
+    fn grTexMaxAddress(tmu: u32) -> u32;
+    fn guAlphaSource(mode: AlphaSource) -> u32;
+    fn guColorCombineFunction(function: ColorCombineFnc) -> u32;
+    fn grTexCombineFunction(tmu: u32, function: TextureCombineFnc) -> u32;
+    fn grDrawTriangle(a: *const Vertex, b: *const Vertex, c: *const Vertex);
+    fn grAlphaBlendFunction(a: Blend, b: Blend, c: Blend, d: Blend);
+}
+
+#[repr(i32)]
+#[derive(Clone, Copy)]
+pub enum Lod {
+    L256x256 = 0,
+    L128x128 = 1,
+    L64x64 = 2,
+    L32x32 = 3,
+    L16x16 = 4,
+    L8x8 = 5,
+    L4x4 = 6,
+    L2x2 = 7,
+    L1x1 = 8,
+}
+
+#[repr(i32)]
+#[derive(Clone, Copy)]
+pub enum AspectRatio {
+    A8x1 = 0,
+    A4x1 = 1,
+    A2x1 = 2,
+    A1x1 = 3,
+    A1x2 = 4,
+    A1x4 = 5,
+    A1x8 = 6,
+}
+
+fn lod_aspect_from_dimensions(dimensions: (u32, u32)) -> (Lod, AspectRatio) {
+    match dimensions {
+        (256, 256) => (Lod::L256x256, AspectRatio::A1x1),
+        (128, 128) => (Lod::L128x128, AspectRatio::A1x1),
+        (64, 64) => (Lod::L64x64, AspectRatio::A1x1),
+        (32, 32) => (Lod::L32x32, AspectRatio::A1x1),
+        (16, 16) => (Lod::L16x16, AspectRatio::A1x1),
+        (8, 8) => (Lod::L8x8, AspectRatio::A1x1),
+        (4, 4) => (Lod::L4x4, AspectRatio::A1x1),
+        (2, 2) => (Lod::L2x2, AspectRatio::A1x1),
+        (1, 1) => (Lod::L1x1, AspectRatio::A1x1),
+        (width, height) => todo!("NPOT texture size {width}×{height}"),
+    }
+}
+
+#[repr(i32)]
+#[derive(Clone, Copy, Debug)]
+pub enum TextureFormat {
+    Rgb332 = 0,
+    Yiq422 = 1,
+    Alpha8 = 2,
+    Intensity8 = 3,
+    AlphaIntensity44 = 4,
+    P8 = 5,
+    Argb8332 = 8,
+    Ayiq8422 = 9,
+    Rgb565 = 10,
+    Argb1555 = 11,
+    Argb4444 = 12,
+    AlphaIntensity88 = 13,
+    Ap88 = 14,
+}
+
+#[repr(C)]
+pub struct TexInfo {
+    pub small_lod: Lod,
+    pub large_lod: Lod,
+    pub aspect: AspectRatio,
+    pub format: TextureFormat,
+    data: *const u8,
+}
+
+impl TexInfo {
+    pub fn new(width: u32, height: u32, format: TextureFormat) -> TexInfo {
+        let (lod, aspect) = lod_aspect_from_dimensions((width, height));
+        TexInfo {
+            small_lod: lod,
+            large_lod: lod,
+            aspect,
+            format,
+            data: null(),
+        }
+    }
+
+    pub fn with_data(width: u32, height: u32, format: TextureFormat, data: &[u8]) -> TexInfo {
+        let (lod, aspect) = lod_aspect_from_dimensions((width, height));
+        TexInfo {
+            small_lod: lod,
+            large_lod: lod,
+            aspect,
+            format,
+            data: data.as_ptr(),
+        }
+    }
+}
+
+#[repr(C)]
+pub struct Vertex {
+    x: f32,
+    y: f32,
+    z: f32,
+    r: f32,
+    g: f32,
+    b: f32,
+    ooz: f32,
+    a: f32,
+    oow: f32,
+    sow0: f32,
+    tow0: f32,
+    oow0: f32,
+    sow1: f32,
+    tow1: f32,
+    oow1: f32,
+}
+
+impl Vertex {
+    pub fn new(x: f32, y: f32, sow: f32, tow: f32, color: u32) -> Vertex {
+        let z = 1.0;
+        let r = ((color >> 24) & 0xff) as f32;
+        let g = ((color >> 16) & 0xff) as f32;
+        let b = ((color >> 8) & 0xff) as f32;
+        let a = (color & 0xff) as f32;
+        let ooz = 1.0;
+        let oow = 1.0;
+        let sow0 = sow;
+        let tow0 = tow;
+        let oow0 = 1.0;
+        let sow1 = sow;
+        let tow1 = tow;
+        let oow1 = 1.0;
+        Vertex {
+            x, y, z,
+            r, g, b,
+            ooz,
+            a,
+            oow,
+            sow0, tow0, oow0,
+            sow1, tow1, oow1,
+        }
+    }
+}
+
+pub fn glide_init() {
+    unsafe { grGlideInit() };
+}
+
+pub fn glide_shutdown() {
+    unsafe { grGlideShutdown() };
+}
+
+pub fn sst_select(sst: u32) {
+    unsafe { grSstSelect(sst) };
+}
+
+pub fn sst_win_open(width: u32, height: u32, refresh: u32) {
+    let resolution = match (width, height) {
+        (320, 200) => 0,
+        (320, 240) => 1,
+        (400, 256) => 2,
+        (512, 384) => 3,
+        (640, 200) => 4,
+        (640, 350) => 5,
+        (640, 400) => 6,
+        (640, 480) => 7,
+        _ => unreachable!("Unknown screen resolution {width}×{height}."),
+    };
+    let refresh = match refresh {
+        60 => 0,
+        70 => 1,
+        72 => 2,
+        75 => 3,
+        80 => 4,
+        90 => 5,
+        100 => 6,
+        85 => 7,
+        120 => 8,
+        _ => unreachable!("Unknown refresh rate {refresh} Hz."),
+    };
+    let color_format = 2; // RGBA
+    let origin_location = 0; // Upper Left
+    unsafe { grSstWinOpen(0, resolution, refresh, color_format, origin_location, 2, 0) };
+}
+
+pub fn buffer_swap(interval: i32) {
+    unsafe { grBufferSwap(interval) };
+}
+
+pub fn buffer_clear(color: u32, alpha: u8, depth: u16) {
+    unsafe { grBufferClear(color, alpha, depth) };
+}
+
+pub fn tex_calc_mem_required(small_lod: Lod, large_lod: Lod, aspect: AspectRatio, format: TextureFormat) -> u32 {
+    unsafe { grTexCalcMemRequired(small_lod, large_lod, aspect, format) }
+}
+
+pub fn tex_download_mip_map(tmu: u32, start: u32, even_odd: EvenOdd, info: &TexInfo) {
+    unsafe { grTexDownloadMipMap(tmu, start, even_odd, info) };
+}
+
+pub fn tex_source(tmu: u32, start: u32, even_odd: EvenOdd, info: &TexInfo) {
+    unsafe { grTexSource(tmu, start, even_odd, info) };
+}
+
+pub fn tex_min_address(tmu: u32) -> u32 {
+    unsafe { grTexMinAddress(tmu) }
+}
+
+pub fn tex_max_address(tmu: u32) -> u32 {
+    unsafe { grTexMaxAddress(tmu) }
+}
+
+pub fn alpha_source(mode: AlphaSource) {
+    unsafe { guAlphaSource(mode) };
+}
+
+pub fn color_combine_function(function: ColorCombineFnc) {
+    unsafe { guColorCombineFunction(function) };
+}
+
+pub fn tex_combine_function(tmu: u32, function: TextureCombineFnc) {
+    unsafe { grTexCombineFunction(tmu, function) };
+}
+
+pub fn alpha_blend_function(a: Blend, b: Blend, c: Blend, d: Blend) {
+    unsafe { grAlphaBlendFunction(a, b, c, d) };
+}
+
+#[repr(i32)]
+pub enum EvenOdd {
+    Even = 0,
+    Odd = 1,
+    Both = 2,
+}
+
+#[repr(i32)]
+pub enum Blend {
+    Zero = 0,
+    SrcAlpha = 1,
+    SrcColor = 2,
+    DstAlpha = 3,
+    One = 4,
+    OneMinusSrcAlpha = 5,
+    OneMinusSrcColor = 6,
+    OneMinusDstAlpha = 7,
+    AlphaSaturate = 15,
+}
+
+#[repr(i32)]
+pub enum AlphaSource {
+    CcAlpha = 0,
+    IteratedAlpha = 1,
+    TextureAlpha = 2,
+    TextureAlphaTimesIteratedAlpha = 3,
+}
+
+#[repr(i32)]
+pub enum ColorCombineFnc {
+    Zero = 0,
+    Ccrgb = 1,
+    Itrgb = 2,
+    ItrgbDelta0 = 3,
+    DecalTexture = 4,
+    TextureTimesCcrgb = 5,
+    TextureTimesItrgb = 6,
+    TextureTimesItrgbDelta0 = 7,
+    TextureTimesItrgbAddAlpha = 8,
+    TextureTimesAlpha = 9,
+    TextureTimesAlphaAddItrgb = 10,
+    TextureAddItrgb = 11,
+    TextureSubItrgb = 12,
+    CcrgbBlendItrgbOnTexalpha = 13,
+    DiffSpecA = 14,
+    DiffSpecB = 15,
+    One = 16,
+}
+
+#[repr(i32)]
+pub enum TextureCombineFnc {
+    Zero = 0,
+    Decal = 1,
+    Other = 2,
+    Add = 3,
+    Multiply = 4,
+    Subtract = 5,
+    Detail = 6,
+    DetailOther = 7,
+    TrilinearOdd = 8,
+    TrilinearEven = 9,
+    One = 10,
+}
+
+pub fn draw_triangle(a: &Vertex, b: &Vertex, c: &Vertex) {
+    unsafe { grDrawTriangle(a, b, c) };
+}