nx_x11_put_image.nx source
↩ module page · 120 lines · 4560 B
1// nx_x11_put_image.nx -- bits-up X11 PutImage: the framebuffer -> window blit the game platform
2// needs (F1105 desktop-native). The prior X11 arc drew rects/text; a game pushes a whole rendered
3// frame per tick, so this adds:
4//
5// PutImage (opcode 72), ZPixmap format:
6// byte 0: 72
7// byte 1: format (2 = ZPixmap)
8// bytes 2-3: request_length in 4-byte words = (24 + data)/4
9// bytes 4-7: drawable
10// bytes 8-11: gc
11// bytes 12-13: width
12// bytes 14-15: height
13// bytes 16-17: dst-x (signed)
14// bytes 18-19: dst-y
15// byte 20: left-pad (0 for ZPixmap)
16// byte 21: depth
17// bytes 22-23: pad
18// bytes 24+: pixel rows, 32bpp for depth-24 TrueColor
19//
20// A full 480x300 frame is 576000 data bytes = far past the CORE max request length (the spec
21// only guarantees 4096 words), so nx_x11_put_image_banded splits the frame into horizontal
22// bands sized from the server's ADVERTISED max_req_words (X11Conn, parsed from setup) --
23// never a hardcoded guess, and never a request the server is allowed to refuse.
24//
25// nx_fb_to_zpixmap converts the ecosystem's packed-i64 framebuffer (R | G<<8 | B<<16, the
26// nx_game_raster/swgpu/wasm-games format) to little-endian depth-24 ZPixmap u32 = R<<16|G<<8|B,
27// i.e. bytes [B,G,R,0] -- the exact layout nx_x11_get_image documents the server handing back,
28// so a put->get round trip is byte-comparable.
29//
30// license_tier: ORIGINAL
31// genealogy_id: international-research-sources/x_org/xproto_v11_r0
32// lineage_id: nishi_x11_put_image_q10
33
34import "nx_syscalls.nx"
35import "nx_x11_connect.nx"
36import "nx_x11_window.nx"
37
38const NX_X11_PUTIMG_HDR: i64 = 24
39// spec floor for max-request-length; used only when the connection reports nothing
40const NX_X11_MIN_REQ_WORDS: i64 = 4096
41
42// packed-i64 game pixel -> depth-24 ZPixmap u32 (R<<16 | G<<8 | B)
43func nx_fb_px_to_z(v: i64) -> i64 {
44 return ((v & 255) << 16) | (((v >> 8) & 255) << 8) | ((v >> 16) & 255)
45}
46
47// whole-frame conversion: n packed-i64 pixels -> n*4 bytes LE [B,G,R,0]
48func nx_fb_to_zpixmap(fbp: *i64, n: i64, out: *u8) -> i64 {
49 var i: i64 = 0
50 while i < n {
51 let v: i64 = fbp[i]
52 out[i*4] = ((v >> 16) & 255) as u8
53 out[i*4 + 1] = ((v >> 8) & 255) as u8
54 out[i*4 + 2] = (v & 255) as u8
55 out[i*4 + 3] = 0 as u8
56 i = i + 1
57 }
58 return n * 4
59}
60
61// rows per PutImage request under a max-request budget (>=1 so progress is guaranteed)
62func nx_x11_put_max_rows(w: i64, max_words: i64) -> i64 {
63 var mw: i64 = max_words
64 if mw < NX_X11_MIN_REQ_WORDS { mw = NX_X11_MIN_REQ_WORDS }
65 var rows: i64 = (mw*4 - NX_X11_PUTIMG_HDR) / (w*4)
66 if rows < 1 { rows = 1 }
67 return rows
68}
69
70// encode the 24-byte PutImage header into req; returns total request bytes (24 + data)
71func nx_x11_put_image_hdr(req: *u8, drawable: i64, gc: i64,
72 w: i64, h: i64, dx: i64, dy: i64, depth: i64) -> i64 {
73 let data: i64 = w*h*4
74 let total: i64 = NX_X11_PUTIMG_HDR + data
75 req[0] = 72
76 req[1] = 2 // ZPixmap
77 _x11_wr_u16(req, 2, total/4)
78 _x11_wr_u32(req, 4, drawable)
79 _x11_wr_u32(req, 8, gc)
80 _x11_wr_u16(req, 12, w)
81 _x11_wr_u16(req, 14, h)
82 _x11_wr_u16(req, 16, dx)
83 _x11_wr_u16(req, 18, dy)
84 req[20] = 0
85 req[21] = depth as u8
86 req[22] = 0
87 req[23] = 0
88 return total
89}
90
91// one PutImage request (caller guarantees it fits the server's max request length)
92func nx_x11_put_image(conn: *X11Conn, drawable: i64, gc: i64,
93 w: i64, h: i64, dx: i64, dy: i64, z: *u8) -> i64 {
94 let hdr: *u8 = sys_mmap(32)
95 let total: i64 = nx_x11_put_image_hdr(hdr, drawable, gc, w, h, dx, dy, conn.root_depth)
96 if _x11_send(conn, hdr, NX_X11_PUTIMG_HDR) < 0 { return 0 - 1 }
97 if _x11_send(conn, z, total - NX_X11_PUTIMG_HDR) < 0 { return 0 - 1 }
98 return 0
99}
100
101// full-frame blit split into server-acceptable horizontal bands; returns bands sent or negative
102func nx_x11_put_image_banded(conn: *X11Conn, drawable: i64, gc: i64,
103 w: i64, h: i64, z: *u8) -> i64 {
104 let rows: i64 = nx_x11_put_max_rows(w, conn.max_req_words)
105 var y: i64 = 0
106 var bands: i64 = 0
107 while y < h {
108 var bh: i64 = rows
109 if y + bh > h { bh = h - y }
110 let zp: *u8 = ((z as i64) + y*w*4) as *u8
111 if nx_x11_put_image(conn, drawable, gc, w, bh, 0, y, zp) < 0 { return 0 - 1 }
112 y = y + bh
113 bands = bands + 1
114 }
115 return bands
116}
117
118func main() -> i64 {
119 return 0
120}