Fix 1bpp Xservers on "whitePixel=0, blackPixel=1" VRAMs
I'm working on porting ancient X11R6/XFree86 based Xsun servers to build with recent Xorg 1.20 DIX APIs for old sun machines still supported by NetBSD. The Xsun server in the NetBSD local tree is now functional on 8bpp cgtwo on sun3, 8bpp cgsix on SPARCstation, and 1bpp bwtwo on sun3.
- http://cvsweb.netbsd.org/bsdweb.cgi/xsrc/external/mit/xorg-server/dist/hw/sun/
- https://twitter.com/tsutsuii/status/1283063395248254976
- https://twitter.com/tsutsuii/status/1284605639587553280
To support sun3 bwtwo 1bpp framebuffer, I had to modify several DIX fb colormap code because its VRAM requires "whitePixel=0, blackPixel=1" settings (i.e. -flipPixels
settings should be default). It would be great if my local changes will also be applied to upstream xorg tree.
There are two problem to support inverted b&w settings:
fbSetupScreen()
in fb/fbscreen.c implicitly overwrites blackPixel
and whitePixel
(1) fbSetupScreen()
has the following code:
https://gitlab.freedesktop.org/xorg/xserver/-/blob/0803918e64262482035f042e5e1f2a571d3dea1b/fb/fbscreen.c#L93
/* let CreateDefColormap do whatever it wants for pixels */
pScreen->blackPixel = pScreen->whitePixel = (Pixel) 0;
However it doesn't seem CreateDefColormap()
handles it in 1bpp case, so fbSetupScreen()
should leave DDX settings.
fbInitializeColormap()
doesn't check blackPixel
and whitePixel
on settings 1bpp colormap?
(2) Even if blackPixel
and whitePixel
in ScreenPtr
are set proplery (as -flipPixels
is specified), it looks fbInitializeColormap()
doesn't check blackPixel
and whitePixel
on settings 1bpp colormap.
Without this colormap settings, at least the following drawing operations don't reflect blackPixel
and whitePixel
values (they refer colormap directly even on 1bpp?)
- mouse cursor
- twm titlebar and window frames
To handle this, I had to take an old mfb function mfbCreateColormap()
derived from X11R6 tree. It just calls AllocColor()
for two colors per whitePixel
value. I'm not sure if this should be implemented in the default fbInitializeColormap()
function, but in NetBSD local tree I've just added an independent function (taken from old tree like https://gitlab.freedesktop.org/xorg/xserver/-/blob/0d7ec5c7d9b451066a079fe56bcc9722341a91ff/mfb/mfbcmap.c#L115 ) for 1bpp servers.
Note I have just noticed the -flipPixels
option have been removed recently in this commit: d1c00c85
but I would also like to denote "it just works with Xorg xf86-video-wsfb driver and this patch, at least Xorg 1.20.5 based NetBSD local tree."
https://twitter.com/tsutsuii/status/1283042381009498120
From 19c16dce27c220e1ae834e0c4eb10fab112c5b06 Mon Sep 17 00:00:00 2001
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
Date: Sun, 9 Aug 2020 11:34:23 +0900
Subject: [PATCH] Fix 1bpp Xservers on "whitePixel=0, blackPixel=1" VRAMs.
---
fb/fb.h | 3 +++
fb/fbcmap_mi.c | 35 +++++++++++++++++++++++++++++++++++
fb/fbscreen.c | 12 +++++++++---
3 files changed, 47 insertions(+), 3 deletions(-)
diff --git a/fb/fb.h b/fb/fb.h
index 8ab050d0f..a113baf01 100644
--- a/fb/fb.h
+++ b/fb/fb.h
@@ -734,6 +734,9 @@ fbResolveColor(unsigned short *pred,
extern _X_EXPORT Bool
fbInitializeColormap(ColormapPtr pmap);
+extern _X_EXPORT Bool
+ mfbCreateColormap(ColormapPtr pmap);
+
extern _X_EXPORT int
fbExpandDirectColors(ColormapPtr pmap,
diff --git a/fb/fbcmap_mi.c b/fb/fbcmap_mi.c
index d9976ce9f..18acd2bf1 100644
--- a/fb/fbcmap_mi.c
+++ b/fb/fbcmap_mi.c
@@ -66,6 +66,41 @@ fbInitializeColormap(ColormapPtr pmap)
return miInitializeColormap(pmap);
}
+Bool
+mfbCreateColormap(ColormapPtr pmap)
+{
+ ScreenPtr pScreen;
+ unsigned short red0, green0, blue0;
+ unsigned short red1, green1, blue1;
+ Pixel pix;
+
+ pScreen = pmap->pScreen;
+ if (pScreen->whitePixel == 0)
+ {
+ red0 = green0 = blue0 = ~0;
+ red1 = green1 = blue1 = 0;
+ }
+ else
+ {
+ red0 = green0 = blue0 = 0;
+ red1 = green1 = blue1 = ~0;
+ }
+
+ /* this is a monochrome colormap, it only has two entries, just fill
+ * them in by hand. If it were a more complex static map, it would be
+ * worth writing a for loop or three to initialize it */
+
+ /* this will be pixel 0 */
+ pix = 0;
+ if (AllocColor(pmap, &red0, &green0, &blue0, &pix, 0) != Success)
+ return FALSE;
+
+ /* this will be pixel 1 */
+ if (AllocColor(pmap, &red1, &green1, &blue1, &pix, 0) != Success)
+ return FALSE;
+ return TRUE;
+}
+
int
fbExpandDirectColors(ColormapPtr pmap,
int ndef, xColorItem * indefs, xColorItem * outdefs)
diff --git a/fb/fbscreen.c b/fb/fbscreen.c
index 4ab807ab5..42efaa911 100644
--- a/fb/fbscreen.c
+++ b/fb/fbscreen.c
@@ -100,8 +100,10 @@ fbSetupScreen(ScreenPtr pScreen, void *pbits, /* pointer to screen bitmap */
if (!fbAllocatePrivates(pScreen))
return FALSE;
pScreen->defColormap = FakeClientID(0);
- /* let CreateDefColormap do whatever it wants for pixels */
- pScreen->blackPixel = pScreen->whitePixel = (Pixel) 0;
+ if (bpp > 1) {
+ /* let CreateDefColormap do whatever it wants for pixels */
+ pScreen->blackPixel = pScreen->whitePixel = (Pixel) 0;
+ }
pScreen->QueryBestSize = fbQueryBestSize;
/* SaveScreen */
pScreen->GetImage = fbGetImage;
@@ -118,7 +120,11 @@ fbSetupScreen(ScreenPtr pScreen, void *pbits, /* pointer to screen bitmap */
pScreen->RealizeFont = fbRealizeFont;
pScreen->UnrealizeFont = fbUnrealizeFont;
pScreen->CreateGC = fbCreateGC;
- pScreen->CreateColormap = fbInitializeColormap;
+ if (bpp == 1) {
+ pScreen->CreateColormap = mfbCreateColormap;
+ } else {
+ pScreen->CreateColormap = fbInitializeColormap;
+ }
pScreen->DestroyColormap = (void (*)(ColormapPtr)) NoopDDA;
pScreen->InstallColormap = fbInstallColormap;
pScreen->UninstallColormap = fbUninstallColormap;
--
2.25.3