diff --git a/src/dev/mgras/rss.rs b/src/dev/mgras/rss.rs index c9f2d1b3..c79a1749 100644 --- a/src/dev/mgras/rss.rs +++ b/src/dev/mgras/rss.rs @@ -64,10 +64,10 @@ pub mod reg { pub const CONFIG: u32 = 0x112; pub const XYWIN: u32 = 0x115; /// Background colour, where an opaque stipple draws its 0 bits: a colour - /// index, or in RGB modes blue (bits 23:12) and green (11:0), 12 bits - /// each, with red in the next register. + /// index, or in RGB modes green (bits 23:12) and red (11:0), 12 bits + /// each, with blue in bits 11:0 of the next register (bkgrd_rg/ba). pub const BG_COLOR: u32 = 0x140; - pub const BG_COLOR_RED: u32 = 0x141; + pub const BG_COLOR_BLUE: u32 = 0x141; /// The clip rectangle: x and y ranges, each `min << 16 | max`, and its /// control (bit 0 enable, bit 4 keep the inside rather than the outside). pub const CLIP_X: u32 = 0x147; @@ -1275,8 +1275,8 @@ impl Rss { pub(super) fn background(&self) -> u32 { let bg = self.reg(reg::BG_COLOR); if self.rgb_mode() { - let red = self.reg(reg::BG_COLOR_RED) & 0xFFF; - pack_rgb(red >> 4, (bg & 0xFFF) >> 4, ((bg >> 12) & 0xFFF) >> 4) + let blue = self.reg(reg::BG_COLOR_BLUE) & 0xFFF; + pack_rgb((bg & 0xFFF) >> 4, ((bg >> 12) & 0xFFF) >> 4, blue >> 4) } else { bg & 0xFFF } @@ -2261,24 +2261,54 @@ mod tests { } /// In RGB modes the background is three 12-bit components across two - /// registers, as IRIX writes it for a 12-bit window's icon: white - /// is 0xf00f00 (blue, green) and 0xf00 (red). These are the values from - /// a trace of the desktop repainting its Icon Catalog. + /// registers, red lowest like the packed colour. The values are the + /// syserrpanel stop sign from a trace of the desktop repainting its + /// Icon Catalog: red 0xf0 dithered with a light red (0xc0, 0x70, 0x70), + /// which hardware shows as a red sign. #[test] fn opaque_stipple_background_in_rgb_modes() { let mut r = x_server(); r.write(reg::PP1FILLMODE, 0x0C00_4004, false); // RGB pixel type r.write(reg::COLORMASKLSBSA, 0xFFF, false); r.write(reg::FILLMODE, FILL_LINE_STIPPLE | FILL_LINE_STIPPLE_OPAQUE, false); - r.write(reg::PACKEDCOLOR, 0xA0_A0A0, false); - r.write(reg::BG_COLOR, 0xC00_700, false); - r.write(reg::BG_COLOR_RED, 0x300, false); + r.write(reg::PACKEDCOLOR, 0xF0, false); + r.write(reg::BG_COLOR, 0x700_C00, false); + r.write(reg::BG_COLOR_BLUE, 0x700, false); r.write(reg::LINE_STIPPLE, 0xAAAA_AAAA, false); r.write(reg::IR_ALIAS, 0x15, false); r.write(reg::LINE_START, 300 << 16 | 40, false); r.write(reg::LINE_END, 301 << 16 | 40, true); - assert_eq!(px(&r, 300, 40), 0xAA_AAAA); - assert_eq!(px(&r, 301, 40), pack_rgb(0x33, 0x77, 0xCC), "expanded RGB444 background"); + assert_eq!(px(&r, 300, 40), 0xFF); + assert_eq!(px(&r, 301, 40), pack_rgb(0xCC, 0x77, 0x77), "expanded RGB444 background"); + } + + /// The syserrpanel stop sign as traced from 4Dwm (testdata): every + /// pixel of the dithered sign is red or light red, half each, never the + /// green the old background decode gave. + #[test] + fn syserrpanel_stop_sign_trace_dithers_red() { + let mut r = x_server(); + for line in include_str!("testdata/syserrpanel_stop_sign.txt").lines() { + let mut f = line.split_whitespace(); + let Some(name) = f.next().filter(|n| !n.starts_with('#')) else { continue }; + let reg = REG_NAMES.iter().position(|&n| n == name).unwrap_or_else(|| panic!("register {name}")); + let val = u32::from_str_radix(f.next().unwrap().trim_start_matches("0x"), 16).unwrap(); + r.write(reg as u32, val, f.next() == Some("x")); + } + let buf = r.target(); + let (red, light) = (pack_rgb(0xFF, 0, 0), pack_rgb(0xCC, 0x77, 0x77)); + let (mut n_red, mut n_light) = (0u32, 0u32); + for y in 266..=294 { + for x in 740..800 { + match r.mem.get(&buf, x, 767 - y) as u32 { + 0 => {} + p if p == red => n_red += 1, + p if p == light => n_light += 1, + p => panic!("({x}, {y}) is {p:#08x}, not red or light red"), + } + } + } + assert!(n_red > 200 && n_red.abs_diff(n_light) < 10, "red {n_red}, light red {n_light}"); } /// Block type 0 is a fill in the iterated colour, drawn at once (the diff --git a/src/dev/mgras/rss_jit_tests.rs b/src/dev/mgras/rss_jit_tests.rs index 9b568b1e..a7bca048 100644 --- a/src/dev/mgras/rss_jit_tests.rs +++ b/src/dev/mgras/rss_jit_tests.rs @@ -261,7 +261,7 @@ fn common_regs(rng: &mut Rng, regs: &mut Regs, gl: bool) { /// Colours, whichever the primitive uses (data: not in the key). fn colour_regs(rng: &mut Rng, regs: &mut Regs) { - for r in [reg::FILL_COLOR_R, reg::FILL_COLOR_G, reg::FILL_COLOR_B, reg::FILL_COLOR_B + 1, reg::RED, reg::PACKEDCOLOR, reg::BG_COLOR, reg::BG_COLOR_RED] { + for r in [reg::FILL_COLOR_R, reg::FILL_COLOR_G, reg::FILL_COLOR_B, reg::FILL_COLOR_B + 1, reg::RED, reg::PACKEDCOLOR, reg::BG_COLOR, reg::BG_COLOR_BLUE] { regs.push((r, rng.u32())); } } diff --git a/src/dev/mgras/testdata/syserrpanel_stop_sign.txt b/src/dev/mgras/testdata/syserrpanel_stop_sign.txt new file mode 100644 index 00000000..2d8322f2 --- /dev/null +++ b/src/dev/mgras/testdata/syserrpanel_stop_sign.txt @@ -0,0 +1,105 @@ +# The syserrpanel stop sign in the IRIX 6.5 Icon Catalog (12-bit RGB window), +# from an RSS trace (mgras trace, rss): 4Dwm dithers the sign 50/50 with an +# opaque line stipple, red 0xf0 on a light red background (bkgrd_rg 0x700c00, +# bkgrd_ba 0x700). Hardware shows a red sign. +# One RSS register write per line: name value, "x" for the execute address. +xywin 0x2ff0000 +winmode 0x0 +pp1fillmode 0xc008004 +ColorMaskLSBsA 0xfff000 +ColorMaskLSBsB 0xfff000 +ColorMaskMSBs 0x0 +packed_color 0xf0 +bkgrd_rg 0x700c00 +bkgrd_ba 0x700 +DRBpointers 0xb81c0 +fillmode 0x60 +ir_alias 0x15 +lscrl 0xf0000 +lspat 0x55555555 +xline_xystarti 0x30c010a +xline_xyendi 0x30f010a x +lspat 0xaaaaaaaa +xline_xystarti 0x30a010b +xline_xyendi 0x310010b x +lspat 0x55555555 +xline_xystarti 0x308010c +xline_xyendi 0x311010c x +lspat 0x55555555 +xline_xystarti 0x305010d +xline_xyendi 0x312010d x +lspat 0xaaaaaaaa +xline_xystarti 0x305010e +xline_xyendi 0x313010e x +lspat 0xaaaaaaaa +xline_xystarti 0x304010f +xline_xyendi 0x313010f x +lspat 0x55555555 +xline_xystarti 0x3040110 +xline_xyendi 0x3130110 x +lspat 0x55555555 +xline_xystarti 0x3030111 +xline_xyendi 0x3130111 x +lspat 0xaaaaaaaa +xline_xystarti 0x3030112 +xline_xyendi 0x3130112 x +lspat 0xaaaaaaaa +xline_xystarti 0x3020113 +xline_xyendi 0x3130113 x +lspat 0x55555555 +xline_xystarti 0x3020114 +xline_xyendi 0x3130114 x +lspat 0x55555555 +xline_xystarti 0x3010115 +xline_xyendi 0x3130115 x +lspat 0xaaaaaaaa +xline_xystarti 0x3010116 +xline_xyendi 0x3130116 x +lspat 0xaaaaaaaa +xline_xystarti 0x3000117 +xline_xyendi 0x3130117 x +lspat 0xaaaaaaaa +xline_xystarti 0x2ff0118 +xline_xyendi 0x3130118 x +lspat 0x55555555 +xline_xystarti 0x2ff0119 +xline_xyendi 0x3130119 x +lspat 0xaaaaaaaa +xline_xystarti 0x2ff011a +xline_xyendi 0x312011a x +lspat 0x55555555 +xline_xystarti 0x2ff011b +xline_xyendi 0x312011b x +lspat 0xaaaaaaaa +xline_xystarti 0x2ff011c +xline_xyendi 0x311011c x +lspat 0x55555555 +xline_xystarti 0x2ff011d +xline_xyendi 0x311011d x +lspat 0xaaaaaaaa +xline_xystarti 0x2ff011e +xline_xyendi 0x310011e x +lspat 0x55555555 +xline_xystarti 0x2ff011f +xline_xyendi 0x310011f x +lspat 0xaaaaaaaa +xline_xystarti 0x2ff0120 +xline_xyendi 0x30f0120 x +lspat 0x55555555 +xline_xystarti 0x2ff0121 +xline_xyendi 0x30f0121 x +lspat 0xaaaaaaaa +xline_xystarti 0x2ff0122 +xline_xyendi 0x30e0122 x +lspat 0x55555555 +xline_xystarti 0x3010123 +xline_xyendi 0x30d0123 x +lspat 0x55555555 +xline_xystarti 0x3020124 +xline_xyendi 0x30b0124 x +lspat 0x55555555 +xline_xystarti 0x3030125 +xline_xyendi 0x3090125 x +lspat 0x55555555 +xline_xystarti 0x3040126 +xline_xyendi 0x3070126 x