code wiki / (root) / nx_graphics_demo_test.nx

nx_graphics_demo_test.nx source

↩ module page · 118 lines · 4364 B

1// nx_graphics_demo_test.nx -- end-to-end G1 pipeline KAT. 2// 3// Proves the full bits-up graphics path from raster to viewable image: 4// 5// alloc fb -> clear black -> rasterize triangle (Pineda edge fn) -> 6// present via swapchain (PPM_BUFFER destination) -> verify PPM bytes 7// 8// Composes: 9// nx_framebuffer.nx (i64 cell buffer + clear + set + pack_rgba) 10// nx_raster_sw.nx (Pineda triangle rasterizer) 11// nx_swapchain.nx (destination abstraction) 12// nx_ppm_writer.nx (PPM P6 serializer, via swapchain) 13// 14// This is the substrate-honest "see it work end-to-end" gate for 15// NISHI_GRAPHICS_ROADMAP G1. Same primitives, ONE call. 16 17import "nx_syscalls.nx" 18import "nx_framebuffer.nx" 19import "nx_raster_sw.nx" 20import "nx_swapchain.nx" 21 22func main() -> i64 { 23 let w: nx_int = 8 24 let h: nx_int = 8 25 let fb: *i64 = nx_fb_alloc(w, h) 26 let black: nx_int = 0 27 let red: nx_int = nx_fb_pack_rgba(255, 0, 0, 255) 28 29 // ----- Render: clear + rasterize triangle (2,2)(7,2)(2,7) ----- 30 // Strict-interior coverage: pixels with x>=3, y>=3, x+y<=8 in fb bounds. 31 // y=3: x in [3,5] 3 pixels 32 // y=4: x in [3,4] 2 pixels 33 // y=5: x in [3,3] 1 pixel 34 // total 6 pixels 35 nx_fb_clear(fb, w, h, black) 36 let n_drawn: i64 = nx_raster_triangle( 37 fb, w, h, 2, 2, 7, 2, 2, 7, red 38 ) 39 if n_drawn != 6 { return 1 } 40 41 // ----- Sanity-check framebuffer pixel reads ----- 42 if nx_fb_get(fb, w, h, 3, 3) != red { return 2 } 43 if nx_fb_get(fb, w, h, 5, 3) != red { return 3 } 44 if nx_fb_get(fb, w, h, 3, 5) != red { return 4 } 45 if nx_fb_get(fb, w, h, 0, 0) != black { return 5 } 46 if nx_fb_get(fb, w, h, 7, 7) != black { return 6 } 47 48 // ----- Present via swapchain to PPM buffer ----- 49 // 8x8 PPM: header "P6\n8 8\n255\n" = 11 bytes; data 8*8*3 = 192; 50 // total 203 bytes. 51 let out_cap: i64 = 512 52 let out: *u8 = sys_mmap(out_cap) 53 let n_bytes: i64 = nx_swap_present( 54 fb, w, h, NX_SWAP_DEST_PPM_BUFFER, out, out_cap 55 ) 56 if n_bytes != 203 { return 10 } 57 58 // ----- Verify PPM header bytes ----- 59 if out[0] != 0x50 { return 20 } // 'P' 60 if out[1] != 0x36 { return 21 } // '6' 61 if out[2] != 0x0A { return 22 } // '\n' 62 if out[3] != 0x38 { return 23 } // '8' (width) 63 if out[4] != 0x20 { return 24 } // ' ' 64 if out[5] != 0x38 { return 25 } // '8' (height) 65 if out[6] != 0x0A { return 26 } // '\n' 66 // "255\n" at offsets 7..10 67 if out[7] != 0x32 { return 27 } // '2' 68 if out[8] != 0x35 { return 28 } // '5' 69 if out[9] != 0x35 { return 29 } // '5' 70 if out[10] != 0x0A { return 30 } // '\n' 71 72 // ----- Verify PPM data bytes ----- 73 // Pixel (0, 0) at data offset 0: black (0, 0, 0). 74 if out[11] != 0 { return 40 } 75 if out[12] != 0 { return 41 } 76 if out[13] != 0 { return 42 } 77 78 // Pixel (3, 3) at data offset 3*(3*8+3) = 81. Header start at 11. 79 // PPM byte offset for (3,3) RGB = 11 + 81 = 92, 93, 94. 80 // Red was packed (255, 0, 0, 255) -> RGB bytes (255, 0, 0). 81 if out[92] != 255 { return 50 } 82 if out[93] != 0 { return 51 } 83 if out[94] != 0 { return 52 } 84 85 // Pixel (7, 7) at data offset 3*(7*8+7) = 3*63 = 189. 86 // PPM byte offset 11 + 189 = 200. Black. 87 if out[200] != 0 { return 60 } 88 if out[201] != 0 { return 61 } 89 if out[202] != 0 { return 62 } 90 91 // ----- Swapchain destination sanity ------ 92 // DISCARD destination returns 0 bytes, no writes performed. 93 let n_discard: i64 = nx_swap_present( 94 fb, w, h, NX_SWAP_DEST_DISCARD, out, out_cap 95 ) 96 if n_discard != 0 { return 70 } 97 98 // KMS_DIRECT stub returns ENOTIMPL deterministically. Substrate- 99 // honest: never silently no-ops on a queued backend. 100 let n_kms: i64 = nx_swap_present( 101 fb, w, h, NX_SWAP_DEST_KMS_DIRECT, out, out_cap 102 ) 103 if n_kms != NX_SWAP_ERR_NOT_IMPL { return 71 } 104 105 // Invalid destination returns BAD_DEST. 106 let n_bad: i64 = nx_swap_present( 107 fb, w, h, 999, out, out_cap 108 ) 109 if n_bad != NX_SWAP_ERR_BAD_DEST { return 72 } 110 111 // Too-small output buffer returns SHORT_BUF (never partial write). 112 let n_short: i64 = nx_swap_present( 113 fb, w, h, NX_SWAP_DEST_PPM_BUFFER, out, 32 114 ) 115 if n_short != NX_SWAP_ERR_SHORT_BUF { return 73 } 116 117 return 0 118}