code wiki / _hdl_build / nx_gx1c_canvas_gate.nx

nx_gx1c_canvas_gate.nx source

↩ module page · 143 lines · 8855 B

1// nx_gx1c_canvas_gate.nx -- Gx-1c (seq103 EAT-BY-BUILD): <canvas> = a FIRST-CLASS sourceless render surface 2// in the LIVE Nishi-Browser + the PER-FRAME loop = the sovereign GAME SUBSTRATE. A fetched page DECLARES 3// <canvas>; br_layout gives it a real CSS-sized box in flow (page.bcanvas + br_find_canvas); the game loop 4// then drives frames: update world state (yaw) -> render the REAL nx_swgpu mesh pipeline (sg_humanoid + 5// sg_project + sg_render -- the seq103 DRY fold, NO inline rasterizer in this gate) -> point page.bimg at the 6// fresh buffer -> the browser repaints the whole page. Frame time MEASURED (mono clock, envelope declared). 7// Neg-control: a page WITHOUT <canvas> finds none. license_tier: ORIGINAL expect_exit: 0 8import "nx_browser_render.nx" 9import "nx_swgpu.nx" 10 11func gxc_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 12func gxc_pn(v: i64) -> i64 { let b: *u8=sys_mmap(32) as *u8; var x: i64=v; var ng: i64=0; if x<0{ng=1;x=0-x} var i: i64=31; if x==0{b[i]=48 as u8;i=i-1} while x>0{b[i]=(48+x%10) as u8;x=x/10;i=i-1} if ng==1{b[i]=45 as u8;i=i-1} sys_write(1,(b as i64+i+1) as *u8,31-i); return 0 } 13func gxc_now_ms() -> i64 { let ts: *i64=sys_mmap(16) as *i64; sys_clock_gettime_mono(ts); return ts[0]*1000 + ts[1]/1000000 } 14 15// swgpu i64 framebuffer (r + g*256 + b*65536) -> tightly packed RGB bytes 16func gxc_fb_to_rgb(base: i64, dst: *u8) -> i64 { 17 let fb: *i64 = sg_fb(base) 18 var p: i64 = 0 19 while p < ww()*hh() { 20 let v: i64 = fb[p] 21 dst[p*3] = (v % 256) as u8 22 dst[p*3+1] = ((v/256) % 256) as u8 23 dst[p*3+2] = ((v/65536) % 256) as u8 24 p = p + 1 25 } 26 return 0 27} 28 29func main() -> i64 { 30 gxc_puts("=== nx_gx1c_canvas_gate -- <canvas> surface + per-frame loop = the sovereign game substrate ===\n" as *u8) 31 var fails: i64=0 32 33 // ---- T0 NEG-CONTROL: a page with NO canvas finds none ---- 34 let h0: *u8 = "<html><body><h1>plain</h1><p>no render surface on this page</p></body></html>\x00" as *u8 35 let p0: *Page = sys_mmap(NX_PAGE_BYTES) as *Page 36 p0.raw = h0; p0.raw_len = br_slen(h0); p0.dark_mode = 0 37 br_layout(p0, 1000) 38 if br_find_canvas(p0, 0) == (0-1) { gxc_puts("T0 PASS neg-control: canvas-less page finds no canvas box\n" as *u8) } 39 else { fails=fails+1; gxc_puts("T0 FAIL neg-control\n" as *u8) } 40 41 // ---- the GAME page: heading + copy + <canvas> + copy, canvas sized by author CSS ---- 42 let html: *u8 = "<html><head><style>canvas{display:block;width:512px;height:384px;margin:18px 0}</style></head><body><h1>Sovereign Game Surface</h1><p>This page is fetched, parsed, and laid out by our own browser engine. The canvas below is a first-class sourceless render surface: each frame the sovereign software GPU renders the world state and the browser repaints it in place.</p><canvas></canvas><p>No WebGPU. No WebGL. No third-party. The game loop is ours from the first byte.</p></body></html>\x00" as *u8 43 let page: *Page = sys_mmap(NX_PAGE_BYTES) as *Page 44 page.raw = html; page.raw_len = br_slen(html); page.dark_mode = 0 45 br_layout(page, 1000) 46 var t1: i64=0 47 if page.ok==1 { if page.tree.count>5 { t1=1 } } 48 gxc_puts(" layout boxes="); gxc_pn(page.tree.count); gxc_puts(" page_h="); gxc_pn(page.page_h); gxc_puts("\n" as *u8) 49 if t1==1 { gxc_puts("T1 PASS the live engine laid out the game page\n" as *u8) } else { fails=fails+1; gxc_puts("T1 FAIL layout\n" as *u8) } 50 51 // ---- T2 the <canvas> element became a REAL laid-out box ---- 52 let cv: i64 = br_find_canvas(page, 0) 53 var cvx: i64=0; var cvy: i64=0 54 if cv>=0 { 55 let cb: *LayoutBox = ((page.tree.boxes as i64)+cv*NX_LAYOUT_BOX_BYTES) as *LayoutBox 56 cvx=cb.x; cvy=cb.y 57 } 58 gxc_puts(" canvas box idx="); gxc_pn(cv); gxc_puts(" at x="); gxc_pn(cvx); gxc_puts(" y="); gxc_pn(cvy); gxc_puts("\n" as *u8) 59 if cv>=0 { gxc_puts("T2 PASS <canvas> is a first-class laid-out box (page.bcanvas)\n" as *u8) } else { fails=fails+1; gxc_puts("T2 FAIL no canvas box\n" as *u8) } 60 61 // ---- T3 FLOW: the canvas sits BELOW the heading (a real in-flow box, not an overlay) ---- 62 var t3: i64=0 63 if cv>=0 { if cvy>40 { t3=1 } } 64 if t3==1 { gxc_puts("T3 PASS canvas is in flow below the heading (y="); gxc_pn(cvy); gxc_puts(")\n" as *u8) } else { fails=fails+1; gxc_puts("T3 FAIL canvas y="); gxc_pn(cvy); gxc_puts("\n" as *u8) } 65 66 // ---- the GAME LOOP: 4 frames, world state = yaw; render = the REAL nx_swgpu pipeline ---- 67 let base: i64 = sys_mmap(swgpu_bytes()) as i64 68 let f0: *u8 = sys_mmap(ww()*hh()*3+16) 69 let fc: *u8 = sys_mmap(ww()*hh()*3+16) 70 let t_start: i64 = gxc_now_ms() 71 var f: i64=0 72 while f<4 { 73 let yaw: i64 = 500 + f*1600 74 sg_reset(base) 75 sg_humanoid(base, 14) 76 sg_project(base, yaw, 0-5) 77 sg_render(base, 240, 182, 158) 78 var dst: *u8 = fc 79 if f==0 { dst = f0 } 80 gxc_fb_to_rgb(base, dst) 81 if cv>=0 { page.bimg[cv] = dst as i64; page.bimg_w[cv] = ww(); page.bimg_h[cv] = hh() } 82 if f==0 { br_shot_png(page, "https://nishifamily.com/world/game\x00" as *u8, 34, "knowledge/nx_gx1c_f0.png\x00" as *u8) } 83 if f==1 { br_shot_png(page, "https://nishifamily.com/world/game\x00" as *u8, 34, "knowledge/nx_gx1c_f1.png\x00" as *u8) } 84 if f==2 { br_shot_png(page, "https://nishifamily.com/world/game\x00" as *u8, 34, "knowledge/nx_gx1c_f2.png\x00" as *u8) } 85 if f==3 { br_shot_png(page, "https://nishifamily.com/world/game\x00" as *u8, 34, "knowledge/nx_gx1c_f3.png\x00" as *u8) } 86 f=f+1 87 } 88 let ms_total: i64 = gxc_now_ms() - t_start 89 gxc_puts(" MEASURED: 4 frames in "); gxc_pn(ms_total); gxc_puts(" ms = "); gxc_pn(ms_total/4) 90 gxc_puts(" ms/frame (envelope: swgpu 512x384 mesh render + FULL 1000x1000 browser repaint + PNG encode per frame)\n" as *u8) 91 92 // ---- T4 the swgpu rendered a real BODY into frame 0 (pixels off the analytic background gradient) ---- 93 var bodypx: i64=0 94 var pi: i64=0 95 while pi < ww()*hh() { 96 let row: i64 = pi / ww() 97 let bgr: i64 = 26 + row*36/hh() 98 let bgg: i64 = 28 + row*34/hh() 99 let bgb: i64 = 42 + row*30/hh() 100 var d1: i64 = (f0[pi*3] as i64) - bgr; if d1<0 { d1=0-d1 } 101 var d2: i64 = (f0[pi*3+1] as i64) - bgg; if d2<0 { d2=0-d2 } 102 var d3: i64 = (f0[pi*3+2] as i64) - bgb; if d3<0 { d3=0-d3 } 103 if d1+d2+d3 > 40 { bodypx=bodypx+1 } 104 pi = pi + 7 105 } 106 var t4: i64=0 107 if bodypx>1500 { t4=1 } 108 gxc_puts(" body pixels (sampled/7)="); gxc_pn(bodypx); gxc_puts("\n" as *u8) 109 if t4==1 { gxc_puts("T4 PASS nx_swgpu rendered the world into the canvas (DRY: sg_humanoid+sg_project+sg_render)\n" as *u8) } else { fails=fails+1; gxc_puts("T4 FAIL bodypx="); gxc_pn(bodypx); gxc_puts("\n" as *u8) } 110 111 // ---- T5 ANIMATION IS REAL: frame 3 differs from frame 0 (the world state advanced) ---- 112 var diffpx: i64=0 113 pi=0 114 while pi < ww()*hh() { 115 var e1: i64 = (f0[pi*3] as i64) - (fc[pi*3] as i64); if e1<0 { e1=0-e1 } 116 var e2: i64 = (f0[pi*3+1] as i64) - (fc[pi*3+1] as i64); if e2<0 { e2=0-e2 } 117 var e3: i64 = (f0[pi*3+2] as i64) - (fc[pi*3+2] as i64); if e3<0 { e3=0-e3 } 118 if e1+e2+e3 > 30 { diffpx=diffpx+1 } 119 pi = pi + 7 120 } 121 var t5: i64=0 122 if diffpx>400 { t5=1 } 123 gxc_puts(" frame0 vs frame3 changed pixels (sampled/7)="); gxc_pn(diffpx); gxc_puts("\n" as *u8) 124 if t5==1 { gxc_puts("T5 PASS per-frame loop animates: the yaw state advanced and the surface changed\n" as *u8) } else { fails=fails+1; gxc_puts("T5 FAIL diffpx="); gxc_pn(diffpx); gxc_puts("\n" as *u8) } 125 126 // ---- T6 all 4 browser-painted frames are on disk ---- 127 let szp: *i64 = sys_mmap(16) as *i64 128 var okpng: i64=0 129 let r0: *u8 = sys_read_file("knowledge/nx_gx1c_f0.png\x00" as *u8, szp) 130 if (r0 as i64)!=0 { if szp[0]>1000 { okpng=okpng+1 } } 131 let r1: *u8 = sys_read_file("knowledge/nx_gx1c_f1.png\x00" as *u8, szp) 132 if (r1 as i64)!=0 { if szp[0]>1000 { okpng=okpng+1 } } 133 let r2: *u8 = sys_read_file("knowledge/nx_gx1c_f2.png\x00" as *u8, szp) 134 if (r2 as i64)!=0 { if szp[0]>1000 { okpng=okpng+1 } } 135 let r3: *u8 = sys_read_file("knowledge/nx_gx1c_f3.png\x00" as *u8, szp) 136 if (r3 as i64)!=0 { if szp[0]>1000 { okpng=okpng+1 } } 137 if okpng==4 { gxc_puts("T6 PASS all 4 browser-painted frames on disk (knowledge/nx_gx1c_f0..f3.png)\n" as *u8) } else { fails=fails+1; gxc_puts("T6 FAIL frames on disk="); gxc_pn(okpng); gxc_puts("\n" as *u8) } 138 139 if fails==0 { gxc_puts("GX1C-CANVAS GREEN -- <canvas> is a first-class surface in the live browser and the per-frame sovereign game loop runs through it (zero 3rd-party)\n" as *u8); sys_exit(0); return 0 } 140 gxc_puts("GX1C-CANVAS RED fails="); gxc_pn(fails); gxc_puts("\n" as *u8) 141 sys_exit(1) 142 return 1 143}