Re: Color support for wsfb/Amiga

Jukka Andberg <[email protected]> Mon, 27 Jun 2022 21:51:57 +0300
Newsgroups gmane.os.netbsd.ports.amiga,gmane.os.netbsd.devel.x11,gmane.os.netbsd.ports.luna68k
Message-ID <[email protected]>
Izumi Tsutsui wrote Sun, 26 Jun 2022 15:53:49 +0900:

> Just FYI, ancient XFree86 driver seems to have "iplan2p2", "iplan2p4",
> and "iplan2p8" drivers (but I have not investigated them yet):
> http://cvsweb.netbsd.org/bsdweb.cgi/xsrc/xfree/xc/programs/Xserver/iplan2p4/Attic/

I suppose those are the "native" planar mode drivers.
 
> Random comments:
> 
> - as rin@ said, it's safer to leave WSDISPLAYIO_GTYPE not mandatory,
>   (i.e. not treat errors as fatal) especially if WSDISPLAYIO_GET_FBINFO
>   is available for newer drivers
>  - we don't have well-defined ioctl specifications so we should not rely
>    on implicit expectations

Ok then, I've updated the patch to just log an warning if WSDISPLAYIO_GTYPE fails.

> - I wonder if we should consider about "len" for mmap in WsfbScreenInit()?
>   fPtr->fbi.fbi_fbsize is enough?  What about fPtr->fbmem_len?

In case of Amiga fbi_fbsize is correct, and fbmem_len is derived from it.
 
> - As commented in WsfbScreenInit(), shadowFB is not supported
>   on depth < 8, so I wonder we should bother to check bitsPerPixel
>   (I doubt there could be >8bpp planar)

For length calculation? Yes, seems safe to assume exactly 8bpp there.

> - wonder what "Afb" stands for, even in Xorg
>   (eventually we could have Afb4, for luna68k and atari etc.?)

I don't think it has any particular meaning beyond being the
identifier for Amiga planar mode routines in Xorg.

Atari seems to have separate routines:
https://lists.x.org/archives/xorg-devel/2013-March/035831.html

--jukka
wsfb2.diff (application/octet-stream, 5.4 KB)
Index: src/sys/arch/amiga/dev/amidisplaycc.c
===================================================================
--- src/sys/arch/amiga/dev/amidisplaycc.c	(revision 928)
+++ src/sys/arch/amiga/dev/amidisplaycc.c	(working copy)
@@ -1112,14 +1112,13 @@
 	bm = adp->gfxview->bitmap;
 	KASSERT(bm);
 
-	/* Depth 1 since current X wsfb driver doesn't support multiple bitplanes */
 	memset(fbinfo, 0, sizeof(*fbinfo));
-	fbinfo->fbi_fbsize = bm->bytes_per_row * bm->rows;
+	fbinfo->fbi_fbsize = bm->bytes_per_row * bm->rows * adp->gfxdepth;
 	fbinfo->fbi_fboffset = 0;
 	fbinfo->fbi_width = bm->bytes_per_row * 8;
 	fbinfo->fbi_height = bm->rows;
 	fbinfo->fbi_stride = bm->bytes_per_row;
-	fbinfo->fbi_bitsperpixel = 1;
+	fbinfo->fbi_bitsperpixel = adp->gfxdepth;
 	fbinfo->fbi_pixeltype = WSFB_CI;
 	fbinfo->fbi_flags = 0;
 	fbinfo->fbi_subtype.fbi_cmapinfo.cmap_entries = 1 << adp->gfxdepth;
Index: xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb.h
===================================================================
--- xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb.h	(revision 928)
+++ xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb.h	(working copy)
@@ -63,6 +63,7 @@
 	Bool			shadowFB;
 	Bool			HWCursor;
 	Bool			useSwap32;
+	Bool			planarAfb;
 	CloseScreenProcPtr	CloseScreen;
 	CreateScreenResourcesProcPtr CreateScreenResources;
 	void                    (*PointerMoved)(SCRN_ARG_TYPE, int, int);
Index: xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb_driver.c
===================================================================
--- xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb_driver.c	(revision 928)
+++ xsrc/external/mit/xf86-video-wsfb/dist/src/wsfb_driver.c	(working copy)
@@ -121,6 +121,8 @@
 static Bool WsfbCloseScreen(CLOSE_SCREEN_ARGS_DECL);
 static void *WsfbWindowLinear(ScreenPtr, CARD32, CARD32, int, CARD32 *,
 			      void *);
+static void *WsfbWindowAfb(ScreenPtr, CARD32, CARD32, int, CARD32 *,
+			      void *);
 static void WsfbPointerMoved(SCRN_ARG_TYPE, int, int);
 static Bool WsfbEnterVT(VT_FUNC_ARGS_DECL);
 static void WsfbLeaveVT(VT_FUNC_ARGS_DECL);
