code wiki / (root) / nx_x11_put_image.nx

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}