Re: Radeon acceleration with Xfbdev

Michel Dänzer <[email protected]>
Newsgroups gmane.comp.freedesktop.xserver
Message-ID <[email protected]>
On Thu, 2003-11-27 at 00:40, Eric Anholt wrote: 
> On Mon, 2003-11-24 at 16:17, Michel Dänzer wrote:
> > 
> > I see some corruption with it, is that to be expected Eric?
> 
> Depends on the sort of corruption.  I haven't seen unexplained
> corruption at 16 bit for a while.  8-bit had issues, and I can't
> remember if 24 was completely fixed or not (I seem to recall issues with
> one of either r128 or radeon in some cases).

I run at 32 bpp most of the time; 8 is indeed worse, can't say much
about 16 because it seems to be broken in radeonfb in 2.6 kernels.

What I see is mostly pixmap corruption, in particular in GTK apps, but
the WindowMaker wallpaper is also corrupted with xcompmgr running (on
the bright side, xcompmgr works correctly now here, the endianness bugs
seem to have been fixed :).

These go away if I limit the amount of video RAM to be used to 8192
scanlines (don't ask me why... I only noticed looking closer at the code
that this shouldn't make a difference after I tried it :), but I can
still reliably cause corruption by maximizing the Text Widget window in
gtk-demo.


> It seems backwards to me to have the fbdev driver implement the
> acceleration itself, but I guess that was the quick'n'dirty part.  

Not really, I think Xfbdev automagically picking the right acceleration
code would be nice, but adding fbdev support to Xati instead is fine
with me.


> I've been playing with having both vesa and fbdev support, with the default
> being to use fbdev (since it should be more trustworthy in the end), and
> what I have so far is attached.  VESA continues to work, but fb is
> getting me a segfault and the following delightful output:
> 
> (gdb) r
> Starting program: /usr/src/xserver/hw/kdrive/ati/Xati
>  
> Program received signal SIGSEGV, Segmentation fault.
> 0x00000000 in ?? ()
> (gdb) bt
> #0  0x00000000 in ?? ()
> (gdb)

After a lot of stepping around in gdb, I tracked this down to
ATICreateResources(), the pointer was never initialised, it probably
doesn't get called with vesa for some reason?


Here's what I've got now.


-- 
Earthling Michel Dänzer      |     Debian (powerpc), X and DRI developer
Software libre enthusiast    |   http://svcs.affero.net/rm.php?r=daenzer
xserver-ati-fbdev.diff (text/x-patch, 15.1 KB)
Index: configure.ac
===================================================================
RCS file: /cvs/xserver/xserver/configure.ac,v
retrieving revision 3.38
diff -p -u -r3.38 configure.ac
--- configure.ac	22 Nov 2003 02:19:44 -0000	3.38
+++ configure.ac	1 Dec 2003 02:53:35 -0000
@@ -64,6 +64,9 @@ AC_CHECK_HEADERS([linux/agpgart.h sys/ag
 # APM header
 AC_CHECK_HEADERS([linux/apm_bios.h])
 
+# fbdev header
+AC_CHECK_HEADERS([linux/fb.h])
+
 # MTRR header
 AC_CHECK_HEADERS([asm/mtrr.h])
 
@@ -221,12 +224,17 @@ AM_CONDITIONAL(USE_RGB_BUILTIN, [test x$
 if test "$USE_RGB_BUILTIN" = yes; then
 	AC_DEFINE(USE_RGB_BUILTIN,1,[Use builtin rgb color database])
 fi
-	
+
 if test "$ac_cv_header_sys_vm86_h" = yes; then
-	AC_DEFINE(KDRIVEVESA, 1, [Include vesa-based X servers])
+	AC_DEFINE(KDRIVEVESA, 1, [Include vesa-based X servers and vesa support])
 fi
 AM_CONDITIONAL(KDRIVEVESA, [test "$ac_cv_header_sys_vm86_h" = yes])
 
+if test "$ac_cv_header_linux_fb_h" = yes; then
+	AC_DEFINE(KDRIVEFBDEV, 1, [Include framebuffer-based X servers and framebuffer support])
+fi
+AM_CONDITIONAL(KDRIVEFBDEV, [test "$ac_cv_header_linux_fb_h" = yes])
+
 AC_DEFINE_UNQUOTED(COMPILEDDEFAULTFONTPATH, ["$FONTPATH"], [Default font path])
 AC_DEFINE_UNQUOTED(VENDOR_STRING,["$VENDOR_STRING"], [Vendor name])
 AC_DEFINE_UNQUOTED(VENDOR_RELEASE, [$VENDOR_RELEASE], [Vendor release])
Index: hw/kdrive/Makefile.am
===================================================================
RCS file: /cvs/xserver/xserver/hw/kdrive/Makefile.am,v
retrieving revision 1.15
diff -p -u -r1.15 Makefile.am
--- hw/kdrive/Makefile.am	19 Nov 2003 08:32:33 -0000	1.15
+++ hw/kdrive/Makefile.am	1 Dec 2003 02:53:35 -0000
@@ -1,10 +1,14 @@
 if KDRIVEVESA
-VESA_SUBDIRS = vesa ati mach64 mga nvidia r128 smi
+VESA_SUBDIRS = vesa mach64 mga nvidia r128 smi
 endif
 
-SUBDIRS =	\
-	src	\
-	linux	\
-	fbdev	\
-	$(VESA_SUBDIRS)
+if KDRIVEFBDEV
+FBDEV_SUBDIRS = fbdev
+endif
 
+SUBDIRS =			\
+	src			\
+	linux			\
+	$(FBDEV_SUBDIRS)	\
+	$(VESA_SUBDIRS)		\
+	ati
Index: hw/kdrive/ati/Makefile.am
===================================================================
RCS file: /cvs/xserver/xserver/hw/kdrive/ati/Makefile.am,v
retrieving revision 1.1
diff -p -u -r1.1 Makefile.am
--- hw/kdrive/ati/Makefile.am	19 Nov 2003 08:32:35 -0000	1.1
+++ hw/kdrive/ati/Makefile.am	1 Dec 2003 02:53:35 -0000
@@ -1,6 +1,18 @@
+if KDRIVEFBDEV
+FBDEV_INCLUDES =-I$(top_srcdir)/hw/kdrive/fbdev
+FBDEV_LIBS = $(top_builddir)/hw/kdrive/fbdev/libfbdev.a
+endif
+
+if KDRIVEVESA
+VESA_INCLUDES = -I$(top_srcdir)/hw/kdrive/vesa
+VESA_LIBS = $(top_builddir)/hw/kdrive/vesa/libvesa.a
+endif
+
+
 INCLUDES = 					\
 	@KDRIVE_INCS@				\
-	-I$(top_srcdir)/hw/kdrive/vesa		\
+	$(FBDEV_INCLUDES)			\
+	$(VESA_INCLUDES)			\
 	@XSERVER_CFLAGS@
 
 bin_PROGRAMS = Xati
@@ -22,7 +34,8 @@ Xati_SOURCES = \
 
 Xati_LDADD = \
 	libati.a 				\
-	$(top_builddir)/hw/kdrive/vesa/libvesa.a \
+	$(FBDEV_LIBS)				\
+	$(VESA_LIBS)				\
 	@KDRIVE_LIBS@				\
 	@XSERVER_LIBS@                          \
 	$(TSLIB_FLAG)
Index: hw/kdrive/ati/ati.c
===================================================================
RCS file: /cvs/xserver/xserver/hw/kdrive/ati/ati.c,v
retrieving revision 1.5
diff -p -u -r1.5 ati.c
--- hw/kdrive/ati/ati.c	25 Nov 2003 22:39:54 -0000	1.5
+++ hw/kdrive/ati/ati.c	1 Dec 2003 02:53:35 -0000
@@ -59,6 +59,7 @@ struct pci_id_list radeon_id_list[] = {
 	{0x1002, 0x4c58, "ATI Radeon RV200 LX"},
 	{0x1002, 0x4c59, "ATI Radeon Mobility M6 LY"},
 	{0x1002, 0x4c5a, "ATI Radeon Mobility LZ"},
+	{0x1002, 0x4c66, "ATI Radeon Mobility M9 Lf"},
 	{0x1002, 0x4e44, "ATI Radeon R300 ND"},
 	{0x1002, 0x4e45, "ATI Radeon R300 NE"},
 	{0x1002, 0x4e46, "ATI Radeon R300 NF"},
@@ -153,15 +154,48 @@ ATICardInit(KdCardInfo *card)
 {
 	ATICardInfo *atic;
 	int i;
+	Bool initialized = FALSE;
 
-	atic = xalloc(sizeof(ATICardInfo));
+	atic = xcalloc(sizeof(ATICardInfo), 1);
 	if (atic == NULL)
 		return FALSE;
 
-	ATIMapReg(card, atic);
+#ifdef KDRIVEFBDEV
+	if (!initialized && fbdevInitialize(card, &atic->backend_priv.fbdev)) {
+		atic->use_fbdev = TRUE;
+		initialized = TRUE;
+		atic->backend_funcs.cardfini = fbdevCardFini;
+		atic->backend_funcs.scrfini = fbdevScreenFini;
+		atic->backend_funcs.initScreen = fbdevInitScreen;
+		atic->backend_funcs.finishInitScreen = fbdevFinishInitScreen;
+		atic->backend_funcs.preserve = fbdevPreserve;
+		atic->backend_funcs.restore = fbdevRestore;
+		atic->backend_funcs.dpms = fbdevDPMS;
+		atic->backend_funcs.enable = fbdevEnable;
+		atic->backend_funcs.disable = fbdevDisable;
+		atic->backend_funcs.getColors = fbdevGetColors;
+		atic->backend_funcs.putColors = fbdevPutColors;
+	}
+#endif
+#ifdef KDRIVEVESA
+	if (!initialized && vesaInitialize(card, &atic->backend_priv.vesa)) {
+		atic->use_vesa = TRUE;
+		initialized = TRUE;
+		atic->backend_funcs.cardfini = vesaCardFini;
+		atic->backend_funcs.scrfini = vesaScreenFini;
+		atic->backend_funcs.initScreen = vesaInitScreen;
+		atic->backend_funcs.finishInitScreen = vesaFinishInitScreen;
+		atic->backend_funcs.preserve = vesaPreserve;
+		atic->backend_funcs.restore = vesaRestore;
+		atic->backend_funcs.dpms = vesaDPMS;
+		atic->backend_funcs.enable = vesaEnable;
+		atic->backend_funcs.disable = vesaDisable;
+		atic->backend_funcs.getColors = vesaGetColors;
+		atic->backend_funcs.putColors = vesaPutColors;
+	}
+#endif
 
-	if (!vesaInitialize(card, &atic->vesa))
-	{
+	if (!initialized || !ATIMapReg(card, atic)) {
 		xfree(atic);
 		return FALSE;
 	}
@@ -181,39 +215,45 @@ ATICardFini(KdCardInfo *card)
 	ATICardInfo *atic = (ATICardInfo *)card->driver;
 
 	ATIUnmapReg(card, atic);
-	vesaCardFini(card);
+	atic->backend_funcs.cardfini(card);
 }
 
 static Bool
 ATIScreenInit(KdScreenInfo *screen)
 {
 	ATIScreenInfo *atis;
-	int screen_size, memory;
+	ATICardInfo *atic = screen->card->driver;
+	int success = FALSE;
 
-	atis = xalloc(sizeof(ATIScreenInfo));
+	atis = xcalloc(sizeof(ATIScreenInfo), 1);
 	if (atis == NULL)
 		return FALSE;
-	memset(atis, '\0', sizeof(ATIScreenInfo));
 
-	if (!vesaScreenInitialize(screen, &atis->vesa))
-	{
+	if (screen->fb[0].depth == 0)
+		screen->fb[0].depth = 16;
+
+	screen->driver = atis;
+
+#ifdef KDRIVEFBDEV
+	if (atic->use_fbdev) {
+		success = fbdevScreenInitialize(screen,
+						&atis->backend_priv.fbdev);
+		screen->memory_size = min(atic->backend_priv.fbdev.fix.smem_len, 8192 * screen->fb[0].byteStride);
+		/*screen->memory_size = atic->backend_priv.fbdev.fix.smem_len;*/
+		screen->off_screen_base = atic->backend_priv.fbdev.var.yres_virtual * screen->fb[0].byteStride;
+	}
+#endif
+#ifdef KDRIVEVESA
+	if (atic->use_vesa)
+		success = vesaScreenInitialize(screen,
+		    &atis->backend_priv.vesa);
+#endif
+	if (!success) {
+		screen->driver = NULL;
 		xfree(atis);
 		return FALSE;
 	}
-	atis->screen = atis->vesa.fb;
-
-	memory = atis->vesa.fb_size;
-	screen_size = screen->fb[0].byteStride * screen->height;
 
-	memory -= screen_size;
-	if (memory > screen->fb[0].byteStride) {
-		atis->off_screen = atis->screen + screen_size;
-		atis->off_screen_size = memory;
-	} else {
-		atis->off_screen = 0;
-		atis->off_screen_size = 0;
-	}
-	screen->driver = atis;
 	return TRUE;
 }
 
@@ -221,8 +261,9 @@ static void
 ATIScreenFini(KdScreenInfo *screen)
 {
 	ATIScreenInfo *atis = (ATIScreenInfo *)screen->driver;
+	ATICardInfo *atic = screen->card->driver;
 
-	vesaScreenFini(screen);
+	atic->backend_funcs.scrfini(screen);
 	xfree(atis);
 	screen->driver = 0;
 }
@@ -266,12 +307,49 @@ ATIResetMMIO(KdCardInfo *card, ATICardIn
 	ATIUnmapReg(card, atic);
 }
 
+static Bool
+ATIInitScreen(ScreenPtr pScreen)
+{
+	KdScreenPriv(pScreen);
+	ATICardInfo(pScreenPriv);
+
+	return atic->backend_funcs.initScreen(pScreen);
+}
+
+static Bool
+ATIFinishInitScreen(ScreenPtr pScreen)
+{
+	KdScreenPriv(pScreen);
+	ATICardInfo(pScreenPriv);
+
+	return atic->backend_funcs.finishInitScreen(pScreen);
+}
+
+static void
+ATIPreserve(KdCardInfo *card)
+{
+	ATICardInfo *atic = card->driver;
+
+	atic->backend_funcs.preserve(card);
+}
+
+static void
+ATIRestore(KdCardInfo *card)
+{
+	ATICardInfo *atic = card->driver;
+
+	ATIResetMMIO(card, atic);
+
+	atic->backend_funcs.restore(card);
+}
 
 static Bool
 ATIDPMS(ScreenPtr pScreen, int mode)
 {
-	/* XXX */
-	return TRUE;
+	KdScreenPriv(pScreen);
+	ATICardInfo(pScreenPriv);
+
+	return atic->backend_funcs.dpms(pScreen, mode);
 }
 
 static Bool
@@ -280,7 +358,7 @@ ATIEnable(ScreenPtr pScreen)
 	KdScreenPriv(pScreen);
 	ATICardInfo(pScreenPriv);
 
-	if (!vesaEnable(pScreen))
+	if (!atic->backend_funcs.enable(pScreen))
 		return FALSE;
 
 	ATISetMMIO(pScreenPriv->card, atic);
@@ -296,25 +374,36 @@ ATIDisable(ScreenPtr pScreen)
 	ATICardInfo(pScreenPriv);
 
 	ATIResetMMIO(pScreenPriv->card, atic);
-	vesaDisable(pScreen);
+
+	atic->backend_funcs.disable(pScreen);
 }
 
 static void
-ATIRestore(KdCardInfo *card)
+ATIGetColors(ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
 {
-	ATICardInfo *atic = card->driver;
+	KdScreenPriv(pScreen);
+	ATICardInfo(pScreenPriv);
 
-	ATIResetMMIO(card, atic);
-	vesaRestore(card);
+	atic->backend_funcs.getColors(pScreen, fb, n, pdefs);
+}
+
+
+static void
+ATIPutColors(ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
+{
+	KdScreenPriv(pScreen);
+	ATICardInfo(pScreenPriv);
+
+	atic->backend_funcs.putColors(pScreen, fb, n, pdefs);
 }
 
 KdCardFuncs ATIFuncs = {
 	ATICardInit,		/* cardinit */
 	ATIScreenInit,		/* scrinit */
-	vesaInitScreen,		/* initScreen */
-	vesaFinishInitScreen,	/* finishInitScreen */
-	vesaCreateResources,	/* createRes */
-	vesaPreserve,		/* preserve */
+	ATIInitScreen,		/* initScreen */
+	ATIFinishInitScreen,	/* finishInitScreen */
+	0,			/* createRes */
+	ATIPreserve,		/* preserve */
 	ATIEnable,		/* enable */
 	ATIDPMS,		/* dpms */
 	ATIDisable,		/* disable */
@@ -334,7 +423,7 @@ KdCardFuncs ATIFuncs = {
 	ATIDrawDisable,		/* disableAccel */
 	ATIDrawFini,		/* finiAccel */
 
-	vesaGetColors,		/* getColors */
-	vesaPutColors,		/* putColors */
+	ATIGetColors,		/* getColors */
+	ATIPutColors,		/* putColors */
 };
 
Index: hw/kdrive/ati/ati.h
===================================================================
RCS file: /cvs/xserver/xserver/hw/kdrive/ati/ati.h,v
retrieving revision 1.2
diff -p -u -r1.2 ati.h
--- hw/kdrive/ati/ati.h	20 Nov 2003 07:49:45 -0000	1.2
+++ hw/kdrive/ati/ati.h	1 Dec 2003 02:53:35 -0000
@@ -25,14 +25,52 @@
 
 #ifndef _ATI_H_
 #define _ATI_H_
+
+#include "config.h"
+
+#ifdef KDRIVEFBDEV
+#include <fbdev.h>
+#endif
+#ifdef KDRIVEVESA
 #include <vesa.h>
+#endif
 
 #define RADEON_REG_BASE(c)		((c)->attr.address[1])
 #define RADEON_REG_SIZE(c)		(0x10000)
 
+#ifdef __powerpc__
+
+static __inline__ void
+MMIO_OUT32(__volatile__ void *base, const unsigned long offset,
+	   const unsigned int val)
+{
+        __asm__ __volatile__(
+                        "stwbrx %1,%2,%3\n\t"
+			"eieio"
+                        : "=m" (*((volatile unsigned char *)base+offset))
+                        : "r" (val), "b" (base), "r" (offset));
+}
+
+static __inline__ CARD32
+MMIO_IN32(__volatile__ void *base, const unsigned long offset)
+{
+        register unsigned int val;
+        __asm__ __volatile__(
+                        "lwbrx %0,%1,%2\n\t"
+                        "eieio"
+                        : "=r" (val)
+                        : "b" (base), "r" (offset),
+                        "m" (*((volatile unsigned char *)base+offset)));
+        return val;
+}
+
+#else
+
 #define MMIO_OUT32(mmio, a, v)		(*(VOL32 *)((mmio) + (a)) = (v))
 #define MMIO_IN32(mmio, a)		(*(VOL32 *)((mmio) + (a)))
 
+#endif
+
 typedef volatile CARD8	VOL8;
 typedef volatile CARD16	VOL16;
 typedef volatile CARD32	VOL32;
@@ -43,20 +81,48 @@ struct pci_id_list {
 	char *name;
 };
 
+struct backend_funcs {
+       void    (*cardfini)(KdCardInfo *);
+       void    (*scrfini)(KdScreenInfo *);
+       Bool    (*initScreen)(ScreenPtr);
+       Bool    (*finishInitScreen)(ScreenPtr pScreen);
+       void    (*preserve)(KdCardInfo *);
+       void    (*restore)(KdCardInfo *);
+       Bool    (*dpms)(ScreenPtr, int);
+       Bool    (*enable)(ScreenPtr);
+       void    (*disable)(ScreenPtr);
+       void    (*getColors)(ScreenPtr, int, int, xColorItem *);
+       void    (*putColors)(ScreenPtr, int, int, xColorItem *);
+};
+
 typedef struct _ATICardInfo {
-	VesaCardPrivRec vesa;
+	union {
+#ifdef KDRIVEFBDEV
+		FbdevPriv fbdev;
+#endif
+#ifdef KDRIVEVESA
+		VesaCardPrivRec vesa;
+#endif
+	} backend_priv;
+	struct backend_funcs backend_funcs;
+
 	CARD8 *reg_base;
 	Bool is_radeon;
+	Bool use_fbdev, use_vesa;
 } ATICardInfo;
 
 #define getATICardInfo(kd)	((ATICardInfo *) ((kd)->card->driver))
 #define ATICardInfo(kd)		ATICardInfo *atic = getATICardInfo(kd)
 
 typedef struct _ATIScreenInfo {
-	VesaScreenPrivRec vesa;
-	CARD8 *screen;
-	CARD8 *off_screen;
-	int off_screen_size;
+	union {
+#ifdef KDRIVEFBDEV
+		FbdevScrPriv fbdev;
+#endif
+#ifdef KDRIVEVESA
+		VesaScreenPrivRec vesa;
+#endif
+	} backend_priv;
 
 	int datatype;
 	int dp_gui_master_cntl;
Index: hw/kdrive/ati/ati_stub.c
===================================================================
RCS file: /cvs/xserver/xserver/hw/kdrive/ati/ati_stub.c,v
retrieving revision 1.1
diff -p -u -r1.1 ati_stub.c
--- hw/kdrive/ati/ati_stub.c	19 Nov 2003 08:32:35 -0000	1.1
+++ hw/kdrive/ati/ati_stub.c	1 Dec 2003 02:53:35 -0000
@@ -73,7 +73,9 @@ void
 ddxUseMsg (void)
 {
 	KdUseMsg();
+#ifdef KDRIVEVESA
 	vesaUseMsg();
+#endif
 }
 
 int
@@ -81,7 +83,10 @@ ddxProcessArgument(int argc, char **argv
 {
 	int	ret;
     
+#ifdef KDRIVEVESA
 	if (!(ret = vesaProcessArgument (argc, argv, i)))
+#endif
 		ret = KdProcessArgument(argc, argv, i);
+
 	return ret;
 }
Index: hw/kdrive/fbdev/fbdev.c
===================================================================
RCS file: /cvs/xserver/xserver/hw/kdrive/fbdev/fbdev.c,v
retrieving revision 1.40
diff -p -u -r1.40 fbdev.c
--- hw/kdrive/fbdev/fbdev.c	17 Nov 2003 06:54:52 -0000	1.40
+++ hw/kdrive/fbdev/fbdev.c	1 Dec 2003 02:53:35 -0000
@@ -37,7 +37,7 @@ fbdevInitialize (KdCardInfo *card, Fbdev
     int		    k;
     unsigned long   off;
     if ((priv->fd = open("/dev/fb0", O_RDWR)) < 0) {
-	perror("Error opening /dev/fb0\n");
+	perror("Error opening /dev/fb0");
 	return FALSE;
     }
     /* quiet valgrind */
Index: hw/kdrive/src/kdrive.h
===================================================================
RCS file: /cvs/xserver/xserver/hw/kdrive/src/kdrive.h,v
retrieving revision 1.44
diff -p -u -r1.44 kdrive.h
--- hw/kdrive/src/kdrive.h	19 Nov 2003 08:32:38 -0000	1.44
+++ hw/kdrive/src/kdrive.h	1 Dec 2003 02:53:36 -0000
@@ -23,6 +23,9 @@
  */
 /* $RCSId: xc/programs/Xserver/hw/kdrive/kdrive.h,v 1.29 2002/11/13 16:37:39 keithp Exp $ */
 
+#ifndef _KDRIVE_H_
+#define _KDRIVE_H_
+
 #include <stdio.h>
 #include <X11/X.h>
 #define NEED_EVENTS
@@ -851,3 +854,5 @@ KdOffscreenFini (ScreenPtr pScreen);
 /* function prototypes to be implemented by the drivers */
 void
 InitCard (char *name);
+
+#endif /* _KDRIVE_H_ */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.