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}