From: Crystal Kolipe Subject: Re: rasops32: fix fonts on byte swapped framebuffers To: Ted Bullock Cc: tech@openbsd.org Date: Thu, 08 Oct 2026 11:33:57 -0000 On Wed, Oct 07, 2026 at 09:57:14AM -0600, Ted Bullock wrote: > On Wed, Oct 7, 2026 at 8:29???AM Crystal Kolipe > wrote: > > > > On Wed, Oct 07, 2026 at 06:34:02AM -0600, tbullock@comlore.com wrote: > > > This patch fixes font rendering on 32 bit byte swapped framebuffers. > > > The function uses a union to write two 32 bit pixels together as one > > > 64 bit value. With sparc64's byte swapped access, that reverses the > > > positions of the two pixels. > > > > Wouldn't it be far simpler and give better performance to just create a > > pixel-swapped font variation in memory the first time this function is called > > and use that with the existing blitting code on subsequent calls? > > > > I did almost exactly that to implement italics and other font variants in > > rasops32.c. > > Honestly I have.a lot of emotional thoughts when I saw the original > union implementation in this function. > > It feels like someone was being needlessly clever and it is also > completely unsurprising that there are endian adjacent problems when > someone starts throwing unions around. The attached patch replaces the union-based type punning with bit-shifting. Does this produce correct rendering results on your hardware? Surprisingly, this ran about 5% faster than the original version on a couple of test machines here. --- rasops32.c +++ rasops32.c @@ -68,10 +68,7 @@ uint32_t fb, clr[2]; struct rasops_info *ri; int64_t *rp; - union { - int64_t q[4]; - int32_t d[4][2]; - } u; + uint64_t u_dot_q[4]; u_char *fr; ri = (struct rasops_info *)cookie; @@ -93,11 +90,15 @@ b = ri->ri_devcmap[(attr >> 16) & 0xf]; f = ri->ri_devcmap[(attr >> 24) & 0xf]; - u.d[0][0] = b; u.d[0][1] = b; - u.d[1][0] = b; u.d[1][1] = f; - u.d[2][0] = f; u.d[2][1] = b; - u.d[3][0] = f; u.d[3][1] = f; +#define R_DL (((uint64_t)b) ^ ((uint64_t)f)) +#define R_DH ((R_DL) << 32) +#define UDOTQ(i) ((uint64_t)((uint64_t)b * 0x100000001)) ^ (((i & 1)) * R_DH) ^ (((i & 2) >> 1) * R_DL) + u_dot_q[0] = UDOTQ(0); + u_dot_q[1] = UDOTQ(1); + u_dot_q[2] = UDOTQ(2); + u_dot_q[3] = UDOTQ(3); + if (uc == ' ') { while (height--) { /* the general, pixel-at-a-time case is fast enough */ @@ -115,9 +116,9 @@ case 6: while (height--) { fb = fr[0]; - rp[0] = u.q[fb >> 6]; - rp[1] = u.q[(fb >> 4) & 3]; - rp[2] = u.q[(fb >> 2) & 3]; + rp[0] = u_dot_q[fb >> 6]; + rp[1] = u_dot_q[(fb >> 4) & 3]; + rp[2] = u_dot_q[(fb >> 2) & 3]; rp += step; fr += 1; } @@ -126,10 +127,10 @@ case 8: while (height--) { fb = fr[0]; - rp[0] = u.q[fb >> 6]; - rp[1] = u.q[(fb >> 4) & 3]; - rp[2] = u.q[(fb >> 2) & 3]; - rp[3] = u.q[fb & 3]; + rp[0] = u_dot_q[fb >> 6]; + rp[1] = u_dot_q[(fb >> 4) & 3]; + rp[2] = u_dot_q[(fb >> 2) & 3]; + rp[3] = u_dot_q[fb & 3]; rp += step; fr += 1; } @@ -138,13 +139,13 @@ case 12: while (height--) { fb = fr[0]; - rp[0] = u.q[fb >> 6]; - rp[1] = u.q[(fb >> 4) & 3]; - rp[2] = u.q[(fb >> 2) & 3]; - rp[3] = u.q[fb & 3]; + rp[0] = u_dot_q[fb >> 6]; + rp[1] = u_dot_q[(fb >> 4) & 3]; + rp[2] = u_dot_q[(fb >> 2) & 3]; + rp[3] = u_dot_q[fb & 3]; fb = fr[1]; - rp[4] = u.q[fb >> 6]; - rp[5] = u.q[(fb >> 4) & 3]; + rp[4] = u_dot_q[fb >> 6]; + rp[5] = u_dot_q[(fb >> 4) & 3]; rp += step; fr += 2; } @@ -153,15 +154,15 @@ case 16: while (height--) { fb = fr[0]; - rp[0] = u.q[fb >> 6]; - rp[1] = u.q[(fb >> 4) & 3]; - rp[2] = u.q[(fb >> 2) & 3]; - rp[3] = u.q[fb & 3]; + rp[0] = u_dot_q[fb >> 6]; + rp[1] = u_dot_q[(fb >> 4) & 3]; + rp[2] = u_dot_q[(fb >> 2) & 3]; + rp[3] = u_dot_q[fb & 3]; fb = fr[1]; - rp[4] = u.q[fb >> 6]; - rp[5] = u.q[(fb >> 4) & 3]; - rp[6] = u.q[(fb >> 2) & 3]; - rp[7] = u.q[fb & 3]; + rp[4] = u_dot_q[fb >> 6]; + rp[5] = u_dot_q[(fb >> 4) & 3]; + rp[6] = u_dot_q[(fb >> 2) & 3]; + rp[7] = u_dot_q[fb & 3]; rp += step; fr += 2; } @@ -170,25 +171,25 @@ case 32: while (height--) { fb = fr[0]; - rp[0] = u.q[fb >> 6]; - rp[1] = u.q[(fb >> 4) & 3]; - rp[2] = u.q[(fb >> 2) & 3]; - rp[3] = u.q[fb & 3]; + rp[0] = u_dot_q[fb >> 6]; + rp[1] = u_dot_q[(fb >> 4) & 3]; + rp[2] = u_dot_q[(fb >> 2) & 3]; + rp[3] = u_dot_q[fb & 3]; fb = fr[1]; - rp[4] = u.q[fb >> 6]; - rp[5] = u.q[(fb >> 4) & 3]; - rp[6] = u.q[(fb >> 2) & 3]; - rp[7] = u.q[fb & 3]; + rp[4] = u_dot_q[fb >> 6]; + rp[5] = u_dot_q[(fb >> 4) & 3]; + rp[6] = u_dot_q[(fb >> 2) & 3]; + rp[7] = u_dot_q[fb & 3]; fb = fr[2]; - rp[8] = u.q[fb >> 6]; - rp[9] = u.q[(fb >> 4) & 3]; - rp[10] = u.q[(fb >> 2) & 3]; - rp[11] = u.q[fb & 3]; + rp[8] = u_dot_q[fb >> 6]; + rp[9] = u_dot_q[(fb >> 4) & 3]; + rp[10] = u_dot_q[(fb >> 2) & 3]; + rp[11] = u_dot_q[fb & 3]; fb = fr[3]; - rp[12] = u.q[fb >> 6]; - rp[13] = u.q[(fb >> 4) & 3]; - rp[14] = u.q[(fb >> 2) & 3]; - rp[15] = u.q[fb & 3]; + rp[12] = u_dot_q[fb >> 6]; + rp[13] = u_dot_q[(fb >> 4) & 3]; + rp[14] = u_dot_q[(fb >> 2) & 3]; + rp[15] = u_dot_q[fb & 3]; rp += step; fr += 4; }