@@ -211,6 +213,7 @@
 	"shadowUpdatePackedWeak",
 	"shadowUpdateRotatePacked",
 	"shadowUpdateRotatePackedWeak",
+	"shadowUpdateAfb8",
 	NULL
 };
 
@@ -444,6 +447,13 @@
 		return FALSE;
 	}
 
+	if (ioctl(fPtr->fd, WSDISPLAYIO_GTYPE, &wstype) == -1) {
+		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			   "ioctl WSDISPLAY_GTYPE: %s\n",
+			   strerror(errno));
+		wstype = WSDISPLAY_TYPE_UNKNOWN;
+	}
+
 	if (ioctl(fPtr->fd, WSDISPLAYIO_GET_FBINFO, &fPtr->fbi) != 0) {
 		struct wsdisplay_fbinfo info;
 		struct wsdisplayio_fbinfo *fbi = &fPtr->fbi;
@@ -457,12 +467,6 @@
 				   strerror(errno));
 			return FALSE;
 		}
-		if (ioctl(fPtr->fd, WSDISPLAYIO_GTYPE, &wstype) == -1) {
-			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-				   "ioctl WSDISPLAY_GTYPE: %s\n",
-				   strerror(errno));
-			return FALSE;
-		}
 		if (ioctl(fPtr->fd, WSDISPLAYIO_LINEBYTES, &lb) == -1) {
 			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 				   "ioctl WSDISPLAYIO_LINEBYTES: %s\n",
@@ -573,6 +577,25 @@
 		bitsperpixel = 1;
 	}
 #endif
+#if defined(__NetBSD__) && defined(WSDISPLAY_TYPE_AMIGACC)
+	if (wstype == WSDISPLAY_TYPE_AMIGACC)
+	{
+		/*
+		 * Video memory is organized in bitplanes.
+		 * 8bpp or 1bpp supported in this driver.
+		 * With 8bpp conversion to bitplane format
+		 * is done in shadow update proc.
+		 * With 1bpp no conversion needed.
+		 */
+		if (bitsperpixel == 8) {
+			fPtr->planarAfb = TRUE;
+		} else {
+			default_depth = 1;
+			bitsperpixel = 1;
+		}
+	}
+#endif
+
 	if (!xf86SetDepthBpp(pScrn, default_depth, default_depth,
 		bitsperpixel,
 		bitsperpixel >= 24 ? Support24bppFb|Support32bppFb : 0))
@@ -826,6 +849,7 @@
 	PixmapPtr pPixmap;
 	Bool ret;
 	void (*shadowproc)(ScreenPtr, shadowBufPtr);
+	ShadowWindowProc windowproc = WsfbWindowLinear;
 
 	pScreen->CreateScreenResources = fPtr->CreateScreenResources;
 	ret = pScreen->CreateScreenResources(pScreen);
@@ -841,11 +865,14 @@
 		shadowproc = WsfbShadowUpdateSwap32;
 	} else if (fPtr->rotate) {
 		shadowproc = shadowUpdateRotatePacked;
+	} else if (fPtr->planarAfb) {
+		shadowproc = shadowUpdateAfb8;
+		windowproc = WsfbWindowAfb;
 	} else
 		shadowproc = shadowUpdatePacked;
 	
 	if (!shadowAdd(pScreen, pPixmap, shadowproc,
-		WsfbWindowLinear, fPtr->rotate, NULL)) {
+		windowproc, fPtr->rotate, NULL)) {
 		return FALSE;
 	}
 	return TRUE;
@@ -987,6 +1014,9 @@
 			 */
 			len = pScrn->virtualX * pScrn->virtualY *
 			    (pScrn->bitsPerPixel >> 3);
+		} else if (fPtr->planarAfb) {
+			/* always 8bpp */
+			len = pScrn->virtualX * pScrn->virtualY;
 		} else {
 			len = fPtr->fbi.fbi_stride * pScrn->virtualY;
 		}
@@ -1006,6 +1036,8 @@
 	 */
 	if (fPtr->rotate) {
 		width = pScrn->displayWidth;
+	} else if (fPtr->planarAfb) {
+		width = pScrn->displayWidth;
 	} else {
 		if (pScrn->bitsPerPixel > 8) {
 			width =
@@ -1232,6 +1264,23 @@
 	return ((CARD8 *)fPtr->fbstart + row * fPtr->fbi.fbi_stride + offset);
 }
 
+/**
+ * For use with shadowUpdateAfb8
+ *
+ * For video memory layout with non-interleaved bitplanes.
+ */
+static void *
+WsfbWindowAfb(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode,
+		CARD32 *size, void *closure)
+{
+	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+	WsfbPtr fPtr = WSFBPTR(pScrn);
+
+	/* size is offset from start of bitplane to next bitplane */
+	*size = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height;
+	return ((CARD8 *)fPtr->fbstart + row * fPtr->fbi.fbi_stride + offset);
+}
+
 static void
 WsfbPointerMoved(SCRN_ARG_TYPE arg, int x, int y)
 {