[Xquartz-changes] xserver: Branch 'server-1.9-apple' - 44 commits

Jeremy Huddleston jeremyhu at freedesktop.org
Thu May 20 23:58:43 PDT 2010


Rebased ref, commits from common ancestor:
commit 52d242c374e8e0ab7aad85505fb7bd388d01dd47
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Fri Feb 12 19:48:52 2010 -0800

    fb: Revert fb changes that broke XQuartz
    
    http://bugs.freedesktop.org/show_bug.cgi?id=26124
    
    Revert "Fix source pictures getting random transforms after 2d6a8f668342a5190cdf43b5."
    Revert "fb: Adjust transform or composite coordinates for pixman operations"
    
    http://bugs.freedesktop.org/26124
    
    This reverts commit a72c65e9176c51de95db2fdbf4c5d946a4911695.
    This reverts commit a6bd5d2e482a5aa84acb3d4932e2a166d8670ef1.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/fb/fb.h b/fb/fb.h
index 91c91ee..6d15b79 100644
--- a/fb/fb.h
+++ b/fb/fb.h
@@ -2078,11 +2078,8 @@ fbFillRegionSolid (DrawablePtr	pDrawable,
 		   FbBits	xor);
 
 extern _X_EXPORT pixman_image_t *
-image_from_pict (PicturePtr	pict,
-		 Bool		has_clip,
-		 int		*xoff,
-		 int		*yoff);
-
+image_from_pict (PicturePtr pict,
+		 Bool       has_clip);
 extern _X_EXPORT void free_pixman_pict (PicturePtr, pixman_image_t *);
 
 #endif /* _FB_H_ */
diff --git a/fb/fbpict.c b/fb/fbpict.c
index 896d33e..00f9ada 100644
--- a/fb/fbpict.c
+++ b/fb/fbpict.c
@@ -156,24 +156,19 @@ fbComposite (CARD8      op,
 	     CARD16     height)
 {
     pixman_image_t *src, *mask, *dest;
-    int src_xoff, src_yoff;
-    int msk_xoff, msk_yoff;
-    int dst_xoff, dst_yoff;
     
     miCompositeSourceValidate (pSrc, xSrc - xDst, ySrc - yDst, width, height);
     if (pMask)
 	miCompositeSourceValidate (pMask, xMask - xDst, yMask - yDst, width, height);
     
-    src = image_from_pict (pSrc, FALSE, &src_xoff, &src_yoff);
-    mask = image_from_pict (pMask, FALSE, &msk_xoff, &msk_yoff);
-    dest = image_from_pict (pDst, TRUE, &dst_xoff, &dst_yoff);
+    src = image_from_pict (pSrc, TRUE);
+    mask = image_from_pict (pMask, TRUE);
+    dest = image_from_pict (pDst, TRUE);
 
     if (src && dest && !(pMask && !mask))
     {
 	pixman_image_composite (op, src, mask, dest,
-				xSrc + src_xoff, ySrc + src_yoff,
-				xMask + msk_xoff, yMask + msk_yoff,
-				xDst + dst_xoff, yDst + dst_yoff,
+				xSrc, ySrc, xMask, yMask, xDst, yDst,
 				width, height);
     }
 
@@ -271,22 +266,22 @@ create_conical_gradient_image (PictGradient *gradient)
 
 static pixman_image_t *
 create_bits_picture (PicturePtr pict,
-		     Bool       has_clip,
-		     int	*xoff,
-		     int	*yoff)
+		     Bool       has_clip)
 {
-    PixmapPtr pixmap;
     FbBits *bits;
     FbStride stride;
-    int bpp;
+    int bpp, xoff, yoff;
     pixman_image_t *image;
     
-    fbGetDrawablePixmap (pict->pDrawable, pixmap, *xoff, *yoff);
-    fbGetPixmapBitsData(pixmap, bits, stride, bpp);
+    fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
+
+    bits = (FbBits*)((CARD8*)bits +
+		     (pict->pDrawable->y + yoff) * stride * sizeof(FbBits) +
+		     (pict->pDrawable->x + xoff) * (bpp / 8));
 
     image = pixman_image_create_bits (
 	pict->format,
-	pixmap->drawable.width, pixmap->drawable.height,
+	pict->pDrawable->width, pict->pDrawable->height,
 	(uint32_t *)bits, stride * sizeof (FbStride));
     
     
@@ -312,52 +307,30 @@ create_bits_picture (PicturePtr pict,
 	if (pict->clientClipType != CT_NONE)
 	    pixman_image_set_has_client_clip (image, TRUE);
 
-	if (*xoff || *yoff)
-	    pixman_region_translate (pict->pCompositeClip, *xoff, *yoff);
+	pixman_region_translate (pict->pCompositeClip, - pict->pDrawable->x, - pict->pDrawable->y);
 
 	pixman_image_set_clip_region (image, pict->pCompositeClip);
 
-	if (*xoff || *yoff)
-	    pixman_region_translate (pict->pCompositeClip, -*xoff, -*yoff);
+	pixman_region_translate (pict->pCompositeClip, pict->pDrawable->x, pict->pDrawable->y);
     }
     
     /* Indexed table */
     if (pict->pFormat->index.devPrivate)
 	pixman_image_set_indexed (image, pict->pFormat->index.devPrivate);
 
-    /* Add in drawable origin to position within the image */
-    *xoff += pict->pDrawable->x;
-    *yoff += pict->pDrawable->y;
-
     return image;
 }
 
 static void
-set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
+set_image_properties (pixman_image_t *image, PicturePtr pict)
 {
     pixman_repeat_t repeat;
     pixman_filter_t filter;
     
     if (pict->transform)
     {
-	/* For source images, adjust the transform to account
-	 * for the drawable offset within the pixman image,
-	 * then set the offset to 0 as it will be used
-	 * to compute positions within the transformed image.
-	 */
-	if (!has_clip) {
-	    struct pixman_transform	adjusted;
-
-	    adjusted = *pict->transform;
-	    pixman_transform_translate(&adjusted,
-				       NULL,
-				       pixman_int_to_fixed(*xoff),
-				       pixman_int_to_fixed(*yoff));
-	    pixman_image_set_transform (image, &adjusted);
-	    *xoff = 0;
-	    *yoff = 0;
-	} else
-	    pixman_image_set_transform (image, pict->transform);
+	pixman_image_set_transform (
+	    image, (pixman_transform_t *)pict->transform);
     }
     
     switch (pict->repeatType)
@@ -384,8 +357,7 @@ set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int
     
     if (pict->alphaMap)
     {
-	int alpha_xoff, alpha_yoff;
-	pixman_image_t *alpha_map = image_from_pict (pict->alphaMap, FALSE, &alpha_xoff, &alpha_yoff);
+	pixman_image_t *alpha_map = image_from_pict (pict->alphaMap, TRUE);
 	
 	pixman_image_set_alpha_map (
 	    image, alpha_map, pict->alphaOrigin.x, pict->alphaOrigin.y);
@@ -418,7 +390,8 @@ set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int
 }
 
 pixman_image_t *
-image_from_pict (PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
+image_from_pict (PicturePtr pict,
+		 Bool has_clip)
 {
     pixman_image_t *image = NULL;
 
@@ -427,7 +400,7 @@ image_from_pict (PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
 
     if (pict->pDrawable)
     {
-	image = create_bits_picture (pict, has_clip, xoff, yoff);
+	image = create_bits_picture (pict, has_clip);
     }
     else if (pict->pSourcePict)
     {
@@ -448,11 +421,10 @@ image_from_pict (PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
 	    else if (sp->type == SourcePictTypeConical)
 		image = create_conical_gradient_image (gradient);
 	}
-	*xoff = *yoff = 0;
     }
     
     if (image)
-	set_image_properties (image, pict, has_clip, xoff, yoff);
+	set_image_properties (image, pict);
     
     return image;
 }
diff --git a/fb/fbtrap.c b/fb/fbtrap.c
index 9f5c39f..9c55236 100644
--- a/fb/fbtrap.c
+++ b/fb/fbtrap.c
@@ -38,8 +38,7 @@ fbAddTraps (PicturePtr	pPicture,
 	    int		ntrap,
 	    xTrap	*traps)
 {
-    int image_xoff, image_yoff;
-    pixman_image_t *image = image_from_pict (pPicture, FALSE, &image_xoff, &image_yoff);
+    pixman_image_t *image = image_from_pict (pPicture, FALSE);
 
     if (!image)
 	return;
@@ -55,8 +54,7 @@ fbRasterizeTrapezoid (PicturePtr    pPicture,
 		      int	    x_off,
 		      int	    y_off)
 {
-    int	mask_xoff, mask_yoff;
-    pixman_image_t *image = image_from_pict (pPicture, FALSE, &mask_xoff, &mask_yoff);
+    pixman_image_t *image = image_from_pict (pPicture, FALSE);
 
     if (!image)
 	return;
commit 4a6c31097f4e0d224b2ce07664656b0cb202956b
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Fri Apr 30 13:08:25 2010 -0700

    Workaround the GC clipping problem in miPaintWindow and add some debugging output.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/mi/miexpose.c b/mi/miexpose.c
index 57968dd..172cc07 100644
--- a/mi/miexpose.c
+++ b/mi/miexpose.c
@@ -525,6 +525,7 @@ void RootlessSetPixmapOfAncestors(WindowPtr pWin);
 void RootlessStartDrawing(WindowPtr pWin);
 void RootlessDamageRegion(WindowPtr pWin, RegionPtr prgn);
 Bool IsFramedWindow(WindowPtr pWin);
+#include "../fb/fb.h"
 #endif 
 
 void
@@ -552,24 +553,37 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
     Bool	solid = TRUE;
     DrawablePtr	drawable = &pWin->drawable;
 
+#ifdef XQUARTZ_CLIP_DEBUG
+    ErrorF("START %d BS %d (pR = %ld)\n", what, pWin->backgroundState, ParentRelative);
+    ErrorF("      Rgn: %d %d %d %d\n", prgn->extents.x1, prgn->extents.y1,
+	                               prgn->extents.x2 - prgn->extents.x1,
+	                               prgn->extents.y2 - prgn->extents.y1);
+    ErrorF("      Win: %d %d (%d %d) %d %d\n", pWin->origin.x, pWin->origin.y,
+	                                       pWin->winSize.extents.x1, pWin->winSize.extents.y1,
+	                                       pWin->winSize.extents.x2 - pWin->winSize.extents.x1,
+					       pWin->winSize.extents.y2 - pWin->winSize.extents.y1);
+    ErrorF("     Draw: %d %d %d %d\n", pWin->drawable.x, pWin->drawable.y,
+				       pWin->drawable.width, pWin->drawable.height);
+#endif
+
 #ifdef ROOTLESS
     if(!drawable || drawable->type == UNDRAWABLE_WINDOW)
 	return;
-
-    if(IsFramedWindow(pWin)) {
-        RootlessStartDrawing(pWin);
-        RootlessDamageRegion(pWin, prgn);
-    
-        if(pWin->backgroundState == ParentRelative) {
-            if((what == PW_BACKGROUND) || 
-               (what == PW_BORDER && !pWin->borderIsPixel))
-                RootlessSetPixmapOfAncestors(pWin);
-        }
-    }
 #endif
     
     if (what == PW_BACKGROUND)
     {
+#ifdef ROOTLESS
+	if(IsFramedWindow(pWin)) {
+	    RootlessStartDrawing(pWin);
+	    RootlessDamageRegion(pWin, prgn);
+
+	    if(pWin->backgroundState == ParentRelative) {
+		RootlessSetPixmapOfAncestors(pWin);
+	    }
+	}
+#endif
+
 	while (pWin->backgroundState == ParentRelative)
 	    pWin = pWin->parent;
 
@@ -591,6 +605,18 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
     {
 	PixmapPtr   pixmap;
 
+#ifdef ROOTLESS
+	if(IsFramedWindow(pWin)) {
+	    RootlessStartDrawing(pWin);
+	    RootlessDamageRegion(pWin, prgn);
+	    
+	    if(!pWin->borderIsPixel &&
+		pWin->backgroundState == ParentRelative) {
+		RootlessSetPixmapOfAncestors(pWin);
+	    }
+	}
+#endif
+
 	tile_x_off = drawable->x;
 	tile_y_off = drawable->y;
 	
@@ -599,6 +625,12 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
 	    return;
 	pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable);
 	drawable = &pixmap->drawable;
+
+#ifdef XQUARTZ_CLIP_DEBUG
+	ErrorF("     Draw: %d %d %d %d\n",
+	       drawable->x, drawable->y, drawable->width, drawable->height);    
+#endif
+	
 #ifdef COMPOSITE
 	draw_x_off = pixmap->screen_x;
 	draw_y_off = pixmap->screen_y;
@@ -661,6 +693,57 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
     ChangeGC (NullClient, pGC, gcmask, gcval);
     ValidateGC (drawable, pGC);
 
+#ifdef XQUARTZ_CLIP_DEBUG
+    ErrorF("       GC: %d %d %d %d\n",
+	   pGC->pCompositeClip->extents.x1, pGC->pCompositeClip->extents.y1,
+	   pGC->pCompositeClip->extents.x2 - pGC->pCompositeClip->extents.x1,
+	   pGC->pCompositeClip->extents.y2 - pGC->pCompositeClip->extents.y1);
+#endif
+    
+#ifdef XQUARTZ
+    /* Looks like our clipping isn't set right for some reason:
+     * http://xquartz.macosforge.org/trac/ticket/290
+     */
+    if(what == PW_BORDER) {
+
+#if 0
+	if(solid) {
+#if 1
+	    fbFillRegionSolid(&pWin->drawable,
+			      prgn,
+			      0,
+			      fbReplicatePixel(fill.pixel,
+					       pWin->drawable.bitsPerPixel));
+#else
+	    fbFillRegionSolid(drawable,
+			      prgn,
+			      0,
+			      fbReplicatePixel(fill.pixel,
+					       drawable->bitsPerPixel));
+#endif
+	    return;
+	}
+#endif
+    
+	pGC->pCompositeClip->extents.x1 += prgn->extents.x1;
+	pGC->pCompositeClip->extents.y1 += prgn->extents.y1;
+	pGC->pCompositeClip->extents.x2 += prgn->extents.x1;
+	pGC->pCompositeClip->extents.y2 += prgn->extents.y1;
+	
+	if(pGC->pCompositeClip->extents.x2 > drawable->pScreen->width)
+	    pGC->pCompositeClip->extents.x2 = drawable->pScreen->width;
+	if(pGC->pCompositeClip->extents.y2 > drawable->pScreen->height)
+	    pGC->pCompositeClip->extents.y2 = drawable->pScreen->height;
+    }
+#endif
+
+#ifdef XQUARTZ_CLIP_DEBUG
+    ErrorF("       GC: %d %d %d %d\n",
+	   pGC->pCompositeClip->extents.x1, pGC->pCompositeClip->extents.y1,
+	   pGC->pCompositeClip->extents.x2 - pGC->pCompositeClip->extents.x1,
+	   pGC->pCompositeClip->extents.y2 - pGC->pCompositeClip->extents.y1);    
+#endif
+
     numRects = REGION_NUM_RECTS(prgn);
     pbox = REGION_RECTS(prgn);
     for (i= numRects; --i >= 0; pbox++, prect++)
commit 5754e66044571d549c295b7c9e02ce3348dbe3c7
Author: Jamey Sharp <jamey at minilop.net>
Date:   Thu May 20 10:46:43 2010 -0700

    Replace screen->rgf scratch GC flags with a bit in each GC.
    
    This eliminates a poorly-named, poorly-documented field from the
    ScreenRec, using a previously-unused flag bit in each GC instead.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>
    Cc: Keith Packard <keithp at keithp.com>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/dix/dispatch.c b/dix/dispatch.c
index c86011a..27cb220 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3916,7 +3916,6 @@ AddScreen(
        any of the strings pointed to by argv.  They may be passed to
        multiple screens.
     */
-    pScreen->rgf = ~0L;  /* there are no scratch GCs yet*/
     WindowTable[i] = NullWindow;
     screenInfo.screens[i] = pScreen;
     screenInfo.numScreens++;
diff --git a/dix/gc.c b/dix/gc.c
index 65d05eb..48a507d 100644
--- a/dix/gc.c
+++ b/dix/gc.c
@@ -537,6 +537,9 @@ CreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus,
     pGC->stipple = pGC->pScreen->PixmapPerDepth[0];
     pGC->stipple->refcnt++;
 
+    /* this is not a scratch GC */
+    pGC->scratch_inuse = FALSE;
+
     /* security creation/labeling check */
     *pStatus = XaceHook(XACE_RESOURCE_ACCESS, client, gcid, RT_GC, pGC,
 			RT_NONE, NULL, DixCreateAccess|DixSetAttrAccess);
@@ -844,6 +847,9 @@ CreateScratchGC(ScreenPtr pScreen, unsigned depth)
     pGC->lastWinOrg.x = 0;
     pGC->lastWinOrg.y = 0;
 
+    /* scratch GCs in the GCperDepth pool start off unused */
+    pGC->scratch_inuse = FALSE;
+
     pGC->stateChanges = GCAllBits;
     if (!(*pScreen->CreateGC)(pGC))
     {
@@ -864,8 +870,10 @@ FreeGCperDepth(int screenNum)
     ppGC = pScreen->GCperDepth;
 
     for (i = 0; i <= pScreen->numDepths; i++)
+    {
 	(void)FreeGC(ppGC[i], (XID)0);
-    pScreen->rgf = ~0L;
+	ppGC[i] = NULL;
+    }
 }
 
 
@@ -878,7 +886,6 @@ CreateGCperDepth(int screenNum)
     GCPtr *ppGC;
 
     pScreen = screenInfo.screens[screenNum];
-    pScreen->rgf = 0;
     ppGC = pScreen->GCperDepth;
     /* do depth 1 separately because it's not included in list */
     if (!(ppGC[0] = CreateScratchGC(pScreen, 1)))
@@ -1097,12 +1104,11 @@ GetScratchGC(unsigned depth, ScreenPtr pScreen)
     GCPtr pGC;
 
     for (i=0; i<=pScreen->numDepths; i++)
-        if ( pScreen->GCperDepth[i]->depth == depth &&
-	     !(pScreen->rgf & (1L << (i+1)))
-	   )
+    {
+	pGC = pScreen->GCperDepth[i];
+	if (pGC && pGC->depth == depth && !pGC->scratch_inuse)
 	{
-	    pScreen->rgf |= (1L << (i+1));
-            pGC = (pScreen->GCperDepth[i]);
+	    pGC->scratch_inuse = TRUE;
 
 	    pGC->alu = GXcopy;
 	    pGC->planemask = ~0;
@@ -1127,6 +1133,7 @@ GetScratchGC(unsigned depth, ScreenPtr pScreen)
 	    pGC->stateChanges = GCAllBits;
 	    return pGC;
 	}
+    }
     /* if we make it this far, need to roll our own */
     pGC = CreateScratchGC(pScreen, depth);
     if (pGC)
@@ -1142,16 +1149,8 @@ mark it as available.
 void
 FreeScratchGC(GCPtr pGC)
 {
-    ScreenPtr pScreen = pGC->pScreen;
-    int i;
-
-    for (i=0; i<=pScreen->numDepths; i++)
-    {
-        if ( pScreen->GCperDepth[i] == pGC)
-	{
-	    pScreen->rgf &= ~(1L << (i+1));
-	    return;
-	}
-    }
-    (void)FreeGC(pGC, (GContext)0);
+    if (pGC->scratch_inuse)
+	pGC->scratch_inuse = FALSE;
+    else
+	FreeGC(pGC, (GContext)0);
 }
diff --git a/hw/xnest/Screen.c b/hw/xnest/Screen.c
index 62255b8..0a05ac8 100644
--- a/hw/xnest/Screen.c
+++ b/hw/xnest/Screen.c
@@ -243,7 +243,6 @@ xnestOpenScreen(int index, ScreenPtr pScreen, int argc, char *argv[])
   pScreen->saveUnderSupport = NotUseful;
   pScreen->whitePixel = xnestWhitePixel;
   pScreen->blackPixel = xnestBlackPixel;
-  /* rgf */
   /* GCperDepth */
   /* PixmapPerDepth */
   pScreen->devPrivate = NULL;
diff --git a/include/gcstruct.h b/include/gcstruct.h
index b9fc5ca..3f70ead 100644
--- a/include/gcstruct.h
+++ b/include/gcstruct.h
@@ -292,7 +292,8 @@ typedef struct _GC {
     unsigned int	tileIsPixel:1; /* tile is solid pixel */
     unsigned int	fExpose:1;     /* Call exposure handling */
     unsigned int	freeCompClip:1;  /* Free composite clip */
-    unsigned int	unused:14; /* see comment above */
+    unsigned int	scratch_inuse:1; /* is this GC in a pool for reuse? */
+    unsigned int	unused:13; /* see comment above */
     unsigned long	planemask;
     unsigned long	fgPixel;
     unsigned long	bgPixel;
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index 3a77e0c..6f1936c 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -455,7 +455,6 @@ typedef struct _Screen {
     short		minInstalledCmaps, maxInstalledCmaps;
     char                backingStoreSupport, saveUnderSupport;
     unsigned long	whitePixel, blackPixel;
-    unsigned long	rgf;	/* array of flags; she's -- HUNGARIAN */
     GCPtr		GCperDepth[MAXFORMATS+1];
 			/* next field is a stipple to use as default in
 			   a GC.  we don't build default tiles of all depths
commit 5a7275d78a2f1c20ed5bb7b228cf370c4ada22c9
Author: Keith Packard <keithp at keithp.com>
Date:   Thu May 20 13:57:02 2010 -0700

    Find windows GL wrapper files in $(srcdir) instead of .
    
    This fixes 'make distcheck' for me.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Julien Cristau <jcristau at debian.org>

diff --git a/hw/xwin/glx/Makefile.am b/hw/xwin/glx/Makefile.am
index 7fc1694..e9fea50 100644
--- a/hw/xwin/glx/Makefile.am
+++ b/hw/xwin/glx/Makefile.am
@@ -45,10 +45,10 @@ wgl.tm:
 	wget http://www.opengl.org/registry/api/wgl.tm
 
 generated_gl_wrappers.c: gen_gl_wrappers.py gl.spec gl.tm
-	./gen_gl_wrappers.py --spec=gl.spec --typemap=gl.tm --dispatch-header=$(top_srcdir)/glx/dispatch.h --staticwrappers >generated_gl_wrappers.c
+	$(srcdir)/gen_gl_wrappers.py --spec=$(srcdir)/gl.spec --typemap=$(srcdir)/gl.tm --dispatch-header=$(top_srcdir)/glx/dispatch.h --staticwrappers >generated_gl_wrappers.c
 
 generated_wgl_wrappers.c: gen_gl_wrappers.py wglext.spec wgl.tm
-	./gen_gl_wrappers.py --spec=wglext.spec --typemap=wgl.tm --prefix=wgl --preresolve >generated_wgl_wrappers.c
+	$(srcdir)/gen_gl_wrappers.py --spec=$(srcdir)/wglext.spec --typemap=$(srcdir)/wgl.tm --prefix=wgl --preresolve >generated_wgl_wrappers.c
 
 wglext.h:
 	wget http://www.opengl.org/registry/api/wglext.h
commit 1197a87b5638037cc48084fba4eec9d3b599e900
Author: Keith Packard <keithp at keithp.com>
Date:   Thu May 20 13:40:24 2010 -0700

    winpriv.h was moved from hw/xwin to hw/xwin/glx in November
    
    hw/xwin/Makefile.am was referencing this instead of hw/xwin/glx/Makefile.am
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Julien Cristau <jcristau at debian.org>

diff --git a/hw/xwin/Makefile.am b/hw/xwin/Makefile.am
index 7544cd3..03cb808 100644
--- a/hw/xwin/Makefile.am
+++ b/hw/xwin/Makefile.am
@@ -117,7 +117,6 @@ SRCS =	InitInput.c \
 	winms.h \
 	winmultiwindowclass.h \
 	winprefs.h \
-	winpriv.h \
 	winresource.h \
 	winwindow.h \
 	XWin.rc \
diff --git a/hw/xwin/glx/Makefile.am b/hw/xwin/glx/Makefile.am
index aadd442..7fc1694 100644
--- a/hw/xwin/glx/Makefile.am
+++ b/hw/xwin/glx/Makefile.am
@@ -2,6 +2,7 @@ noinst_LTLIBRARIES = libXwinGLX.la
 
 libXwinGLX_la_SOURCES = \
 	winpriv.c \
+	winpriv.h \
 	glwindows.h \
 	glwrap.c \
 	indirect.c \
commit 1cad520f3f1d9d520422e3e4d5d8f4ea85a212a4
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Mon May 17 20:35:10 2010 -0700

    XFree86 Design doc: Convert LinuxDoc ``quotes'' to DocBook <quote> tags
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Tested-by: Gaetan Nadon <memsize at videotron.ca>

diff --git a/hw/xfree86/doc/sgml/DESIGN.xml b/hw/xfree86/doc/sgml/DESIGN.xml
index 8a3047b..826a970 100644
--- a/hw/xfree86/doc/sgml/DESIGN.xml
+++ b/hw/xfree86/doc/sgml/DESIGN.xml
@@ -150,7 +150,7 @@ changes:
       </para>
 
       <para>
-    A &k.device; section is considered ``active'' if there is a reference
+    A &k.device; section is considered <quote>active</quote> if there is a reference
     to it in an active &k.screen; section.
       </para>
     </sect2>
@@ -166,7 +166,7 @@ changes:
     can be used to identify which screen is to be active when multiple
     &k.screen; sections are present.  It is possible to specify the active
     screen from the command line.  A default is chosen in the absence
-    of one being specified.  A &k.screen; section is considered ``active''
+    of one being specified.  A &k.screen; section is considered <quote>active</quote>
     if there is a reference to it either from the command line, or from
     an active &k.serverlayout; section.
       </para>
@@ -336,7 +336,7 @@ framebuffer code are outside the scope of this document.
     <para>
 This approach to the driver interface provides good flexibility, but does
 increase the complexity of drivers.  To help address this, the XFree86
-common layer provides a set of ``helper'' functions to take care of things
+common layer provides a set of <quote>helper</quote> functions to take care of things
 that most drivers need.  These helpers help minimise the amount of code
 duplication between drivers.  The use of helper functions by drivers is
 however optional, though encouraged.  The basic philosophy behind the
@@ -466,11 +466,11 @@ mechanism for this.
 	<title>Bus</title>
 
 	<para>
-    ``Bus'' is ambiguous as it is used for different things: it may refer
+    <quote>Bus</quote> is ambiguous as it is used for different things: it may refer
     to physical incompatible extension connectors in a computer system.
     The RAC system knows two such systems: The ISA bus and the PCI bus.
     (On the software level EISA, MCA and VL buses are currently treated
-    like ISA buses).  ``Bus'' may also refer to logically different
+    like ISA buses).  <quote>Bus</quote> may also refer to logically different
     entities on a single bus system which are connected via bridges.  A
     PCI system may have several distinct PCI buses connecting each other
     by PCI-PCI bridges or to the host CPU by HOST-PCI bridges.
@@ -503,7 +503,7 @@ mechanism for this.
 	<title>Resource</title>
 
 	<para>
-    ``Resource'' refers to a range of memory or I/O addresses an entity
+    <quote>Resource</quote> refers to a range of memory or I/O addresses an entity
     can decode.
 	</para>
 
@@ -609,7 +609,7 @@ Here is what <function>InitOutput()</function> does:
 
       <para>
     Port I/O access is controlled from the XFree86 common layer, and is
-    ``all or nothing''.  It is enabled prior to calling driver probes, at
+    <quote>all or nothing</quote>.  It is enabled prior to calling driver probes, at
     the start of subsequent server generations, and when VT switching
     back to the Xserver.  It is disabled at the end of server generations,
     and when VT switching away from the Xserver.
@@ -775,7 +775,7 @@ Here is what <function>InitOutput()</function> does:
     calling any driver functions that may access hardware.  All generic
     bus information is probed and saved (for restoration later).  All
     (shared resource) video devices are disabled at the generic bus
-    level, and a probe is done to find the ``primary'' video device.  These
+    level, and a probe is done to find the <quote>primary</quote> video device.  These
     devices remain disabled for the next step.
       </para>
     </sect2>
@@ -870,7 +870,7 @@ Here is what <function>InitOutput()</function> does:
       entities. Optionally <function>xf86AllocateScreen()</function>
       function may also be used to allocate the <structname>ScrnInfoRec</structname>.
       Any of these functions take care of initialising fields to defined
-      ``unused'' values.
+      <quote>unused</quote> values.
 	</para>
 
 	<para>
@@ -928,7 +928,7 @@ Here is what <function>InitOutput()</function> does:
       <structfield>origIndex</structfield>, <structfield>module</structfield> and
       <structfield>drv</structfield> fields are initialised.  The reference count
       in <parameter>drv</parameter> is incremented.  The storage for any
-      currently allocated ``privates'' pointers is also allocated and
+      currently allocated <quote>privates</quote> pointers is also allocated and
       the <structfield>privates</structfield> field initialised (the privates data
       is of course not allocated or initialised).  This function never
       returns on failure.  If the allocation fails, the server exits
@@ -1107,9 +1107,9 @@ Here is what <function>InitOutput()</function> does:
       the <structname>ScrnInfoRec</structname>'s <structfield>driverPrivate</structfield>
       field.  Any other modules which require persistent data (ie data
       that persists across server generations) should be initialised in
-      this function, and they should allocate a ``privates'' index to
+      this function, and they should allocate a <quote>privates</quote> index to
       hook their data into by calling
-      <function>xf86AllocateScrnInfoPrivateIndex()</function>.  The ``privates''
+      <function>xf86AllocateScrnInfoPrivateIndex()</function>.  The <quote>privates</quote>
       data is persistent.
 	    </para>
 
@@ -1406,18 +1406,18 @@ Here is what <function>InitOutput()</function> does:
 	    </para></listitem>
 
 	  <listitem><para>
-        A resource marked ``disabled'' during OPERATING state will be
+        A resource marked <quote>disabled</quote> during OPERATING state will be
         ignored entirely.
 	    </para></listitem>
 
 	  <listitem><para>
-	A resource marked ``unused'' will only conflict with an overlapping
+	A resource marked <quote>unused</quote> will only conflict with an overlapping
 	resource of an other entity if the second is actually in use
 	during OPERATING state.
 	    </para></listitem>
 
 	  <listitem><para>
-	If an ``unused'' resource was found to conflict but the entity
+	If an <quote>unused</quote> resource was found to conflict but the entity
 	does not use any other resource of this type the entire resource
 	type will be disabled for that entity.
 	    </para></listitem>
@@ -1619,7 +1619,7 @@ Here is what <function>InitOutput()</function> does:
                                    -1, -1, -1, -1, -1, NewApertureAddress);
 	  </programlisting>
 	  <blockquote><para>
-        where the <structfield>``ppix''</structfield> field in a ScrnInfoRec
+        where the <structfield>ppix</structfield> field in a ScrnInfoRec
         points to the pixmap used by the screen's
         <function>SaveRestoreImage()</function> function to hold the screen's
         contents while switched out.
@@ -1759,7 +1759,7 @@ MODECHECK_FINAL are intended for checks that may involve more than one mode.
       call.  This would predominantly be data allocated by
       <function>ChipPreInit()</function> that persists across server
       generations.  It would include the <structfield>driverPrivate</structfield>,
-      and any ``privates'' entries that modules may have allocated.
+      and any <quote>privates</quote> entries that modules may have allocated.
 
 	    </para></blockquote>
 	</para></blockquote>
@@ -2279,8 +2279,8 @@ these and will disable them before returning from
 <function>PreInit()</function>.  This also applies to all other driver
 functions.  Several functions are provided to request resource ranges,
 register these, correct PCI config space and add replacements for the
-generic access functions.  Resources may be marked ``disabled'' or
-``unused'' during OPERATING stage.  Although these steps could also be
+generic access functions.  Resources may be marked <quote>disabled</quote> or
+<quote>unused</quote> during OPERATING stage.  Although these steps could also be
 performed in <function>ScreenInit()</function>, this is not desirable.
       </para>
 
@@ -2311,18 +2311,18 @@ rules:
 	    </para></listitem>
 
 	  <listitem><para>
-   A resource marked ``disabled'' during OPERATING state will be ignored
+   A resource marked <quote>disabled</quote> during OPERATING state will be ignored
    entirely.
 	    </para></listitem>
 
 	  <listitem><para>
-   A resource marked ``unused'' will only conflicts with an overlapping
+   A resource marked <quote>unused</quote> will only conflicts with an overlapping
    resource of an other entity if the second is actually in use during
    OPERATING state.
 	    </para></listitem>
 
 	  <listitem><para>
-   If an ``unused'' resource was found to conflict however the entity
+   If an <quote>unused</quote> resource was found to conflict however the entity
    does not use any other resource of this type the entire resource type
    will be disabled for that entity.
 	    </para></listitem>
@@ -2357,7 +2357,7 @@ certain resources:
    driver function enabling them needs to disable them before it will
    return.  This should be used if a resource which can be controlled
    in a device dependent way is only required during SETUP state.  This
-   way it can be marked ``unused'' during OPERATING state.
+   way it can be marked <quote>unused</quote> during OPERATING state.
 	    </para></listitem>
 	</orderedlist>
       </para>
@@ -2602,8 +2602,8 @@ available at the driver level:
       Takes a <parameter>BusID</parameter> string, and if it is in the correct
       format, returns the PCI <parameter>bus</parameter>, <parameter>device</parameter>,
       <parameter>func</parameter> values that it indicates.  The format of the
-      string is expected to be "PCI:bus:device:func" where each of `bus',
-      `device' and `func' are decimal integers.  The ":func" part may
+      string is expected to be "PCI:bus:device:func" where each of <quote>bus</quote>,
+      <quote>device</quote> and <quote>func</quote> are decimal integers.  The ":func" part may
       be omitted, and the func value assumed to be zero, but this isn't
       encouraged.  The "PCI" prefix may also be omitted.  The prefix
       "AGP" is currently equivalent to the "PCI" prefix.  If the string
@@ -3147,7 +3147,7 @@ The flags are ORed together.
   </sect1>
 
   <sect1 id="options">
-    <title>Config file ``Option'' entries</title>
+    <title>Config file <quote>Option</quote> entries</title>
 
     <para>
 Option entries are permitted in most sections and subsections of the
@@ -3520,7 +3520,7 @@ Next, the higher level functions that most drivers would use.
 	<blockquote><para>
       This function should be used when comparing strings from the config
       file with expected values.  It works like <function>strcmp()</function>,
-      but is not case sensitive and space, tab, and `<literal>_</literal>' characters
+      but is not case sensitive and space, tab, and <quote><literal>_</literal></quote> characters
       are ignored in the comparison.  The use of this function isn't
       restricted to parsing option values.  It may be used anywhere
       where this functionality required.
@@ -4498,7 +4498,7 @@ typedef struct {
 
     <para>
 XFree86 offers the X Video Extension which allows clients to treat video
-as any another primitive and ``Put'' video into drawables.  By default,
+as any another primitive and <quote>Put</quote> video into drawables.  By default,
 the extension reports no video adaptors as being available since the
 DDX layer has not been initialized.  The driver can initialize the DDX
 layer by filling out one or more <literal remap="tt">XF86VideoAdaptorRecs</literal>
@@ -4606,12 +4606,12 @@ as follows:
 		  <term><constant>VIDEO_NO_CLIPPING</constant></term>
 		  <listitem><para>
 	   This indicates that the video adaptor does not support
-	   clipping.  The driver will never receive ``Put'' requests
+	   clipping.  The driver will never receive <quote>Put</quote> requests
 	   where less than the entire area determined by
 	   <parameter>drw_x</parameter>, <parameter>drw_y</parameter>,
 	   <parameter>drw_w</parameter> and <parameter>drw_h</parameter> is visible.
-	   This flag does not apply to ``Get'' requests.  Hardware
-	   that is incapable of clipping ``Gets'' may punt or get
+	   This flag does not apply to <quote>Get</quote> requests.  Hardware
+	   that is incapable of clipping <quote>Gets</quote> may punt or get
 	   the extents of the clipping region passed to it.
 		    </para></listitem>
 
@@ -4817,7 +4817,7 @@ as follows:
 	  the various hardware expected to be used with this extension,
 	  it is not expected that all hardware will be able to do this
 	  exactly as described.  In that case the driver should just do
-	  ``the best it can,'' scaling as closely to the target rectangle
+	  <quote>the best it can,</quote> scaling as closely to the target rectangle
 	  as it can without rendering outside of it.  In the worst case,
 	  the driver can opt to just not turn on the video.
 	      </para>
@@ -5065,7 +5065,7 @@ typedef struct {
    Each adaptor may have an array of these advertising the attributes
    for its ports.  Currently defined flags are <literal remap="tt">XvGettable</literal>
    and <literal remap="tt">XvSettable</literal> which may be OR'd together indicating that
-   attribute is ``gettable'' or ``settable'' by the client.  The
+   attribute is <quote>gettable</quote> or <quote>settable</quote> by the client.  The
    <literal remap="tt">min</literal> and <literal remap="tt">max</literal> field specify the valid range
    for the value.  <literal remap="tt">Name</literal> is a text string describing the
    attribute by name.
@@ -5385,7 +5385,7 @@ XFree86 common layer.
 		    </para>
 
 		    <para>
-		  When loading ``external'' modules (modules that don't
+		  When loading <quote>external</quote> modules (modules that don't
 		  have the standard entry point, for example a
 		  special shared library) the options parameter can be
 		  set to <constant>EXTERN_MODULE</constant> to tell the
@@ -5423,7 +5423,7 @@ typedef struct {
 		  information in the module's
 		  <structname>XF86ModuleVersionInfo</structname> record (which
 		  is described below).  The values in comments above
-		  indicate ``don't care'' settings for each of the fields.
+		  indicate <quote>don't care</quote> settings for each of the fields.
 		  The comparisons made are as follows:
 
 		      <variablelist>
@@ -5968,12 +5968,12 @@ the server, and may also be used from within modules.
                    int errmaj, int errmin);
 	  </programlisting>
 	  <blockquote><para>
-    This function prints an error message that includes the text ``Failed
-    to load module'', the module name <parameter>modname</parameter>, a message
+    This function prints an error message that includes the text <quote>Failed
+    to load module</quote>, the module name <parameter>modname</parameter>, a message
     specific to the <parameter>errmaj</parameter> value, and the value if
     <parameter>errmin</parameter>.  If <parameter>name</parameter> is
     non-<constant>NULL</constant>, it is printed as an identifying prefix
-    to the message (followed by a `:').
+    to the message (followed by a <quote>:</quote>).
 	    </para>
 
 	  </blockquote></para></blockquote>
@@ -6036,9 +6036,9 @@ typedef struct {
     <title>Helper Functions</title>
 
     <para>
-This section describe ``helper'' functions that video driver
+This section describe <quote>helper</quote> functions that video driver
 might find useful.  While video drivers are not required to use any of
-these to be considered ``compliant'', the use of appropriate helpers is
+these to be considered <quote>compliant</quote>, the use of appropriate helpers is
 strongly encouraged to improve the consistency of driver behaviour.
     </para>
 
@@ -6994,7 +6994,7 @@ be catered for the by the helpers.
 	    <para>
       Note that the <structfield>mode-&gt;SynthClock</structfield> field is always
       filled in by <function>xf86ValidateModes()</function>: it will contain
-      the ``data transport clock'', which is the clock that will have
+      the <quote>data transport clock</quote>, which is the clock that will have
       to be programmed in the chip when it has a programmable clock, or
       the clock that will be picked from the clocks list when it is not
       a programmable one.  Thus:
@@ -7975,7 +7975,7 @@ programming the standard VGA registers, and for handling VGA colourmaps.
     void writeMiscOut(vgaHWPtr hwp, CARD8 value);
 	  </programlisting>
 	  <blockquote><para>
-      Write `<parameter>value</parameter>' to the Miscellaneous Output register.
+      Write <quote><parameter>value</parameter></quote> to the Miscellaneous Output register.
 	    </para>
 
 	  </blockquote></para></blockquote>
@@ -8112,7 +8112,7 @@ most drivers (even those which don't fit that basic description).
 
     <para>
 The information here is based on the initial conversion of the Matrox
-Millennium driver to the ``new design''.  For a fleshing out and sample
+Millennium driver to the <quote>new design</quote>.  For a fleshing out and sample
 implementation of some of the bits outlined here, refer to that driver.
 Note that this is an example only.  The approach used here will not be
 appropriate for all drivers.
@@ -8122,7 +8122,7 @@ appropriate for all drivers.
 Each driver must reserve a unique driver name, and a string that is used
 to prefix all of its externally visible symbols.  This is to avoid name
 space clashes when loading multiple drivers.  The examples here are for
-the ``ZZZ'' driver, which uses the ``ZZZ'' or ``zzz'' prefix for its externally
+the <quote>ZZZ</quote> driver, which uses the <quote>ZZZ</quote> or <quote>zzz</quote> prefix for its externally
 visible symbols.
     </para>
 
@@ -8373,7 +8373,7 @@ typedef struct {
 	<listitem>
 	  <para>
     Define the list of config file Options that the driver accepts.  For
-    consistency between drivers those in the list of ``standard'' options
+    consistency between drivers those in the list of <quote>standard</quote> options
     should be used where appropriate before inventing new options.
 
 	    <programlisting>
commit 8367913be3305be4f03d095615d3885107094427
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Fri May 14 22:05:50 2010 -0700

    XFree86 Design doc: Explain this version covers the current Xorg release
    
    Update the title & preface to explain that while this was originally
    the XFree86 4.0 design, we've changed a lot since forking.
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Tested-by: Gaetan Nadon <memsize at videotron.ca>

diff --git a/hw/xfree86/doc/sgml/DESIGN.xml b/hw/xfree86/doc/sgml/DESIGN.xml
index 200990c..8a3047b 100644
--- a/hw/xfree86/doc/sgml/DESIGN.xml
+++ b/hw/xfree86/doc/sgml/DESIGN.xml
@@ -19,10 +19,13 @@
 <article>
   <articleinfo>
 
-    <title>XFree86 server 4.x Design (DRAFT)</title>
+    <title>XFree86 DDX Design (Xorg server version &xserver.version;)</title>
 
     <authorgroup>
-      <corpauthor>The XFree86 Project, Inc</corpauthor>
+      <corpauthor><ulink url="http://www.xfree86.org/">
+	The XFree86 Project, Inc.</ulink></corpauthor>
+      <corpauthor><ulink url="http://www.x.org/">
+	The X.Org Foundation, Inc.</ulink></corpauthor>
 
       <othercredit>
 	<firstname>Jim</firstname><surname>Gettys</surname>
@@ -36,8 +39,11 @@
   </articleinfo>
 
   <note><para>
-This is a DRAFT document, and the interfaces described here
-are subject to change without notice.
+This document describes software undergoing continual evolution, and
+the interfaces described here are subject to change without notice.
+This document is intended to cover the interfaces as found in the
+xorg-server-&xserver.version; release, but is probably not completely
+in sync with the code base.
     </para></note>
 
 
@@ -45,7 +51,17 @@ are subject to change without notice.
     <title>Preface</title>
 
     <para>
-The broad design principles are:
+This document was originally the design spec for the DDX layer of the
+XFree86 4.0 X server.  The X.Org Foundation adopted the XFree86 4.4rc2
+version of that server as the basis of the Xorg server project, and has
+evolved the XFree86 DDX layer greatly since forking.   This document thus
+covers only the current implementation of the XFree86 DDX as found in the
+Xorg server &xserver.version; release, and no longer matches the XFree86
+server itself.
+      </para>
+
+    <para>
+The XFree86 Project's broad design principles for XFree86 4.0 were:
       <itemizedlist>
 	<listitem><para>keep it reasonable
 	    <itemizedlist>
@@ -86,8 +102,15 @@ The broad design principles are:
     </para>
 
     <para>
-Unless we find major deficiencies in the DIX layer, we should avoid
-making changes there.
+While the XFree86 project had a goal of avoiding changes to the DIX
+layer unless they found major deficiencies there, to avoid divergence from
+the X.Org sample implementation they were integrating changes from, the
+X.Org developers now maintain both sides, and make changes where they are
+most appropriate.   This document concentrates on the XFree86 DDX layer used
+in the Xorg server itself (the code found in <filename>hw/xfree86</filename>
+in the source tree), and developers will also want to refer to the
+<filename>Xserver-spec</filename> documentation that covers the DIX layer
+routines common to all the X servers in the sample implementation.
     </para>
   </sect1>
 
commit 78fe4be4c43db1f07a30e8a6c9a17f81c1082d76
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Mon May 17 20:27:10 2010 -0700

    Show Xserver release/version date in DIX & DDX docs
    
    Uses a fake absolute path to the entity definition files so that
    the xmlto --searchpath will work for finding the actual path
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Reviewed-by: Dan Nicholson <dbn.lists at gmail.com>
    Tested-by: Gaetan Nadon <memsize at videotron.ca>

diff --git a/configure.ac b/configure.ac
index 25a27a7..b5b638a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2139,6 +2139,7 @@ AC_TRY_COMPILE([
 
 AC_DEFINE_DIR(PROJECTROOT, prefix, [Overall prefix])
 
+AC_SUBST([RELEASE_DATE])
 BUILD_DATE="`date +'%Y%m%d'`"
 AC_SUBST([BUILD_DATE])
 BUILD_TIME="`date +'1%H%M%S'`"
@@ -2162,6 +2163,7 @@ dbe/Makefile
 dix/Makefile
 doc/Makefile
 doc/xml/Makefile
+doc/xml/xserver.ent
 fb/Makefile
 record/Makefile
 config/Makefile
diff --git a/doc/xml/.gitignore b/doc/xml/.gitignore
new file mode 100644
index 0000000..4961738
--- /dev/null
+++ b/doc/xml/.gitignore
@@ -0,0 +1,5 @@
+#		Add & Override for this directory and its subdirectories
+xserver.ent
+Xserver-spec.html
+Xserver-spec.pdf
+Xserver-spec.txt
diff --git a/doc/xml/Xserver-spec.xml b/doc/xml/Xserver-spec.xml
index 8691f18..1bea20f 100644
--- a/doc/xml/Xserver-spec.xml
+++ b/doc/xml/Xserver-spec.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="ISO-8859-1"?>
 <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
  "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+ <!ENTITY % defs SYSTEM "/xserver/doc/xml/xserver.ent"> %defs;
 ]>
 
 <article>
@@ -38,7 +39,8 @@
       <affiliation><orgname>X.org Foundation and Hewlett Packard</orgname></affiliation>
     </author>
     <publisher><publishername>The X.Org Foundation</publishername></publisher>
-    <pubdate>2004</pubdate>
+    <pubdate>&xserver.reldate;</pubdate>
+    <releaseinfo>X server version &xserver.version;</releaseinfo>
     <title>Definition of the Porting Layer for the X v11 Sample Server</title>
     <titleabbrev>X Porting Layer</titleabbrev>
     <revhistory>
diff --git a/doc/xml/xmlrules.in b/doc/xml/xmlrules.in
index a4d43f9..1be3691 100644
--- a/doc/xml/xmlrules.in
+++ b/doc/xml/xmlrules.in
@@ -36,24 +36,33 @@ BUILT_DOC_FILES =
 
 SUFFIXES = .xml .txt .html .pdf
 
+XML_ENT_DIR = $(abs_top_builddir)/doc/xml
+XMLTO_FLAGS = --searchpath $(XML_ENT_DIR)
+
 if HAVE_XMLTO
 BUILT_DOC_FILES += $(TXT_FILES)
 .xml.txt:
 	@rm -f $@
-	$(AM_V_GEN)$(XMLTO) txt $<
+	$(AM_V_GEN)$(XMLTO) $(XMLTO_FLAGS) txt $<
 
 BUILT_DOC_FILES += $(HTML_FILES)
 .xml.html:
 	@rm -f $@
-	$(AM_V_GEN)$(XMLTO) xhtml-nochunks $<
+	$(AM_V_GEN)$(XMLTO) $(XMLTO_FLAGS) xhtml-nochunks $<
 
 if HAVE_FOP
 BUILT_DOC_FILES += $(PDF_FILES)
 .xml.pdf:
 	@rm -f $@
-	$(AM_V_GEN)$(XMLTO) --with-fop pdf $<
+	$(AM_V_GEN)$(XMLTO) $(XMLTO_FLAGS) --with-fop pdf $<
 endif
 
 endif
 
 CLEAN_DOC_FILES = $(TXT_FILES) $(HTML_FILES) $(PDF_FILES)
+
+# All the files we build depend on the entities
+$(BUILT_DOC_FILES): $(XML_ENT_DIR)/xserver.ent
+
+$(XML_ENT_DIR)/xserver.ent:
+	(cd $(XML_ENT_DIR) && $(MAKE) $(AM_MAKEFLAGS) $(@F))
diff --git a/doc/xml/xserver.ent.in b/doc/xml/xserver.ent.in
new file mode 100644
index 0000000..5cb4e23
--- /dev/null
+++ b/doc/xml/xserver.ent.in
@@ -0,0 +1,3 @@
+<!-- shared -*-xml-*- entity definitions for the X server documentation -->
+<!ENTITY xserver.version "@PACKAGE_VERSION@">
+<!ENTITY xserver.reldate "@RELEASE_DATE@">
diff --git a/hw/xfree86/doc/sgml/DESIGN.xml b/hw/xfree86/doc/sgml/DESIGN.xml
index 6abfa60..200990c 100644
--- a/hw/xfree86/doc/sgml/DESIGN.xml
+++ b/hw/xfree86/doc/sgml/DESIGN.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="ISO-8859-1"?>
 <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
  "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+ <!ENTITY % defs SYSTEM "/xserver/doc/xml/xserver.ent"> %defs;
  <!-- config file keyword markup -->
  <!-- specific config file keywords -->
  <!ENTITY k.device "<emphasis>Device</emphasis>">
@@ -29,7 +30,8 @@
       </othercredit>
     </authorgroup>
 
-    <pubdate>19 December 2003</pubdate>
+    <pubdate>&xserver.reldate;</pubdate>
+    <releaseinfo>Xorg server version &xserver.version;</releaseinfo>
 
   </articleinfo>
 
commit 2bdc73bcf41ff0c10e70ecc15fc8b8333af6db65
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Fri May 14 15:33:46 2010 -0700

    Move Xserver-spec.xml from xorg-docs to doc/xml
    
    Allows keeping it in sync with the sources it documents, and to be
    released with them
    
    Requires the previous patch to convert the Xserver tree from
    LinuxDoc to DocBook for SGML/XML documents.
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Reviewed-by: Rémi Cardona <remi at gentoo.org>
    Tested-by: Gaetan Nadon <memsize at videotron.ca>

diff --git a/configure.ac b/configure.ac
index 41fa63f..25a27a7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2161,6 +2161,7 @@ damageext/Makefile
 dbe/Makefile
 dix/Makefile
 doc/Makefile
+doc/xml/Makefile
 fb/Makefile
 record/Makefile
 config/Makefile
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 2ff683c..43606a3 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -22,3 +22,5 @@ EXTRAMANDEFS = -D__default_font_path__="`echo $(COMPILEDDEFAULTFONTPATH) | $(SED
 DEVEL_DOCS = smartsched
 
 EXTRA_DIST = $(DEVEL_DOCS) $(appman_PRE) $(fileman_PRE)
+
+SUBDIRS = xml
diff --git a/doc/xml/Makefile.am b/doc/xml/Makefile.am
new file mode 100644
index 0000000..df4833c
--- /dev/null
+++ b/doc/xml/Makefile.am
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
+
+XML_FILES = Xserver-spec.xml
+
+include xmlrules.in
+
+if ENABLE_DEVEL_DOCS
+noinst_DATA = $(BUILT_DOC_FILES)
+endif
+CLEANFILES = $(CLEAN_DOC_FILES)
+
+EXTRA_DIST = $(XML_FILES)
diff --git a/doc/xml/Xserver-spec.xml b/doc/xml/Xserver-spec.xml
new file mode 100644
index 0000000..8691f18
--- /dev/null
+++ b/doc/xml/Xserver-spec.xml
@@ -0,0 +1,5180 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+]>
+
+<article>
+  <articleinfo>
+    <author>
+      <firstname>Susan</firstname><surname>Angebranndt</surname>
+      <affiliation><orgname>Digital Equipment Corporation</orgname></affiliation>
+    </author>
+    <author>
+      <firstname>Raymond</firstname><surname>Drewry</surname>
+      <affiliation><orgname>Digital Equipment Corporation</orgname></affiliation>
+    </author>
+    <author>
+      <firstname>Philip</firstname><surname>Karlton</surname>
+      <affiliation><orgname>Digital Equipment Corporation</orgname></affiliation>
+    </author>
+    <author>
+      <firstname>Todd</firstname><surname>Newman</surname>
+      <affiliation><orgname>Digital Equipment Corporation</orgname></affiliation>
+    </author>
+    <author>
+      <firstname>Bob</firstname><surname>Scheifler</surname>
+      <affiliation><orgname>Massachusetts Institute of Technology</orgname></affiliation>
+    </author>
+    <author>
+      <firstname>Keith</firstname><surname>Packard</surname>
+      <affiliation><orgname>MIT X Consortium</orgname></affiliation>
+    </author>
+    <author>
+      <firstname>David</firstname><othername>P.</othername><surname>Wiggins</surname>
+      <affiliation><orgname>X Consortium</orgname></affiliation>
+    </author>
+    <author>
+      <firstname>Jim</firstname><surname>Gettys</surname>
+      <affiliation><orgname>X.org Foundation and Hewlett Packard</orgname></affiliation>
+    </author>
+    <publisher><publishername>The X.Org Foundation</publishername></publisher>
+    <pubdate>2004</pubdate>
+    <title>Definition of the Porting Layer for the X v11 Sample Server</title>
+    <titleabbrev>X Porting Layer</titleabbrev>
+    <revhistory>
+      <revision>
+	<revnumber>1.0</revnumber>
+	<date>27 Oct 2004</date>
+	<authorinitials>sa</authorinitials>
+	<revremark>Initial Version</revremark>
+      </revision>
+      <revision>
+	<revnumber>1.1</revnumber>
+	<date>27 Oct 2004</date>
+	<authorinitials>bs</authorinitials>
+	<revremark>Minor Revisions</revremark>
+      </revision>
+      <revision>
+	<revnumber>2.0</revnumber>
+	<date>27 Oct 2004</date>
+	<authorinitials>kp</authorinitials>
+	<revremark>Revised for Release 4 and 5</revremark>
+      </revision>
+      <revision>
+	<revnumber>3.0</revnumber>
+	<date>27 Oct 2004</date>
+	<authorinitials>dpw</authorinitials>
+	<revremark>Revised for Release 6</revremark>
+      </revision>
+      <revision>
+	<revnumber>3.1</revnumber>
+	<date>27 Oct 2004</date>
+	<authorinitials>jg</authorinitials>
+	<revremark>Revised for Release 6.8.2</revremark>
+      </revision>
+      <revision>
+	<revnumber>3.2</revnumber>
+	<date>17 Dec 2006</date>
+	<authorinitials>efw</authorinitials>
+	<revremark>DocBook conversion</revremark>
+      </revision>
+      <revision>
+	<revnumber>3.3</revnumber>
+	<date>17 Feb 2008</date>
+	<authorinitials>aj</authorinitials>
+	<revremark>Revised for backing store changes</revremark>
+      </revision>
+      <revision>
+	<revnumber>3.4</revnumber>
+	<date>31 Mar 2008</date>
+	<authorinitials>efw</authorinitials>
+	<revremark>Revised for devPrivates changes</revremark>
+      </revision>
+    </revhistory>
+    <legalnotice>
+      <para>Copyright &#xA9; 1994 X Consortium, Inc., 2004 X.org Foundation, Inc.</para>
+      <para>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ``Software''), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</para>
+      <para>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</para>
+      <para>THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</para>
+      <para>LK201 and DEC are trademarks of Digital Equipment Corporation.  Macintosh and Apple are trademarks of Apple Computer, Inc.  PostScript is a trademark of Adobe Systems, Inc.  Ethernet is a trademark of Xerox Corporation.  X Window System is a trademark of the X.org Foundation, Inc.  Cray is a trademark of Cray Research, Inc.</para>
+    </legalnotice>
+    <abstract>
+      <para>The following document explains the structure of the X Window System display server and the interfaces among the larger pieces.  It is intended as a reference for programmers who are implementing an X Display Server on their workstation hardware.  It is included with the X Window System source tape, along with the document "Strategies for Porting the X v11 Sample Server."  The order in which you should read these documents is:
+      <orderedlist>
+	<listitem><para>Read the first section of the "Strategies for Porting" document (Overview of Porting Process).</para></listitem>
+	<listitem><para>Skim over this document (the Definition document).</para></listitem>
+	<listitem><para>Skim over the remainder of the Strategies document.</para></listitem>
+	<listitem><para>Start planning and working, referring to the Strategies and Definition documents.</para></listitem>
+      </orderedlist>
+      You may also want to look at the following documents:
+      <itemizedlist>
+	<listitem><para>"The X Window System" for an overview of X.</para></listitem>
+	<listitem><para>"Xlib - C Language X Interface" for a view of what the client programmer sees.</para></listitem>
+	<listitem><para>"X Window System Protocol" for a terse description of the byte stream protocol between the client and server.</para></listitem>
+      </itemizedlist>
+      </para>
+      <para>To understand this document and the accompanying source code, you should know the C language.  You should be familiar with 2D graphics and windowing concepts such as clipping, bitmaps, fonts, etc.  You should have a general knowledge of the X Window System.  To implement the server code on your hardware, you need to know a lot about your hardware, its graphic display device(s), and (possibly) its networking and multitasking facilities.  This document depends a lot on the source code, so you should have a listing of the code handy.</para>
+      <para>Some source in the distribution is directly compilable on your machine.  Some of it will require modification.  Other parts may have to be completely written from scratch.  The distribution also includes source for a sample implementation of a display server which runs on a very wide variety of color and monochrome displays on Linux and *BSD which you will find useful for implementing any type of X server.</para>
+      <para>Note to the 2008 edition: at this time this document must be considered incomplete, though improved over the 2004 edition.  In particular, the new Render extension is still lacking good documentation, and has become vital to high performance X implementations.  Modern applications and desktop environments are now much more sensitive to good implementation of the Render extension than in most operations of the old X graphics model.  The shadow frame buffer implementation is also very useful in many circumstances, and also needs documentation.  We hope to rectify these shortcomings in our documentation in the future.  Help would be greatly appreciated.</para>
+    </abstract>
+  </articleinfo>
+
+<!-- Original authorship information:
+
+.OF 'Porting Layer Definition'- % -'October 27, 2004'
+Definition of the Porting Layer
+for the X v11 Sample Server
+Susan Angebranndt
+Raymond Drewry
+Philip Karlton
+Todd Newman
+Digital Equipment Corporation
+
+minor revisions by
+Bob Scheifler
+Massachusetts Institute of Technology
+
+Revised for Release 4 and Release 5 by
+Keith Packard
+MIT X Consortium
+
+Revised for Release 6 by
+David P. Wiggins
+X Consortium
+
+Minor Revisions for Release 6.8.2 by
+Jim Gettys
+X.org Foundation and Hewlett Packard
+-->
+
+<section>
+  <title>The X Window System</title>
+<para>
+The X Window System, or simply "X," is a
+windowing system that provides high-performance, high-level,
+device-independent graphics.
+</para>
+<para>
+X is a windowing system designed for bitmapped graphic displays.
+The display can have a
+simple, monochrome display or it can have a color display with up to 32 bits
+per pixel with a special graphics processor doing the work.  (In this
+document, monochrome means a black and white display with one bit per pixel.
+Even though the usual meaning of monochrome is more general, this special
+case is so common that we decided to reserve the word for this purpose.)
+In practice, monochrome displays are now almost unheard of, with 4 bit
+gray scale displays being the low end.
+</para>
+<para>
+X is designed for a networking environment where
+users can run applications on machines other than their own workstations.
+Sometimes, the connection is over an Ethernet network with a protocol such as TCP/IP;
+but, any "reliable" byte stream is allowable.
+A high-bandwidth byte stream is preferable; RS-232 at
+9600 baud would be slow without compression techniques.
+</para>
+<para>
+X by itself allows great freedom of design.
+For instance, it does not include any user interface standard.
+Its intent is to "provide mechanism, not policy."
+By making it general, it can be the foundation for a wide
+variety of interactive software.
+</para>
+<para>
+For a more detailed overview, see the document "The X Window System."
+For details on the byte stream protocol, see "X Window System protocol."
+</para>
+</section>
+<section>
+<title>Overview of the Server</title>
+<para>
+The display server
+manages windows and simple graphics requests
+for the user on behalf of different client applications.
+The client applications can be running on any machine on the network.
+The server mainly does three things:
+<itemizedlist>
+  <listitem><para>Responds to protocol requests from existing clients (mostly graphic and text drawing commands)</para></listitem>
+  <listitem><para>Sends device input (keystrokes and mouse actions) and other events to existing clients</para></listitem>
+  <listitem><para>Maintains client connections</para></listitem>
+</itemizedlist>
+</para>
+<para>
+The server code is organized into four major pieces:
+<itemizedlist>
+  <listitem><para>Device Independent (DIX) layer - code shared among all implementations</para></listitem>
+  <listitem><para>Operating System (OS) layer - code that is different for each operating system but is shared among all graphic devices for this operating system</para></listitem>
+  <listitem><para>Device Dependent (DDX) layer - code that is (potentially) different for each combination of operating system and graphic device</para></listitem>
+  <listitem><para>Extension Interface - a standard way to add features to the X server</para></listitem>
+</itemizedlist>
+</para>
+<para>
+The "porting layer" consists of the OS and DDX layers; these are
+actually parallel and neither one is on top of the other.
+The DIX layer is intended to be portable
+without change to target systems and is not
+detailed here, although several routines
+in DIX that are called by DDX are
+documented.
+Extensions incorporate new functionality into the server; and require
+additional functionality over a simple DDX.
+</para>
+<para>
+The following sections outline the functions of the layers.
+Section 3 briefly tells what you need to know about the DIX layer.
+The OS layer is explained in Section 4.
+Section 5 gives the theory of operation and procedural interface for the
+DDX layer.
+Section 6 describes the functions which exist for the extension writer.
+</para>
+</section>
+
+<section>
+  <title>DIX Layer</title>
+<para>
+The DIX layer is the machine and device independent part of X.
+The source should be common to all operating systems and devices.
+The port process should not include changes to this part, therefore internal interfaces to DIX
+modules are not discussed, except for public interfaces to the DDX and the OS layers.
+The functions described in this section are available for extension writers to use.
+</para>
+<para>
+In the process of getting your server to work, if
+you think that DIX must be modified for purposes other than bug fixes,
+you may be doing something wrong.
+Keep looking for a more compatible solution.
+When the next release of the X server code is available,
+you should be able to just drop in the new DIX code and compile it.
+If you change DIX,
+you will have to remember what changes you made and will have
+to change the new sources before you can update to the new version.
+</para>
+<para>
+The heart of the DIX code is a loop called the dispatch loop.
+Each time the processor goes around the loop, it sends off accumulated input events
+from the input devices to the clients, and it processes requests from the clients.
+This loop is the most organized way for the server to
+process the asynchronous requests that
+it needs to process.
+Most of these operations are performed by OS and DDX routines that you must supply.
+</para>
+<section>
+  <title>Server Resource System</title>
+<para>
+X resources are C structs inside the server.
+Client applications create and manipulate these objects
+according to the rules of the X byte stream protocol.
+Client applications refer to resources with resource IDs,
+which are 32-bit integers that are sent over the network.
+Within the server, of course, they are just C structs, and we refer to them
+by pointers.
+</para>
+<section>
+  <title>Pre-Defined Resource Types</title>
+<para>
+The DDX layer has several kinds of resources:
+<itemizedlist>
+<listitem><para>Window</para></listitem>
+<listitem><para>Pixmap</para></listitem>
+<listitem><para>Screen</para></listitem>
+<listitem><para>Device</para></listitem>
+<listitem><para>Colormap</para></listitem>
+<listitem><para>Font</para></listitem>
+<listitem><para>Cursor</para></listitem>
+<listitem><para>Graphics Contexts</para></listitem>
+</itemizedlist>
+</para>
+<para>
+The type names of the more
+important server
+structs usually end in "Rec," such as "DeviceRec;"
+the pointer types usually end in "Ptr," such as "DevicePtr."
+</para>
+<para>
+The structs and
+important defined constants are declared
+in .h files that have names that suggest the name of the object.
+For instance, there are two .h files for windows,
+window.h and windowstr.h.
+window.h defines only what needs to be defined in order to use windows
+without peeking inside of them;
+windowstr.h defines the structs with all of their components in great detail
+for those who need it.
+</para>
+<para>
+Three kinds of fields are in these structs:
+<itemizedlist>
+<listitem><para>Attribute fields - struct fields that contain values like normal structs</para></listitem>
+<listitem><para>Pointers to procedures, or structures of procedures, that operate on the object</para></listitem>
+<listitem><para>A single private field or a devPrivates list (see <xref linkend="wrappers_and_privates"/>)
+used by your DDX code to store private data.</para></listitem>
+</itemizedlist>
+</para>
+<para>
+DIX calls through
+the struct's procedure pointers to do its tasks.
+These procedures are set either directly or indirectly by DDX procedures.
+Most of
+the procedures described in the remainder of this
+document are accessed through one of these structs.
+For example, the procedure to create a pixmap
+is attached to a ScreenRec and might be called by using the expression
+</para>
+<para>
+<blockquote>
+<programlisting>(* pScreen->CreatePixmap)(pScreen, width, height, depth).</programlisting>
+</blockquote>
+</para>
+<para>
+All procedure pointers must be set to some routine unless noted otherwise;
+a null pointer will have unfortunate consequences.
+</para>
+<para>
+Procedure routines will be indicated in the documentation by this convention:
+<blockquote>
+<programlisting>void pScreen->MyScreenRoutine(arg, arg, ...)</programlisting>
+</blockquote>
+as opposed to a free routine, not in a data structure:
+<blockquote>
+<programlisting>void MyFreeRoutine(arg, arg, ...)</programlisting>
+</blockquote>
+</para>
+<para>
+The attribute fields are mostly set by DIX; DDX should not modify them
+unless noted otherwise.
+</para>
+</section>
+<section>
+  <title>Creating Resources and Resource Types</title>
+<para>
+These functions should also be called from your extensionInitProc to
+allocate all of the various resource classes and types required for
+the extension.  Each time the server resets, these types must be reallocated
+as the old allocations will have been discarded.
+Resource types are integer values starting at 1.  Get
+a resource type by calling
+<blockquote><programlisting>
+
+    RESTYPE CreateNewResourceType(deleteFunc)
+
+</programlisting></blockquote>
+deleteFunc will be called to destroy all resources with this
+type.</para>
+<para>
+Resource classes are masks starting at 1 &lt;&lt; 31 which can
+be or'ed with any resource type to provide attributes for the
+type.  To allocate a new class bit, call
+<blockquote><programlisting>
+
+    RESTYPE CreateNewResourceClass()
+
+</programlisting></blockquote>
+</para>
+<para>
+There are two ways of looking up resources, by type or
+by class.  Classes are non-exclusive subsets of the space of
+all resources, so you can lookup the union of multiple classes.
+(RC_ANY is the union of all classes).</para>
+<para>
+Note that the appropriate class bits must be or'ed into the value returned
+by CreateNewResourceType when calling resource lookup functions.</para>
+<para>
+If you need to create a ``private'' resource ID for internal use, you
+can call FakeClientID.
+<blockquote><programlisting>
+
+	XID FakeClientID(client)
+	    int client;
+
+</programlisting></blockquote>
+This allocates from ID space reserved for the server.</para>
+<para>
+To associate a resource value with an ID, use AddResource.
+<blockquote><programlisting>
+
+	Bool AddResource(id, type, value)
+	    XID id;
+	    RESTYPE type;
+	    pointer value;
+
+</programlisting></blockquote>
+The type should be the full type of the resource, including any class
+bits.  If AddResource fails to allocate memory to store the resource,
+it will call the deleteFunc for the type, and then return False.</para>
+<para>
+To free a resource, use one of the following.
+<blockquote><programlisting>
+
+	void FreeResource(id, skipDeleteFuncType)
+	    XID id;
+	    RESTYPE skipDeleteFuncType;
+
+	void FreeResourceByType(id, type, skipFree)
+	    XID id;
+	    RESTYPE type;
+	    Bool    skipFree;
+
+</programlisting></blockquote>
+FreeResource frees all resources matching the given id, regardless of
+type; the type's deleteFunc will be called on each matching resource,
+except that skipDeleteFuncType can be set to a single type for which
+the deleteFunc should not be called (otherwise pass RT_NONE).
+FreeResourceByType frees a specific resource matching a given id
+and type; if skipFree is true, then the deleteFunc is not called.
+</para>
+</section>
+<section>
+  <title>Looking Up Resources</title>
+<para>
+To look up a resource, use one of the following.
+<blockquote><programlisting>
+
+	pointer LookupIDByType(id, rtype)
+	    XID id;
+	    RESTYPE rtype;
+
+	pointer LookupIDByClass(id, classes)
+	    XID id;
+	    RESTYPE classes;
+
+</programlisting></blockquote>
+LookupIDByType finds a resource with the given id and exact type.
+LookupIDByClass finds a resource with the given id whose type is
+included in any one of the specified classes.</para>
+</section>
+</section>
+<section>
+  <title>Callback Manager</title>
+<para>
+To satisfy a growing number of requests for the introduction of ad hoc
+notification style hooks in the server, a generic callback manager was
+introduced in R6.  A callback list object can be introduced for each
+new hook that is desired, and other modules in the server can register
+interest in the new callback list.  The following functions support
+these operations.</para>
+<para>
+Before getting bogged down in the interface details, an typical usage
+example should establish the framework.  Let's look at the
+ClientStateCallback in dix/dispatch.c.  The purpose of this particular
+callback is to notify intereseted parties when a client's state
+(initial, running, gone) changes.  The callback is "created" in this
+case by simply declaring a variable:
+<blockquote><programlisting>
+	CallbackListPtr ClientStateCallback;
+</programlisting></blockquote>
+</para>
+<para>
+Whenever the client's state changes, the following code appears, which notifies
+all intereseted parties of the change:
+<blockquote><programlisting>
+	if (ClientStateCallback) CallCallbacks(&amp;ClientStateCallback, (pointer)client);
+</programlisting></blockquote>
+</para>
+<para>
+Interested parties subscribe to the ClientStateCallback list by saying:
+<blockquote><programlisting>
+	AddCallback(&amp;ClientStateCallback, func, data);
+</programlisting></blockquote>
+</para>
+<para>
+When CallCallbacks is invoked on the list, func will be called thusly:
+<blockquote><programlisting>
+	(*func)(&amp;ClientStateCallback, data, client)
+</programlisting></blockquote>
+</para>
+<para>
+Now for the details.
+<blockquote><programlisting>
+
+	Bool CreateCallbackList(pcbl, cbfuncs)
+	    CallbackListPtr  *pcbl;
+	    CallbackFuncsPtr cbfuncs;
+
+</programlisting></blockquote>
+CreateCallbackList creates a callback list.  We envision that this
+function will be rarely used because the callback list is created
+automatically (if it doesn't already exist) when the first call to
+AddCallback is made on the list.  The only reason to explicitly create
+the callback list with this function is if you want to override the
+implementation of some of the other operations on the list by passing
+your own cbfuncs.  You also lose something by explicit creation: you
+introduce an order dependency during server startup because the list
+must be created before any modules subscribe to it.  Returns TRUE if
+successful.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool AddCallback(pcbl, callback, subscriber_data)
+	    CallbackListPtr *pcbl;
+	    CallbackProcPtr callback;
+	    pointer         subscriber_data;
+
+</programlisting></blockquote>
+Adds the (callback, subscriber_data) pair to the given callback list.  Creates the callback
+list if it doesn't exist.  Returns TRUE if successful.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool DeleteCallback(pcbl, callback, subscriber_data)
+	    CallbackListPtr *pcbl;
+	    CallbackProcPtr callback;
+	    pointer         subscriber_data;
+
+</programlisting></blockquote>
+Removes the (callback, data) pair to the given callback list if present.
+Returns TRUE if (callback, data) was found.</para>
+<para>
+<blockquote><programlisting>
+
+	void CallCallbacks(pcbl, call_data)
+	    CallbackListPtr    *pcbl;
+	    pointer	    call_data;
+
+</programlisting></blockquote>
+For each callback currently registered on the given callback list, call
+it as follows:
+<blockquote><programlisting>
+
+	(*callback)(pcbl, subscriber_data, call_data);
+</programlisting></blockquote>
+</para>
+<para>
+<blockquote><programlisting>
+	void DeleteCallbackList(pcbl)
+	    CallbackListPtr    *pcbl;
+
+</programlisting></blockquote>
+Destroys the given callback list.</para>
+</section>
+<section>
+  <title>Extension Interfaces</title>
+<para>
+This function should be called from your extensionInitProc which
+should be called by InitExtensions.
+<blockquote><programlisting>
+
+	ExtensionEntry *AddExtension(name, NumEvents,NumErrors,
+		MainProc, SwappedMainProc, CloseDownProc, MinorOpcodeProc)
+
+		char *name;  /*Null terminate string; case matters*/
+		int NumEvents;
+		int NumErrors;
+		int (* MainProc)(ClientPtr);/*Called if client matches server order*/
+		int (* SwappedMainProc)(ClientPtr);/*Called if client differs from server*/
+		void (* CloseDownProc)(ExtensionEntry *);
+		unsigned short (*MinorOpcodeProc)(ClientPtr);
+
+</programlisting></blockquote>
+name is the name used by clients to refer to the extension.  NumEvents is the
+number of event types used by the extension, NumErrors is the number of
+error codes needed by the extension.  MainProc is called whenever a client
+accesses the major opcode assigned to the extension.  SwappedMainProc is
+identical, except the client using the extension has reversed byte-sex.
+CloseDownProc is called at server reset time to deallocate any private
+storage used by the extension.  MinorOpcodeProc is used by DIX to place the
+appropriate value into errors.  The DIX routine StandardMinorOpcode can be
+used here which takes the minor opcode from the normal place in the request
+(i.e. just after the major opcode).</para>
+</section>
+<section>
+  <title>Macros and Other Helpers</title>
+<para>
+There are a number of macros in Xserver/include/dix.h which
+are useful to the extension writer.  Ones of particular interest
+are: REQUEST, REQUEST_SIZE_MATCH, REQUEST_AT_LEAST_SIZE,
+REQUEST_FIXED_SIZE, LEGAL_NEW_RESOURCE, LOOKUP_DRAWABLE, VERIFY_GC, and
+VALIDATE_DRAWABLE_AND_GC. Useful byte swapping macros can be found
+in Xserver/include/misc.h: lswapl, lswaps, LengthRestB, LengthRestS,
+LengthRestL, SwapRestS, SwapRestL, swapl, swaps, cpswapl, and cpswaps.</para>
+</section>
+</section>
+
+<section>
+  <title>OS Layer</title>
+<para>
+This part of the source consists of a few routines that you have to rewrite
+for each operating system.
+These OS functions maintain the client connections and schedule work
+to be done for clients.
+They also provide an interface to font files,
+font name to file name translation, and
+low level memory management.
+<blockquote>
+<programlisting>void OsInit()</programlisting>
+</blockquote>
+OsInit initializes your OS code, performing whatever tasks need to be done.
+Frequently there is not much to be done.
+The sample server implementation is in Xserver/os/osinit.c.
+</para>
+<section>
+  <title>Scheduling and Request Delivery</title>
+<para>
+The main dispatch loop in DIX creates the illusion of multitasking between
+different windows, while the server is itself but a single process.
+The dispatch loop breaks up the work for each client into small digestible parts.
+Some parts are requests from a client, such as individual graphic commands.
+Some parts are events delivered to the client, such as keystrokes from the user.
+The processing of events and requests for different
+clients can be interleaved with one another so true multitasking
+is not needed in the server.
+</para>
+<para>
+You must supply some of the pieces for proper scheduling between clients.
+<blockquote>
+<programlisting>
+	int WaitForSomething(pClientReady)
+		int *pClientReady;
+</programlisting>
+</blockquote>
+</para>
+<para>
+WaitForSomething is the scheduler procedure you must write that will
+suspend your server process until something needs to be done.
+This call should
+make the server suspend until one or more of the following occurs:
+<itemizedlist>
+<listitem><para>There is an input event from the user or hardware (see SetInputCheck())</para></listitem>
+<listitem><para>There are requests waiting from known clients, in which case you should return a count of clients stored in pClientReady</para></listitem>
+<listitem><para>A new client tries to connect, in which case you should create the client and then continue waiting</para></listitem>
+</itemizedlist>
+</para>
+<para>
+Before WaitForSomething() computes the masks to pass to select, poll or
+similar operating system interface, it needs to
+see if there is anything to do on the work queue; if so, it must call a DIX
+routine called ProcessWorkQueue.
+<blockquote>
+<programlisting>
+	extern WorkQueuePtr	workQueue;
+
+	if (workQueue)
+		ProcessWorkQueue ();
+</programlisting>
+</blockquote>
+</para>
+<para>
+If WaitForSomething() decides it is about to do something that might block
+(in the sample server,  before it calls select() or poll) it must call a DIX
+routine called BlockHandler().
+<blockquote>
+<programlisting>
+	void BlockHandler(pTimeout, pReadmask)
+		pointer pTimeout;
+		pointer pReadmask;
+</programlisting>
+</blockquote>
+The types of the arguments are for agreement between the OS and DDX
+implementations,  but the pTimeout is a pointer to the information
+determining how long the block is allowed to last,  and the
+pReadmask is a pointer to the information describing the descriptors
+that will be waited on.
+</para>
+<para>
+In the sample server,  pTimeout is a struct timeval **,  and pReadmask is
+the address of the select() mask for reading.
+</para>
+<para>
+The DIX BlockHandler() iterates through the Screens,  for each one calling
+its BlockHandler.  A BlockHandler is declared thus:
+<blockquote>
+<programlisting>
+	void xxxBlockHandler(nscreen, pbdata, pptv, pReadmask)
+		int nscreen;
+		pointer pbdata;
+		struct timeval ** pptv;
+		pointer pReadmask;
+</programlisting>
+</blockquote>
+The arguments are the index of the Screen,  the blockData field
+of the Screen,  and the arguments to the DIX BlockHandler().
+</para>
+<para>
+Immediately after WaitForSomething returns from the
+block,  even if it didn't actually block,  it must call the DIX routine
+WakeupHandler().
+<blockquote>
+<programlisting>
+	void WakeupHandler(result, pReadmask)
+		int result;
+		pointer pReadmask;
+</programlisting>
+</blockquote>
+Once again,  the types are not specified by DIX.  The result is the
+success indicator for the thing that (may have) blocked,
+and the pReadmask is a mask of the descriptors that came active.
+In the sample server,  result is the result from select() (or equivalent
+operating system function),  and pReadmask is
+the address of the select() mask for reading.
+</para>
+<para>
+The DIX WakeupHandler() calls each Screen's
+WakeupHandler.  A WakeupHandler is declared thus:
+<blockquote>
+<programlisting>
+	void xxxWakeupHandler(nscreen, pbdata, err, pReadmask)
+		int nscreen;
+		pointer pbdata;
+		unsigned long result;
+		pointer pReadmask;
+</programlisting>
+</blockquote>
+The arguments are the index of the Screen,  the blockData field
+of the Screen,  and the arguments to the DIX WakeupHandler().
+</para>
+<para>
+In addition to the per-screen BlockHandlers, any module may register
+block and wakeup handlers (only together) using:
+<blockquote>
+<programlisting>
+	Bool RegisterBlockAndWakeupHandlers (blockHandler, wakeupHandler, blockData)
+		BlockHandlerProcPtr    blockHandler;
+		WakeupHandlerProcPtr   wakeupHandler;
+		pointer blockData;
+</programlisting>
+</blockquote>
+A FALSE return code indicates that the registration failed for lack of
+memory.  To remove a registered Block handler at other than server reset time
+(when they are all removed automatically), use:
+<blockquote>
+<programlisting>
+	RemoveBlockAndWakeupHandlers (blockHandler, wakeupHandler, blockData)
+		BlockHandlerProcPtr   blockHandler;
+		WakeupHandlerProcPtr  wakeupHandler;
+		pointer blockData;
+</programlisting>
+</blockquote>
+All three arguments must match the values passed to
+RegisterBlockAndWakeupHandlers.
+</para>
+<para>
+These registered block handlers are called after the per-screen handlers:
+<blockquote>
+<programlisting>
+	void (*BlockHandler) (blockData, pptv, pReadmask)
+		pointer	blockData;
+		OSTimePtr pptv;
+		pointer	pReadmask;
+</programlisting>
+</blockquote>
+</para>
+<para>
+Sometimes block handlers need to adjust the time in a OSTimePtr structure,
+which on UNIX family systems is generally represented by a struct timeval
+consisting of seconds and microseconds in 32 bit values.
+As a convenience to reduce error prone struct timeval computations which
+require modulus arithmetic and correct overflow behavior in the face of
+millisecond wrapping throrugh 32 bits,
+<blockquote><programlisting>
+
+	void AdjustWaitForDelay(pointer /*waitTime*, unsigned long /* newdelay */)
+
+</programlisting></blockquote>
+has been provided.
+</para>
+<para>
+Any wakeup handlers registered with RegisterBlockAndWakeupHandlers will
+be called before the Screen handlers:
+<blockquote><programlisting>
+
+	void (*WakeupHandler) (blockData, err, pReadmask)
+		pointer	blockData;
+		int err;
+		pointer pReadmask;
+</programlisting></blockquote>
+</para>
+<para>
+The WaitForSomething on the sample server also has a built
+in screen saver that darkens the screen if no input happens for a period of time.
+The sample server implementation is in Xserver/os/WaitFor.c.
+</para>
+<para>
+Note that WaitForSomething() may be called when you already have several
+outstanding things (events, requests, or new clients) queued up.
+For instance, your server may have just done a large graphics request,
+and it may have been a long time since WaitForSomething() was last called.
+If many clients have lots of requests queued up, DIX will only service
+some of them for a given client
+before going on to the next client (see isItTimeToYield, below).
+Therefore, WaitForSomething() will have to report that these same clients
+still have requests queued up the next time around.
+</para>
+<para>
+An implementation should return information on as
+many outstanding things as it can.
+For instance, if your implementation always checks for client data first and does not
+report any input events until there is no client data left,
+your mouse and keyboard might get locked out by an application that constantly
+barrages the server with graphics drawing requests.
+Therefore, as a general rule, input devices should always have priority over graphics
+devices.
+</para>
+<para>
+A list of indexes (client->index) for clients with data ready to be read or
+processed should be returned in pClientReady, and the count of indexes
+returned as the result value of the call.
+These are not clients that have full requests ready, but any clients who have
+any data ready to be read or processed.
+The DIX dispatcher
+will process requests from each client in turn by calling
+ReadRequestFromClient(), below.
+</para>
+<para>
+WaitForSomething() must create new clients as they are requested (by
+whatever mechanism at the transport level).  A new client is created
+by calling the DIX routine:
+<blockquote><programlisting>
+
+	ClientPtr NextAvailableClient(ospriv)
+		pointer ospriv;
+</programlisting></blockquote>
+This routine returns NULL if a new client cannot be allocated (e.g. maximum
+number of clients reached).  The ospriv argument will be stored into the OS
+private field (pClient->osPrivate), to store OS private information about the
+client.  In the sample server, the osPrivate field contains the
+number of the socket for this client. See also "New Client Connections."
+NextAvailableClient() will call InsertFakeRequest(), so you must be
+prepared for this.
+</para>
+<para>
+If there are outstanding input events,
+you should make sure that the two SetInputCheck() locations are unequal.
+The DIX dispatcher will call your implementation of ProcessInputEvents()
+until the SetInputCheck() locations are equal.
+</para>
+<para>
+The sample server contains an implementation of WaitForSomething().
+The
+following two routines indicate to WaitForSomething() what devices should
+be waited for.   fd is an OS dependent type; in the sample server
+it is an open file descriptor.
+<blockquote><programlisting>
+
+	int AddEnabledDevice(fd)
+		int fd;
+
+	int RemoveEnabledDevice(fd)
+		int fd;
+</programlisting></blockquote>
+These two routines are
+usually called by DDX from the initialize cases of the
+Input Procedures that are stored in the DeviceRec (the
+routine passed to AddInputDevice()).
+The sample server implementation of AddEnabledDevice
+and RemoveEnabledDevice are in Xserver/os/connection.c.
+</para>
+<section>
+  <title>Timer Facilities</title>
+<para>
+Similarly, the X server or an extension may need to wait for some timeout.
+Early X releases implemented this functionality using block and wakeup handlers,
+but this has been rewritten to use a general timer facilty, and the
+internal screen saver facilties reimplemented to use Timers.
+These functions are TimerInit, TimerForce, TimerSet, TimerCheck, TimerCancel,
+and TimerFree, as defined in Xserver/include/os.h. A callback function will be called
+when the timer fires, along with the current time, and a user provided argument.
+<blockquote><programlisting>
+	typedef	struct _OsTimerRec *OsTimerPtr;
+
+	typedef CARD32 (*OsTimerCallback)(
+		OsTimerPtr /* timer */,
+		CARD32 /* time */,
+		pointer /* arg */);
+
+	 OsTimerPtr TimerSet( OsTimerPtr /* timer */,
+		int /* flags */,
+		CARD32 /* millis */,
+		OsTimerCallback /* func */,
+		pointer /* arg */);
+
+</programlisting></blockquote>
+</para>
+<para>
+TimerSet returns a pointer to a timer structure and sets a timer to the specified time
+with the specified argument.  The flags can be TimerAbsolute and TimerForceOld.
+The TimerSetOld flag controls whether if the timer is reset and the timer is pending, the
+whether the callback function will get called.
+The TimerAbsolute flag sets the callback time to an absolute time in the future rather
+than a time relative to when TimerSet is called.
+TimerFree should be called to free the memory allocated
+for the timer entry.
+<blockquote><programlisting>
+	void TimerInit(void)
+
+	Bool TimerForce(OsTimerPtr /* pTimer */)
+
+	void TimerCheck(void);
+
+	void TimerCancel(OsTimerPtr /* pTimer */)
+
+	void TimerFree(OSTimerPtr /* pTimer */)
+</programlisting></blockquote>
+</para>
+<para>
+TimerInit frees any exisiting timer entries. TimerForce forces a call to the timer's
+callback function and returns true if the timer entry existed, else it returns false and
+does not call the callback function. TimerCancel will cancel the specified timer.
+TimerFree calls TimerCancel and frees the specified timer.
+Calling TimerCheck will force the server to see if any timer callbacks should be called.
+</para>
+</section>
+</section>
+<section>
+  <title>New Client Connections</title>
+<para>
+The process whereby a new client-server connection starts up is
+very dependent upon what your byte stream mechanism.
+This section describes byte stream initiation using examples from the TCP/IP
+implementation on the sample server.
+</para>
+<para>
+The first thing that happens is a client initiates a connection with the server.
+How a client knows to do this depends upon your network facilities and the
+Xlib implementation.
+In a typical scenario, a user named Fred
+on his X workstation is logged onto a Cray
+supercomputer running a command shell in an X window.  Fred can type shell
+commands and have the Cray respond as though the X server were a dumb terminal.
+Fred types in a command to run an X client application that was linked with Xlib.
+Xlib looks at the shell environment variable DISPLAY, which has the
+value "fredsbittube:0.0."
+The host name of Fred's workstation is "fredsbittube," and the 0s are
+for multiple screens and multiple X server processes.
+(Precisely what
+happens on your system depends upon how X and Xlib are implemented.)
+</para>
+<para>
+The client application calls a TCP routine on the
+Cray to open a TCP connection for X
+to communicate with the network node "fredsbittube."
+The TCP software on the Cray does this by looking up the TCP
+address of "fredsbittube" and sending an open request to TCP port 6000
+on fredsbittube.
+</para>
+<para>
+All X servers on TCP listen for new clients on port 6000 by default;
+this is known as a "well-known port" in IP terminology.
+</para>
+<para>
+The server receives this request from its port 6000
+and checks where it came from to see if it is on the server's list
+of "trustworthy" hosts to talk to.
+Then, it opens another port for communications with the client.
+This is the byte stream that all X communications will go over.
+</para>
+<para>
+Actually, it is a bit more complicated than that.
+Each X server process running on the host machine is called a "display."
+Each display can have more than one screen that it manages.
+"corporatehydra:3.2" represents screen 2 on display 3 on
+the multi-screened network node corporatehydra.
+The open request would be sent on well-known port number 6003.
+</para>
+<para>
+Once the byte stream is set up, what goes on does not depend very much
+upon whether or not it is TCP.
+The client sends an xConnClientPrefix struct (see Xproto.h) that has the
+version numbers for the version of Xlib it is running, some byte-ordering information,
+and two character strings used for authorization.
+If the server does not like the authorization strings
+or the version numbers do not match within the rules,
+or if anything else is wrong, it sends a failure
+response with a reason string.
+</para>
+<para>
+If the information never comes, or comes much too slowly, the connection
+should be broken off.  You must implement the connection timeout.  The
+sample server implements this by keeping a timestamp for each still-connecting
+client and, each time just before it attempts to accept new connections, it
+closes any connection that are too old.
+The connection timeout can be set from the command line.
+</para>
+<para>
+You must implement whatever authorization schemes you want to support.
+The sample server on the distribution tape supports a simple authorization
+scheme.  The only interface seen by DIX is:
+<blockquote><programlisting>
+
+	char *
+	ClientAuthorized(client, proto_n, auth_proto, string_n, auth_string)
+	    ClientPtr client;
+	    unsigned int proto_n;
+	    char *auth_proto;
+	    unsigned int string_n;
+	    char *auth_string;
+</programlisting></blockquote>
+DIX will only call this once per client, once it has read the full initial
+connection data from the client.  If the connection should be
+accepted ClientAuthorized() should return NULL, and otherwise should
+return an error message string.
+</para>
+<para>
+Accepting new connections happens internally to WaitForSomething().
+WaitForSomething() must call the DIX routine NextAvailableClient()
+to create a client object.
+Processing of the initial connection data will be handled by DIX.
+Your OS layer must be able to map from a client
+to whatever information your OS code needs to communicate
+on the given byte stream to the client.
+DIX uses this ClientPtr to refer to
+the client from now on.   The sample server uses the osPrivate field in
+the ClientPtr to store the file descriptor for the socket, the
+input and output buffers, and authorization information.
+</para>
+<para>
+To initialize the methods you choose to allow clients to connect to
+your server, main() calls the routine
+<blockquote><programlisting>
+
+	void CreateWellKnownSockets()
+</programlisting></blockquote>
+This routine is called only once, and not called when the server
+is reset.  To recreate any sockets during server resets, the following
+routine is called from the main loop:
+<blockquote><programlisting>
+
+	void ResetWellKnownSockets()
+</programlisting></blockquote>
+Sample implementations of both of these routines are found in
+Xserver/os/connection.c.
+</para>
+<para>
+For more details, see the section called "Connection Setup" in the X protocol specification.
+</para>
+</section>
+<section>
+  <title>Reading Data from Clients</title>
+<para>
+Requests from the client are read in as a byte stream by the OS layer.
+They may be in the form of several blocks of bytes delivered in sequence; requests may
+be broken up over block boundaries or there may be many requests per block.
+Each request carries with it length information.
+It is the responsibility of the following routine to break it up into request blocks.
+<blockquote><programlisting>
+
+	int ReadRequestFromClient(who)
+		ClientPtr who;
+</programlisting></blockquote>
+</para>
+<para>
+You must write
+the routine ReadRequestFromClient() to get one request from the byte stream
+belonging to client "who."
+You must swap the third and fourth bytes (the second 16-bit word) according to the
+byte-swap rules of
+the protocol to determine the length of the
+request.
+This length is measured in 32-bit words, not in bytes.  Therefore, the
+theoretical maximum request is 256K.
+(However, the maximum length allowed is dependent upon the server's input
+buffer.  This size is sent to the client upon connection.  The maximum
+size is the constant MAX_REQUEST_SIZE in Xserver/include/os.h)
+The rest of the request you return is
+assumed NOT to be correctly swapped for internal
+use, because that is the responsibility of DIX.
+</para>
+<para>
+The 'who' argument is the ClientPtr returned from WaitForSomething.
+The return value indicating status should be set to the (positive) byte count if the read is successful,
+0 if the read was blocked, or a negative error code if an error happened.
+</para>
+<para>
+You must then store a pointer to
+the bytes of the request in the client request buffer field;
+who->requestBuffer.  This can simply be a pointer into your buffer;
+DIX may modify it in place but will not otherwise cause damage.
+Of course, the request must be contiguous; you must
+shuffle it around in your buffers if not.
+</para>
+<para>
+The sample server implementation is in Xserver/os/io.c.
+</para>
+<section><title>Inserting Data for Clients</title>
+<para>
+DIX can insert data into the client stream, and can cause a "replay" of
+the current request.
+<blockquote><programlisting>
+
+	Bool InsertFakeRequest(client, data, count)
+	    ClientPtr client;
+	    char *data;
+	    int count;
+
+	int ResetCurrentRequest(client)
+	    ClientPtr client;
+</programlisting></blockquote>
+</para>
+<para>
+InsertFakeRequest() must insert the specified number of bytes of data
+into the head of the input buffer for the client.  This may be a
+complete request, or it might be a partial request.  For example,
+NextAvailableCient() will insert a partial request in order to read
+the initial connection data sent by the client.  The routine returns FALSE
+if memory could not be allocated.  ResetCurrentRequest()
+should "back up" the input buffer so that the currently executing request
+will be reexecuted.  DIX may have altered some values (e.g. the overall
+request length), so you must recheck to see if you still have a complete
+request.  ResetCurrentRequest() should always cause a yield (isItTimeToYield).
+</para>
+</section>
+</section>
+
+<section>
+  <title>Sending Events, Errors And Replies To Clients</title>
+<para>
+<blockquote><programlisting>
+
+	int WriteToClient(who, n, buf)
+		ClientPtr who;
+		int n;
+		char *buf;
+</programlisting></blockquote>
+WriteToClient should write n bytes starting at buf to the
+ClientPtr "who".
+It returns the number of bytes written, but for simplicity,
+the number returned must be either the same value as the number
+requested, or -1, signaling an error.
+The sample server implementation is in Xserver/os/io.c.
+</para>
+<para>
+<blockquote><programlisting>
+	void SendErrorToClient(client, majorCode, minorCode, resId, errorCode)
+	    ClientPtr client;
+	    unsigned int majorCode;
+	    unsigned int minorCode;
+	    XID resId;
+	    int errorCode;
+</programlisting></blockquote>
+SendErrorToClient can be used to send errors back to clients,
+although in most cases your request function should simply return
+the error code, having set client->errorValue to the appropriate
+error value to return to the client, and DIX will call this
+function with the correct opcodes for you.
+</para>
+<para>
+<blockquote><programlisting>
+
+	void FlushAllOutput()
+
+	void FlushIfCriticalOutputPending()
+
+	void SetCriticalOutputPending()
+</programlisting></blockquote>
+These three routines may be implemented to support buffered or delayed
+writes to clients, but at the very least, the stubs must exist.
+FlushAllOutput() unconditionally flushes all output to clients;
+FlushIfCriticalOutputPending() flushes output only if
+SetCriticalOutputPending() has be called since the last time output
+was flushed.
+The sample server implementation is in Xserver/os/io.c and
+actually ignores requests to flush output on a per-client basis
+if it knows that there
+are requests in that client's input queue.
+</para>
+</section>
+<section>
+  <title>Font Support</title>
+<para>
+In the sample server, fonts are encoded in disk files or fetched from the
+font server.
+For disk fonts, there is one file per font, with a file name like
+"fixed.pcf".  Font server fonts are read over the network using the
+X Font Server Protocol.  The disk directories containing disk fonts and
+the names of the font servers are listed together in the current "font path."
+</para>
+<para>
+In principle, you can put all your fonts in ROM or in RAM in your server.
+You can put them all in one library file on disk.
+You could generate them on the fly from stroke descriptions.  By placing the
+appropriate code in the Font Library, you will automatically export fonts in
+that format both through the X server and the Font server.
+</para>
+<para>
+With the incorporation of font-server based fonts and the Speedo donation
+from Bitstream, the font interfaces have been moved into a separate
+library, now called the Font Library (../fonts/lib).  These routines are
+shared between the X server and the Font server, so instead of this document
+specifying what you must implement, simply refer to the font
+library interface specification for the details.  All of the interface code to the Font
+library is contained in dix/dixfonts.c
+</para>
+</section>
+<section>
+  <title>Memory Management</title>
+<para>
+Memory management is based on functions in the C runtime library.
+Xalloc(), Xrealloc(), and Xfree() work just like malloc(), realloc(),
+and free(), except that you can pass a null pointer to Xrealloc() to
+have it allocate anew or pass a null pointer to Xfree() and nothing
+will happen.  The versions in the sample server also do some checking
+that is useful for debugging.  Consult a C runtime library reference
+manual for more details.
+</para>
+<para>
+The macros ALLOCATE_LOCAL and DEALLOCATE_LOCAL are provided in
+Xserver/include/os.h.  These are useful if your compiler supports
+alloca() (or some method of allocating memory from the stack); and are
+defined appropriately on systems which support it.
+</para>
+<para>
+Treat memory allocation carefully in your implementation.  Memory
+leaks can be very hard to find and are frustrating to a user.  An X
+server could be running for days or weeks without being reset, just
+like a regular terminal.  If you leak a few dozen k per day, that will
+add up and will cause problems for users that leave their workstations
+on.
+</para>
+</section>
+<section>
+  <title>Client Scheduling</title>
+<para>
+The X server
+has the ability to schedule clients much like an operating system would,
+suspending and restarting them without regard for the state of their input
+buffers.  This functionality allows the X server to suspend one client and
+continue processing requests from other clients while waiting for a
+long-term network activity (like loading a font) before continuing with the
+first client.
+<blockquote><programlisting>
+	Bool isItTimeToYield;
+</programlisting></blockquote>
+isItTimeToYield is a global variable you can set
+if you want to tell
+DIX to end the client's "time slice" and start paying attention to the next client.
+After the current request is finished, DIX will move to the next client.
+</para>
+<para>
+In the sample
+server, ReadRequestFromClient() sets isItTimeToYield after
+10 requests packets in a row are read from the same client.
+</para>
+<para>
+This scheduling algorithm can have a serious effect upon performance when two
+clients are drawing into their windows simultaneously.
+If it allows one client to run until its request
+queue is empty by ignoring isItTimeToYield, the client's queue may
+in fact never empty and other clients will be blocked out.
+On the other hand, if it switchs between different clients too quickly,
+performance may suffer due to too much switching between contexts.
+For example, if a graphics processor needs to be set up with drawing modes
+before drawing, and two different clients are drawing with
+different modes into two different windows, you may
+switch your graphics processor modes so often that performance is impacted.
+</para>
+<para>
+See the Strategies document for
+heuristics on setting isItTimeToYield.
+</para>
+<para>
+The following functions provide the ability to suspend request
+processing on a particular client, resuming it at some later time:
+<blockquote><programlisting>
+
+	int IgnoreClient (who)
+		ClientPtr who;
+
+	int AttendClient (who)
+		ClientPtr who;
+</programlisting></blockquote>
+Ignore client is responsible for pretending that the given client doesn't
+exist.  WaitForSomething should not return this client as ready for reading
+and should not return if only this client is ready.  AttendClient undoes
+whatever IgnoreClient did, setting it up for input again.
+</para>
+<para>
+Three functions support "process control" for X clients:
+<blockquote><programlisting>
+
+	Bool ClientSleep (client, function, closure)
+		ClientPtr	client;
+		Bool		(*function)();
+		pointer		closure;
+
+</programlisting></blockquote>
+This suspends the current client (the calling routine is responsible for
+making its way back to Dispatch()).  No more X requests will be processed
+for this client until ClientWakeup is called.
+<blockquote><programlisting>
+
+	Bool ClientSignal (client)
+		ClientPtr	client;
+
+</programlisting></blockquote>
+This function causes a call to the (*function) parameter passed to
+ClientSleep to be queued on the work queue.  This does not automatically
+"wakeup" the client, but the function called is free to do so by calling:
+<blockquote><programlisting>
+
+	ClientWakeup (client)
+		ClientPtr	client;
+
+</programlisting></blockquote>
+This re-enables X request processing for the specified client.
+</para>
+</section>
+<section>
+  <title>Other OS Functions</title>
+<para>
+<blockquote><programlisting>
+	void
+	ErrorF(char *f, ...)
+
+	void
+	FatalError(char *f, ...)
+
+	void
+	Error(str)
+	    char *str;
+</programlisting></blockquote>
+You should write these three routines to provide for diagnostic output
+from the dix and ddx layers, although implementing them to produce no
+output will not affect the correctness of your server.  ErrorF() and
+FatalError() take a printf() type of format specification in the first
+argument and an implementation-dependent number of arguments following
+that.  Normally, the formats passed to ErrorF() and FatalError()
+should be terminated with a newline.  Error() provides an os interface
+for printing out the string passed as an argument followed by a
+meaningful explanation of the last system error.  Normally the string
+does not contain a newline, and it is only called by the ddx layer.
+In the sample implementation, Error() uses the perror() function.
+</para>
+<para>
+After printing the message arguments, FatalError() must be implemented
+such that the server will call AbortDDX() to give the ddx layer
+a chance to reset the hardware, and then
+terminate the server; it must not return.
+</para>
+<para>
+The sample server implementation for these routines
+is in Xserver/os/util.c.
+</para>
+</section>
+<section>
+  <title>Idiom Support</title>
+<para>
+The DBE specification introduces the notion of idioms, which are
+groups of X requests which can be executed more efficiently when taken
+as a whole compared to being performed individually and sequentially.
+This following server internal support to allows DBE
+implementations, as well as other parts of the server,
+to do idiom processing.
+</para>
+<para>
+<blockquote><programlisting>
+
+	xReqPtr PeekNextRequest(xReqPtr req, ClientPtr client, Bool readmore)
+</programlisting></blockquote>
+If req is NULL, the return value will be a pointer to the start of the
+complete request that follows the one currently being executed for the
+client.  If req is not NULL, the function assumes that req is a
+pointer to a request in the client's request buffer, and the return
+value will be a pointer to the the start of the complete request that
+follows req.  If the complete request is not available, the function
+returns NULL; pointers to partial requests will never be returned.  If
+(and only if) readmore is TRUE, PeekNextRequest should try to read an
+additional request from the client if one is not already available in
+the client's request buffer.  If PeekNextRequest reads more data into
+the request buffer, it should not move or change the existing data.
+</para>
+<para>
+<blockquote><programlisting>
+
+	void SkipRequests(xReqPtr req, ClientPtr client, int numskipped)
+</programlisting></blockquote>
+The requests for the client up to and including the one specified by
+req will be skipped.  numskipped must be the number of requests being
+skipped.  Normal request processing will resume with the request that
+follows req.  The caller must not have modified the contents of the
+request buffer in any way (e.g., by doing byte swapping in place).
+</para>
+<para>
+Additionally, two macros in os.h operate on the xReq
+pointer returned by PeekNextRequest:
+<blockquote><programlisting>
+
+	int ReqLen(xReqPtr req, ClientPtr client)
+</programlisting></blockquote>
+The value of ReqLen is the request length in bytes of the given xReq.
+<blockquote><programlisting>
+
+	otherReqTypePtr CastxReq(xReq *req, otherReqTypePtr)
+</programlisting></blockquote>
+The value of CastxReq is the conversion of the given request pointer
+to an otherReqTypePtr (which should be a pointer to a protocol
+structure type).  Only those fields which come after the length field
+of otherReqType may be accessed via the returned pointer.
+</para>
+<para>
+Thus the first two fields of a request, reqType and data, can be
+accessed directly using the xReq * returned by PeekNextRequest.  The
+next field, the length, can be accessed with ReqLen.  Fields beyond
+that can be accessed with CastxReq.  This complexity was necessary
+because of the reencoding of core protocol that can happen due to the
+BigRequests extension.
+</para>
+</section>
+</section>
+
+<section>
+  <title>DDX Layer</title>
+<para>
+This section describes the
+interface between DIX and DDX.
+While there may be an OS-dependent driver interface between DDX
+and the physical device, that interface is left to the DDX
+implementor and is not specified here.
+</para>
+<para>
+The DDX layer does most of its work through procedures that are
+pointed to by different structs.
+As previously described, the behavior of these resources is largely determined by
+these procedure pointers.
+Most of these routines are for graphic display on the screen or support functions thereof.
+The rest are for user input from input devices.
+</para>
+<section>
+  <title>Input</title>
+<para>
+In this document "input" refers to input from the user,
+such as mouse, keyboard, and
+bar code readers.
+X input devices are of several types: keyboard, pointing device, and
+many others.  The core server has support for extension devices as
+described by the X Input Extension document; the interfaces used by
+that extension are described elsewhere.  The core devices are actually
+implemented as two collections of devices, the mouse is a ButtonDevice,
+a ValuatorDevice and a PtrFeedbackDevice while the keyboard is a KeyDevice,
+a FocusDevice and a KbdFeedbackDevice.  Each part implements a portion of
+the functionality of the device.  This abstraction is hidden from view for
+core devices by DIX.
+</para>
+<para>
+You, the DDX programmer, are
+responsible for some of the routines in this section.
+Others are DIX routines that you should call to do the things you need to do in these DDX routines.
+Pay attention to which is which.
+</para>
+<section>
+  <title>Input Device Data Structures</title>
+<para>
+DIX keeps a global directory of devices in a central data structure
+called InputInfo.
+For each device there is a device structure called a DeviceRec.
+DIX can locate any DeviceRec through InputInfo.
+In addition, it has a special pointer to identify the main pointing device
+and a special pointer to identify the main keyboard.
+</para>
+<para>
+The DeviceRec (Xserver/include/input.h) is a device-independent
+structure that contains the state of an input device.
+A DevicePtr is simply a pointer to a DeviceRec.
+</para>
+<para>
+An xEvent describes an event the server reports to a client.
+Defined in Xproto.h, it is a huge struct of union of structs that have fields for
+all kinds of events.
+All of the variants overlap, so that the struct is actually very small in memory.
+</para>
+</section>
+<section>
+  <title>Processing Events</title>
+<para>
+The main DDX input interface is the following routine:
+<blockquote><programlisting>
+
+	void ProcessInputEvents()
+</programlisting></blockquote>
+You must write this routine to deliver input events from the user.
+DIX calls it when input is pending (see next section), and possibly
+even when it is not.
+You should write it to get events from each device and deliver
+the events to DIX.
+To deliver the events to DIX, DDX should call the following
+routine:
+<blockquote><programlisting>
+
+	void DevicePtr->processInputProc(pEvent, device, count)
+		    xEventPtr events;
+		    DeviceIntPtr device;
+		    int count;
+</programlisting></blockquote>
+This is the "input proc" for the device, a DIX procedure.
+DIX will fill in this procedure pointer to one of its own routines by
+the time ProcessInputEvents() is called the first time.
+Call this input proc routine as many times as needed to
+deliver as many events as should be delivered.
+DIX will buffer them up and send them out as needed.  Count is set
+to the number of event records which make up one atomic device event and
+is always 1 for the core devices (see the X Input Extension for descriptions
+of devices which may use count &#x3E; 1).
+</para>
+<para>
+For example, your ProcessInputEvents() routine might check the mouse and the
+keyboard.
+If the keyboard had several keystrokes queued up, it could just call
+the keyboard's processInputProc as many times as needed to flush its internal queue.
+</para>
+<para>
+event is an xEvent struct you pass to the input proc.
+When the input proc returns, it is finished with the event rec, and you can fill
+in new values and call the input proc again with it.
+</para>
+<para>
+You should deliver the events in the same order that they were generated.
+</para>
+<para>
+For keyboard and pointing devices the xEvent variant should be keyButtonPointer.
+Fill in the following fields in the xEvent record:
+<itemizedlist>
+
+<listitem><para>type - is one of the following: KeyPress, KeyRelease, ButtonPress,
+					ButtonRelease, or MotionNotify</para></listitem>
+<listitem><para>detail - for KeyPress or KeyRelease fields, this should be the
+					key number (not the ASCII code); otherwise unused</para></listitem>
+<listitem><para>time - is the time that the event happened (32-bits, in milliseconds, arbitrary origin)</para></listitem>
+<listitem><para>rootX - is the x coordinate of cursor</para></listitem>
+<listitem><para>rootY - is the y coordinate of cursor</para></listitem>
+
+</itemizedlist>
+The rest of the fields are filled in by DIX.
+</para>
+<para>
+The time stamp is maintained by your code in the DDX layer, and it is your responsibility to
+stamp all events correctly.
+</para>
+<para>
+The x and y coordinates of the pointing device and the time must be filled in for all event types
+including keyboard events.
+</para>
+<para>
+The pointing device must report all button press and release events.
+In addition, it should report a MotionNotify event every time it gets called
+if the pointing device has moved since the last notify.
+Intermediate pointing device moves are stored in a special GetMotionEvents buffer,
+because most client programs are not interested in them.
+</para>
+<para>
+There are quite a collection of sample implementations of this routine,
+one for each supported device.
+</para>
+</section>
+<section>
+<title>Telling DIX When Input is Pending</title>
+<para>
+In the server's dispatch loop, DIX checks to see
+if there is any device input pending whenever WaitForSomething() returns.
+If the check says that input is pending, DIX calls the
+DDX routine ProcessInputEvents().
+</para>
+<para>
+This check for pending input must be very quick; a procedure call
+is too slow.
+The code that does the check is a hardwired IF
+statement in DIX code that simply compares the values
+pointed to by two pointers.
+If the values are different, then it assumes that input is pending and
+ProcessInputEvents() is called by DIX.
+</para>
+<para>
+You must pass pointers to DIX to tell it what values to compare.
+The following procedure
+is used to set these pointers:
+<blockquote><programlisting>
+
+	void SetInputCheck(p1, p2)
+		long *p1, *p2;
+</programlisting></blockquote>
+You should call it sometime during initialization to indicate to DIX the
+correct locations to check.
+You should
+pay special attention to the size of what they actually point to,
+because the locations are assumed to be longs.
+</para>
+<para>
+These two pointers are initialized by DIX
+to point to arbitrary values that
+are different.
+In other words, if you forget to call this routine during initialization,
+the worst thing that will happen is that
+ProcessInputEvents will be called when
+there are no events to process.
+</para>
+<para>
+p1 and p2 might
+point at the head and tail of some shared
+memory queue.
+Another use would be to have one point at a constant 0, with the
+other pointing at some mask containing 1s
+for each input device that has
+something pending.
+</para>
+<para>
+The DDX layer of the sample server calls SetInputCheck()
+once when the
+server's private internal queue is initialized.
+It passes pointers to the queue's head and tail.  See Xserver/mi/mieq.c.
+</para>
+<para>
+<blockquote><programlisting>
+	int TimeSinceLastInputEvent()
+</programlisting></blockquote>
+DDX must time stamp all hardware input
+events.  But DIX sometimes needs to know the
+time and the OS layer needs to know the time since the last hardware
+input event in
+order for the screen saver to work.   TimeSinceLastInputEvent() returns
+the this time in milliseconds.
+</para>
+</section>
+<section>
+  <title>Controlling Input Devices</title>
+<para>
+You must write four routines to do various device-specific
+things with the keyboard and pointing device.
+They can have any name you wish because
+you pass the procedure pointers to DIX routines.
+</para>
+<para>
+<blockquote><programlisting>
+
+	int pInternalDevice->valuator->GetMotionProc(pdevice, coords, start, stop, pScreen)
+		DeviceIntPtr pdevice;
+		xTimecoord * coords;
+		unsigned long start;
+		unsigned long stop;
+		ScreenPtr pScreen;
+</programlisting></blockquote>
+You write this DDX routine to fill in coords with all the motion
+events that have times (32-bit count of milliseconds) between time
+start and time stop.  It should return the number of motion events
+returned.  If there is no motion events support, this routine should
+do nothing and return zero.  The maximum number of coords to return is
+set in InitPointerDeviceStruct(), below.
+</para>
+<para>
+When the user drags the pointing device, the cursor position
+theoretically sweeps through an infinite number of points.  Normally,
+a client that is concerned with points other than the starting and
+ending points will receive a pointer-move event only as often as the
+server generates them. (Move events do not queue up; each new one
+replaces the last in the queue.)  A server, if desired, can implement
+a scheme to save these intermediate events in a motion buffer.  A
+client application, like a paint program, may then request that these
+events be delivered to it through the GetMotionProc routine.
+</para>
+<para>
+<blockquote><programlisting>
+
+	void pInternalDevice->bell->BellProc(percent, pDevice, ctrl, unknown)
+		int percent;
+		DeviceIntPtr pDevice;
+		pointer ctrl;
+		int class;
+</programlisting></blockquote>
+You need to write this routine to ring the bell on the keyboard.
+loud is a number from 0 to 100, with 100 being the loudest.
+Class is either BellFeedbackClass or KbdFeedbackClass (from XI.h).
+</para>
+<para>
+<blockquote><programlisting>
+
+	void pInternalDevice->somedevice->CtrlProc(device, ctrl)
+		DevicePtr device;
+		SomethingCtrl *ctrl;
+
+</programlisting></blockquote>
+You write two versions of this procedure, one for the keyboard and one for the pointing device.
+DIX calls it to inform DDX when a client has requested changes in the current
+settings for the particular device.
+For a keyboard, this might be the repeat threshold and rate.
+For a pointing device, this might be a scaling factor (coarse or fine) for position reporting.
+See input.h for the ctrl structures.
+</para>
+</section>
+<section>
+  <title>Input Initialization</title>
+<para>
+Input initialization is a bit complicated.
+It all starts with InitInput(), a routine that you write to call
+AddInputDevice() twice
+(once for pointing device and once for keyboard.)
+You also want to call RegisterKeyboardDevice() and RegisterPointerDevice()
+on them.
+</para>
+<para>
+When you Add the devices, a routine you supply for each device
+gets called to initialize them.
+Your individual initialize routines must call InitKeyboardDeviceStruct()
+or InitPointerDeviceStruct(), depending upon which it is.
+In other words, you indicate twice that the keyboard is the keyboard and
+the pointer is the pointer.
+</para>
+<para>
+<blockquote><programlisting>
+
+	void InitInput(argc, argv)
+	    int argc;
+	    char **argv;
+</programlisting></blockquote>
+InitInput is a DDX routine you must write to initialize the
+input subsystem in DDX.
+It must call AddInputDevice() for each device that might generate events.
+In addition, you must register the main keyboard and pointing devices by
+calling RegisterPointerDevice() and RegisterKeyboardDevice().
+</para>
+<para>
+<blockquote><programlisting>
+
+	DevicePtr AddInputDevice(deviceProc, autoStart)
+		DeviceProc deviceProc;
+		Bool autoStart;
+</programlisting></blockquote>
+AddInputDevice is a DIX routine you call to create a device object.
+deviceProc is a DDX routine that is called by DIX to do various operations.
+AutoStart should be TRUE for devices that need to be turned on at
+initialization time with a special call, as opposed to waiting for some
+client application to
+turn them on.
+This routine returns NULL if sufficient memory cannot be allocated to
+install the device.
+</para>
+<para>
+Note also that except for the main keyboard and pointing device,
+an extension is needed to provide for a client interface to a device.
+</para>
+<para>
+<blockquote><programlisting>
+
+	void RegisterPointerDevice(device)
+		DevicePtr device;
+</programlisting></blockquote>
+RegisterPointerDevice is a DIX routine that your DDX code calls that
+makes that device the main pointing device.
+This routine is called once upon initialization and cannot be called again.
+</para>
+<para>
+<blockquote><programlisting>
+
+	void RegisterKeyboardDevice(device)
+		DevicePtr device;
+</programlisting></blockquote>
+RegisterKeyboardDevice makes the given device the main keyboard.
+This routine is called once upon initialization and cannot be called again.
+</para>
+<para>
+The following DIX
+procedures return the specified DevicePtr. They may or may not be useful
+to DDX implementors.
+</para>
+<para>
+<blockquote><programlisting>
+
+	DevicePtr LookupKeyboardDevice()
+</programlisting></blockquote>
+LookupKeyboardDevice returns pointer for current main keyboard device.
+</para>
+<para>
+<blockquote><programlisting>
+
+	DevicePtr LookupPointerDevice()
+</programlisting></blockquote>
+LookupPointerDevice returns pointer for current main pointing device.
+</para>
+<para>
+A DeviceProc (the kind passed to AddInputDevice()) in the following form:
+<blockquote><programlisting>
+
+	Bool pInternalDevice->DeviceProc(device, action);
+		DeviceIntPtr device;
+		int action;
+</programlisting></blockquote>
+You must write a DeviceProc for each device.
+device points to the device record.
+action tells what action to take;
+it will be one of  these defined constants  (defined in input.h):
+<itemizedlist>
+<listitem><para>
+DEVICE_INIT -
+At DEVICE_INIT time, the device should initialize itself by calling
+InitPointerDeviceStruct(), InitKeyboardDeviceStruct(), or a similar
+routine (see below)
+and "opening" the device if necessary.
+If you return a non-zero (i.e., != Success) value from the DEVICE_INIT
+call, that device will be considered unavailable. If either the main keyboard
+or main pointing device cannot be initialized, the DIX code will refuse
+to continue booting up.</para></listitem>
+<listitem><para>
+DEVICE_ON - If the DeviceProc is called with DEVICE_ON, then it is
+allowed to start
+putting events into the client stream by calling through the ProcessInputProc
+in the device.</para></listitem>
+<listitem><para>
+DEVICE_OFF - If the DeviceProc is called with DEVICE_OFF, no further
+events from that
+device should be given to the DIX layer.
+The device will appear to be dead to the user.</para></listitem>
+<listitem><para>
+DEVICE_CLOSE - At DEVICE_CLOSE (terminate or reset) time, the device should
+be totally closed down.</para></listitem>
+</itemizedlist>
+</para>
+<para>
+<blockquote><programlisting>
+
+	void InitPointerDeviceStruct(device, map, mapLength,
+			GetMotionEvents, ControlProc, numMotionEvents)
+		DevicePtr device;
+		CARD8 *map;
+		int mapLength;
+		ValuatorMotionProcPtr ControlProc;
+		PtrCtrlProcPtr GetMotionEvents;
+		int numMotionEvents;
+</programlisting></blockquote>
+InitPointerDeviceStruct is a DIX routine you call at DEVICE_INIT time to declare
+some operating routines and data structures for a pointing device.
+map and mapLength are as described in the X Window
+System protocol specification.
+ControlProc and GetMotionEvents are DDX routines, see above.
+</para>
+<para>
+numMotionEvents is for the motion-buffer-size for the GetMotionEvents
+request.
+A typical length for a motion buffer would be 100 events.
+A server that does not implement this capability should set
+numMotionEvents to zero.
+</para>
+<para>
+<blockquote><programlisting>
+
+	void InitKeyboardDeviceStruct(device, pKeySyms, pModifiers, Bell, ControlProc)
+		DevicePtr device;
+		KeySymsPtr pKeySyms;
+		CARD8 *pModifiers;
+		BellProcPtr Bell;
+		KbdCtrlProcPtr ControlProc;
+
+</programlisting></blockquote>
+You call this DIX routine when a keyboard device is initialized and
+its device procedure is called with
+DEVICE_INIT.
+The formats of the keysyms and modifier maps are defined in
+Xserver/include/input.h.
+They describe the layout of keys on the keyboards, and the glyphs
+associated with them.  ( See the next section for information on
+setting up the modifier map and the keysym map.)
+ControlProc and Bell are DDX routines, see above.
+</para>
+</section>
+<section>
+  <title>Keyboard Mapping and Keycodes</title>
+<para>
+When you send a keyboard event, you send a report that a given key has
+either been pressed or has been released.  There must be a keycode for
+each key that identifies the key; the keycode-to-key mapping can be
+any mapping you desire, because you specify the mapping in a table you
+set up for DIX.  However, you are restricted by the protocol
+specification to keycode values in the range 8 to 255 inclusive.
+</para>
+<para>
+The keycode mapping information that you set up consists of the following:
+<itemizedlist>
+<listitem><para>
+A minimum and maximum keycode number</para></listitem>
+<listitem><para>
+An array of sets of keysyms for each key, that is of length
+maxkeycode - minkeycode + 1.
+Each element of this array is a list of codes for symbols that are on that key.
+There is no limit to the number of symbols that can be on a key.</para></listitem>
+</itemizedlist>
+Once the map is set up, DIX keeps and
+maintains the client's changes to it.
+</para>
+<para>
+The X protocol defines standard names to indicate the symbol(s)
+printed on each keycap. (See X11/keysym.h)
+</para>
+<para>
+Legal modifier keys must generate both up and down transitions.  When
+a client tries to change a modifier key (for instance, to make "A" the
+"Control" key), DIX calls the following routine, which should retuurn
+TRUE if the key can be used as a modifier on the given device:
+<blockquote><programlisting>
+
+	Bool LegalModifier(key, pDev)
+	    unsigned int key;
+	    DevicePtr pDev;
+</programlisting></blockquote>
+</para>
+</section>
+</section>
+<section>
+<title>Screens</title>
+<para>
+Different computer graphics
+displays have different capabilities.
+Some are simple monochrome
+frame buffers that are just lying
+there in memory, waiting to be written into.
+Others are color displays with many bits per pixel using some color lookup table.
+Still others have high-speed graphic processors that prefer to do all of the work
+themselves,
+including maintaining their own high-level, graphic data structures.
+</para>
+<section>
+  <title>Screen Hardware Requirements</title>
+<para>
+The only requirement on screens is that you be able to both read
+and write locations in the frame buffer.
+All screens must have a depth of 32 or less (unless you use
+an X extension to allow a greater depth).
+All screens must fit into one of the classes listed in the section
+in this document on Visuals and Depths.
+</para>
+<para>
+X uses the pixel as its fundamental unit of distance on the screen.
+Therefore, most programs will measure everything in pixels.</para>
+<para>
+The sample server assumes square pixels.
+Serious WYSIWYG (what you see is what you get) applications for
+publishing and drawing programs will adjust for
+different screen resolutions automatically.
+Considerable work
+is involved in compensating for non-square pixels (a bit in the DDX
+code for the sample server but quite a bit in the client applications).</para>
+</section>
+<section>
+  <title>Data Structures</title>
+<para>
+X supports multiple screens that are connected to the same
+server.  Therefore, all the per-screen information is bundled into one data
+structure of attributes and procedures, which is the ScreenRec (see
+Xserver/include/scrnintstr.h).
+The procedure entry points in a ScreenRec operate on
+regions, colormaps, cursors, and fonts, because these resources
+can differ in format from one screen to another.</para>
+<para>
+Windows are areas on the screen that can be drawn into by graphic
+routines.  "Pixmaps" are off-screen graphic areas that can be drawn
+into.  They are both considered drawables and are described in the
+section on Drawables.  All graphic operations work on drawables, and
+operations are available to copy patches from one drawable to another.</para>
+<para>
+The pixel image data in all drawables is in a format that is private
+to DDX.  In fact, each instance of a drawable is associated with a
+given screen.  Presumably, the pixel image data for pixmaps is chosen
+to be conveniently understood by the hardware.  All screens in a
+single server must be able to handle all pixmaps depths declared in
+the connection setup information.</para>
+<para>
+Pixmap images are transferred to the server in one of two ways:
+XYPixmap or ZPimap.  XYPixmaps are a series of bitmaps, one for each
+bit plane of the image, using the bitmap padding rules from the
+connection setup.  ZPixmaps are a series of bits, nibbles, bytes or
+words, one for each pixel, using the format rules (padding and so on)
+for the appropriate depth.</para>
+<para>
+All screens in a given server must agree on a set of pixmap image
+formats (PixmapFormat) to support (depth, number of bits per pixel,
+etc.).</para>
+<para>
+There is no color interpretation of bits in the pixmap.  Pixmaps
+do not contain pixel values.  The interpretation is made only when
+the bits are transferred onto the screen.</para>
+<para>
+The screenInfo structure (in scrnintstr.h) is a global data structure
+that has a pointer to an array of ScreenRecs, one for each screen on
+the server.  (These constitute the one and only description of each
+screen in the server.)  Each screen has an identifying index (0, 1, 2, ...).
+In addition, the screenInfo struct contains global server-wide
+details, such as the bit- and byte- order in all bit images, and the
+list of pixmap image formats that are supported.  The X protocol
+insists that these must be the same for all screens on the server.</para>
+</section>
+<section>
+  <title>Output Initialization</title>
+<para>
+<blockquote><programlisting>
+
+	InitOutput(pScreenInfo, argc, argv)
+		ScreenInfo *pScreenInfo;
+		int argc;
+		char **argv;
+</programlisting></blockquote>
+Upon initialization, your DDX routine InitOutput() is called by DIX.
+It is passed a pointer to screenInfo to initialize.  It is also passed
+the argc and argv from main() for your server for the command-line
+arguments.  These arguments may indicate what or how many screen
+device(s) to use or in what way to use them.  For instance, your
+server command line may allow a "-D" flag followed by the name of the
+screen device to use.</para>
+<para>
+Your InitOutput() routine should initialize each screen you wish to
+use by calling AddScreen(), and then it should initialize the pixmap
+formats that you support by storing values directly into the
+screenInfo data structure.  You should also set certain
+implementation-dependent numbers and procedures in your screenInfo,
+which determines the pixmap and scanline padding rules for all screens
+in the server.</para>
+<para>
+<blockquote><programlisting>
+
+	int AddScreen(scrInitProc, argc, argv)
+		Bool (*scrInitProc)();
+		int argc;
+		char **argv;
+</programlisting></blockquote>
+You should call AddScreen(), a DIX procedure, in InitOutput() once for
+each screen to add it to the screenInfo database.  The first argument
+is an initialization procedure for the screen that you supply.  The
+second and third are the argc and argv from main().  It returns the
+screen number of the screen installed, or -1 if there is either
+insufficient memory to add the screen, or (*scrInitProc) returned
+FALSE.</para>
+<para>
+The scrInitProc should be of the following form:
+<blockquote><programlisting>
+
+	Bool scrInitProc(iScreen, pScreen, argc, argv)
+		int iScreen;
+		ScreenPtr pScreen;
+		int argc;
+		char **argv;
+</programlisting></blockquote>
+iScreen is the index for this screen; 0 for the first one initialized,
+1 for the second, etc.  pScreen is the pointer to the screen's new
+ScreenRec.  argc and argv are as before.  Your screen initialize
+procedure should return TRUE upon success or FALSE if the screen
+cannot be initialized (for instance, if the screen hardware does not
+exist on this machine).</para>
+<para>
+This procedure must determine what actual device it is supposed to initialize.
+If you have a different procedure for each screen, then it is no problem.
+If you have the same procedure for multiple screens, it may have trouble
+figuring out which screen to initialize each time around, especially if
+InitOutput() does not initialize all of the screens.
+It is probably easiest to have one procedure for each screen.</para>
+<para>
+The initialization procedure should fill in all the screen procedures
+for that screen (windowing functions, region functions, etc.) and certain
+screen attributes for that screen.</para>
+</section>
+<section>
+  <title>Region Routines in the ScreenRec</title>
+<para>
+A region is a dynamically allocated data structure that describes an
+irregularly shaped piece of real estate in XY pixel space.  You can
+think of it as a set of pixels on the screen to be operated upon with
+set operations such as AND and OR.</para>
+<para>
+A region is frequently implemented as a list of rectangles or bitmaps
+that enclose the selected pixels.  Region operators control the
+"clipping policy," or the operations that work on regions.  (The
+sample server uses YX-banded rectangles.  Unless you have something
+already implemented for your graphics system, you should keep that
+implementation.)  The procedure pointers to the region operators are
+located in the ScreenRec data structure.  The definition of a region
+can be found in the file Xserver/include/regionstr.h.  The region code
+is found in Xserver/mi/miregion.c.  DDX implementations using other
+region formats will need to supply different versions of the region
+operators.</para>
+<para>
+Since the list of rectangles is unbounded in size, part of the region
+data structure is usually a large, dynamically allocated chunk of
+memory.  As your region operators calculate logical combinations of
+regions, these blocks may need to be reallocated by your region
+software.  For instance, in the sample server, a RegionRec has some
+header information and a pointer to a dynamically allocated rectangle
+list.  Periodically, the rectangle list needs to be expanded with
+Xrealloc(), whereupon the new pointer is remembered in the RegionRec.</para>
+<para>
+Most of the region operations come in two forms: a function pointer in
+the Screen structure, and a macro.  The server can be compiled so that
+the macros make direct calls to the appropriate functions (instead of
+indirecting through a screen function pointer), or it can be compiled
+so that the macros are identical to the function pointer forms.
+Making direct calls is faster on many architectures.</para>
+<para>
+<blockquote><programlisting>
+
+	RegionPtr pScreen->RegionCreate( rect, size)
+		BoxPtr rect;
+		int size;
+
+	macro: RegionPtr REGION_CREATE(pScreen, rect, size)
+
+</programlisting></blockquote>
+RegionCreate creates a region that describes ONE rectangle.  The
+caller can avoid unnecessary reallocation and copying by declaring the
+probable maximum number of rectangles that this region will need to
+describe itself.  Your region routines, though, cannot fail just
+because the region grows beyond this size.  The caller of this routine
+can pass almost anything as the size; the value is merely a good guess
+as to the maximum size until it is proven wrong by subsequent use.
+Your region procedures are then on their own in estimating how big the
+region will get.  Your implementation might ignore size, if
+applicable.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->RegionInit (pRegion, rect, size)
+		RegionPtr	pRegion;
+		BoxPtr		rect;
+		int		size;
+
+	macro: REGION_INIT(pScreen, pRegion, rect, size)
+
+</programlisting></blockquote>
+Given an existing raw region structure (such as an local variable), this
+routine fills in the appropriate fields to make this region as usable as
+one returned from RegionCreate.  This avoids the additional dynamic memory
+allocation overhead for the region structure itself.
+</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->RegionCopy(dstrgn, srcrgn)
+		RegionPtr dstrgn, srcrgn;
+
+	macro: Bool REGION_COPY(pScreen, dstrgn, srcrgn)
+
+</programlisting></blockquote>
+RegionCopy copies the description of one region, srcrgn, to another
+already-created region,
+dstrgn; returning TRUE if the copy succeeded, and FALSE otherwise.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->RegionDestroy( pRegion)
+		RegionPtr pRegion;
+
+	macro: REGION_DESTROY(pScreen, pRegion)
+
+</programlisting></blockquote>
+RegionDestroy destroys a region and frees all allocated memory.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->RegionUninit (pRegion)
+		RegionPtr pRegion;
+
+	macro: REGION_UNINIT(pScreen, pRegion)
+
+</programlisting></blockquote>
+Frees everything except the region structure itself, useful when the
+region was originally passed to RegionInit instead of received from
+RegionCreate.  When this call returns, pRegion must not be reused until
+it has been RegionInit'ed again.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->Intersect(newReg, reg1, reg2)
+		RegionPtr newReg, reg1, reg2;
+
+	macro: Bool REGION_INTERSECT(pScreen, newReg, reg1, reg2)
+
+	Bool  pScreen->Union(newReg, reg1, reg2)
+		RegionPtr newReg, reg1, reg2;
+
+	macro: Bool REGION_UNION(pScreen, newReg, reg1, reg2)
+
+	Bool  pScreen->Subtract(newReg, regMinuend, regSubtrahend)
+		RegionPtr newReg, regMinuend, regSubtrahend;
+
+	macro: Bool REGION_UNION(pScreen, newReg, regMinuend, regSubtrahend)
+
+	Bool pScreen->Inverse(newReg, pReg,  pBox)
+		RegionPtr newReg, pReg;
+		BoxPtr pBox;
+
+	macro: Bool REGION_INVERSE(pScreen, newReg, pReg,  pBox)
+
+</programlisting></blockquote>
+The above four calls all do basic logical operations on regions.  They
+set the new region (which already exists) to describe the logical
+intersection, union, set difference, or inverse of the region(s) that
+were passed in.  Your routines must be able to handle a situation
+where the newReg is the same region as one of the other region
+arguments.</para>
+<para>
+The subtract function removes the Subtrahend from the Minuend and
+puts the result in newReg.</para>
+<para>
+The inverse function returns a region that is the pBox minus the
+region passed in.  (A true "inverse" would make a region that extends
+to infinity in all directions but has holes in the middle.)  It is
+undefined for situations where the region extends beyond the box.</para>
+<para>
+Each routine must return the value TRUE for success.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->RegionReset(pRegion, pBox)
+		RegionPtr pRegion;
+		BoxPtr pBox;
+
+	macro: REGION_RESET(pScreen, pRegion, pBox)
+
+</programlisting></blockquote>
+RegionReset sets the region to describe
+one rectangle and reallocates it to a size of one rectangle, if applicable.</para>
+<para>
+<blockquote><programlisting>
+
+	void  pScreen->TranslateRegion(pRegion, x, y)
+		RegionPtr pRegion;
+		int x, y;
+
+	macro: REGION_TRANSLATE(pScreen, pRegion, x, y)
+
+</programlisting></blockquote>
+TranslateRegion simply moves a region +x in the x direction and +y in the y
+direction.</para>
+<para>
+<blockquote><programlisting>
+
+	int  pScreen->RectIn(pRegion, pBox)
+		RegionPtr pRegion;
+		BoxPtr pBox;
+
+	macro: int RECT_IN_REGION(pScreen, pRegion, pBox)
+
+</programlisting></blockquote>
+RectIn returns one of the defined constants rgnIN, rgnOUT, or rgnPART,
+depending upon whether the box is entirely inside the region, entirely
+outside of the region, or partly in and partly out of the region.
+These constants are defined in Xserver/include/region.h.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->PointInRegion(pRegion, x, y, pBox)
+		RegionPtr pRegion;
+		int x, y;
+		BoxPtr pBox;
+
+	macro: Bool POINT_IN_REGION(pScreen, pRegion, x, y, pBox)
+
+</programlisting></blockquote>
+PointInRegion returns true if the point x, y is in the region.  In
+addition, it fills the rectangle pBox with coordinates of a rectangle
+that is entirely inside of pRegion and encloses the point.  In the mi
+implementation, it is the largest such rectangle.  (Due to the sample
+server implementation, this comes cheaply.)</para>
+<para>
+This routine used by DIX when tracking the pointing device and
+deciding whether to report mouse events or change the cursor.  For
+instance, DIX needs to change the cursor when it moves from one window
+to another.  Due to overlapping windows, the shape to check may be
+irregular.  A PointInRegion() call for every pointing device movement
+may be too expensive.  The pBox is a kind of wake-up box; DIX need not
+call PointInRegion() again until the cursor wanders outside of the
+returned box.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->RegionNotEmpty(pRegion)
+		RegionPtr pRegion;
+
+	macro: Bool REGION_NOTEMPTY(pScreen, pRegion)
+
+</programlisting></blockquote>
+RegionNotEmpty is a boolean function that returns
+true or false depending upon whether the region encloses any pixels.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->RegionEmpty(pRegion)
+		RegionPtr pRegion;
+
+	macro: REGION_EMPTY(pScreen, pRegion)
+
+</programlisting></blockquote>
+RegionEmpty sets the region to be empty.</para>
+<para>
+<blockquote><programlisting>
+
+	BoxPtr pScreen->RegionExtents(pRegion)
+		RegionPtr pRegion;
+
+	macro: REGION_EXTENTS(pScreen, pRegion)
+
+</programlisting></blockquote>
+RegionExtents returns a rectangle that is the smallest
+possible superset of the entire region.
+The caller will not modify this rectangle, so it can be the one
+in your region struct.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->RegionAppend (pDstRgn, pRegion)
+		RegionPtr pDstRgn;
+		RegionPtr pRegion;
+
+	macro: Bool REGION_APPEND(pScreen, pDstRgn, pRegion)
+
+	Bool pScreen->RegionValidate (pRegion, pOverlap)
+		RegionPtr pRegion;
+		Bool *pOverlap;
+
+	macro: Bool REGION_VALIDATE(pScreen, pRegion, pOverlap)
+
+</programlisting></blockquote>
+These functions provide an optimization for clip list generation and
+must be used in conjunction.  The combined effect is to produce the
+union of a collection of regions, by using RegionAppend several times,
+and finally calling RegionValidate which takes the intermediate
+representation (which needn't be a valid region) and produces the
+desired union.  pOverlap is set to TRUE if any of the original
+regions overlap; FALSE otherwise.</para>
+<para>
+<blockquote><programlisting>
+
+	RegionPtr pScreen->BitmapToRegion (pPixmap)
+		PixmapPtr pPixmap;
+
+	macro: RegionPtr BITMAP_TO_REGION(pScreen, pPixmap)
+
+</programlisting></blockquote>
+Given a depth-1 pixmap, this routine must create a valid region which
+includes all the areas of the pixmap filled with 1's and excludes the
+areas filled with 0's.  This routine returns NULL if out of memory.</para>
+<para>
+<blockquote><programlisting>
+
+	RegionPtr pScreen->RectsToRegion (nrects, pRects, ordering)
+		int nrects;
+		xRectangle *pRects;
+		int ordering;
+
+	macro: RegionPtr RECTS_TO_REGION(pScreen, nrects, pRects, ordering)
+
+</programlisting></blockquote>
+Given a client-supplied list of rectangles, produces a region which includes
+the union of all the rectangles.  Ordering may be used as a hint which
+describes how the rectangles are sorted.  As the hint is provided by a
+client, it must not be required to be correct, but the results when it is
+not correct are not defined (core dump is not an option here).</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->SendGraphicsExpose(client,pRegion,drawable,major,minor)
+		ClientPtr client;
+		RegionPtr pRegion;
+		XID drawable;
+		int major;
+		int minor;
+
+</programlisting></blockquote>
+SendGraphicsExpose dispatches a list of GraphicsExposure events which
+span the region to the specified client.  If the region is empty, or
+a NULL pointer, a NoExpose event is sent instead.</para>
+</section>
+<section>
+  <title>Cursor Routines for a Screen</title>
+<para>
+A cursor is the visual form tied to the pointing device.  The default
+cursor is an "X" shape, but the cursor can have any shape.  When a
+client creates a window, it declares what shape the cursor will be
+when it strays into that window on the screen.</para>
+<para>
+For each possible shape the cursor assumes, there is a CursorRec data
+structure.  This data structure contains a pointer to a CursorBits
+data structure which contains a bitmap for the image of the cursor and
+a bitmap for a mask behind the cursor, in addition, the CursorRec data
+structure contains foreground and background colors for the cursor.
+The CursorBits data structure is shared among multiple CursorRec
+structures which use the same font and glyph to describe both source
+and mask.  The cursor image is applied to the screen by applying the
+mask first, clearing 1 bits in its form to the background color, and
+then overwriting on the source image, in the foreground color.  (One
+bits of the source image that fall on top of zero bits of the mask
+image are undefined.)  This way, a cursor can have transparent parts,
+and opaque parts in two colors.  X allows any cursor size, but some
+hardware cursor schemes allow a maximum of N pixels by M pixels.
+Therefore, you are allowed to transform the cursor to a smaller size,
+but be sure to include the hot-spot.</para>
+<para>
+CursorBits in Xserver/include/cursorstr.h is a device-independent
+structure containing a device-independent representation of the bits
+for the source and mask.  (This is possible because the bitmap
+representation is the same for all screens.)</para>
+<para>
+When a cursor is created, it is "realized" for each screen.  At
+realization time, each screen has the chance to convert the bits into
+some other representation that may be more convenient (for instance,
+putting the cursor into off-screen memory) and set up its
+device-private area in either the CursorRec data structure or
+CursorBits data structure as appropriate to possibly point to whatever
+data structures are needed.  It is more memory-conservative to share
+realizations by using the CursorBits private field, but this makes the
+assumption that the realization is independent of the colors used
+(which is typically true).  For instance, the following are the device
+private entries for a particular screen and cursor:
+<blockquote><programlisting>
+
+	pCursor->devPriv[pScreen->myNum]
+	pCursor->bits->devPriv[pScreen->myNum]
+
+</programlisting></blockquote>
+This is done because the change from one cursor shape to another must
+be fast and responsive; the cursor image should be able to flutter as
+fast as the user moves it across the screen.</para>
+<para>
+You must implement the following routines for your hardware:
+<blockquote><programlisting>
+
+	Bool pScreen->RealizeCursor( pScr, pCurs)
+		ScreenPtr pScr;
+		CursorPtr pCurs;
+
+	Bool pScreen->UnrealizeCursor( pScr, pCurs)
+		ScreenPtr pScr;
+		CursorPtr pCurs;
+
+</programlisting></blockquote>
+</para>
+<para>
+RealizeCursor and UnrealizeCursor should realize (allocate and
+calculate all data needed) and unrealize (free the dynamically
+allocated data) a given cursor when DIX needs them.  They are called
+whenever a device-independent cursor is created or destroyed.  The
+source and mask bits pointed to by fields in pCurs are undefined for
+bits beyond the right edge of the cursor.  This is so because the bits
+are in Bitmap format, which may have pad bits on the right edge.  You
+should inhibit UnrealizeCursor() if the cursor is currently in use;
+this happens when the system is reset.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->DisplayCursor( pScr, pCurs)
+		ScreenPtr pScr;
+		CursorPtr pCurs;
+
+</programlisting></blockquote>
+DisplayCursor should change the cursor on the given screen to the one
+passed in.  It is called by DIX when the user moves the pointing
+device into a different window with a different cursor.  The hotspot
+in the cursor should be aligned with the current cursor position.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->RecolorCursor( pScr, pCurs, displayed)
+		ScreenPtr pScr;
+		CursorPtr pCurs;
+		Bool displayed;
+</programlisting></blockquote>
+RecolorCursor notifies DDX that the colors in pCurs have changed and
+indicates whether this is the cursor currently being displayed.  If it
+is, the cursor hardware state may have to be updated.  Whether
+displayed or not, state created at RealizeCursor time may have to be
+updated.  A generic version, miRecolorCursor, may be used that
+does an unrealize, a realize, and possibly a display (in micursor.c);
+however this constrains UnrealizeCursor and RealizeCursor to always return
+TRUE as no error indication is returned here.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->ConstrainCursor( pScr, pBox)
+		ScreenPtr pScr;
+		BoxPtr pBox;
+
+</programlisting></blockquote>
+ConstrainCursor should cause the cursor to restrict its motion to the
+rectangle pBox.  DIX code is capable of enforcing this constraint by
+forcefully moving the cursor if it strays out of the rectangle, but
+ConstrainCursor offers a way to send a hint to the driver or hardware
+if such support is available.  This can prevent the cursor from
+wandering out of the box, then jumping back, as DIX forces it back.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->PointerNonInterestBox( pScr, pBox)
+		ScreenPtr pScr;
+		BoxPtr pBox;
+
+</programlisting></blockquote>
+PointerNonInterestBox is DIX's way of telling the pointing device code
+not to report motion events while the cursor is inside a given
+rectangle on the given screen.  It is optional and, if not
+implemented, it should do nothing.  This routine is called only when
+the client has declared that it is not interested in motion events in
+a given window.  The rectangle you get may be a subset of that window.
+It saves DIX code the time required to discard uninteresting mouse
+motion events.  This is only a hint, which may speed performance.
+Nothing in DIX currently calls PointerNonInterestBox.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->CursorLimits( pScr, pCurs, pHotBox, pTopLeftBox)
+		ScreenPtr pScr;
+		CursorPtr pCurs;
+		BoxPtr pHotBox;
+		BoxPtr pTopLeftBox;	/* return value */
+
+</programlisting></blockquote>
+CursorLimits should calculate the box that the cursor hot spot is
+physically capable of moving within, as a function of the screen pScr,
+the device-independent cursor pCurs, and a box that DIX hypothetically
+would want the hot spot confined within, pHotBox.  This routine is for
+informing DIX only; it alters no state within DDX.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->SetCursorPosition( pScr, newx, newy, generateEvent)
+		ScreenPtr pScr;
+		int newx;
+		int newy;
+		Bool generateEvent;
+
+</programlisting></blockquote>
+SetCursorPosition should artificially move the cursor as though the
+user had jerked the pointing device very quickly.  This is called in
+response to the WarpPointer request from the client, and at other
+times.  If generateEvent is True, the device should decide whether or
+not to call ProcessInputEvents() and then it must call
+DevicePtr->processInputProc.  Its effects are, of course, limited in
+value for absolute pointing devices such as a tablet.</para>
+<para>
+<blockquote><programlisting>
+
+	void NewCurrentScreen(newScreen, x, y)
+	    ScreenPtr newScreen;
+	    int x,y;
+
+</programlisting></blockquote>
+If your ddx provides some mechanism for the user to magically move the
+pointer between multiple screens, you need to inform DIX when this
+occurs.  You should call NewCurrentScreen to accomplish this, specifying
+the new screen and the new x and y coordinates of the pointer on that screen.</para>
+</section>
+<section>
+  <title>Visuals, Depths and Pixmap Formats for Screens</title>
+<para>
+The "depth" of a image is the number of bits that are used per pixel to display it.</para>
+<para>
+The "bits per pixel" of a pixmap image that is sent over the client
+byte stream is a number that is either 4, 8, 16, 24 or 32.  It is the
+number of bits used per pixel in Z format.  For instance, a pixmap
+image that has a depth of six is best sent in Z format as 8 bits per
+pixel.</para>
+<para>
+A "pixmap image format" or a "pixmap format" is a description of the
+format of a pixmap image as it is sent over the byte stream.  For each
+depth available on a server, there is one and only one pixmap format.
+This pixmap image format gives the bits per pixel and the scanline
+padding unit. (For instance, are pixel rows padded to bytes, 16-bit
+words, or 32-bit words?)</para>
+<para>
+For each screen, you must decide upon what depth(s) it supports.  You
+should only count the number of bits used for the actual image.  Some
+displays store additional bits to indicate what window this pixel is
+in, how close this object is to a viewer, transparency, and other
+data; do not count these bits.</para>
+<para>
+A "display class" tells whether the display is monochrome or color,
+whether there is a lookup table, and how the lookup table works.</para>
+<para>
+A "visual" is a combination of depth, display class, and a description
+of how the pixel values result in a color on the screen.  Each visual
+has a set of masks and offsets that are used to separate a pixel value
+into its red, green, and blue components and a count of the number of
+colormap entries.  Some of these fields are only meaningful when the
+class dictates so.  Each visual also has a screen ID telling which
+screen it is usable on.  Note that the depth does not imply the number
+of map_entries; for instance, a display can have 8 bits per pixel but
+only 254 colormap entries for use by applications (the other two being
+reserved by hardware for the cursor).</para>
+<para>
+Each visual is identified by a 32-bit visual ID which the client uses
+to choose what visual is desired on a given window.  Clients can be
+using more than one visual on the same screen at the same time.</para>
+<para>
+The class of a display describes how this translation takes place.
+There are three ways to do the translation.
+<itemizedlist>
+<listitem><para>
+Pseudo - The pixel value, as a whole, is looked up
+in a table of length map_entries to
+determine the color to display.</para></listitem>
+<listitem><para>
+True - The
+pixel value is broken up into red, green, and blue fields, each of which
+are looked up in separate red, green, and blue lookup tables,
+each of length map_entries.</para></listitem>
+<listitem><para>
+Gray - The pixel value is looked up in a table of length map_entries to
+determine a gray level to display.</para></listitem>
+</itemizedlist>
+</para>
+<para>
+In addition, the lookup table can be static (resulting colors are fixed for each
+pixel value)
+or dynamic (lookup entries are under control of the client program).
+This leads to a total of six classes:
+<itemizedlist>
+<listitem><para>
+Static Gray - The pixel value (of however many bits) determines directly the
+level of gray
+that the pixel assumes.</para></listitem>
+<listitem><para>
+Gray Scale - The pixel value is fed through a lookup table to arrive at the level
+of gray to display
+for the given pixel.</para></listitem>
+<listitem><para>
+Static Color - The pixel value is fed through a fixed lookup table that yields the
+color to display
+for that pixel.</para></listitem>
+<listitem><para>
+PseudoColor - The whole pixel value is fed through a programmable lookup
+table that has one
+color (including red, green, and blue intensities) for each possible pixel value,
+and that color is displayed.</para></listitem>
+<listitem><para>
+True Color - Each pixel value consists of one or more bits
+that directly determine each primary color intensity after being fed through
+a fixed table.</para></listitem>
+<listitem><para>
+Direct Color - Each pixel value consists of one or more bits for each primary color.
+Each primary color value is individually looked up in a table for that primary
+color, yielding
+an intensity for that primary color.
+For each pixel, the red value is looked up in the
+red table, the green value in the green table, and
+the blue value in the blue table.</para></listitem>
+</itemizedlist>
+</para>
+<para>
+Here are some examples:
+<itemizedlist>
+<listitem><para>
+A simple monochrome 1 bit per pixel display is Static Gray.</para></listitem>
+<listitem><para>
+A display that has 2 bits per pixel for a choice
+between the colors of black, white, green and violet is Static Color.</para></listitem>
+<listitem><para>
+A display that has three bits per pixel, where
+each bit turns on or off one of the red, green or
+blue guns, is in the True Color class.</para></listitem>
+<listitem><para>
+If you take the last example and scramble the
+correspondence between pixel values and colors
+it becomes a Static Color display.</para></listitem>
+</itemizedlist></para>
+<para>
+A display has 8 bits per pixel.  The 8 bits select one entry out of 256 entries
+in a lookup table, each entry consisting of 24 bits (8bits each for red, green,
+and blue).
+The display can show any 256 of 16 million colors on the screen at once.
+This is a pseudocolor display.
+The client application gets to fill the lookup table in this class of display.</para>
+<para>
+Imagine the same hardware from the last example.
+Your server software allows the user, on the
+command line that starts up the server
+program,
+to fill the lookup table to his liking once and for all.
+From then on, the server software would not change the lookup table
+until it exits.
+For instance, the default might be a lookup table with a reasonable sample of
+colors from throughout the color space.
+But the user could specify that the table be filled with 256 steps of gray scale
+because he knew ahead of time he would be manipulating a lot of black-and-white
+scanned photographs
+and not very many color things.
+Clients would be presented with this unchangeable lookup table.
+Although the hardware qualifies as a PseudoColor display,
+the facade presented to the X client is that this is a Static Color display.</para>
+<para>
+You have to decide what kind of display you have or want
+to pretend you have.
+When you initialize the screen(s), this class value must be set in the
+VisualRec data structure along with other display characteristics like the
+depth and other numbers.</para>
+<para>
+The allowable DepthRec's and VisualRec's are pointed to by fields in the ScreenRec.
+These are set up when InitOutput() is called; you should Xalloc() appropriate blocks
+or use static variables initialized to the correct values.</para>
+</section>
+<section>
+<title>Colormaps for Screens</title>
+<para>
+A colormap is a device-independent
+mapping between pixel values and colors displayed on the screen.</para>
+<para>
+Different windows on the same screen can have different
+colormaps at the same time.
+At any given time, the most recently installed
+colormap(s) will be in use in the server
+so that its (their) windows' colors will be guaranteed to be correct.
+Other windows may be off-color.
+Although this may seem to be chaotic, in practice most clients
+use the default colormap for the screen.</para>
+<para>
+The default colormap for a screen is initialized when the screen is initialized.
+It always remains in existence and is not owned by any regular client.  It
+is owned by client 0 (the server itself).
+Many clients will simply use this default colormap for their drawing.
+Depending upon the class of the screen, the entries in this colormap may
+be modifiable by client applications.</para>
+</section>
+<section>
+  <title>Colormap Routines</title>
+<para>
+You need to implement the following routines to handle the device-dependent
+aspects of color maps.  You will end up placing pointers to these procedures
+in your ScreenRec data structure(s).  The sample server implementations of
+many of these routines are in fbcmap.c.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->CreateColormap(pColormap)
+		ColormapPtr pColormap;
+
+</programlisting></blockquote>
+This routine is called by the DIX CreateColormap routine after it has allocated
+all the data for the new colormap and just before it returns to the dispatcher.
+It is the DDX layer's chance to initialize the colormap, particularly if it is
+a static map.  See the following
+section for more details on initializing colormaps.
+The routine returns FALSE if creation failed, such as due to memory
+limitations.
+Notice that the colormap has a devPriv field from which you can hang any
+colormap specific storage you need.  Since each colormap might need special
+information, we attached the field to the colormap and not the visual.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->DestroyColormap(pColormap)
+		ColormapPtr pColormap;
+
+</programlisting></blockquote>
+This routine is called by the DIX FreeColormap routine after it has uninstalled
+the colormap and notified all interested parties, and before it has freed
+any of the colormap storage.
+It is the DDX layer's chance to free any data it added to the colormap.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->InstallColormap(pColormap)
+		ColormapPtr pColormap;
+
+</programlisting></blockquote>
+InstallColormap should
+fill a lookup table on the screen with which the colormap is associated with
+the colors in pColormap.
+If there is only one hardware lookup table for the screen, then all colors on
+the screen may change simultaneously.</para>
+<para>
+In the more general case of multiple hardware lookup tables,
+this may cause some other colormap to be
+uninstalled, meaning that windows that subscribed to the colormap
+that was uninstalled may end up being off-color.
+See the note, below, about uninstalling maps.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->UninstallColormap(pColormap)
+		ColormapPtr pColormap;
+
+</programlisting></blockquote>
+UninstallColormap should
+remove pColormap from screen pColormap->pScreen.
+Some other map, such as the default map if possible,
+should be installed in place of pColormap if applicable.
+If
+pColormap is the default map, do nothing.
+If any client has requested ColormapNotify events, the DDX layer must notify the client.
+(The routine WalkTree() is
+be used to find such windows.  The DIX routines TellNoMap(),
+TellNewMap()  and TellGainedMap() are provided to be used as
+the procedure parameter to WalkTree.  These procedures are in
+Xserver/dix/colormap.c.)</para>
+<para>
+<blockquote><programlisting>
+
+	int pScreen->ListInstalledColormaps(pScreen, pCmapList)
+		ScreenPtr pScreen;
+		XID *pCmapList;
+
+
+</programlisting></blockquote>
+ListInstalledColormaps fills the pCMapList in with the resource ids
+of the installed maps and returns a count of installed maps.
+pCmapList will point to an array of size MaxInstalledMaps that was allocated
+by the caller.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->StoreColors (pmap, ndef, pdefs)
+		ColormapPtr pmap;
+		int ndef;
+		xColorItem *pdefs;
+
+</programlisting></blockquote>
+StoreColors changes some of the entries in the colormap pmap.
+The number of entries to change are ndef, and pdefs points to the information
+describing what to change.
+Note that partial changes of entries in the colormap are allowed.
+Only the colors
+indicated in the flags field of each xColorItem need to be changed.
+However, all three color fields will be sent with the proper value for the
+benefit of screens that may not be able to set part of a colormap value.
+If the screen is a static class, this routine does nothing.
+The structure of colormap entries is nontrivial; see colormapst.h
+and the definition of xColorItem in Xproto.h for
+more details.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->ResolveColor(pRed, pGreen, pBlue, pVisual)
+		unsigned short *pRed, *pGreen, *pBlue;
+		VisualPtr pVisual;
+
+
+</programlisting></blockquote>
+Given a requested color, ResolveColor returns the nearest color that this hardware is
+capable of displaying on this visual.
+In other words, this rounds off each value, in place, to the number of bits
+per primary color that your screen can use.
+Remember that each screen has one of these routines.
+The level of roundoff should be what you would expect from the value
+you put in the bits_per_rgb field of the pVisual.</para>
+<para>
+Each value is an unsigned value ranging from 0 to 65535.
+The bits least likely to be used are the lowest ones.</para>
+<para>
+For example, if you had a pseudocolor display
+with any number of bits per pixel
+that had a lookup table supplying 6 bits for each color gun
+(a total of 256K different colors), you would
+round off each value to 6 bits.  Please don't simply truncate these values
+to the upper 6 bits, scale the result so that the maximum value seen
+by the client will be 65535 for each primary.  This makes color values
+more portable between different depth displays (a 6-bit truncated white
+will not look white on an 8-bit display).</para>
+<section>
+<title>Initializing a Colormap</title>
+<para>
+When a client requests a new colormap and when the server creates the default
+colormap, the procedure CreateColormap in the DIX layer is invoked.
+That procedure allocates memory for the colormap and related storage such as
+the lists of which client owns which pixels.
+It then sets a bit, BeingCreated, in the flags field of the ColormapRec
+and calls the DDX layer's CreateColormap routine.
+This is your chance to initialize the colormap.
+If the colormap is static, which you can tell by looking at the class field,
+you will want to fill in each color cell to match the hardwares notion of the
+color for that pixel.
+If the colormap is the default for the screen, which you can tell by looking
+at the IsDefault bit in the flags field, you should allocate BlackPixel
+and WhitePixel to match the values you set in the pScreen structure.
+(Of course, you picked those values to begin with.)</para>
+<para>
+You can also wait and use AllocColor() to allocate blackPixel
+and whitePixel after the default colormap has been created.
+If the default colormap is static and you initialized it in
+pScreen->CreateColormap, then use can use AllocColor afterwards
+to choose pixel values with the closest rgb values to those
+desired for blackPixel and whitePixel.
+If the default colormap is dynamic and uninitialized, then
+the rgb values you request will be obeyed, and AllocColor will
+again choose pixel values for you.
+These pixel values can then be stored into the screen.</para>
+<para>
+There are two ways to fill in the colormap.
+The simplest way is to use the DIX function AllocColor.
+<blockquote><programlisting>
+
+int AllocColor (pmap, pred, pgreen, pblue, pPix, client)
+    ColormapPtr         pmap;
+    unsigned short      *pred, *pgreen, *pblue;
+    Pixel               *pPix;
+    int                 client;
+
+</programlisting></blockquote>
+This takes three pointers to 16 bit color values and a pointer to a suggested
+pixel value.  The pixel value is either an index into one colormap or a
+combination of three indices depending on the type of pmap.
+If your colormap starts out empty, and you don't deliberately pick the same
+value twice, you will always get your suggested pixel.
+The truly nervous could check that the value returned in *pPix is the one
+AllocColor was called with.
+If you don't care which pixel is used, or would like them sequentially
+allocated from entry 0, set *pPix to 0.  This will find the first free
+pixel and use that.</para>
+<para>
+AllocColor will take care of all the  bookkeeping  and  will
+call StoreColors to get the colormap rgb values initialized.
+The hardware colormap will be changed whenever this colormap
+is installed.</para>
+<para>
+If for some reason AllocColor doesn't do what you want, you can do your
+own bookkeeping and call StoreColors yourself.  This is much more difficult
+and shouldn't be necessary for most devices.</para>
+</section>
+</section>
+<section>
+  <title>Fonts for Screens</title>
+<para>
+A font is a set of bitmaps that depict the symbols in a character set.
+Each font is for only one typeface in a given size, in other words,
+just one bitmap for each character.  Parallel fonts may be available
+in a variety of sizes and variations, including "bold" and "italic."
+X supports fonts for 8-bit and 16-bit character codes (for oriental
+languages that have more than 256 characters in the font).  Glyphs are
+bitmaps for individual characters.</para>
+<para>
+The source comes with some useful font files in an ASCII, plain-text
+format that should be comprehensible on a wide variety of operating
+systems.  The text format, referred to as BDF, is a slight extension
+of the current Adobe 2.1 Bitmap Distribution Format (Adobe Systems,
+Inc.).</para>
+<para>
+A short paper in PostScript format is included with the sample server
+that defines BDF.  It includes helpful pictures, which is why it is
+done in PostScript and is not included in this document.</para>
+<para>
+Your implementation should include some sort of font compiler to read
+these files and generate binary files that are directly usable by your
+server implementation.  The sample server comes with the source for a
+font compiler.</para>
+<para>
+It is important the font properties contained in the BDF files are
+preserved across any font compilation. In particular, copyright
+information cannot be casually tossed aside without legal
+ramifications. Other properties will be important to some
+sophisticated applications.</para>
+<para>
+All clients get font information from the server.  Therefore, your
+server can support any fonts it wants to.  It should probably support
+at least the fonts supplied with the X11 tape.  In principle, you can
+convert fonts from other sources or dream up your own fonts for use on
+your server.</para>
+<section>
+<title>Portable Compiled Format</title>
+<para>
+A font compiler is supplied with the sample server.  It has
+compile-time switches to convert the BDF files into a portable binary
+form, called Portable Compiled Format or PCF.  This allows for an
+arbitrary data format inside the file, and by describing the details
+of the format in the header of the file, any PCF file can be read by
+any PCF reading client.  By selecting the format which matches the
+required internal format for your renderer, the PCF reader can avoid
+reformatting the data each time it is read in.  The font compiler
+should be quite portable.</para>
+<para>
+The fonts included with the tape are stored in fonts/bdf.  The
+font compiler is found in fonts/tools/bdftopcf.</para>
+</section>
+<section>
+  <title>Font Realization</title>
+<para>
+Each screen configured into the server
+has an opportunity at font-load time
+to "realize" a font into some internal format if necessary.
+This happens every time the font is loaded into memory.</para>
+<para>
+A font (FontRec in Xserver/include/dixfontstr.h) is
+a device-independent structure containing a device-independent
+representation of the font.  When a font is created, it is "realized"
+for each screen.  At this point, the screen has the chance to convert
+the font into some other format.  The DDX layer can also put information
+in the devPrivate storage.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->RealizeFont(pScr, pFont)
+		ScreenPtr pScr;
+		FontPtr pFont;
+
+	Bool pScreen->UnrealizeFont(pScr, pFont)
+		ScreenPtr pScr;
+		FontPtr pFont;
+
+</programlisting></blockquote>
+RealizeFont and UnrealizeFont should calculate and allocate these extra data structures and
+dispose of them when no longer needed.
+These are called in response to OpenFont and CloseFont requests from
+the client.
+The sample server implementation is in fbscreen.c (which does very little).</para>
+</section>
+</section>
+<section>
+  <title>Other Screen Routines</title>
+<para>
+You must supply several other screen-specific routines for
+your X server implementation.
+Some of these are described in other sections:
+<itemizedlist>
+<listitem><para>
+GetImage() is described in the Drawing Primitives section.</para></listitem>
+<listitem><para>
+GetSpans() is described in the Pixblit routine section.</para></listitem>
+<listitem><para>
+Several window and pixmap manipulation procedures are
+described in the Window section under Drawables.</para></listitem>
+<listitem><para>
+The CreateGC() routine is described under Graphics Contexts.</para></listitem>
+</itemizedlist>
+</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->QueryBestSize(kind, pWidth, pHeight)
+		int kind;
+		unsigned short *pWidth, *pHeight;
+		ScreenPtr pScreen;
+
+</programlisting></blockquote>
+QueryBestSize() returns the best sizes for cursors, tiles, and stipples
+in response to client requests.
+kind is one of the defined constants CursorShape, TileShape, or StippleShape
+(defined in X.h).
+For CursorShape, return the maximum width and
+height for cursors that you can handle.
+For TileShape and StippleShape, start with the suggested values in pWidth
+and pHeight and modify them in place to be optimal values that are
+greater than or equal to the suggested values.
+The sample server implementation is in Xserver/fb/fbscreen.c.</para>
+<para>
+<blockquote><programlisting>
+
+	pScreen->SourceValidate(pDrawable, x, y, width, height)
+		DrawablePtr pDrawable;
+		int x, y, width, height;
+
+</programlisting></blockquote>
+SourceValidate should be called by CopyArea/CopyPlane primitives when
+the source drawable is not the same as the destination, and the
+SourceValidate function pointer in the screen is non-null.  If you know that
+you will never need SourceValidate, you can avoid this check.  Currently,
+SourceValidate is used by the mi software cursor code to remove the cursor
+from the screen when the source rectangle overlaps the cursor position.
+x,y,width,height describe the source rectangle (source relative, that is)
+for the copy operation.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->SaveScreen(pScreen, on)
+		ScreenPtr pScreen;
+		int on;
+
+</programlisting></blockquote>
+SaveScreen() is used for Screen Saver support (see WaitForSomething()).
+pScreen is the screen to save.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->CloseScreen(pScreen)
+	    ScreenPtr pScreen;
+
+</programlisting></blockquote>
+When the server is reset, it calls this routine for each screen.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->CreateScreenResources(pScreen)
+	    ScreenPtr pScreen;
+
+</programlisting></blockquote>
+If this routine is not NULL, it will be called once per screen per
+server initialization/reset after all modules have had a chance to
+request private space on all structures that support them (see
+<xref linkend="wrappers_and_privates"/> below).  You may create resources
+in this function instead of in the
+screen init function passed to AddScreen in order to guarantee that
+all pre-allocated space requests have been registered first.  With the
+new devPrivates mechanism, this is not strictly necessary, however.
+This routine returns TRUE if successful.</para>
+</section>
+</section>
+<section>
+<title>Drawables</title>
+<para>
+A drawable is a descriptor of a surface that graphics are drawn into, either
+a window on the screen or a pixmap in memory.</para>
+<para>
+Each drawable has a type, class,
+ScreenPtr for the screen it is associated with, depth, position, size,
+and serial number.
+The type is one of the defined constants DRAWABLE_PIXMAP,
+DRAWABLE_WINDOW and UNDRAWABLE_WINDOW.
+(An undrawable window is used for window class InputOnly.)
+The serial number is guaranteed to be unique across drawables, and
+is used in determining
+the validity of the clipping information in a GC.
+The screen selects the set of procedures used to manipulate and draw into the
+drawable.  Position is used (currently) only by windows; pixmaps must
+set these fields to 0,0 as this reduces the amount of conditional code
+executed throughout the mi code.  Size indicates the actual client-specified
+size of the drawable.
+There are, in fact, no other fields that a window drawable and pixmap
+drawable have in common besides those mentioned here.</para>
+<para>
+Both PixmapRecs and WindowRecs are structs that start with a drawable
+and continue on with more fields.  Pixmaps have a single pointer field
+named devPrivate which usually points to the pixmap data but could conceivably be
+used for anything that DDX wants.  Both windows and pixmaps also have a
+devPrivates field which can be used for DDX specific data (see <xref linkend="wrappers_and_privates"/>
+below).  This is done because different graphics hardware has
+different requirements for management; if the graphics is always
+handled by a processor with an independent address space, there is no
+point having a pointer to the bit image itself.</para>
+<para>
+The definition of a drawable and a pixmap can be found in the file
+Xserver/include/pixmapstr.h.
+The definition of a window can be found in the file Xserver/include/windowstr.h.</para>
+<section>
+  <title>Pixmaps</title>
+<para>
+A pixmap is a three-dimensional array of bits stored somewhere offscreen,
+rather than in the visible portion of the screen's display frame buffer.  It
+can be used as a source or destination in graphics operations.  There is no
+implied interpretation of the pixel values in a pixmap, because it has no
+associated visual or colormap.  There is only a depth that indicates the
+number of significant bits per pixel.  Also, there is no implied physical
+size for each pixel; all graphic units are in numbers of pixels.  Therefore,
+a pixmap alone does not constitute a complete image; it represents only a
+rectangular array of pixel values.</para>
+<para>
+Note that the pixmap data structure is reference-counted.</para>
+<para>
+The server implementation is free to put the pixmap data
+anywhere it sees fit, according to its graphics hardware setup.  Many
+implementations will simply have the data dynamically allocated in the
+server's address space.  More sophisticated implementations may put the
+data in undisplayed framebuffer storage.</para>
+<para>
+In addition to dynamic devPrivates (see <xref linkend="wrappers_and_privates"/>
+below), the pixmap data structure has two fields that are private to
+the device.  Although you can use them for anything you want, they
+have intended purposes.  devKind is intended to be a device specific
+indication of the pixmap location (host memory, off-screen, etc.).  In
+the sample server, since all pixmaps are in memory, devKind stores the
+width of the pixmap in bitmap scanline units.  devPrivate is usually
+a pointer to the bits in the pixmap.</para>
+<para>
+A bitmap is a pixmap that is one bit deep.</para>
+<para>
+<blockquote><programlisting>
+
+	PixmapPtr pScreen->CreatePixmap(pScreen, width, height, depth)
+		ScreenPtr pScreen;
+		int width, height, depth;
+
+</programlisting></blockquote>
+This ScreenRec procedure must create a pixmap of the size
+requested.
+It must allocate a PixmapRec and fill in all of the fields.
+The reference count field must be set to 1.
+If width or height are zero, no space should be allocated
+for the pixmap data, and if the implementation is using the
+devPrivate field as a pointer to the pixmap data, it should be
+set to NULL.
+If successful, it returns a pointer to the new pixmap; if not, it returns NULL.
+See Xserver/fb/fbpixmap.c for the sample server implementation.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->DestroyPixmap(pPixmap)
+		PixmapPtr pPixmap;
+
+</programlisting></blockquote>
+This ScreenRec procedure must "destroy" a pixmap.
+It should decrement the reference count and, if zero, it
+must deallocate the PixmapRec and all attached devPrivate blocks.
+If successful, it returns TRUE.
+See Xserver/fb/fbpixmap.c for the sample server implementation.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool
+	pScreen->ModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, devKind, pPixData)
+		PixmapPtr   pPixmap;
+		int	    width;
+		int	    height;
+		int	    depth;
+		int	    bitsPerPixel;
+		int	    devKind;
+		pointer     pPixData;
+
+</programlisting></blockquote>
+This routine takes a pixmap header and initializes the fields of the PixmapRec to the
+parameters of the same name.  pPixmap must have been created via
+pScreen->CreatePixmap with a zero width or height to avoid
+allocating space for the pixmap data.  pPixData is assumed to be the
+pixmap data; it will be stored in an implementation-dependent place
+(usually pPixmap->devPrivate.ptr).  This routine returns
+TRUE if successful.  See Xserver/mi/miscrinit.c for the sample
+server implementation.</para>
+<para>
+<blockquote><programlisting>
+
+	PixmapPtr
+	GetScratchPixmapHeader(pScreen, width, height, depth, bitsPerPixel, devKind, pPixData)
+		ScreenPtr   pScreen;
+		int	    width;
+		int	    height;
+		int	    depth;
+		int	    bitsPerPixel;
+		int	    devKind;
+		pointer     pPixData;
+
+	void FreeScratchPixmapHeader(pPixmap)
+		PixmapPtr pPixmap;
+
+</programlisting></blockquote>
+DDX should use these two DIX routines when it has a buffer of raw
+image data that it wants to manipulate as a pixmap temporarily,
+usually so that some other part of the server can be leveraged to
+perform some operation on the data.  The data should be passed in
+pPixData, and will be stored in an implementation-dependent place
+(usually pPixmap->devPrivate.ptr). The other
+fields go into the corresponding PixmapRec fields.
+If successful, GetScratchPixmapHeader returns a valid PixmapPtr which can
+be used anywhere the server expects a pixmap, else
+it returns NULL.  The pixmap should be released when no longer needed
+(usually within the same function that allocated it)
+with FreeScratchPixmapHeader.</para>
+</section>
+<section>
+  <title>Windows</title>
+<para>
+A window is a visible, or potentially visible, rectangle on the screen.
+DIX windowing functions maintain an internal n-ary tree data structure, which
+represents the current relationships of the mapped windows.
+Windows that are contained in another window are children of that window and
+are clipped to the boundaries of the parent.
+The root window in the tree is the window for the entire screen.
+Sibling windows constitute a doubly-linked list; the parent window has a pointer
+to the head and tail of this list.
+Each child also has a pointer to its parent.</para>
+<para>
+The border of a window is drawn by a DDX procedure when DIX requests that it
+be drawn.  The contents of the window is drawn by the client through
+requests to the server.</para>
+<para>
+Window painting is orchestrated through an expose event system.
+When a region is exposed,
+DIX generates an expose event, telling the client to repaint the window and
+passing the region that is the minimal area needed to be repainted.</para>
+<para>
+As a favor to clients, the server may retain
+the output to the hidden parts of windows
+in off-screen memory; this is called "backing store".
+When a part of such a window becomes exposed, it
+can quickly move pixels into place instead of
+triggering an expose event and waiting for a client on the other
+end of the network to respond.
+Even if the network response is insignificant, the time to
+intelligently paint a section of a window is usually more than
+the time to just copy already-painted sections.
+At best, the repainting involves blanking out the area to a background color,
+which will take about the
+same amount of time.
+In this way, backing store can dramatically increase the
+performance of window moves.</para>
+<para>
+On the other hand, backing store can be quite complex, because
+all graphics drawn to hidden areas must be intercepted and redirected
+to the off-screen window sections.
+Not only can this be complicated for the server programmer,
+but it can also impact window painting performance.
+The backing store implementation can choose, at any time, to
+forget pieces of backing that are written into, relying instead upon
+expose events to repaint for simplicity.</para>
+<para>
+In X, the decision to use the backing-store scheme is made
+by you, the server implementor.  The sample server implements
+backing store "for free" by reusing the infrastructure for the Composite
+extension.  As a side effect, it treats the WhenMapped and Always hints
+as equivalent.  However, it will never forget pixel contents when the
+window is mapped.</para>
+<para>
+When a window operation is requested by the client,
+such as a window being created or moved,
+a new state is computed.
+During this transition, DIX informs DDX what rectangles in what windows are about to
+become obscured and what rectangles in what windows have become exposed.
+This provides a hook for the implementation of backing store.
+If DDX is unable to restore exposed regions, DIX generates expose
+events to the client.
+It is then the client's responsibility to paint the
+window parts that were exposed but not restored.</para>
+<para>
+If a window is resized, pixels sometimes need to be
+moved, depending upon
+the application.
+The client can request "Gravity" so that
+certain blocks of the window are
+moved as a result of a resize.
+For instance, if the window has controls or other items
+that always hang on the edge of the
+window, and that edge is moved as a result of the resize,
+then those pixels should be moved
+to avoid having the client repaint it.
+If the client needs to repaint it anyway, such an operation takes
+time, so it is desirable
+for the server to approximate the appearance of the window as best
+it can while waiting for the client
+to do it perfectly.
+Gravity is used for that, also.</para>
+<para>
+The window has several fields used in drawing
+operations:
+<itemizedlist>
+<listitem><para>
+clipList - This region, in conjunction with
+the client clip region in the gc, is used to clip output.
+clipList has the window's children subtracted from it, in addition to pieces of sibling windows
+that overlap this window.  To get the list with the
+children included (subwindow-mode is IncludeInferiors),
+the routine NotClippedByChildren(pWin) returns the unclipped region.</para></listitem>
+<listitem><para>
+borderClip is the region used by CopyWindow and
+includes the area of the window, its children, and the border, but with the
+overlapping areas of sibling children removed.</para></listitem>
+</itemizedlist>
+Most of the other fields are for DIX use only.</para>
+<section>
+<title>Window Procedures in the ScreenRec</title>
+<para>
+You should implement
+all of the following procedures and store pointers to them in the screen record.</para>
+<para>
+The device-independent portion of the server "owns" the window tree.
+However, clever hardware might want to know the relationship of
+mapped windows.  There are pointers to procedures
+in the ScreenRec data structure that are called to give the hardware
+a chance to update its internal state.  These are helpers and
+hints to DDX only;
+they do not change the window tree, which is only changed by DIX.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->CreateWindow(pWin)
+		WindowPtr pWin;
+
+</programlisting></blockquote>
+This routine is a hook for when DIX creates a window.
+It should fill in the "Window Procedures in the WindowRec" below
+and also allocate the devPrivate block for it.</para>
+<para>
+See Xserver/fb/fbwindow.c for the sample server implementation.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->DestroyWindow(pWin);
+		WindowPtr pWin;
+
+</programlisting></blockquote>
+This routine is a hook for when DIX destroys a window.
+It should deallocate the devPrivate block for it and any other blocks that need
+to be freed, besides doing other cleanup actions.</para>
+<para>
+See Xserver/fb/fbwindow.c for the sample server implementation.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->PositionWindow(pWin, x, y);
+		WindowPtr pWin;
+		int x, y;
+
+</programlisting></blockquote>
+This routine is a hook for when DIX moves or resizes a window.
+It should do whatever private operations need to be done when a window is moved or resized.
+For instance, if DDX keeps a pixmap tile used for drawing the background
+or border, and it keeps the tile rotated such that it is longword
+aligned to longword locations in the frame buffer, then you should rotate your tiles here.
+The actual graphics involved in moving the pixels on the screen and drawing the
+border are handled by CopyWindow(), below.</para>
+<para>
+See Xserver/fb/fbwindow.c for the sample server implementation.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->RealizeWindow(pWin);
+		WindowPtr pWin;
+
+	Bool  pScreen->UnrealizeWindow(pWin);
+		WindowPtr pWin;
+
+</programlisting></blockquote>
+These routines are hooks for when DIX maps (makes visible) and unmaps
+(makes invisible) a window.  It should do whatever private operations
+need to be done when these happen, such as allocating or deallocating
+structures that are only needed for visible windows.  RealizeWindow
+does NOT draw the window border, background or contents;
+UnrealizeWindow does NOT erase the window or generate exposure events
+for underlying windows; this is taken care of by DIX.  DIX does,
+however, call PaintWindowBackground() and PaintWindowBorder() to
+perform some of these.</para>
+<para>
+<blockquote><programlisting>
+
+	Bool pScreen->ChangeWindowAttributes(pWin, vmask)
+		WindowPtr pWin;
+		unsigned long vmask;
+
+</programlisting></blockquote>
+ChangeWindowAttributes is called whenever DIX changes window
+attributes, such as the size, front-to-back ordering, title, or
+anything of lesser severity that affects the window itself.  The
+sample server implements this routine.  It computes accelerators for
+quickly putting up background and border tiles.  (See description of
+the set of routines stored in the WindowRec.)</para>
+<para>
+<blockquote><programlisting>
+
+	int pScreen->ValidateTree(pParent,  pChild, kind)
+		WindowPtr pParent, pChild;
+		VTKind kind;
+
+</programlisting></blockquote>
+ValidateTree calculates the clipping region for the parent window and
+all of its children.  This routine must be provided. The sample server
+has a machine-independent version in Xserver/mi/mivaltree.c.  This is
+a very difficult routine to replace.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->PostValidateTree(pParent,  pChild, kind)
+		WindowPtr pParent, pChild;
+		VTKind kind;
+
+</programlisting></blockquote>
+If this routine is not NULL, DIX calls it shortly after calling
+ValidateTree, passing it the same arguments.  This is useful for
+managing multi-layered framebuffers.
+The sample server sets this to NULL.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->WindowExposures(pWin, pRegion, pBSRegion)
+		WindowPtr pWin;
+		RegionPtr pRegion;
+		RegionPtr pBSRegion;
+
+</programlisting></blockquote>
+The WindowExposures() routine
+paints the border and generates exposure events for the window.
+pRegion is an unoccluded region of the window, and pBSRegion is an
+occluded region that has backing store.
+Since exposure events include a rectangle describing what was exposed,
+this routine may have to send back a series of exposure events, one for
+each rectangle of the region.
+The count field in the expose event is a hint to the
+client as to the number of
+regions that are after this one.
+This routine must be provided. The sample
+server has a machine-independent version in Xserver/mi/miexpose.c.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->ClipNotify (pWin, dx, dy)
+		WindowPtr pWin;
+		int dx, dy;
+
+</programlisting></blockquote>
+Whenever the cliplist for a window is changed, this function is called to
+perform whatever hardware manipulations might be necessary.  When called,
+the clip list and border clip regions in the window are set to the new
+values.  dx,dy are the distance that the window has been moved (if at all).</para>
+</section>
+<section>
+  <title>Window Painting Procedures</title>
+<para>
+In addition to the procedures listed above, there are two routines which
+manipulate the actual window image directly.
+In the sample server, mi implementations will work for
+most purposes and fb routines speed up situations, such
+as solid backgrounds/borders or tiles that are 8, 16 or 32 pixels square.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->ClearToBackground(pWin, x, y, w, h, generateExposures);
+		WindowPtr pWin;
+		int x, y, w, h;
+		Bool generateExposures;
+
+</programlisting></blockquote>
+This routine is called on a window in response to a ClearToBackground request
+from the client.
+This request has two different but related functions, depending upon generateExposures.</para>
+<para>
+If generateExposures is true, the client is declaring that the given rectangle
+on the window is incorrectly painted and needs to be repainted.
+The sample server implementation calculates the exposure region
+and hands it to the DIX procedure HandleExposures(), which
+calls the WindowExposures() routine, below, for the window
+and all of its child windows.</para>
+<para>
+If generateExposures is false, the client is trying to simply erase part
+of the window to the background fill style.
+ClearToBackground should write the background color or tile to the
+rectangle in question (probably using PaintWindowBackground).
+If w or h is zero, it clears all the way to the right or lower edge of the window.</para>
+<para>
+The sample server implementation is in Xserver/mi/miwindow.c.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->CopyWindow(pWin, oldpt, oldRegion);
+		WindowPtr pWin;
+		DDXPointRec oldpt;
+		RegionPtr oldRegion;
+
+</programlisting></blockquote>
+CopyWindow is called when a window is moved, and graphically moves to
+pixels of a window on the screen.  It should not change any other
+state within DDX (see PositionWindow(), above).</para>
+<para>
+oldpt is the old location of the upper-left corner.  oldRegion is the
+old region it is coming from.  The new location and new region is
+stored in the WindowRec.  oldRegion might modified in place by this
+routine (the sample implementation does this).</para>
+<para>
+CopyArea could be used, except that this operation has more
+complications.  First of all, you do not want to copy a rectangle onto
+a rectangle.  The original window may be obscured by other windows,
+and the new window location may be similarly obscured.  Second, some
+hardware supports multiple windows with multiple depths, and your
+routine needs to take care of that.</para>
+<para>
+The pixels in oldRegion (with reference point oldpt) are copied to the
+window's new region (pWin->borderClip).  pWin->borderClip is gotten
+directly from the window, rather than passing it as a parameter.</para>
+<para>
+The sample server implementation is in Xserver/fb/fbwindow.c.</para>
+</section>
+<section>
+<title>Screen Operations for Multi-Layered Framebuffers</title>
+<para>
+The following screen functions are useful if you have a framebuffer with
+multiple sets of independent bit planes, e.g. overlays or underlays in
+addition to the "main" planes.  If you have a simple single-layer
+framebuffer, you should probably use the mi versions of these routines
+in mi/miwindow.c.  This can be easily accomplished by calling miScreenInit.</para>
+<para>
+<blockquote><programlisting>
+
+    void pScreen->MarkWindow(pWin)
+	WindowPtr pWin;
+
+</programlisting></blockquote>
+This formerly dix function MarkWindow has moved to ddx and is accessed
+via this screen function.  This function should store something,
+usually a pointer to a device-dependent structure, in pWin->valdata so
+that ValidateTree has the information it needs to validate the window.</para>
+<para>
+<blockquote><programlisting>
+
+    Bool pScreen->MarkOverlappedWindows(parent, firstChild, ppLayerWin)
+	WindowPtr parent;
+	WindowPtr firstChild;
+	WindowPtr * ppLayerWin;
+
+</programlisting></blockquote>
+This formerly dix function MarkWindow has moved to ddx and is accessed
+via this screen function.  In the process, it has grown another
+parameter: ppLayerWin, which is filled in with a pointer to the window
+at which save under marking and ValidateTree should begin.  In the
+single-layered framebuffer case, pLayerWin == pWin.</para>
+<para>
+<blockquote><programlisting>
+
+    Bool pScreen->ChangeSaveUnder(pLayerWin, firstChild)
+	WindowPtr pLayerWin;
+	WindowPtr firstChild;
+
+</programlisting></blockquote>
+The dix functions ChangeSaveUnder and CheckSaveUnder have moved to ddx and
+are accessed via this screen function.  pLayerWin should be the window
+returned in the ppLayerWin parameter of MarkOverlappedWindows.  The function
+may turn on backing store for windows that might be covered, and may partially
+turn off backing store for windows.  It returns TRUE if PostChangeSaveUnder
+needs to be called to finish turning off backing store.</para>
+<para>
+<blockquote><programlisting>
+
+    void pScreen->PostChangeSaveUnder(pLayerWin, firstChild)
+	WindowPtr pLayerWin;
+	WindowPtr firstChild;
+
+</programlisting></blockquote>
+The dix function DoChangeSaveUnder has moved to ddx and is accessed via
+this screen function.  This function completes the job of turning off
+backing store that was started by ChangeSaveUnder.</para>
+<para>
+<blockquote><programlisting>
+
+    void pScreen->MoveWindow(pWin, x, y, pSib, kind)
+	WindowPtr pWin;
+	int x;
+	int y;
+	WindowPtr pSib;
+	VTKind kind;
+
+</programlisting></blockquote>
+The formerly dix function MoveWindow has moved to ddx and is accessed via
+this screen function.  The new position of the window is given by
+x,y.  kind is VTMove if the window is only moving, or VTOther if
+the border is also changing.</para>
+<para>
+<blockquote><programlisting>
+
+    void pScreen->ResizeWindow(pWin, x, y, w, h, pSib)
+	WindowPtr pWin;
+	int x;
+	int y;
+	unsigned int w;
+	unsigned int h;
+	WindowPtr pSib;
+
+</programlisting></blockquote>
+The formerly dix function SlideAndSizeWindow has moved to ddx and is accessed via
+this screen function.  The new position is given by x,y.  The new size
+is given by w,h.</para>
+<para>
+<blockquote><programlisting>
+
+    WindowPtr pScreen->GetLayerWindow(pWin)
+	WindowPtr pWin
+
+</programlisting></blockquote>
+This is a new function which returns a child of the layer parent of pWin.</para>
+<para>
+<blockquote><programlisting>
+
+    void pScreen->HandleExposures(pWin)
+	WindowPtr pWin;
+
+</programlisting></blockquote>
+The formerly dix function HandleExposures has moved to ddx and is accessed via
+this screen function.  This function is called after ValidateTree and
+uses the information contained in valdata to send exposures to windows.</para>
+<para>
+<blockquote><programlisting>
+
+    void pScreen->ReparentWindow(pWin, pPriorParent)
+	WindowPtr pWin;
+	WindowPtr pPriorParent;
+
+</programlisting></blockquote>
+This function will be called when a window is reparented.  At the time of
+the call, pWin will already be spliced into its new position in the
+window tree, and pPriorParent is its previous parent.  This function
+can be NULL.</para>
+<para>
+<blockquote><programlisting>
+
+    void pScreen->SetShape(pWin)
+	WindowPtr pWin;
+
+</programlisting></blockquote>
+The formerly dix function SetShape has moved to ddx and is accessed via
+this screen function.  The window's new shape will have already been
+stored in the window when this function is called.</para>
+<para>
+<blockquote><programlisting>
+
+    void pScreen->ChangeBorderWidth(pWin, width)
+	WindowPtr pWin;
+	unsigned int width;
+
+</programlisting></blockquote>
+The formerly dix function ChangeBorderWidth has moved to ddx and is accessed via
+this screen function.  The new border width is given by width.</para>
+<para>
+<blockquote><programlisting>
+
+    void pScreen->MarkUnrealizedWindow(pChild, pWin, fromConfigure)
+	WindowPtr pChild;
+	WindowPtr pWin;
+	Bool fromConfigure;
+
+</programlisting></blockquote>
+This function is called for windows that are being unrealized as part of
+an UnrealizeTree.  pChild is the window being unrealized, pWin is an
+ancestor, and the fromConfigure value is simply propogated from UnrealizeTree.</para>
+</section>
+</section>
+</section>
+<section>
+<title>Graphics Contexts and Validation</title>
+<para>
+This graphics context (GC) contains state variables such as foreground and
+background pixel value (color), the current line style and width,
+the current tile or stipple for pattern generation, the current font for text
+generation, and other similar attributes.</para>
+<para>
+In many graphics systems, the equivalent of the graphics context and the
+drawable are combined as one entity.
+The main distinction between the two kinds of status is that a drawable
+describes a writing surface and the writings that may have already been done
+on it, whereas a graphics context describes the drawing process.
+A drawable is like a chalkboard.
+A GC is like a piece of chalk.</para>
+<para>
+Unlike many similar systems, there is no "current pen location."
+Every graphic operation is accompanied by the coordinates where it is to happen.</para>
+<para>
+The GC also includes two vectors of procedure pointers, the first
+operate on the GC itself and are called GC funcs.  The second, called
+GC ops,
+contains the functions that carry out the fundamental graphic operations
+such as drawing lines, polygons, arcs, text, and copying bitmaps.
+The DDX graphic software can, if it
+wants to be smart, change these two vectors of procedure pointers
+to take advantage of hardware/firmware in the server machine, which can do
+a better job under certain circumstances.  To reduce the amount of memory
+consumed by each GC, it is wise to create a few "boilerplate" GC ops vectors
+which can be shared by every GC which matches the constraints for that set.
+Also, it is usually reasonable to have every GC created by a particular
+module to share a common set of GC funcs.  Samples of this sort of
+sharing can be seen in fb/fbgc.c.</para>
+<para>
+The DDX software is notified any time the client (or DIX) uses a changed GC.
+For instance, if the hardware has special support for drawing fixed-width
+fonts, DDX can intercept changes to the current font in a GC just before
+drawing is done.  It can plug into either a fixed-width procedure that makes
+the hardware draw characters, or a variable-width procedure that carefully
+lays out glyphs by hand in software, depending upon the new font that is
+selected.</para>
+<para>
+A definition of these structures can be found in the file
+Xserver/include/gcstruct.h.</para>
+<para>
+Also included in each GC is support for dynamic devPrivates, which the
+DDX can use for any purpose (see <xref linkend="wrappers_and_privates"/> below).</para>
+<para>
+The DIX routines available for manipulating GCs are
+CreateGC, ChangeGC, CopyGC, SetClipRects, SetDashes, and FreeGC.
+<blockquote><programlisting>
+
+	GCPtr CreateGC(pDrawable, mask, pval, pStatus)
+	    DrawablePtr pDrawable;
+	    BITS32 mask;
+	    XID *pval;
+	    int *pStatus;
+
+	int ChangeGC(pGC, mask, pval)
+	    GCPtr pGC;
+	    BITS32 mask;
+	    XID *pval;
+
+	int CopyGC(pgcSrc, pgcDst, mask)
+	    GCPtr pgcSrc;
+	    GCPtr pgcDst;
+	    BITS32 mask;
+
+	int SetClipRects(pGC, xOrigin, yOrigin, nrects, prects, ordering)
+	    GCPtr pGC;
+	    int xOrigin, yOrigin;
+	    int nrects;
+	    xRectangle *prects;
+	    int ordering;
+
+	SetDashes(pGC, offset, ndash, pdash)
+	    GCPtr pGC;
+	    unsigned offset;
+	    unsigned ndash;
+	    unsigned char *pdash;
+
+	int FreeGC(pGC, gid)
+	    GCPtr pGC;
+	    GContext gid;
+
+</programlisting></blockquote>
+</para>
+<para>
+As a convenience, each Screen structure contains an array of
+GCs that are preallocated, one at each depth the screen supports.
+These are particularly useful in the mi code.  Two DIX routines
+must be used to get these GCs:
+<blockquote><programlisting>
+
+	GCPtr GetScratchGC(depth, pScreen)
+	    int depth;
+	    ScreenPtr pScreen;
+
+	FreeScratchGC(pGC)
+	    GCPtr pGC;
+
+</programlisting></blockquote>
+Always use these two routines, don't try to extract the scratch
+GC yourself -- someone else might be using it, so a new one must
+be created on the fly.</para>
+<para>
+If you need a GC for a very long time, say until the server is restarted,
+you should not take one from the pool used by GetScratchGC, but should
+get your own using CreateGC or CreateScratchGC.
+This leaves the ones in the pool free for routines that only need it for
+a little while and don't want to pay a heavy cost to get it.
+<blockquote><programlisting>
+
+	GCPtr CreateScratchGC(pScreen, depth)
+	    ScreenPtr pScreen;
+	    int depth;
+
+</programlisting></blockquote>
+NULL is returned if the GC cannot be created.
+The GC returned can be freed with FreeScratchGC.</para>
+<section>
+  <title>Details of Operation</title>
+<para>
+At screen initialization, a screen must supply a GC creation procedure.
+At GC creation, the screen must fill in GC funcs and GC ops vectors
+(Xserver/include/gcstruct.h).  For any particular GC, the func vector
+must remain constant, while the op vector may vary.  This invariant is to
+ensure that Wrappers work correctly.</para>
+<para>
+When a client request is processed that results in a change
+to the GC, the device-independent state of the GC is updated.
+This includes a record of the state that changed.
+Then the ChangeGC GC func is called.
+This is useful for graphics subsystems that are able to process
+state changes in parallel with the server CPU.
+DDX may opt not to take any action at GC-modify time.
+This is more efficient if multiple GC-modify requests occur
+between draws using a given GC.</para>
+<para>
+Validation occurs at the first draw operation that specifies the GC after
+that GC was modified.  DIX calls then the ValidateGC GC func.  DDX should
+then update its internal state.  DDX internal state may be stored as one or
+more of the following:  1) device private block on the GC; 2) hardware
+state; 3) changes to the GC ops.</para>
+<para>
+The GC contains a serial number, which is loaded with a number fetched from
+the window that was drawn into the last time the GC was used.  The serial
+number in the drawable is changed when the drawable's
+clipList or absCorner changes.  Thus, by
+comparing the GC serial number with the drawable serial number, DIX can
+force a validate if the drawable has been changed since the last time it
+was used with this GC.</para>
+<para>
+In addition, the drawable serial number is always guaranteed to have the
+most significant bit set to 0.  Thus, the DDX layer can set the most
+significant bit of the serial number to 1 in a GC to force a validate the next time
+the GC is used.  DIX also uses this technique to indicate that a change has
+been made to the GC by way of a SetGC, a SetDashes or a SetClip request.</para>
+</section>
+<section>
+  <title>GC Handling Routines</title>
+<para>
+The ScreenRec data structure has a pointer for
+CreateGC().
+<blockquote><programlisting>
+
+	Bool pScreen->CreateGC(pGC)
+		GCPtr pGC;
+</programlisting></blockquote>
+This routine must fill in the fields of
+a dynamically allocated GC that is passed in.
+It does NOT allocate the GC record itself or fill
+in the defaults; DIX does that.</para>
+<para>
+This must fill in both the GC funcs and ops; none of the drawing
+functions will be called before the GC has been validated,
+but the others (dealing with allocating of clip regions,
+changing and destroying the GC, etc.) might be.</para>
+<para>
+The GC funcs vector contains pointers to 7
+routines and a devPrivate field:
+<blockquote><programlisting>
+
+	pGC->funcs->ChangeGC(pGC, changes)
+		GCPtr pGC;
+		unsigned long changes;
+
+</programlisting></blockquote>
+This GC func is called immediately after a field in the GC is changed.
+changes is a bit mask indicating the changed fields of the GC in this
+request.</para>
+<para>
+The ChangeGC routine is useful if you have a system where
+state-changes to the GC can be swallowed immediately by your graphics
+system, and a validate is not necessary.</para>
+<para>
+<blockquote><programlisting>
+
+	pGC->funcs->ValidateGC(pGC, changes, pDraw)
+		GCPtr pGC;
+		unsigned long changes;
+		DrawablePtr pDraw;
+
+</programlisting></blockquote>
+ValidateGC is called by DIX just before the GC will be used when one
+of many possible changes to the GC or the graphics system has
+happened.  It can modify devPrivates data attached to the GC,
+change the op vector, or change hardware according to the
+values in the GC.  It may not change the device-independent portion of
+the GC itself.</para>
+<para>
+In almost all cases, your ValidateGC() procedure should take the
+regions that drawing needs to be clipped to and combine them into a
+composite clip region, which you keep a pointer to in the private part
+of the GC.  In this way, your drawing primitive routines (and whatever
+is below them) can easily determine what to clip and where.  You
+should combine the regions clientClip (the region that the client
+desires to clip output to) and the region returned by
+NotClippedByChildren(), in DIX.  An example is in Xserver/fb/fbgc.c.</para>
+<para>
+Some kinds of extension software may cause this routine to be called
+more than originally intended; you should not rely on algorithms that
+will break under such circumstances.</para>
+<para>
+See the Strategies document for more information on creatively using
+this routine.</para>
+<para>
+<blockquote><programlisting>
+
+	pGC->funcs->CopyGC(pGCSrc, mask, pGCDst)
+		GCPtr pGCSrc;
+		unsigned long mask;
+		GCPtr pGCDst;
+
+</programlisting></blockquote>
+This routine is called by DIX when a GC is being copied to another GC.
+This is for situations where dynamically allocated chunks of memory
+are stored in the GC's dynamic devPrivates and need to be transferred to
+the destination GC.</para>
+<para>
+<blockquote><programlisting>
+
+	pGC->funcs->DestroyGC(pGC)
+		GCPtr pGC;
+
+</programlisting></blockquote>
+This routine is called before the GC is destroyed for the
+entity interested in this GC to clean up after itself.
+This routine is responsible for freeing any auxiliary storage allocated.</para>
+</section>
+<section>
+  <title>GC Clip Region Routines</title>
+<para>
+The GC clientClip field requires three procedures to manage it.  These
+procedures are in the GC funcs vector.  The underlying principle is that dix
+knows nothing about the internals of the clipping information, (except when
+it has come from the client), and so calls ddX whenever it needs to copy,
+set, or destroy such information.  It could have been possible for dix not
+to allow ddX to touch the field in the GC, and require it to keep its own
+copy in devPriv, but since clip masks can be very large, this seems like a
+bad idea.  Thus, the server allows ddX to do whatever it wants to the
+clientClip field of the GC, but requires it to do all manipulation itself.</para>
+<para>
+<blockquote><programlisting>
+
+	void pGC->funcs->ChangeClip(pGC, type, pValue, nrects)
+		GCPtr pGC;
+		int type;
+		char *pValue;
+		int nrects;
+
+</programlisting></blockquote>
+This routine is called whenever the client changes the client clip
+region.  The pGC points to the GC involved, the type tells what form
+the region has been sent in.  If type is CT_NONE, then there is no
+client clip.  If type is CT_UNSORTED, CT_YBANDED or CT_YXBANDED, then
+pValue pointer to a list of rectangles, nrects long.  If type is
+CT_REGION, then pValue pointer to a RegionRec from the mi region code.
+If type is CT_PIXMAP pValue is a pointer to a pixmap.  (The defines
+for CT_NONE, etc. are in Xserver/include/gc.h.)  This routine is
+responsible for incrementing any necessary reference counts (e.g. for
+a pixmap clip mask) for the new clipmask and freeing anything that
+used to be in the GC's clipMask field.  The lists of rectangles passed
+in can be freed with Xfree(), the regions can be destroyed with the
+RegionDestroy field in the screen, and pixmaps can be destroyed by
+calling the screen's DestroyPixmap function.  DIX and MI code expect
+what they pass in to this to be freed or otherwise inaccessible, and
+will never look inside what's been put in the GC.  This is a good
+place to be wary of storage leaks.</para>
+<para>
+In the sample server, this routine transforms either the bitmap or the
+rectangle list into a region, so that future routines will have a more
+predictable starting point to work from.  (The validate routine must
+take this client clip region and merge it with other regions to arrive
+at a composite clip region before any drawing is done.)</para>
+<para>
+<blockquote><programlisting>
+
+	void pGC->funcs->DestroyClip(pGC)
+		GCPtr pGC;
+
+</programlisting></blockquote>
+This routine is called whenever the client clip region must be destroyed.
+The pGC points to the GC involved.  This call should set the clipType
+field of the GC to CT_NONE.
+In the sample server, the pointer to the client clip region is set to NULL
+by this routine after destroying the region, so that other software
+(including ChangeClip() above) will recognize that there is no client clip region.</para>
+<para>
+<blockquote><programlisting>
+
+	void pGC->funcs->CopyClip(pgcDst, pgcSrc)
+		GCPtr pgcDst, pgcSrc;
+
+</programlisting></blockquote>
+This routine makes a copy of the clipMask and clipType from pgcSrc
+into pgcDst.  It is responsible for destroying any previous clipMask
+in pgcDst.  The clip mask in the source can be the same as the
+clip mask in the dst (clients do the strangest things), so care must
+be taken when destroying things.  This call is required because dix
+does not know how to copy the clip mask from pgcSrc.</para>
+</section>
+</section>
+<section>
+  <title>Drawing Primitives</title>
+<para>
+The X protocol (rules for the byte stream that goes between client and server)
+does all graphics using primitive
+operations, which are called Drawing Primitives.
+These include line drawing, area filling, arcs, and text drawing.
+Your implementation must supply 16 routines
+to perform these on your hardware.
+(The number 16 is arbitrary.)</para>
+<para>
+More specifically, 16 procedure pointers are in each
+GC op vector.
+At any given time, ALL of them MUST point to a valid procedure that
+attempts to do the operation assigned, although
+the procedure pointers may change and may
+point to different procedures to carry out the same operation.
+A simple server will leave them all pointing to the same 16 routines, while
+a more optimized implementation will switch each from one
+procedure to another, depending upon what is most optimal
+for the current GC and drawable.</para>
+<para>
+The sample server contains a considerable chunk of code called the
+mi (machine independent)
+routines, which serve as drawing primitive routines.
+Many server implementations will be able to use these as-is,
+because they work for arbitrary depths.
+They make no assumptions about the formats of pixmaps
+and frame buffers, since they call a set of routines
+known as the "Pixblit Routines" (see next section).
+They do assume that the way to draw is
+through these low-level routines that apply pixel values rows at a time.
+If your hardware or firmware gives more performance when
+things are done differently, you will want to take this fact into account
+and rewrite some or all of the drawing primitives to fit your needs.</para>
+<section>
+  <title>GC Components</title>
+<para>
+This section describes the fields in the GC that affect each drawing primitive.
+The only primitive that is not affected is GetImage, which does not use a GC
+because its destination is a protocol-style bit image.
+Since each drawing primitive mirrors exactly the X protocol request of the
+same name, you should refer to the X protocol specification document
+for more details.</para>
+<para>
+ALL of these routines MUST CLIP to the
+appropriate regions in the drawable.
+Since there are many regions to clip to simultaneously,
+your ValidateGC routine should combine these into a unified
+clip region to which your drawing routines can quickly refer.
+This is exactly what the fb routines supplied with the sample server
+do.
+The mi implementation passes responsibility for clipping while drawing
+down to the Pixblit routines.</para>
+<para>
+Also, all of them must adhere to the current plane mask.
+The plane mask has one bit for every bit plane in the drawable;
+only planes with 1 bits in the mask are affected by any drawing operation.</para>
+<para>
+All functions except for ImageText calls must obey the alu function.
+This is usually Copy, but could be any of the allowable 16 raster-ops.</para>
+<para>
+All of the functions, except for CopyArea, might use the current
+foreground and background pixel values.
+Each pixel value is 32 bits.
+These correspond to foreground and background colors, but you have
+to run them through the colormap to find out what color the pixel values
+represent.  Do not worry about the color, just apply the pixel value.</para>
+<para>
+The routines that draw lines (PolyLine, PolySegment, PolyRect, and PolyArc)
+use the line width, line style, cap style, and join style.
+Line width is in pixels.
+The line style specifies whether it is solid or dashed, and what kind of dash.
+The cap style specifies whether Rounded, Butt, etc.
+The join style specifies whether joins between joined lines are Miter, Round or Beveled.
+When lines cross as part of the same polyline, they are assumed to be drawn once.
+(See the X protocol specification for more details.)</para>
+<para>
+Zero-width lines are NOT meant to be really zero width; this is the client's way
+of telling you that you can optimize line drawing with little regard to
+the end caps and joins.
+They are called "thin" lines and are meant to be one pixel wide.
+These are frequently done in hardware or in a streamlined assembly language
+routine.</para>
+<para>
+Lines with widths greater than zero, though, must all be drawn with the same
+algorithm, because client software assumes that every jag on every
+line at an angle will come at the same place.
+Two lines that should have
+one pixel in the space between them
+(because of their distance apart and their widths) should have such a one-pixel line
+of space between them if drawn, regardless of angle.</para>
+<para>
+The solid area fill routines (FillPolygon, PolyFillRect, PolyFillArc)
+all use the fill rule, which specifies subtle interpretations of
+what points are inside and what are outside of a given polygon.
+The PolyFillArc routine also uses the arc mode, which specifies
+whether to fill pie segments or single-edge slices of an ellipse.</para>
+<para>
+The line drawing, area fill, and PolyText routines must all
+apply the correct "fill style."
+This can be either a solid foreground color, a transparent stipple,
+an opaque stipple, or a tile.
+Stipples are bitmaps where the 1 bits represent that the foreground color is written,
+and 0 bits represent that either the pixel is left alone (transparent) or that
+the background color is written (opaque).
+A tile is a pixmap of the full depth of the GC that is applied in its full glory to all areas.
+The stipple and tile patterns can be any rectangular size, although some implementations
+will be faster for certain sizes such as 8x8 or 32x32.
+The mi implementation passes this responsibility down to the Pixblit routines.</para>
+<para>
+See the X protocol document for full details.
+The description of the CreateGC request has a very good, detailed description of these
+attributes.</para>
+</section>
+<section>
+<title>The Primitives</title>
+<para>
+The Drawing Primitives are as follows:
+
+<blockquote><programlisting>
+
+	RegionPtr pGC->ops->CopyArea(src, dst, pGC, srcx, srcy, w, h, dstx, dsty)
+		DrawablePtr dst, src;
+		GCPtr pGC;
+		int srcx, srcy, w, h, dstx, dsty;
+
+</programlisting></blockquote>
+CopyArea copies a rectangle of pixels from one drawable to another of
+the same depth.  To effect scrolling, this must be able to copy from
+any drawable to itself, overlapped.  No squeezing or stretching is done
+because the source and destination are the same size.  However,
+everything is still clipped to the clip regions of the destination
+drawable.</para>
+<para>
+If pGC->graphicsExposures is True, any portions of the destination which
+were not valid in the source (either occluded by covering windows, or
+outside the bounds of the drawable) should be collected together and
+returned as a region (if this resultant region is empty, NULL can be
+returned instead).  Furthermore, the invalid bits of the source are
+not copied to the destination and (when the destination is a window)
+are filled with the background tile.  The sample routine
+miHandleExposures generates the appropriate return value and fills the
+invalid area using pScreen->PaintWindowBackground.</para>
+<para>
+For instance, imagine a window that is partially obscured by other
+windows in front of it.  As text is scrolled on your window, the pixels
+that are scrolled out from under obscuring windows will not be
+available on the screen to copy to the right places, and so an exposure
+event must be sent for the client to correctly repaint them.  Of
+course, if you implement backing store, you could do this without resorting
+to exposure events.</para>
+<para>
+An example implementation is fbCopyArea() in Xserver/fb/fbcopy.c.</para>
+<para>
+<blockquote><programlisting>
+
+	RegionPtr pGC->ops->CopyPlane(src, dst, pGC, srcx, srcy, w, h, dstx, dsty, plane)
+		DrawablePtr dst, src;
+		GCPtr pGC;
+		int srcx, srcy, w, h, dstx, dsty;
+		unsigned long plane;
+
+</programlisting></blockquote>
+CopyPlane must copy one plane of a rectangle from the source drawable
+onto the destination drawable.  Because this routine only copies one
+bit out of each pixel, it can copy between drawables of different
+depths.  This is the only way of copying between drawables of
+different depths, except for copying bitmaps to pixmaps and applying
+foreground and background colors to it.  All other conditions of
+CopyArea apply to CopyPlane too.</para>
+<para>
+An example implementation is fbCopyPlane() in
+Xserver/fb/fbcopy.c.</para>
+<para>
+<blockquote><programlisting>
+
+	void pGC->ops->PolyPoint(dst, pGC, mode, n, pPoint)
+		DrawablePtr dst;
+		GCPtr pGC;
+		int mode;
+		int n;
+		DDXPointPtr pPoint;
+
+</programlisting></blockquote>
+PolyPoint draws a set of one-pixel dots (foreground color)
+at the locations given in the array.
+mode is one of the defined constants Origin (absolute coordinates) or Previous
+(each coordinate is relative to the last).
+Note that this does not use the background color or any tiles or stipples.</para>
+<para>
+Example implementations are fbPolyPoint() in Xserver/fb/fbpoint.c and
+miPolyPoint in Xserver/mi/mipolypnt.c.</para>
+<para>
+<blockquote><programlisting>
+
+	void pGC->ops->Polylines(dst, pGC, mode, n, pPoint)
+		DrawablePtr dst;
+		GCPtr pGC;
+		int mode;
+		int n;
+		DDXPointPtr pPoint;
+
+</programlisting></blockquote>
+Similar to PolyPoint, Polylines draws lines between the locations given in the array.
+Zero-width lines are NOT meant to be really zero width; this is the client's way of
+telling you that you can maximally optimize line drawing with little regard to
+the end caps and joins.
+mode is one of the defined constants Previous or Origin, depending upon
+whether the points are each relative to the last or are absolute.</para>
+<para>
+Example implementations are miWideLine() and miWideDash() in
+mi/miwideline.c and miZeroLine() in mi/mizerline.c.</para>
+<para>
+<blockquote><programlisting>
+
+	void pGC->ops->PolySegment(dst, pGC, n, pPoint)
+		DrawablePtr dst;
+		GCPtr pGC;
+		int n;
+		xSegment *pSegments;
+
+</programlisting></blockquote>
+PolySegments draws unconnected
+lines between pairs of points in the array; the array must be of
+even size; no interconnecting lines are drawn.</para>
+<para>
+An example implementation is miPolySegment() in mipolyseg.c.</para>
+<para>
+<blockquote><programlisting>
+
+	void pGC->ops->PolyRectangle(dst, pGC, n, pRect)
+		DrawablePtr dst;
+		GCPtr pGC;
+		int n;
+		xRectangle *pRect;
+
+</programlisting></blockquote>
+PolyRectangle draws outlines of rectangles for each rectangle in the array.</para>
+<para>
+An example implementation is miPolyRectangle() in Xserver/mi/mipolyrect.c.</para>
+<para>
+<blockquote><programlisting>
+
+	void pGC->ops->PolyArc(dst, pGC, n, pArc)
+		DrawablePtr dst;
+		GCPtr pGC;
+		int n;
+		xArc*pArc;
+
+</programlisting></blockquote>
+PolyArc draws connected conic arcs according to the descriptions in the array.
+See the protocol specification for more details.</para>
+<para>
+Example implementations are miZeroPolyArc in Xserver/mi/mizerarc. and
+miPolyArc() in Xserver/mi/miarc.c.</para>
+<para>
+<blockquote><programlisting>
+
+	void pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pPoint)
+		DrawablePtr dst;
+		GCPtr pGC;
+		int shape;
+		int mode;
+		int count;
+		DDXPointPtr pPoint;
+
+</programlisting></blockquote>
+FillPolygon fills a polygon specified by the points in the array
+with the appropriate fill style.
+If necessary, an extra border line is assumed between the starting and ending lines.
+The shape can be used as a hint
+to optimize filling; it indicates whether it is convex (all interior angles
+less than 180), nonconvex (some interior angles greater than 180 but
+border does not cross itself), or complex (border crosses itself).
+You can choose appropriate algorithms or hardware based upon mode.
+mode is one of the defined constants Previous or Origin, depending upon
+whether the points are each relative to the last or are absolute.</para>
+<para>
+An example implementation is miFillPolygon() in Xserver/mi/mipoly.c.</para>
+<para>
+<blockquote><programlisting>
+
+	void pGC->ops->PolyFillRect(dst, pGC, n, pRect)
+		DrawablePtr dst;
+		GCPtr pGC;
+		int n;
+		xRectangle *pRect;
+
+</programlisting></blockquote>
+PolyFillRect fills multiple rectangles.</para>
+<para>
+Example implementations are fbPolyFillRect() in Xserver/fb/fbfillrect.c and
+miPolyFillRect() in Xserver/mi/mifillrct.c.</para>
+<para>
+<blockquote><programlisting>
+
+	void pGC->ops->PolyFillArc(dst, pGC, n, pArc)
+		DrawablePtr dst;
+		GCPtr pGC;
+		int n;
+		xArc *pArc;
+
+</programlisting></blockquote>
+PolyFillArc fills a shape for each arc in the
+list that is bounded by the arc and one or two
+line segments with the current fill style.</para>
+<para>
+An example implementation is miPolyFillArc() in Xserver/mi/mifillarc.c.</para>
+<para>
+<blockquote><programlisting>
+
+	void pGC->ops->PutImage(dst, pGC, depth, x, y, w, h, leftPad, format, pBinImage)
+		DrawablePtr dst;
+		GCPtr pGC;
+		int x, y, w, h;
+		int format;
+		char *pBinImage;
+
+</programlisting></blockquote>
+PutImage copies a pixmap image into the drawable.  The pixmap image
+must be in X protocol format (either Bitmap, XYPixmap, or ZPixmap),
+and format tells the format.  (See the X protocol specification for
+details on these formats).  You must be able to accept all three
+formats, because the client gets to decide which format to send.
+Either the drawable and the pixmap image have the same depth, or the
+source pixmap image must be a Bitmap.  If a Bitmap, the foreground and
+background colors will be applied to the destination.</para>
+<para>
+An example implementation is fbPutImage() in Xserver/fb/fbimage.c.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->GetImage(src, x, y, w, h, format, planeMask, pBinImage)
+		 DrawablePtr src;
+		 int x, y, w, h;
+		 unsigned int format;
+		 unsigned long planeMask;
+		 char *pBinImage;
+
+</programlisting></blockquote>
+GetImage copies the bits from the source drawable into
+the destination pointer.  The bits are written into the buffer
+according to the server-defined pixmap padding rules.
+pBinImage is guaranteed to be big enough to hold all
+the bits that must be written.</para>
+<para>
+This routine does not correspond exactly to the X protocol GetImage
+request, since DIX has to break the reply up into buffers of a size
+requested by the transport layer.  If format is ZPixmap, the bits are
+written in the ZFormat for the depth of the drawable; if there is a 0
+bit in the planeMask for a particular plane, all pixels must have the
+bit in that plane equal to 0.  If format is XYPixmap, planemask is
+guaranteed to have a single bit set; the bits should be written in
+Bitmap format, which is the format for a single plane of an XYPixmap.</para>
+<para>
+An example implementation is miGetImage() in Xserver/mi/mibitblt.c.
+<blockquote><programlisting>
+
+	void pGC->ops->ImageText8(pDraw, pGC, x, y, count, chars)
+		DrawablePtr pDraw;
+		GCPtr pGC;
+		int x, y;
+		int count;
+		char *chars;
+
+</programlisting></blockquote>
+ImageText8 draws text.  The text is drawn in the foreground color; the
+background color fills the remainder of the character rectangles.  The
+coordinates specify the baseline and start of the text.</para>
+<para>
+An example implementation is miImageText8() in Xserver/mi/mipolytext.c.</para>
+<para>
+<blockquote><programlisting>
+
+	int pGC->ops->PolyText8(pDraw, pGC, x, y, count, chars)
+		DrawablePtr pDraw;
+		GCPtr pGC;
+		int x, y;
+		int count;
+		char *chars;
+
+</programlisting></blockquote>
+PolyText8 works like ImageText8, except it draws with
+the current fill style for special effects such as
+shaded text.
+See the X protocol specification for more details.</para>
+<para>
+An example implementation is miPolyText8() in Xserver/mi/mipolytext.c.</para>
+<para>
+<blockquote><programlisting>
+
+	int pGC->ops->PolyText16(pDraw, pGC, x, y, count, chars)
+		DrawablePtr pDraw;
+		GCPtr pGC;
+		int x, y;
+		int count;
+		unsigned short *chars;
+
+	void pGC->ops->ImageText16(pDraw, pGC, x, y, count, chars)
+		DrawablePtr pDraw;
+		GCPtr pGC;
+		int x, y;
+		int count;
+		unsigned short *chars;
+
+</programlisting></blockquote>
+These two routines are the same as the "8" versions,
+except that they are for 16-bit character codes (useful
+for oriental writing systems).</para>
+<para>
+The primary difference is in the way the character information is
+looked up.  The 8-bit and the 16-bit versions obviously have different
+kinds of character values to look up; the main goal of the lookup is
+to provide a pointer to the CharInfo structs for the characters to
+draw and to pass these pointers to the Glyph routines.  Given a
+CharInfo struct, lower-level software can draw the glyph desired with
+little concern for other characteristics of the font.</para>
+<para>
+16-bit character fonts have a row-and-column scheme, where the 2bytes
+of the character code constitute the row and column in a square matrix
+of CharInfo structs.  Each font has row and column minimum and maximum
+values; the CharInfo structures form a two-dimensional matrix.</para>
+<para>
+Example implementations are miPolyText16() and
+miImageText16() in Xserver/mi/mipolytext.c.</para>
+<para>
+See the X protocol specification for more details on these graphic operations.</para>
+<para>
+There is a hook in the GC ops, called LineHelper, that used to be used in the
+sample implementation by the code for wide lines.  It no longer servers any
+purpose in the sample servers, but still exists, #ifdef'ed by NEED_LINEHELPER,
+in case someone needs it.</para>
+</section>
+</section>
+<section>
+  <title>Pixblit Procedures</title>
+<para>
+The Drawing Primitive functions must be defined for your server.
+One possible way to do this is to use the mi routines from the sample server.
+If you choose to use the mi routines (even part of them!) you must implement
+these Pixblit routines.
+These routines read and write pixel values
+and deal directly with the image data.</para>
+<para>
+The Pixblit routines for the sample server are part of the "fb"
+routines.  As with the mi routines, the fb routines are
+portable but are not as portable as the mi routines.</para>
+<para>
+The fb subsystem is a depth-independent framebuffer core, capable of
+operating at any depth from 1 to 32, based on the depth of the window
+or pixmap it is currently operating on.  In particular, this means it
+can support pixmaps of multiple depths on the same screen.  It supplies
+both Pixblit routines and higher-level optimized implementations of the
+Drawing Primitive routines.  It does make the assumption that the pixel
+data it touches is available in the server's address space.</para>
+<para>
+In other words, if you have a "normal" frame buffer type display, you
+can probably use the fb code, and the mi code.  If you
+have a stranger hardware, you will have to supply your own Pixblit
+routines, but you can use the mi routines on top of them.  If you have
+better ways of doing some of the Drawing Primitive functions, then you
+may want to supply some of your own Drawing Primitive routines.  (Even
+people who write their own Drawing Primitives save at least some of
+the mi code for certain special cases that their hardware or library
+or fancy algorithm does not handle.)</para>
+<para>
+The client, DIX, and the machine-independent routines do not carry the
+final responsibility of clipping.  They all depend upon the Pixblit
+routines to do their clipping for them.  The rule is, if you touch the
+frame buffer, you clip.</para>
+<para>
+(The higher level routines may decide to clip at a high level, but
+this is only for increased performance and cannot substitute for
+bottom-level clipping.  For instance, the mi routines, DIX, or the
+client may decide to check all character strings to be drawn and chop
+off all characters that would not be displayed.  If so, it must retain
+the character on the edge that is partly displayed so that the Pixblit
+routines can clip off precisely at the right place.)</para>
+<para>
+To make this easier, all of the reasons to clip can be combined into
+one region in your ValidateGC procedure.  You take this composite clip
+region with you into the Pixblit routines.  (The sample server does
+this.)</para>
+<para>
+Also, FillSpans() has to apply tile and stipple patterns.  The
+patterns are all aligned to the window origin so that when two people
+write patches that are contiguous, they will merge nicely.  (Really,
+they are aligned to the patOrg point in the GC.  This defaults to (0,
+0) but can be set by the client to anything.)</para>
+<para>
+However, the mi routines can translate (relocate) the points from
+window-relative to screen-relative if desired.  If you set the
+miTranslate field in the GC (set it in the CreateGC or ValidateGC
+routine), then the mi output routines will translate all coordinates.
+If it is false, then the coordinates will be passed window-relative.
+Screens with no hardware translation will probably set miTranslate to
+TRUE, so that geometry (e.g. polygons, rectangles) can be translated,
+rather than having the resulting list of scanlines translated; this is
+good because the list vertices in a drawing request will generally be
+much smaller than the list of scanlines it produces.  Similarly,
+hardware that does translation can set miTranslate to FALSE, and avoid
+the extra addition per vertex, which can be (but is not always)
+important for getting the highest possible performance.  (Contrast the
+behavior of GetSpans, which is not expected to be called as often, and
+so has different constraints.)  The miTranslate field is settable in
+each GC, if , for example, you are mixing several kinds of
+destinations (offscreen pixmaps, main memory pixmaps, backing store,
+and windows), all of which have different requirements, on one screen.</para>
+<para>
+As with other drawing routines, there are fields in the GC to direct
+higher code to the correct routine to execute for each function.  In
+this way, you can optimize for special cases, for example, drawing
+solids versus drawing stipples.</para>
+<para>
+The Pixblit routines are broken up into three sets.  The Span routines
+simply fill in rows of pixels.  The Glyph routines fill in character
+glyphs.  The PushPixels routine is a three-input bitblt for more
+sophisticated image creation.</para>
+<para>
+It turns out that the Glyph and PushPixels routines actually have a
+machine-independent implementation that depends upon the Span
+routines.  If you are really pressed for time, you can use these
+versions, although they are quite slow.</para>
+<section>
+<title>Span Routines</title>
+<para>
+For these routines, all graphic operations have been reduced to "spans."
+A span is a horizontal row of pixels.
+If you can design these routines which write into and read from
+rows of pixels at a time, you can use the mi routines.</para>
+<para>
+Each routine takes
+a destination drawable to draw into, a GC to use while drawing,
+the number of spans to do, and two pointers to arrays that indicate the list
+of starting points and the list of widths of spans.</para>
+<para>
+<blockquote><programlisting>
+
+	void pGC->ops->FillSpans(dst, pGC, nSpans, pPoints, pWidths, sorted)
+		DrawablePtr dst;
+		GCPtr pGC;
+		int nSpans;
+		DDXPointPtr pPoints;
+		int *pWidths;
+		int sorted;
+
+</programlisting></blockquote>
+FillSpans should fill horizontal rows of pixels with
+the appropriate patterns, stipples, etc.,
+based on the values in the GC.
+The starting points are in the array at pPoints; the widths are in pWidths.
+If sorted is true, the scan lines are in increasing y order, in which case
+you may be able to make assumptions and optimizations.</para>
+<para>
+GC components: alu, clipOrg, clientClip, and fillStyle.</para>
+<para>
+GC mode-dependent components: fgPixel (for fillStyle Solid); tile, patOrg
+(for fillStyle Tile); stipple, patOrg, fgPixel (for fillStyle Stipple);
+and stipple, patOrg, fgPixel and bgPixel (for fillStyle OpaqueStipple).</para>
+<para>
+<blockquote><programlisting>
+
+	void pGC->ops->SetSpans(pDrawable, pGC, pSrc, ppt, pWidths, nSpans, sorted)
+		DrawablePtr pDrawable;
+		GCPtr pGC;
+		char *pSrc;
+		DDXPointPtr pPoints;
+		int *pWidths;
+		int nSpans;
+		int sorted;
+
+</programlisting></blockquote>
+For each span, this routine should copy pWidths bits from pSrc to
+pDrawable at pPoints using the raster-op from the GC.
+If sorted is true, the scan lines are in increasing y order.
+The pixels in pSrc are
+padded according to the screen's padding rules.
+These
+can be used to support
+interesting extension libraries, for example, shaded primitives.   It does not
+use the tile and stipple.</para>
+<para>
+GC components: alu, clipOrg, and clientClip</para>
+<para>
+The above functions are expected to handle all modifiers in the current
+GC.  Therefore, it is expedient to have
+different routines to quickly handle common special cases
+and reload the procedure pointers
+at validate time, as with the other output functions.</para>
+<para>
+<blockquote><programlisting>
+
+	void pScreen->GetSpans(pDrawable, wMax, pPoints, pWidths, nSpans)
+		DrawablePtr pDrawable;
+		int wMax;
+		DDXPointPtr pPoints;
+		int *pWidths;
+		int nSpans;
+		char *pDst;
+
+</programlisting></blockquote>
+For each span, GetSpans gets bits from the drawable starting at pPoints
+and continuing for pWidths bits.
+Each scanline returned will be server-scanline padded.
+The routine can return NULL if memory cannot be allocated to hold the
+result.</para>
+<para>
+GetSpans never translates -- for a window, the coordinates are already
+screen-relative.  Consider the case of hardware that doesn't do
+translation: the mi code that calls ddX will translate each shape
+(rectangle, polygon,. etc.) before scan-converting it, which requires
+many fewer additions that having GetSpans translate each span does.
+Conversely, consider hardware that does translate: it can set its
+translation point to (0, 0) and get each span, and the only penalty is
+the small number of additions required to translate each shape being
+scan-converted by the calling code.  Contrast the behavior of
+FillSpans and SetSpans (discussed above under miTranslate), which are
+expected to be used more often.</para>
+<para>
+Thus, the penalty to hardware that does hardware translation is
+negligible, and code that wants to call GetSpans() is greatly
+simplified, both for extensions and the machine-independent core
+implementation.</para>
+<section>
+  <title>Glyph Routines</title>
+<para>
+The Glyph routines draw individual character glyphs for text drawing requests.</para>
+<para>
+You have a choice in implementing these routines.  You can use the mi
+versions; they depend ultimately upon the span routines.  Although
+text drawing will work, it will be very slow.</para>
+<para>
+<blockquote><programlisting>
+
+	void pGC->ops->PolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
+		DrawablePtr pDrawable;
+		GCPtr pGC;
+		int x , y;
+		unsigned int nglyph;
+		CharInfoRec **ppci;		/* array of character info */
+		pointer unused;			/* unused since R5 */
+
+</programlisting></blockquote>
+GC components: alu, clipOrg, clientClip, font, and fillStyle.</para>
+<para>
+GC mode-dependent components: fgPixel (for fillStyle Solid); tile, patOrg
+(for fillStyle Tile); stipple, patOrg, fgPixel (for fillStyle Stipple);
+and stipple, patOrg, fgPixel and bgPixel (for fillStyle OpaqueStipple).</para>
+<para>
+<blockquote><programlisting>
+
+	void pGC->ops->ImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
+		DrawablePtr pDrawable;
+		GCPtr pGC;
+		int x , y;
+		unsigned int nglyph;
+		CharInfoRec **ppci;	/* array of character info */
+		pointer unused;		/* unused since R5 */
+
+</programlisting></blockquote>
+GC components: clipOrg, clientClip, font, fgPixel, bgPixel</para>
+<para>
+These routines must copy the glyphs defined by the bitmaps in
+pglyphBase and the font metrics in ppci to the DrawablePtr, pDrawable.
+The poly routine follows all fill, stipple, and tile rules.  The image
+routine simply blasts the glyph onto the glyph's rectangle, in
+foreground and background colors.</para>
+<para>
+More precisely, the Image routine fills the character rectangle with
+the background color, and then the glyph is applied in the foreground
+color.  The glyph can extend outside of the character rectangle.
+ImageGlyph() is used for terminal emulators and informal text purposes
+such as button labels.</para>
+<para>
+The exact specification for the Poly routine is that the glyph is
+painted with the current fill style.  The character rectangle is
+irrelevant for this operation.  PolyText, at a higher level, includes
+facilities for font changes within strings and such; it is to be used
+for WYSIWYG word processing and similar systems.</para>
+<para>
+Both of these routines must clip themselves to the overall clipping region.</para>
+<para>
+Example implementations in mi are miPolyGlyphBlt() and
+miImageGlyphBlt() in Xserver/mi/miglblt.c.</para>
+</section>
+<section>
+<title>PushPixels routine</title>
+<para>
+The PushPixels routine writes the current fill style onto the drawable
+in a certain shape defined by a bitmap.  PushPixels is equivalent to
+using a second stipple.  You can thing of it as pushing the fillStyle
+through a stencil.  PushPixels is not used by any of the mi rendering code,
+but is used by the mi software cursor code.
+<blockquote><para>
+	Suppose the stencil is:	00111100
+	and the stipple is:	10101010
+	PushPixels result:	00101000
+</para></blockquote>
+</para>
+<para>
+You have a choice in implementing this routine.
+You can use the mi version which depends ultimately upon FillSpans().
+Although it will work, it will be slow.</para>
+<para>
+<blockquote><programlisting>
+
+	void pGC->ops->PushPixels(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg)
+		GCPtr pGC;
+		PixmapPtr pBitMap;
+		DrawablePtr pDrawable;
+		int dx, dy, xOrg, yOrg;
+
+</programlisting></blockquote>
+GC components: alu, clipOrg, clientClip, and fillStyle.</para>
+<para>
+GC mode-dependent components: fgPixel (for fillStyle Solid); tile, patOrg
+(for fillStyle Tile); stipple, patOrg, fgPixel (for fillStyle Stipple);
+and stipple, patOrg, fgPixel and bgPixel (for fillStyle OpaqueStipple).</para>
+<para>
+PushPixels applys the foreground color, tile, or stipple from the pGC
+through a stencil onto pDrawable.  pBitMap points to a stencil (of
+which we use an area dx wide by dy high), which is oriented over the
+drawable at xOrg, yOrg.  Where there is a 1 bit in the bitmap, the
+destination is set according to the current fill style.  Where there
+is a 0 bit in the bitmap, the destination is left the way it is.</para>
+<para>
+This routine must clip to the overall clipping region.</para>
+<para>
+An Example implementation is miPushPixels() in Xserver/mi/mipushpxl.c.</para>
+</section>
+</section>
+</section>
+<section>
+  <title>Shutdown Procedures</title>
+<para>
+<blockquote><programlisting>
+	void AbortDDX()
+	void ddxGiveUp()
+</programlisting></blockquote>
+Some hardware may require special work to be done before the server
+exits so that it is not left in an intermediate state.  As explained
+in the OS layer, FatalError() will call AbortDDX() just before
+terminating the server.  In addition, ddxGiveUp() will be called just
+before terminating the server on a "clean" death.  What AbortDDX() and
+ddxGiveUP do is left unspecified, only that stubs must exist in the
+ddx layer.  It is up to local implementors as to what they should
+accomplish before termination.</para>
+<section>
+  <title>Command Line Procedures</title>
+<para>
+<blockquote><programlisting>
+	int ddxProcessArgument(argc, argv, i)
+	    int argc;
+	    char *argv[];
+	    int i;
+
+	void
+	ddxUseMsg()
+
+</programlisting></blockquote>
+You should write these routines to deal with device-dependent command line
+arguments.  The routine ddxProcessArgument() is called with the command line,
+and the current index into argv; you should return zero if the argument
+is not a device-dependent one, and otherwise return a count of the number
+of elements of argv that are part of this one argument.  For a typical
+option (e.g., "-realtime"), you should return the value one.  This
+routine gets called before checks are made against device-independent
+arguments, so it is possible to peek at all arguments or to override
+device-independent argument processing.  You can document the
+device-dependent arguments in ddxUseMsg(), which will be
+called from UseMsg() after printing out the device-independent arguments.</para>
+</section>
+</section>
+<section id="wrappers_and_privates">
+  <title>Wrappers and Privates</title>
+<para>
+Two new extensibility concepts have been developed for release 4, Wrappers
+and devPrivates.  These replace the R3 GCInterest queues, which were not a
+general enough mechanism for many extensions and only provided hooks into a
+single data structure.  devPrivates have been revised substantially for
+X.org X server relase 1.5.</para>
+<section>
+  <title>devPrivates</title>
+<para>
+devPrivates provides a way to attach arbitrary private data to various server structures.
+Any structure which contains a <structfield>devPrivates</structfield> field of
+type <type>PrivateRec</type> supports this mechanism.  Private data can be allocated at
+any time during an object's life cycle and callbacks are available to initialize and clean
+up allocated space.</para>
+<para>
+To attach a piece of private data to an object, use:
+<blockquote><programlisting>
+	int dixSetPrivate(PrivateRec **privates, const DevPrivateKey key, pointer val)
+</programlisting></blockquote>
+The first argument is the address of the <structfield>devPrivates</structfield> field
+in the target structure.  This field is managed privately by the DIX layer and
+should not be directly modified.  The second argument is some address value which
+will serve as the unique identifier for the private data.  Typically this is the address
+of some global variable in your code.  Only one piece of data with a given key can be attached to an object.  However, you
+can use the same key to store data in any object that supports the devPrivates mechanism.  The third
+argument is the value to store.</para>
+<para>
+If private data with the given key is already associated with the object, <function>dixSetPrivate</function> will
+overwrite the old value with the new one.  Otherwise, new space will be allocated to hold the pointer value.
+The function returns <literal>TRUE</literal> unless memory allocation fails, but note that since memory allocation only
+occurs on the first reference to the private data, all subsequent calls are guaranteed to succeed.</para>
+
+<para>
+To look up a piece of private data, use one of:
+<blockquote><programlisting>
+	pointer dixLookupPrivate(PrivateRec **privates, const DevPrivateKey key)
+	pointer *dixLookupPrivateAddr(PrivateRec **privates, const DevPrivateKey key)
+</programlisting></blockquote>
+The first argument is the address of the <structfield>devPrivates</structfield> field
+in the target structure.  The second argument is the key to look up.  If private data with the given key is already associated
+with the object, <function>dixLookupPrivate</function> will return the stored pointer value while <function>dixLookupPrivateAddr</function>
+will return the address of the stored pointer.  Otherwise, new space will be first allocated to hold the pointer value
+and it will be initialized to NULL.  Both functions return <literal>NULL</literal> if memory allocation fails, but note that
+since memory allocation only occurs on the first reference to the private data, all subsequent calls are guaranteed to succeed.</para>
+
+<para>
+To request pre-allocated private space, use
+<blockquote><programlisting>
+	int dixRequestPrivate(const DevPrivateKey key, unsigned size)
+</programlisting></blockquote>
+The first argument is the key for which space is being requested.  The second argument is the size of the space being requested.
+After this function has been called,
+future calls to <function>dixLookupPrivate</function> or <function>dixLookupPrivateAddr</function> that cause the private pointer
+to be initially allocated will also allocate <varname>size</varname> bytes of space cleared to zero and initialize the private pointer to point
+to this space instead of <literal>NULL</literal>.  This space will be automatically freed.  Note that a call to <function>dixSetPrivate</function>
+that changes the pointer value may cause the space to be unreachable by the caller, however it will still be automatically freed.
+The function returns <literal>TRUE</literal> unless memory allocation fails.  If the function is called more than once, the largest value
+of <type>size</type> is used.</para>
+
+<para>
+To set callbacks for initializing and cleaning up private space, use
+<blockquote><programlisting>
+	typedef struct {
+		DevPrivateKey key;
+		pointer *value;
+	} PrivateCallbackRec;
+
+	int dixRegisterPrivateInitFunc(const DevPrivateKey key,
+		CallbackProcPtr callback,
+		pointer userdata)
+	int dixRegisterPrivateDeleteFunc(const DevPrivateKey key,
+		CallbackProcPtr callback,
+		pointer userdata)
+</programlisting></blockquote>
+The first argument is the key for which the callbacks are being registered.  The second argument is the callback function.  The third argument
+will be passed as the user data argument to the callback function when it is called.  The call data argument to the callback is a pointer to
+a structure of type <type>PrivateCallbackRec</type>.</para>
+<para>
+The init callback is called immediately after new private space has been allocated for the given key.  The delete callback is called immediately
+before the private space is freed when the object is being destroyed.  The <type>PrivateCallbackRec</type> structure contains the devPrivate key
+and the address of the private pointer.  The init callback may be used to initialize any pre-allocated space requested by
+<function>dixRequestPrivate</function>, while the delete callback may be used to free any data stored there.  However the callbacks are called even
+if no pre-allocated space was requested.</para>
+
+<para>
+When implementing new server resource objects that support devPrivates, there are three steps to perform:
+Declare a field of type <type>PrivateRec *</type> in your structure;
+initialize this field to <literal>NULL</literal> when creating any objects; and
+call the <function>dixFreePrivates</function> function, passing in the field value, when freeing any objects.</para>
+</section>
+<section>
+  <title>Wrappers</title>
+<para>
+Wrappers are not a body of code, nor an interface spec.  They are, instead,
+a technique for hooking a new module into an existing calling sequence.
+There are limitations on other portions of the server implementation which
+make using wrappers possible; limits on when specific fields of data
+structures may be modified.  They are intended as a replacement for
+GCInterest queues, which were not general enough to support existing
+modules; in particular software cursors needed more
+control over the activity.  The general mechanism for using wrappers is:
+<blockquote><programlisting>
+privateWrapperFunction (object, ...)
+	ObjectPtr	object;
+{
+	pre-wrapped-function-stuff ...
+
+	object->functionVector = dixLookupPrivate(&amp;object->devPrivates, privateKey);
+	(*object->functionVector) (object, ...);
+	/*
+	 * this next line is occasionally required by the rules governing
+	 * wrapper functions.  Always using it will not cause problems.
+	 * Not using it when necessary can cause severe troubles.
+	 */
+	dixSetPrivate(&amp;object->devPrivates, privateKey, object->functionVector);
+	object->functionVector = privateWrapperFunction;
+
+	post-wrapped-function-stuff ...
+}
+
+privateInitialize (object)
+	ObjectPtr	object;
+{
+	dixSetPrivate(&amp;object->devPrivates, privateKey, object->functionVector);
+	object->functionVector = privateWrapperFunction;
+}
+</programlisting></blockquote>
+</para>
+<para>
+Thus the privateWrapperFunction provides hooks for performing work both
+before and after the wrapped function has been called; the process of
+resetting the functionVector is called "unwrapping" while the process of
+fetching the wrapped function and replacing it with the wrapping function
+is called "wrapping".  It should be clear that GCInterest queues could
+be emulated using wrappers.  In general, any function vectors contained in
+objects can be wrapped, but only vectors in GCs and Screens have been tested.</para>
+<para>
+Wrapping screen functions is quite easy; each vector is individually
+wrapped.  Screen functions are not supposed to change after initialization,
+so rewrapping is technically not necessary, but causes no problems.</para>
+<para>
+Wrapping GC functions is a bit more complicated.  GC's have two tables of
+function vectors, one hanging from gc->ops and the other from gc->funcs, which
+should be initially wrapped from a CreateGC wrapper.  Wrappers should modify
+only table pointers, not the contents of the tables, as they
+may be shared by more than one GC (and, in the case of funcs, are probably
+shared by all gcs).  Your func wrappers may change the GC funcs or ops
+pointers, and op wrappers may change the GC op pointers but not the funcs.</para>
+<para>
+Thus, the rule for GC wrappings is: wrap the funcs from CreateGC and, in each
+func wrapper, unwrap the ops and funcs, call down, and re-wrap.  In each op
+wrapper, unwrap the ops, call down, and rewrap afterwards.  Note that in
+re-wrapping you must save out the pointer you're replacing again.  This way the
+chain will be maintained when wrappers adjust the funcs/ops tables they use.</para>
+</section>
+</section>
+<section>
+    <title>Work Queue</title>
+<para>
+To queue work for execution when all clients are in a stable state (i.e.
+just before calling select() in WaitForSomething), call:
+<blockquote><programlisting>
+	Bool QueueWorkProc(function,client,closure)
+		Bool		(*function)();
+		ClientPtr	client;
+		pointer		closure;
+</programlisting></blockquote>
+</para>
+<para>
+When the server is about to suspend itself, the given function will be
+executed:
+<blockquote><programlisting>
+	(*function) (client, closure)
+</programlisting></blockquote>
+</para>
+<para>
+Neither client nor closure are actually used inside the work queue routines.</para>
+</section>
+</section>
+<section>
+  <title>Summary of Routines</title>
+<para>
+This is a summary of the routines discussed in this document.
+The procedure names are in alphabetical order.
+The Struct is the structure it is attached to; if blank, this
+procedure is not attached to a struct and must be named as shown.
+The sample server provides implementations in the following
+categories.  Notice that many of the graphics routines have both
+mi and fb implementations.</para>
+<para>
+<itemizedlist>
+<listitem><para>dix	portable to all systems; do not attempt to rewrite (Xserver/dix)</para></listitem>
+<listitem><para>os	routine provided in Xserver/os or Xserver/include/os.h</para></listitem>
+<listitem><para>ddx	frame buffer dependent (examples in Xserver/fb)</para></listitem>
+<listitem><para>mi	routine provided in Xserver/mi</para></listitem>
+<listitem><para>hd	hardware dependent (examples in many Xserver/hw directories)</para></listitem>
+<listitem><para>none	not implemented in sample implementation</para></listitem>
+</itemizedlist>
+</para>
+	<table frame="all" id="routines-1">
+	  <title>Server Routines (Page 1)</title>
+	  <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+	    <thead>
+	      <row>
+		<entry>Procedure</entry>
+		<entry>Port</entry>
+		<entry>Struct</entry>
+	      </row>
+	    </thead>
+	    <tbody>
+<row><entry><function>ALLOCATE_LOCAL</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>AbortDDX</function></entry><entry><literal>hd</literal></entry><entry><para></para></entry></row>
+<row><entry><function>AddCallback</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>AddEnabledDevice</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>AddInputDevice</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>AddScreen</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>AdjustWaitForDelay</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>Bell</function></entry><entry><literal>hd</literal></entry><entry><para>Device</para></entry></row>
+<row><entry><function>ChangeClip</function></entry><entry><literal>mi</literal></entry><entry><para>GC func</para></entry></row>
+<row><entry><function>ChangeGC</function></entry><entry><literal></literal></entry><entry><para>GC func</para></entry></row>
+<row><entry><function>ChangeWindowAttributes</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>ClearToBackground</function></entry><entry><literal>ddx</literal></entry><entry><para>Window</para></entry></row>
+<row><entry><function>ClientAuthorized</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>ClientSignal</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>ClientSleep</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>ClientWakeup</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>ClipNotify</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>CloseScreen</function></entry><entry><literal>hd</literal></entry><entry><para></para></entry></row>
+<row><entry><function>ConstrainCursor</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>CopyArea</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>CopyGCDest</function></entry><entry><literal>ddx</literal></entry><entry><para>GC func</para></entry></row>
+<row><entry><function>CopyGCSource</function></entry><entry><literal>none</literal></entry><entry><para>GC func</para></entry></row>
+<row><entry><function>CopyPlane</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>CopyWindow</function></entry><entry><literal>ddx</literal></entry><entry><para>Window</para></entry></row>
+<row><entry><function>CreateGC</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>CreateCallbackList</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>CreatePixmap</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>CreateScreenResources</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>CreateWellKnowSockets</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>CreateWindow</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>CursorLimits</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>DEALLOCATE_LOCAL</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>DeleteCallback</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>DeleteCallbackList</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>DestroyClip</function></entry><entry><literal>ddx</literal></entry><entry><para>GC func</para></entry></row>
+<row><entry><function>DestroyGC</function></entry><entry><literal>ddx</literal></entry><entry><para>GC func</para></entry></row>
+<row><entry><function>DestroyPixmap</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>DestroyWindow</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>DisplayCursor</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>Error</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>ErrorF</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>FatalError</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>FillPolygon</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>FillSpans</function></entry><entry><literal>ddx</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>FlushAllOutput</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>FlushIfCriticalOutputPending</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>FreeScratchPixmapHeader</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>GetImage</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>GetMotionEvents</function></entry><entry><literal>hd</literal></entry><entry><para>Device</para></entry></row>
+<row><entry><function>GetScratchPixmapHeader</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>GetSpans</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>GetStaticColormap</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+	    </tbody>
+	  </tgroup>
+	</table>
+
+	<table frame="all" id="routines-2">
+	  <title>Server Routines (Page 2)</title>
+	  <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+	    <thead>
+	      <row>
+		<entry>Procedure</entry>
+		<entry>Port</entry>
+		<entry>Struct</entry>
+	      </row>
+	    </thead>
+	    <tbody>
+<row><entry><function>ImageGlyphBlt</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>ImageText16</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>ImageText8</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>InitInput</function></entry><entry><literal>hd</literal></entry><entry><para></para></entry></row>
+<row><entry><function>InitKeyboardDeviceStruct</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>InitOutput</function></entry><entry><literal>hd</literal></entry><entry><para></para></entry></row>
+<row><entry><function>InitPointerDeviceStruct</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>InsertFakeRequest</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>InstallColormap</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>Intersect</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>Inverse</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>LegalModifier</function></entry><entry><literal>hd</literal></entry><entry><para></para></entry></row>
+<row><entry><function>LineHelper</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>ListInstalledColormaps</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>LookupKeyboardDevice</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>LookupPointerDevice</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>ModifyPixmapheader</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>NextAvailableClient</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>OsInit</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>PaintWindowBackground</function></entry><entry><literal>mi</literal></entry><entry><para>Window</para></entry></row>
+<row><entry><function>PaintWindowBorder</function></entry><entry><literal>mi</literal></entry><entry><para>Window</para></entry></row>
+<row><entry><function>PointerNonInterestBox</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>PointInRegion</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>PolyArc</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>PolyFillArc</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>PolyFillRect</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>PolyGlyphBlt</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>Polylines</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>PolyPoint</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>PolyRectangle</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>PolySegment</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>PolyText16</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>PolyText8</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>PositionWindow</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>ProcessInputEvents</function></entry><entry><literal>hd</literal></entry><entry><para></para></entry></row>
+<row><entry><function>PushPixels</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>PutImage</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>QueryBestSize</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>ReadRequestFromClient</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>RealizeCursor</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>RealizeFont</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>RealizeWindow</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>RecolorCursor</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>RectIn</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>RegionCopy</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>RegionCreate</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>RegionDestroy</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>RegionEmpty</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>RegionExtents</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>RegionNotEmpty</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>RegionReset</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>ResolveColor</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+	    </tbody>
+	  </tgroup>
+	</table>
+
+	<table frame="all" id="routines-3">
+	  <title>Server Routines (Page 3)</title>
+	  <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+	    <thead>
+	      <row>
+		<entry>Procedure</entry>
+		<entry>Port</entry>
+		<entry>Struct</entry>
+	      </row>
+	    </thead>
+	    <tbody>
+<row><entry><function>RegisterKeyboardDevice</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>RegisterPointerDevice</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>RemoveEnabledDevice</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>ResetCurrentRequest</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>SaveScreen</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>SetCriticalOutputPending</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>SetCursorPosition</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>SetInputCheck</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row>
+<row><entry><function>SetSpans</function></entry><entry><literal>ddx</literal></entry><entry><para>GC op</para></entry></row>
+<row><entry><function>StoreColors</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>Subtract</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>TimerCancel</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>TimerCheck</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>TimerForce</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>TimerFree</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>TimerInit</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>TimerSet</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>TimeSinceLastInputEvent</function></entry><entry><literal>hd</literal></entry><entry><para></para></entry></row>
+<row><entry><function>TranslateRegion</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>UninstallColormap</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>Union</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>UnrealizeCursor</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>UnrealizeFont</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>UnrealizeWindow</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>ValidateGC</function></entry><entry><literal>ddx</literal></entry><entry><para>GC func</para></entry></row>
+<row><entry><function>ValidateTree</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row>
+<row><entry><function>WaitForSomething</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>WindowExposures</function></entry><entry><literal>mi</literal></entry><entry><para>Window</para></entry></row>
+<row><entry><function>WriteToClient</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>Xalloc</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>Xfree</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+<row><entry><function>Xrealloc</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row>
+	    </tbody>
+	  </tgroup>
+	</table>
+</section>
+</article>
commit fc6ebe1e1d3057378f61f992549a98e67a04dc6c
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Fri May 14 14:56:09 2010 -0700

    Convert LinuxDoc documents to DocBook/XML
    
    Only the markup/formatting is changed - the contents should still
    be wildly out of date for now.
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Reviewed-by: Rémi Cardona <remi at gentoo.org>
    Tested-by: Gaetan Nadon <memsize at videotron.ca>

diff --git a/configure.ac b/configure.ac
index 4aafceb..41fa63f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -716,10 +716,9 @@ fi
 
 dnl Handle building documentation
 AM_CONDITIONAL(BUILDDOCS, test "x$BUILDDOCS" = xyes)
-
-dnl Only build sgml docs when linuxdoc is available and
-dnl def.ents has been installed
-XORG_CHECK_LINUXDOC
+XORG_ENABLE_DEVEL_DOCS
+XORG_WITH_XMLTO(0.0.20)
+XORG_WITH_FOP
 
 dnl Handle installing libxf86config
 AM_CONDITIONAL(INSTALL_LIBXF86CONFIG, [test "x$INSTALL_LIBXF86CONFIG" = xyes])
diff --git a/doc/xml/xmlrules.in b/doc/xml/xmlrules.in
new file mode 100644
index 0000000..a4d43f9
--- /dev/null
+++ b/doc/xml/xmlrules.in
@@ -0,0 +1,59 @@
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
+
+# This file is included by Makefile.am in subdirectories that have
+# DocBook XML documentation files.
+#
+# No files are automatically distributed or installed by this subset of rules
+# Any files to be distributed or installed would be listed in the including
+# Makefile.am
+
+TXT_FILES  = $(XML_FILES:%.xml=%.txt)
+HTML_FILES = $(XML_FILES:%.xml=%.html)
+PDF_FILES  = $(XML_FILES:%.xml=%.pdf)
+
+BUILT_DOC_FILES =
+
+SUFFIXES = .xml .txt .html .pdf
+
+if HAVE_XMLTO
+BUILT_DOC_FILES += $(TXT_FILES)
+.xml.txt:
+	@rm -f $@
+	$(AM_V_GEN)$(XMLTO) txt $<
+
+BUILT_DOC_FILES += $(HTML_FILES)
+.xml.html:
+	@rm -f $@
+	$(AM_V_GEN)$(XMLTO) xhtml-nochunks $<
+
+if HAVE_FOP
+BUILT_DOC_FILES += $(PDF_FILES)
+.xml.pdf:
+	@rm -f $@
+	$(AM_V_GEN)$(XMLTO) --with-fop pdf $<
+endif
+
+endif
+
+CLEAN_DOC_FILES = $(TXT_FILES) $(HTML_FILES) $(PDF_FILES)
diff --git a/hw/dmx/doc/Makefile.am b/hw/dmx/doc/Makefile.am
index ef7c23d..58306d2 100644
--- a/hw/dmx/doc/Makefile.am
+++ b/hw/dmx/doc/Makefile.am
@@ -19,37 +19,14 @@
 #  NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 #  CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-SGML_FILES = dmx.sgml scaled.sgml
+XML_FILES = dmx.xml scaled.xml
 
-if BUILD_LINUXDOC
-TXT_FILES  = $(SGML_FILES:%.sgml=%.txt)
-PS_FILES   = $(SGML_FILES:%.sgml=%.ps)
-if BUILD_PDFDOC
-PDF_FILES  = $(SGML_FILES:%.sgml=%.pdf)
-endif
-HTML_FILES = $(SGML_FILES:%.sgml=%.html)
-
-SUFFIXES = .sgml .txt .html .ps .pdf
-
-.sgml.txt:
-	@rm -f $@
-	$(AM_V_GEN)$(MAKE_TEXT) $<
-
-.sgml.ps:
-	@rm -f $@
-	$(AM_V_GEN)$(MAKE_PS) $<
-
-.ps.pdf:
-	@rm -f $@
-	$(AM_V_GEN)$(MAKE_PDF) $<
-
-.sgml.html:
-	@rm -f $@
-	$(AM_V_GEN)$(MAKE_HTML) $<
+include ../../../doc/xml/xmlrules.in
 
-noinst_DATA = $(TXT_FILES) $(PS_FILES) $(PDF_FILES) $(HTML_FILES)
-CLEANFILES = $(TXT_FILES) $(PS_FILES) $(PDF_FILES) $(HTML_FILES)
+if ENABLE_DEVEL_DOCS
+noinst_DATA = $(BUILT_DOC_FILES)
 endif
+CLEANFILES = $(CLEAN_DOC_FILES)
 
 if HAVE_DOXYGEN
 
@@ -67,7 +44,7 @@ maintainer-clean-local:
 endif
 
 EXTRA_DIST = \
-	$(SGML_FILES) \
+	$(XML_FILES) \
 	DMXSpec.txt \
 	DMXSpec-v1.txt \
 	dmx.txt \
diff --git a/hw/dmx/doc/dmx.sgml b/hw/dmx/doc/dmx.sgml
deleted file mode 100644
index 6aa0ec5..0000000
--- a/hw/dmx/doc/dmx.sgml
+++ /dev/null
@@ -1,2777 +0,0 @@
-<!DOCTYPE linuxdoc PUBLIC "-//XFree86//DTD linuxdoc//EN">
-  <article>
-
-    <!-- Title information -->
-      <title>Distributed Multihead X design
-      <author>Kevin E. Martin, David H. Dawes, and Rickard E. Faith
-      <date>29 June 2004 (created 25 July 2001)
-      <abstract>
-        This document covers the motivation, background, design, and
-        implementation of the distributed multihead X (DMX) system.  It
-        is a living document and describes the current design and
-        implementation details of the DMX system.  As the project
-        progresses, this document will be continually updated to reflect
-        the changes in the code and/or design.  <it>Copyright 2001 by VA
-        Linux Systems, Inc., Fremont, California.  Copyright 2001-2004
-        by Red Hat, Inc., Raleigh, North Carolina</it>
-      </abstract>
-
-      <!-- Table of contents -->
-    <toc>
-
-<!-- Begin the document -->
-<sect>Introduction
-
-<sect1>The Distributed Multihead X Server
-
-<p>Current Open Source multihead solutions are limited to a single
-physical machine.  A single X server controls multiple display devices,
-which can be arranged as independent heads or unified into a single
-desktop (with Xinerama).  These solutions are limited to the number of
-physical devices that can co-exist in a single machine (e.g., due to the
-number of AGP/PCI slots available for graphics cards).  Thus, large
-tiled displays are not currently possible.  The work described in this
-paper will eliminate the requirement that the display devices reside in
-the same physical machine.  This will be accomplished by developing a
-front-end proxy X server that will control multiple back-end X servers
-that make up the large display.
-
-<p>The overall structure of the distributed multihead X (DMX) project is
-as follows: A single front-end X server will act as a proxy to a set of
-back-end X servers, which handle all of the visible rendering.  X
-clients will connect to the front-end server just as they normally would
-to a regular X server.  The front-end server will present an abstracted
-view to the client of a single large display.  This will ensure that all
-standard X clients will continue to operate without modification
-(limited, as always, by the visuals and extensions provided by the X
-server).  Clients that are DMX-aware will be able to use an extension to
-obtain information about the back-end servers (e.g., for placement of
-pop-up windows, window alignments by the window manager, etc.).
-
-<p>The architecture of the DMX server is divided into two main sections:
-input (e.g., mouse and keyboard events) and output (e.g., rendering and
-windowing requests).  Each of these are describe briefly below, and the
-rest of this design document will describe them in greater detail.
-
-<p>The DMX server can receive input from three general types of input
-devices: "local" devices that are physically attached to the machine on
-which DMX is running, "backend" devices that are physically attached to
-one or more of the back-end X servers (and that generate events via the
-X protocol stream from the backend), and "console" devices that can be
-abstracted from any non-back-end X server.  Backend and console devices
-are treated differently because the pointer device on the back-end X
-server also controls the location of the hardware X cursor.  Full
-support for XInput extension devices is provided.
-
-<p>Rendering requests will be accepted by the front-end server; however,
-rendering to visible windows will be broken down as needed and sent to
-the appropriate back-end server(s) via X11 library calls for actual
-rendering.  The basic framework will follow a Xnest-style approach.  GC
-state will be managed in the front-end server and sent to the
-appropriate back-end server(s) as required.  Pixmap rendering will (at
-least initially) be handled by the front-end X server.  Windowing
-requests (e.g., ordering, mapping, moving, etc.) will handled in the
-front-end server.  If the request requires a visible change, the
-windowing operation will be translated into requests for the appropriate
-back-end server(s).  Window state will be mirrored in the back-end
-server(s) as needed.
-
-<sect1>Layout of Paper
-
-<p>The next section describes the general development plan that was
-actually used for implementation.  The final section discusses
-outstanding issues at the conclusion of development.  The first appendix
-provides low-level technical detail that may be of interest to those
-intimately familiar with the X server architecture.  The final appendix
-describes the four phases of development that were performed during the
-first two years of development.
-
-<p>The final year of work was divided into 9 tasks that are not
-described in specific sections of this document.  The major tasks during
-that time were the enhancement of the reconfiguration ability added in
-Phase IV, addition of support for a dynamic number of back-end displays
-(instead of a hard-coded limit), and the support for back-end display
-and input removal and addition.  This work is mentioned in this paper,
-but is not covered in detail.
-
-<!-- ============================================================ -->
-<sect>Development plan
-
-<p>This section describes the development plan from approximately June
-2001 through July 2003.
-
-<sect1>Bootstrap code
-
-<p>To allow for rapid development of the DMX server by multiple
-developers during the first development stage, the problem will be
-broken down into three tasks: the overall DMX framework, back-end
-rendering services and input device handling services.  However, before
-the work begins on these tasks, a simple framework that each developer
-could use was implemented to bootstrap the development effort.  This
-framework renders to a single back-end server and provides dummy input
-devices (i.e., the keyboard and mouse).  The simple back-end rendering
-service was implemented using the shadow framebuffer support currently
-available in the XFree86 environment.
-
-<p>Using this bootstrapping framework, each developer has been able to
-work on each of the tasks listed above independently as follows: the
-framework will be extended to handle arbitrary back-end server
-configurations; the back-end rendering services will be transitioned to
-the more efficient Xnest-style implementation; and, an input device
-framework to handle various input devices via the input extension will
-be developed.
-
-<p>Status: The boot strap code is complete.  <!-- August 2001 -->
-
-
-<sect1>Input device handling
-
-<p>An X server (including the front-end X server) requires two core
-input devices -- a keyboard and a pointer (mouse).  These core devices
-are handled and required by the core X11 protocol.  Additional types of
-input devices may be attached and utilized via the XInput extension.
-These are usually referred to as ``XInput extension devices'',
-
-<p>There are some options as to how the front-end X server gets its core
-input devices:
-
-<enum>
-    <item>Local Input. The physical input devices (e.g., keyboard and
-    mouse) can be attached directly to the front-end X server.  In this
-    case, the keyboard and mouse on the machine running the front-end X
-    server will be used.  The front-end will have drivers to read the
-    raw input from those devices and convert it into the required X
-    input events (e.g., key press/release, pointer button press/release,
-    pointer motion).  The front-end keyboard driver will keep track of
-    keyboard properties such as key and modifier mappings, autorepeat
-    state, keyboard sound and led state.  Similarly the front-end
-    pointer driver will keep track if pointer properties such as the
-    button mapping and movement acceleration parameters.  With this
-    option, input is handled fully in the front-end X server, and the
-    back-end X servers are used in a display-only mode.  This option was
-    implemented and works for a limited number of Linux-specific
-    devices.  Adding additional local input devices for other
-    architectures is expected to be relatively simple.
-
-    <p>The following options are available for implementing local input
-    devices:
-
-    <enum>
-        <item>The XFree86 X server has modular input drivers that could
-        be adapted for this purpose.  The mouse driver supports a wide
-        range of mouse types and interfaces, as well as a range of
-        Operating System platforms.  The keyboard driver in XFree86 is
-        not currently as modular as the mouse driver, but could be made
-        so.  The XFree86 X server also has a range of other input
-        drivers for extended input devices such as tablets and touch
-        screens.  Unfortunately, the XFree86 drivers are generally
-        complex, often simultaneously providing support for multiple
-        devices across multiple architectures; and rely so heavily on
-        XFree86-specific helper-functions, that this option was not
-        pursued.
-
-
-        <item>The <tt/kdrive/ X server in XFree86 has built-in drivers that
-        support PS/2 mice and keyboard under Linux.  The mouse driver
-        can indirectly handle other mouse types if the Linux utility
-        <tt/gpm/ is used as to translate the native mouse protocol into
-        PS/2 mouse format.  These drivers could be adapted and built in
-        to the front-end X server if this range of hardware and OS
-        support is sufficient.  While much simpler than the XFree86
-        drivers, the <tt/kdrive/ drivers were not used for the DMX
-        implementation.
-
-        <item>Reimplementation of keyboard and mouse drivers from
-        scratch for the DMX framework.  Because keyboard and mouse
-        drivers are relatively trivial to implement, this pathway was
-        selected.  Other drivers in the X source tree were referenced,
-        and significant contributions from other drivers are noted in
-        the DMX source code.
-    </enum>
-
-    <item>Backend Input.  The front-end can make use of the core input
-    devices attached to one or more of the back-end X servers.  Core
-    input events from multiple back-ends are merged into a single input
-    event stream.  This can work sanely when only a single set of input
-    devices is used at any given time.  The keyboard and pointer state
-    will be handled in the front-end, with changes propagated to the
-    back-end servers as needed.  This option was implemented and works
-    well.  Because the core pointer on a back-end controls the hardware
-    mouse on that back-end, core pointers cannot be treated as XInput
-    extension devices.  However, all back-end XInput extensions devices
-    can be mapped to either DMX core or DMX XInput extension devices.
-
-    <item>Console Input.  The front-end server could create a console
-    window that is displayed on an X server independent of the back-end
-    X servers.  This console window could display things like the
-    physical screen layout, and the front-end could get its core input
-    events from events delivered to the console window.  This option was
-    implemented and works well.  To help the human navigate, window
-    outlines are also displayed in the console window.  Further, console
-    windows can be used as either core or XInput extension devices.
-
-    <item>Other options were initially explored, but they were all
-    partial subsets of the options listed above and, hence, are
-    irrelevant.
-
-</enum>
-
-<p>Although extended input devices are not specifically mentioned in the
-Distributed X requirements, the options above were all implemented so
-that XInput extension devices were supported.
-
-<p>The bootstrap code (Xdmx) had dummy input devices, and these are
-still supported in the final version.  These do the necessary
-initialization to satisfy the X server's requirements for core pointer
-and keyboard devices, but no input events are ever generated.
-
-<p>Status: The input code is complete.  Because of the complexity of the
-XFree86 input device drivers (and their heavy reliance on XFree86
-infrastructure), separate low-level device drivers were implemented for
-Xdmx.  The following kinds of drivers are supported (in general, the
-devices can be treated arbitrarily as "core" input devices or as XInput
-"extension" devices; and multiple instances of different kinds of
-devices can be simultaneously available):
-    <enum>
-        <item> A "dummy" device drive that never generates events.
-
-        <item> "Local" input is from the low-level hardware on which the
-        Xdmx binary is running.  This is the only area where using the
-        XFree86 driver infrastructure would have been helpful, and then
-        only partially, since good support for generic USB devices does
-        not yet exist in XFree86 (in any case, XFree86 and kdrive driver
-        code was used where possible).  Currently, the following local
-        devices are supported under Linux (porting to other operating
-        systems should be fairly straightforward):
-        <itemize>
-            <item>Linux keyboard
-            <item>Linux serial mouse (MS)
-            <item>Linux PS/2 mouse
-            <item>USB keyboard
-            <item>USB mouse
-            <item>USB generic device (e.g., joystick, gamepad, etc.)
-        </itemize>
-
-        <item> "Backend" input is taken from one or more of the back-end
-        displays.  In this case, events are taken from the back-end X
-        server and are converted to Xdmx events.  Care must be taken so
-        that the sprite moves properly on the display from which input
-        is being taken.
-
-        <item> "Console" input is taken from an X window that Xdmx
-        creates on the operator's display (i.e., on the machine running
-        the Xdmx binary).  When the operator's mouse is inside the
-        console window, then those events are converted to Xdmx events.
-        Several special features are available: the console can display
-        outlines of windows that are on the Xdmx display (to facilitate
-        navigation), the cursor can be confined to the console, and a
-        "fine" mode can be activated to allow very precise cursor
-        positioning.
-    </enum>
-
-
-<!-- May 2002; July 2003 -->
-
-<sect1>Output device handling
-
-<p>The output of the DMX system displays rendering and windowing
-requests across multiple screens.  The screens are typically arranged in
-a grid such that together they represent a single large display.
-
-<p>The output section of the DMX code consists of two parts.  The first
-is in the front-end proxy X server (Xdmx), which accepts client
-connections, manages the windows, and potentially renders primitives but
-does not actually display any of the drawing primitives.  The second
-part is the back-end X server(s), which accept commands from the
-front-end server and display the results on their screens.
-
-<sect2>Initialization
-
-<p>The DMX front-end must first initialize its screens by connecting to
-each of the back-end X servers and collecting information about each of
-these screens.  However, the information collected from the back-end X
-servers might be inconsistent.  Handling these cases can be difficult
-and/or inefficient.  For example, a two screen system has one back-end X
-server running at 16bpp while the second is running at 32bpp.
-Converting rendering requests (e.g., XPutImage() or XGetImage()
-requests) to the appropriate bit depth can be very time consuming.
-Analyzing these cases to determine how or even if it is possible to
-handle them is required.  The current Xinerama code handles many of
-these cases (e.g., in PanoramiXConsolidate()) and will be used as a
-starting point.  In general, the best solution is to use homogeneous X
-servers and display devices.  Using back-end servers with the same depth
-is a requirement of the final DMX implementation.
-
-<p>Once this screen consolidation is finished, the relative position of
-each back-end X server's screen in the unified screen is initialized.  A
-full-screen window is opened on each of the back-end X servers, and the
-cursor on each screen is turned off.  The final DMX implementation can
-also make use of a partial-screen window, or multiple windows per
-back-end screen.
-
-<sect2>Handling rendering requests
-
-<p>After initialization, X applications connect to the front-end server.
-There are two possible implementations of how rendering and windowing
-requests are handled in the DMX system:
-
-<enum>
-    <item>A shadow framebuffer is used in the front-end server as the
-    render target.  In this option, all protocol requests are completely
-    handled in the front-end server.  All state and resources are
-    maintained in the front-end including a shadow copy of the entire
-    framebuffer.  The framebuffers attached to the back-end servers are
-    updated by XPutImage() calls with data taken directly from the
-    shadow framebuffer.
-
-    <p>This solution suffers from two main problems.  First, it does not
-    take advantage of any accelerated hardware available in the system.
-    Second, the size of the XPutImage() calls can be quite large and
-    thus will be limited by the bandwidth available.
-
-    <p>The initial DMX implementation used a shadow framebuffer by
-    default.
-
-    <item>Rendering requests are sent to each back-end server for
-    handling (as is done in the Xnest server described above).  In this
-    option, certain protocol requests are handled in the front-end
-    server and certain requests are repackaged and then sent to the
-    back-end servers.  The framebuffer is distributed across the
-    multiple back-end servers.  Rendering to the framebuffer is handled
-    on each back-end and can take advantage of any acceleration
-    available on the back-end servers' graphics display device.  State
-    is maintained both in the front and back-end servers.
-
-    <p>This solution suffers from two main drawbacks.  First, protocol
-    requests are sent to all back-end servers -- even those that will
-    completely clip the rendering primitive -- which wastes bandwidth
-    and processing time.  Second, state is maintained both in the front-
-    and back-end servers.  These drawbacks are not as severe as in
-    option 1 (above) and can either be overcome through optimizations or
-    are acceptable.  Therefore, this option will be used in the final
-    implementation.
-
-    <p>The final DMX implementation defaults to this mechanism, but also
-    supports the shadow framebuffer mechanism.  Several optimizations
-    were implemented to eliminate the drawbacks of the default
-    mechanism.  These optimizations are described the section below and
-    in Phase II of the Development Results (see appendix).
-
-</enum>
-
-<p>Status: Both the shadow framebuffer and Xnest-style code is complete.
-<!-- May 2002 -->
-
-
-<sect1>Optimizing DMX
-
-<p>Initially, the Xnest-style solution's performance will be measured
-and analyzed to determine where the performance bottlenecks exist.
-There are four main areas that will be addressed.
-
-<p>First, to obtain reasonable interactivity with the first development
-phase, XSync() was called after each protocol request.  The XSync()
-function flushes any pending protocol requests.  It then waits for the
-back-end to process the request and send a reply that the request has
-completed.  This happens with each back-end server and performance
-greatly suffers.  As a result of the way XSync() is called in the first
-development phase, the batching that the X11 library performs is
-effectively defeated.  The XSync() call usage will be analyzed and
-optimized by batching calls and performing them at regular intervals,
-except where interactivity will suffer (e.g., on cursor movements).
-
-<p>Second, the initial Xnest-style solution described above sends the
-repackaged protocol requests to all back-end servers regardless of
-whether or not they would be completely clipped out.  The requests that
-are trivially rejected on the back-end server wastes the limited
-bandwidth available.  By tracking clipping changes in the DMX X server's
-windowing code (e.g., by opening, closing, moving or resizing windows),
-we can determine whether or not back-end windows are visible so that
-trivial tests in the front-end server's GC ops drawing functions can
-eliminate these unnecessary protocol requests.
-
-<p>Third, each protocol request will be analyzed to determine if it is
-possible to break the request into smaller pieces at display boundaries.
-The initial ones to be analyzed are put and get image requests since
-they will require the greatest bandwidth to transmit data between the
-front and back-end servers.  Other protocol requests will be analyzed
-and those that will benefit from breaking them into smaller requests
-will be implemented.
-
-<p>Fourth, an extension is being considered that will allow font glyphs to
-be transferred from the front-end DMX X server to each back-end server.
-This extension will permit the front-end to handle all font requests and
-eliminate the requirement that all back-end X servers share the exact
-same fonts as the front-end server.  We are investigating the
-feasibility of this extension during this development phase.
-
-<p>Other potential optimizations will be determined from the performance
-analysis.
-
-<p>Please note that in our initial design, we proposed optimizing BLT
-operations (e.g., XCopyArea() and window moves) by developing an
-extension that would allow individual back-end servers to directly copy
-pixel data to other back-end servers.  This potential optimization was
-in response to the simple image movement implementation that required
-potentially many calls to GetImage() and PutImage().  However, the
-current Xinerama implementation handles these BLT operations
-differently.  Instead of copying data to and from screens, they generate
-expose events -- just as happens in the case when a window is moved from
-off a screen to on screen.  This approach saves the limited bandwidth
-available between front and back-end servers and is being standardized
-with Xinerama.  It also eliminates the potential setup problems and
-security issues resulting from having each back-end server open
-connections to all other back-end servers.  Therefore, we suggest
-accepting Xinerama's expose event solution.
-
-<p>Also note that the approach proposed in the second and third
-optimizations might cause backing store algorithms in the back-end to be
-defeated, so a DMX X server configuration flag will be added to disable
-these optimizations.
-
-<p>Status: The optimizations proposed above are complete.  It was
-determined that the using the xfs font server was sufficient and
-creating a new mechanism to pass glyphs was redundant; therefore, the
-fourth optimization proposed above was not included in DMX.
-<!-- September 2002 -->
-
-
-<sect1>DMX X extension support
-
-<p>The DMX X server keeps track of all the windowing information on the
-back-end X servers, but does not currently export this information to
-any client applications.  An extension will be developed to pass the
-screen information and back-end window IDs to DMX-aware clients.  These
-clients can then use this information to directly connect to and render
-to the back-end windows.  Bypassing the DMX X server allows DMX-aware
-clients to break up complex rendering requests on their own and send
-them directly to the windows on the back-end server's screens.  An
-example of a client that can make effective use of this extension is
-Chromium.
-
-<p>Status: The extension, as implemented, is fully documented in
-"Client-to-Server DMX Extension to the X Protocol".  Future changes
-might be required based on feedback and other proposed enhancements to
-DMX.  Currently, the following facilities are supported:
-<enum>
-    <item>
-        Screen information (clipping rectangle for each screen relative
-        to the virtual screen)
-    <item>
-        Window information (window IDs and clipping information for each
-        back-end window that corresponds to each DMX window)
-    <item>
-        Input device information (mappings from DMX device IDs to
-        back-end device IDs)
-    <item>
-        Force window creation (so that a client can override the
-        server-side lazy window creation optimization)
-    <item>
-        Reconfiguration (so that a client can request that a screen
-        position be changed)
-    <item>
-        Addition and removal of back-end servers and back-end and
-        console inputs.
-</enum>
-<!-- September 2002; July 2003 -->
-
-
-<sect1>Common X extension support
-
-<p>The XInput, XKeyboard and Shape extensions are commonly used
-extensions to the base X11 protocol.  XInput allows multiple and
-non-standard input devices to be accessed simultaneously.  These input
-devices can be connected to either the front-end or back-end servers.
-XKeyboard allows much better keyboard mappings control.  Shape adds
-support for arbitrarily shaped windows and is used by various window
-managers.  Nearly all potential back-end X servers make these extensions
-available, and support for each one will be added to the DMX system.
-
-<p>In addition to the extensions listed above, support for the X
-Rendering extension (Render) is being developed.  Render adds digital
-image composition to the rendering model used by the X Window System.
-While this extension is still under development by Keith Packard of HP,
-support for the current version will be added to the DMX system.
-
-<p>Support for the XTest extension was added during the first
-development phase.
-
-<!-- WARNING: this list is duplicated in the Phase IV discussion -->
-<p>Status: The following extensions are supported and are discussed in
-more detail in Phase IV of the Development Results (see appendix):
-    BIG-REQUESTS,
-    DEC-XTRAP,
-    DMX,
-    DPMS,
-    Extended-Visual-Information,
-    GLX,
-    LBX,
-    RECORD,
-    RENDER,
-    SECURITY,
-    SHAPE,
-    SYNC,
-    X-Resource,
-    XC-APPGROUP,
-    XC-MISC,
-    XFree86-Bigfont,
-    XINERAMA,
-    XInputExtension,
-    XKEYBOARD, and
-    XTEST.
-<!-- November 2002; updated February 2003, July 2003 -->
-
-<sect1>OpenGL support
-
-<p>OpenGL support using the Mesa code base exists in XFree86 release 4
-and later.  Currently, the direct rendering infrastructure (DRI)
-provides accelerated OpenGL support for local clients and unaccelerated
-OpenGL support (i.e., software rendering) is provided for non-local
-clients.
-
-<p>The single head OpenGL support in XFree86 4.x will be extended to use
-the DMX system.  When the front and back-end servers are on the same
-physical hardware, it is possible to use the DRI to directly render to
-the back-end servers.  First, the existing DRI will be extended to
-support multiple display heads, and then to support the DMX system.
-OpenGL rendering requests will be direct rendering to each back-end X
-server.  The DRI will request the screen layout (either from the
-existing Xinerama extension or a DMX-specific extension).  Support for
-synchronized swap buffers will also be added (on hardware that supports
-it).  Note that a single front-end server with a single back-end server
-on the same physical machine can emulate accelerated indirect rendering.
-
-<p>When the front and back-end servers are on different physical
-hardware or are using non-XFree86 4.x X servers, a mechanism to render
-primitives across the back-end servers will be provided.  There are
-several options as to how this can be implemented.
-
-<enum>
-    <item>The existing OpenGL support in each back-end server can be
-    used by repackaging rendering primitives and sending them to each
-    back-end server.  This option is similar to the unoptimized
-    Xnest-style approach mentioned above.  Optimization of this solution
-    is beyond the scope of this project and is better suited to other
-    distributed rendering systems.
-
-    <item>Rendering to a pixmap in the front-end server using the
-    current XFree86 4.x code, and then displaying to the back-ends via
-    calls to XPutImage() is another option.  This option is similar to
-    the shadow frame buffer approach mentioned above.  It is slower and
-    bandwidth intensive, but has the advantage that the back-end servers
-    are not required to have OpenGL support.
-</enum>
-
-<p>These, and other, options will be investigated in this phase of the
-work.
-
-<p>Work by others have made Chromium DMX-aware.  Chromium will use the
-DMX X protocol extension to obtain information about the back-end
-servers and will render directly to those servers, bypassing DMX.
-
-<p>Status: OpenGL support by the glxProxy extension was implemented by
-SGI and has been integrated into the DMX code base.
-<!-- May 2003-->
-
-
-<!-- ============================================================ -->
-<sect>Current issues
-
-<p>In this sections the current issues are outlined that require further
-investigation.
-
-<sect1>Fonts
-
-<p>The font path and glyphs need to be the same for the front-end and
-each of the back-end servers.  Font glyphs could be sent to the back-end
-servers as necessary but this would consume a significant amount of
-available bandwidth during font rendering for clients that use many
-different fonts (e.g., Netscape).  Initially, the font server (xfs) will
-be used to provide the fonts to both the front-end and back-end servers.
-Other possibilities will be investigated during development.
-
-<sect1>Zero width rendering primitives
-
-<p>To allow pixmap and on-screen rendering to be pixel perfect, all
-back-end servers must render zero width primitives exactly the same as
-the front-end renders the primitives to pixmaps.  For those back-end
-servers that do not exactly match, zero width primitives will be
-automatically converted to one width primitives.  This can be handled in
-the front-end server via the GC state.
-
-<sect1>Output scaling
-
-<p>With very large tiled displays, it might be difficult to read the
-information on the standard X desktop.  In particular, the cursor can be
-easily lost and fonts could be difficult to read.  Automatic primitive
-scaling might prove to be very useful.  We will investigate the
-possibility of scaling the cursor and providing a set of alternate
-pre-scaled fonts to replace the standard fonts that many applications
-use (e.g., fixed).  Other options for automatic scaling will also be
-investigated.
-
-<sect1>Per-screen colormaps
-
-<p>Each screen's default colormap in the set of back-end X servers
-should be able to be adjusted via a configuration utility.  This support
-is would allow the back-end screens to be calibrated via custom gamma
-tables.  On 24-bit systems that support a DirectColor visual, this type
-of correction can be accommodated.  One possible implementation would be
-to advertise to X client of the DMX server a TrueColor visual while
-using DirectColor visuals on the back-end servers to implement this type
-of color correction.  Other options will be investigated.
-
-<!-- ============================================================ -->
-<appendix>
-
-<sect>Background
-
-<p>This section describes the existing Open Source architectures that
-can be used to handle multiple screens and upon which this development
-project is based.  This section was written before the implementation
-was finished, and may not reflect actual details of the implementation.
-It is left for historical interest only.
-
-<sect1>Core input device handling
-
-<p>The following is a description of how core input devices are handled
-by an X server.
-
-<sect2>InitInput()
-
-<p>InitInput() is a DDX function that is called at the start of each
-server generation from the X server's main() function.  Its purpose is
-to determine what input devices are connected to the X server, register
-them with the DIX and MI layers, and initialize the input event queue.
-InitInput() does not have a return value, but the X server will abort if
-either a core keyboard device or a core pointer device are not
-registered.  Extended input (XInput) devices can also be registered in
-InitInput().
-
-<p>InitInput() usually has implementation specific code to determine
-which input devices are available.  For each input device it will be
-using, it calls AddInputDevice():
-
-<descrip>
-<tag/AddInputDevice()/ This DIX function allocates the device structure,
-registers a callback function (which handles device init, close, on and
-off), and returns the input handle, which can be treated as opaque.  It
-is called once for each input device.
-</descrip>
-
-<p>Once input handles for core keyboard and core pointer devices have
-been obtained from AddInputDevice(), they are registered as core devices
-by calling RegisterPointerDevice() and RegisterKeyboardDevice().  Each
-of these should be called once.  If both core devices are not
-registered, then the X server will exit with a fatal error when it
-attempts to start the input devices in InitAndStartDevices(), which is
-called directly after InitInput() (see below).
-
-<descrip>
-<tag/Register{Pointer,Keyboard}Device()/ These DIX functions take a
-handle returned from AddInputDevice() and initialize the core input
-device fields in inputInfo, and initialize the input processing and grab
-functions for each core input device.
-</descrip>
-
-<p>The core pointer device is then registered with the miPointer code
-(which does the high level cursor handling).  While this registration
-is not necessary for correct miPointer operation in the current XFree86
-code, it is still done mostly for compatibility reasons.
-
-<descrip>
-<tag/miRegisterPointerDevice()/ This MI function registers the core
-pointer's input handle with with the miPointer code.
-</descrip>
-
-<p>The final part of InitInput() is the initialization of the input
-event queue handling.  In most cases, the event queue handling provided
-in the MI layer is used.  The primary XFree86 X server uses its own
-event queue handling to support some special cases related to the XInput
-extension and the XFree86-specific DGA extension.  For our purposes, the
-MI event queue handling should be suitable.  It is initialized by
-calling mieqInit():
-
-<descrip>
-<tag/mieqInit()/ This MI function initializes the MI event queue for the
-core devices, and is passed the public component of the input handles
-for the two core devices.
-</descrip>
-
-<p>If a wakeup handler is required to deliver synchronous input
-events, it can be registered here by calling the DIX function
-RegisterBlockAndWakeupHandlers().  (See the devReadInput() description
-below.)
-
-<sect2>InitAndStartDevices()
-
-<p>InitAndStartDevices() is a DIX function that is called immediately
-after InitInput() from the X server's main() function.  Its purpose is
-to initialize each input device that was registered with
-AddInputDevice(), enable each input device that was successfully
-initialized, and create the list of enabled input devices.  Once each
-registered device is processed in this way, the list of enabled input
-devices is checked to make sure that both a core keyboard device and
-core pointer device were registered and successfully enabled.  If not,
-InitAndStartDevices() returns failure, and results in the the X server
-exiting with a fatal error.
-
-<p>Each registered device is initialized by calling its callback
-(dev-&gt;deviceProc) with the DEVICE_INIT argument:
-
-<descrip>
-<tag/(*dev-&gt;deviceProc)(dev, DEVICE_INIT)/ This function initializes the
-device structs with core information relevant to the device.
-
-<p>For pointer devices, this means specifying the number of buttons,
-default button mapping, the function used to get motion events (usually
-miPointerGetMotionEvents()), the function used to change/control the
-core pointer motion parameters (acceleration and threshold), and the
-motion buffer size.
-
-<p>For keyboard devices, this means specifying the keycode range,
-default keycode to keysym mapping, default modifier mapping, and the
-functions used to sound the keyboard bell and modify/control the
-keyboard parameters (LEDs, bell pitch and duration, key click, which
-keys are auto-repeating, etc).
-</descrip>
-
-<p>Each initialized device is enabled by calling EnableDevice():
-
-<descrip>
-<tag/EnableDevice()/ EnableDevice() calls the device callback with
-DEVICE_ON:
-    <descrip>
-    <tag/(*dev-&gt;deviceProc)(dev, DEVICE_ON)/ This typically opens and
-    initializes the relevant physical device, and when appropriate,
-    registers the device's file descriptor (or equivalent) as a valid
-    input source.
-    </descrip>
-
-    <p>EnableDevice() then adds the device handle to the X server's
-    global list of enabled devices.
-</descrip>
-
-<p>InitAndStartDevices() then verifies that a valid core keyboard and
-pointer has been initialized and enabled.  It returns failure if either
-are missing.
-
-<sect2>devReadInput()
-
-<p>Each device will have some function that gets called to read its
-physical input.  These may be called in a number of different ways.  In
-the case of synchronous I/O, they will be called from a DDX
-wakeup-handler that gets called after the server detects that new input is
-available.  In the case of asynchronous I/O, they will be called from a
-(SIGIO) signal handler triggered when new input is available.  This
-function should do at least two things: make sure that input events get
-enqueued, and make sure that the cursor gets moved for motion events
-(except if these are handled later by the driver's own event queue
-processing function, which cannot be done when using the MI event queue
-handling).
-
-<p>Events are queued by calling mieqEnqueue():
-
-<descrip>
-<tag/mieqEnqueue()/ This MI function is used to add input events to the
-event queue.  It is simply passed the event to be queued.
-</descrip>
-
-<p>The cursor position should be updated when motion events are
-enqueued, by calling either miPointerAbsoluteCursor() or
-miPointerDeltaCursor():
-
-<descrip>
-<tag/miPointerAbsoluteCursor()/ This MI function is used to move the
-cursor to the absolute coordinates provided.
-<tag/miPointerDeltaCursor()/ This MI function is used to move the cursor
-relative to its current position.
-</descrip>
-
-<sect2>ProcessInputEvents()
-
-<p>ProcessInputEvents() is a DDX function that is called from the X
-server's main dispatch loop when new events are available in the input
-event queue.  It typically processes the enqueued events, and updates
-the cursor/pointer position.  It may also do other DDX-specific event
-processing.
-
-<p>Enqueued events are processed by mieqProcessInputEvents() and passed
-to the DIX layer for transmission to clients:
-
-<descrip>
-<tag/mieqProcessInputEvents()/ This function processes each event in the
-event queue, and passes it to the device's input processing function.
-The DIX layer provides default functions to do this processing, and they
-handle the task of getting the events passed back to the relevant
-clients.
-<tag/miPointerUpdate()/ This function resynchronized the cursor position
-with the new pointer position.  It also takes care of moving the cursor
-between screens when needed in multi-head configurations.
-</descrip>
-
-
-<sect2>DisableDevice()
-
-<p>DisableDevice is a DIX function that removes an input device from the
-list of enabled devices.  The result of this is that the device no
-longer generates input events.  The device's data structures are kept in
-place, and disabling a device like this can be reversed by calling
-EnableDevice().  DisableDevice() may be called from the DDX when it is
-desirable to do so (e.g., the XFree86 server does this when VT
-switching).  Except for special cases, this is not normally called for
-core input devices.
-
-<p>DisableDevice() calls the device's callback function with
-<tt/DEVICE_OFF/:
-
-<descrip>
-<tag/(*dev-&gt;deviceProc)(dev, DEVICE_OFF)/ This typically closes the
-relevant physical device, and when appropriate, unregisters the device's
-file descriptor (or equivalent) as a valid input source.
-</descrip>
-
-<p>DisableDevice() then removes the device handle from the X server's
-global list of enabled devices.
-
-
-<sect2>CloseDevice()
-
-<p>CloseDevice is a DIX function that removes an input device from the
-list of available devices.  It disables input from the device and frees
-all data structures associated with the device.  This function is
-usually called from CloseDownDevices(), which is called from main() at
-the end of each server generation to close all input devices.
-
-<p>CloseDevice() calls the device's callback function with
-<tt/DEVICE_CLOSE/:
-
-<descrip>
-<tag/(*dev-&gt;deviceProc)(dev, DEVICE_CLOSE)/ This typically closes the
-relevant physical device, and when appropriate, unregisters the device's
-file descriptor (or equivalent) as a valid input source.  If any device
-specific data structures were allocated when the device was initialized,
-they are freed here.
-</descrip>
-
-<p>CloseDevice() then frees the data structures that were allocated
-for the device when it was registered/initialized.
-
-
-<sect2>LegalModifier()
-<!-- dmx/dmxinput.c - currently returns TRUE -->           
-<p>LegalModifier() is a required DDX function that can be used to
-restrict which keys may be modifier keys.  This seems to be present for
-historical reasons, so this function should simply return TRUE
-unconditionally.
-
-
-<sect1>Output handling
-
-<p>The following sections describe the main functions required to
-initialize, use and close the output device(s) for each screen in the X
-server.
-
-<sect2>InitOutput()
-
-<p>This DDX function is called near the start of each server generation
-from the X server's main() function.  InitOutput()'s main purpose is to
-initialize each screen and fill in the global screenInfo structure for
-each screen.  It is passed three arguments: a pointer to the screenInfo
-struct, which it is to initialize, and argc and argv from main(), which
-can be used to determine additional configuration information.
-
-<p>The primary tasks for this function are outlined below:
-
-<enum>
-    <item><bf/Parse configuration info:/ The first task of InitOutput()
-    is to parses any configuration information from the configuration
-    file.  In addition to the XF86Config file, other configuration
-    information can be taken from the command line.  The command line
-    options can be gathered either in InitOutput() or earlier in the
-    ddxProcessArgument() function, which is called by
-    ProcessCommandLine().  The configuration information determines the
-    characteristics of the screen(s).  For example, in the XFree86 X
-    server, the XF86Config file specifies the monitor information, the
-    screen resolution, the graphics devices and slots in which they are
-    located, and, for Xinerama, the screens' layout.
-
-    <item><bf/Initialize screen info:/ The next task is to initialize
-    the screen-dependent internal data structures.  For example, part of
-    what the XFree86 X server does is to allocate its screen and pixmap
-    private indices, probe for graphics devices, compare the probed
-    devices to the ones listed in the XF86Config file, and add the ones that
-    match to the internal xf86Screens&lsqb;&rsqb; structure.
-
-    <item><bf/Set pixmap formats:/ The next task is to initialize the
-    screenInfo's image byte order, bitmap bit order and bitmap scanline
-    unit/pad.  The screenInfo's pixmap format's depth, bits per pixel
-    and scanline padding is also initialized at this stage.
-
-    <item><bf/Unify screen info:/ An optional task that might be done at
-    this stage is to compare all of the information from the various
-    screens and determines if they are compatible (i.e., if the set of
-    screens can be unified into a single desktop).  This task has
-    potential to be useful to the DMX front-end server, if Xinerama's
-    PanoramiXConsolidate() function is not sufficient.
-</enum>
-
-<p>Once these tasks are complete, the valid screens are known and each
-of these screens can be initialized by calling AddScreen().
-
-<sect2>AddScreen()
-
-<p>This DIX function is called from InitOutput(), in the DDX layer, to
-add each new screen to the screenInfo structure.  The DDX screen
-initialization function and command line arguments (i.e., argc and argv)
-are passed to it as arguments.
-
-<p>This function first allocates a new Screen structure and any privates
-that are required.  It then initializes some of the fields in the Screen
-struct and sets up the pixmap padding information.  Finally, it calls
-the DDX screen initialization function ScreenInit(), which is described
-below.  It returns the number of the screen that were just added, or -1
-if there is insufficient memory to add the screen or if the DDX screen
-initialization fails.
-
-<sect2>ScreenInit()
-
-<p>This DDX function initializes the rest of the Screen structure with
-either generic or screen-specific functions (as necessary).  It also
-fills in various screen attributes (e.g., width and height in
-millimeters, black and white pixel values).
-
-<p>The screen init function usually calls several functions to perform
-certain screen initialization functions.  They are described below:
-
-<descrip>
-<tag/{mi,*fb}ScreenInit()/ The DDX layer's ScreenInit() function usually
-calls another layer's ScreenInit() function (e.g., miScreenInit() or
-fbScreenInit()) to initialize the fallbacks that the DDX driver does not
-specifically handle.
-
-<p>After calling another layer's ScreenInit() function, any
-screen-specific functions either wrap or replace the other layer's
-function pointers.  If a function is to be wrapped, each of the old
-function pointers from the other layer are stored in a screen private
-area.  Common functions to wrap are CloseScreen() and SaveScreen().
-
-<tag/miInitializeBackingStore()/ This MI function initializes the
-screen's backing storage functions, which are used to save areas of
-windows that are currently covered by other windows.
-
-<tag/miDCInitialize()/ This MI function initializes the MI cursor
-display structures and function pointers.  If a hardware cursor is used,
-the DDX layer's ScreenInit() function will wrap additional screen and
-the MI cursor display function pointers.
-</descrip>
-
-<p>Another common task for ScreenInit() function is to initialize the
-output device state.  For example, in the XFree86 X server, the
-ScreenInit() function saves the original state of the video card and
-then initializes the video mode of the graphics device.
-
-<sect2>CloseScreen()
-
-<p>This function restores any wrapped screen functions (and in
-particular the wrapped CloseScreen() function) and restores the state of
-the output device to its original state.  It should also free any
-private data it created during the screen initialization.
-
-<sect2>GC operations
-
-<p>When the X server is requested to render drawing primitives, it does
-so by calling drawing functions through the graphics context's operation
-function pointer table (i.e., the GCOps functions).  These functions
-render the basic graphics operations such as drawing rectangles, lines,
-text or copying pixmaps.  Default routines are provided either by the MI
-layer, which draws indirectly through a simple span interface, or by the
-framebuffer layers (e.g., CFB, MFB, FB), which draw directly to a
-linearly mapped frame buffer.
-
-<p>To take advantage of special hardware on the graphics device,
-specific GCOps functions can be replaced by device specific code.
-However, many times the graphics devices can handle only a subset of the
-possible states of the GC, so during graphics context validation,
-appropriate routines are selected based on the state and capabilities of
-the hardware.  For example, some graphics hardware can accelerate single
-pixel width lines with certain dash patterns.  Thus, for dash patterns
-that are not supported by hardware or for width 2 or greater lines, the
-default routine is chosen during GC validation.
-
-<p>Note that some pointers to functions that draw to the screen are
-stored in the Screen structure.  They include GetImage(), GetSpans(),
-CopyWindow() and RestoreAreas().
-
-<sect2>Xnest
-
-<p>The Xnest X server is a special proxy X server that relays the X
-protocol requests that it receives to a ``real'' X server that then
-processes the requests and displays the results, if applicable.  To the X
-applications, Xnest appears as if it is a regular X server.  However,
-Xnest is both server to the X application and client of the real X
-server, which will actually handle the requests.
-
-<p>The Xnest server implements all of the standard input and output
-initialization steps outlined above.
-
-<descrip>
-<tag/InitOutput()/ Xnest takes its configuration information from
-command line arguments via ddxProcessArguments().  This information
-includes the real X server display to connect to, its default visual
-class, the screen depth, the Xnest window's geometry, etc.  Xnest then
-connects to the real X server and gathers visual, colormap, depth and
-pixmap information about that server's display, creates a window on that
-server, which will be used as the root window for Xnest.
-
-<p>Next, Xnest initializes its internal data structures and uses the
-data from the real X server's pixmaps to initialize its own pixmap
-formats.  Finally, it calls AddScreen(xnestOpenScreen, argc, argv) to
-initialize each of its screens.
-
-<tag/ScreenInit()/ Xnest's ScreenInit() function is called
-xnestOpenScreen().  This function initializes its screen's depth and
-visual information, and then calls miScreenInit() to set up the default
-screen functions.  It then calls miInitializeBackingStore() and
-miDCInitialize() to initialize backing store and the software cursor.
-Finally, it replaces many of the screen functions with its own
-functions that repackage and send the requests to the real X server to
-which Xnest is attached.
-
-<tag/CloseScreen()/ This function frees its internal data structure
-allocations.  Since it replaces instead of wrapping screen functions,
-there are no function pointers to unwrap.  This can potentially lead to
-problems during server regeneration.
-
-<tag/GC operations/ The GC operations in Xnest are very simple since
-they leave all of the drawing to the real X server to which Xnest is
-attached.  Each of the GCOps takes the request and sends it to the
-real X server using standard Xlib calls.  For example, the X
-application issues a XDrawLines() call.  This function turns into a
-protocol request to Xnest, which calls the xnestPolylines() function
-through Xnest's GCOps function pointer table.  The xnestPolylines()
-function is only a single line, which calls XDrawLines() using the same
-arguments that were passed into it.  Other GCOps functions are very
-similar.  Two exceptions to the simple GCOps functions described above
-are the image functions and the BLT operations.
-
-<p>The image functions, GetImage() and PutImage(), must use a temporary
-image to hold the image to be put of the image that was just grabbed
-from the screen while it is in transit to the real X server or the
-client.  When the image has been transmitted, the temporary image is
-destroyed.
-
-<p>The BLT operations, CopyArea() and CopyPlane(), handle not only the
-copy function, which is the same as the simple cases described above,
-but also the graphics exposures that result when the GC's graphics
-exposure bit is set to True.  Graphics exposures are handled in a helper
-function, xnestBitBlitHelper().  This function collects the exposure
-events from the real X server and, if any resulting in regions being
-exposed, then those regions are passed back to the MI layer so that it
-can generate exposure events for the X application.
-</descrip>
-
-<p>The Xnest server takes its input from the X server to which it is
-connected.  When the mouse is in the Xnest server's window, keyboard and
-mouse events are received by the Xnest server, repackaged and sent back
-to any client that requests those events.
-
-<sect2>Shadow framebuffer
-
-<p>The most common type of framebuffer is a linear array memory that
-maps to the video memory on the graphics device.  However, accessing
-that video memory over an I/O bus (e.g., ISA or PCI) can be slow.  The
-shadow framebuffer layer allows the developer to keep the entire
-framebuffer in main memory and copy it back to video memory at regular
-intervals.  It also has been extended to handle planar video memory and
-rotated framebuffers.
-
-<p>There are two main entry points to the shadow framebuffer code:
-
-<descrip>
-<tag/shadowAlloc(width, height, bpp)/ This function allocates the in
-memory copy of the framebuffer of size width*height*bpp.  It returns a
-pointer to that memory, which will be used by the framebuffer
-ScreenInit() code during the screen's initialization.
-
-<tag/shadowInit(pScreen, updateProc, windowProc)/ This function
-initializes the shadow framebuffer layer.  It wraps several screen
-drawing functions, and registers a block handler that will update the
-screen.  The updateProc is a function that will copy the damaged regions
-to the screen, and the windowProc is a function that is used when the
-entire linear video memory range cannot be accessed simultaneously so
-that only a window into that memory is available (e.g., when using the
-VGA aperture).
-</descrip>
-
-<p>The shadow framebuffer code keeps track of the damaged area of each
-screen by calculating the bounding box of all drawing operations that
-have occurred since the last screen update.  Then, when the block handler
-is next called, only the damaged portion of the screen is updated.
-
-<p>Note that since the shadow framebuffer is kept in main memory, all
-drawing operations are performed by the CPU and, thus, no accelerated
-hardware drawing operations are possible.
-
-
-<sect1>Xinerama
-
-<p>Xinerama is an X extension that allows multiple physical screens
-controlled by a single X server to appear as a single screen.  Although
-the extension allows clients to find the physical screen layout via
-extension requests, it is completely transparent to clients at the core
-X11 protocol level.  The original public implementation of Xinerama came
-from Digital/Compaq.  XFree86 rewrote it, filling in some missing pieces
-and improving both X11 core protocol compliance and performance.  The
-Xinerama extension will be passing through X.Org's standardization
-process in the near future, and the sample implementation will be based
-on this rewritten version.
-
-<p>The current implementation of Xinerama is based primarily in the DIX
-(device independent) and MI (machine independent) layers of the X
-server.  With few exceptions the DDX layers do not need any changes to
-support Xinerama.  X server extensions often do need modifications to
-provide full Xinerama functionality.
-
-<p>The following is a code-level description of how Xinerama functions.
-
-<p>Note: Because the Xinerama extension was originally called the
-PanoramiX extension, many of the Xinerama functions still have the
-PanoramiX prefix.
-
-<descrip>
-    <tag/PanoramiXExtensionInit()/ PanoramiXExtensionInit() is a
-    device-independent extension function that is called at the start of
-    each server generation from InitExtensions(), which is called from
-    the X server's main() function after all output devices have been
-    initialized, but before any input devices have been initialized.
-
-    <p>PanoramiXNumScreens is set to the number of physical screens.  If
-    only one physical screen is present, the extension is disabled, and
-    PanoramiXExtensionInit() returns without doing anything else.
-
-    <p>The Xinerama extension is registered by calling AddExtension().
-    
-    <p>A local per-screen array of data structures
-    (panoramiXdataPtr&lsqb;&rsqb;)
-    is allocated for each physical screen, and GC and Screen private
-    indexes are allocated, and both GC and Screen private areas are
-    allocated for each physical screen.  These hold Xinerama-specific
-    per-GC and per-Screen data.  Each screen's CreateGC and CloseScreen
-    functions are wrapped by XineramaCreateGC() and
-    XineramaCloseScreen() respectively.  Some new resource classes are
-    created for Xinerama drawables and GCs, and resource types for
-    Xinerama windows, pixmaps and colormaps.
-
-    <p>A region (XineramaScreenRegions&lsqb;i&rsqb;) is initialized for each
-    physical screen, and single region (PanoramiXScreenRegion) is
-    initialized to be the union of the screen regions.  The
-    panoramiXdataPtr&lsqb;&rsqb; array is also initialized with the size and
-    origin of each screen.  The relative positioning information for the
-    physical screens is taken from the array
-    dixScreenOrigins&lsqb;&rsqb;, which
-    the DDX layer must initialize in InitOutput().  The bounds of the
-    combined screen is also calculated (PanoramiXPixWidth and
-    PanoramiXPixHeight).
-
-    <p>The DIX layer has a list of function pointers
-    (ProcVector&lsqb;&rsqb;) that
-    holds the entry points for the functions that process core protocol
-    requests.  The requests that Xinerama must intercept and break up
-    into physical screen-specific requests are wrapped.  The original
-    set is copied to SavedProcVector&lsqb;&rsqb;.  The types of requests
-    intercepted are Window requests, GC requests, colormap requests,
-    drawing requests, and some geometry-related requests.  This wrapping
-    allows the bulk of the protocol request processing to be handled
-    transparently to the DIX layer.  Some operations cannot be dealt with
-    in this way and are handled with Xinerama-specific code within the
-    DIX layer.
-
-    <tag/PanoramiXConsolidate()/ PanoramiXConsolidate() is a
-    device-independent extension function that is called directly from
-    the X server's main() function after extensions and input/output
-    devices have been initialized, and before the root windows are
-    defined and initialized.
-
-    <p>This function finds the set of depths (PanoramiXDepths&lsqb;&rsqb;) and
-    visuals (PanoramiXVisuals&lsqb;&rsqb;)
-    common to all of the physical screens.
-    PanoramiXNumDepths is set to the number of common depths, and
-    PanoramiXNumVisuals is set to the number of common visuals.
-    Resources are created for the single root window and the default
-    colormap.  Each of these resources has per-physical screen entries.
-
-    <tag/PanoramiXCreateConnectionBlock()/ PanoramiXConsolidate() is a
-    device-independent extension function that is called directly from
-    the X server's main() function after the per-physical screen root
-    windows are created.  It is called instead of the standard DIX
-    CreateConnectionBlock() function.  If this function returns FALSE,
-    the X server exits with a fatal error.  This function will return
-    FALSE if no common depths were found in PanoramiXConsolidate().
-    With no common depths, Xinerama mode is not possible.
-
-    <p>The connection block holds the information that clients get when
-    they open a connection to the X server.  It includes information
-    such as the supported pixmap formats, number of screens and the
-    sizes, depths, visuals, default colormap information, etc, for each
-    of the screens (much of information that <tt/xdpyinfo/ shows).  The
-    connection block is initialized with the combined single screen
-    values that were calculated in the above two functions.
-
-    <p>The Xinerama extension allows the registration of connection
-    block callback functions.  The purpose of these is to allow other
-    extensions to do processing at this point.  These callbacks can be
-    registered by calling XineramaRegisterConnectionBlockCallback() from
-    the other extension's ExtensionInit() function.  Each registered
-    connection block callback is called at the end of
-    PanoramiXCreateConnectionBlock().
-</descrip>
-
-<sect2>Xinerama-specific changes to the DIX code
-
-<p>There are a few types of Xinerama-specific changes within the DIX
-code.  The main ones are described here.
-
-<p>Functions that deal with colormap or GC -related operations outside of
-the intercepted protocol requests have a test added to only do the
-processing for screen numbers > 0.  This is because they are handled for
-the single Xinerama screen and the processing is done once for screen 0.
-
-<p>The handling of motion events does some coordinate translation between
-the physical screen's origin and screen zero's origin.  Also, motion
-events must be reported relative to the composite screen origin rather
-than the physical screen origins.
-
-<p>There is some special handling for cursor, window and event processing
-that cannot (either not at all or not conveniently) be done via the
-intercepted protocol requests.  A particular case is the handling of
-pointers moving between physical screens.
-
-<sect2>Xinerama-specific changes to the MI code
-
-<p>The only Xinerama-specific change to the MI code is in miSendExposures()
-to handle the coordinate (and window ID) translation for expose events.
-
-<sect2>Intercepted DIX core requests
-
-<p>Xinerama breaks up drawing requests for dispatch to each physical
-screen.  It also breaks up windows into pieces for each physical screen.
-GCs are translated into per-screen GCs.  Colormaps are replicated on
-each physical screen.  The functions handling the intercepted requests
-take care of breaking the requests and repackaging them so that they can
-be passed to the standard request handling functions for each screen in
-turn.  In addition, and to aid the repackaging, the information from
-many of the intercepted requests is used to keep up to date the
-necessary state information for the single composite screen.  Requests
-(usually those with replies) that can be satisfied completely from this
-stored state information do not call the standard request handling
-functions.
-
-<!-- ============================================================ -->
-
-<sect>Development Results
-
-<p>In this section the results of each phase of development are
-discussed.  This development took place between approximately June 2001
-and July 2003.
-
-<sect1>Phase I
-
-<p>The initial development phase dealt with the basic implementation
-including the bootstrap code, which used the shadow framebuffer, and the
-unoptimized implementation, based on an Xnest-style implementation.
-
-<sect2>Scope
-
-<p>The goal of Phase I is to provide fundamental functionality that can
-act as a foundation for ongoing work:
-<enum>
-    <item>Develop the proxy X server
-    <itemize>
-	<item>The proxy X server will operate on the X11 protocol and
-	relay requests as necessary to correctly perform the request.
-	<item>Work will be based on the existing work for Xinerama and
-	Xnest.
-	<item>Input events and windowing operations are handled in the
-	proxy server and rendering requests are repackaged and sent to
-	each of the back-end servers for display.
-	<item>The multiple screen layout (including support for
-	overlapping screens) will be user configurable via a
-	configuration file or through the configuration tool.
-    </itemize>
-    <item>Develop graphical configuration tool
-    <itemize>
-	<item>There will be potentially a large number of X servers to
-	configure into a single display.  The tool will allow the user
-	to specify which servers are involved in the configuration and
-	how they should be laid out.
-    </itemize>
-    <item>Pass the X Test Suite
-    <itemize>
-	<item>The X Test Suite covers the basic X11 operations.  All
-	tests known to succeed must correctly operate in the distributed
-	X environment.
-    </itemize>
-</enum>
-
-<p>For this phase, the back-end X servers are assumed to be unmodified X
-servers that do not support any DMX-related protocol extensions; future
-optimization pathways are considered, but are not implemented; and the
-configuration tool is assumed to rely only on libraries in the X source
-tree (e.g., Xt).
-
-<sect2>Results
-
-<p>The proxy X server, Xdmx, was developed to distribute X11 protocol
-requests to the set of back-end X servers.  It opens a window on each
-back-end server, which represents the part of the front-end's root
-window that is visible on that screen.  It mirrors window, pixmap and
-other state in each back-end server.  Drawing requests are sent to
-either windows or pixmaps on each back-end server.  This code is based
-on Xnest and uses the existing Xinerama extension.
-
-<p>Input events can be taken from (1) devices attached to the back-end
-server, (2) core devices attached directly to the Xdmx server, or (3)
-from a ``console'' window on another X server.  Events for these devices
-are gathered, processed and delivered to clients attached to the Xdmx
-server.
-
-<p>An intuitive configuration format was developed to help the user
-easily configure the multiple back-end X servers.  It was defined (see
-grammar in Xdmx man page) and a parser was implemented that is used by
-the Xdmx server and by a standalone xdmxconfig utility.  The parsing
-support was implemented such that it can be easily factored out of the X
-source tree for use with other tools (e.g., vdl).  Support for
-converting legacy vdl-format configuration files to the DMX format is
-provided by the vdltodmx utility.
-
-<p>Originally, the configuration file was going to be a subsection of
-XFree86's XF86Config file, but that was not possible since Xdmx is a
-completely separate X server.  Thus, a separate config file format was
-developed.  In addition, a graphical configuration
-tool, xdmxconfig, was developed to allow the user to create and arrange
-the screens in the configuration file.  The <bf/-configfile/ and <bf/-config/
-command-line options can be used to start Xdmx using a configuration
-file.
-
-<p>An extension that enables remote input testing is required for the X
-Test Suite to function.  During this phase, this extension (XTEST) was
-implemented in the Xdmx server.  The results from running the X Test
-Suite are described in detail below.
-
-<sect2>X Test Suite
-
-          <sect3> Introduction
-            <p>
-              The X Test Suite contains tests that verify Xlib functions
-              operate correctly.  The test suite is designed to run on a
-              single X server; however, since X applications will not be
-              able to tell the difference between the DMX server and a
-              standard X server, the X Test Suite should also run on the
-              DMX server.
-            <p>
-              The Xdmx server was tested with the X Test Suite, and the
-              existing failures are noted in this section.  To put these
-              results in perspective, we first discuss expected X Test
-              failures and how errors in underlying systems can impact
-              Xdmx test results.
-
-          <sect3>Expected Failures for a Single Head
-            <p>
-              A correctly implemented X server with a single screen is
-              expected to fail certain X Test tests.  The following
-              well-known errors occur because of rounding error in the X
-              server code:
-              <verb>
-XDrawArc: Tests 42, 63, 66, 73
-XDrawArcs: Tests 45, 66, 69, 76
-              </verb>
-            <p>
-              The following failures occur because of the high-level X
-              server implementation:
-              <verb>
-XLoadQueryFont: Test 1
-XListFontsWithInfo: Tests 3, 4
-XQueryFont: Tests 1, 2
-              </verb>
-            <p>
-              The following test fails when running the X server as root
-              under Linux because of the way directory modes are
-              interpreted:
-              <verb>
-XWriteBitmapFile: Test 3
-              </verb>
-            <p>
-              Depending on the video card used for the back-end, other
-              failures may also occur because of bugs in the low-level
-              driver implementation.  Over time, failures of this kind
-              are usually fixed by XFree86, but will show up in Xdmx
-              testing until then.
-
-          <sect3>Expected Failures for Xinerama
-            <p>
-              Xinerama fails several X Test Suite tests because of
-              design decisions made for the current implementation of
-              Xinerama.  Over time, many of these errors will be
-              corrected by XFree86 and the group working on a new
-              Xinerama implementation.  Therefore, Xdmx will also share
-              X Suite Test failures with Xinerama.
-            <p>
-              We may be able to fix or work-around some of these
-              failures at the Xdmx level, but this will require
-              additional exploration that was not part of Phase I.
-            <p>
-              Xinerama is constantly improving, and the list of
-              Xinerama-related failures depends on XFree86 version and
-              the underlying graphics hardware.  We tested with a
-              variety of hardware, including nVidia, S3, ATI Radeon,
-              and Matrox G400 (in dual-head mode).  The list below
-              includes only those failures that appear to be from the
-              Xinerama layer, and does not include failures listed in
-              the previous section, or failures that appear to be from
-              the low-level graphics driver itself:
-            <p>
-              These failures were noted with multiple Xinerama
-              configurations:
-              <verb>
-XCopyPlane: Tests 13, 22, 31 (well-known Xinerama implementation issue)
-XSetFontPath: Test 4
-XGetDefault: Test 5
-XMatchVisualInfo: Test 1
-              </verb>
-            <p>
-              These failures were noted only when using one dual-head
-              video card with a 4.2.99.x XFree86 server:
-              <verb>
-XListPixmapFormats: Test 1
-XDrawRectangles: Test 45
-              </verb>
-            <p>
-              These failures were noted only when using two video cards
-              from different vendors with a 4.1.99.x XFree86 server:
-              <verb>
-XChangeWindowAttributes: Test 32
-XCreateWindow: Test 30
-XDrawLine: Test 22
-XFillArc: Test 22
-XChangeKeyboardControl: Tests 9, 10
-XRebindKeysym: Test 1
-              </verb>
-
-          <sect3>Additional Failures from Xdmx
-            <p>
-              When running Xdmx, no unexpected failures were noted.
-              Since the Xdmx server is based on Xinerama, we expect to
-              have most of the Xinerama failures present in the Xdmx
-              server.  Similarly, since the Xdmx server must rely on the
-              low-level device drivers on each back-end server, we also
-              expect that Xdmx will exhibit most of the back-end
-              failures.  Here is a summary:
-              <verb>
-XListPixmapFormats: Test 1 (configuration dependent)
-XChangeWindowAttributes: Test 32
-XCreateWindow: Test 30
-XCopyPlane: Test 13, 22, 31
-XSetFontPath: Test 4
-XGetDefault: Test 5 (configuration dependent)
-XMatchVisualInfo: Test 1
-XRebindKeysym: Test 1 (configuration dependent)
-              </verb>
-            <p>
-              Note that this list is shorter than the combined list for
-              Xinerama because Xdmx uses different code paths to perform
-              some Xinerama operations.  Further, some Xinerama failures
-              have been fixed in the XFree86 4.2.99.x CVS repository.
-            
-          <sect3>Summary and Future Work
-            <p>
-              Running the X Test Suite on Xdmx does not produce any
-              failures that cannot be accounted for by the underlying
-              Xinerama subsystem used by the front-end or by the
-              low-level device-driver code running on the back-end X
-              servers.  The Xdmx server therefore is as ``correct'' as
-              possible with respect to the standard set of X Test Suite
-              tests.
-            <p>
-              During the following phases, we will continue to verify
-              Xdmx correctness using the X Test Suite.  We may also use
-              other tests suites or write additional tests that run
-              under the X Test Suite that specifically verify the
-              expected behavior of DMX.
-
-<sect2>Fonts
-
-<p>In Phase I, fonts are handled directly by both the front-end and the
-back-end servers, which is required since we must treat each back-end
-server during this phase as a ``black box''.  What this requires is that
-<bf/the front- and back-end servers must share the exact same font
-path/.  There are two ways to help make sure that all servers share the
-same font path:
-
-<enum>
-    <item>First, each server can be configured to use the same font
-    server.  The font server, xfs, can be configured to serve fonts to
-    multiple X servers via TCP.
-
-    <item>Second, each server can be configured to use the same font
-    path and either those font paths can be copied to each back-end
-    machine or they can be mounted (e.g., via NFS) on each back-end
-    machine.
-</enum>
-
-<p>One additional concern is that a client program can set its own font
-path, and if it does so, then that font path must be available on each
-back-end machine.
-
-<p>The -fontpath command line option was added to allow users to
-initialize the font path of the front end server.  This font path is
-propagated to each back-end server when the default font is loaded.  If
-there are any problems, an error message is printed, which will describe
-the problem and list the current font path.  For more information about
-setting the font path, see the -fontpath option description in the man
-page.
-
-<sect2>Performance
-
-<p>Phase I of development was not intended to optimize performance.  Its
-focus was on completely and correctly handling the base X11 protocol in
-the Xdmx server.  However, several insights were gained during Phase I,
-which are listed here for reference during the next phase of
-development.
-
-<enum>
-    <item>Calls to XSync() can slow down rendering since it requires a
-    complete round trip to and from a back-end server.  This is
-    especially problematic when communicating over long haul networks.
-    <item>Sending drawing requests to only the screens that they overlap
-    should improve performance.
-</enum>
-
-<sect2>Pixmaps
-
-<p>Pixmaps were originally expected to be handled entirely in the
-front-end X server; however, it was found that this overly complicated
-the rendering code and would have required sending potentially large
-images to each back server that required them when copying from pixmap
-to screen.  Thus, pixmap state is mirrored in the back-end server just
-as it is with regular window state.  With this implementation, the same
-rendering code that draws to windows can be used to draw to pixmaps on
-the back-end server, and no large image transfers are required to copy
-from pixmap to window.
-
-<!-- ============================================================ -->
-<sect1>Phase II
-
-<p>The second phase of development concentrates on performance
-optimizations.  These optimizations are documented here, with
-<tt/x11perf/ data to show how the optimizations improve performance.
-
-<p>All benchmarks were performed by running Xdmx on a dual processor
-1.4GHz AMD Athlon machine with 1GB of RAM connecting over 100baseT to
-two single-processor 1GHz Pentium III machines with 256MB of RAM and ATI
-Rage 128 (RF) video cards.  The front end was running Linux
-2.4.20-pre1-ac1 and the back ends were running Linux 2.4.7-10 and
-version 4.2.99.1 of XFree86 pulled from the XFree86 CVS repository on
-August 7, 2002.  All systems were running Red Hat Linux 7.2.
-
-<sect2>Moving from XFree86 4.1.99.1 to 4.2.0.0
-
-<p>For phase II, the working source tree was moved to the branch tagged
-with dmx-1-0-branch and was updated from version 4.1.99.1 (20 August
-2001) of the XFree86 sources to version 4.2.0.0 (18 January 2002).
-After this update, the following tests were noted to be more than 10%
-faster:
-            <verb>
-1.13   Fill 300x300 opaque stippled trapezoid (161x145 stipple) 
-1.16   Fill 1x1 tiled trapezoid (161x145 tile) 
-1.13   Fill 10x10 tiled trapezoid (161x145 tile) 
-1.17   Fill 100x100 tiled trapezoid (161x145 tile) 
-1.16   Fill 1x1 tiled trapezoid (216x208 tile) 
-1.20   Fill 10x10 tiled trapezoid (216x208 tile) 
-1.15   Fill 100x100 tiled trapezoid (216x208 tile) 
-1.37   Circulate Unmapped window (200 kids) 
-            </verb>
-And the following tests were noted to be more than 10% slower:
-            <verb>
-0.88   Unmap window via parent (25 kids) 
-0.75   Circulate Unmapped window (4 kids) 
-0.79   Circulate Unmapped window (16 kids) 
-0.80   Circulate Unmapped window (25 kids) 
-0.82   Circulate Unmapped window (50 kids) 
-0.85   Circulate Unmapped window (75 kids) 
-            </verb>
-<p>These changes were not caused by any changes in the DMX system, and
-may point to changes in the XFree86 tree or to tests that have more
-"jitter" than most other <tt/x11perf/ tests.
-
-<sect2>Global changes
-
-<p>During the development of the Phase II DMX server, several global
-changes were made.  These changes were also compared with the Phase I
-server.  The following tests were noted to be more than 10% faster:
-            <verb>
-1.13   Fill 300x300 opaque stippled trapezoid (161x145 stipple) 
-1.15   Fill 1x1 tiled trapezoid (161x145 tile) 
-1.13   Fill 10x10 tiled trapezoid (161x145 tile) 
-1.17   Fill 100x100 tiled trapezoid (161x145 tile) 
-1.16   Fill 1x1 tiled trapezoid (216x208 tile) 
-1.19   Fill 10x10 tiled trapezoid (216x208 tile) 
-1.15   Fill 100x100 tiled trapezoid (216x208 tile) 
-1.15   Circulate Unmapped window (4 kids) 
-            </verb>
-
-<p>The following tests were noted to be more than 10% slower:
-            <verb>
-0.69   Scroll 10x10 pixels 
-0.68   Scroll 100x100 pixels 
-0.68   Copy 10x10 from window to window 
-0.68   Copy 100x100 from window to window 
-0.76   Circulate Unmapped window (75 kids) 
-0.83   Circulate Unmapped window (100 kids) 
-            </verb>
-
-<p>For the remainder of this analysis, the baseline of comparison will
-be the Phase II deliverable with all optimizations disabled (unless
-otherwise noted).  This will highlight how the optimizations in
-isolation impact performance.
-
-<sect2>XSync() Batching
-
-<p>During the Phase I implementation, XSync() was called after every
-protocol request made by the DMX server.  This provided the DMX server
-with an interactive feel, but defeated X11's protocol buffering system
-and introduced round-trip wire latency into every operation.  During
-Phase II, DMX was changed so that protocol requests are no longer
-followed by calls to XSync().  Instead, the need for an XSync() is
-noted, and XSync() calls are only made every 100mS or when the DMX
-server specifically needs to make a call to guarantee interactivity.
-With this new system, X11 buffers protocol as much as possible during a
-100mS interval, and many unnecessary XSync() calls are avoided.
-
-<p>Out of more than 300 <tt/x11perf/ tests, 8 tests became more than 100
-times faster, with 68 more than 50X faster, 114 more than 10X faster,
-and 181 more than 2X faster.  See table below for summary.
-
-<p>The following tests were noted to be more than 10% slower with
-XSync() batching on:
-            <verb>
-0.88   500x500 tiled rectangle (161x145 tile) 
-0.89   Copy 500x500 from window to window 
-            </verb>
-
-<sect2>Offscreen Optimization
-
-<p>Windows span one or more of the back-end servers' screens; however,
-during Phase I development, windows were created on every back-end
-server and every rendering request was sent to every window regardless
-of whether or not that window was visible.  With the offscreen
-optimization, the DMX server tracks when a window is completely off of a
-back-end server's screen and, in that case, it does not send rendering
-requests to those back-end windows.  This optimization saves bandwidth
-between the front and back-end servers, and it reduces the number of
-XSync() calls.  The performance tests were run on a DMX system with only
-two back-end servers.  Greater performance gains will be had as the
-number of back-end servers increases.
-
-<p>Out of more than 300 <tt/x11perf/ tests, 3 tests were at least twice as
-fast, and 146 tests were at least 10% faster.  Two tests were more than
-10% slower with the offscreen optimization:
-            <verb>
-0.88   Hide/expose window via popup (4 kids) 
-0.89   Resize unmapped window (75 kids) 
-            </verb>
-
-<sect2>Lazy Window Creation Optimization
-
-<p>As mentioned above, during Phase I, windows were created on every
-back-end server even if they were not visible on that back-end.  With
-the lazy window creation optimization, the DMX server does not create
-windows on a back-end server until they are either visible or they
-become the parents of a visible window.  This optimization builds on the
-offscreen optimization (described above) and requires it to be enabled.
-
-<p>The lazy window creation optimization works by creating the window
-data structures in the front-end server when a client creates a window,
-but delays creation of the window on the back-end server(s).  A private
-window structure in the DMX server saves the relevant window data and
-tracks changes to the window's attributes and stacking order for later
-use.  The only times a window is created on a back-end server are (1)
-when it is mapped and is at least partially overlapping the back-end
-server's screen (tracked by the offscreen optimization), or (2) when the
-window becomes the parent of a previously visible window.  The first
-case occurs when a window is mapped or when a visible window is copied,
-moved or resized and now overlaps the back-end server's screen.  The
-second case occurs when starting a window manager after having created
-windows to which the window manager needs to add decorations.
-
-<p>When either case occurs, a window on the back-end server is created
-using the data saved in the DMX server's window private data structure.
-The stacking order is then adjusted to correctly place the window on the
-back-end and lastly the window is mapped.  From this time forward, the
-window is handled exactly as if the window had been created at the time
-of the client's request.
-
-<p>Note that when a window is no longer visible on a back-end server's
-screen (e.g., it is moved offscreen), the window is not destroyed;
-rather, it is kept and reused later if the window once again becomes
-visible on the back-end server's screen.  Originally with this
-optimization, destroying windows was implemented but was later rejected
-because it increased bandwidth when windows were opaquely moved or
-resized, which is common in many window managers.
-
-<p>The performance tests were run on a DMX system with only two back-end
-servers.  Greater performance gains will be had as the number of
-back-end servers increases.
-
-<p>This optimization improved the following <tt/x11perf/ tests by more
-than 10%:
-            <verb>
-1.10   500x500 rectangle outline 
-1.12   Fill 100x100 stippled trapezoid (161x145 stipple) 
-1.20   Circulate Unmapped window (50 kids) 
-1.19   Circulate Unmapped window (75 kids) 
-            </verb>
-            
-<sect2>Subdividing Rendering Primitives
-
-<p>X11 imaging requests transfer significant data between the client and
-the X server.  During Phase I, the DMX server would then transfer the
-image data to each back-end server.  Even with the offscreen
-optimization (above), these requests still required transferring
-significant data to each back-end server that contained a visible
-portion of the window.  For example, if the client uses XPutImage() to
-copy an image to a window that overlaps the entire DMX screen, then the
-entire image is copied by the DMX server to every back-end server.
-
-<p>To reduce the amount of data transferred between the DMX server and
-the back-end servers when XPutImage() is called, the image data is
-subdivided and only the data that will be visible on a back-end server's
-screen is sent to that back-end server.  Xinerama already implements a
-subdivision algorithm for XGetImage() and no further optimization was
-needed.
-
-<p>Other rendering primitives were analyzed, but the time required to
-subdivide these primitives was a significant proportion of the time
-required to send the entire rendering request to the back-end server, so
-this optimization was rejected for the other rendering primitives.
-
-<p>Again, the performance tests were run on a DMX system with only two
-back-end servers.  Greater performance gains will be had as the number
-of back-end servers increases.
-
-<p>This optimization improved the following <tt/x11perf/ tests by more
-than 10%:
-            <verb>
-1.12   Fill 100x100 stippled trapezoid (161x145 stipple) 
-1.26   PutImage 10x10 square 
-1.83   PutImage 100x100 square 
-1.91   PutImage 500x500 square 
-1.40   PutImage XY 10x10 square 
-1.48   PutImage XY 100x100 square 
-1.50   PutImage XY 500x500 square 
-1.45   Circulate Unmapped window (75 kids) 
-1.74   Circulate Unmapped window (100 kids) 
-            </verb>
-
-<p>The following test was noted to be more than 10% slower with this
-optimization:
-            <verb>
-0.88   10-pixel fill chord partial circle 
-            </verb>
-
-<sect2>Summary of x11perf Data
-
-<p>With all of the optimizations on, 53 <tt/x11perf/ tests are more than
-100X faster than the unoptimized Phase II deliverable, with 69 more than
-50X faster, 73 more than 10X faster, and 199 more than twice as fast.
-No tests were more than 10% slower than the unoptimized Phase II
-deliverable.  (Compared with the Phase I deliverable, only Circulate
-Unmapped window (100 kids) was more than 10% slower than the Phase II
-deliverable.  As noted above, this test seems to have wider variability
-than other <tt/x11perf/ tests.)
-
-<p>The following table summarizes relative <tt/x11perf/ test changes for
-all optimizations individually and collectively.  Note that some of the
-optimizations have a synergistic effect when used together.
-            <verb>
-
-1: XSync() batching only
-2: Off screen optimizations only
-3: Window optimizations only
-4: Subdivprims only
-5: All optimizations
-
-    1     2    3    4      5 Operation
------- ---- ---- ---- ------ ---------
-  2.14 1.85 1.00 1.00   4.13 Dot 
-  1.67 1.80 1.00 1.00   3.31 1x1 rectangle 
-  2.38 1.43 1.00 1.00   2.44 10x10 rectangle 
-  1.00 1.00 0.92 0.98   1.00 100x100 rectangle 
-  1.00 1.00 1.00 1.00   1.00 500x500 rectangle 
-  1.83 1.85 1.05 1.06   3.54 1x1 stippled rectangle (8x8 stipple) 
-  2.43 1.43 1.00 1.00   2.41 10x10 stippled rectangle (8x8 stipple) 
-  0.98 1.00 1.00 1.00   1.00 100x100 stippled rectangle (8x8 stipple) 
-  1.00 1.00 1.00 1.00   0.98 500x500 stippled rectangle (8x8 stipple) 
-  1.75 1.75 1.00 1.00   3.40 1x1 opaque stippled rectangle (8x8 stipple) 
-  2.38 1.42 1.00 1.00   2.34 10x10 opaque stippled rectangle (8x8 stipple) 
-  1.00 1.00 0.97 0.97   1.00 100x100 opaque stippled rectangle (8x8 stipple) 
-  1.00 1.00 1.00 1.00   0.99 500x500 opaque stippled rectangle (8x8 stipple) 
-  1.82 1.82 1.04 1.04   3.56 1x1 tiled rectangle (4x4 tile) 
-  2.33 1.42 1.00 1.00   2.37 10x10 tiled rectangle (4x4 tile) 
-  1.00 0.92 1.00 1.00   1.00 100x100 tiled rectangle (4x4 tile) 
-  1.00 1.00 1.00 1.00   1.00 500x500 tiled rectangle (4x4 tile) 
-  1.94 1.62 1.00 1.00   3.66 1x1 stippled rectangle (17x15 stipple) 
-  1.74 1.28 1.00 1.00   1.73 10x10 stippled rectangle (17x15 stipple) 
-  1.00 1.00 1.00 0.89   0.98 100x100 stippled rectangle (17x15 stipple) 
-  1.00 1.00 1.00 1.00   0.98 500x500 stippled rectangle (17x15 stipple) 
-  1.94 1.62 1.00 1.00   3.67 1x1 opaque stippled rectangle (17x15 stipple) 
-  1.69 1.26 1.00 1.00   1.66 10x10 opaque stippled rectangle (17x15 stipple) 
-  1.00 0.95 1.00 1.00   1.00 100x100 opaque stippled rectangle (17x15 stipple) 
-  1.00 1.00 1.00 1.00   0.97 500x500 opaque stippled rectangle (17x15 stipple) 
-  1.93 1.61 0.99 0.99   3.69 1x1 tiled rectangle (17x15 tile) 
-  1.73 1.27 1.00 1.00   1.72 10x10 tiled rectangle (17x15 tile) 
-  1.00 1.00 1.00 1.00   0.98 100x100 tiled rectangle (17x15 tile) 
-  1.00 1.00 0.97 0.97   1.00 500x500 tiled rectangle (17x15 tile) 
-  1.95 1.63 1.00 1.00   3.83 1x1 stippled rectangle (161x145 stipple) 
-  1.80 1.30 1.00 1.00   1.83 10x10 stippled rectangle (161x145 stipple) 
-  0.97 1.00 1.00 1.00   1.01 100x100 stippled rectangle (161x145 stipple) 
-  1.00 1.00 1.00 1.00   0.98 500x500 stippled rectangle (161x145 stipple) 
-  1.95 1.63 1.00 1.00   3.56 1x1 opaque stippled rectangle (161x145 stipple) 
-  1.65 1.25 1.00 1.00   1.68 10x10 opaque stippled rectangle (161x145 stipple) 
-  1.00 1.00 1.00 1.00   1.01 100x100 opaque stippled rectangle (161x145...
-  1.00 1.00 1.00 1.00   0.97 500x500 opaque stippled rectangle (161x145...
-  1.95 1.63 0.98 0.99   3.80 1x1 tiled rectangle (161x145 tile) 
-  1.67 1.26 1.00 1.00   1.67 10x10 tiled rectangle (161x145 tile) 
-  1.13 1.14 1.14 1.14   1.14 100x100 tiled rectangle (161x145 tile) 
-  0.88 1.00 1.00 1.00   0.99 500x500 tiled rectangle (161x145 tile) 
-  1.93 1.63 1.00 1.00   3.53 1x1 tiled rectangle (216x208 tile) 
-  1.69 1.26 1.00 1.00   1.66 10x10 tiled rectangle (216x208 tile) 
-  1.00 1.00 1.00 1.00   1.00 100x100 tiled rectangle (216x208 tile) 
-  1.00 1.00 1.00 1.00   1.00 500x500 tiled rectangle (216x208 tile) 
-  1.82 1.70 1.00 1.00   3.38 1-pixel line segment 
-  2.07 1.56 0.90 1.00   3.31 10-pixel line segment 
-  1.29 1.10 1.00 1.00   1.27 100-pixel line segment 
-  1.05 1.06 1.03 1.03   1.09 500-pixel line segment 
-  1.30 1.13 1.00 1.00   1.29 100-pixel line segment (1 kid) 
-  1.32 1.15 1.00 1.00   1.32 100-pixel line segment (2 kids) 
-  1.33 1.16 1.00 1.00   1.33 100-pixel line segment (3 kids) 
-  1.92 1.64 1.00 1.00   3.73 10-pixel dashed segment 
-  1.34 1.16 1.00 1.00   1.34 100-pixel dashed segment 
-  1.24 1.11 0.99 0.97   1.23 100-pixel double-dashed segment 
-  1.72 1.77 1.00 1.00   3.25 10-pixel horizontal line segment 
-  1.83 1.66 1.01 1.00   3.54 100-pixel horizontal line segment 
-  1.86 1.30 1.00 1.00   1.84 500-pixel horizontal line segment 
-  2.11 1.52 1.00 0.99   3.02 10-pixel vertical line segment 
-  1.21 1.10 1.00 1.00   1.20 100-pixel vertical line segment 
-  1.03 1.03 1.00 1.00   1.02 500-pixel vertical line segment 
-  4.42 1.68 1.00 1.01   4.64 10x1 wide horizontal line segment 
-  1.83 1.31 1.00 1.00   1.83 100x10 wide horizontal line segment 
-  1.07 1.00 0.96 1.00   1.07 500x50 wide horizontal line segment 
-  4.10 1.67 1.00 1.00   4.62 10x1 wide vertical line segment 
-  1.50 1.24 1.06 1.06   1.48 100x10 wide vertical line segment 
-  1.06 1.03 1.00 1.00   1.05 500x50 wide vertical line segment 
-  2.54 1.61 1.00 1.00   3.61 1-pixel line 
-  2.71 1.48 1.00 1.00   2.67 10-pixel line 
-  1.19 1.09 1.00 1.00   1.19 100-pixel line 
-  1.04 1.02 1.00 1.00   1.03 500-pixel line 
-  2.68 1.51 0.98 1.00   3.17 10-pixel dashed line 
-  1.23 1.11 0.99 0.99   1.23 100-pixel dashed line 
-  1.15 1.08 1.00 1.00   1.15 100-pixel double-dashed line 
-  2.27 1.39 1.00 1.00   2.23 10x1 wide line 
-  1.20 1.09 1.00 1.00   1.20 100x10 wide line 
-  1.04 1.02 1.00 1.00   1.04 500x50 wide line 
-  1.52 1.45 1.00 1.00   1.52 100x10 wide dashed line 
-  1.54 1.47 1.00 1.00   1.54 100x10 wide double-dashed line 
-  1.97 1.30 0.96 0.95   1.95 10x10 rectangle outline 
-  1.44 1.27 1.00 1.00   1.43 100x100 rectangle outline 
-  3.22 2.16 1.10 1.09   3.61 500x500 rectangle outline 
-  1.95 1.34 1.00 1.00   1.90 10x10 wide rectangle outline 
-  1.14 1.14 1.00 1.00   1.13 100x100 wide rectangle outline 
-  1.00 1.00 1.00 1.00   1.00 500x500 wide rectangle outline 
-  1.57 1.72 1.00 1.00   3.03 1-pixel circle 
-  1.96 1.35 1.00 1.00   1.92 10-pixel circle 
-  1.21 1.07 0.86 0.97   1.20 100-pixel circle 
-  1.08 1.04 1.00 1.00   1.08 500-pixel circle 
-  1.39 1.19 1.03 1.03   1.38 100-pixel dashed circle 
-  1.21 1.11 1.00 1.00   1.23 100-pixel double-dashed circle 
-  1.59 1.28 1.00 1.00   1.58 10-pixel wide circle 
-  1.22 1.12 0.99 1.00   1.22 100-pixel wide circle 
-  1.06 1.04 1.00 1.00   1.05 500-pixel wide circle 
-  1.87 1.84 1.00 1.00   1.85 100-pixel wide dashed circle 
-  1.90 1.93 1.01 1.01   1.90 100-pixel wide double-dashed circle 
-  2.13 1.43 1.00 1.00   2.32 10-pixel partial circle 
-  1.42 1.18 1.00 1.00   1.42 100-pixel partial circle 
-  1.92 1.85 1.01 1.01   1.89 10-pixel wide partial circle 
-  1.73 1.67 1.00 1.00   1.73 100-pixel wide partial circle 
-  1.36 1.95 1.00 1.00   2.64 1-pixel solid circle 
-  2.02 1.37 1.00 1.00   2.03 10-pixel solid circle 
-  1.19 1.09 1.00 1.00   1.19 100-pixel solid circle 
-  1.02 0.99 1.00 1.00   1.01 500-pixel solid circle 
-  1.74 1.28 1.00 0.88   1.73 10-pixel fill chord partial circle 
-  1.31 1.13 1.00 1.00   1.31 100-pixel fill chord partial circle 
-  1.67 1.31 1.03 1.03   1.72 10-pixel fill slice partial circle 
-  1.30 1.13 1.00 1.00   1.28 100-pixel fill slice partial circle 
-  2.45 1.49 1.01 1.00   2.71 10-pixel ellipse 
-  1.22 1.10 1.00 1.00   1.22 100-pixel ellipse 
-  1.09 1.04 1.00 1.00   1.09 500-pixel ellipse 
-  1.90 1.28 1.00 1.00   1.89 100-pixel dashed ellipse 
-  1.62 1.24 0.96 0.97   1.61 100-pixel double-dashed ellipse 
-  2.43 1.50 1.00 1.00   2.42 10-pixel wide ellipse 
-  1.61 1.28 1.03 1.03   1.60 100-pixel wide ellipse 
-  1.08 1.05 1.00 1.00   1.08 500-pixel wide ellipse 
-  1.93 1.88 1.00 1.00   1.88 100-pixel wide dashed ellipse 
-  1.94 1.89 1.01 1.00   1.94 100-pixel wide double-dashed ellipse 
-  2.31 1.48 1.00 1.00   2.67 10-pixel partial ellipse 
-  1.38 1.17 1.00 1.00   1.38 100-pixel partial ellipse 
-  2.00 1.85 0.98 0.97   1.98 10-pixel wide partial ellipse 
-  1.89 1.86 1.00 1.00   1.89 100-pixel wide partial ellipse 
-  3.49 1.60 1.00 1.00   3.65 10-pixel filled ellipse 
-  1.67 1.26 1.00 1.00   1.67 100-pixel filled ellipse 
-  1.06 1.04 1.00 1.00   1.06 500-pixel filled ellipse 
-  2.38 1.43 1.01 1.00   2.32 10-pixel fill chord partial ellipse 
-  2.06 1.30 1.00 1.00   2.05 100-pixel fill chord partial ellipse 
-  2.27 1.41 1.00 1.00   2.27 10-pixel fill slice partial ellipse 
-  1.98 1.33 1.00 0.97   1.97 100-pixel fill slice partial ellipse 
- 57.46 1.99 1.01 1.00 114.92 Fill 1x1 equivalent triangle 
- 56.94 1.98 1.01 1.00  73.89 Fill 10x10 equivalent triangle 
-  6.07 1.75 1.00 1.00   6.07 Fill 100x100 equivalent triangle 
- 51.12 1.98 1.00 1.00 102.81 Fill 1x1 trapezoid 
- 51.42 1.82 1.01 1.00  94.89 Fill 10x10 trapezoid 
-  6.47 1.80 1.00 1.00   6.44 Fill 100x100 trapezoid 
-  1.56 1.28 1.00 0.99   1.56 Fill 300x300 trapezoid 
- 51.27 1.97 0.96 0.97 102.54 Fill 1x1 stippled trapezoid (8x8 stipple) 
- 51.73 2.00 1.02 1.02  67.92 Fill 10x10 stippled trapezoid (8x8 stipple) 
-  5.36 1.72 1.00 1.00   5.36 Fill 100x100 stippled trapezoid (8x8 stipple) 
-  1.54 1.26 1.00 1.00   1.59 Fill 300x300 stippled trapezoid (8x8 stipple) 
- 51.41 1.94 1.01 1.00 102.82 Fill 1x1 opaque stippled trapezoid (8x8 stipple) 
- 50.71 1.95 0.99 1.00  65.44 Fill 10x10 opaque stippled trapezoid (8x8...
-  5.33 1.73 1.00 1.00   5.36 Fill 100x100 opaque stippled trapezoid (8x8...
-  1.58 1.25 1.00 1.00   1.58 Fill 300x300 opaque stippled trapezoid (8x8...
- 51.56 1.96 0.99 0.90 103.68 Fill 1x1 tiled trapezoid (4x4 tile) 
- 51.59 1.99 1.01 1.01  62.25 Fill 10x10 tiled trapezoid (4x4 tile) 
-  5.38 1.72 1.00 1.00   5.38 Fill 100x100 tiled trapezoid (4x4 tile) 
-  1.54 1.25 1.00 0.99   1.58 Fill 300x300 tiled trapezoid (4x4 tile) 
- 51.70 1.98 1.01 1.01 103.98 Fill 1x1 stippled trapezoid (17x15 stipple) 
- 44.86 1.97 1.00 1.00  44.86 Fill 10x10 stippled trapezoid (17x15 stipple) 
-  2.74 1.56 1.00 1.00   2.73 Fill 100x100 stippled trapezoid (17x15 stipple) 
-  1.29 1.14 1.00 1.00   1.27 Fill 300x300 stippled trapezoid (17x15 stipple) 
- 51.41 1.96 0.96 0.95 103.39 Fill 1x1 opaque stippled trapezoid (17x15...
- 45.14 1.96 1.01 1.00  45.14 Fill 10x10 opaque stippled trapezoid (17x15...
-  2.68 1.56 1.00 1.00   2.68 Fill 100x100 opaque stippled trapezoid (17x15...
-  1.26 1.10 1.00 1.00   1.28 Fill 300x300 opaque stippled trapezoid (17x15...
- 51.13 1.97 1.00 0.99 103.39 Fill 1x1 tiled trapezoid (17x15 tile) 
- 47.58 1.96 1.00 1.00  47.86 Fill 10x10 tiled trapezoid (17x15 tile) 
-  2.74 1.56 1.00 1.00   2.74 Fill 100x100 tiled trapezoid (17x15 tile) 
-  1.29 1.14 1.00 1.00   1.28 Fill 300x300 tiled trapezoid (17x15 tile) 
- 51.13 1.97 0.99 0.97 103.39 Fill 1x1 stippled trapezoid (161x145 stipple) 
- 45.14 1.97 1.00 1.00  44.29 Fill 10x10 stippled trapezoid (161x145 stipple) 
-  3.02 1.77 1.12 1.12   3.38 Fill 100x100 stippled trapezoid (161x145 stipple) 
-  1.31 1.13 1.00 1.00   1.30 Fill 300x300 stippled trapezoid (161x145 stipple) 
- 51.27 1.97 1.00 1.00 103.10 Fill 1x1 opaque stippled trapezoid (161x145...
- 45.01 1.97 1.00 1.00  45.01 Fill 10x10 opaque stippled trapezoid (161x145...
-  2.67 1.56 1.00 1.00   2.69 Fill 100x100 opaque stippled trapezoid (161x145..
-  1.29 1.13 1.00 1.01   1.27 Fill 300x300 opaque stippled trapezoid (161x145..
- 51.41 1.96 1.00 0.99 103.39 Fill 1x1 tiled trapezoid (161x145 tile) 
- 45.01 1.96 0.98 1.00  45.01 Fill 10x10 tiled trapezoid (161x145 tile) 
-  2.62 1.36 1.00 1.00   2.69 Fill 100x100 tiled trapezoid (161x145 tile) 
-  1.27 1.13 1.00 1.00   1.22 Fill 300x300 tiled trapezoid (161x145 tile) 
- 51.13 1.98 1.00 1.00 103.39 Fill 1x1 tiled trapezoid (216x208 tile) 
- 45.14 1.97 1.01 0.99  45.14 Fill 10x10 tiled trapezoid (216x208 tile) 
-  2.62 1.55 1.00 1.00   2.71 Fill 100x100 tiled trapezoid (216x208 tile) 
-  1.28 1.13 1.00 1.00   1.20 Fill 300x300 tiled trapezoid (216x208 tile) 
- 50.71 1.95 1.00 1.00  54.70 Fill 10x10 equivalent complex polygon 
-  5.51 1.71 0.96 0.98   5.47 Fill 100x100 equivalent complex polygons 
-  8.39 1.97 1.00 1.00  16.75 Fill 10x10 64-gon (Convex) 
-  8.38 1.83 1.00 1.00   8.43 Fill 100x100 64-gon (Convex) 
-  8.50 1.96 1.00 1.00  16.64 Fill 10x10 64-gon (Complex) 
-  8.26 1.83 1.00 1.00   8.35 Fill 100x100 64-gon (Complex) 
- 14.09 1.87 1.00 1.00  14.05 Char in 80-char line (6x13) 
- 11.91 1.87 1.00 1.00  11.95 Char in 70-char line (8x13) 
- 11.16 1.85 1.01 1.00  11.10 Char in 60-char line (9x15) 
- 10.09 1.78 1.00 1.00  10.09 Char16 in 40-char line (k14) 
-  6.15 1.75 1.00 1.00   6.31 Char16 in 23-char line (k24) 
- 11.92 1.90 1.03 1.03  11.88 Char in 80-char line (TR 10) 
-  8.18 1.78 1.00 0.99   8.17 Char in 30-char line (TR 24) 
- 42.83 1.44 1.01 1.00  42.11 Char in 20/40/20 line (6x13, TR 10) 
- 27.45 1.43 1.01 1.01  27.45 Char16 in 7/14/7 line (k14, k24) 
- 12.13 1.85 1.00 1.00  12.05 Char in 80-char image line (6x13) 
- 10.00 1.84 1.00 1.00  10.00 Char in 70-char image line (8x13) 
-  9.18 1.83 1.00 1.00   9.12 Char in 60-char image line (9x15) 
-  9.66 1.82 0.98 0.95   9.66 Char16 in 40-char image line (k14) 
-  5.82 1.72 1.00 1.00   5.99 Char16 in 23-char image line (k24) 
-  8.70 1.80 1.00 1.00   8.65 Char in 80-char image line (TR 10) 
-  4.67 1.66 1.00 1.00   4.67 Char in 30-char image line (TR 24) 
- 84.43 1.47 1.00 1.00 124.18 Scroll 10x10 pixels 
-  3.73 1.50 1.00 0.98   3.73 Scroll 100x100 pixels 
-  1.00 1.00 1.00 1.00   1.00 Scroll 500x500 pixels 
- 84.43 1.51 1.00 1.00 134.02 Copy 10x10 from window to window 
-  3.62 1.51 0.98 0.98   3.62 Copy 100x100 from window to window 
-  0.89 1.00 1.00 1.00   1.00 Copy 500x500 from window to window 
- 57.06 1.99 1.00 1.00  88.64 Copy 10x10 from pixmap to window 
-  2.49 2.00 1.00 1.00   2.48 Copy 100x100 from pixmap to window 
-  1.00 0.91 1.00 1.00   0.98 Copy 500x500 from pixmap to window 
-  2.04 1.01 1.00 1.00   2.03 Copy 10x10 from window to pixmap 
-  1.05 1.00 1.00 1.00   1.05 Copy 100x100 from window to pixmap 
-  1.00 1.00 0.93 1.00   1.04 Copy 500x500 from window to pixmap 
- 58.52 1.03 1.03 1.02  57.95 Copy 10x10 from pixmap to pixmap 
-  2.40 1.00 1.00 1.00   2.45 Copy 100x100 from pixmap to pixmap 
-  1.00 1.00 1.00 1.00   1.00 Copy 500x500 from pixmap to pixmap 
- 51.57 1.92 1.00 1.00  85.75 Copy 10x10 1-bit deep plane 
-  6.37 1.75 1.01 1.01   6.37 Copy 100x100 1-bit deep plane 
-  1.26 1.11 1.00 1.00   1.24 Copy 500x500 1-bit deep plane 
-  4.23 1.63 0.98 0.97   4.38 Copy 10x10 n-bit deep plane 
-  1.04 1.02 1.00 1.00   1.04 Copy 100x100 n-bit deep plane 
-  1.00 1.00 1.00 1.00   1.00 Copy 500x500 n-bit deep plane 
-  6.45 1.98 1.00 1.26  12.80 PutImage 10x10 square 
-  1.10 1.87 1.00 1.83   2.11 PutImage 100x100 square 
-  1.02 1.93 1.00 1.91   1.91 PutImage 500x500 square 
-  4.17 1.78 1.00 1.40   7.18 PutImage XY 10x10 square 
-  1.27 1.49 0.97 1.48   2.10 PutImage XY 100x100 square 
-  1.00 1.50 1.00 1.50   1.52 PutImage XY 500x500 square 
-  1.07 1.01 1.00 1.00   1.06 GetImage 10x10 square 
-  1.01 1.00 1.00 1.00   1.01 GetImage 100x100 square 
-  1.00 1.00 1.00 1.00   1.00 GetImage 500x500 square 
-  1.56 1.00 0.99 0.97   1.56 GetImage XY 10x10 square 
-  1.02 1.00 1.00 1.00   1.02 GetImage XY 100x100 square 
-  1.00 1.00 1.00 1.00   1.00 GetImage XY 500x500 square 
-  1.00 1.00 1.01 0.98   0.95 X protocol NoOperation 
-  1.02 1.03 1.04 1.03   1.00 QueryPointer 
-  1.03 1.02 1.04 1.03   1.00 GetProperty 
-100.41 1.51 1.00 1.00 198.76 Change graphics context 
- 45.81 1.00 0.99 0.97  57.10 Create and map subwindows (4 kids) 
- 78.45 1.01 1.02 1.02  63.07 Create and map subwindows (16 kids) 
- 73.91 1.01 1.00 1.00  56.37 Create and map subwindows (25 kids) 
- 73.22 1.00 1.00 1.00  49.07 Create and map subwindows (50 kids) 
- 72.36 1.01 0.99 1.00  32.14 Create and map subwindows (75 kids) 
- 70.34 1.00 1.00 1.00  30.12 Create and map subwindows (100 kids) 
- 55.00 1.00 1.00 0.99  23.75 Create and map subwindows (200 kids) 
- 55.30 1.01 1.00 1.00 141.03 Create unmapped window (4 kids) 
- 55.38 1.01 1.01 1.00 163.25 Create unmapped window (16 kids) 
- 54.75 0.96 1.00 0.99 166.95 Create unmapped window (25 kids) 
- 54.83 1.00 1.00 0.99 178.81 Create unmapped window (50 kids) 
- 55.38 1.01 1.01 1.00 181.20 Create unmapped window (75 kids) 
- 55.38 1.01 1.01 1.00 181.20 Create unmapped window (100 kids) 
- 54.87 1.01 1.01 1.00 182.05 Create unmapped window (200 kids) 
- 28.13 1.00 1.00 1.00  30.75 Map window via parent (4 kids) 
- 36.14 1.01 1.01 1.01  32.58 Map window via parent (16 kids) 
- 26.13 1.00 0.98 0.95  29.85 Map window via parent (25 kids) 
- 40.07 1.00 1.01 1.00  27.57 Map window via parent (50 kids) 
- 23.26 0.99 1.00 1.00  18.23 Map window via parent (75 kids) 
- 22.91 0.99 1.00 0.99  16.52 Map window via parent (100 kids) 
- 27.79 1.00 1.00 0.99  12.50 Map window via parent (200 kids) 
- 22.35 1.00 1.00 1.00  56.19 Unmap window via parent (4 kids) 
-  9.57 1.00 0.99 1.00  89.78 Unmap window via parent (16 kids) 
- 80.77 1.01 1.00 1.00 103.85 Unmap window via parent (25 kids) 
- 96.34 1.00 1.00 1.00 116.06 Unmap window via parent (50 kids) 
- 99.72 1.00 1.00 1.00 124.93 Unmap window via parent (75 kids) 
-112.36 1.00 1.00 1.00 125.27 Unmap window via parent (100 kids) 
-105.41 1.00 1.00 0.99 120.00 Unmap window via parent (200 kids) 
- 51.29 1.03 1.02 1.02  74.19 Destroy window via parent (4 kids) 
- 86.75 0.99 0.99 0.99 116.87 Destroy window via parent (16 kids) 
-106.43 1.01 1.01 1.01 127.49 Destroy window via parent (25 kids) 
-120.34 1.01 1.01 1.00 140.11 Destroy window via parent (50 kids) 
-126.67 1.00 0.99 0.99 145.00 Destroy window via parent (75 kids) 
-126.11 1.01 1.01 1.00 140.56 Destroy window via parent (100 kids) 
-128.57 1.01 1.00 1.00 137.91 Destroy window via parent (200 kids) 
- 16.04 0.88 1.00 1.00  20.36 Hide/expose window via popup (4 kids) 
- 19.04 1.01 1.00 1.00  23.48 Hide/expose window via popup (16 kids) 
- 19.22 1.00 1.00 1.00  20.44 Hide/expose window via popup (25 kids) 
- 17.41 1.00 0.91 0.97  17.68 Hide/expose window via popup (50 kids) 
- 17.29 1.01 1.00 1.01  17.07 Hide/expose window via popup (75 kids) 
- 16.74 1.00 1.00 1.00  16.17 Hide/expose window via popup (100 kids) 
- 10.30 1.00 1.00 1.00  10.51 Hide/expose window via popup (200 kids) 
- 16.48 1.01 1.00 1.00  26.05 Move window (4 kids) 
- 17.01 0.95 1.00 1.00  23.97 Move window (16 kids) 
- 16.95 1.00 1.00 1.00  22.90 Move window (25 kids) 
- 16.05 1.01 1.00 1.00  21.32 Move window (50 kids) 
- 15.58 1.00 0.98 0.98  19.44 Move window (75 kids) 
- 14.98 1.02 1.03 1.03  18.17 Move window (100 kids) 
- 10.90 1.01 1.01 1.00  12.68 Move window (200 kids) 
- 49.42 1.00 1.00 1.00 198.27 Moved unmapped window (4 kids) 
- 50.72 0.97 1.00 1.00 193.66 Moved unmapped window (16 kids) 
- 50.87 1.00 0.99 1.00 195.09 Moved unmapped window (25 kids) 
- 50.72 1.00 1.00 1.00 189.34 Moved unmapped window (50 kids) 
- 50.87 1.00 1.00 1.00 191.33 Moved unmapped window (75 kids) 
- 50.87 1.00 1.00 0.90 186.71 Moved unmapped window (100 kids) 
- 50.87 1.00 1.00 1.00 179.19 Moved unmapped window (200 kids) 
- 41.04 1.00 1.00 1.00  56.61 Move window via parent (4 kids) 
- 69.81 1.00 1.00 1.00 130.82 Move window via parent (16 kids) 
- 95.81 1.00 1.00 1.00 141.92 Move window via parent (25 kids) 
- 95.98 1.00 1.00 1.00 149.43 Move window via parent (50 kids) 
- 96.59 1.01 1.01 1.00 153.98 Move window via parent (75 kids) 
- 97.19 1.00 1.00 1.00 157.30 Move window via parent (100 kids) 
- 96.67 1.00 0.99 0.96 159.44 Move window via parent (200 kids) 
- 17.75 1.01 1.00 1.00  27.61 Resize window (4 kids) 
- 17.94 1.00 1.00 0.99  25.42 Resize window (16 kids) 
- 17.92 1.01 1.00 1.00  24.47 Resize window (25 kids) 
- 17.24 0.97 1.00 1.00  24.14 Resize window (50 kids) 
- 16.81 1.00 1.00 0.99  22.75 Resize window (75 kids) 
- 16.08 1.00 1.00 1.00  21.20 Resize window (100 kids) 
- 12.92 1.00 0.99 1.00  16.26 Resize window (200 kids) 
- 52.94 1.01 1.00 1.00 327.12 Resize unmapped window (4 kids) 
- 53.60 1.01 1.01 1.01 333.71 Resize unmapped window (16 kids) 
- 52.99 1.00 1.00 1.00 337.29 Resize unmapped window (25 kids) 
- 51.98 1.00 1.00 1.00 329.38 Resize unmapped window (50 kids) 
- 53.05 0.89 1.00 1.00 322.60 Resize unmapped window (75 kids) 
- 53.05 1.00 1.00 1.00 318.08 Resize unmapped window (100 kids) 
- 53.11 1.00 1.00 0.99 306.21 Resize unmapped window (200 kids) 
- 16.76 1.00 0.96 1.00  19.46 Circulate window (4 kids) 
- 17.24 1.00 1.00 0.97  16.24 Circulate window (16 kids) 
- 16.30 1.03 1.03 1.03  15.85 Circulate window (25 kids) 
- 13.45 1.00 1.00 1.00  14.90 Circulate window (50 kids) 
- 12.91 1.00 1.00 1.00  13.06 Circulate window (75 kids) 
- 11.30 0.98 1.00 1.00  11.03 Circulate window (100 kids) 
-  7.58 1.01 1.01 0.99   7.47 Circulate window (200 kids) 
-  1.01 1.01 0.98 1.00   0.95 Circulate Unmapped window (4 kids) 
-  1.07 1.07 1.01 1.07   1.02 Circulate Unmapped window (16 kids) 
-  1.04 1.09 1.06 1.05   0.97 Circulate Unmapped window (25 kids) 
-  1.04 1.23 1.20 1.18   1.05 Circulate Unmapped window (50 kids) 
-  1.18 1.53 1.19 1.45   1.24 Circulate Unmapped window (75 kids) 
-  1.08 1.02 1.01 1.74   1.01 Circulate Unmapped window (100 kids) 
-  1.01 1.12 0.98 0.91   0.97 Circulate Unmapped window (200 kids) 
-            </verb>
-
-<sect2>Profiling with OProfile
-
-<p>OProfile (available from http://oprofile.sourceforge.net/) is a
-system-wide profiler for Linux systems that uses processor-level
-counters to collect sampling data.  OProfile can provide information
-that is similar to that provided by <tt/gprof/, but without the
-necessity of recompiling the program with special instrumentation (i.e.,
-OProfile can collect statistical profiling information about optimized
-programs).  A test harness was developed to collect OProfile data for
-each <tt/x11perf/ test individually.
-
-<p>Test runs were performed using the RETIRED_INSNS counter on the AMD
-Athlon and the CPU_CLK_HALTED counter on the Intel Pentium III (with a
-test configuration different from the one described above).  We have
-examined OProfile output and have compared it with <tt/gprof/ output.
-This investigation has not produced results that yield performance
-increases in <tt/x11perf/ numbers.
-
-<!--
-<sect3>Retired Instructions
-
-<p>The initial tests using OProfile were done using the RETIRED_INSNS
-counter with DMX running on the dual-processor AMD Athlon machine - the
-same test configuration that was described above and that was used for
-other tests.  The RETIRED_INSNS counter counts retired instructions and
-showed drawing, text, copying, and image tests to be dominated (&gt;
-30%) by calls to Hash(), SecurityLookupIDByClass(),
-SecurityLookupIDByType(), and StandardReadRequestFromClient().  Some of
-these tests also executed significant instructions in
-WaitForSomething().
-
-<p>In contrast, the window tests executed significant
-instructions in SecurityLookupIDByType(), Hash(),
-StandardReadRequestFromClient(), but also executed significant
-instructions in other routines, such as ConfigureWindow().  Some time
-was spent looking at Hash() function, but optimizations in this routine
-did not lead to a dramatic increase in <tt/x11perf/ performance.
--->
-
-<!-- 
-<sect3>Clock Cycles
-
-<p>Retired instructions can be misleading because Intel/AMD instructions
-execute in variable amounts of time.  The OProfile tests were repeated
-using the Intel CPU_CLK_HALTED counter with DMX running on the second
-back-end machine.  Note that this is a different test configuration that
-the one described above.  However, these tests show the amount of time
-(as measured in CPU cycles) that are spent in each routine.  Because
-<tt/x11perf/ was running on the first back-end machine and because
-window optimizations were on, the load on the second back-end machine
-was not significant.
-
-<p>Using CPU_CLK_HALTED, DMX showed simple drawing
-tests spending more than 10% of their time in
-StandardReadRequestFromClient(), with significant time (&gt; 20% total)
-spent in SecurityLookupIDByClass(), WaitForSomething(), and Dispatch().
-For these tests, &lt; 5% of the time was spent in Hash(), which explains
-why optimizing the Hash() routine did not impact <tt/x11perf/ results.
-
-<p>The trapezoid, text, scrolling, copying, and image tests were
-dominated by time in ProcFillPoly(), PanoramiXFillPoly(), dmxFillPolygon(),
-SecurityLookupIDByClass(), SecurityLookupIDByType(), and
-StandardReadRequestFromClient().  Hash() time was generally above 5% but
-less than 10% of total time.
--->
-
-<sect2>X Test Suite
-
-<p>The X Test Suite was run on the fully optimized DMX server using the
-configuration described above.  The following failures were noted:
-            <verb>
-XListPixmapFormats: Test 1              [1]
-XChangeWindowAttributes: Test 32        [1]
-XCreateWindow: Test 30                  [1]
-XFreeColors: Test 4                     [3]
-XCopyArea: Test 13, 17, 21, 25, 30      [2]
-XCopyPlane: Test 11, 15, 27, 31         [2]
-XSetFontPath: Test 4                    [1]
-XChangeKeyboardControl: Test 9, 10      [1]
-
-[1] Previously documented errors expected from the Xinerama
-    implementation (see Phase I discussion).
-[2] Newly noted errors that have been verified as expected
-    behavior of the Xinerama implementation.
-[3] Newly noted error that has been verified as a Xinerama
-    implementation bug.
-            </verb>
-          
-<!-- ============================================================ -->
-<sect1>Phase III
-
-<p>During the third phase of development, support was provided for the
-following extensions: SHAPE, RENDER, XKEYBOARD, XInput.
-
-<sect2>SHAPE
-
-<p>The SHAPE extension is supported.  Test applications (e.g., xeyes and
-oclock) and window managers that make use of the SHAPE extension will
-work as expected.
-
-<sect2>RENDER
-
-<p>The RENDER extension is supported.  The version included in the DMX
-CVS tree is version 0.2, and this version is fully supported by Xdmx.
-Applications using only version 0.2 functions will work correctly;
-however, some apps that make use of functions from later versions do not
-properly check the extension's major/minor version numbers.  These apps
-will fail with a Bad Implementation error when using post-version 0.2
-functions.  This is expected behavior.  When the DMX CVS tree is updated
-to include newer versions of RENDER, support for these newer functions
-will be added to the DMX X server.
-
-<sect2>XKEYBOARD
-
-<p>The XKEYBOARD extension is supported.  If present on the back-end X
-servers, the XKEYBOARD extension will be used to obtain information
-about the type of the keyboard for initialization.  Otherwise, the
-keyboard will be initialized using defaults.  Note that this departs
-from older behavior: when Xdmx is compiled without XKEYBOARD support,
-the map from the back-end X server will be preserved.  With XKEYBOARD
-support, the map is not preserved because better information and control
-of the keyboard is available.
-
-<sect2>XInput
-
-<p>The XInput extension is supported.  Any device can be used as a core
-device and be used as an XInput extension device, with the exception of
-core devices on the back-end servers.  This limitation is present
-because cursor handling on the back-end requires that the back-end
-cursor sometimes track the Xdmx core cursor -- behavior that is
-incompatible with using the back-end pointer as a non-core device.
-
-<p>Currently, back-end extension devices are not available as Xdmx
-extension devices, but this limitation should be removed in the future.
-
-<p>To demonstrate the XInput extension, and to provide more examples for
-low-level input device driver writers, USB device drivers have been
-written for mice (usb-mou), keyboards (usb-kbd), and
-non-mouse/non-keyboard USB devices (usb-oth).  Please see the man page
-for information on Linux kernel drivers that are required for using
-these Xdmx drivers.
-
-<sect2>DPMS
-
-<p>The DPMS extension is exported but does not do anything at this time.
-
-<sect2>Other Extensions
-
-<p>The LBX,
-       SECURITY,
-       XC-APPGROUP, and
-       XFree86-Bigfont
-extensions do not require any special Xdmx support and have been exported.
-
-<p>The
-    BIG-REQUESTS,
-    DEC-XTRAP,
-    DOUBLE-BUFFER,
-    Extended-Visual-Information,
-    FontCache,
-    GLX,
-    MIT-SCREEN-SAVER,
-    MIT-SHM,
-    MIT-SUNDRY-NONSTANDARD,
-    RECORD,
-    SECURITY,
-    SGI-GLX,
-    SYNC,
-    TOG-CUP,
-    X-Resource,
-    XC-MISC,
-    XFree86-DGA,
-    XFree86-DRI,
-    XFree86-Misc,
-    XFree86-VidModeExtension, and
-    XVideo
-extensions are <it/not/ supported at this time, but will be evaluated
-for inclusion in future DMX releases.  <bf>See below for additional work
-on extensions after Phase III.</bf>
-
-<sect1>Phase IV
-
-<sect2>Moving to XFree86 4.3.0
-
-<p>For Phase IV, the recent release of XFree86 4.3.0 (27 February 2003)
-was merged onto the dmx.sourceforge.net CVS trunk and all work is
-proceeding using this tree.
-
-<sect2>Extensions 
-
-<sect3>XC-MISC (supported)
-
-<p>XC-MISC is used internally by the X library to recycle XIDs from the
-X server.  This is important for long-running X server sessions.  Xdmx
-supports this extension.  The X Test Suite passed and failed the exact
-same tests before and after this extension was enabled.
-<!-- Tested February/March 2003 -->
-
-<sect3>Extended-Visual-Information (supported)
-
-<p>The Extended-Visual-Information extension provides a method for an X
-client to obtain detailed visual information.  Xdmx supports this
-extension.  It was tested using the <tt>hw/dmx/examples/evi</tt> example
-program.  <bf/Note that this extension is not Xinerama-aware/ -- it will
-return visual information for each screen even though Xinerama is
-causing the X server to export a single logical screen.
-<!-- Tested March 2003 -->
-
-<sect3>RES (supported)
-
-<p>The X-Resource extension provides a mechanism for a client to obtain
-detailed information about the resources used by other clients.  This
-extension was tested with the <tt>hw/dmx/examples/res</tt> program.  The
-X Test Suite passed and failed the exact same tests before and after
-this extension was enabled.
-<!-- Tested March 2003 -->
-
-<sect3>BIG-REQUESTS (supported)
-
-<p>This extension enables the X11 protocol to handle requests longer
-than 262140 bytes.  The X Test Suite passed and failed the exact same
-tests before and after this extension was enabled.
-<!-- Tested March 2003 -->
-
-<sect3>XSYNC (supported)
-
-<p>This extension provides facilities for two different X clients to
-synchronize their requests.  This extension was minimally tested with
-<tt/xdpyinfo/ and the X Test Suite passed and failed the exact same
-tests before and after this extension was enabled.
-<!-- Tested March 2003 -->
-
-<sect3>XTEST, RECORD, DEC-XTRAP (supported) and XTestExtension1 (not supported)
-
-<p>The XTEST and RECORD extension were developed by the X Consortium for
-use in the X Test Suite and are supported as a standard in the X11R6
-tree.  They are also supported in Xdmx.  When X Test Suite tests that
-make use of the XTEST extension are run, Xdmx passes and fails exactly
-the same tests as does a standard XFree86 X server.  When the
-<tt/rcrdtest/ test (a part of the X Test Suite that verifies the RECORD
-extension) is run, Xdmx passes and fails exactly the same tests as does
-a standard XFree86 X server. <!-- Tested February/March 2003 -->
-
-<p>There are two older XTEST-like extensions: DEC-XTRAP and
-XTestExtension1.  The XTestExtension1 extension was developed for use by
-the X Testing Consortium for use with a test suite that eventually
-became (part of?) the X Test Suite.  Unlike XTEST, which only allows
-events to be sent to the server, the XTestExtension1 extension also
-allowed events to be recorded (similar to the RECORD extension).  The
-second is the DEC-XTRAP extension that was developed by the Digital
-Equipment Corporation.
-
-<p>The DEC-XTRAP extension is available from Xdmx and has been tested
-with the <tt/xtrap*/ tools which are distributed as standard X11R6
-clients. <!-- Tested March 2003 -->
-
-<p>The XTestExtension1 is <em/not/ supported because it does not appear
-to be used by any modern X clients (the few that support it also support
-XTEST) and because there are no good methods available for testing that
-it functions correctly (unlike XTEST and DEC-XTRAP, the code for
-XTestExtension1 is not part of the standard X server source tree, so
-additional testing is important). <!-- Tested March 2003 -->
-
-<p>Most of these extensions are documented in the X11R6 source tree.
-Further, several original papers exist that this author was unable to
-locate -- for completeness and historical interest, citations are
-provide:
-<descrip>
-<tag/XRECORD/ Martha Zimet. Extending X For Recording.  8th Annual X
-Technical Conference Boston, MA January 24-26, 1994.
-<tag/DEC-XTRAP/ Dick Annicchiarico, Robert Chesler, Alan Jamison. XTrap
-Architecture. Digital Equipment Corporation, July 1991.
-<tag/XTestExtension1/ Larry Woestman. X11 Input Synthesis Extension
-Proposal. Hewlett Packard, November 1991.
-</descrip>
-
-<sect3>MIT-MISC (not supported)
-
-<p>The MIT-MISC extension is used to control a bug-compatibility flag
-that provides compatibility with xterm programs from X11R1 and X11R2.
-There does not appear to be a single client available that makes use of
-this extension and there is not way to verify that it works correctly.
-The Xdmx server does <em/not/ support MIT-MISC.
-
-<sect3>SCREENSAVER (not supported)
-
-<p>This extension provides special support for the X screen saver.  It
-was tested with beforelight, which appears to be the only client that
-works with it.  When Xinerama was not active, <tt/beforelight/ behaved
-as expected.  However, when Xinerama was active, <tt/beforelight/ did
-not behave as expected.  Further, when this extension is not active,
-<tt/xscreensaver/ (a widely-used X screen saver program) did not behave
-as expected.  Since this extension is not Xinerama-aware and is not
-commonly used with expected results by clients, we have left this
-extension disabled at this time.
-
-<sect3>GLX (supported)
-
-<p>The GLX extension provides OpenGL and GLX windowing support.  In
-Xdmx, the extension is called glxProxy, and it is Xinerama aware.  It
-works by either feeding requests forward through Xdmx to each of the
-back-end servers or handling them locally.  All rendering requests are
-handled on the back-end X servers.  This code was donated to the DMX
-project by SGI.  For the X Test Suite results comparison, see below.
-
-<sect3>RENDER (supported)
-
-<p>The X Rendering Extension (RENDER) provides support for digital image
-composition.  Geometric and text rendering are supported.  RENDER is
-partially Xinerama-aware, with text and the most basic compositing
-operator; however, its higher level primitives (triangles, triangle
-strips, and triangle fans) are not yet Xinerama-aware.  The RENDER
-extension is still under development, and is currently at version 0.8.
-Additional support will be required in DMX as more primitives and/or
-requests are added to the extension.
-
-<p>There is currently no test suite for the X Rendering Extension;
-however, there has been discussion of developing a test suite as the
-extension matures.  When that test suite becomes available, additional
-testing can be performed with Xdmx.  The X Test Suite passed and failed
-the exact same tests before and after this extension was enabled.
-
-<sect3>Summary
-
-<!-- WARNING: this list is duplicated in the "Common X extension
-support" section -->
-<p>To summarize, the following extensions are currently supported:
-    BIG-REQUESTS,
-    DEC-XTRAP,
-    DMX,
-    DPMS,
-    Extended-Visual-Information,
-    GLX,
-    LBX,
-    RECORD,
-    RENDER,
-    SECURITY,
-    SHAPE,
-    SYNC,
-    X-Resource,
-    XC-APPGROUP,
-    XC-MISC,
-    XFree86-Bigfont,
-    XINERAMA,
-    XInputExtension,
-    XKEYBOARD, and
-    XTEST.
-
-<p>The following extensions are <em/not/ supported at this time:
-    DOUBLE-BUFFER,
-    FontCache,
-    MIT-SCREEN-SAVER,
-    MIT-SHM,
-    MIT-SUNDRY-NONSTANDARD,
-    TOG-CUP,
-    XFree86-DGA,
-    XFree86-Misc,
-    XFree86-VidModeExtension,
-    XTestExtensionExt1, and
-    XVideo.
-
-<sect2>Additional Testing with the X Test Suite
-
-<sect3>XFree86 without XTEST
-
-<p>After the release of XFree86 4.3.0, we retested the XFree86 X server
-with and without using the XTEST extension.  When the XTEST extension
-was <em/not/ used for testing, the XFree86 4.3.0 server running on our
-usual test system with a Radeon VE card reported unexpected failures in
-the following tests:
-<verb>
-XListPixmapFormats: Test 1
-XChangeKeyboardControl: Tests 9, 10
-XGetDefault: Test 5
-XRebindKeysym: Test 1
-</verb>
-
-<sect3>XFree86 with XTEST
-
-<p>When using the XTEST extension, the XFree86 4.3.0 server reported the
-following errors:
-<verb>
-XListPixmapFormats: Test 1
-XChangeKeyboardControl: Tests 9, 10
-XGetDefault: Test 5
-XRebindKeysym: Test 1
-
-XAllowEvents: Tests 20, 21, 24
-XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25
-XGrabKey: Test 8
-XSetPointerMapping: Test 3
-XUngrabButton: Test 4
-</verb>
-
-<p>While these errors may be important, they will probably be fixed
-eventually in the XFree86 source tree.  We are particularly interested
-in demonstrating that the Xdmx server does not introduce additional
-failures that are not known Xinerama failures.
-
-<sect3>Xdmx with XTEST, without Xinerama, without GLX
-
-<p>Without Xinerama, but using the XTEST extension, the following errors
-were reported from Xdmx (note that these are the same as for the XFree86
-4.3.0, except that XGetDefault no longer fails):
-<verb>
-XListPixmapFormats: Test 1
-XChangeKeyboardControl: Tests 9, 10
-XRebindKeysym: Test 1
-
-XAllowEvents: Tests  20, 21, 24
-XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25
-XGrabKey: Test 8
-XSetPointerMapping: Test 3
-XUngrabButton: Test 4
-</verb>
-
-<sect3>Xdmx with XTEST, with Xinerama, without GLX
-
-<p>With Xinerama, using the XTEST extension, the following errors
-were reported from Xdmx:
-<verb>
-XListPixmapFormats: Test 1
-XChangeKeyboardControl: Tests 9, 10
-XRebindKeysym: Test 1
-
-XAllowEvents: Tests 20, 21, 24
-XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25
-XGrabKey: Test 8
-XSetPointerMapping: Test 3
-XUngrabButton: Test 4
-
-XCopyPlane: Tests 13, 22, 31 (well-known XTEST/Xinerama interaction issue)
-XDrawLine: Test 67
-XDrawLines: Test 91
-XDrawSegments: Test 68
-</verb>
-Note that the first two sets of errors are the same as for the XFree86
-4.3.0 server, and that the XCopyPlane error is a well-known error
-resulting from an XTEST/Xinerama interaction when the request crosses a
-screen boundary.  The XDraw* errors are resolved when the tests are run
-individually and they do not cross a screen boundary.  We will
-investigate these errors further to determine their cause.
-
-<sect3>Xdmx with XTEST, with Xinerama, with GLX
-
-<p>With GLX enabled, using the XTEST extension, the following errors
-were reported from Xdmx (these results are from early during the Phase
-IV development, but were confirmed with a late Phase IV snapshot):
-<verb>
-XListPixmapFormats: Test 1
-XChangeKeyboardControl: Tests 9, 10
-XRebindKeysym: Test 1
-
-XAllowEvents: Tests 20, 21, 24
-XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25
-XGrabKey: Test 8
-XSetPointerMapping: Test 3
-XUngrabButton: Test 4
-
-XClearArea: Test 8
-XCopyArea: Tests 4, 5, 11, 14, 17, 23, 25, 27, 30
-XCopyPlane: Tests 6, 7, 10, 19, 22, 31
-XDrawArcs: Tests 89, 100, 102
-XDrawLine: Test 67
-XDrawSegments: Test 68
-</verb>
-Note that the first two sets of errors are the same as for the XFree86
-4.3.0 server, and that the third set has different failures than when
-Xdmx does not include GLX support.  Since the GLX extension adds new
-visuals to support GLX's visual configs and the X Test Suite runs tests
-over the entire set of visuals, additional rendering tests were run and
-presumably more of them crossed a screen boundary.  This conclusion is
-supported by the fact that nearly all of the rendering errors reported
-are resolved when the tests are run individually and they do no cross a
-screen boundary.
-
-<p>Further, when hardware rendering is disabled on the back-end displays,
-many of the errors in the third set are eliminated, leaving only:
-<verb>
-XClearArea: Test 8
-XCopyArea: Test 4, 5, 11, 14, 17, 23, 25, 27, 30
-XCopyPlane: Test 6, 7, 10, 19, 22, 31
-</verb>
-
-<sect3>Conclusion
-
-<p>We conclude that all of the X Test Suite errors reported for Xdmx are
-the result of errors in the back-end X server or the Xinerama
-implementation.  Further, all of these errors that can be reasonably
-fixed at the Xdmx layer have been.  (Where appropriate, we have
-submitted patches to the XFree86 and Xinerama upstream maintainers.)
-
-<sect2>Dynamic Reconfiguration
-
-<p>During this development phase, dynamic reconfiguration support was
-added to DMX.  This support allows an application to change the position
-and offset of a back-end server's screen.  For example, if the
-application would like to shift a screen slightly to the left, it could
-query Xdmx for the screen's &lt;x,y&gt; position and then dynamically
-reconfigure that screen to be at position &lt;x+10,y&gt;.  When a screen
-is dynamically reconfigured, input handling and a screen's root window
-dimensions are adjusted as needed.  These adjustments are transparent to
-the user.
-
-<sect3>Dynamic reconfiguration extension
-
-<p>The application interface to DMX's dynamic reconfiguration is through
-a function in the DMX extension library:
-<verb>
-Bool DMXReconfigureScreen(Display *dpy, int screen, int x, int y)
-</verb>
-where <it/dpy/ is DMX server's display, <it/screen/ is the number of the
-screen to be reconfigured, and <it/x/ and <it/y/ are the new upper,
-left-hand coordinates of the screen to be reconfigured.
-
-<p>The coordinates are not limited other than as required by the X
-protocol, which limits all coordinates to a signed 16 bit number.  In
-addition, all coordinates within a screen must also be legal values.
-Therefore, setting a screen's upper, left-hand coordinates such that the
-right or bottom edges of the screen is greater than 32,767 is illegal.
-
-<sect3>Bounding box
-
-<p>When the Xdmx server is started, a bounding box is calculated from
-the screens' layout given either on the command line or in the
-configuration file.  This bounding box is currently fixed for the
-lifetime of the Xdmx server.
-
-<p>While it is possible to move a screen outside of the bounding box, it
-is currently not possible to change the dimensions of the bounding box.
-For example, it is possible to specify coordinates of &lt;-100,-100&gt;
-for the upper, left-hand corner of the bounding box, which was
-previously at coordinates &lt;0,0&gt;.  As expected, the screen is moved
-down and to the right; however, since the bounding box is fixed, the
-left side and upper portions of the screen exposed by the
-reconfiguration are no longer accessible on that screen.  Those
-inaccessible regions are filled with black.
-
-<p>This fixed bounding box limitation will be addressed in a future
-development phase.
-
-<sect3>Sample applications
-
-<p>An example of where this extension is useful is in setting up a video
-wall.  It is not always possible to get everything perfectly aligned,
-and sometimes the positions are changed (e.g., someone might bump into a
-projector).  Instead of physically moving projectors or monitors, it is
-now possible to adjust the positions of the back-end server's screens
-using the dynamic reconfiguration support in DMX.
-
-<p>Other applications, such as automatic setup and calibration tools,
-can make use of dynamic reconfiguration to correct for projector
-alignment problems, as long as the projectors are still arranged
-rectilinearly.  Horizontal and vertical keystone correction could be
-applied to projectors to correct for non-rectilinear alignment problems;
-however, this must be done external to Xdmx.
-
-<p>A sample test program is included in the DMX server's examples
-directory to demonstrate the interface and how an application might use
-dynamic reconfiguration.  See <tt/dmxreconfig.c/ for details.
-
-<sect3>Additional notes
-
-<p>In the original development plan, Phase IV was primarily devoted to
-adding OpenGL support to DMX; however, SGI became interested in the DMX
-project and developed code to support OpenGL/GLX.  This code was later
-donated to the DMX project and integrated into the DMX code base, which
-freed the DMX developers to concentrate on dynamic reconfiguration (as
-described above).
-
-<sect2>Doxygen documentation
-
-<p>Doxygen is an open-source (GPL) documentation system for generating
-browseable documentation from stylized comments in the source code.  We
-have placed all of the Xdmx server and DMX protocol source code files
-under Doxygen so that comprehensive documentation for the Xdmx source
-code is available in an easily browseable format.
-
-<sect2>Valgrind
-
-<p>Valgrind, an open-source (GPL) memory debugger for Linux, was used to
-search for memory management errors.  Several memory leaks were detected
-and repaired.  The following errors were not addressed:
-<enum>
-    <item>
-        When the X11 transport layer sends a reply to the client, only
-        those fields that are required by the protocol are filled in --
-        unused fields are left as uninitialized memory and are therefore
-        noted by valgrind.  These instances are not errors and were not
-        repaired.
-    <item>
-        At each server generation, glxInitVisuals allocates memory that
-        is never freed.  The amount of memory lost each generation
-        approximately equal to 128 bytes for each back-end visual.
-        Because the code involved is automatically generated, this bug
-        has not been fixed and will be referred to SGI.
-    <item>
-        At each server generation, dmxRealizeFont calls XLoadQueryFont,
-        which allocates a font structure that is not freed.
-        dmxUnrealizeFont can free the font structure for the first
-        screen, but cannot free it for the other screens since they are
-        already closed by the time dmxUnrealizeFont could free them.
-        The amount of memory lost each generation is approximately equal
-        to 80 bytes per font per back-end.  When this bug is fixed in
-        the the X server's device-independent (dix) code, DMX will be
-        able to properly free the memory allocated by XLoadQueryFont.
-</enum>
-
-<sect2>RATS
-
-<p>RATS (Rough Auditing Tool for Security) is an open-source (GPL)
-security analysis tool that scans source code for common
-security-related programming errors (e.g., buffer overflows and TOCTOU
-races).  RATS was used to audit all of the code in the hw/dmx directory
-and all "High" notations were checked manually.  The code was either
-re-written to eliminate the warning, or a comment containing "RATS" was
-inserted on the line to indicate that a human had checked the code.
-Unrepaired warnings are as follows:
-<enum>
-    <item>
-        Fixed-size buffers are used in many areas, but code has been
-        added to protect against buffer overflows (e.g., XmuSnprint).
-        The only instances that have not yet been fixed are in
-        config/xdmxconfig.c (which is not part of the Xdmx server) and
-        input/usb-common.c.
-    <item>
-        vprintf and vfprintf are used in the logging routines.  In
-        general, all uses of these functions (e.g., dmxLog) provide a
-        constant format string from a trusted source, so the use is
-        relatively benign.
-    <item>
-        glxProxy/glxscreens.c uses getenv and strcat.  The use of these
-        functions is safe and will remain safe as long as
-        ExtensionsString is longer then GLXServerExtensions (ensuring
-        this may not be ovious to the casual programmer, but this is in
-        automatically generated code, so we hope that the generator
-        enforces this constraint).
-</enum>
-
-  </article>
-  
-  <!-- Local Variables: -->
-  <!-- fill-column: 72  -->
-  <!-- End:             -->
diff --git a/hw/dmx/doc/dmx.xml b/hw/dmx/doc/dmx.xml
new file mode 100644
index 0000000..12d7067
--- /dev/null
+++ b/hw/dmx/doc/dmx.xml
@@ -0,0 +1,3447 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+]>
+
+<article>
+
+  <articleinfo>
+    <!-- Title information -->
+    <title>Distributed Multihead X design</title>
+    <authorgroup>
+      <author><firstname>Kevin E.</firstname><surname>Martin</surname></author>
+      <author><firstname>David H.</firstname><surname>Dawes</surname></author>
+      <author><firstname>Rickard E.</firstname><surname>Faith</surname></author>
+    </authorgroup>
+    <pubdate>29 June 2004 (created 25 July 2001)</pubdate>
+    <abstract><para>
+        This document covers the motivation, background, design, and
+        implementation of the distributed multihead X (DMX) system.  It
+        is a living document and describes the current design and
+        implementation details of the DMX system.  As the project
+        progresses, this document will be continually updated to reflect
+        the changes in the code and/or design.  <emphasis remap="it">Copyright 2001 by VA
+        Linux Systems, Inc., Fremont, California.  Copyright 2001-2004
+        by Red Hat, Inc., Raleigh, North Carolina</emphasis>
+      </para></abstract>
+  </articleinfo>
+
+<!-- Begin the document -->
+<sect1>
+<title>Introduction</title>
+
+<sect2>
+<title>The Distributed Multihead X Server</title>
+
+<para>Current Open Source multihead solutions are limited to a single
+physical machine.  A single X server controls multiple display devices,
+which can be arranged as independent heads or unified into a single
+desktop (with Xinerama).  These solutions are limited to the number of
+physical devices that can co-exist in a single machine (e.g., due to the
+number of AGP/PCI slots available for graphics cards).  Thus, large
+tiled displays are not currently possible.  The work described in this
+paper will eliminate the requirement that the display devices reside in
+the same physical machine.  This will be accomplished by developing a
+front-end proxy X server that will control multiple back-end X servers
+that make up the large display.
+</para>
+
+<para>The overall structure of the distributed multihead X (DMX) project is
+as follows: A single front-end X server will act as a proxy to a set of
+back-end X servers, which handle all of the visible rendering.  X
+clients will connect to the front-end server just as they normally would
+to a regular X server.  The front-end server will present an abstracted
+view to the client of a single large display.  This will ensure that all
+standard X clients will continue to operate without modification
+(limited, as always, by the visuals and extensions provided by the X
+server).  Clients that are DMX-aware will be able to use an extension to
+obtain information about the back-end servers (e.g., for placement of
+pop-up windows, window alignments by the window manager, etc.).
+</para>
+
+<para>The architecture of the DMX server is divided into two main sections:
+input (e.g., mouse and keyboard events) and output (e.g., rendering and
+windowing requests).  Each of these are describe briefly below, and the
+rest of this design document will describe them in greater detail.
+</para>
+
+<para>The DMX server can receive input from three general types of input
+devices: "local" devices that are physically attached to the machine on
+which DMX is running, "backend" devices that are physically attached to
+one or more of the back-end X servers (and that generate events via the
+X protocol stream from the backend), and "console" devices that can be
+abstracted from any non-back-end X server.  Backend and console devices
+are treated differently because the pointer device on the back-end X
+server also controls the location of the hardware X cursor.  Full
+support for XInput extension devices is provided.
+</para>
+
+<para>Rendering requests will be accepted by the front-end server; however,
+rendering to visible windows will be broken down as needed and sent to
+the appropriate back-end server(s) via X11 library calls for actual
+rendering.  The basic framework will follow a Xnest-style approach.  GC
+state will be managed in the front-end server and sent to the
+appropriate back-end server(s) as required.  Pixmap rendering will (at
+least initially) be handled by the front-end X server.  Windowing
+requests (e.g., ordering, mapping, moving, etc.) will handled in the
+front-end server.  If the request requires a visible change, the
+windowing operation will be translated into requests for the appropriate
+back-end server(s).  Window state will be mirrored in the back-end
+server(s) as needed.
+</para>
+</sect2>
+
+<sect2>
+<title>Layout of Paper</title>
+
+<para>The next section describes the general development plan that was
+actually used for implementation.  The final section discusses
+outstanding issues at the conclusion of development.  The first appendix
+provides low-level technical detail that may be of interest to those
+intimately familiar with the X server architecture.  The final appendix
+describes the four phases of development that were performed during the
+first two years of development.
+</para>
+
+<para>The final year of work was divided into 9 tasks that are not
+described in specific sections of this document.  The major tasks during
+that time were the enhancement of the reconfiguration ability added in
+Phase IV, addition of support for a dynamic number of back-end displays
+(instead of a hard-coded limit), and the support for back-end display
+and input removal and addition.  This work is mentioned in this paper,
+but is not covered in detail.
+</para>
+</sect2>
+</sect1>
+
+<!-- ============================================================ -->
+<sect1>
+<title>Development plan</title>
+
+<para>This section describes the development plan from approximately June
+2001 through July 2003.
+</para>
+
+<sect2>
+<title>Bootstrap code</title>
+
+<para>To allow for rapid development of the DMX server by multiple
+developers during the first development stage, the problem will be
+broken down into three tasks: the overall DMX framework, back-end
+rendering services and input device handling services.  However, before
+the work begins on these tasks, a simple framework that each developer
+could use was implemented to bootstrap the development effort.  This
+framework renders to a single back-end server and provides dummy input
+devices (i.e., the keyboard and mouse).  The simple back-end rendering
+service was implemented using the shadow framebuffer support currently
+available in the XFree86 environment.
+</para>
+
+<para>Using this bootstrapping framework, each developer has been able to
+work on each of the tasks listed above independently as follows: the
+framework will be extended to handle arbitrary back-end server
+configurations; the back-end rendering services will be transitioned to
+the more efficient Xnest-style implementation; and, an input device
+framework to handle various input devices via the input extension will
+be developed.
+</para>
+
+<para>Status: The boot strap code is complete.   <!-- August 2001 -->
+</para>
+
+</sect2>
+
+<sect2>
+<title>Input device handling</title>
+
+<para>An X server (including the front-end X server) requires two core
+input devices -- a keyboard and a pointer (mouse).  These core devices
+are handled and required by the core X11 protocol.  Additional types of
+input devices may be attached and utilized via the XInput extension.
+These are usually referred to as ``XInput extension devices'',
+</para>
+
+<para>There are some options as to how the front-end X server gets its core
+input devices:
+
+<orderedlist>
+<listitem>
+    <para>Local Input. The physical input devices (e.g., keyboard and
+    mouse) can be attached directly to the front-end X server.  In this
+    case, the keyboard and mouse on the machine running the front-end X
+    server will be used.  The front-end will have drivers to read the
+    raw input from those devices and convert it into the required X
+    input events (e.g., key press/release, pointer button press/release,
+    pointer motion).  The front-end keyboard driver will keep track of
+    keyboard properties such as key and modifier mappings, autorepeat
+    state, keyboard sound and led state.  Similarly the front-end
+    pointer driver will keep track if pointer properties such as the
+    button mapping and movement acceleration parameters.  With this
+    option, input is handled fully in the front-end X server, and the
+    back-end X servers are used in a display-only mode.  This option was
+    implemented and works for a limited number of Linux-specific
+    devices.  Adding additional local input devices for other
+    architectures is expected to be relatively simple.
+</para>
+
+    <para>The following options are available for implementing local input
+    devices:
+
+<orderedlist>
+<listitem>
+        <para>The XFree86 X server has modular input drivers that could
+        be adapted for this purpose.  The mouse driver supports a wide
+        range of mouse types and interfaces, as well as a range of
+        Operating System platforms.  The keyboard driver in XFree86 is
+        not currently as modular as the mouse driver, but could be made
+        so.  The XFree86 X server also has a range of other input
+        drivers for extended input devices such as tablets and touch
+        screens.  Unfortunately, the XFree86 drivers are generally
+        complex, often simultaneously providing support for multiple
+        devices across multiple architectures; and rely so heavily on
+        XFree86-specific helper-functions, that this option was not
+        pursued.
+</para>
+</listitem>
+
+<listitem>
+        <para>The <command>kdrive</command> X server in XFree86 has built-in drivers that
+        support PS/2 mice and keyboard under Linux.  The mouse driver
+        can indirectly handle other mouse types if the Linux utility
+        <command>gpm</command> is used as to translate the native mouse protocol into
+        PS/2 mouse format.  These drivers could be adapted and built in
+        to the front-end X server if this range of hardware and OS
+        support is sufficient.  While much simpler than the XFree86
+        drivers, the <command>kdrive</command> drivers were not used for the DMX
+        implementation.
+</para>
+</listitem>
+
+<listitem>
+        <para>Reimplementation of keyboard and mouse drivers from
+        scratch for the DMX framework.  Because keyboard and mouse
+        drivers are relatively trivial to implement, this pathway was
+        selected.  Other drivers in the X source tree were referenced,
+        and significant contributions from other drivers are noted in
+        the DMX source code.
+</para>
+</listitem>
+</orderedlist>
+</para>
+</listitem>
+
+<listitem>
+    <para>Backend Input.  The front-end can make use of the core input
+    devices attached to one or more of the back-end X servers.  Core
+    input events from multiple back-ends are merged into a single input
+    event stream.  This can work sanely when only a single set of input
+    devices is used at any given time.  The keyboard and pointer state
+    will be handled in the front-end, with changes propagated to the
+    back-end servers as needed.  This option was implemented and works
+    well.  Because the core pointer on a back-end controls the hardware
+    mouse on that back-end, core pointers cannot be treated as XInput
+    extension devices.  However, all back-end XInput extensions devices
+    can be mapped to either DMX core or DMX XInput extension devices.
+</para>
+</listitem>
+
+<listitem>
+    <para>Console Input.  The front-end server could create a console
+    window that is displayed on an X server independent of the back-end
+    X servers.  This console window could display things like the
+    physical screen layout, and the front-end could get its core input
+    events from events delivered to the console window.  This option was
+    implemented and works well.  To help the human navigate, window
+    outlines are also displayed in the console window.  Further, console
+    windows can be used as either core or XInput extension devices.
+</para>
+</listitem>
+
+<listitem>
+    <para>Other options were initially explored, but they were all
+    partial subsets of the options listed above and, hence, are
+    irrelevant.
+</para>
+</listitem>
+
+</orderedlist>
+</para>
+
+<para>Although extended input devices are not specifically mentioned in the
+Distributed X requirements, the options above were all implemented so
+that XInput extension devices were supported.
+</para>
+
+<para>The bootstrap code (Xdmx) had dummy input devices, and these are
+still supported in the final version.  These do the necessary
+initialization to satisfy the X server's requirements for core pointer
+and keyboard devices, but no input events are ever generated.
+</para>
+
+<para>Status: The input code is complete.  Because of the complexity of the
+XFree86 input device drivers (and their heavy reliance on XFree86
+infrastructure), separate low-level device drivers were implemented for
+Xdmx.  The following kinds of drivers are supported (in general, the
+devices can be treated arbitrarily as "core" input devices or as XInput
+"extension" devices; and multiple instances of different kinds of
+devices can be simultaneously available):
+<orderedlist>
+<listitem>
+        <para> A "dummy" device drive that never generates events.
+</para>
+</listitem>
+
+<listitem>
+        <para> "Local" input is from the low-level hardware on which the
+        Xdmx binary is running.  This is the only area where using the
+        XFree86 driver infrastructure would have been helpful, and then
+        only partially, since good support for generic USB devices does
+        not yet exist in XFree86 (in any case, XFree86 and kdrive driver
+        code was used where possible).  Currently, the following local
+        devices are supported under Linux (porting to other operating
+        systems should be fairly straightforward):
+        <itemizedlist>
+            <listitem><para>Linux keyboard</para></listitem>
+            <listitem><para>Linux serial mouse (MS)</para></listitem>
+            <listitem><para>Linux PS/2 mouse</para></listitem>
+            <listitem><para>USB keyboard</para></listitem>
+            <listitem><para>USB mouse</para></listitem>
+            <listitem><para>USB generic device (e.g., joystick, gamepad, etc.)</para></listitem>
+        </itemizedlist>
+</para>
+</listitem>
+
+<listitem>
+        <para> "Backend" input is taken from one or more of the back-end
+        displays.  In this case, events are taken from the back-end X
+        server and are converted to Xdmx events.  Care must be taken so
+        that the sprite moves properly on the display from which input
+        is being taken.
+</para>
+</listitem>
+
+<listitem>
+        <para> "Console" input is taken from an X window that Xdmx
+        creates on the operator's display (i.e., on the machine running
+        the Xdmx binary).  When the operator's mouse is inside the
+        console window, then those events are converted to Xdmx events.
+        Several special features are available: the console can display
+        outlines of windows that are on the Xdmx display (to facilitate
+        navigation), the cursor can be confined to the console, and a
+        "fine" mode can be activated to allow very precise cursor
+        positioning.
+</para>
+</listitem>
+</orderedlist>
+
+</para>
+
+</sect2>
+
+<!-- May 2002; July 2003 -->
+
+<sect2>
+<title>Output device handling</title>
+
+<para>The output of the DMX system displays rendering and windowing
+requests across multiple screens.  The screens are typically arranged in
+a grid such that together they represent a single large display.
+</para>
+
+<para>The output section of the DMX code consists of two parts.  The first
+is in the front-end proxy X server (Xdmx), which accepts client
+connections, manages the windows, and potentially renders primitives but
+does not actually display any of the drawing primitives.  The second
+part is the back-end X server(s), which accept commands from the
+front-end server and display the results on their screens.
+</para>
+
+<sect3>
+<title>Initialization</title>
+
+<para>The DMX front-end must first initialize its screens by connecting to
+each of the back-end X servers and collecting information about each of
+these screens.  However, the information collected from the back-end X
+servers might be inconsistent.  Handling these cases can be difficult
+and/or inefficient.  For example, a two screen system has one back-end X
+server running at 16bpp while the second is running at 32bpp.
+Converting rendering requests (e.g., XPutImage() or XGetImage()
+requests) to the appropriate bit depth can be very time consuming.
+Analyzing these cases to determine how or even if it is possible to
+handle them is required.  The current Xinerama code handles many of
+these cases (e.g., in PanoramiXConsolidate()) and will be used as a
+starting point.  In general, the best solution is to use homogeneous X
+servers and display devices.  Using back-end servers with the same depth
+is a requirement of the final DMX implementation.
+</para>
+
+<para>Once this screen consolidation is finished, the relative position of
+each back-end X server's screen in the unified screen is initialized.  A
+full-screen window is opened on each of the back-end X servers, and the
+cursor on each screen is turned off.  The final DMX implementation can
+also make use of a partial-screen window, or multiple windows per
+back-end screen.
+</para>
+</sect3>
+
+<sect3>
+<title>Handling rendering requests</title>
+
+<para>After initialization, X applications connect to the front-end server.
+There are two possible implementations of how rendering and windowing
+requests are handled in the DMX system:
+
+<orderedlist>
+<listitem>
+    <para>A shadow framebuffer is used in the front-end server as the
+    render target.  In this option, all protocol requests are completely
+    handled in the front-end server.  All state and resources are
+    maintained in the front-end including a shadow copy of the entire
+    framebuffer.  The framebuffers attached to the back-end servers are
+    updated by XPutImage() calls with data taken directly from the
+    shadow framebuffer.
+</para>
+
+    <para>This solution suffers from two main problems.  First, it does not
+    take advantage of any accelerated hardware available in the system.
+    Second, the size of the XPutImage() calls can be quite large and
+    thus will be limited by the bandwidth available.
+</para>
+
+    <para>The initial DMX implementation used a shadow framebuffer by
+    default.
+</para>
+</listitem>
+
+<listitem>
+    <para>Rendering requests are sent to each back-end server for
+    handling (as is done in the Xnest server described above).  In this
+    option, certain protocol requests are handled in the front-end
+    server and certain requests are repackaged and then sent to the
+    back-end servers.  The framebuffer is distributed across the
+    multiple back-end servers.  Rendering to the framebuffer is handled
+    on each back-end and can take advantage of any acceleration
+    available on the back-end servers' graphics display device.  State
+    is maintained both in the front and back-end servers.
+</para>
+
+    <para>This solution suffers from two main drawbacks.  First, protocol
+    requests are sent to all back-end servers -- even those that will
+    completely clip the rendering primitive -- which wastes bandwidth
+    and processing time.  Second, state is maintained both in the front-
+    and back-end servers.  These drawbacks are not as severe as in
+    option 1 (above) and can either be overcome through optimizations or
+    are acceptable.  Therefore, this option will be used in the final
+    implementation.
+</para>
+
+    <para>The final DMX implementation defaults to this mechanism, but also
+    supports the shadow framebuffer mechanism.  Several optimizations
+    were implemented to eliminate the drawbacks of the default
+    mechanism.  These optimizations are described the section below and
+    in Phase II of the Development Results (see appendix).
+</para>
+</listitem>
+
+</orderedlist>
+</para>
+
+<para>Status: Both the shadow framebuffer and Xnest-style code is complete.
+<!-- May 2002 -->
+</para>
+
+</sect3>
+</sect2>
+
+<sect2>
+<title>Optimizing DMX</title>
+
+<para>Initially, the Xnest-style solution's performance will be measured
+and analyzed to determine where the performance bottlenecks exist.
+There are four main areas that will be addressed.
+</para>
+
+<para>First, to obtain reasonable interactivity with the first development
+phase, XSync() was called after each protocol request.  The XSync()
+function flushes any pending protocol requests.  It then waits for the
+back-end to process the request and send a reply that the request has
+completed.  This happens with each back-end server and performance
+greatly suffers.  As a result of the way XSync() is called in the first
+development phase, the batching that the X11 library performs is
+effectively defeated.  The XSync() call usage will be analyzed and
+optimized by batching calls and performing them at regular intervals,
+except where interactivity will suffer (e.g., on cursor movements).
+</para>
+
+<para>Second, the initial Xnest-style solution described above sends the
+repackaged protocol requests to all back-end servers regardless of
+whether or not they would be completely clipped out.  The requests that
+are trivially rejected on the back-end server wastes the limited
+bandwidth available.  By tracking clipping changes in the DMX X server's
+windowing code (e.g., by opening, closing, moving or resizing windows),
+we can determine whether or not back-end windows are visible so that
+trivial tests in the front-end server's GC ops drawing functions can
+eliminate these unnecessary protocol requests.
+</para>
+
+<para>Third, each protocol request will be analyzed to determine if it is
+possible to break the request into smaller pieces at display boundaries.
+The initial ones to be analyzed are put and get image requests since
+they will require the greatest bandwidth to transmit data between the
+front and back-end servers.  Other protocol requests will be analyzed
+and those that will benefit from breaking them into smaller requests
+will be implemented.
+</para>
+
+<para>Fourth, an extension is being considered that will allow font glyphs to
+be transferred from the front-end DMX X server to each back-end server.
+This extension will permit the front-end to handle all font requests and
+eliminate the requirement that all back-end X servers share the exact
+same fonts as the front-end server.  We are investigating the
+feasibility of this extension during this development phase.
+</para>
+
+<para>Other potential optimizations will be determined from the performance
+analysis.
+</para>
+
+<para>Please note that in our initial design, we proposed optimizing BLT
+operations (e.g., XCopyArea() and window moves) by developing an
+extension that would allow individual back-end servers to directly copy
+pixel data to other back-end servers.  This potential optimization was
+in response to the simple image movement implementation that required
+potentially many calls to GetImage() and PutImage().  However, the
+current Xinerama implementation handles these BLT operations
+differently.  Instead of copying data to and from screens, they generate
+expose events -- just as happens in the case when a window is moved from
+off a screen to on screen.  This approach saves the limited bandwidth
+available between front and back-end servers and is being standardized
+with Xinerama.  It also eliminates the potential setup problems and
+security issues resulting from having each back-end server open
+connections to all other back-end servers.  Therefore, we suggest
+accepting Xinerama's expose event solution.
+</para>
+
+<para>Also note that the approach proposed in the second and third
+optimizations might cause backing store algorithms in the back-end to be
+defeated, so a DMX X server configuration flag will be added to disable
+these optimizations.
+</para>
+
+<para>Status: The optimizations proposed above are complete.  It was
+determined that the using the xfs font server was sufficient and
+creating a new mechanism to pass glyphs was redundant; therefore, the
+fourth optimization proposed above was not included in DMX.
+<!-- September 2002 -->
+</para>
+
+</sect2>
+
+<sect2>
+<title>DMX X extension support</title>
+
+<para>The DMX X server keeps track of all the windowing information on the
+back-end X servers, but does not currently export this information to
+any client applications.  An extension will be developed to pass the
+screen information and back-end window IDs to DMX-aware clients.  These
+clients can then use this information to directly connect to and render
+to the back-end windows.  Bypassing the DMX X server allows DMX-aware
+clients to break up complex rendering requests on their own and send
+them directly to the windows on the back-end server's screens.  An
+example of a client that can make effective use of this extension is
+Chromium.
+</para>
+
+<para>Status: The extension, as implemented, is fully documented in
+"Client-to-Server DMX Extension to the X Protocol".  Future changes
+might be required based on feedback and other proposed enhancements to
+DMX.  Currently, the following facilities are supported:
+<orderedlist>
+<listitem><para>
+        Screen information (clipping rectangle for each screen relative
+        to the virtual screen)
+</para></listitem>
+<listitem><para>
+        Window information (window IDs and clipping information for each
+        back-end window that corresponds to each DMX window)
+</para></listitem>
+<listitem><para>
+        Input device information (mappings from DMX device IDs to
+        back-end device IDs)
+</para></listitem>
+<listitem><para>
+        Force window creation (so that a client can override the
+        server-side lazy window creation optimization)
+</para></listitem>
+<listitem><para>
+        Reconfiguration (so that a client can request that a screen
+        position be changed)
+</para></listitem>
+<listitem><para>
+        Addition and removal of back-end servers and back-end and
+        console inputs.
+</para></listitem>
+</orderedlist>
+</para>
+<!-- September 2002; July 2003 -->
+
+</sect2>
+
+<sect2>
+<title>Common X extension support</title>
+
+<para>The XInput, XKeyboard and Shape extensions are commonly used
+extensions to the base X11 protocol.  XInput allows multiple and
+non-standard input devices to be accessed simultaneously.  These input
+devices can be connected to either the front-end or back-end servers.
+XKeyboard allows much better keyboard mappings control.  Shape adds
+support for arbitrarily shaped windows and is used by various window
+managers.  Nearly all potential back-end X servers make these extensions
+available, and support for each one will be added to the DMX system.
+</para>
+
+<para>In addition to the extensions listed above, support for the X
+Rendering extension (Render) is being developed.  Render adds digital
+image composition to the rendering model used by the X Window System.
+While this extension is still under development by Keith Packard of HP,
+support for the current version will be added to the DMX system.
+</para>
+
+<para>Support for the XTest extension was added during the first
+development phase.
+</para>
+
+<!-- WARNING: this list is duplicated in the Phase IV discussion -->
+<para>Status: The following extensions are supported and are discussed in
+more detail in Phase IV of the Development Results (see appendix):
+    BIG-REQUESTS,
+    DEC-XTRAP,
+    DMX,
+    DPMS,
+    Extended-Visual-Information,
+    GLX,
+    LBX,
+    RECORD,
+    RENDER,
+    SECURITY,
+    SHAPE,
+    SYNC,
+    X-Resource,
+    XC-APPGROUP,
+    XC-MISC,
+    XFree86-Bigfont,
+    XINERAMA,
+    XInputExtension,
+    XKEYBOARD, and
+    XTEST.
+<!-- November 2002; updated February 2003, July 2003 -->
+</para>
+</sect2>
+
+<sect2>
+<title>OpenGL support</title>
+
+<para>OpenGL support using the Mesa code base exists in XFree86 release 4
+and later.  Currently, the direct rendering infrastructure (DRI)
+provides accelerated OpenGL support for local clients and unaccelerated
+OpenGL support (i.e., software rendering) is provided for non-local
+clients.
+</para>
+
+<para>The single head OpenGL support in XFree86 4.x will be extended to use
+the DMX system.  When the front and back-end servers are on the same
+physical hardware, it is possible to use the DRI to directly render to
+the back-end servers.  First, the existing DRI will be extended to
+support multiple display heads, and then to support the DMX system.
+OpenGL rendering requests will be direct rendering to each back-end X
+server.  The DRI will request the screen layout (either from the
+existing Xinerama extension or a DMX-specific extension).  Support for
+synchronized swap buffers will also be added (on hardware that supports
+it).  Note that a single front-end server with a single back-end server
+on the same physical machine can emulate accelerated indirect rendering.
+</para>
+
+<para>When the front and back-end servers are on different physical
+hardware or are using non-XFree86 4.x X servers, a mechanism to render
+primitives across the back-end servers will be provided.  There are
+several options as to how this can be implemented.
+</para>
+
+<orderedlist>
+<listitem>
+    <para>The existing OpenGL support in each back-end server can be
+    used by repackaging rendering primitives and sending them to each
+    back-end server.  This option is similar to the unoptimized
+    Xnest-style approach mentioned above.  Optimization of this solution
+    is beyond the scope of this project and is better suited to other
+    distributed rendering systems.
+</para></listitem>
+
+<listitem>
+    <para>Rendering to a pixmap in the front-end server using the
+    current XFree86 4.x code, and then displaying to the back-ends via
+    calls to XPutImage() is another option.  This option is similar to
+    the shadow frame buffer approach mentioned above.  It is slower and
+    bandwidth intensive, but has the advantage that the back-end servers
+    are not required to have OpenGL support.
+</para></listitem>
+</orderedlist>
+
+<para>These, and other, options will be investigated in this phase of the
+work.
+</para>
+
+<para>Work by others have made Chromium DMX-aware.  Chromium will use the
+DMX X protocol extension to obtain information about the back-end
+servers and will render directly to those servers, bypassing DMX.
+</para>
+
+<para>Status: OpenGL support by the glxProxy extension was implemented by
+SGI and has been integrated into the DMX code base.
+</para>
+<!-- May 2003-->
+</sect2>
+
+</sect1>
+
+<!-- ============================================================ -->
+<sect1>
+<title>Current issues</title>
+
+<para>In this sections the current issues are outlined that require further
+investigation.
+</para>
+
+<sect2>
+<title>Fonts</title>
+
+<para>The font path and glyphs need to be the same for the front-end and
+each of the back-end servers.  Font glyphs could be sent to the back-end
+servers as necessary but this would consume a significant amount of
+available bandwidth during font rendering for clients that use many
+different fonts (e.g., Netscape).  Initially, the font server (xfs) will
+be used to provide the fonts to both the front-end and back-end servers.
+Other possibilities will be investigated during development.
+</para>
+</sect2>
+
+<sect2>
+<title>Zero width rendering primitives</title>
+
+<para>To allow pixmap and on-screen rendering to be pixel perfect, all
+back-end servers must render zero width primitives exactly the same as
+the front-end renders the primitives to pixmaps.  For those back-end
+servers that do not exactly match, zero width primitives will be
+automatically converted to one width primitives.  This can be handled in
+the front-end server via the GC state.
+</para>
+</sect2>
+
+<sect2>
+<title>Output scaling</title>
+
+<para>With very large tiled displays, it might be difficult to read the
+information on the standard X desktop.  In particular, the cursor can be
+easily lost and fonts could be difficult to read.  Automatic primitive
+scaling might prove to be very useful.  We will investigate the
+possibility of scaling the cursor and providing a set of alternate
+pre-scaled fonts to replace the standard fonts that many applications
+use (e.g., fixed).  Other options for automatic scaling will also be
+investigated.
+</para>
+</sect2>
+
+<sect2>
+<title>Per-screen colormaps</title>
+
+<para>Each screen's default colormap in the set of back-end X servers
+should be able to be adjusted via a configuration utility.  This support
+is would allow the back-end screens to be calibrated via custom gamma
+tables.  On 24-bit systems that support a DirectColor visual, this type
+of correction can be accommodated.  One possible implementation would be
+to advertise to X client of the DMX server a TrueColor visual while
+using DirectColor visuals on the back-end servers to implement this type
+of color correction.  Other options will be investigated.
+</para>
+</sect2>
+</sect1>
+
+<!-- ============================================================ -->
+<appendix>
+<title>Appendix</title>
+
+<sect1>
+<title>Background</title>
+
+<para>This section describes the existing Open Source architectures that
+can be used to handle multiple screens and upon which this development
+project is based.  This section was written before the implementation
+was finished, and may not reflect actual details of the implementation.
+It is left for historical interest only.
+</para>
+
+<sect2>
+<title>Core input device handling</title>
+
+<para>The following is a description of how core input devices are handled
+by an X server.
+</para>
+
+<sect3>
+<title>InitInput()</title>
+
+<para>InitInput() is a DDX function that is called at the start of each
+server generation from the X server's main() function.  Its purpose is
+to determine what input devices are connected to the X server, register
+them with the DIX and MI layers, and initialize the input event queue.
+InitInput() does not have a return value, but the X server will abort if
+either a core keyboard device or a core pointer device are not
+registered.  Extended input (XInput) devices can also be registered in
+InitInput().
+</para>
+
+<para>InitInput() usually has implementation specific code to determine
+which input devices are available.  For each input device it will be
+using, it calls AddInputDevice():
+
+<variablelist>
+<varlistentry>
+<term>AddInputDevice()</term>
+<listitem><para>This DIX function allocates the device structure,
+registers a callback function (which handles device init, close, on and
+off), and returns the input handle, which can be treated as opaque.  It
+is called once for each input device.
+</para></listitem>
+</varlistentry>
+</variablelist>
+</para>
+
+<para>Once input handles for core keyboard and core pointer devices have
+been obtained from AddInputDevice(), they are registered as core devices
+by calling RegisterPointerDevice() and RegisterKeyboardDevice().  Each
+of these should be called once.  If both core devices are not
+registered, then the X server will exit with a fatal error when it
+attempts to start the input devices in InitAndStartDevices(), which is
+called directly after InitInput() (see below).
+
+<variablelist>
+<varlistentry>
+<term>Register{Pointer,Keyboard}Device()</term>
+<listitem><para>These DIX functions take a
+handle returned from AddInputDevice() and initialize the core input
+device fields in inputInfo, and initialize the input processing and grab
+functions for each core input device.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>The core pointer device is then registered with the miPointer code
+(which does the high level cursor handling).  While this registration
+is not necessary for correct miPointer operation in the current XFree86
+code, it is still done mostly for compatibility reasons.
+</para>
+
+<para><variablelist>
+
+<varlistentry>
+<term>miRegisterPointerDevice()</term>
+<listitem><para>This MI function registers the core
+pointer's input handle with with the miPointer code.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>The final part of InitInput() is the initialization of the input
+event queue handling.  In most cases, the event queue handling provided
+in the MI layer is used.  The primary XFree86 X server uses its own
+event queue handling to support some special cases related to the XInput
+extension and the XFree86-specific DGA extension.  For our purposes, the
+MI event queue handling should be suitable.  It is initialized by
+calling mieqInit():
+
+<variablelist>
+<varlistentry>
+<term>mieqInit()</term>
+<listitem><para>This MI function initializes the MI event queue for the
+core devices, and is passed the public component of the input handles
+for the two core devices.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>If a wakeup handler is required to deliver synchronous input
+events, it can be registered here by calling the DIX function
+RegisterBlockAndWakeupHandlers().  (See the devReadInput() description
+below.)
+</para>
+</sect3>
+
+<sect3>
+<title>InitAndStartDevices()</title>
+
+<para>InitAndStartDevices() is a DIX function that is called immediately
+after InitInput() from the X server's main() function.  Its purpose is
+to initialize each input device that was registered with
+AddInputDevice(), enable each input device that was successfully
+initialized, and create the list of enabled input devices.  Once each
+registered device is processed in this way, the list of enabled input
+devices is checked to make sure that both a core keyboard device and
+core pointer device were registered and successfully enabled.  If not,
+InitAndStartDevices() returns failure, and results in the the X server
+exiting with a fatal error.
+</para>
+
+<para>Each registered device is initialized by calling its callback
+(dev-&gt;deviceProc) with the DEVICE_INIT argument:
+
+<variablelist>
+<varlistentry>
+<term>(*dev-&gt;deviceProc)(dev, DEVICE_INIT)</term>
+<listitem>
+<para>This function initializes the
+device structs with core information relevant to the device.
+</para>
+
+<para>For pointer devices, this means specifying the number of buttons,
+default button mapping, the function used to get motion events (usually
+miPointerGetMotionEvents()), the function used to change/control the
+core pointer motion parameters (acceleration and threshold), and the
+motion buffer size.
+</para>
+
+<para>For keyboard devices, this means specifying the keycode range,
+default keycode to keysym mapping, default modifier mapping, and the
+functions used to sound the keyboard bell and modify/control the
+keyboard parameters (LEDs, bell pitch and duration, key click, which
+keys are auto-repeating, etc).
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>Each initialized device is enabled by calling EnableDevice():
+
+<variablelist>
+<varlistentry>
+<term>EnableDevice()</term>
+<listitem>
+<para>EnableDevice() calls the device callback with
+DEVICE_ON:
+    <variablelist>
+    <varlistentry>
+    <term>(*dev-&gt;deviceProc)(dev, DEVICE_ON)</term>
+    <listitem>
+    <para>This typically opens and
+    initializes the relevant physical device, and when appropriate,
+    registers the device's file descriptor (or equivalent) as a valid
+    input source.
+    </para></listitem></varlistentry>
+    </variablelist>
+    </para>
+
+    <para>EnableDevice() then adds the device handle to the X server's
+    global list of enabled devices.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>InitAndStartDevices() then verifies that a valid core keyboard and
+pointer has been initialized and enabled.  It returns failure if either
+are missing.
+</para>
+</sect3>
+
+<sect3>
+<title>devReadInput()</title>
+
+<para>Each device will have some function that gets called to read its
+physical input.  These may be called in a number of different ways.  In
+the case of synchronous I/O, they will be called from a DDX
+wakeup-handler that gets called after the server detects that new input is
+available.  In the case of asynchronous I/O, they will be called from a
+(SIGIO) signal handler triggered when new input is available.  This
+function should do at least two things: make sure that input events get
+enqueued, and make sure that the cursor gets moved for motion events
+(except if these are handled later by the driver's own event queue
+processing function, which cannot be done when using the MI event queue
+handling).
+</para>
+
+<para>Events are queued by calling mieqEnqueue():
+
+<variablelist>
+<varlistentry>
+<term>mieqEnqueue()</term>
+<listitem>
+<para>This MI function is used to add input events to the
+event queue.  It is simply passed the event to be queued.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>The cursor position should be updated when motion events are
+enqueued, by calling either miPointerAbsoluteCursor() or
+miPointerDeltaCursor():
+
+<variablelist>
+<varlistentry>
+<term>miPointerAbsoluteCursor()</term>
+<listitem>
+<para>This MI function is used to move the
+cursor to the absolute coordinates provided.
+</para></listitem></varlistentry>
+<varlistentry>
+<term>miPointerDeltaCursor()</term>
+<listitem>
+<para>This MI function is used to move the cursor
+relative to its current position.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+</sect3>
+
+<sect3>
+<title>ProcessInputEvents()</title>
+
+<para>ProcessInputEvents() is a DDX function that is called from the X
+server's main dispatch loop when new events are available in the input
+event queue.  It typically processes the enqueued events, and updates
+the cursor/pointer position.  It may also do other DDX-specific event
+processing.
+</para>
+
+<para>Enqueued events are processed by mieqProcessInputEvents() and passed
+to the DIX layer for transmission to clients:
+
+<variablelist>
+<varlistentry>
+<term>mieqProcessInputEvents()</term>
+<listitem>
+<para>This function processes each event in the
+event queue, and passes it to the device's input processing function.
+The DIX layer provides default functions to do this processing, and they
+handle the task of getting the events passed back to the relevant
+clients.
+</para></listitem></varlistentry>
+<varlistentry>
+<term>miPointerUpdate()</term>
+<listitem>
+<para>This function resynchronized the cursor position
+with the new pointer position.  It also takes care of moving the cursor
+between screens when needed in multi-head configurations.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+</sect3>
+
+<sect3>
+<title>DisableDevice()</title>
+
+<para>DisableDevice is a DIX function that removes an input device from the
+list of enabled devices.  The result of this is that the device no
+longer generates input events.  The device's data structures are kept in
+place, and disabling a device like this can be reversed by calling
+EnableDevice().  DisableDevice() may be called from the DDX when it is
+desirable to do so (e.g., the XFree86 server does this when VT
+switching).  Except for special cases, this is not normally called for
+core input devices.
+</para>
+
+<para>DisableDevice() calls the device's callback function with
+<constant>DEVICE_OFF</constant>:
+
+<variablelist>
+<varlistentry>
+<term>(*dev-&gt;deviceProc)(dev, DEVICE_OFF)</term>
+<listitem>
+<para>This typically closes the
+relevant physical device, and when appropriate, unregisters the device's
+file descriptor (or equivalent) as a valid input source.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>DisableDevice() then removes the device handle from the X server's
+global list of enabled devices.
+</para>
+
+</sect3>
+
+<sect3>
+<title>CloseDevice()</title>
+
+<para>CloseDevice is a DIX function that removes an input device from the
+list of available devices.  It disables input from the device and frees
+all data structures associated with the device.  This function is
+usually called from CloseDownDevices(), which is called from main() at
+the end of each server generation to close all input devices.
+</para>
+
+<para>CloseDevice() calls the device's callback function with
+<constant>DEVICE_CLOSE</constant>:
+
+<variablelist>
+<varlistentry>
+<term>(*dev-&gt;deviceProc)(dev, DEVICE_CLOSE)</term>
+<listitem>
+<para>This typically closes the
+relevant physical device, and when appropriate, unregisters the device's
+file descriptor (or equivalent) as a valid input source.  If any device
+specific data structures were allocated when the device was initialized,
+they are freed here.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>CloseDevice() then frees the data structures that were allocated
+for the device when it was registered/initialized.
+</para>
+
+</sect3>
+
+<sect3>
+<title>LegalModifier()</title>
+<!-- dmx/dmxinput.c - currently returns TRUE -->
+<para>LegalModifier() is a required DDX function that can be used to
+restrict which keys may be modifier keys.  This seems to be present for
+historical reasons, so this function should simply return TRUE
+unconditionally.
+</para>
+
+</sect3>
+</sect2>
+
+<sect2>
+<title>Output handling</title>
+
+<para>The following sections describe the main functions required to
+initialize, use and close the output device(s) for each screen in the X
+server.
+</para>
+
+<sect3>
+<title>InitOutput()</title>
+
+<para>This DDX function is called near the start of each server generation
+from the X server's main() function.  InitOutput()'s main purpose is to
+initialize each screen and fill in the global screenInfo structure for
+each screen.  It is passed three arguments: a pointer to the screenInfo
+struct, which it is to initialize, and argc and argv from main(), which
+can be used to determine additional configuration information.
+</para>
+
+<para>The primary tasks for this function are outlined below:
+
+<orderedlist>
+<listitem>
+    <para><emphasis remap="bf">Parse configuration info:</emphasis> The first task of InitOutput()
+    is to parses any configuration information from the configuration
+    file.  In addition to the XF86Config file, other configuration
+    information can be taken from the command line.  The command line
+    options can be gathered either in InitOutput() or earlier in the
+    ddxProcessArgument() function, which is called by
+    ProcessCommandLine().  The configuration information determines the
+    characteristics of the screen(s).  For example, in the XFree86 X
+    server, the XF86Config file specifies the monitor information, the
+    screen resolution, the graphics devices and slots in which they are
+    located, and, for Xinerama, the screens' layout.
+</para>
+</listitem>
+
+<listitem>
+    <para><emphasis remap="bf">Initialize screen info:</emphasis> The next task is to initialize
+    the screen-dependent internal data structures.  For example, part of
+    what the XFree86 X server does is to allocate its screen and pixmap
+    private indices, probe for graphics devices, compare the probed
+    devices to the ones listed in the XF86Config file, and add the ones that
+    match to the internal xf86Screens&lsqb;&rsqb; structure.
+</para>
+</listitem>
+
+<listitem>
+    <para><emphasis remap="bf">Set pixmap formats:</emphasis> The next task is to initialize the
+    screenInfo's image byte order, bitmap bit order and bitmap scanline
+    unit/pad.  The screenInfo's pixmap format's depth, bits per pixel
+    and scanline padding is also initialized at this stage.
+</para>
+</listitem>
+
+<listitem>
+    <para><emphasis remap="bf">Unify screen info:</emphasis> An optional task that might be done at
+    this stage is to compare all of the information from the various
+    screens and determines if they are compatible (i.e., if the set of
+    screens can be unified into a single desktop).  This task has
+    potential to be useful to the DMX front-end server, if Xinerama's
+    PanoramiXConsolidate() function is not sufficient.
+</para>
+</listitem>
+</orderedlist>
+</para>
+
+<para>Once these tasks are complete, the valid screens are known and each
+of these screens can be initialized by calling AddScreen().
+</para>
+</sect3>
+
+<sect3>
+<title>AddScreen()</title>
+
+<para>This DIX function is called from InitOutput(), in the DDX layer, to
+add each new screen to the screenInfo structure.  The DDX screen
+initialization function and command line arguments (i.e., argc and argv)
+are passed to it as arguments.
+</para>
+
+<para>This function first allocates a new Screen structure and any privates
+that are required.  It then initializes some of the fields in the Screen
+struct and sets up the pixmap padding information.  Finally, it calls
+the DDX screen initialization function ScreenInit(), which is described
+below.  It returns the number of the screen that were just added, or -1
+if there is insufficient memory to add the screen or if the DDX screen
+initialization fails.
+</para>
+</sect3>
+
+<sect3>
+<title>ScreenInit()</title>
+
+<para>This DDX function initializes the rest of the Screen structure with
+either generic or screen-specific functions (as necessary).  It also
+fills in various screen attributes (e.g., width and height in
+millimeters, black and white pixel values).
+</para>
+
+<para>The screen init function usually calls several functions to perform
+certain screen initialization functions.  They are described below:
+
+<variablelist>
+<varlistentry>
+<term>{mi,*fb}ScreenInit()</term>
+<listitem>
+<para>The DDX layer's ScreenInit() function usually
+calls another layer's ScreenInit() function (e.g., miScreenInit() or
+fbScreenInit()) to initialize the fallbacks that the DDX driver does not
+specifically handle.
+</para>
+
+<para>After calling another layer's ScreenInit() function, any
+screen-specific functions either wrap or replace the other layer's
+function pointers.  If a function is to be wrapped, each of the old
+function pointers from the other layer are stored in a screen private
+area.  Common functions to wrap are CloseScreen() and SaveScreen().
+</para></listitem></varlistentry>
+
+<varlistentry>
+<term>miInitializeBackingStore()</term>
+<listitem>
+<para>This MI function initializes the
+screen's backing storage functions, which are used to save areas of
+windows that are currently covered by other windows.
+</para></listitem></varlistentry>
+
+<varlistentry>
+<term>miDCInitialize()</term>
+<listitem>
+<para>This MI function initializes the MI cursor
+display structures and function pointers.  If a hardware cursor is used,
+the DDX layer's ScreenInit() function will wrap additional screen and
+the MI cursor display function pointers.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>Another common task for ScreenInit() function is to initialize the
+output device state.  For example, in the XFree86 X server, the
+ScreenInit() function saves the original state of the video card and
+then initializes the video mode of the graphics device.
+</para>
+</sect3>
+
+<sect3>
+<title>CloseScreen()</title>
+
+<para>This function restores any wrapped screen functions (and in
+particular the wrapped CloseScreen() function) and restores the state of
+the output device to its original state.  It should also free any
+private data it created during the screen initialization.
+</para>
+</sect3>
+
+<sect3>
+<title>GC operations</title>
+
+<para>When the X server is requested to render drawing primitives, it does
+so by calling drawing functions through the graphics context's operation
+function pointer table (i.e., the GCOps functions).  These functions
+render the basic graphics operations such as drawing rectangles, lines,
+text or copying pixmaps.  Default routines are provided either by the MI
+layer, which draws indirectly through a simple span interface, or by the
+framebuffer layers (e.g., CFB, MFB, FB), which draw directly to a
+linearly mapped frame buffer.
+</para>
+
+<para>To take advantage of special hardware on the graphics device,
+specific GCOps functions can be replaced by device specific code.
+However, many times the graphics devices can handle only a subset of the
+possible states of the GC, so during graphics context validation,
+appropriate routines are selected based on the state and capabilities of
+the hardware.  For example, some graphics hardware can accelerate single
+pixel width lines with certain dash patterns.  Thus, for dash patterns
+that are not supported by hardware or for width 2 or greater lines, the
+default routine is chosen during GC validation.
+</para>
+
+<para>Note that some pointers to functions that draw to the screen are
+stored in the Screen structure.  They include GetImage(), GetSpans(),
+CopyWindow() and RestoreAreas().
+</para>
+</sect3>
+
+<sect3>
+<title>Xnest</title>
+
+<para>The Xnest X server is a special proxy X server that relays the X
+protocol requests that it receives to a ``real'' X server that then
+processes the requests and displays the results, if applicable.  To the X
+applications, Xnest appears as if it is a regular X server.  However,
+Xnest is both server to the X application and client of the real X
+server, which will actually handle the requests.
+</para>
+
+<para>The Xnest server implements all of the standard input and output
+initialization steps outlined above.
+</para>
+
+<para><variablelist>
+<varlistentry>
+<term>InitOutput()</term>
+<listitem>
+<para>Xnest takes its configuration information from
+command line arguments via ddxProcessArguments().  This information
+includes the real X server display to connect to, its default visual
+class, the screen depth, the Xnest window's geometry, etc.  Xnest then
+connects to the real X server and gathers visual, colormap, depth and
+pixmap information about that server's display, creates a window on that
+server, which will be used as the root window for Xnest.
+</para>
+
+<para>Next, Xnest initializes its internal data structures and uses the
+data from the real X server's pixmaps to initialize its own pixmap
+formats.  Finally, it calls AddScreen(xnestOpenScreen, argc, argv) to
+initialize each of its screens.
+</para></listitem></varlistentry>
+
+<varlistentry>
+<term>ScreenInit()</term>
+<listitem>
+<para>Xnest's ScreenInit() function is called
+xnestOpenScreen().  This function initializes its screen's depth and
+visual information, and then calls miScreenInit() to set up the default
+screen functions.  It then calls miInitializeBackingStore() and
+miDCInitialize() to initialize backing store and the software cursor.
+Finally, it replaces many of the screen functions with its own
+functions that repackage and send the requests to the real X server to
+which Xnest is attached.
+</para></listitem></varlistentry>
+
+<varlistentry>
+<term>CloseScreen()</term>
+<listitem>
+<para>This function frees its internal data structure
+allocations.  Since it replaces instead of wrapping screen functions,
+there are no function pointers to unwrap.  This can potentially lead to
+problems during server regeneration.
+</para></listitem></varlistentry>
+
+<varlistentry>
+<term>GC operations</term>
+<listitem>
+<para>The GC operations in Xnest are very simple since
+they leave all of the drawing to the real X server to which Xnest is
+attached.  Each of the GCOps takes the request and sends it to the
+real X server using standard Xlib calls.  For example, the X
+application issues a XDrawLines() call.  This function turns into a
+protocol request to Xnest, which calls the xnestPolylines() function
+through Xnest's GCOps function pointer table.  The xnestPolylines()
+function is only a single line, which calls XDrawLines() using the same
+arguments that were passed into it.  Other GCOps functions are very
+similar.  Two exceptions to the simple GCOps functions described above
+are the image functions and the BLT operations.
+</para>
+
+<para>The image functions, GetImage() and PutImage(), must use a temporary
+image to hold the image to be put of the image that was just grabbed
+from the screen while it is in transit to the real X server or the
+client.  When the image has been transmitted, the temporary image is
+destroyed.
+</para>
+
+<para>The BLT operations, CopyArea() and CopyPlane(), handle not only the
+copy function, which is the same as the simple cases described above,
+but also the graphics exposures that result when the GC's graphics
+exposure bit is set to True.  Graphics exposures are handled in a helper
+function, xnestBitBlitHelper().  This function collects the exposure
+events from the real X server and, if any resulting in regions being
+exposed, then those regions are passed back to the MI layer so that it
+can generate exposure events for the X application.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>The Xnest server takes its input from the X server to which it is
+connected.  When the mouse is in the Xnest server's window, keyboard and
+mouse events are received by the Xnest server, repackaged and sent back
+to any client that requests those events.
+</para>
+</sect3>
+
+<sect3>
+<title>Shadow framebuffer</title>
+
+<para>The most common type of framebuffer is a linear array memory that
+maps to the video memory on the graphics device.  However, accessing
+that video memory over an I/O bus (e.g., ISA or PCI) can be slow.  The
+shadow framebuffer layer allows the developer to keep the entire
+framebuffer in main memory and copy it back to video memory at regular
+intervals.  It also has been extended to handle planar video memory and
+rotated framebuffers.
+</para>
+
+<para>There are two main entry points to the shadow framebuffer code:
+
+<variablelist>
+<varlistentry>
+<term>shadowAlloc(width, height, bpp)</term>
+<listitem>
+<para>This function allocates the in
+memory copy of the framebuffer of size width*height*bpp.  It returns a
+pointer to that memory, which will be used by the framebuffer
+ScreenInit() code during the screen's initialization.
+</para></listitem></varlistentry>
+
+<varlistentry>
+<term>shadowInit(pScreen, updateProc, windowProc)</term>
+<listitem>
+<para>This function
+initializes the shadow framebuffer layer.  It wraps several screen
+drawing functions, and registers a block handler that will update the
+screen.  The updateProc is a function that will copy the damaged regions
+to the screen, and the windowProc is a function that is used when the
+entire linear video memory range cannot be accessed simultaneously so
+that only a window into that memory is available (e.g., when using the
+VGA aperture).
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>The shadow framebuffer code keeps track of the damaged area of each
+screen by calculating the bounding box of all drawing operations that
+have occurred since the last screen update.  Then, when the block handler
+is next called, only the damaged portion of the screen is updated.
+</para>
+
+<para>Note that since the shadow framebuffer is kept in main memory, all
+drawing operations are performed by the CPU and, thus, no accelerated
+hardware drawing operations are possible.
+</para>
+
+</sect3>
+</sect2>
+
+<sect2>
+<title>Xinerama</title>
+
+<para>Xinerama is an X extension that allows multiple physical screens
+controlled by a single X server to appear as a single screen.  Although
+the extension allows clients to find the physical screen layout via
+extension requests, it is completely transparent to clients at the core
+X11 protocol level.  The original public implementation of Xinerama came
+from Digital/Compaq.  XFree86 rewrote it, filling in some missing pieces
+and improving both X11 core protocol compliance and performance.  The
+Xinerama extension will be passing through X.Org's standardization
+process in the near future, and the sample implementation will be based
+on this rewritten version.
+</para>
+
+<para>The current implementation of Xinerama is based primarily in the DIX
+(device independent) and MI (machine independent) layers of the X
+server.  With few exceptions the DDX layers do not need any changes to
+support Xinerama.  X server extensions often do need modifications to
+provide full Xinerama functionality.
+</para>
+
+<para>The following is a code-level description of how Xinerama functions.
+</para>
+
+<para>Note: Because the Xinerama extension was originally called the
+PanoramiX extension, many of the Xinerama functions still have the
+PanoramiX prefix.
+</para>
+
+<variablelist>
+<varlistentry>
+<term>PanoramiXExtensionInit()</term>
+<listitem>
+    <para>PanoramiXExtensionInit() is a
+    device-independent extension function that is called at the start of
+    each server generation from InitExtensions(), which is called from
+    the X server's main() function after all output devices have been
+    initialized, but before any input devices have been initialized.
+    </para>
+
+    <para>PanoramiXNumScreens is set to the number of physical screens.  If
+    only one physical screen is present, the extension is disabled, and
+    PanoramiXExtensionInit() returns without doing anything else.
+    </para>
+
+    <para>The Xinerama extension is registered by calling AddExtension().
+    </para>
+
+    <para>A local per-screen array of data structures
+    (panoramiXdataPtr&lsqb;&rsqb;)
+    is allocated for each physical screen, and GC and Screen private
+    indexes are allocated, and both GC and Screen private areas are
+    allocated for each physical screen.  These hold Xinerama-specific
+    per-GC and per-Screen data.  Each screen's CreateGC and CloseScreen
+    functions are wrapped by XineramaCreateGC() and
+    XineramaCloseScreen() respectively.  Some new resource classes are
+    created for Xinerama drawables and GCs, and resource types for
+    Xinerama windows, pixmaps and colormaps.
+    </para>
+
+    <para>A region (XineramaScreenRegions&lsqb;i&rsqb;) is initialized for each
+    physical screen, and single region (PanoramiXScreenRegion) is
+    initialized to be the union of the screen regions.  The
+    panoramiXdataPtr&lsqb;&rsqb; array is also initialized with the size and
+    origin of each screen.  The relative positioning information for the
+    physical screens is taken from the array
+    dixScreenOrigins&lsqb;&rsqb;, which
+    the DDX layer must initialize in InitOutput().  The bounds of the
+    combined screen is also calculated (PanoramiXPixWidth and
+    PanoramiXPixHeight).
+    </para>
+
+    <para>The DIX layer has a list of function pointers
+    (ProcVector&lsqb;&rsqb;) that
+    holds the entry points for the functions that process core protocol
+    requests.  The requests that Xinerama must intercept and break up
+    into physical screen-specific requests are wrapped.  The original
+    set is copied to SavedProcVector&lsqb;&rsqb;.  The types of requests
+    intercepted are Window requests, GC requests, colormap requests,
+    drawing requests, and some geometry-related requests.  This wrapping
+    allows the bulk of the protocol request processing to be handled
+    transparently to the DIX layer.  Some operations cannot be dealt with
+    in this way and are handled with Xinerama-specific code within the
+    DIX layer.
+    </para>
+</listitem></varlistentry>
+
+<varlistentry>
+<term>PanoramiXConsolidate()</term>
+<listitem>
+    <para>PanoramiXConsolidate() is a
+    device-independent extension function that is called directly from
+    the X server's main() function after extensions and input/output
+    devices have been initialized, and before the root windows are
+    defined and initialized.
+</para>
+
+    <para>This function finds the set of depths (PanoramiXDepths&lsqb;&rsqb;) and
+    visuals (PanoramiXVisuals&lsqb;&rsqb;)
+    common to all of the physical screens.
+    PanoramiXNumDepths is set to the number of common depths, and
+    PanoramiXNumVisuals is set to the number of common visuals.
+    Resources are created for the single root window and the default
+    colormap.  Each of these resources has per-physical screen entries.
+    </para>
+</listitem></varlistentry>
+
+<varlistentry>
+<term>PanoramiXCreateConnectionBlock()</term>
+<listitem>
+    <para>PanoramiXConsolidate() is a
+    device-independent extension function that is called directly from
+    the X server's main() function after the per-physical screen root
+    windows are created.  It is called instead of the standard DIX
+    CreateConnectionBlock() function.  If this function returns FALSE,
+    the X server exits with a fatal error.  This function will return
+    FALSE if no common depths were found in PanoramiXConsolidate().
+    With no common depths, Xinerama mode is not possible.
+    </para>
+
+    <para>The connection block holds the information that clients get when
+    they open a connection to the X server.  It includes information
+    such as the supported pixmap formats, number of screens and the
+    sizes, depths, visuals, default colormap information, etc, for each
+    of the screens (much of information that <command>xdpyinfo</command> shows).  The
+    connection block is initialized with the combined single screen
+    values that were calculated in the above two functions.
+    </para>
+
+    <para>The Xinerama extension allows the registration of connection
+    block callback functions.  The purpose of these is to allow other
+    extensions to do processing at this point.  These callbacks can be
+    registered by calling XineramaRegisterConnectionBlockCallback() from
+    the other extension's ExtensionInit() function.  Each registered
+    connection block callback is called at the end of
+    PanoramiXCreateConnectionBlock().
+    </para>
+</listitem></varlistentry>
+</variablelist>
+
+<sect3>
+<title>Xinerama-specific changes to the DIX code</title>
+
+<para>There are a few types of Xinerama-specific changes within the DIX
+code.  The main ones are described here.
+</para>
+
+<para>Functions that deal with colormap or GC -related operations outside of
+the intercepted protocol requests have a test added to only do the
+processing for screen numbers &gt; 0.  This is because they are handled for
+the single Xinerama screen and the processing is done once for screen 0.
+</para>
+
+<para>The handling of motion events does some coordinate translation between
+the physical screen's origin and screen zero's origin.  Also, motion
+events must be reported relative to the composite screen origin rather
+than the physical screen origins.
+</para>
+
+<para>There is some special handling for cursor, window and event processing
+that cannot (either not at all or not conveniently) be done via the
+intercepted protocol requests.  A particular case is the handling of
+pointers moving between physical screens.
+</para>
+</sect3>
+
+<sect3>
+<title>Xinerama-specific changes to the MI code</title>
+
+<para>The only Xinerama-specific change to the MI code is in miSendExposures()
+to handle the coordinate (and window ID) translation for expose events.
+</para>
+</sect3>
+
+<sect3>
+<title>Intercepted DIX core requests</title>
+
+<para>Xinerama breaks up drawing requests for dispatch to each physical
+screen.  It also breaks up windows into pieces for each physical screen.
+GCs are translated into per-screen GCs.  Colormaps are replicated on
+each physical screen.  The functions handling the intercepted requests
+take care of breaking the requests and repackaging them so that they can
+be passed to the standard request handling functions for each screen in
+turn.  In addition, and to aid the repackaging, the information from
+many of the intercepted requests is used to keep up to date the
+necessary state information for the single composite screen.  Requests
+(usually those with replies) that can be satisfied completely from this
+stored state information do not call the standard request handling
+functions.
+</para>
+
+</sect3>
+
+</sect2>
+
+</sect1>
+
+<!-- ============================================================ -->
+
+<sect1>
+<title>Development Results</title>
+
+<para>In this section the results of each phase of development are
+discussed.  This development took place between approximately June 2001
+and July 2003.
+</para>
+
+<sect2>
+<title>Phase I</title>
+
+<para>The initial development phase dealt with the basic implementation
+including the bootstrap code, which used the shadow framebuffer, and the
+unoptimized implementation, based on an Xnest-style implementation.
+</para>
+
+<sect3>
+<title>Scope</title>
+
+<para>The goal of Phase I is to provide fundamental functionality that can
+act as a foundation for ongoing work:
+<orderedlist>
+<listitem>
+    <para>Develop the proxy X server
+    <itemizedlist>
+	<listitem>
+	<para>The proxy X server will operate on the X11 protocol and
+	relay requests as necessary to correctly perform the request.
+	</para></listitem>
+	<listitem>
+	<para>Work will be based on the existing work for Xinerama and
+	Xnest.
+	</para></listitem>
+	<listitem>
+	<para>Input events and windowing operations are handled in the
+	proxy server and rendering requests are repackaged and sent to
+	each of the back-end servers for display.
+	</para></listitem>
+	<listitem>
+	<para>The multiple screen layout (including support for
+	overlapping screens) will be user configurable via a
+	configuration file or through the configuration tool.
+	</para></listitem>
+    </itemizedlist>
+    </para></listitem>
+    <listitem>
+    <para>Develop graphical configuration tool
+    <itemizedlist>
+	<listitem>
+	<para>There will be potentially a large number of X servers to
+	configure into a single display.  The tool will allow the user
+	to specify which servers are involved in the configuration and
+	how they should be laid out.
+	</para></listitem>
+    </itemizedlist>
+    </para></listitem>
+    <listitem>
+    <para>Pass the X Test Suite
+    <itemizedlist>
+	<listitem>
+	<para>The X Test Suite covers the basic X11 operations.  All
+	tests known to succeed must correctly operate in the distributed
+	X environment.
+	</para></listitem>
+    </itemizedlist>
+    </para></listitem>
+</orderedlist>
+
+</para>
+
+<para>For this phase, the back-end X servers are assumed to be unmodified X
+servers that do not support any DMX-related protocol extensions; future
+optimization pathways are considered, but are not implemented; and the
+configuration tool is assumed to rely only on libraries in the X source
+tree (e.g., Xt).
+</para>
+</sect3>
+
+<sect3>
+<title>Results</title>
+
+<para>The proxy X server, Xdmx, was developed to distribute X11 protocol
+requests to the set of back-end X servers.  It opens a window on each
+back-end server, which represents the part of the front-end's root
+window that is visible on that screen.  It mirrors window, pixmap and
+other state in each back-end server.  Drawing requests are sent to
+either windows or pixmaps on each back-end server.  This code is based
+on Xnest and uses the existing Xinerama extension.
+</para>
+
+<para>Input events can be taken from (1) devices attached to the back-end
+server, (2) core devices attached directly to the Xdmx server, or (3)
+from a ``console'' window on another X server.  Events for these devices
+are gathered, processed and delivered to clients attached to the Xdmx
+server.
+</para>
+
+<para>An intuitive configuration format was developed to help the user
+easily configure the multiple back-end X servers.  It was defined (see
+grammar in Xdmx man page) and a parser was implemented that is used by
+the Xdmx server and by a standalone xdmxconfig utility.  The parsing
+support was implemented such that it can be easily factored out of the X
+source tree for use with other tools (e.g., vdl).  Support for
+converting legacy vdl-format configuration files to the DMX format is
+provided by the vdltodmx utility.
+</para>
+
+<para>Originally, the configuration file was going to be a subsection of
+XFree86's XF86Config file, but that was not possible since Xdmx is a
+completely separate X server.  Thus, a separate config file format was
+developed.  In addition, a graphical configuration
+tool, xdmxconfig, was developed to allow the user to create and arrange
+the screens in the configuration file.  The <emphasis remap="bf">-configfile</emphasis> and <emphasis remap="bf">-config</emphasis>
+command-line options can be used to start Xdmx using a configuration
+file.
+</para>
+
+<para>An extension that enables remote input testing is required for the X
+Test Suite to function.  During this phase, this extension (XTEST) was
+implemented in the Xdmx server.  The results from running the X Test
+Suite are described in detail below.
+</para>
+</sect3>
+
+<sect3>
+<title>X Test Suite</title>
+
+        <sect4>
+          <title>Introduction</title>
+            <para>
+              The X Test Suite contains tests that verify Xlib functions
+              operate correctly.  The test suite is designed to run on a
+              single X server; however, since X applications will not be
+              able to tell the difference between the DMX server and a
+              standard X server, the X Test Suite should also run on the
+              DMX server.
+            </para>
+            <para>
+              The Xdmx server was tested with the X Test Suite, and the
+              existing failures are noted in this section.  To put these
+              results in perspective, we first discuss expected X Test
+              failures and how errors in underlying systems can impact
+              Xdmx test results.
+            </para>
+        </sect4>
+
+        <sect4>
+          <title>Expected Failures for a Single Head</title>
+            <para>
+              A correctly implemented X server with a single screen is
+              expected to fail certain X Test tests.  The following
+              well-known errors occur because of rounding error in the X
+              server code:
+              <literallayout>
+XDrawArc: Tests 42, 63, 66, 73
+XDrawArcs: Tests 45, 66, 69, 76
+              </literallayout>
+            </para>
+            <para>
+              The following failures occur because of the high-level X
+              server implementation:
+              <literallayout>
+XLoadQueryFont: Test 1
+XListFontsWithInfo: Tests 3, 4
+XQueryFont: Tests 1, 2
+              </literallayout>
+            </para>
+            <para>
+              The following test fails when running the X server as root
+              under Linux because of the way directory modes are
+              interpreted:
+              <literallayout>
+XWriteBitmapFile: Test 3
+              </literallayout>
+            </para>
+            <para>
+              Depending on the video card used for the back-end, other
+              failures may also occur because of bugs in the low-level
+              driver implementation.  Over time, failures of this kind
+              are usually fixed by XFree86, but will show up in Xdmx
+              testing until then.
+            </para>
+        </sect4>
+
+        <sect4>
+          <title>Expected Failures for Xinerama</title>
+            <para>
+              Xinerama fails several X Test Suite tests because of
+              design decisions made for the current implementation of
+              Xinerama.  Over time, many of these errors will be
+              corrected by XFree86 and the group working on a new
+              Xinerama implementation.  Therefore, Xdmx will also share
+              X Suite Test failures with Xinerama.
+            </para>
+
+            <para>
+              We may be able to fix or work-around some of these
+              failures at the Xdmx level, but this will require
+              additional exploration that was not part of Phase I.
+            </para>
+
+            <para>
+              Xinerama is constantly improving, and the list of
+              Xinerama-related failures depends on XFree86 version and
+              the underlying graphics hardware.  We tested with a
+              variety of hardware, including nVidia, S3, ATI Radeon,
+              and Matrox G400 (in dual-head mode).  The list below
+              includes only those failures that appear to be from the
+              Xinerama layer, and does not include failures listed in
+              the previous section, or failures that appear to be from
+              the low-level graphics driver itself:
+            </para>
+
+            <para>
+              These failures were noted with multiple Xinerama
+              configurations:
+              <literallayout>
+XCopyPlane: Tests 13, 22, 31 (well-known Xinerama implementation issue)
+XSetFontPath: Test 4
+XGetDefault: Test 5
+XMatchVisualInfo: Test 1
+              </literallayout>
+            </para>
+            <para>
+              These failures were noted only when using one dual-head
+              video card with a 4.2.99.x XFree86 server:
+              <literallayout>
+XListPixmapFormats: Test 1
+XDrawRectangles: Test 45
+              </literallayout>
+            </para>
+            <para>
+              These failures were noted only when using two video cards
+              from different vendors with a 4.1.99.x XFree86 server:
+              <literallayout>
+XChangeWindowAttributes: Test 32
+XCreateWindow: Test 30
+XDrawLine: Test 22
+XFillArc: Test 22
+XChangeKeyboardControl: Tests 9, 10
+XRebindKeysym: Test 1
+              </literallayout>
+            </para>
+        </sect4>
+
+        <sect4>
+	  <title>Additional Failures from Xdmx</title>
+
+            <para>
+              When running Xdmx, no unexpected failures were noted.
+              Since the Xdmx server is based on Xinerama, we expect to
+              have most of the Xinerama failures present in the Xdmx
+              server.  Similarly, since the Xdmx server must rely on the
+              low-level device drivers on each back-end server, we also
+              expect that Xdmx will exhibit most of the back-end
+              failures.  Here is a summary:
+              <literallayout>
+XListPixmapFormats: Test 1 (configuration dependent)
+XChangeWindowAttributes: Test 32
+XCreateWindow: Test 30
+XCopyPlane: Test 13, 22, 31
+XSetFontPath: Test 4
+XGetDefault: Test 5 (configuration dependent)
+XMatchVisualInfo: Test 1
+XRebindKeysym: Test 1 (configuration dependent)
+                </literallayout>
+            </para>
+            <para>
+              Note that this list is shorter than the combined list for
+              Xinerama because Xdmx uses different code paths to perform
+              some Xinerama operations.  Further, some Xinerama failures
+              have been fixed in the XFree86 4.2.99.x CVS repository.
+            </para>
+        </sect4>
+
+        <sect4>
+          <title>Summary and Future Work</title>
+
+            <para>
+              Running the X Test Suite on Xdmx does not produce any
+              failures that cannot be accounted for by the underlying
+              Xinerama subsystem used by the front-end or by the
+              low-level device-driver code running on the back-end X
+              servers.  The Xdmx server therefore is as ``correct'' as
+              possible with respect to the standard set of X Test Suite
+              tests.
+            </para>
+
+            <para>
+              During the following phases, we will continue to verify
+              Xdmx correctness using the X Test Suite.  We may also use
+              other tests suites or write additional tests that run
+              under the X Test Suite that specifically verify the
+              expected behavior of DMX.
+            </para>
+        </sect4>
+</sect3>
+
+<sect3>
+<title>Fonts</title>
+
+<para>In Phase I, fonts are handled directly by both the front-end and the
+back-end servers, which is required since we must treat each back-end
+server during this phase as a ``black box''.  What this requires is that
+<emphasis remap="bf">the front- and back-end servers must share the exact same font
+path</emphasis>.  There are two ways to help make sure that all servers share the
+same font path:
+
+<orderedlist>
+  <listitem>
+    <para>First, each server can be configured to use the same font
+    server.  The font server, xfs, can be configured to serve fonts to
+    multiple X servers via TCP.
+    </para></listitem>
+
+  <listitem>
+    <para>Second, each server can be configured to use the same font
+    path and either those font paths can be copied to each back-end
+    machine or they can be mounted (e.g., via NFS) on each back-end
+    machine.
+    </para></listitem>
+</orderedlist>
+</para>
+
+<para>One additional concern is that a client program can set its own font
+path, and if it does so, then that font path must be available on each
+back-end machine.
+</para>
+
+<para>The -fontpath command line option was added to allow users to
+initialize the font path of the front end server.  This font path is
+propagated to each back-end server when the default font is loaded.  If
+there are any problems, an error message is printed, which will describe
+the problem and list the current font path.  For more information about
+setting the font path, see the -fontpath option description in the man
+page.
+</para>
+</sect3>
+
+<sect3>
+<title>Performance</title>
+
+<para>Phase I of development was not intended to optimize performance.  Its
+focus was on completely and correctly handling the base X11 protocol in
+the Xdmx server.  However, several insights were gained during Phase I,
+which are listed here for reference during the next phase of
+development.
+</para>
+
+<orderedlist>
+  <listitem>
+    <para>Calls to XSync() can slow down rendering since it requires a
+    complete round trip to and from a back-end server.  This is
+    especially problematic when communicating over long haul networks.
+    </para></listitem>
+
+  <listitem>
+    <para>Sending drawing requests to only the screens that they overlap
+    should improve performance.
+    </para></listitem>
+</orderedlist>
+</sect3>
+
+<sect3>
+<title>Pixmaps</title>
+
+<para>Pixmaps were originally expected to be handled entirely in the
+front-end X server; however, it was found that this overly complicated
+the rendering code and would have required sending potentially large
+images to each back server that required them when copying from pixmap
+to screen.  Thus, pixmap state is mirrored in the back-end server just
+as it is with regular window state.  With this implementation, the same
+rendering code that draws to windows can be used to draw to pixmaps on
+the back-end server, and no large image transfers are required to copy
+from pixmap to window.
+</para>
+
+</sect3>
+
+</sect2>
+
+<!-- ============================================================ -->
+<sect2>
+<title>Phase II</title>
+
+<para>The second phase of development concentrates on performance
+optimizations.  These optimizations are documented here, with
+<command>x11perf</command> data to show how the optimizations improve performance.
+</para>
+
+<para>All benchmarks were performed by running Xdmx on a dual processor
+1.4GHz AMD Athlon machine with 1GB of RAM connecting over 100baseT to
+two single-processor 1GHz Pentium III machines with 256MB of RAM and ATI
+Rage 128 (RF) video cards.  The front end was running Linux
+2.4.20-pre1-ac1 and the back ends were running Linux 2.4.7-10 and
+version 4.2.99.1 of XFree86 pulled from the XFree86 CVS repository on
+August 7, 2002.  All systems were running Red Hat Linux 7.2.
+</para>
+
+<sect3>
+<title>Moving from XFree86 4.1.99.1 to 4.2.0.0</title>
+
+<para>For phase II, the working source tree was moved to the branch tagged
+with dmx-1-0-branch and was updated from version 4.1.99.1 (20 August
+2001) of the XFree86 sources to version 4.2.0.0 (18 January 2002).
+After this update, the following tests were noted to be more than 10%
+faster:
+<screen>
+1.13   Fill 300x300 opaque stippled trapezoid (161x145 stipple)
+1.16   Fill 1x1 tiled trapezoid (161x145 tile)
+1.13   Fill 10x10 tiled trapezoid (161x145 tile)
+1.17   Fill 100x100 tiled trapezoid (161x145 tile)
+1.16   Fill 1x1 tiled trapezoid (216x208 tile)
+1.20   Fill 10x10 tiled trapezoid (216x208 tile)
+1.15   Fill 100x100 tiled trapezoid (216x208 tile)
+1.37   Circulate Unmapped window (200 kids)
+</screen>
+And the following tests were noted to be more than 10% slower:
+<screen>
+0.88   Unmap window via parent (25 kids)
+0.75   Circulate Unmapped window (4 kids)
+0.79   Circulate Unmapped window (16 kids)
+0.80   Circulate Unmapped window (25 kids)
+0.82   Circulate Unmapped window (50 kids)
+0.85   Circulate Unmapped window (75 kids)
+</screen>
+</para>
+
+<para>These changes were not caused by any changes in the DMX system, and
+may point to changes in the XFree86 tree or to tests that have more
+"jitter" than most other <command>x11perf</command> tests.
+</para>
+</sect3>
+
+<sect3>
+<title>Global changes</title>
+
+<para>During the development of the Phase II DMX server, several global
+changes were made.  These changes were also compared with the Phase I
+server.  The following tests were noted to be more than 10% faster:
+<screen>
+1.13   Fill 300x300 opaque stippled trapezoid (161x145 stipple)
+1.15   Fill 1x1 tiled trapezoid (161x145 tile)
+1.13   Fill 10x10 tiled trapezoid (161x145 tile)
+1.17   Fill 100x100 tiled trapezoid (161x145 tile)
+1.16   Fill 1x1 tiled trapezoid (216x208 tile)
+1.19   Fill 10x10 tiled trapezoid (216x208 tile)
+1.15   Fill 100x100 tiled trapezoid (216x208 tile)
+1.15   Circulate Unmapped window (4 kids)
+</screen>
+</para>
+
+<para>The following tests were noted to be more than 10% slower:
+<screen>
+0.69   Scroll 10x10 pixels
+0.68   Scroll 100x100 pixels
+0.68   Copy 10x10 from window to window
+0.68   Copy 100x100 from window to window
+0.76   Circulate Unmapped window (75 kids)
+0.83   Circulate Unmapped window (100 kids)
+</screen>
+</para>
+
+<para>For the remainder of this analysis, the baseline of comparison will
+be the Phase II deliverable with all optimizations disabled (unless
+otherwise noted).  This will highlight how the optimizations in
+isolation impact performance.
+</para>
+</sect3>
+
+<sect3>
+<title>XSync() Batching</title>
+
+<para>During the Phase I implementation, XSync() was called after every
+protocol request made by the DMX server.  This provided the DMX server
+with an interactive feel, but defeated X11's protocol buffering system
+and introduced round-trip wire latency into every operation.  During
+Phase II, DMX was changed so that protocol requests are no longer
+followed by calls to XSync().  Instead, the need for an XSync() is
+noted, and XSync() calls are only made every 100mS or when the DMX
+server specifically needs to make a call to guarantee interactivity.
+With this new system, X11 buffers protocol as much as possible during a
+100mS interval, and many unnecessary XSync() calls are avoided.
+</para>
+
+<para>Out of more than 300 <command>x11perf</command> tests, 8 tests became more than 100
+times faster, with 68 more than 50X faster, 114 more than 10X faster,
+and 181 more than 2X faster.  See table below for summary.
+</para>
+
+<para>The following tests were noted to be more than 10% slower with
+XSync() batching on:
+<screen>
+0.88   500x500 tiled rectangle (161x145 tile)
+0.89   Copy 500x500 from window to window
+</screen>
+</para>
+</sect3>
+
+<sect3>
+<title>Offscreen Optimization</title>
+
+<para>Windows span one or more of the back-end servers' screens; however,
+during Phase I development, windows were created on every back-end
+server and every rendering request was sent to every window regardless
+of whether or not that window was visible.  With the offscreen
+optimization, the DMX server tracks when a window is completely off of a
+back-end server's screen and, in that case, it does not send rendering
+requests to those back-end windows.  This optimization saves bandwidth
+between the front and back-end servers, and it reduces the number of
+XSync() calls.  The performance tests were run on a DMX system with only
+two back-end servers.  Greater performance gains will be had as the
+number of back-end servers increases.
+</para>
+
+<para>Out of more than 300 <command>x11perf</command> tests, 3 tests were at least twice as
+fast, and 146 tests were at least 10% faster.  Two tests were more than
+10% slower with the offscreen optimization:
+<screen>
+0.88   Hide/expose window via popup (4 kids)
+0.89   Resize unmapped window (75 kids)
+</screen>
+</para>
+</sect3>
+
+<sect3>
+<title>Lazy Window Creation Optimization</title>
+
+<para>As mentioned above, during Phase I, windows were created on every
+back-end server even if they were not visible on that back-end.  With
+the lazy window creation optimization, the DMX server does not create
+windows on a back-end server until they are either visible or they
+become the parents of a visible window.  This optimization builds on the
+offscreen optimization (described above) and requires it to be enabled.
+</para>
+
+<para>The lazy window creation optimization works by creating the window
+data structures in the front-end server when a client creates a window,
+but delays creation of the window on the back-end server(s).  A private
+window structure in the DMX server saves the relevant window data and
+tracks changes to the window's attributes and stacking order for later
+use.  The only times a window is created on a back-end server are (1)
+when it is mapped and is at least partially overlapping the back-end
+server's screen (tracked by the offscreen optimization), or (2) when the
+window becomes the parent of a previously visible window.  The first
+case occurs when a window is mapped or when a visible window is copied,
+moved or resized and now overlaps the back-end server's screen.  The
+second case occurs when starting a window manager after having created
+windows to which the window manager needs to add decorations.
+</para>
+
+<para>When either case occurs, a window on the back-end server is created
+using the data saved in the DMX server's window private data structure.
+The stacking order is then adjusted to correctly place the window on the
+back-end and lastly the window is mapped.  From this time forward, the
+window is handled exactly as if the window had been created at the time
+of the client's request.
+</para>
+
+<para>Note that when a window is no longer visible on a back-end server's
+screen (e.g., it is moved offscreen), the window is not destroyed;
+rather, it is kept and reused later if the window once again becomes
+visible on the back-end server's screen.  Originally with this
+optimization, destroying windows was implemented but was later rejected
+because it increased bandwidth when windows were opaquely moved or
+resized, which is common in many window managers.
+</para>
+
+<para>The performance tests were run on a DMX system with only two back-end
+servers.  Greater performance gains will be had as the number of
+back-end servers increases.
+</para>
+
+<para>This optimization improved the following <command>x11perf</command> tests by more
+than 10%:
+<screen>
+1.10   500x500 rectangle outline
+1.12   Fill 100x100 stippled trapezoid (161x145 stipple)
+1.20   Circulate Unmapped window (50 kids)
+1.19   Circulate Unmapped window (75 kids)
+</screen>
+</para>
+</sect3>
+
+<sect3>
+<title>Subdividing Rendering Primitives</title>
+
+<para>X11 imaging requests transfer significant data between the client and
+the X server.  During Phase I, the DMX server would then transfer the
+image data to each back-end server.  Even with the offscreen
+optimization (above), these requests still required transferring
+significant data to each back-end server that contained a visible
+portion of the window.  For example, if the client uses XPutImage() to
+copy an image to a window that overlaps the entire DMX screen, then the
+entire image is copied by the DMX server to every back-end server.
+</para>
+
+<para>To reduce the amount of data transferred between the DMX server and
+the back-end servers when XPutImage() is called, the image data is
+subdivided and only the data that will be visible on a back-end server's
+screen is sent to that back-end server.  Xinerama already implements a
+subdivision algorithm for XGetImage() and no further optimization was
+needed.
+</para>
+
+<para>Other rendering primitives were analyzed, but the time required to
+subdivide these primitives was a significant proportion of the time
+required to send the entire rendering request to the back-end server, so
+this optimization was rejected for the other rendering primitives.
+</para>
+
+<para>Again, the performance tests were run on a DMX system with only two
+back-end servers.  Greater performance gains will be had as the number
+of back-end servers increases.
+</para>
+
+<para>This optimization improved the following <command>x11perf</command> tests by more
+than 10%:
+<screen>
+1.12   Fill 100x100 stippled trapezoid (161x145 stipple)
+1.26   PutImage 10x10 square
+1.83   PutImage 100x100 square
+1.91   PutImage 500x500 square
+1.40   PutImage XY 10x10 square
+1.48   PutImage XY 100x100 square
+1.50   PutImage XY 500x500 square
+1.45   Circulate Unmapped window (75 kids)
+1.74   Circulate Unmapped window (100 kids)
+</screen>
+</para>
+
+<para>The following test was noted to be more than 10% slower with this
+optimization:
+<screen>
+0.88   10-pixel fill chord partial circle
+</screen>
+</para>
+</sect3>
+
+<sect3>
+<title>Summary of x11perf Data</title>
+
+<para>With all of the optimizations on, 53 <command>x11perf</command> tests are more than
+100X faster than the unoptimized Phase II deliverable, with 69 more than
+50X faster, 73 more than 10X faster, and 199 more than twice as fast.
+No tests were more than 10% slower than the unoptimized Phase II
+deliverable.  (Compared with the Phase I deliverable, only Circulate
+Unmapped window (100 kids) was more than 10% slower than the Phase II
+deliverable.  As noted above, this test seems to have wider variability
+than other <command>x11perf</command> tests.)
+</para>
+
+<para>The following table summarizes relative <command>x11perf</command> test changes for
+all optimizations individually and collectively.  Note that some of the
+optimizations have a synergistic effect when used together.
+<screen>
+
+1: XSync() batching only
+2: Off screen optimizations only
+3: Window optimizations only
+4: Subdivprims only
+5: All optimizations
+
+    1     2    3    4      5 Operation
+------ ---- ---- ---- ------ ---------
+  2.14 1.85 1.00 1.00   4.13 Dot
+  1.67 1.80 1.00 1.00   3.31 1x1 rectangle
+  2.38 1.43 1.00 1.00   2.44 10x10 rectangle
+  1.00 1.00 0.92 0.98   1.00 100x100 rectangle
+  1.00 1.00 1.00 1.00   1.00 500x500 rectangle
+  1.83 1.85 1.05 1.06   3.54 1x1 stippled rectangle (8x8 stipple)
+  2.43 1.43 1.00 1.00   2.41 10x10 stippled rectangle (8x8 stipple)
+  0.98 1.00 1.00 1.00   1.00 100x100 stippled rectangle (8x8 stipple)
+  1.00 1.00 1.00 1.00   0.98 500x500 stippled rectangle (8x8 stipple)
+  1.75 1.75 1.00 1.00   3.40 1x1 opaque stippled rectangle (8x8 stipple)
+  2.38 1.42 1.00 1.00   2.34 10x10 opaque stippled rectangle (8x8 stipple)
+  1.00 1.00 0.97 0.97   1.00 100x100 opaque stippled rectangle (8x8 stipple)
+  1.00 1.00 1.00 1.00   0.99 500x500 opaque stippled rectangle (8x8 stipple)
+  1.82 1.82 1.04 1.04   3.56 1x1 tiled rectangle (4x4 tile)
+  2.33 1.42 1.00 1.00   2.37 10x10 tiled rectangle (4x4 tile)
+  1.00 0.92 1.00 1.00   1.00 100x100 tiled rectangle (4x4 tile)
+  1.00 1.00 1.00 1.00   1.00 500x500 tiled rectangle (4x4 tile)
+  1.94 1.62 1.00 1.00   3.66 1x1 stippled rectangle (17x15 stipple)
+  1.74 1.28 1.00 1.00   1.73 10x10 stippled rectangle (17x15 stipple)
+  1.00 1.00 1.00 0.89   0.98 100x100 stippled rectangle (17x15 stipple)
+  1.00 1.00 1.00 1.00   0.98 500x500 stippled rectangle (17x15 stipple)
+  1.94 1.62 1.00 1.00   3.67 1x1 opaque stippled rectangle (17x15 stipple)
+  1.69 1.26 1.00 1.00   1.66 10x10 opaque stippled rectangle (17x15 stipple)
+  1.00 0.95 1.00 1.00   1.00 100x100 opaque stippled rectangle (17x15 stipple)
+  1.00 1.00 1.00 1.00   0.97 500x500 opaque stippled rectangle (17x15 stipple)
+  1.93 1.61 0.99 0.99   3.69 1x1 tiled rectangle (17x15 tile)
+  1.73 1.27 1.00 1.00   1.72 10x10 tiled rectangle (17x15 tile)
+  1.00 1.00 1.00 1.00   0.98 100x100 tiled rectangle (17x15 tile)
+  1.00 1.00 0.97 0.97   1.00 500x500 tiled rectangle (17x15 tile)
+  1.95 1.63 1.00 1.00   3.83 1x1 stippled rectangle (161x145 stipple)
+  1.80 1.30 1.00 1.00   1.83 10x10 stippled rectangle (161x145 stipple)
+  0.97 1.00 1.00 1.00   1.01 100x100 stippled rectangle (161x145 stipple)
+  1.00 1.00 1.00 1.00   0.98 500x500 stippled rectangle (161x145 stipple)
+  1.95 1.63 1.00 1.00   3.56 1x1 opaque stippled rectangle (161x145 stipple)
+  1.65 1.25 1.00 1.00   1.68 10x10 opaque stippled rectangle (161x145 stipple)
+  1.00 1.00 1.00 1.00   1.01 100x100 opaque stippled rectangle (161x145...
+  1.00 1.00 1.00 1.00   0.97 500x500 opaque stippled rectangle (161x145...
+  1.95 1.63 0.98 0.99   3.80 1x1 tiled rectangle (161x145 tile)
+  1.67 1.26 1.00 1.00   1.67 10x10 tiled rectangle (161x145 tile)
+  1.13 1.14 1.14 1.14   1.14 100x100 tiled rectangle (161x145 tile)
+  0.88 1.00 1.00 1.00   0.99 500x500 tiled rectangle (161x145 tile)
+  1.93 1.63 1.00 1.00   3.53 1x1 tiled rectangle (216x208 tile)
+  1.69 1.26 1.00 1.00   1.66 10x10 tiled rectangle (216x208 tile)
+  1.00 1.00 1.00 1.00   1.00 100x100 tiled rectangle (216x208 tile)
+  1.00 1.00 1.00 1.00   1.00 500x500 tiled rectangle (216x208 tile)
+  1.82 1.70 1.00 1.00   3.38 1-pixel line segment
+  2.07 1.56 0.90 1.00   3.31 10-pixel line segment
+  1.29 1.10 1.00 1.00   1.27 100-pixel line segment
+  1.05 1.06 1.03 1.03   1.09 500-pixel line segment
+  1.30 1.13 1.00 1.00   1.29 100-pixel line segment (1 kid)
+  1.32 1.15 1.00 1.00   1.32 100-pixel line segment (2 kids)
+  1.33 1.16 1.00 1.00   1.33 100-pixel line segment (3 kids)
+  1.92 1.64 1.00 1.00   3.73 10-pixel dashed segment
+  1.34 1.16 1.00 1.00   1.34 100-pixel dashed segment
+  1.24 1.11 0.99 0.97   1.23 100-pixel double-dashed segment
+  1.72 1.77 1.00 1.00   3.25 10-pixel horizontal line segment
+  1.83 1.66 1.01 1.00   3.54 100-pixel horizontal line segment
+  1.86 1.30 1.00 1.00   1.84 500-pixel horizontal line segment
+  2.11 1.52 1.00 0.99   3.02 10-pixel vertical line segment
+  1.21 1.10 1.00 1.00   1.20 100-pixel vertical line segment
+  1.03 1.03 1.00 1.00   1.02 500-pixel vertical line segment
+  4.42 1.68 1.00 1.01   4.64 10x1 wide horizontal line segment
+  1.83 1.31 1.00 1.00   1.83 100x10 wide horizontal line segment
+  1.07 1.00 0.96 1.00   1.07 500x50 wide horizontal line segment
+  4.10 1.67 1.00 1.00   4.62 10x1 wide vertical line segment
+  1.50 1.24 1.06 1.06   1.48 100x10 wide vertical line segment
+  1.06 1.03 1.00 1.00   1.05 500x50 wide vertical line segment
+  2.54 1.61 1.00 1.00   3.61 1-pixel line
+  2.71 1.48 1.00 1.00   2.67 10-pixel line
+  1.19 1.09 1.00 1.00   1.19 100-pixel line
+  1.04 1.02 1.00 1.00   1.03 500-pixel line
+  2.68 1.51 0.98 1.00   3.17 10-pixel dashed line
+  1.23 1.11 0.99 0.99   1.23 100-pixel dashed line
+  1.15 1.08 1.00 1.00   1.15 100-pixel double-dashed line
+  2.27 1.39 1.00 1.00   2.23 10x1 wide line
+  1.20 1.09 1.00 1.00   1.20 100x10 wide line
+  1.04 1.02 1.00 1.00   1.04 500x50 wide line
+  1.52 1.45 1.00 1.00   1.52 100x10 wide dashed line
+  1.54 1.47 1.00 1.00   1.54 100x10 wide double-dashed line
+  1.97 1.30 0.96 0.95   1.95 10x10 rectangle outline
+  1.44 1.27 1.00 1.00   1.43 100x100 rectangle outline
+  3.22 2.16 1.10 1.09   3.61 500x500 rectangle outline
+  1.95 1.34 1.00 1.00   1.90 10x10 wide rectangle outline
+  1.14 1.14 1.00 1.00   1.13 100x100 wide rectangle outline
+  1.00 1.00 1.00 1.00   1.00 500x500 wide rectangle outline
+  1.57 1.72 1.00 1.00   3.03 1-pixel circle
+  1.96 1.35 1.00 1.00   1.92 10-pixel circle
+  1.21 1.07 0.86 0.97   1.20 100-pixel circle
+  1.08 1.04 1.00 1.00   1.08 500-pixel circle
+  1.39 1.19 1.03 1.03   1.38 100-pixel dashed circle
+  1.21 1.11 1.00 1.00   1.23 100-pixel double-dashed circle
+  1.59 1.28 1.00 1.00   1.58 10-pixel wide circle
+  1.22 1.12 0.99 1.00   1.22 100-pixel wide circle
+  1.06 1.04 1.00 1.00   1.05 500-pixel wide circle
+  1.87 1.84 1.00 1.00   1.85 100-pixel wide dashed circle
+  1.90 1.93 1.01 1.01   1.90 100-pixel wide double-dashed circle
+  2.13 1.43 1.00 1.00   2.32 10-pixel partial circle
+  1.42 1.18 1.00 1.00   1.42 100-pixel partial circle
+  1.92 1.85 1.01 1.01   1.89 10-pixel wide partial circle
+  1.73 1.67 1.00 1.00   1.73 100-pixel wide partial circle
+  1.36 1.95 1.00 1.00   2.64 1-pixel solid circle
+  2.02 1.37 1.00 1.00   2.03 10-pixel solid circle
+  1.19 1.09 1.00 1.00   1.19 100-pixel solid circle
+  1.02 0.99 1.00 1.00   1.01 500-pixel solid circle
+  1.74 1.28 1.00 0.88   1.73 10-pixel fill chord partial circle
+  1.31 1.13 1.00 1.00   1.31 100-pixel fill chord partial circle
+  1.67 1.31 1.03 1.03   1.72 10-pixel fill slice partial circle
+  1.30 1.13 1.00 1.00   1.28 100-pixel fill slice partial circle
+  2.45 1.49 1.01 1.00   2.71 10-pixel ellipse
+  1.22 1.10 1.00 1.00   1.22 100-pixel ellipse
+  1.09 1.04 1.00 1.00   1.09 500-pixel ellipse
+  1.90 1.28 1.00 1.00   1.89 100-pixel dashed ellipse
+  1.62 1.24 0.96 0.97   1.61 100-pixel double-dashed ellipse
+  2.43 1.50 1.00 1.00   2.42 10-pixel wide ellipse
+  1.61 1.28 1.03 1.03   1.60 100-pixel wide ellipse
+  1.08 1.05 1.00 1.00   1.08 500-pixel wide ellipse
+  1.93 1.88 1.00 1.00   1.88 100-pixel wide dashed ellipse
+  1.94 1.89 1.01 1.00   1.94 100-pixel wide double-dashed ellipse
+  2.31 1.48 1.00 1.00   2.67 10-pixel partial ellipse
+  1.38 1.17 1.00 1.00   1.38 100-pixel partial ellipse
+  2.00 1.85 0.98 0.97   1.98 10-pixel wide partial ellipse
+  1.89 1.86 1.00 1.00   1.89 100-pixel wide partial ellipse
+  3.49 1.60 1.00 1.00   3.65 10-pixel filled ellipse
+  1.67 1.26 1.00 1.00   1.67 100-pixel filled ellipse
+  1.06 1.04 1.00 1.00   1.06 500-pixel filled ellipse
+  2.38 1.43 1.01 1.00   2.32 10-pixel fill chord partial ellipse
+  2.06 1.30 1.00 1.00   2.05 100-pixel fill chord partial ellipse
+  2.27 1.41 1.00 1.00   2.27 10-pixel fill slice partial ellipse
+  1.98 1.33 1.00 0.97   1.97 100-pixel fill slice partial ellipse
+ 57.46 1.99 1.01 1.00 114.92 Fill 1x1 equivalent triangle
+ 56.94 1.98 1.01 1.00  73.89 Fill 10x10 equivalent triangle
+  6.07 1.75 1.00 1.00   6.07 Fill 100x100 equivalent triangle
+ 51.12 1.98 1.00 1.00 102.81 Fill 1x1 trapezoid
+ 51.42 1.82 1.01 1.00  94.89 Fill 10x10 trapezoid
+  6.47 1.80 1.00 1.00   6.44 Fill 100x100 trapezoid
+  1.56 1.28 1.00 0.99   1.56 Fill 300x300 trapezoid
+ 51.27 1.97 0.96 0.97 102.54 Fill 1x1 stippled trapezoid (8x8 stipple)
+ 51.73 2.00 1.02 1.02  67.92 Fill 10x10 stippled trapezoid (8x8 stipple)
+  5.36 1.72 1.00 1.00   5.36 Fill 100x100 stippled trapezoid (8x8 stipple)
+  1.54 1.26 1.00 1.00   1.59 Fill 300x300 stippled trapezoid (8x8 stipple)
+ 51.41 1.94 1.01 1.00 102.82 Fill 1x1 opaque stippled trapezoid (8x8 stipple)
+ 50.71 1.95 0.99 1.00  65.44 Fill 10x10 opaque stippled trapezoid (8x8...
+  5.33 1.73 1.00 1.00   5.36 Fill 100x100 opaque stippled trapezoid (8x8...
+  1.58 1.25 1.00 1.00   1.58 Fill 300x300 opaque stippled trapezoid (8x8...
+ 51.56 1.96 0.99 0.90 103.68 Fill 1x1 tiled trapezoid (4x4 tile)
+ 51.59 1.99 1.01 1.01  62.25 Fill 10x10 tiled trapezoid (4x4 tile)
+  5.38 1.72 1.00 1.00   5.38 Fill 100x100 tiled trapezoid (4x4 tile)
+  1.54 1.25 1.00 0.99   1.58 Fill 300x300 tiled trapezoid (4x4 tile)
+ 51.70 1.98 1.01 1.01 103.98 Fill 1x1 stippled trapezoid (17x15 stipple)
+ 44.86 1.97 1.00 1.00  44.86 Fill 10x10 stippled trapezoid (17x15 stipple)
+  2.74 1.56 1.00 1.00   2.73 Fill 100x100 stippled trapezoid (17x15 stipple)
+  1.29 1.14 1.00 1.00   1.27 Fill 300x300 stippled trapezoid (17x15 stipple)
+ 51.41 1.96 0.96 0.95 103.39 Fill 1x1 opaque stippled trapezoid (17x15...
+ 45.14 1.96 1.01 1.00  45.14 Fill 10x10 opaque stippled trapezoid (17x15...
+  2.68 1.56 1.00 1.00   2.68 Fill 100x100 opaque stippled trapezoid (17x15...
+  1.26 1.10 1.00 1.00   1.28 Fill 300x300 opaque stippled trapezoid (17x15...
+ 51.13 1.97 1.00 0.99 103.39 Fill 1x1 tiled trapezoid (17x15 tile)
+ 47.58 1.96 1.00 1.00  47.86 Fill 10x10 tiled trapezoid (17x15 tile)
+  2.74 1.56 1.00 1.00   2.74 Fill 100x100 tiled trapezoid (17x15 tile)
+  1.29 1.14 1.00 1.00   1.28 Fill 300x300 tiled trapezoid (17x15 tile)
+ 51.13 1.97 0.99 0.97 103.39 Fill 1x1 stippled trapezoid (161x145 stipple)
+ 45.14 1.97 1.00 1.00  44.29 Fill 10x10 stippled trapezoid (161x145 stipple)
+  3.02 1.77 1.12 1.12   3.38 Fill 100x100 stippled trapezoid (161x145 stipple)
+  1.31 1.13 1.00 1.00   1.30 Fill 300x300 stippled trapezoid (161x145 stipple)
+ 51.27 1.97 1.00 1.00 103.10 Fill 1x1 opaque stippled trapezoid (161x145...
+ 45.01 1.97 1.00 1.00  45.01 Fill 10x10 opaque stippled trapezoid (161x145...
+  2.67 1.56 1.00 1.00   2.69 Fill 100x100 opaque stippled trapezoid (161x145..
+  1.29 1.13 1.00 1.01   1.27 Fill 300x300 opaque stippled trapezoid (161x145..
+ 51.41 1.96 1.00 0.99 103.39 Fill 1x1 tiled trapezoid (161x145 tile)
+ 45.01 1.96 0.98 1.00  45.01 Fill 10x10 tiled trapezoid (161x145 tile)
+  2.62 1.36 1.00 1.00   2.69 Fill 100x100 tiled trapezoid (161x145 tile)
+  1.27 1.13 1.00 1.00   1.22 Fill 300x300 tiled trapezoid (161x145 tile)
+ 51.13 1.98 1.00 1.00 103.39 Fill 1x1 tiled trapezoid (216x208 tile)
+ 45.14 1.97 1.01 0.99  45.14 Fill 10x10 tiled trapezoid (216x208 tile)
+  2.62 1.55 1.00 1.00   2.71 Fill 100x100 tiled trapezoid (216x208 tile)
+  1.28 1.13 1.00 1.00   1.20 Fill 300x300 tiled trapezoid (216x208 tile)
+ 50.71 1.95 1.00 1.00  54.70 Fill 10x10 equivalent complex polygon
+  5.51 1.71 0.96 0.98   5.47 Fill 100x100 equivalent complex polygons
+  8.39 1.97 1.00 1.00  16.75 Fill 10x10 64-gon (Convex)
+  8.38 1.83 1.00 1.00   8.43 Fill 100x100 64-gon (Convex)
+  8.50 1.96 1.00 1.00  16.64 Fill 10x10 64-gon (Complex)
+  8.26 1.83 1.00 1.00   8.35 Fill 100x100 64-gon (Complex)
+ 14.09 1.87 1.00 1.00  14.05 Char in 80-char line (6x13)
+ 11.91 1.87 1.00 1.00  11.95 Char in 70-char line (8x13)
+ 11.16 1.85 1.01 1.00  11.10 Char in 60-char line (9x15)
+ 10.09 1.78 1.00 1.00  10.09 Char16 in 40-char line (k14)
+  6.15 1.75 1.00 1.00   6.31 Char16 in 23-char line (k24)
+ 11.92 1.90 1.03 1.03  11.88 Char in 80-char line (TR 10)
+  8.18 1.78 1.00 0.99   8.17 Char in 30-char line (TR 24)
+ 42.83 1.44 1.01 1.00  42.11 Char in 20/40/20 line (6x13, TR 10)
+ 27.45 1.43 1.01 1.01  27.45 Char16 in 7/14/7 line (k14, k24)
+ 12.13 1.85 1.00 1.00  12.05 Char in 80-char image line (6x13)
+ 10.00 1.84 1.00 1.00  10.00 Char in 70-char image line (8x13)
+  9.18 1.83 1.00 1.00   9.12 Char in 60-char image line (9x15)
+  9.66 1.82 0.98 0.95   9.66 Char16 in 40-char image line (k14)
+  5.82 1.72 1.00 1.00   5.99 Char16 in 23-char image line (k24)
+  8.70 1.80 1.00 1.00   8.65 Char in 80-char image line (TR 10)
+  4.67 1.66 1.00 1.00   4.67 Char in 30-char image line (TR 24)
+ 84.43 1.47 1.00 1.00 124.18 Scroll 10x10 pixels
+  3.73 1.50 1.00 0.98   3.73 Scroll 100x100 pixels
+  1.00 1.00 1.00 1.00   1.00 Scroll 500x500 pixels
+ 84.43 1.51 1.00 1.00 134.02 Copy 10x10 from window to window
+  3.62 1.51 0.98 0.98   3.62 Copy 100x100 from window to window
+  0.89 1.00 1.00 1.00   1.00 Copy 500x500 from window to window
+ 57.06 1.99 1.00 1.00  88.64 Copy 10x10 from pixmap to window
+  2.49 2.00 1.00 1.00   2.48 Copy 100x100 from pixmap to window
+  1.00 0.91 1.00 1.00   0.98 Copy 500x500 from pixmap to window
+  2.04 1.01 1.00 1.00   2.03 Copy 10x10 from window to pixmap
+  1.05 1.00 1.00 1.00   1.05 Copy 100x100 from window to pixmap
+  1.00 1.00 0.93 1.00   1.04 Copy 500x500 from window to pixmap
+ 58.52 1.03 1.03 1.02  57.95 Copy 10x10 from pixmap to pixmap
+  2.40 1.00 1.00 1.00   2.45 Copy 100x100 from pixmap to pixmap
+  1.00 1.00 1.00 1.00   1.00 Copy 500x500 from pixmap to pixmap
+ 51.57 1.92 1.00 1.00  85.75 Copy 10x10 1-bit deep plane
+  6.37 1.75 1.01 1.01   6.37 Copy 100x100 1-bit deep plane
+  1.26 1.11 1.00 1.00   1.24 Copy 500x500 1-bit deep plane
+  4.23 1.63 0.98 0.97   4.38 Copy 10x10 n-bit deep plane
+  1.04 1.02 1.00 1.00   1.04 Copy 100x100 n-bit deep plane
+  1.00 1.00 1.00 1.00   1.00 Copy 500x500 n-bit deep plane
+  6.45 1.98 1.00 1.26  12.80 PutImage 10x10 square
+  1.10 1.87 1.00 1.83   2.11 PutImage 100x100 square
+  1.02 1.93 1.00 1.91   1.91 PutImage 500x500 square
+  4.17 1.78 1.00 1.40   7.18 PutImage XY 10x10 square
+  1.27 1.49 0.97 1.48   2.10 PutImage XY 100x100 square
+  1.00 1.50 1.00 1.50   1.52 PutImage XY 500x500 square
+  1.07 1.01 1.00 1.00   1.06 GetImage 10x10 square
+  1.01 1.00 1.00 1.00   1.01 GetImage 100x100 square
+  1.00 1.00 1.00 1.00   1.00 GetImage 500x500 square
+  1.56 1.00 0.99 0.97   1.56 GetImage XY 10x10 square
+  1.02 1.00 1.00 1.00   1.02 GetImage XY 100x100 square
+  1.00 1.00 1.00 1.00   1.00 GetImage XY 500x500 square
+  1.00 1.00 1.01 0.98   0.95 X protocol NoOperation
+  1.02 1.03 1.04 1.03   1.00 QueryPointer
+  1.03 1.02 1.04 1.03   1.00 GetProperty
+100.41 1.51 1.00 1.00 198.76 Change graphics context
+ 45.81 1.00 0.99 0.97  57.10 Create and map subwindows (4 kids)
+ 78.45 1.01 1.02 1.02  63.07 Create and map subwindows (16 kids)
+ 73.91 1.01 1.00 1.00  56.37 Create and map subwindows (25 kids)
+ 73.22 1.00 1.00 1.00  49.07 Create and map subwindows (50 kids)
+ 72.36 1.01 0.99 1.00  32.14 Create and map subwindows (75 kids)
+ 70.34 1.00 1.00 1.00  30.12 Create and map subwindows (100 kids)
+ 55.00 1.00 1.00 0.99  23.75 Create and map subwindows (200 kids)
+ 55.30 1.01 1.00 1.00 141.03 Create unmapped window (4 kids)
+ 55.38 1.01 1.01 1.00 163.25 Create unmapped window (16 kids)
+ 54.75 0.96 1.00 0.99 166.95 Create unmapped window (25 kids)
+ 54.83 1.00 1.00 0.99 178.81 Create unmapped window (50 kids)
+ 55.38 1.01 1.01 1.00 181.20 Create unmapped window (75 kids)
+ 55.38 1.01 1.01 1.00 181.20 Create unmapped window (100 kids)
+ 54.87 1.01 1.01 1.00 182.05 Create unmapped window (200 kids)
+ 28.13 1.00 1.00 1.00  30.75 Map window via parent (4 kids)
+ 36.14 1.01 1.01 1.01  32.58 Map window via parent (16 kids)
+ 26.13 1.00 0.98 0.95  29.85 Map window via parent (25 kids)
+ 40.07 1.00 1.01 1.00  27.57 Map window via parent (50 kids)
+ 23.26 0.99 1.00 1.00  18.23 Map window via parent (75 kids)
+ 22.91 0.99 1.00 0.99  16.52 Map window via parent (100 kids)
+ 27.79 1.00 1.00 0.99  12.50 Map window via parent (200 kids)
+ 22.35 1.00 1.00 1.00  56.19 Unmap window via parent (4 kids)
+  9.57 1.00 0.99 1.00  89.78 Unmap window via parent (16 kids)
+ 80.77 1.01 1.00 1.00 103.85 Unmap window via parent (25 kids)
+ 96.34 1.00 1.00 1.00 116.06 Unmap window via parent (50 kids)
+ 99.72 1.00 1.00 1.00 124.93 Unmap window via parent (75 kids)
+112.36 1.00 1.00 1.00 125.27 Unmap window via parent (100 kids)
+105.41 1.00 1.00 0.99 120.00 Unmap window via parent (200 kids)
+ 51.29 1.03 1.02 1.02  74.19 Destroy window via parent (4 kids)
+ 86.75 0.99 0.99 0.99 116.87 Destroy window via parent (16 kids)
+106.43 1.01 1.01 1.01 127.49 Destroy window via parent (25 kids)
+120.34 1.01 1.01 1.00 140.11 Destroy window via parent (50 kids)
+126.67 1.00 0.99 0.99 145.00 Destroy window via parent (75 kids)
+126.11 1.01 1.01 1.00 140.56 Destroy window via parent (100 kids)
+128.57 1.01 1.00 1.00 137.91 Destroy window via parent (200 kids)
+ 16.04 0.88 1.00 1.00  20.36 Hide/expose window via popup (4 kids)
+ 19.04 1.01 1.00 1.00  23.48 Hide/expose window via popup (16 kids)
+ 19.22 1.00 1.00 1.00  20.44 Hide/expose window via popup (25 kids)
+ 17.41 1.00 0.91 0.97  17.68 Hide/expose window via popup (50 kids)
+ 17.29 1.01 1.00 1.01  17.07 Hide/expose window via popup (75 kids)
+ 16.74 1.00 1.00 1.00  16.17 Hide/expose window via popup (100 kids)
+ 10.30 1.00 1.00 1.00  10.51 Hide/expose window via popup (200 kids)
+ 16.48 1.01 1.00 1.00  26.05 Move window (4 kids)
+ 17.01 0.95 1.00 1.00  23.97 Move window (16 kids)
+ 16.95 1.00 1.00 1.00  22.90 Move window (25 kids)
+ 16.05 1.01 1.00 1.00  21.32 Move window (50 kids)
+ 15.58 1.00 0.98 0.98  19.44 Move window (75 kids)
+ 14.98 1.02 1.03 1.03  18.17 Move window (100 kids)
+ 10.90 1.01 1.01 1.00  12.68 Move window (200 kids)
+ 49.42 1.00 1.00 1.00 198.27 Moved unmapped window (4 kids)
+ 50.72 0.97 1.00 1.00 193.66 Moved unmapped window (16 kids)
+ 50.87 1.00 0.99 1.00 195.09 Moved unmapped window (25 kids)
+ 50.72 1.00 1.00 1.00 189.34 Moved unmapped window (50 kids)
+ 50.87 1.00 1.00 1.00 191.33 Moved unmapped window (75 kids)
+ 50.87 1.00 1.00 0.90 186.71 Moved unmapped window (100 kids)
+ 50.87 1.00 1.00 1.00 179.19 Moved unmapped window (200 kids)
+ 41.04 1.00 1.00 1.00  56.61 Move window via parent (4 kids)
+ 69.81 1.00 1.00 1.00 130.82 Move window via parent (16 kids)
+ 95.81 1.00 1.00 1.00 141.92 Move window via parent (25 kids)
+ 95.98 1.00 1.00 1.00 149.43 Move window via parent (50 kids)
+ 96.59 1.01 1.01 1.00 153.98 Move window via parent (75 kids)
+ 97.19 1.00 1.00 1.00 157.30 Move window via parent (100 kids)
+ 96.67 1.00 0.99 0.96 159.44 Move window via parent (200 kids)
+ 17.75 1.01 1.00 1.00  27.61 Resize window (4 kids)
+ 17.94 1.00 1.00 0.99  25.42 Resize window (16 kids)
+ 17.92 1.01 1.00 1.00  24.47 Resize window (25 kids)
+ 17.24 0.97 1.00 1.00  24.14 Resize window (50 kids)
+ 16.81 1.00 1.00 0.99  22.75 Resize window (75 kids)
+ 16.08 1.00 1.00 1.00  21.20 Resize window (100 kids)
+ 12.92 1.00 0.99 1.00  16.26 Resize window (200 kids)
+ 52.94 1.01 1.00 1.00 327.12 Resize unmapped window (4 kids)
+ 53.60 1.01 1.01 1.01 333.71 Resize unmapped window (16 kids)
+ 52.99 1.00 1.00 1.00 337.29 Resize unmapped window (25 kids)
+ 51.98 1.00 1.00 1.00 329.38 Resize unmapped window (50 kids)
+ 53.05 0.89 1.00 1.00 322.60 Resize unmapped window (75 kids)
+ 53.05 1.00 1.00 1.00 318.08 Resize unmapped window (100 kids)
+ 53.11 1.00 1.00 0.99 306.21 Resize unmapped window (200 kids)
+ 16.76 1.00 0.96 1.00  19.46 Circulate window (4 kids)
+ 17.24 1.00 1.00 0.97  16.24 Circulate window (16 kids)
+ 16.30 1.03 1.03 1.03  15.85 Circulate window (25 kids)
+ 13.45 1.00 1.00 1.00  14.90 Circulate window (50 kids)
+ 12.91 1.00 1.00 1.00  13.06 Circulate window (75 kids)
+ 11.30 0.98 1.00 1.00  11.03 Circulate window (100 kids)
+  7.58 1.01 1.01 0.99   7.47 Circulate window (200 kids)
+  1.01 1.01 0.98 1.00   0.95 Circulate Unmapped window (4 kids)
+  1.07 1.07 1.01 1.07   1.02 Circulate Unmapped window (16 kids)
+  1.04 1.09 1.06 1.05   0.97 Circulate Unmapped window (25 kids)
+  1.04 1.23 1.20 1.18   1.05 Circulate Unmapped window (50 kids)
+  1.18 1.53 1.19 1.45   1.24 Circulate Unmapped window (75 kids)
+  1.08 1.02 1.01 1.74   1.01 Circulate Unmapped window (100 kids)
+  1.01 1.12 0.98 0.91   0.97 Circulate Unmapped window (200 kids)
+</screen>
+</para>
+</sect3>
+
+<sect3>
+<title>Profiling with OProfile</title>
+
+<para>OProfile (available from http://oprofile.sourceforge.net/) is a
+system-wide profiler for Linux systems that uses processor-level
+counters to collect sampling data.  OProfile can provide information
+that is similar to that provided by <command>gprof</command>, but without the
+necessity of recompiling the program with special instrumentation (i.e.,
+OProfile can collect statistical profiling information about optimized
+programs).  A test harness was developed to collect OProfile data for
+each <command>x11perf</command> test individually.
+</para>
+
+<para>Test runs were performed using the RETIRED_INSNS counter on the AMD
+Athlon and the CPU_CLK_HALTED counter on the Intel Pentium III (with a
+test configuration different from the one described above).  We have
+examined OProfile output and have compared it with <command>gprof</command> output.
+This investigation has not produced results that yield performance
+increases in <command>x11perf</command> numbers.
+</para>
+
+</sect3>
+
+<!--
+<sect3>Retired Instructions
+
+<p>The initial tests using OProfile were done using the RETIRED_INSNS
+counter with DMX running on the dual-processor AMD Athlon machine - the
+same test configuration that was described above and that was used for
+other tests.  The RETIRED_INSNS counter counts retired instructions and
+showed drawing, text, copying, and image tests to be dominated (&gt;
+30%) by calls to Hash(), SecurityLookupIDByClass(),
+SecurityLookupIDByType(), and StandardReadRequestFromClient().  Some of
+these tests also executed significant instructions in
+WaitForSomething().
+
+<p>In contrast, the window tests executed significant
+instructions in SecurityLookupIDByType(), Hash(),
+StandardReadRequestFromClient(), but also executed significant
+instructions in other routines, such as ConfigureWindow().  Some time
+was spent looking at Hash() function, but optimizations in this routine
+did not lead to a dramatic increase in <tt/x11perf/ performance.
+-->
+
+<!--
+<sect3>Clock Cycles
+
+<p>Retired instructions can be misleading because Intel/AMD instructions
+execute in variable amounts of time.  The OProfile tests were repeated
+using the Intel CPU_CLK_HALTED counter with DMX running on the second
+back-end machine.  Note that this is a different test configuration that
+the one described above.  However, these tests show the amount of time
+(as measured in CPU cycles) that are spent in each routine.  Because
+<tt/x11perf/ was running on the first back-end machine and because
+window optimizations were on, the load on the second back-end machine
+was not significant.
+
+<p>Using CPU_CLK_HALTED, DMX showed simple drawing
+tests spending more than 10% of their time in
+StandardReadRequestFromClient(), with significant time (&gt; 20% total)
+spent in SecurityLookupIDByClass(), WaitForSomething(), and Dispatch().
+For these tests, &lt; 5% of the time was spent in Hash(), which explains
+why optimizing the Hash() routine did not impact <tt/x11perf/ results.
+
+<p>The trapezoid, text, scrolling, copying, and image tests were
+dominated by time in ProcFillPoly(), PanoramiXFillPoly(), dmxFillPolygon(),
+SecurityLookupIDByClass(), SecurityLookupIDByType(), and
+StandardReadRequestFromClient().  Hash() time was generally above 5% but
+less than 10% of total time.
+-->
+
+<sect3>
+<title>X Test Suite</title>
+
+<para>The X Test Suite was run on the fully optimized DMX server using the
+configuration described above.  The following failures were noted:
+<screen>
+XListPixmapFormats: Test 1              [1]
+XChangeWindowAttributes: Test 32        [1]
+XCreateWindow: Test 30                  [1]
+XFreeColors: Test 4                     [3]
+XCopyArea: Test 13, 17, 21, 25, 30      [2]
+XCopyPlane: Test 11, 15, 27, 31         [2]
+XSetFontPath: Test 4                    [1]
+XChangeKeyboardControl: Test 9, 10      [1]
+
+[1] Previously documented errors expected from the Xinerama
+    implementation (see Phase I discussion).
+[2] Newly noted errors that have been verified as expected
+    behavior of the Xinerama implementation.
+[3] Newly noted error that has been verified as a Xinerama
+    implementation bug.
+</screen>
+</para>
+
+</sect3>
+
+</sect2>
+
+<!-- ============================================================ -->
+<sect2>
+<title>Phase III</title>
+
+<para>During the third phase of development, support was provided for the
+following extensions: SHAPE, RENDER, XKEYBOARD, XInput.
+</para>
+
+<sect3>
+<title>SHAPE</title>
+
+<para>The SHAPE extension is supported.  Test applications (e.g., xeyes and
+oclock) and window managers that make use of the SHAPE extension will
+work as expected.
+</para>
+</sect3>
+
+<sect3>
+<title>RENDER</title>
+
+<para>The RENDER extension is supported.  The version included in the DMX
+CVS tree is version 0.2, and this version is fully supported by Xdmx.
+Applications using only version 0.2 functions will work correctly;
+however, some apps that make use of functions from later versions do not
+properly check the extension's major/minor version numbers.  These apps
+will fail with a Bad Implementation error when using post-version 0.2
+functions.  This is expected behavior.  When the DMX CVS tree is updated
+to include newer versions of RENDER, support for these newer functions
+will be added to the DMX X server.
+</para>
+</sect3>
+
+<sect3>
+<title>XKEYBOARD</title>
+
+<para>The XKEYBOARD extension is supported.  If present on the back-end X
+servers, the XKEYBOARD extension will be used to obtain information
+about the type of the keyboard for initialization.  Otherwise, the
+keyboard will be initialized using defaults.  Note that this departs
+from older behavior: when Xdmx is compiled without XKEYBOARD support,
+the map from the back-end X server will be preserved.  With XKEYBOARD
+support, the map is not preserved because better information and control
+of the keyboard is available.
+</para>
+</sect3>
+
+<sect3>
+<title>XInput</title>
+
+<para>The XInput extension is supported.  Any device can be used as a core
+device and be used as an XInput extension device, with the exception of
+core devices on the back-end servers.  This limitation is present
+because cursor handling on the back-end requires that the back-end
+cursor sometimes track the Xdmx core cursor -- behavior that is
+incompatible with using the back-end pointer as a non-core device.
+</para>
+
+<para>Currently, back-end extension devices are not available as Xdmx
+extension devices, but this limitation should be removed in the future.
+</para>
+
+<para>To demonstrate the XInput extension, and to provide more examples for
+low-level input device driver writers, USB device drivers have been
+written for mice (usb-mou), keyboards (usb-kbd), and
+non-mouse/non-keyboard USB devices (usb-oth).  Please see the man page
+for information on Linux kernel drivers that are required for using
+these Xdmx drivers.
+</para>
+</sect3>
+
+<sect3>
+<title>DPMS</title>
+
+<para>The DPMS extension is exported but does not do anything at this time.
+</para>
+
+</sect3>
+
+<sect3>
+<title>Other Extensions</title>
+
+<para>The LBX,
+       SECURITY,
+       XC-APPGROUP, and
+       XFree86-Bigfont
+extensions do not require any special Xdmx support and have been exported.
+</para>
+
+<para>The
+    BIG-REQUESTS,
+    DEC-XTRAP,
+    DOUBLE-BUFFER,
+    Extended-Visual-Information,
+    FontCache,
+    GLX,
+    MIT-SCREEN-SAVER,
+    MIT-SHM,
+    MIT-SUNDRY-NONSTANDARD,
+    RECORD,
+    SECURITY,
+    SGI-GLX,
+    SYNC,
+    TOG-CUP,
+    X-Resource,
+    XC-MISC,
+    XFree86-DGA,
+    XFree86-DRI,
+    XFree86-Misc,
+    XFree86-VidModeExtension, and
+    XVideo
+extensions are <emphasis remap="it">not</emphasis> supported at this time, but will be evaluated
+for inclusion in future DMX releases.  <emphasis remap="bf">See below for additional work
+on extensions after Phase III.</emphasis>
+</para>
+</sect3>
+</sect2>
+
+<sect2>
+<title>Phase IV</title>
+
+<sect3>
+<title>Moving to XFree86 4.3.0</title>
+
+<para>For Phase IV, the recent release of XFree86 4.3.0 (27 February 2003)
+was merged onto the dmx.sourceforge.net CVS trunk and all work is
+proceeding using this tree.
+</para>
+</sect3>
+
+<sect3>
+<title>Extensions </title>
+
+<sect4>
+<title>XC-MISC (supported)</title>
+
+<para>XC-MISC is used internally by the X library to recycle XIDs from the
+X server.  This is important for long-running X server sessions.  Xdmx
+supports this extension.  The X Test Suite passed and failed the exact
+same tests before and after this extension was enabled.
+<!-- Tested February/March 2003 -->
+</para>
+</sect4>
+
+<sect4>
+<title>Extended-Visual-Information (supported)</title>
+
+<para>The Extended-Visual-Information extension provides a method for an X
+client to obtain detailed visual information.  Xdmx supports this
+extension.  It was tested using the <filename>hw/dmx/examples/evi</filename> example
+program.  <emphasis remap="bf">Note that this extension is not Xinerama-aware</emphasis> -- it will
+return visual information for each screen even though Xinerama is
+causing the X server to export a single logical screen.
+<!-- Tested March 2003 -->
+</para>
+</sect4>
+
+<sect4>
+<title>RES (supported)</title>
+
+<para>The X-Resource extension provides a mechanism for a client to obtain
+detailed information about the resources used by other clients.  This
+extension was tested with the <filename>hw/dmx/examples/res</filename> program.  The
+X Test Suite passed and failed the exact same tests before and after
+this extension was enabled.
+<!-- Tested March 2003 -->
+</para>
+</sect4>
+
+<sect4>
+<title>BIG-REQUESTS (supported)</title>
+
+<para>This extension enables the X11 protocol to handle requests longer
+than 262140 bytes.  The X Test Suite passed and failed the exact same
+tests before and after this extension was enabled.
+<!-- Tested March 2003 -->
+</para>
+</sect4>
+
+<sect4>
+<title>XSYNC (supported)</title>
+
+<para>This extension provides facilities for two different X clients to
+synchronize their requests.  This extension was minimally tested with
+<command>xdpyinfo</command> and the X Test Suite passed and failed the exact same
+tests before and after this extension was enabled.
+<!-- Tested March 2003 -->
+</para>
+</sect4>
+
+<sect4>
+<title>XTEST, RECORD, DEC-XTRAP (supported) and XTestExtension1 (not supported)</title>
+
+<para>The XTEST and RECORD extension were developed by the X Consortium for
+use in the X Test Suite and are supported as a standard in the X11R6
+tree.  They are also supported in Xdmx.  When X Test Suite tests that
+make use of the XTEST extension are run, Xdmx passes and fails exactly
+the same tests as does a standard XFree86 X server.  When the
+<literal remap="tt">rcrdtest</literal> test (a part of the X Test Suite that verifies the RECORD
+extension) is run, Xdmx passes and fails exactly the same tests as does
+a standard XFree86 X server. <!-- Tested February/March 2003 -->
+</para>
+
+<para>There are two older XTEST-like extensions: DEC-XTRAP and
+XTestExtension1.  The XTestExtension1 extension was developed for use by
+the X Testing Consortium for use with a test suite that eventually
+became (part of?) the X Test Suite.  Unlike XTEST, which only allows
+events to be sent to the server, the XTestExtension1 extension also
+allowed events to be recorded (similar to the RECORD extension).  The
+second is the DEC-XTRAP extension that was developed by the Digital
+Equipment Corporation.
+</para>
+
+<para>The DEC-XTRAP extension is available from Xdmx and has been tested
+with the <command>xtrap*</command> tools which are distributed as standard X11R6
+clients. <!-- Tested March 2003 -->
+</para>
+
+<para>The XTestExtension1 is <emphasis>not</emphasis> supported because it does not appear
+to be used by any modern X clients (the few that support it also support
+XTEST) and because there are no good methods available for testing that
+it functions correctly (unlike XTEST and DEC-XTRAP, the code for
+XTestExtension1 is not part of the standard X server source tree, so
+additional testing is important). <!-- Tested March 2003 -->
+</para>
+
+<para>Most of these extensions are documented in the X11R6 source tree.
+Further, several original papers exist that this author was unable to
+locate -- for completeness and historical interest, citations are
+provide:
+<variablelist>
+<varlistentry>
+<term>XRECORD</term>
+<listitem>
+<para>Martha Zimet. Extending X For Recording.  8th Annual X
+Technical Conference Boston, MA January 24-26, 1994.
+</para></listitem></varlistentry>
+<varlistentry>
+<term>DEC-XTRAP</term>
+<listitem>
+<para>Dick Annicchiarico, Robert Chesler, Alan Jamison. XTrap
+Architecture. Digital Equipment Corporation, July 1991.
+</para></listitem></varlistentry>
+<varlistentry>
+<term>XTestExtension1</term>
+<listitem>
+<para>Larry Woestman. X11 Input Synthesis Extension
+Proposal. Hewlett Packard, November 1991.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+</sect4>
+
+<sect4>
+<title>MIT-MISC (not supported)</title>
+
+<para>The MIT-MISC extension is used to control a bug-compatibility flag
+that provides compatibility with xterm programs from X11R1 and X11R2.
+There does not appear to be a single client available that makes use of
+this extension and there is not way to verify that it works correctly.
+The Xdmx server does <emphasis>not</emphasis> support MIT-MISC.
+</para>
+</sect4>
+
+<sect4>
+<title>SCREENSAVER (not supported)</title>
+
+<para>This extension provides special support for the X screen saver.  It
+was tested with beforelight, which appears to be the only client that
+works with it.  When Xinerama was not active, <command>beforelight</command> behaved
+as expected.  However, when Xinerama was active, <command>beforelight</command> did
+not behave as expected.  Further, when this extension is not active,
+<command>xscreensaver</command> (a widely-used X screen saver program) did not behave
+as expected.  Since this extension is not Xinerama-aware and is not
+commonly used with expected results by clients, we have left this
+extension disabled at this time.
+</para>
+</sect4>
+
+<sect4>
+<title>GLX (supported)</title>
+
+<para>The GLX extension provides OpenGL and GLX windowing support.  In
+Xdmx, the extension is called glxProxy, and it is Xinerama aware.  It
+works by either feeding requests forward through Xdmx to each of the
+back-end servers or handling them locally.  All rendering requests are
+handled on the back-end X servers.  This code was donated to the DMX
+project by SGI.  For the X Test Suite results comparison, see below.
+</para>
+</sect4>
+
+<sect4>
+<title>RENDER (supported)</title>
+
+<para>The X Rendering Extension (RENDER) provides support for digital image
+composition.  Geometric and text rendering are supported.  RENDER is
+partially Xinerama-aware, with text and the most basic compositing
+operator; however, its higher level primitives (triangles, triangle
+strips, and triangle fans) are not yet Xinerama-aware.  The RENDER
+extension is still under development, and is currently at version 0.8.
+Additional support will be required in DMX as more primitives and/or
+requests are added to the extension.
+</para>
+
+<para>There is currently no test suite for the X Rendering Extension;
+however, there has been discussion of developing a test suite as the
+extension matures.  When that test suite becomes available, additional
+testing can be performed with Xdmx.  The X Test Suite passed and failed
+the exact same tests before and after this extension was enabled.
+</para>
+</sect4>
+
+<sect4>
+<title>Summary</title>
+
+<!-- WARNING: this list is duplicated in the "Common X extension
+support" section -->
+<para>To summarize, the following extensions are currently supported:
+    BIG-REQUESTS,
+    DEC-XTRAP,
+    DMX,
+    DPMS,
+    Extended-Visual-Information,
+    GLX,
+    LBX,
+    RECORD,
+    RENDER,
+    SECURITY,
+    SHAPE,
+    SYNC,
+    X-Resource,
+    XC-APPGROUP,
+    XC-MISC,
+    XFree86-Bigfont,
+    XINERAMA,
+    XInputExtension,
+    XKEYBOARD, and
+    XTEST.
+</para>
+
+<para>The following extensions are <emphasis>not</emphasis> supported at this time:
+    DOUBLE-BUFFER,
+    FontCache,
+    MIT-SCREEN-SAVER,
+    MIT-SHM,
+    MIT-SUNDRY-NONSTANDARD,
+    TOG-CUP,
+    XFree86-DGA,
+    XFree86-Misc,
+    XFree86-VidModeExtension,
+    XTestExtensionExt1, and
+    XVideo.
+</para>
+</sect4>
+</sect3>
+
+<sect3>
+<title>Additional Testing with the X Test Suite</title>
+
+<sect4>
+<title>XFree86 without XTEST</title>
+
+<para>After the release of XFree86 4.3.0, we retested the XFree86 X server
+with and without using the XTEST extension.  When the XTEST extension
+was <emphasis>not</emphasis> used for testing, the XFree86 4.3.0 server running on our
+usual test system with a Radeon VE card reported unexpected failures in
+the following tests:
+<literallayout>
+XListPixmapFormats: Test 1
+XChangeKeyboardControl: Tests 9, 10
+XGetDefault: Test 5
+XRebindKeysym: Test 1
+</literallayout>
+</para>
+</sect4>
+
+<sect4>
+<title>XFree86 with XTEST</title>
+
+<para>When using the XTEST extension, the XFree86 4.3.0 server reported the
+following errors:
+<literallayout>
+XListPixmapFormats: Test 1
+XChangeKeyboardControl: Tests 9, 10
+XGetDefault: Test 5
+XRebindKeysym: Test 1
+
+XAllowEvents: Tests 20, 21, 24
+XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25
+XGrabKey: Test 8
+XSetPointerMapping: Test 3
+XUngrabButton: Test 4
+</literallayout>
+</para>
+
+<para>While these errors may be important, they will probably be fixed
+eventually in the XFree86 source tree.  We are particularly interested
+in demonstrating that the Xdmx server does not introduce additional
+failures that are not known Xinerama failures.
+</para>
+</sect4>
+
+<sect4>
+<title>Xdmx with XTEST, without Xinerama, without GLX</title>
+
+<para>Without Xinerama, but using the XTEST extension, the following errors
+were reported from Xdmx (note that these are the same as for the XFree86
+4.3.0, except that XGetDefault no longer fails):
+<literallayout>
+XListPixmapFormats: Test 1
+XChangeKeyboardControl: Tests 9, 10
+XRebindKeysym: Test 1
+
+XAllowEvents: Tests  20, 21, 24
+XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25
+XGrabKey: Test 8
+XSetPointerMapping: Test 3
+XUngrabButton: Test 4
+</literallayout>
+</para>
+</sect4>
+
+<sect4>
+<title>Xdmx with XTEST, with Xinerama, without GLX</title>
+
+<para>With Xinerama, using the XTEST extension, the following errors
+were reported from Xdmx:
+<literallayout>
+XListPixmapFormats: Test 1
+XChangeKeyboardControl: Tests 9, 10
+XRebindKeysym: Test 1
+
+XAllowEvents: Tests 20, 21, 24
+XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25
+XGrabKey: Test 8
+XSetPointerMapping: Test 3
+XUngrabButton: Test 4
+
+XCopyPlane: Tests 13, 22, 31 (well-known XTEST/Xinerama interaction issue)
+XDrawLine: Test 67
+XDrawLines: Test 91
+XDrawSegments: Test 68
+</literallayout>
+Note that the first two sets of errors are the same as for the XFree86
+4.3.0 server, and that the XCopyPlane error is a well-known error
+resulting from an XTEST/Xinerama interaction when the request crosses a
+screen boundary.  The XDraw* errors are resolved when the tests are run
+individually and they do not cross a screen boundary.  We will
+investigate these errors further to determine their cause.
+</para>
+</sect4>
+
+<sect4>
+<title>Xdmx with XTEST, with Xinerama, with GLX</title>
+
+<para>With GLX enabled, using the XTEST extension, the following errors
+were reported from Xdmx (these results are from early during the Phase
+IV development, but were confirmed with a late Phase IV snapshot):
+<literallayout>
+XListPixmapFormats: Test 1
+XChangeKeyboardControl: Tests 9, 10
+XRebindKeysym: Test 1
+
+XAllowEvents: Tests 20, 21, 24
+XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25
+XGrabKey: Test 8
+XSetPointerMapping: Test 3
+XUngrabButton: Test 4
+
+XClearArea: Test 8
+XCopyArea: Tests 4, 5, 11, 14, 17, 23, 25, 27, 30
+XCopyPlane: Tests 6, 7, 10, 19, 22, 31
+XDrawArcs: Tests 89, 100, 102
+XDrawLine: Test 67
+XDrawSegments: Test 68
+</literallayout>
+Note that the first two sets of errors are the same as for the XFree86
+4.3.0 server, and that the third set has different failures than when
+Xdmx does not include GLX support.  Since the GLX extension adds new
+visuals to support GLX's visual configs and the X Test Suite runs tests
+over the entire set of visuals, additional rendering tests were run and
+presumably more of them crossed a screen boundary.  This conclusion is
+supported by the fact that nearly all of the rendering errors reported
+are resolved when the tests are run individually and they do no cross a
+screen boundary.
+</para>
+
+<para>Further, when hardware rendering is disabled on the back-end displays,
+many of the errors in the third set are eliminated, leaving only:
+<literallayout>
+XClearArea: Test 8
+XCopyArea: Test 4, 5, 11, 14, 17, 23, 25, 27, 30
+XCopyPlane: Test 6, 7, 10, 19, 22, 31
+</literallayout>
+</para>
+</sect4>
+
+<sect4>
+<title>Conclusion</title>
+
+<para>We conclude that all of the X Test Suite errors reported for Xdmx are
+the result of errors in the back-end X server or the Xinerama
+implementation.  Further, all of these errors that can be reasonably
+fixed at the Xdmx layer have been.  (Where appropriate, we have
+submitted patches to the XFree86 and Xinerama upstream maintainers.)
+</para>
+</sect4>
+</sect3>
+
+<sect3>
+<title>Dynamic Reconfiguration</title>
+
+<para>During this development phase, dynamic reconfiguration support was
+added to DMX.  This support allows an application to change the position
+and offset of a back-end server's screen.  For example, if the
+application would like to shift a screen slightly to the left, it could
+query Xdmx for the screen's &lt;x,y&gt; position and then dynamically
+reconfigure that screen to be at position &lt;x+10,y&gt;.  When a screen
+is dynamically reconfigured, input handling and a screen's root window
+dimensions are adjusted as needed.  These adjustments are transparent to
+the user.
+</para>
+
+<sect4>
+<title>Dynamic reconfiguration extension</title>
+
+<para>The application interface to DMX's dynamic reconfiguration is through
+a function in the DMX extension library:
+<programlisting>
+Bool DMXReconfigureScreen(Display *dpy, int screen, int x, int y)
+</programlisting>
+where <parameter>dpy</parameter> is DMX server's display, <parameter>screen</parameter> is the number of the
+screen to be reconfigured, and <parameter>x</parameter> and <parameter>y</parameter> are the new upper,
+left-hand coordinates of the screen to be reconfigured.
+</para>
+
+<para>The coordinates are not limited other than as required by the X
+protocol, which limits all coordinates to a signed 16 bit number.  In
+addition, all coordinates within a screen must also be legal values.
+Therefore, setting a screen's upper, left-hand coordinates such that the
+right or bottom edges of the screen is greater than 32,767 is illegal.
+</para>
+</sect4>
+
+<sect4>
+<title>Bounding box</title>
+
+<para>When the Xdmx server is started, a bounding box is calculated from
+the screens' layout given either on the command line or in the
+configuration file.  This bounding box is currently fixed for the
+lifetime of the Xdmx server.
+</para>
+
+<para>While it is possible to move a screen outside of the bounding box, it
+is currently not possible to change the dimensions of the bounding box.
+For example, it is possible to specify coordinates of &lt;-100,-100&gt;
+for the upper, left-hand corner of the bounding box, which was
+previously at coordinates &lt;0,0&gt;.  As expected, the screen is moved
+down and to the right; however, since the bounding box is fixed, the
+left side and upper portions of the screen exposed by the
+reconfiguration are no longer accessible on that screen.  Those
+inaccessible regions are filled with black.
+</para>
+
+<para>This fixed bounding box limitation will be addressed in a future
+development phase.
+</para>
+</sect4>
+
+<sect4>
+<title>Sample applications</title>
+
+<para>An example of where this extension is useful is in setting up a video
+wall.  It is not always possible to get everything perfectly aligned,
+and sometimes the positions are changed (e.g., someone might bump into a
+projector).  Instead of physically moving projectors or monitors, it is
+now possible to adjust the positions of the back-end server's screens
+using the dynamic reconfiguration support in DMX.
+</para>
+
+<para>Other applications, such as automatic setup and calibration tools,
+can make use of dynamic reconfiguration to correct for projector
+alignment problems, as long as the projectors are still arranged
+rectilinearly.  Horizontal and vertical keystone correction could be
+applied to projectors to correct for non-rectilinear alignment problems;
+however, this must be done external to Xdmx.
+</para>
+
+<para>A sample test program is included in the DMX server's examples
+directory to demonstrate the interface and how an application might use
+dynamic reconfiguration.  See <filename>dmxreconfig.c</filename> for details.
+</para>
+</sect4>
+
+<sect4>
+<title>Additional notes</title>
+
+<para>In the original development plan, Phase IV was primarily devoted to
+adding OpenGL support to DMX; however, SGI became interested in the DMX
+project and developed code to support OpenGL/GLX.  This code was later
+donated to the DMX project and integrated into the DMX code base, which
+freed the DMX developers to concentrate on dynamic reconfiguration (as
+described above).
+</para>
+</sect4>
+</sect3>
+
+<sect3>
+<title>Doxygen documentation</title>
+
+<para>Doxygen is an open-source (GPL) documentation system for generating
+browseable documentation from stylized comments in the source code.  We
+have placed all of the Xdmx server and DMX protocol source code files
+under Doxygen so that comprehensive documentation for the Xdmx source
+code is available in an easily browseable format.
+</para>
+</sect3>
+
+<sect3>
+<title>Valgrind</title>
+
+<para>Valgrind, an open-source (GPL) memory debugger for Linux, was used to
+search for memory management errors.  Several memory leaks were detected
+and repaired.  The following errors were not addressed:
+<orderedlist>
+    <listitem><para>
+        When the X11 transport layer sends a reply to the client, only
+        those fields that are required by the protocol are filled in --
+        unused fields are left as uninitialized memory and are therefore
+        noted by valgrind.  These instances are not errors and were not
+        repaired.
+    </para></listitem>
+    <listitem><para>
+        At each server generation, glxInitVisuals allocates memory that
+        is never freed.  The amount of memory lost each generation
+        approximately equal to 128 bytes for each back-end visual.
+        Because the code involved is automatically generated, this bug
+        has not been fixed and will be referred to SGI.
+    </para></listitem>
+    <listitem><para>
+        At each server generation, dmxRealizeFont calls XLoadQueryFont,
+        which allocates a font structure that is not freed.
+        dmxUnrealizeFont can free the font structure for the first
+        screen, but cannot free it for the other screens since they are
+        already closed by the time dmxUnrealizeFont could free them.
+        The amount of memory lost each generation is approximately equal
+        to 80 bytes per font per back-end.  When this bug is fixed in
+        the the X server's device-independent (dix) code, DMX will be
+        able to properly free the memory allocated by XLoadQueryFont.
+    </para></listitem>
+</orderedlist>
+</para>
+</sect3>
+
+<sect3>
+<title>RATS</title>
+
+<para>RATS (Rough Auditing Tool for Security) is an open-source (GPL)
+security analysis tool that scans source code for common
+security-related programming errors (e.g., buffer overflows and TOCTOU
+races).  RATS was used to audit all of the code in the hw/dmx directory
+and all "High" notations were checked manually.  The code was either
+re-written to eliminate the warning, or a comment containing "RATS" was
+inserted on the line to indicate that a human had checked the code.
+Unrepaired warnings are as follows:
+<orderedlist>
+    <listitem><para>
+        Fixed-size buffers are used in many areas, but code has been
+        added to protect against buffer overflows (e.g., XmuSnprint).
+        The only instances that have not yet been fixed are in
+        config/xdmxconfig.c (which is not part of the Xdmx server) and
+        input/usb-common.c.
+    </para></listitem>
+    <listitem><para>
+        vprintf and vfprintf are used in the logging routines.  In
+        general, all uses of these functions (e.g., dmxLog) provide a
+        constant format string from a trusted source, so the use is
+        relatively benign.
+    </para></listitem>
+    <listitem><para>
+        glxProxy/glxscreens.c uses getenv and strcat.  The use of these
+        functions is safe and will remain safe as long as
+        ExtensionsString is longer then GLXServerExtensions (ensuring
+        this may not be ovious to the casual programmer, but this is in
+        automatically generated code, so we hope that the generator
+        enforces this constraint).
+    </para></listitem>
+</orderedlist>
+
+</para>
+
+</sect3>
+
+</sect2>
+
+</sect1>
+
+</appendix>
+
+  </article>
+
+  <!-- Local Variables: -->
+  <!-- fill-column: 72  -->
+  <!-- End:             -->
diff --git a/hw/dmx/doc/scaled.sgml b/hw/dmx/doc/scaled.sgml
deleted file mode 100644
index 6b8ee41..0000000
--- a/hw/dmx/doc/scaled.sgml
+++ /dev/null
@@ -1,707 +0,0 @@
-<!DOCTYPE linuxdoc PUBLIC "-//XFree86//DTD linuxdoc//EN">
-  <article>
-
-    <!-- Title information -->
-    <title>Scaled Window Support in DMX</title>
-    <author>Rickard E. Faith and Kevin E. Martin</author>
-    <date>15 October 2003 (created 19 September 2003)</date>
-    <abstract>
-      This document investigates the possibility of adding scaled window
-      support to the DMX X server, thereby allowing a window or some
-      selected part of the logical DMX area to be displayed using a
-      scaling factor.  For example, this might allow the contents of a
-      window to be magnified for easier viewing.  In particular, scaling
-      for the VNC client is explored.  <it>Copyright 2003
-        by Red Hat, Inc., Raleigh, North Carolina</it>
-    </abstract>
-
-    <!-- Table of contents -->
-    <toc>
-      
-      <!-- Begin the document -->
-      <sect>Introduction
-        <sect1>DMX
-          <p>
-            The DMX X server (Xdmx) is a proxy server that is designed
-            to allow X servers on multiple machines to be combined into
-            a single multi-headed X server.  Combined with Xinerama,
-            these heads can appear as a single very high-resolution
-            screen.  Typical applications include the creation of a
-            video wall with 16 1280x1024 displays arranged in a
-            rectangle, for a total resolution of of 5120x4096.
-          </p>
-        </sect1>
-        <sect1>Problem Statement
-          <p>
-            Applications displayed on a physically large video wall that
-            provides high pixel-resolution may be difficult to see,
-            especially if the application is designed for use on a
-            typical desktop computer with a relatively small display
-            located close to the human operator.  The goal of this paper
-            is to describe and discuss solutions to this problem.
-          </p>
-          <p>
-            The original driving problem for this work is to provide
-            scaling for the <tt>vncviewer</tt> application when
-            displayed using DMX (VNC scaling is currently available only
-            with the Windows client, and there is no plan to extend that
-            capability to other clients).  While this specific problem
-            will be addressed in this paper, the general solution space
-            will also be explored, since this may lead to a good
-            solution not only for <tt>vncviewer</tt> but also for
-            other applications.
-          </p>
-        </sect1>
-        <sect1>Task
-          <p>
-            For reference, here is the original description of the task
-            this paper addresses:
-            <itemize>
-              <item>Scaled window support (for VNC)
-                <itemize>
-                  <item>
-                    Investigate possibility of implementing a "scaled
-                    window" extension:
-                    <itemize>
-                      <item>
-                        Add XCreateScaledWindow call that could be used
-                        in place of XCreateWindow
-                      </item>
-                      <item>
-                        All primitives drawn to scaled window would be
-                        scaled by appropriate (integral?) scaling factor
-                      </item>
-                    </itemize>
-                  </item>
-                  <item>
-                    Alternate approach: special case VNC support
-                  </item>
-                </itemize>
-              </item>
-            </itemize>
-          </p>
-        </sect1>
-      </sect>
-      
-      <sect>Previous Work
-        <p>
-          This section reviews relevant previous work.
-        </p>
-        <sect1>VNC
-          <sect2>Scaling under VNC
-            <p>
-              When using the <tt>vncviewer</tt> program for Windows, it
-              is possible to specify a scaling factor (as numerator and
-              denominator).  When scaling is in effect, the viewer
-              software uses StretchBlt (instead of BitBlt) to display
-              the pixels for the user.  When this call is made, the
-              viewer already has received all of the pixel information
-              (at full unscaled resolution).
-            </p>
-            <p>
-              The scaling in VNC is primitive.  It does not conserve
-              bandwidth, it does not treat textual information
-              differently (i.e., by using a suitably scaled font), and
-              it does not provide any anti-aliasing other than that
-              provided by the underlying (Windows-only) system library.
-            </p>
-          </sect2>
-        </sect1>
-        <sect1>The X Video Extension
-          <p>
-            The X Video Extension is a widely-available extension to the
-            X11 protocol that provides support for streaming video.
-            Integral to this support is the ability to arbitrarily scale
-            the output.  In version 2.2 of the X Video specification,
-            support for scaled still images was provided, using both
-            shared memory and traditional transport.  The API for this
-            support uses calls that are quite similar to XCreateWindow,
-            XPutImage, and XShmPutImage.  Currently, most of the drivers
-            implemented in XFree86 only support data in various YUV
-            formats.  However, several modern video adaptors support RGB
-            as well.
-          </p>
-          <p>
-            Note, though, that the target output for this scaling is an
-            overlay plane -- so X Video provides functionality that is
-            fundamentally different from that provided by the Windows
-            StrechBlt call.
-          </p>
-        </sect1>
-      </sect>
-    
-      <sect>Possible Solutions
-        <p>
-          This section briefly discusses possible solutions, including
-          major advantages and disadvantages from both the
-          implementation and the end-user programmer standpoint.
-        </p>
-        <sect1>VNC-like Scaling
-          <sect2>Software Scaling
-            <p>
-              The <tt>vncviewer</tt> application could be modified to
-              provide software scaling.  This is not a general solution,
-              but it does solve one of the goals of this work.
-            </p>
-            <p>
-              A prototype of this solution was implemented and a patch
-              against <tt>vnc-3.3.7-unixsrc</tt> is available in the
-              <tt>dmx/external</tt> directory.  Because of limited time
-              available for this work, all of the edge cases were not
-              considered and the solution works well mainly for integer
-              scaling.
-            </p>
-            <p>
-              Currently, <tt>vncviewer</tt> writes to the X display
-              with XPutImage, XCopyArea, and XFillRectangle.  All
-              instances of these calls have to be aware of scaling
-              and must round correctly.  In the prototype solution,
-              rounding is incorrect and can cause artifacts.
-            </p>
-            <p>
-              A better solution would be to cache all updates to the
-              desktop image in <tt>vncviewer</tt> and only send the
-              damaged area to the X display with XPutImage.  This would
-              allow the damaged area to be computed so that rounding
-              errors do not create artifacts.  This method is probably
-              similar to what is used in the Window client.  (The whole
-              VNC suite is being re-written in C++ and the forthcoming
-              version 4 has not been evaluated.)
-            </p>
-          </sect2>
-          <sect2>Scaling with the X Video Extension
-            <p>
-              The scaling in the Windows <tt>vncviewer</tt> application
-              makes use of a scaled blit that is supplied by the
-              underlying system library.  Several video cards currently
-              provide support for a scaled blit, and some X servers
-              (including XFree86) expose this capability to applications
-              via the XvPutImage interface of the X Video Extension.
-              The capability exposed by XvPutImage results in the scaled
-              image being drawn to an overlay plane.  Most video cards
-              also provide support for a scaled blit into the normal
-              output planes, but this is not exposed via XvPutImage.
-            </p>
-            <p>
-              The <tt>vncviewer</tt> program could be modified to use
-              the X Video Extension to provide scaling under X11 that is
-              similar to the scaling currently provided under Windows.
-              Unfortunately, Xdmx does not currently export the X Video
-              Extension, so this would not provide an immediate solution
-              usable with DMX.
-            </p>
-            <p>
-              A very early-stage proof-of-concept prototype was
-              implemented and a preliminary patch against
-              <tt>vnc-3.3.7-unixsrc</tt> is available in the
-              <tt>dmx/external</tt> directory.  This prototype was
-              implemented to better understand the problems that must be
-              solved to make this solution viable:
-              <itemize>
-                <item>
-                  As noted under the software scaling section above,
-                  <tt>vncviewer</tt> writes to the X display with
-                  several different calls.  These calls write to the
-                  normal output planes and are compatible with
-                  XvPutImage, which writes to an overlay plane.  To
-                  eliminate artifacts caused by this problem,
-                  <tt>vncviewer</tt> should be modified so that a cached
-                  copy of the desktop is available, either as a
-                  client-side image or a server-side off-screen pixmap,
-                  so that XvPutImage would be the only method for
-                  writing to the X display.
-                </item>
-                <item>
-                  <p>
-                    Although several modern graphics adaptors support
-                    hardware scaling using an RGB format (e.g., ATI
-                    Radeon, nVidia, etc.), XFree86 drivers typically
-                    only implement YUV formats.  YUV generally compress
-                    the pixel information in some way.  For example, two
-                    commonly implemented formats, YUY2 and UYVY provide
-                    intensity information for every RGB pixel, but only
-                    provide chroma and luminance information for pairs
-                    of horizontal pixels.  Since VNC uses
-                    pixel-resolution for communicating updates on the
-                    wire, additional artifacts are introduced (because
-                    there may not be enough information from the wire to
-                    update a pair of pixels).
-                  <p>
-                    Further, the well-known problem with YUV encoding
-                    is even more evident when the image is a desktop
-                    instead of a movie.  For example, consider a
-                    1-pixel-wide vertical window border.  If the border
-                    changes in color but not intensity (e.g., because a
-                    window manager uses color to indicate focus), there
-                    may or may not be a change in the YUY2 image,
-                    depending on the algorithm used for RGB to YUV
-                    conversion and on how the border pixel is ordered in
-                    the pair of pixels used by the algorithm.
-                  <p>
-                    Many of these artifacts could be eliminated if
-                    <tt>vncviewer</tt> cached a complete RGB image of
-                    the desktop, and only did the conversion to YUV for
-                    properly aligned areas of damage.  The remaining artifacts
-                    could be eliminated if an RGB format was used with X
-                    Video (which may require the extension of existing
-                    XFree86 drivers to support RGB).
-                </item>
-                <item>
-                  Most modern video cards support exactly one overlay
-                  plane that is suitable for use with X Video.
-                  Therefore, only one application can use X Video at any
-                  given time.  This is a severe limitation in a desktop
-                  environment.
-                </item>
-              </itemize>
-            </p>
-            <sect3>Implementing the X Video Extension for DMX
-              <p>
-                The user-level API for X Video is fairly simple, but the
-                underlying support required for the full specification
-                is large.  However, since the API provides a method to
-                query supported capabilities, a usable subset of X
-                Video can be implemented that would support XvPutImage
-                and little else.  This would require support for the
-                following:
-                <itemize>
-                  <item>
-                    X Video Extension API calls, including the
-                    following:
-                    <itemize>
-                      <item>XvQueryExtension</item>
-                      <item>XvQueryAdaptors</item>
-                      <item>XvQueryPortAttributes</item>
-                      <item>XvFreeAdaptorInfo</item>
-                      <item>XvListImageFormats</item>
-                      <item>XvGrabPort</item>
-                      <item>XvCreateImage</item>
-                      <item>XvPutImage</item>
-                      <item>XvShmCreateImage</item>
-                      <item>XvShmPutImage</item>
-                    </itemize>
-                  </item>
-                  <item>
-                    Support for querying back-end X Video Extension
-                    capabilities.
-                  </item>
-                  <item>
-                    Support for sending the image to the back-ends.
-                    Because X Video requires sending full images, there
-                    may be a trade-off between bandwidth limitations and
-                    additional complexity to divide the image up such
-                    that is scales properly.
-                  </item>
-                  <item>
-                    Possible support for a software fall-back.  For
-                    example, if all of the back-ends do not support the X
-                    Video Extension, software scaling can be implemented
-                    such that the image is sent to the back-end with
-                    XPutImage.  This pathway would have poor
-                    performance.
-                  </item>
-                </itemize>
-              </p>
-            </sect3>
-            <sect3>Supporting RGB formats for the X Video Extension
-              <p>
-                Assuming an XFree86 driver already supports the X Video
-                Extension, and assuming the target hardware supports an
-                RGB format, then adding support for that format is
-                relatively simple and straightforward.
-              </p>
-            </sect3>
-          </sect2>
-          <sect2>Scaling with an XPutImageScaled Extension
-            <p>
-              Instead of (or in addition to) implementing the X Video
-              Extension in DMX, one obvious solution would be to
-              implement a new extension that provides access to
-              hardware-assisted scaled blits, similar to the StretchBlt
-              call available under Windows.  This call would scale RGB
-              images and would not use the overlay plane (unlike the X
-              Video Extension).
-            </p>
-            <p>
-              This approach has many of the same advantages and
-              disadvantages as the XCopyAreaScaled Extension, discussed
-              in the next section.  Discussion of XPutImageScaled is
-              deferred in favor of XCopyAreaScaled for the following
-              reasons:
-              <itemize>
-                <item>
-                  XPutImageScaled can be emulated with XCopyAreaScaled
-                  by first using XPutImage to copy the image to an
-                  off-screen pixmap, and then calling XCopyAreaScaled
-                  between that off-screen pixmap and the target
-                  drawable.
-                </item>
-                <item>
-                  Since XCopyAreaScaled would copy between two areas of
-                  on-screen or off-screen memory, it has additional uses
-                  and can be viewed as efficiently providing a superset
-                  of XPutImageScaled functionality.
-                </item>
-              </itemize>
-            </p>
-          </sect2>
-          <sect2>Scaling with an XCopyAreaScaled Extension
-            <p>
-              As noted in the previous section, because XCopyAreaScaled
-              provides a superset of the functionality provided by
-              XPutImageScaled, we will consider this extension instead.
-            </p>
-            <p>
-              First, XCopyAreaScaled would provide for RGB scaling
-              between pixmaps (i.e., on-screen or off-screen areas of
-              memory that reside on the video card).  Unlike the X Video
-              Extension, which writes into an overlay plane,
-              XCopyAreaScaled would write into the non-overlay areas of
-              the screen.  Key points to consider are as follows:
-              <itemize>
-                <item>
-                  Because different planes are involved, the two scaling
-                  operations are usually implemented in hardware
-                  differently, so an XCopyAreaScaled extension could be
-                  added in a manner that would neither conflict with nor
-                  interact with the X Video extension in any way.
-                </item>
-                <item>
-                  The XCopyAreaScaled extension provides new
-                  functionality that the X Video Extension does not
-                  provide.  Based on anecdotal feedback, we believe that
-                  many people outside the DMX and VNC communities would
-                  be excited about this extension.
-                </item>
-                <item>
-                  The main drawback to this extension is that it is new
-                  and needs to be implemented at the driver level in
-                  XFree86 for each video card to be supported.  At the
-                  present time, it is more likely that the X Video
-                  Extension will be implemented for a particular piece
-                  hardware because the X Video extension has multimedia
-                  uses.  However, over time, we would expect the
-                  XCopyAreaScaled extension to be implemented along with
-                  the X Video extension, especially if it becomes
-                  popular.
-                </item>
-                <item>
-                  Another drawback is that not all modern cards provide
-                  support for a simple scaled blit operation.  However,
-                  these cards usually do provide a 3D pipeline which
-                  could be used to provide this functionality in a
-                  manner that is transparent to the client application
-                  that is using the XCopyAreaScaled extension.  However,
-                  this implementation pathway would make this extension
-                  somewhat more difficult to implement on certain cards.
-                </item>
-              </itemize>
-            </p>
-          </sect2>
-          <sect2>Scaling with OpenGL
-            <p>
-              Another general solution to the scaling problem is to use
-              the texture scaling found in all 3D hardware.  This
-              ability is already exposed through OpenGL and can be
-              exploited by clients without X server modification (i.e.,
-              other than the ability to support OpenGL).  An application
-              using OpenGL would transmit the non-scaled image to the X
-              server as a texture, and would then display a single
-              non-transformed rect using that texture.  This also works
-              around the single overlay problem with the X Video
-              Extension as well as the need to implement additional
-              scaled primitive extensions.
-            </p>
-            <p>
-              The downside is that most OpenGL implementations require
-              power of 2 texture sizes and this can be very wasteful of
-              memory if, for example, the application needs to scale a
-              1025x1025 image, which would require a 2048x2048 texture
-              area (even a 640x480 image would require a 1024x512
-              texture).  Another downside is that some OpenGL
-              implementations have a limited about of texture memory and
-              cannot handle textures that are very large.  For example,
-              they might limit the texture size to 1024x1024.
-            </p>
-          </sect2>
-        </sect1>
-        <sect1>Application-transparent Scaling for DMX
-          <sect2>Back-end Scaling Without Disconnect/Reconnect
-            <p>
-              VNC does scaling on the client side (in the
-              <tt>vncviewer</tt> application).  Implementing a similar
-              solution for DMX would require support in the back-end X
-              servers and, therefore, is not a general solution.
-            </p>
-            <p>
-              XFree86 already implements some support for "scaling" that
-              could be used with DMX: if, in the XF86Config file,
-              multiple Modes are listed in the Display Subsection of the
-              Screen Section, then pressing Ctrl-Alt-Plus and
-              Ctrl-Alt-Minus can be used to iterate through the listed
-              modes.  The display dimensions will change to the
-              dimensions in the Modes line, but the logical dimensions
-              of the X server (i.e., the dimensions that Xdmx knows
-              about) will not change.
-            </p>
-            <p>
-              Further, the dimensions of the XFree86 display are under
-              software control (via the XFree86-VidModeExtension), so
-              the Xdmx server could change the screen dimensions on a
-              per-display basis, thereby scaling the information on part
-              of that display.
-            </p>
-            <p>
-              However, this scaling appears to have limited use.  For
-              example, assume a 4 by 4 display wall consisting of 16
-              1280x1024 displays.  If all of the back-end servers were
-              simultaneously configured to display 640x480, the left
-              hand corner of each display would be magnified, but the
-              composite result would be unreadable.  Magnifying one
-              display at a time could be usable, but could have limited
-              utility, since the result would still be no larger than a
-              single display.
-            </p>
-          </sect2>
-          <sect2>Back-end Scaling With Disconnect/Reconnect
-            <p>
-              Disconnect and reconnect features are not currently
-              supported in DMX, but are scheduled to be implemented in
-              the future.  These features, combined with the
-              XFree86-VidModeExtension Extension, would allow an
-              application to do the following:
-              <itemize>
-                <item>
-                  Disconnect a specific back-end server (via the DMX
-                  Extension),
-                </item>
-                <item>
-                  reconfigure the XFree86 back-end server resolution,
-                  and 
-                </item>
-                <item>
-                  reconnect the back-end server to DMX -- at a new
-                  origin with the new screen resolution.
-                </item>
-              </itemize>
-            </p>
-            <p>
-              For example, consider a display wall consisting of 16
-              1280x1024 displays with a total resolution of 5120x4096.
-              All of the screens could be disconnected, repositioned,
-              and reconnected each at a resolution of 640x480.  The
-              total resolution of the display wall would be 2560x1920,
-              allowing a view of a selected area approximately
-              one-fourth of the size of the DMX display.  This change
-              would be completely application independent (except,
-              perhaps, for a DMX-aware window manager).  When work at
-              the increased resolution was completed, the back-end
-              servers could be disconnected, reconfigured, and
-              reconnected for the original 5120x4096 view.
-            </p>
-            <p>
-              Support for this type of scaling can be implemented in a
-              DMX-aware X11 client assuming the DMX server support
-              arbitrary disconnect and reconnect semantics.  Because
-              this application cannot be written before
-              disconnect/reconnect is implemented, this solution will
-              not be discussed further in this paper.
-            </p>
-          </sect2>
-          <sect2>Server-side Scaling
-            <p>
-              In earlier versions of DMX, a frame buffer was maintained
-              on the server side, and XPutImage was used to move the
-              information from the server to the client (similar to some
-              early VNC implementations).  The use of a server-side
-              frame buffer would allow the server to do scaling, but is
-              not a recommended solution because of overall performance
-              issues and server-side memory issues (i.e., the frame
-              buffer would be very large for large display walls).
-            </p>
-            <p>
-              Exploration of this path is not recommended.
-            </p>
-          </sect2>
-        </sect1>
-        <sect1>XCreateScaledWindow API
-          <p>
-            The implementation of X Video Extension in DMX, and the use
-            of XvPutImage by applications requiring scaling requires
-            significant changes in DMX Further, XvPutImage is,
-            essentially a scaled blit, and it is only useful for
-            applications which are already using (or can be modified to
-            use) XPutImage.  Therefore, a more general API will be
-            discussed as another possibility.
-          </p>
-          <p>
-            X applications typically create windows with the
-            XCreateWindow call.  A new extension could provide an
-            XCreateScaledWindow call that could be used in place of the
-            XCreateWindow call and be otherwise transparent to the
-            application.  This would allow applications, even those that
-            do not depend on XPutImage, to take advantage of window
-            scaling.  In this section we describe how the call would
-            work, what transparency it provides, and how to solve the
-            potential problems that transparency creates.
-          </p>
-          <sect2>XCreateWindow
-            <p>
-              The XCreateWindow call takes width and height as
-              parameters.  An XCreateScaledWindow call could take all
-              the same parameters, with the addition of a scaling factor.
-            </p>
-          </sect2>
-          <sect2>XSetWindowAttributes
-            <p>
-              An X11 window has several attributes that would have to be
-              scaled:
-              <itemize>
-                <item>Background and border pixmaps</item>
-                <item>Border width</item>
-                <item>Cursor</item>
-              </itemize>
-            </p>
-          </sect2>
-          <sect2>XGetWindowAttributes, XGetGeometry
-            <p>
-              For transparency, calls that query the window attributes
-              should return unscaled information.  This suggests that
-              all unscaled pixmaps and window attributes should be
-              cached.
-            </p>
-            <p>
-              Unfortunately, a window manager requires the scaled
-              geometry to properly decorate the window.  The X server
-              can probably determine which client is acting as the
-              window manager (e.g., because that client will select
-              events that are used exclusively by the window manager).
-              However, other Scaled Window Extension aware clients may
-              also need to determine the scaled geometry.  Therefore, at
-              least two additional extension calls should be
-              implemented: XGetScaledWindowAttributes and
-              XGetScaledGeometry.
-            </p>
-          </sect2>
-          <sect2>Popup and Child window positions
-            <p>
-              Some applications may position popup and child windows
-              based on an unscaled notion of the main window geometry.
-              In this case, additional modifications to the client would
-              be required.
-            </p>
-          </sect2>
-          <sect2>Events
-            <p>
-              Most events (e.g., for mouse motion) return information
-              about the coordinates at which the even occurred.  These
-              coordinates would have to be modified so that unscaled
-              values were presented to the client.
-            </p>
-          </sect2>
-          <sect2>Implementation
-            <p>
-              There are many implementation issues, some of which are
-              similar to the issues involved in implementing the X Video
-              Extension for DMX.  The window contents must be scaled,
-              either by performing all operations to a frame buffer and
-              then writing the image to the display (perhaps using
-              hardware scaling support), or by modifying all of the
-              various drawing operations to perform scaling.  Because of
-              the complexity involved, the frame buffer option is
-              recommended.
-            </p>
-          </sect2>
-        </sect1>
-      </sect>
-      
-      <sect>Conclusion and Recommendations
-        <p>
-          We recommend a three phase implementation strategy, based on
-          how an application could be written to take advantage of
-          scaling:
-          <enum>
-            <item>
-              <p>
-                The XCopyAreaScaled extension should be implemented, since
-                this is the ideal solution for applications like VNC, and
-                since making use of this extension will require minimal
-                changes to applications that already use XPutImage or
-                XCopyArea.
-              <p>
-                The initial implementation work would include the design
-                of the X protocol extension, writing this up in the
-                usual format for extension documentation, implementation
-                of the protocol transport pieces in XFree86,
-                implementation of a software fall-back in XFree86 and
-                DMX, one example hardware implementation for XFree86,
-                and implementation of support for this extension in DMX.
-              <p>
-                We suggest implementing the extension first on the ATI
-                Radeon cards.  However, since these cards do not provide
-                a 2D scaled blit primitive, the implementation would
-                have to make use of the 3D texture engine to emulate a
-                scaled blit.  This is recommended, since other modern
-                graphics cards also do not provide a simple 2D scaled
-                blit operation and an example of the more difficult
-                implementation pathway would be helpful to others.
-            </item>
-            <item>
-              <p>
-                Until XCopyAreaScaled is widely supported, applications
-                that require scaling will have to fall back to another
-                scaling method.  We suggest OpenGL as the first fall-back
-                method because it is widely available and supported by
-                DMX.
-              <p>
-                A project centered around OpenGL-based scaling would
-                implement this scaling in VNC as an example.  This work
-                would include re-writing the <tt>vncviewer</tt>
-                rendering engine to cache a master copy of the desktop
-                image for all operations.
-            </item>
-            <item>
-              <p>
-                Since OpenGL is not implemented everywhere, and may not
-                provide hardware-assisted performance in every
-                implementation, an application that requires scaling
-                should also fall back to using the X Video Extension.
-              <p>
-                This project would add support for the X Video Extension
-                to DMX and would add support to VNC to take advantage of
-                this extension without introducing artifacts.  This
-                would require modifying the <tt>vncviewer</tt> rendering
-                engine to cache a master copy of the desktop image for
-                all operations.  This project should also add support
-                for the RGB format to at least one XFree86 driver (e.g.,
-                ATI Radeon).
-              <p>
-                The X Video Extension is one of the few popular
-                extensions that DMX does not support.  We recommend
-                implementing the X Video Extension even if scaling is
-                the specific goal of that work.
-            </item>
-          </enum>
-        </p>
-        <p>
-          We do <bf>not</bf> recommend implementation of the
-          XCreateScaledWindow extension because of the complexity
-          involved.  We do <bf>not</bf> recommend implementation of the
-          XPutImageScaled extension because it requires the same amount
-          of work as the XCopyAreaScaled extension, but provides less
-          functionality.  Further, server-side scaling with a large
-          frame buffer is <bf>not</bf> recommended because of the
-          performance implications.
-        </p>
-        <p>
-          The back-end scaling, especially with disconnect/reconnect
-          support should be explored in the future after
-          disconnect/reconnect is implemented, but not at the present
-          time.
-        </p>
-      </sect>
-      
-  </article>
-  <!-- Local Variables: -->
-  <!-- fill-column: 72  -->
-  <!-- End:             -->
diff --git a/hw/dmx/doc/scaled.xml b/hw/dmx/doc/scaled.xml
new file mode 100644
index 0000000..48c83e0
--- /dev/null
+++ b/hw/dmx/doc/scaled.xml
@@ -0,0 +1,725 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+]>
+  <article>
+
+  <articleinfo>
+    <!-- Title information -->
+    <title>Scaled Window Support in DMX</title>
+    <authorgroup>
+      <author><firstname>Kevin E.</firstname><surname>Martin</surname></author>
+      <author><firstname>Rickard E.</firstname><surname>Faith</surname></author>
+    </authorgroup>
+    <pubdate>15 October 2003 (created 19 September 2003)</pubdate>
+    <abstract>
+      <para>
+      This document investigates the possibility of adding scaled window
+      support to the DMX X server, thereby allowing a window or some
+      selected part of the logical DMX area to be displayed using a
+      scaling factor.  For example, this might allow the contents of a
+      window to be magnified for easier viewing.  In particular, scaling
+      for the VNC client is explored.  <emphasis remap="it">Copyright 2003
+        by Red Hat, Inc., Raleigh, North Carolina</emphasis>
+      </para>
+    </abstract>
+  </articleinfo>
+
+      <!-- Begin the document -->
+      <sect1><title>Introduction</title>
+        <sect2><title>DMX</title>
+          <para>
+            The DMX X server (Xdmx) is a proxy server that is designed
+            to allow X servers on multiple machines to be combined into
+            a single multi-headed X server.  Combined with Xinerama,
+            these heads can appear as a single very high-resolution
+            screen.  Typical applications include the creation of a
+            video wall with 16 1280x1024 displays arranged in a
+            rectangle, for a total resolution of of 5120x4096.
+          </para>
+        </sect2>
+        <sect2><title>Problem Statement</title>
+          <para>
+            Applications displayed on a physically large video wall that
+            provides high pixel-resolution may be difficult to see,
+            especially if the application is designed for use on a
+            typical desktop computer with a relatively small display
+            located close to the human operator.  The goal of this paper
+            is to describe and discuss solutions to this problem.
+          </para>
+          <para>
+            The original driving problem for this work is to provide
+            scaling for the <command>vncviewer</command> application when
+            displayed using DMX (VNC scaling is currently available only
+            with the Windows client, and there is no plan to extend that
+            capability to other clients).  While this specific problem
+            will be addressed in this paper, the general solution space
+            will also be explored, since this may lead to a good
+            solution not only for <command>vncviewer</command> but also for
+            other applications.
+          </para>
+        </sect2>
+        <sect2><title>Task</title>
+          <para>
+            For reference, here is the original description of the task
+            this paper addresses:
+            <itemizedlist>
+              <listitem><para>Scaled window support (for VNC)
+                <itemizedlist>
+                  <listitem><para>
+                    Investigate possibility of implementing a "scaled
+                    window" extension:
+                    <itemizedlist>
+                      <listitem><para>
+                        Add XCreateScaledWindow call that could be used
+                        in place of XCreateWindow
+                      </para></listitem>
+                      <listitem><para>
+                        All primitives drawn to scaled window would be
+                        scaled by appropriate (integral?) scaling factor
+                      </para></listitem>
+                    </itemizedlist>
+                  </para></listitem>
+                  <listitem><para>
+                    Alternate approach: special case VNC support
+                  </para></listitem>
+                </itemizedlist>
+              </para></listitem>
+            </itemizedlist>
+          </para>
+        </sect2>
+      </sect1>
+
+      <sect1><title>Previous Work</title>
+        <para>
+          This section reviews relevant previous work.
+        </para>
+        <sect2><title>VNC</title>
+          <sect3><title>Scaling under VNC</title>
+            <para>
+              When using the <command>vncviewer</command> program for Windows, it
+              is possible to specify a scaling factor (as numerator and
+              denominator).  When scaling is in effect, the viewer
+              software uses StretchBlt (instead of BitBlt) to display
+              the pixels for the user.  When this call is made, the
+              viewer already has received all of the pixel information
+              (at full unscaled resolution).
+            </para>
+            <para>
+              The scaling in VNC is primitive.  It does not conserve
+              bandwidth, it does not treat textual information
+              differently (i.e., by using a suitably scaled font), and
+              it does not provide any anti-aliasing other than that
+              provided by the underlying (Windows-only) system library.
+            </para>
+          </sect3>
+        </sect2>
+        <sect2><title>The X Video Extension</title>
+          <para>
+            The X Video Extension is a widely-available extension to the
+            X11 protocol that provides support for streaming video.
+            Integral to this support is the ability to arbitrarily scale
+            the output.  In version 2.2 of the X Video specification,
+            support for scaled still images was provided, using both
+            shared memory and traditional transport.  The API for this
+            support uses calls that are quite similar to XCreateWindow,
+            XPutImage, and XShmPutImage.  Currently, most of the drivers
+            implemented in XFree86 only support data in various YUV
+            formats.  However, several modern video adaptors support RGB
+            as well.
+          </para>
+          <para>
+            Note, though, that the target output for this scaling is an
+            overlay plane -- so X Video provides functionality that is
+            fundamentally different from that provided by the Windows
+            StrechBlt call.
+          </para>
+        </sect2>
+      </sect1>
+
+      <sect1><title>Possible Solutions</title>
+        <para>
+          This section briefly discusses possible solutions, including
+          major advantages and disadvantages from both the
+          implementation and the end-user programmer standpoint.
+        </para>
+        <sect2><title>VNC-like Scaling</title>
+          <sect3><title>Software Scaling</title>
+            <para>
+              The <command>vncviewer</command> application could be modified to
+              provide software scaling.  This is not a general solution,
+              but it does solve one of the goals of this work.
+            </para>
+            <para>
+              A prototype of this solution was implemented and a patch
+              against <filename>vnc-3.3.7-unixsrc</filename> is available in the
+              <filename>dmx/external</filename> directory.  Because of limited time
+              available for this work, all of the edge cases were not
+              considered and the solution works well mainly for integer
+              scaling.
+            </para>
+            <para>
+              Currently, <command>vncviewer</command> writes to the X display
+              with XPutImage, XCopyArea, and XFillRectangle.  All
+              instances of these calls have to be aware of scaling
+              and must round correctly.  In the prototype solution,
+              rounding is incorrect and can cause artifacts.
+            </para>
+            <para>
+              A better solution would be to cache all updates to the
+              desktop image in <command>vncviewer</command> and only send the
+              damaged area to the X display with XPutImage.  This would
+              allow the damaged area to be computed so that rounding
+              errors do not create artifacts.  This method is probably
+              similar to what is used in the Window client.  (The whole
+              VNC suite is being re-written in C++ and the forthcoming
+              version 4 has not been evaluated.)
+            </para>
+          </sect3>
+          <sect3><title>Scaling with the X Video Extension</title>
+            <para>
+              The scaling in the Windows <command>vncviewer</command> application
+              makes use of a scaled blit that is supplied by the
+              underlying system library.  Several video cards currently
+              provide support for a scaled blit, and some X servers
+              (including XFree86) expose this capability to applications
+              via the XvPutImage interface of the X Video Extension.
+              The capability exposed by XvPutImage results in the scaled
+              image being drawn to an overlay plane.  Most video cards
+              also provide support for a scaled blit into the normal
+              output planes, but this is not exposed via XvPutImage.
+            </para>
+            <para>
+              The <command>vncviewer</command> program could be modified to use
+              the X Video Extension to provide scaling under X11 that is
+              similar to the scaling currently provided under Windows.
+              Unfortunately, Xdmx does not currently export the X Video
+              Extension, so this would not provide an immediate solution
+              usable with DMX.
+            </para>
+            <para>
+              A very early-stage proof-of-concept prototype was
+              implemented and a preliminary patch against
+              <filename>vnc-3.3.7-unixsrc</filename> is available in the
+              <filename>dmx/external</filename> directory.  This prototype was
+              implemented to better understand the problems that must be
+              solved to make this solution viable:
+              <itemizedlist>
+                <listitem><para>
+                  As noted under the software scaling section above,
+                  <command>vncviewer</command> writes to the X display with
+                  several different calls.  These calls write to the
+                  normal output planes and are compatible with
+                  XvPutImage, which writes to an overlay plane.  To
+                  eliminate artifacts caused by this problem,
+                  <command>vncviewer</command> should be modified so that a cached
+                  copy of the desktop is available, either as a
+                  client-side image or a server-side off-screen pixmap,
+                  so that XvPutImage would be the only method for
+                  writing to the X display.
+                </para></listitem>
+                <listitem>
+                  <para>
+                    Although several modern graphics adaptors support
+                    hardware scaling using an RGB format (e.g., ATI
+                    Radeon, nVidia, etc.), XFree86 drivers typically
+                    only implement YUV formats.  YUV generally compress
+                    the pixel information in some way.  For example, two
+                    commonly implemented formats, YUY2 and UYVY provide
+                    intensity information for every RGB pixel, but only
+                    provide chroma and luminance information for pairs
+                    of horizontal pixels.  Since VNC uses
+                    pixel-resolution for communicating updates on the
+                    wire, additional artifacts are introduced (because
+                    there may not be enough information from the wire to
+                    update a pair of pixels).
+                  </para>
+                  <para>
+                    Further, the well-known problem with YUV encoding
+                    is even more evident when the image is a desktop
+                    instead of a movie.  For example, consider a
+                    1-pixel-wide vertical window border.  If the border
+                    changes in color but not intensity (e.g., because a
+                    window manager uses color to indicate focus), there
+                    may or may not be a change in the YUY2 image,
+                    depending on the algorithm used for RGB to YUV
+                    conversion and on how the border pixel is ordered in
+                    the pair of pixels used by the algorithm.
+                  </para>
+                  <para>
+                    Many of these artifacts could be eliminated if
+                    <command>vncviewer</command> cached a complete RGB image of
+                    the desktop, and only did the conversion to YUV for
+                    properly aligned areas of damage.  The remaining artifacts
+                    could be eliminated if an RGB format was used with X
+                    Video (which may require the extension of existing
+                    XFree86 drivers to support RGB).
+                  </para>
+	        </listitem>
+                <listitem><para>
+                  Most modern video cards support exactly one overlay
+                  plane that is suitable for use with X Video.
+                  Therefore, only one application can use X Video at any
+                  given time.  This is a severe limitation in a desktop
+                  environment.
+                </para></listitem>
+              </itemizedlist>
+            </para>
+            <sect4><title>Implementing the X Video Extension for DMX</title>
+              <para>
+                The user-level API for X Video is fairly simple, but the
+                underlying support required for the full specification
+                is large.  However, since the API provides a method to
+                query supported capabilities, a usable subset of X
+                Video can be implemented that would support XvPutImage
+                and little else.  This would require support for the
+                following:
+                <itemizedlist>
+                  <listitem><para>
+                    X Video Extension API calls, including the
+                    following:
+                    <itemizedlist>
+                      <listitem><para>XvQueryExtension</para></listitem>
+                      <listitem><para>XvQueryAdaptors</para></listitem>
+                      <listitem><para>XvQueryPortAttributes</para></listitem>
+                      <listitem><para>XvFreeAdaptorInfo</para></listitem>
+                      <listitem><para>XvListImageFormats</para></listitem>
+                      <listitem><para>XvGrabPort</para></listitem>
+                      <listitem><para>XvCreateImage</para></listitem>
+                      <listitem><para>XvPutImage</para></listitem>
+                      <listitem><para>XvShmCreateImage</para></listitem>
+                      <listitem><para>XvShmPutImage</para></listitem>
+                    </itemizedlist>
+                  </para></listitem>
+                  <listitem><para>
+                    Support for querying back-end X Video Extension
+                    capabilities.
+                  </para></listitem>
+                  <listitem><para>
+                    Support for sending the image to the back-ends.
+                    Because X Video requires sending full images, there
+                    may be a trade-off between bandwidth limitations and
+                    additional complexity to divide the image up such
+                    that is scales properly.
+                  </para></listitem>
+                  <listitem><para>
+                    Possible support for a software fall-back.  For
+                    example, if all of the back-ends do not support the X
+                    Video Extension, software scaling can be implemented
+                    such that the image is sent to the back-end with
+                    XPutImage.  This pathway would have poor
+                    performance.
+                  </para></listitem>
+                </itemizedlist>
+              </para>
+            </sect4>
+            <sect4><title>Supporting RGB formats for the X Video Extension</title>
+              <para>
+                Assuming an XFree86 driver already supports the X Video
+                Extension, and assuming the target hardware supports an
+                RGB format, then adding support for that format is
+                relatively simple and straightforward.
+              </para>
+            </sect4>
+          </sect3>
+          <sect3><title>Scaling with an XPutImageScaled Extension</title>
+            <para>
+              Instead of (or in addition to) implementing the X Video
+              Extension in DMX, one obvious solution would be to
+              implement a new extension that provides access to
+              hardware-assisted scaled blits, similar to the StretchBlt
+              call available under Windows.  This call would scale RGB
+              images and would not use the overlay plane (unlike the X
+              Video Extension).
+            </para>
+            <para>
+              This approach has many of the same advantages and
+              disadvantages as the XCopyAreaScaled Extension, discussed
+              in the next section.  Discussion of XPutImageScaled is
+              deferred in favor of XCopyAreaScaled for the following
+              reasons:
+              <itemizedlist>
+                <listitem><para>
+                  XPutImageScaled can be emulated with XCopyAreaScaled
+                  by first using XPutImage to copy the image to an
+                  off-screen pixmap, and then calling XCopyAreaScaled
+                  between that off-screen pixmap and the target
+                  drawable.
+                </para></listitem>
+                <listitem><para>
+                  Since XCopyAreaScaled would copy between two areas of
+                  on-screen or off-screen memory, it has additional uses
+                  and can be viewed as efficiently providing a superset
+                  of XPutImageScaled functionality.
+                </para></listitem>
+              </itemizedlist>
+            </para>
+          </sect3>
+          <sect3><title>Scaling with an XCopyAreaScaled Extension</title>
+            <para>
+              As noted in the previous section, because XCopyAreaScaled
+              provides a superset of the functionality provided by
+              XPutImageScaled, we will consider this extension instead.
+            </para>
+            <para>
+              First, XCopyAreaScaled would provide for RGB scaling
+              between pixmaps (i.e., on-screen or off-screen areas of
+              memory that reside on the video card).  Unlike the X Video
+              Extension, which writes into an overlay plane,
+              XCopyAreaScaled would write into the non-overlay areas of
+              the screen.  Key points to consider are as follows:
+              <itemizedlist>
+                <listitem><para>
+                  Because different planes are involved, the two scaling
+                  operations are usually implemented in hardware
+                  differently, so an XCopyAreaScaled extension could be
+                  added in a manner that would neither conflict with nor
+                  interact with the X Video extension in any way.
+                </para></listitem>
+                <listitem><para>
+                  The XCopyAreaScaled extension provides new
+                  functionality that the X Video Extension does not
+                  provide.  Based on anecdotal feedback, we believe that
+                  many people outside the DMX and VNC communities would
+                  be excited about this extension.
+                </para></listitem>
+                <listitem><para>
+                  The main drawback to this extension is that it is new
+                  and needs to be implemented at the driver level in
+                  XFree86 for each video card to be supported.  At the
+                  present time, it is more likely that the X Video
+                  Extension will be implemented for a particular piece
+                  hardware because the X Video extension has multimedia
+                  uses.  However, over time, we would expect the
+                  XCopyAreaScaled extension to be implemented along with
+                  the X Video extension, especially if it becomes
+                  popular.
+                </para></listitem>
+                <listitem><para>
+                  Another drawback is that not all modern cards provide
+                  support for a simple scaled blit operation.  However,
+                  these cards usually do provide a 3D pipeline which
+                  could be used to provide this functionality in a
+                  manner that is transparent to the client application
+                  that is using the XCopyAreaScaled extension.  However,
+                  this implementation pathway would make this extension
+                  somewhat more difficult to implement on certain cards.
+                </para></listitem>
+              </itemizedlist>
+            </para>
+          </sect3>
+          <sect3><title>Scaling with OpenGL</title>
+            <para>
+              Another general solution to the scaling problem is to use
+              the texture scaling found in all 3D hardware.  This
+              ability is already exposed through OpenGL and can be
+              exploited by clients without X server modification (i.e.,
+              other than the ability to support OpenGL).  An application
+              using OpenGL would transmit the non-scaled image to the X
+              server as a texture, and would then display a single
+              non-transformed rect using that texture.  This also works
+              around the single overlay problem with the X Video
+              Extension as well as the need to implement additional
+              scaled primitive extensions.
+            </para>
+            <para>
+              The downside is that most OpenGL implementations require
+              power of 2 texture sizes and this can be very wasteful of
+              memory if, for example, the application needs to scale a
+              1025x1025 image, which would require a 2048x2048 texture
+              area (even a 640x480 image would require a 1024x512
+              texture).  Another downside is that some OpenGL
+              implementations have a limited about of texture memory and
+              cannot handle textures that are very large.  For example,
+              they might limit the texture size to 1024x1024.
+            </para>
+          </sect3>
+        </sect2>
+        <sect2><title>Application-transparent Scaling for DMX
+          </title><sect3><title>Back-end Scaling Without Disconnect/Reconnect</title>
+            <para>
+              VNC does scaling on the client side (in the
+              <command>vncviewer</command> application).  Implementing a similar
+              solution for DMX would require support in the back-end X
+              servers and, therefore, is not a general solution.
+            </para>
+            <para>
+              XFree86 already implements some support for "scaling" that
+              could be used with DMX: if, in the XF86Config file,
+              multiple Modes are listed in the Display Subsection of the
+              Screen Section, then pressing Ctrl-Alt-Plus and
+              Ctrl-Alt-Minus can be used to iterate through the listed
+              modes.  The display dimensions will change to the
+              dimensions in the Modes line, but the logical dimensions
+              of the X server (i.e., the dimensions that Xdmx knows
+              about) will not change.
+            </para>
+            <para>
+              Further, the dimensions of the XFree86 display are under
+              software control (via the XFree86-VidModeExtension), so
+              the Xdmx server could change the screen dimensions on a
+              per-display basis, thereby scaling the information on part
+              of that display.
+            </para>
+            <para>
+              However, this scaling appears to have limited use.  For
+              example, assume a 4 by 4 display wall consisting of 16
+              1280x1024 displays.  If all of the back-end servers were
+              simultaneously configured to display 640x480, the left
+              hand corner of each display would be magnified, but the
+              composite result would be unreadable.  Magnifying one
+              display at a time could be usable, but could have limited
+              utility, since the result would still be no larger than a
+              single display.
+            </para>
+          </sect3>
+          <sect3><title>Back-end Scaling With Disconnect/Reconnect</title>
+            <para>
+              Disconnect and reconnect features are not currently
+              supported in DMX, but are scheduled to be implemented in
+              the future.  These features, combined with the
+              XFree86-VidModeExtension Extension, would allow an
+              application to do the following:
+              <itemizedlist>
+                <listitem><para>
+                  Disconnect a specific back-end server (via the DMX
+                  Extension),
+                </para></listitem>
+                <listitem><para>
+                  reconfigure the XFree86 back-end server resolution,
+                  and
+                </para></listitem>
+                <listitem><para>
+                  reconnect the back-end server to DMX -- at a new
+                  origin with the new screen resolution.
+                </para></listitem>
+              </itemizedlist>
+            </para>
+            <para>
+              For example, consider a display wall consisting of 16
+              1280x1024 displays with a total resolution of 5120x4096.
+              All of the screens could be disconnected, repositioned,
+              and reconnected each at a resolution of 640x480.  The
+              total resolution of the display wall would be 2560x1920,
+              allowing a view of a selected area approximately
+              one-fourth of the size of the DMX display.  This change
+              would be completely application independent (except,
+              perhaps, for a DMX-aware window manager).  When work at
+              the increased resolution was completed, the back-end
+              servers could be disconnected, reconfigured, and
+              reconnected for the original 5120x4096 view.
+            </para>
+            <para>
+              Support for this type of scaling can be implemented in a
+              DMX-aware X11 client assuming the DMX server support
+              arbitrary disconnect and reconnect semantics.  Because
+              this application cannot be written before
+              disconnect/reconnect is implemented, this solution will
+              not be discussed further in this paper.
+            </para>
+          </sect3>
+          <sect3><title>Server-side Scaling</title>
+            <para>
+              In earlier versions of DMX, a frame buffer was maintained
+              on the server side, and XPutImage was used to move the
+              information from the server to the client (similar to some
+              early VNC implementations).  The use of a server-side
+              frame buffer would allow the server to do scaling, but is
+              not a recommended solution because of overall performance
+              issues and server-side memory issues (i.e., the frame
+              buffer would be very large for large display walls).
+            </para>
+            <para>
+              Exploration of this path is not recommended.
+            </para>
+          </sect3>
+        </sect2>
+        <sect2><title>XCreateScaledWindow API</title>
+          <para>
+            The implementation of X Video Extension in DMX, and the use
+            of XvPutImage by applications requiring scaling requires
+            significant changes in DMX Further, XvPutImage is,
+            essentially a scaled blit, and it is only useful for
+            applications which are already using (or can be modified to
+            use) XPutImage.  Therefore, a more general API will be
+            discussed as another possibility.
+          </para>
+          <para>
+            X applications typically create windows with the
+            XCreateWindow call.  A new extension could provide an
+            XCreateScaledWindow call that could be used in place of the
+            XCreateWindow call and be otherwise transparent to the
+            application.  This would allow applications, even those that
+            do not depend on XPutImage, to take advantage of window
+            scaling.  In this section we describe how the call would
+            work, what transparency it provides, and how to solve the
+            potential problems that transparency creates.
+          </para>
+          <sect3><title>XCreateWindow</title>
+            <para>
+              The XCreateWindow call takes width and height as
+              parameters.  An XCreateScaledWindow call could take all
+              the same parameters, with the addition of a scaling factor.
+            </para>
+          </sect3>
+          <sect3><title>XSetWindowAttributes</title>
+            <para>
+              An X11 window has several attributes that would have to be
+              scaled:
+              <itemizedlist>
+                <listitem><para>Background and border pixmaps</para></listitem>
+                <listitem><para>Border width</para></listitem>
+                <listitem><para>Cursor</para></listitem>
+              </itemizedlist>
+            </para>
+          </sect3>
+          <sect3><title>XGetWindowAttributes, XGetGeometry</title>
+            <para>
+              For transparency, calls that query the window attributes
+              should return unscaled information.  This suggests that
+              all unscaled pixmaps and window attributes should be
+              cached.
+            </para>
+            <para>
+              Unfortunately, a window manager requires the scaled
+              geometry to properly decorate the window.  The X server
+              can probably determine which client is acting as the
+              window manager (e.g., because that client will select
+              events that are used exclusively by the window manager).
+              However, other Scaled Window Extension aware clients may
+              also need to determine the scaled geometry.  Therefore, at
+              least two additional extension calls should be
+              implemented: XGetScaledWindowAttributes and
+              XGetScaledGeometry.
+            </para>
+          </sect3>
+          <sect3><title>Popup and Child window positions</title>
+            <para>
+              Some applications may position popup and child windows
+              based on an unscaled notion of the main window geometry.
+              In this case, additional modifications to the client would
+              be required.
+            </para>
+          </sect3>
+          <sect3><title>Events</title>
+            <para>
+              Most events (e.g., for mouse motion) return information
+              about the coordinates at which the even occurred.  These
+              coordinates would have to be modified so that unscaled
+              values were presented to the client.
+            </para>
+          </sect3>
+          <sect3><title>Implementation</title>
+            <para>
+              There are many implementation issues, some of which are
+              similar to the issues involved in implementing the X Video
+              Extension for DMX.  The window contents must be scaled,
+              either by performing all operations to a frame buffer and
+              then writing the image to the display (perhaps using
+              hardware scaling support), or by modifying all of the
+              various drawing operations to perform scaling.  Because of
+              the complexity involved, the frame buffer option is
+              recommended.
+            </para>
+          </sect3>
+        </sect2>
+      </sect1>
+
+      <sect1><title>Conclusion and Recommendations
+        </title><para>
+          We recommend a three phase implementation strategy, based on
+          how an application could be written to take advantage of
+          scaling:
+          <orderedlist>
+            <listitem>
+              <para>
+                The XCopyAreaScaled extension should be implemented, since
+                this is the ideal solution for applications like VNC, and
+                since making use of this extension will require minimal
+                changes to applications that already use XPutImage or
+                XCopyArea.
+              </para>
+              <para>
+                The initial implementation work would include the design
+                of the X protocol extension, writing this up in the
+                usual format for extension documentation, implementation
+                of the protocol transport pieces in XFree86,
+                implementation of a software fall-back in XFree86 and
+                DMX, one example hardware implementation for XFree86,
+                and implementation of support for this extension in DMX.
+              </para>
+              <para>
+                We suggest implementing the extension first on the ATI
+                Radeon cards.  However, since these cards do not provide
+                a 2D scaled blit primitive, the implementation would
+                have to make use of the 3D texture engine to emulate a
+                scaled blit.  This is recommended, since other modern
+                graphics cards also do not provide a simple 2D scaled
+                blit operation and an example of the more difficult
+                implementation pathway would be helpful to others.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                Until XCopyAreaScaled is widely supported, applications
+                that require scaling will have to fall back to another
+                scaling method.  We suggest OpenGL as the first fall-back
+                method because it is widely available and supported by
+                DMX.
+              </para>
+              <para>
+                A project centered around OpenGL-based scaling would
+                implement this scaling in VNC as an example.  This work
+                would include re-writing the <command>vncviewer</command>
+                rendering engine to cache a master copy of the desktop
+                image for all operations.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                Since OpenGL is not implemented everywhere, and may not
+                provide hardware-assisted performance in every
+                implementation, an application that requires scaling
+                should also fall back to using the X Video Extension.
+              </para>
+              <para>
+                This project would add support for the X Video Extension
+                to DMX and would add support to VNC to take advantage of
+                this extension without introducing artifacts.  This
+                would require modifying the <command>vncviewer</command> rendering
+                engine to cache a master copy of the desktop image for
+                all operations.  This project should also add support
+                for the RGB format to at least one XFree86 driver (e.g.,
+                ATI Radeon).
+              </para>
+              <para>
+                The X Video Extension is one of the few popular
+                extensions that DMX does not support.  We recommend
+                implementing the X Video Extension even if scaling is
+                the specific goal of that work.
+              </para>
+            </listitem>
+          </orderedlist>
+        </para>
+        <para>
+          We do <emphasis>not</emphasis> recommend implementation of the
+          XCreateScaledWindow extension because of the complexity
+          involved.  We do <emphasis>not</emphasis> recommend implementation of the
+          XPutImageScaled extension because it requires the same amount
+          of work as the XCopyAreaScaled extension, but provides less
+          functionality.  Further, server-side scaling with a large
+          frame buffer is <emphasis>not</emphasis> recommended because of the
+          performance implications.
+        </para>
+        <para>
+          The back-end scaling, especially with disconnect/reconnect
+          support should be explored in the future after
+          disconnect/reconnect is implemented, but not at the present
+          time.
+        </para>
+      </sect1>
+
+  </article>
+  <!-- Local Variables: -->
+  <!-- fill-column: 72  -->
+  <!-- End:             -->
diff --git a/hw/xfree86/doc/sgml/DESIGN.sgml b/hw/xfree86/doc/sgml/DESIGN.sgml
deleted file mode 100644
index 8999e0c..0000000
--- a/hw/xfree86/doc/sgml/DESIGN.sgml
+++ /dev/null
@@ -1,7420 +0,0 @@
-<!DOCTYPE linuxdoc PUBLIC "-//Xorg//DTD linuxdoc//EN" [
- <!ENTITY % defs SYSTEM "X11/defs.ent"> %defs;
- <!-- config file keyword markup -->
- <!ENTITY s.key STARTTAG "bf">
- <!ENTITY e.key ENDTAG "bf">
- <!-- specific config file keywords -->
- <!ENTITY k.device "&s.key;Device&e.key;">
- <!ENTITY k.monitor "&s.key;Monitor&e.key;">
- <!ENTITY k.display "&s.key;Display&e.key;">
- <!ENTITY k.inputdevice "&s.key;InputDevice&e.key;">
- <!ENTITY k.screen "&s.key;Screen&e.key;">
- <!ENTITY k.serverlayout "&s.key;ServerLayout&e.key;">
- <!ENTITY k.driver "&s.key;Driver&e.key;">
- <!ENTITY k.module "&s.key;Module&e.key;">
- <!ENTITY k.identifier "&s.key;Identifier&e.key;">
- <!ENTITY k.serverflags "&s.key;ServerFlags&e.key;">
- <!-- command line markup -->
- <!ENTITY s.cmd STARTTAG "tt">
- <!ENTITY e.cmd ENDTAG "tt">
- <!-- inline code markup -->
- <!ENTITY s.code STARTTAG "tt">
- <!ENTITY e.code ENDTAG "tt">
- <!-- function indent -->
- <!ENTITY f.indent "&nl&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp">
-] >
-
-<article>
-
-<title>XFree86 server 4.x Design (DRAFT)
-<author>The XFree86 Project, Inc
-<and>Updates for X11R&relvers; by Jim Gettys
-<date>19 December 2003
-
-
-
-
-
-
-
-<ident>
-$XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/DESIGN.sgml,v 1.53 2003/08/23 14:10:14 dawes Exp $
-</ident>
-
-
-<p>
-<bf>NOTE</bf>: This is a DRAFT document, and the interfaces described here
-are subject to change without notice.
-
-
-<sect>Preface
-<p>
-
-The broad design principles are:
-<itemize>
-  <item>keep it reasonable
-	<itemize>
-	  <item>We cannot rewrite the complete server
-	  <item>We don't want to re-invent the wheel
-	</itemize>
-  <item>keep it modular
-	<itemize>
-	  <item>As many things as possible should go into modules
-	  <item>The basic loader binary should be minimal
-	  <item>A clean design with well defined layering is important
-	  <item>DDX specific global variables are a nono
-	  <item>The structure should be flexible enough to allow
-		future extensions
-	  <item> The structure should minimize duplication of common code
-	</itemize>
-  <item>keep important features in mind
-	<itemize>
-	  <item>multiple screens, including multiple instances of drivers
-	  <item>mixing different color depths and visuals on different
-		and ideally even on the same screen
-	  <item>better control of the PCI device used
-	  <item>better config file parser
-	  <item>get rid of all VGA compatibility assumptions
-	</itemize>
-</itemize>
-
-Unless we find major deficiencies in the DIX layer, we should avoid
-making changes there.
-
-<sect>The xorg.conf File
-<p>
-
-The xorg.conf file format is similar to the old format, with the following
-changes:
-
-<sect1>&k.device; section
-<p>
-
-    The &k.device; sections are similar to what they used to be, and
-    describe hardware-specific information for a single video card.
-    &k.device;
-    Some new keywords are added:
-
-
-    <descrip>
-      <tag>Driver "drivername"</tag>
-        Specifies the name of the driver to be used for the card.  This
-        is mandatory.
-      <tag>BusID "busslot"</tag>
-        Specifies uniquely the location of the card on the bus.  The
-        purpose is to identify particular cards in a multi-headed
-        configuration.  The format of the argument is intentionally
-        vague, and may be architecture dependent.  For a PCI bus, it
-        is something like "bus:slot:func".
-    </descrip>
-
-    A &k.device; section is considered ``active'' if there is a reference
-    to it in an active &k.screen; section.
-
-<sect1>&k.screen; section
-<p>
-
-    The &k.screen; sections are similar to what they used to be.  They
-    no longer have a &k.driver; keyword, but an &k.identifier; keyword
-    is added.  (The &k.driver; keyword may be accepted in place of the
-    &k.identifier; keyword for compatibility purposes.)  The identifier
-    can be used to identify which screen is to be active when multiple
-    &k.screen sections are present.  It is possible to specify the active
-    screen from the command line.  A default is chosen in the absence
-    of one being specified.  A &k.screen; section is considered ``active''
-    if there is a reference to it either from the command line, or from
-    an active &k.serverlayout; section.
-
-<sect1>&k.inputdevice; section
-<p>
-
-    The &k.inputdevice; section is a new section that describes
-    configuration information for input devices.  It replaces the old
-    &s.key;Keyboard&e.key;, &s.key;Pointer&e.key; and &s.key;XInput&e.key;
-    sections.  Like the &k.device; section, it has two mandatory keywords:
-    &k.identifier; and &k.driver;.  For compatibility purposes the old
-    &s.key;Keyboard&e.key; and &s.key;Pointer&e.key; sections are
-    converted by the parser into &k.inputdevice; sections as follows:
-
-    <descrip>
-      <tag>&s.key;Keyboard&e.key;</tag>
-             &k.identifier; "Implicit Core Keyboard"<newline>
-             &k.driver; "keyboard"
-      <tag>&s.key;Pointer&e.key;</tag>
-             &k.identifier; "Implicit Core Pointer"<newline>
-             &k.driver; "mouse"
-    </descrip>
-
-    An &k.inputdevice; section is considered active if there is a
-    reference to it in an active &k.serverlayout; section.  An
-    &k.inputdevice; section may also be referenced implicitly if there
-    is no &k.serverlayout; section, if the &s.cmd;-screen&e.cmd; command
-    line options is used, or if the &k.serverlayout; section doesn't
-    reference any &k.inputdevice; sections.  In this case, the first
-    sections with drivers "keyboard" and "mouse" are used as the core
-    keyboard and pointer respectively.
-
-<sect1>&k.serverlayout; section
-<p>
-
-    The &k.serverlayout; section is a new section that is used to identify
-    which &k.screen; sections are to be used in a multi-headed configuration,
-    and the relative layout of those screens.  It also identifies which
-    &k.inputdevice; sections are to be used.  Each &k.serverlayout section
-    has an identifier, a list of &k.screen; section identifiers, and a list of
-    &k.inputdevice; section identifiers.  &k.serverflags; options may also be
-    included in a &k.serverlayout; section, making it possible to override
-    the global values in the &k.serverflags; section.
-
-    A &k.serverlayout; section can be made active by being referenced on
-    the command line.  In the absence of this, a default will be chosen
-    (the first one found).  The screen names may optionally be followed
-    by a number specifying the preferred screen number, and optionally
-    by information specifying the physical positioning of the screen,
-    either in absolute terms or relative to another screen (or screens).
-    When no screen number is specified, they are numbered according to
-    the order in which they are listed.  The old (now obsolete) method
-    of providing the positioning information is to give the names of
-    the four adjacent screens.  The order of these is top, bottom, left,
-    right.  Here is an example of a &k.serverlayout; section for two
-    screens using the old method, with the second located to the right
-    of the first:
-
-    <code>
-      Section "ServerLayout"
-        Identifier "Main Layout"
-        Screen     0 "Screen 1" ""  ""  ""  "Screen 2"
-        Screen     1 "Screen 2"
-        Screen     "Screen 3"
-      EndSection
-    </code>
-
-    The preferred way of specifying the layout is to explicitly specify
-    the screen's location in absolute terms or relative to another
-    screen.
-
-    In the absolute case, the upper left corner's coordinates are given
-    after the &s.key;Absolute&e.key; keyword.  If the coordinates are
-    omitted, a value of &s.code;(0,0)&e.code; is assumed.  An example
-    of absolute positioning follows:
-
-    <code>
-      Section "ServerLayout"
-        Identifier "Main Layout"
-        Screen     0 "Screen 1" Absolute 0 0
-        Screen     1 "Screen 2" Absolute 1024 0
-        Screen     "Screen 3" Absolute 2048 0
-      EndSection
-    </code>
-
-    In the relative case, the position is specified by either using one of
-    the following keywords followed by the name of the reference screen:
-
-    <quote>
-      &s.key;RightOf&nl;
-      LeftOf&nl;
-      Above&nl;
-      Below&nl;
-      Relative&e.key;
-    </quote>
-
-    When the &s.key;Relative&e.key; keyword is used, the reference screen
-    name is followed by the coordinates of the new screen's origin
-    relative to reference screen.  The following example shows how to use
-    some of the relative positioning options.
-
-    <code>
-      Section "ServerLayout"
-        Identifier "Main Layout"
-        Screen     0 "Screen 1"
-        Screen     1 "Screen 2" RightOf "Screen 1"
-        Screen     "Screen 3" Relative "Screen 1" 2048 0
-      EndSection
-    </code>
-
-<sect1>Options
-<p>
-
-    Options are used more extensively.  They may appear in most sections
-    now.  Options related to drivers can be present in the &k.screen;,
-    &k.device; and &k.monitor; sections and the &k.display; subsections.
-    The order of precedence is &k.display;, &k.screen;, &k.monitor;,
-    &k.device;.  Options have been extended to allow an optional value
-    to be specified in addition to the option name.  For more details
-    about options, see the <ref id="options" name="Options"> section
-    for details.
-
-<sect>Driver Interface
-<p>
-
-The driver interface consists of a minimal set of entry points that are
-required based on the external events that the driver must react to.
-No non-essential structure is imposed on the way they are used beyond
-that.  This is a significant difference compared with the old design.
-
-The entry points for drawing operations are already taken care of by
-the framebuffer code (including, XAA).  Extensions and enhancements to
-framebuffer code are outside the scope of this document.
-
-This approach to the driver interface provides good flexibility, but does
-increase the complexity of drivers.  To help address this, the XFree86
-common layer provides a set of ``helper'' functions to take care of things
-that most drivers need.  These helpers help minimise the amount of code
-duplication between drivers.  The use of helper functions by drivers is
-however optional, though encouraged.  The basic philosophy behind the
-helper functions is that they should be useful to many drivers, that
-they should balance this against the complexity of their interface.  It
-is inevitable that some drivers may find some helpers unsuitable and
-need to provide their own code.
-
-Events that a driver needs to react to are:
-
-   <descrip>
-   <tag>ScreenInit</tag>
-
-     An initialisation function is called from the DIX layer for each
-     screen at the start of each server generation.
-
-   <tag>Enter VT</tag>
-
-     The server takes control of the console.
-
-   <tag>Leave VT</tag>
-
-     The server releases control of the console.
-
-   <tag>Mode Switch</tag>
-
-     Change video mode.
-
-   <tag>ViewPort change</tag>
-
-     Change the origin of the physical view port.
-
-   <tag>ScreenSaver state change</tag>
-
-     Screen saver activation/deactivation.
-
-   <tag>CloseScreen</tag>
-
-     A close screen function is called from the DIX layer for each screen
-     at the end of each server generation.
-   </descrip>
-
-
-In addition to these events, the following functions are required by
-the XFree86 common layer:
-
-   <descrip>
-   <tag>Identify</tag>
-
-     Print a driver identifying message.
-
-   <tag>Probe</tag>
-
-     This is how a driver identifies if there is any hardware present that
-     it knows how to drive.
-
-   <tag>PreInit</tag>
-
-     Process information from the xorg.conf file, determine the
-     full characteristics of the hardware, and determine if a valid
-     configuration is present.
-   </descrip>
-
-The VidMode extension also requires:
-
-   <descrip>
-   <tag>ValidMode</tag>
-
-     Identify if a new mode is usable with the current configuration.
-     The PreInit function (and/or helpers it calls) may also make use
-     of the ValidMode function or something similar.
-   </descrip>
-
-
-Other extensions may require other entry points.  The drivers will
-inform the common layer of these in such cases.
-
-<sect>Resource Access Control Introduction
-<p>
-
-Graphics devices are accessed through ranges in I/O or memory space.
-While most modern graphics devices allow relocation of such ranges many
-of them still require the use of well established interfaces such as
-VGA memory and IO ranges or 8514/A IO ranges.  With modern buses (like
-PCI) it is possible for multiple video devices to share access to these
-resources.  The RAC (Resource Access Control) subsystem provides a
-mechanism for this.
-
-<sect1>Terms and Definitions
-<p>
-
-<sect2>Bus
-<p>
-
-    ``Bus'' is ambiguous as it is used for different things: it may refer
-    to physical incompatible extension connectors in a computer system.
-    The RAC system knows two such systems: The ISA bus and the PCI bus.
-    (On the software level EISA, MCA and VL buses are currently treated
-    like ISA buses).  ``Bus'' may also refer to logically different
-    entities on a single bus system which are connected via bridges.  A
-    PCI system may have several distinct PCI buses connecting each other
-    by PCI-PCI bridges or to the host CPU by HOST-PCI bridges.
-
-    Systems that host more than one bus system link these together using
-    bridges.  Bridges are a concern to RAC as they might block or pass
-    specific resources.  PCI-PCI bridges may be set up to pass VGA
-    resources to the secondary bus.  PCI-ISA buses pass any resources not
-    decoded on the primary PCI bus to the ISA bus.  This way VGA resources
-    (although exclusive on the ISA bus) can be shared by ISA and PCI
-    cards.  Currently HOST-PCI bridges are not yet handled by RAC as they
-    require specific drivers.
-
-<sect2>Entity
-<p>
-
-    The smallest independently addressable unit on a system bus is
-    referred to as an entity.  So far we know ISA and PCI entities.  PCI
-    entities can be located on the PCI bus by an unique ID consisting of
-    the bus, card and function number.
-
-<sect2>Resource
-<p>
-
-    ``Resource'' refers to a range of memory or I/O addresses an entity
-    can decode.
-
-    If a device is capable of disabling this decoding the resource is
-    called sharable.  For PCI devices a generic method is provided to
-    control resource decoding.  Other devices will have to provide a
-    device specific function to control decoding.
-
-    If the entity is capable of decoding this range at a different
-    location this resource is considered relocatable.
-
-    Resources which start at a specific address and occupy a single
-    continuous range are called block resources.
-
-    Alternatively resource addresses can be decoded in a way that they
-    satisfy the conditions:
-    <quote><verb>
-                    address & mask == base
-    </verb></quote>
-    and
-    <quote><verb>
-                       base & mask == base
-    </verb></quote>
-    Resources addressed in such a way are called sparse resources.
-
-<sect2>Server States
-<p>
-
-    The resource access control system knows two server states: the
-    SETUP and the OPERATING state.  The SETUP state is entered whenever
-    a mode change takes place or the server exits or does VT switching.
-    During this state all entity resources are under resource access
-    control.  During OPERATING state only those entities are controlled
-    which actually have shared resources that conflict with others.
-
-<sect>Control Flow in the Server and Mandatory Driver Functions
-<p>
-
-At the start of each server generation, &s.code;main()&e.code;
-(&s.code;dix/main.c&e.code;) calls the DDX function
-&s.code;InitOutput()&e.code;.  This is the first place that the DDX gets
-control.  &s.code;InitOutput()&e.code; is expected to fill in the global
-&s.code;screenInfo&e.code; struct, and one
-&s.code;screenInfo.screen[]&e.code; entry for each screen present.  Here
-is what &s.code;InitOutput()&e.code; does:
-
-<sect1>Parse the xorg.conf file
-<p>
-
-    This is done at the start of the first server generation only.
-
-    The xorg.conf file is read in full, and the resulting information
-    stored in data structures.  None of the parsed information is
-    processed at this point.  The parser data structures are opaque to
-    the video drivers and to most of the common layer code.
-
-    The entire file is parsed first to remove any section ordering
-    requirements.
-
-
-<sect1>Initial processing of parsed information and command line options
-<p>
-
-    This is done at the start of the first server generation only.
-
-    The initial processing is to determine paths like the
-    &s.key;ModulePath&e.key;, etc, and to determine which &k.serverlayout;,
-    &k.screen; and &k.device; sections are active.
-
-
-<sect1>Enable port I/O access
-<p>
-
-    Port I/O access is controlled from the XFree86 common layer, and is
-    ``all or nothing''.  It is enabled prior to calling driver probes, at
-    the start of subsequent server generations, and when VT switching
-    back to the Xserver.  It is disabled at the end of server generations,
-    and when VT switching away from the Xserver.
-
-    The implementation details of this may vary on different platforms.
-
-
-<sect1>General bus probe
-<p>
-
-    This is done at the start of the first server generation only.
-
-    In the case of ix86 machines, this will be a general PCI probe.
-    The full information obtained here will be available to the drivers.
-    This information persists for the life of the Xserver.  In the PCI
-    case, the PCI information for all video cards found is available by
-    calling &s.code;xf86GetPciVideoInfo()&e.code;.
-
-    <quote>
-    &s.code;pciVideoPtr *xf86GetPciVideoInfo(void)&e.code;
-    <quote><p>
-	returns a pointer to a list of pointers to
-	&s.code;pciVideoRec&e.code; entries, of which there is one for
-	each detected PCI video card.  The list is terminated with a
-	&s.code;NULL&e.code; pointer.  If no PCI video cards were
-	detected, the return value is &s.code;NULL&e.code;.
-
-    </quote>
-    </quote>
-
-    After the bus probe, the resource broker is initialised.
-
-
-<sect1>Load initial set of modules
-<p>
-
-    This is done at the start of the first server generation only.
-
-    The core server contains a list of mandatory modules.  These are loaded
-    first.  Currently the only module on this list is the bitmap font module.
-
-    The next set of modules loaded are those specified explicitly in the
-    &k.module; section of the config file.
-
-    The final set of initial modules are the driver modules referenced
-    by the active &k.device; and &k.inputdevice; sections in the config
-    file.  Each of these modules is loaded exactly once.
-
-
-<sect1>Register Video and Input Drivers
-<p>
-
-    This is done at the start of the first server generation only.
-
-    When a driver module is loaded, the loader calls its
-    &s.code;Setup&e.code; function.  For video drivers, this function
-    calls &s.code;xf86AddDriver()&e.code; to register the driver's
-    &s.code;DriverRec&e.code;, which contains a small set of essential
-    details and driver entry points required during the early phase of
-    &s.code;InitOutput()&e.code;.  &s.code;xf86AddDriver()&e.code; adds
-    it to the global &s.code;xf86DriverList[]&e.code; array.
-
-    The &s.code;DriverRec&e.code; contains the driver canonical name,
-    the &s.code;Identify()&e.code;,
-    &s.code;Probe()&e.code; and &s.code;AvailableOptions()&e.code;
-    function entry points as well as a pointer
-    to the driver's module (as returned from the loader when the driver
-    was loaded) and a reference count which keeps track of how many
-    screens are using the driver.  The entry driver entry points are
-    those required prior to the driver allocating and filling in its
-    &s.code;ScrnInfoRec&e.code;.
-
-    For a static server, the &s.code;xf86DriverList[]&e.code; array is
-    initialised at build time, and the loading of modules is not done.
-
-    A similar procedure is used for input drivers.  The input driver's
-    &s.code;Setup&e.code; function calls
-    &s.code;xf86AddInputDriver()&e.code; to register the driver's
-    &s.code;InputDriverRec&e.code;, which contains a small set of
-    essential details and driver entry points required during the early
-    phase of &s.code;InitInput()&e.code;.
-    &s.code;xf86AddInputDriver()&e.code; adds it to the global
-    &s.code;xf86InputDriverList[]&e.code; array.  For a static server,
-    the &s.code;xf86InputDriverList[]&e.code; array is initialised at
-    build time.
-
-    Both the &s.code;xf86DriverList[]&e.code; and
-    &s.code;xf86InputDriverList[]&e.code; arrays have been initialised
-    by the end of this stage.
-
-    Once all the drivers are registered, their
-    &s.code;ChipIdentify()&e.code; functions are called.
-
-    <quote>
-    &s.code;void ChipIdentify(int flags)&e.code;
-    <quote>
-      This is expected to print a message indicating the driver name,
-      a short summary of what it supports, and a list of the chipset
-      names that it supports.  It may use the xf86PrintChipsets() helper
-      to do this.
-    </quote>
-    </quote>
-
-    <quote>
-    &s.code;void xf86PrintChipsets(const char *drvname, const char *drvmsg,
-                     &f.indent;SymTabPtr chips)&e.code;
-    <quote>
-      This function provides an easy way for a driver's ChipIdentify
-      function to format the identification message.
-    </quote>
-    </quote>
-
-<sect1>Initialise Access Control
-<p>
-
-    This is done at the start of the first server generation only.
-
-    The Resource Access Control (RAC) subsystem is initialised before
-    calling any driver functions that may access hardware.  All generic
-    bus information is probed and saved (for restoration later).  All
-    (shared resource) video devices are disabled at the generic bus
-    level, and a probe is done to find the ``primary'' video device.  These
-    devices remain disabled for the next step.
-
-
-<sect1>Video Driver Probe<label id="probe">
-<p>
-    This is done at the start of the first server generation only.  The
-    &s.code;ChipProbe()&e.code; function of each registered video driver
-    is called.
-
-    <quote><p>
-    &s.code;Bool ChipProbe(DriverPtr drv, int flags)&e.code;
-    <quote><p>
-      The purpose of this is to identify all instances of hardware
-      supported by the driver.  The flags value is currently either 0,
-      &s.code;PROBE_DEFAULT&e.code; or &s.code;PROBE_DETECT&e.code;.
-      &s.code;PROBE_DETECT&e.code; is used if "-configure" or "-probe"
-      command line arguments are given and indicates to the
-      &s.code;Probe()&e.code; function that it should not configure the
-      bus entities and that no xorg.conf information is available.
-
-      The probe must find the active device sections that match the
-      driver by calling &s.code;xf86MatchDevice()&e.code;.  The number
-      of matches found limits the maximum number of instances for this
-      driver.  If no matches are found, the function should return
-      &s.code;FALSE&e.code; immediately.
-
-      Devices that cannot be identified by using device-independent
-      methods should be probed at this stage (keeping in mind that access
-      to all resources that can be disabled in a device-independent way
-      are disabled during this phase).  The probe must be a minimal
-      probe.  It should just determine if there is a card present that
-      the driver can drive.  It should use the least intrusive probe
-      methods possible.  It must not do anything that is not essential,
-      like probing for other details such as the amount of memory
-      installed, etc.  It is recommended that the
-      &s.code;xf86MatchPciInstances()&e.code; helper function be used
-      for identifying matching PCI devices, and similarly the
-      &s.code;xf86MatchIsaInstances()&e.code; for ISA (non-PCI) devices
-      (see the <ref id="rac" name="RAC"> section).  These helpers also
-      checks and claims the appropriate entity.  When not using the
-      helper, that should be done with &s.code;xf86CheckPciSlot()&e.code;
-      and &s.code;xf86ClaimPciSlot()&e.code; for PCI devices and
-      &s.code;xf86ClaimIsaSlot()&e.code; for ISA devices (see the
-      <ref id="rac" name="RAC"> section).
-
-      The probe must register all non-relocatable resources at this
-      stage.  If a resource conflict is found between exclusive resources
-      the driver will fail immediately.  This is usually best done with
-      the &s.code;xf86ConfigPciEntity()&e.code; helper function
-      for PCI and &s.code;xf86ConfigIsaEntity()&e.code; for ISA
-      (see the <ref id="rac" name="RAC"> section).  It is possible to
-      register some entity specific functions with those helpers.  When
-      not using the helpers, the &s.code;xf86AddEntityToScreen()&e.code;
-      &s.code;xf86ClaimFixedResources()&e.code; and
-      &s.code;xf86SetEntityFuncs()&e.code; should be used instead (see
-      the <ref id="rac" name="RAC"> section).
-
-      If a chipset is specified in an active device section which the
-      driver considers relevant (ie it has no driver specified, or the
-      driver specified matches the driver doing the probe), the Probe
-      must return &s.code;FALSE&e.code; if the chipset doesn't match
-      one supported by the driver.
-
-      If there are no active device sections that the driver considers
-      relevant, it must return &s.code;FALSE&e.code;.
-
-      Allocate a &s.code;ScrnInfoRec&e.code; for each active instance of the
-      hardware found, and fill in the basic information, including the
-      other driver entry points.   This is best done with the
-      &s.code;xf86ConfigIsaEntity()&e.code; helper function for ISA
-      instances or &s.code;xf86ConfigPciEntity()&e.code; for PCI instances.
-      These functions allocate a &s.code;ScrnInfoRec&e.code; for active
-      entities. Optionally &s.code;xf86AllocateScreen()&e.code;
-      function may also be used to allocate the &s.code;ScrnInfoRec&e.code;.
-      Any of these functions take care of initialising fields to defined
-      ``unused'' values.
-
-      Claim the entities for each instance of the hardware found.  This
-      prevents other drivers from claiming the same hardware.
-
-      Must leave hardware in the same state it found it in, and must not
-      do any hardware initialisation.
-
-      All detection can be overridden via the config file, and that
-      parsed information is available to the driver at this stage.
-
-      Returns &s.code;TRUE&e.code; if one or more instances are found,
-      and &s.code;FALSE&e.code; otherwise.
-
-    </quote>
-
-    &s.code;int xf86MatchDevice(const char *drivername,
-		&f.indent;GDevPtr **driversectlist)&e.code;
-    <quote><p>
-
-      This function takes the name of the driver and returns via
-      &s.code;driversectlist&e.code; a list of device sections that
-      match the driver name.  The function return value is the number
-      of matches found.  If a fatal error is encountered the return
-      value is &s.code;-1&e.code;.
-
-      The caller should use &s.code;xfree()&e.code; to free
-      &s.code;*driversectlist&e.code; when it is no longer needed.
-
-    </quote>
-
-    &s.code;ScrnInfoPtr xf86AllocateScreen(DriverPtr drv, int flags)&e.code;
-    <quote><p>
-      This function allocates a new &s.code;ScrnInfoRec&e.code; in the
-      &s.code;xf86Screens[]&e.code; array.  This function is normally
-      called by the video driver &s.code;ChipProbe()&e.code; functions.
-      The return value is a pointer to the newly allocated
-      &s.code;ScrnInfoRec&e.code;.  The &s.code;scrnIndex&e.code;,
-      &s.code;origIndex&e.code;, &s.code;module&e.code; and
-      &s.code;drv&e.code; fields are initialised.  The reference count
-      in &s.code;drv&e.code; is incremented.  The storage for any
-      currently allocated ``privates'' pointers is also allocated and
-      the &s.code;privates&e.code; field initialised (the privates data
-      is of course not allocated or initialised).  This function never
-      returns on failure.  If the allocation fails, the server exits
-      with a fatal error.  The flags value is not currently used, and
-      should be set to zero.
-    </quote>
-    </quote>
-
-    At the completion of this, a list of &s.code;ScrnInfoRecs&e.code;
-    have been allocated in the &s.code;xf86Screens[]&e.code; array, and
-    the associated entities and fixed resources have been claimed.  The
-    following &s.code;ScrnInfoRec&e.code; fields must be initialised at
-    this point:
-
-    <quote><verb>
-          driverVersion
-          driverName
-          scrnIndex(*)
-          origIndex(*)
-          drv(*)
-          module(*)
-          name
-          Probe
-          PreInit
-          ScreenInit
-          EnterVT
-          LeaveVT
-          numEntities
-          entityList
-          access
-    </verb></quote>
-
-    <tt>(*)</tt> These are initialised when the &s.code;ScrnInfoRec&e.code;
-    is allocated, and not explicitly by the driver.
-
-    The following &s.code;ScrnInfoRec&e.code; fields must be initialised
-    if the driver is going to use them:
-
-    <quote><verb>
-          SwitchMode
-          AdjustFrame
-          FreeScreen
-          ValidMode
-    </verb></quote>
-
-<sect1>Matching Screens
-<p>
-
-    This is done at the start of the first server generation only.
-
-    After the Probe phase is finished, there will be some number of
-    &s.code;ScrnInfoRecs&e.code;.  These are then matched with the active
-    &k.screen; sections in the xorg.conf, and those not having an active
-    &k.screen; section are deleted.  If the number of remaining screens
-    is 0, &s.code;InitOutput()&e.code; sets
-    &s.code;screenInfo.numScreens&e.code; to &s.code;0&e.code; and
-    returns.
-
-    At this point the following fields of the &s.code;ScrnInfoRecs&e.code;
-    must be initialised:
-
-    <quote><verb>
-          confScreen
-    </verb></quote>
-
-
-<sect1>Allocate non-conflicting resources
-<p>
-
-    This is done at the start of the first server generation only.
-
-    Before calling the drivers again, the resource information collected
-    from the Probe phase is processed.  This includes checking the extent
-    of PCI resources for the probed devices, and resolving any conflicts
-    in the relocatable PCI resources.  It also reports conflicts, checks
-    bus routing issues, and anything else that is needed to enable the
-    entities for the next phase.
-
-    If any drivers registered an &s.code;EntityInit()&e.code; function
-    during the Probe phase, then they are called here.
-
-
-<sect1>Sort the Screens and pre-check Monitor Information
-<p>
-
-    This is done at the start of the first server generation only.
-
-    The list of screens is sorted to match the ordering requested in the
-    config file.
-
-    The list of modes for each active monitor is checked against the
-    monitor's parameters.  Invalid modes are pruned.
-
-
-<sect1>PreInit
-<p>
-
-    This is done at the start of the first server generation only.
-
-    For each &s.code;ScrnInfoRec&e.code;, enable access to the screens entities and call
-    the &s.code;ChipPreInit()&e.code; function.
-
-    <quote><p>
-    &s.code;Bool ChipPreInit(ScrnInfoRec screen, int flags)&e.code;
-    <quote><p>
-      The purpose of this function is to find out all the information
-      required to determine if the configuration is usable, and to
-      initialise those parts of the &s.code;ScrnInfoRec&e.code; that
-      can be set once at the beginning of the first server generation.
-
-      The number of entities registered for the screen should be checked
-      against the expected number (most drivers expect only one).  The
-      entity information for each of them should be retrieved (with
-      &s.code;xf86GetEntityInfo()&e.code;) and checked for the correct
-      bus type and that none of the sharable resources registered during
-      the Probe phase was rejected.
-
-      Access to resources for the entities that can be controlled in a
-      device-independent way are enabled before this function is called.
-      If the driver needs to access any resources that it has disabled
-      in an &s.code;EntityInit()&e.code; function that it registered,
-      then it may enable them here providing that it disables them before
-      this function returns.
-
-      This includes probing for video memory, clocks, ramdac, and all
-      other HW info that is needed.  It includes determining the
-      depth/bpp/visual and related info.  It includes validating and
-      determining the set of video modes that will be used (and anything
-      that is required to determine that).
-
-      This information should be determined in the least intrusive way
-      possible.  The state of the HW must remain unchanged by this
-      function.  Although video memory (including MMIO) may be mapped
-      within this function, it must be unmapped before returning.  Driver
-      specific information should be stored in a structure hooked into
-      the &s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code;
-      field.  Any other modules which require persistent data (ie data
-      that persists across server generations) should be initialised in
-      this function, and they should allocate a ``privates'' index to
-      hook their data into by calling
-      &s.code;xf86AllocateScrnInfoPrivateIndex().&e.code;  The ``privates''
-      data is persistent.
-
-      Helper functions for some of these things are provided at the
-      XFree86 common level, and the driver can choose to make use of
-      them.
-
-      All additional resources that the screen needs must be registered
-      here.  This should be done with
-      &s.code;xf86RegisterResources()&e.code;.  If some of the fixed
-      resources registered in the Probe phase are not needed or not
-      decoded by the hardware when in the OPERATING server state, their
-      status should be updated with
-      &s.code;xf86SetOperatingState()&e.code;.
-
-      Modules may be loaded at any point in this function, and all
-      modules that the driver will need must be loaded before the end
-      of this function.  Either the  &s.code;xf86LoadSubModule()&e.code;
-      or the &s.code;xf86LoadDrvSubModule()&e.code; function should be
-      used to load modules depending on whether a
-      &s.code;ScrnInfoRec&e.code; has been set up. A driver may unload
-      a module within this function if it was only needed temporarily,
-      and the &s.code;xf86UnloadSubModule()&e.code; function should be used
-      to do that.  Otherwise there is no need to explicitly unload modules
-      because the loader takes care of module dependencies and will
-      unload submodules automatically if/when the driver module is
-      unloaded.
-
-      The bulk of the &s.code;ScrnInfoRec&e.code; fields should be filled
-      out in this function.
-
-      &s.code;ChipPreInit()&e.code; returns &s.code;FALSE&e.code; when
-      the configuration is unusable in some way (unsupported depth, no
-      valid modes, not enough video memory, etc), and &s.code;TRUE&e.code;
-      if it is usable.
-
-      It is expected that if the &s.code;ChipPreInit()&e.code; function
-      returns &s.code;TRUE&e.code;, then the only reasons that subsequent
-      stages in the driver might fail are lack or resources (like xalloc
-      failures).  All other possible reasons for failure should be
-      determined by the &s.code;ChipPreInit()&e.code; function.
-
-    </quote>
-    </quote>
-
-    The &s.code;ScrnInfoRecs&e.code; for screens where the &s.code;ChipPreInit()&e.code; fails are removed.
-    If none remain, &s.code;InitOutput()&e.code; sets &s.code;screenInfo.numScreens&e.code; to &s.code;0&e.code; and returns.
-
-    At this point, further fields of the &s.code;ScrnInfoRecs&e.code; would normally be
-    filled in.  Most are not strictly mandatory, but many are required
-    by other layers and/or helper functions that the driver may choose
-    to use.  The documentation for those layers and helper functions
-    indicates which they require.
-
-    The following fields of the &s.code;ScrnInfoRecs&e.code; should be filled in if the
-    driver is going to use them:
-
-    <quote><verb>
-          monitor
-          display
-          depth
-          pixmapBPP
-          bitsPerPixel
-          weight                (>8bpp only)
-          mask                  (>8bpp only)
-          offset                (>8bpp only)
-          rgbBits               (8bpp only)
-          gamma
-          defaultVisual
-          maxHValue
-          maxVValue
-          virtualX
-          virtualY
-          displayWidth
-          frameX0
-          frameY0
-          frameX1
-          frameY1
-          zoomLocked
-          modePool
-          modes
-          currentMode
-          progClock             (TRUE if clock is programmable)
-          chipset
-          ramdac
-          clockchip
-          numClocks             (if not programmable)
-          clock[]               (if not programmable)
-          videoRam
-          biosBase
-          memBase
-          memClk
-          driverPrivate
-          chipID
-          chipRev
-    </verb></quote>
-
-    <quote><p>
-    &s.code;pointer xf86LoadSubModule(ScrnInfoPtr pScrn, const char *name)&e.code:
-      and
-    &s.code;pointer xf86LoadDrvSubModule(DriverPtr drv, const char *name)&e.code:
-    <quote><p>
-      Load a module that a driver depends on.  This function loads the
-      module &s.code;name&e.code; as a sub module of the driver.  The
-      return value is a handle identifying the new module.  If the load
-      fails, the return value will be &s.code;NULL&e.code;.  If a driver
-      needs to explicitly unload a module it has loaded in this way,
-      the return value must be saved and passed to
-      &s.code;xf86UnloadSubModule()&e.code; when unloading.
-
-    </quote>
-
-    &s.code;void xf86UnloadSubModule(pointer module)&e.code;
-    <quote><p>
-      Unloads the module referenced by &s.code;module&e.code;.
-      &s.code;module&e.code; should be a pointer returned previously
-      by &s.code;xf86LoadSubModule()&e.code; or
-      &s.code;xf86LoadDrvSubModule()&e.code; .
-
-    </quote>
-    </quote>
-
-<sect1>Cleaning up Unused Drivers
-<p>
-
-    At this point it is known which screens will be in use, and which
-    drivers are being used.  Unreferenced drivers (and modules they
-    may have loaded) are unloaded here.
-
-
-<sect1>Consistency Checks
-<p>
-
-    The parameters that must be global to the server, like pixmap formats,
-    bitmap bit order, bitmap scanline unit and image byte order are
-    compared for each of the screens.  If a mismatch is found, the server
-    exits with an appropriate message.
-
-
-<sect1>Check if Resource Control is Needed
-<p>
-
-    Determine if resource access control is needed.  This is the case
-    if more than one screen is used.  If necessary the RAC wrapper module
-    is loaded.
-
-<sect1>AddScreen (ScreenInit)
-<p>
-
-    At this point, the valid screens are known.
-    &s.code;AddScreen()&e.code; is called for each of them, passing
-    &s.code;ChipScreenInit()&e.code; as the argument.
-    &s.code;AddScreen()&e.code; is a DIX function that allocates a new
-    &s.code;screenInfo.screen[]&e.code; entry (aka
-    &s.code;pScreen&e.code;), and does some basic initialisation of it.
-    It then calls the &s.code;ChipScreenInit()&e.code; function, with
-    &s.code;pScreen&e.code; as one of its arguments.  If
-    &s.code;ChipScreenInit()&e.code; returns &s.code;FALSE&e.code;,
-    &s.code;AddScreen()&e.code; returns &s.code;-1&e.code;.  Otherwise
-    it returns the index of the screen.  &s.code;AddScreen()&e.code;
-    should only fail because of programming errors or failure to allocate
-    resources (like memory).  All configuration problems should be
-    detected BEFORE this point.
-
-    <quote><p>
-    &s.code;Bool ChipScreenInit(int index, ScreenPtr pScreen,
-	&f.indent;int argc, char **argv)&e.code;
-    <quote><p>
-      This is called at the start of each server generation.
-
-      Fill in all of &s.code;pScreen&e.code;, possibly doing some of
-      this by calling ScreenInit functions from other layers like mi,
-      framebuffers (cfb, etc), and extensions.
-
-      Decide which operations need to be placed under resource access
-      control.  The classes of operations are the frame buffer operations
-      (&s.code;RAC_FB&e.code;), the pointer operations
-      (&s.code;RAC_CURSOR&e.code;), the viewport change operations
-      (&s.code;RAC_VIEWPORT&e.code;) and the colormap operations
-      (&s.code;RAC_COLORMAP&e.code;).  Any operation that requires
-      resources which might be disabled during OPERATING state should
-      be set to use RAC.  This can be specified separately for memory
-      and IO resources (the &s.code;racMemFlags&e.code; and
-      &s.code;racIoFlags&e.code; fields of the &s.code;ScrnInfoRec&e.code;
-      respectively).
-
-      Map any video memory or other memory regions.
-
-      Save the video card state.  Enough state must be saved so that
-      the original state can later be restored.
-
-      Initialise the initial video mode.  The &s.code;ScrnInfoRec&e.code;'s
-      &s.code;vtSema&e.code; field should be set to &s.code;TRUE&e.code;
-      just prior to changing the video hardware's state.
-
-    </quote>
-    </quote>
-
-
-    The &s.code;ChipScreenInit()&e.code; function (or functions from other
-    layers that it calls) should allocate entries in the
-    &s.code;ScreenRec&e.code;'s &s.code;devPrivates&e.code; area by
-    calling &s.code;AllocateScreenPrivateIndex()&e.code; if it needs
-    per-generation storage.  Since the &s.code;ScreenRec&e.code;'s
-    &s.code;devPrivates&e.code; information is cleared for each server
-    generation, this is the correct place to initialise it.
-
-    After &s.code;AddScreen()&e.code; has successfully returned, the
-    following &s.code;ScrnInfoRec&e.code; fields are initialised:
-
-    <quote><verb>
-          pScreen
-          racMemFlags
-          racIoFlags
-    </verb></quote>
-
-    The &s.code;ChipScreenInit()&e.code; function should initialise the
-    &s.code;CloseScreen&e.code; and &s.code;SaveScreen&e.code; fields
-    of &s.code;pScreen&e.code;.  The old value of
-    &s.code;pScreen-&gt;CloseScreen&e.code; should be saved as part of
-    the driver's per-screen private data, allowing it to be called from
-    &s.code;ChipCloseScreen()&e.code;.  This means that the existing
-    &s.code;CloseScreen()&e.code; function is wrapped.
-
-<sect1>Finalising RAC Initialisation
-<p>
-
-    After all the &s.code;ChipScreenInit()&e.code; functions have been
-    called, each screen has registered its RAC requirements.  This
-    information is used to determine which shared resources are requested
-    by more than one driver and set the access functions accordingly.
-    This is done following these rules:
-
-    <enum>
-     <item>The sharable resources registered by each entity are compared.
-	If a resource is registered by more than one entity the entity
-	will be marked to indicate that it needs to share this resources
-	type (IO or MEM).
-
-     <item>A resource marked ``disabled'' during OPERATING state will be
-        ignored entirely.
-
-     <item>A resource marked ``unused'' will only conflict with an overlapping
-	resource of an other entity if the second is actually in use
-	during OPERATING state.
-
-     <item>If an ``unused'' resource was found to conflict but the entity
-	does not use any other resource of this type the entire resource
-	type will be disabled for that entity.
-    </enum>
-
-
-<sect1>Finishing InitOutput()
-<p>
-
-    At this point &s.code;InitOutput()&e.code; is finished, and all the
-    screens have been setup in their initial video mode.
-
-
-<sect1>Mode Switching
-<p>
-
-    When a SwitchMode event is received, &s.code;ChipSwitchMode()&e.code;
-    is called (when it exists):
-
-    <quote><p>
-    &s.code;Bool ChipSwitchMode(int index, DisplayModePtr mode, int flags)&e.code;
-    <quote><p>
-      Initialises the new mode for the screen identified by
-      &s.code;index;&e.code;.  The viewport may need to be adjusted
-      also.
-
-    </quote>
-    </quote>
-
-
-<sect1>Changing Viewport
-<p>
-
-    When a Change Viewport event is received,
-    &s.code;ChipAdjustFrame()&e.code; is called (when it exists):
-
-    <quote><p>
-    &s.code;void ChipAdjustFrame(int index, int x, int y, int flags)&e.code;
-    <quote><p>
-      Changes the viewport for the screen identified by
-      &s.code;index;&e.code;.
-
-      It should be noted that many chipsets impose restrictions on where the
-      viewport may be placed in the virtual resolution, either for alignment
-      reasons, or to prevent the start of the viewport from being positioned
-      within a pixel (as can happen in a 24bpp mode).  After calculating the
-      value the chipset's panning registers need to be set to for non-DGA
-      modes, this function should recalculate the ScrnInfoRec's
-      &s.code;frameX0&e.code;, &s.code;frameY0&e.code, &s.code;frameX1&e.code;
-      and &s.code;frameY1&e.code; fields to correspond to that value.  If
-      this is not done, switching to another mode might cause the position
-      of a hardware cursor to change.
-
-    </quote>
-    </quote>
-
-
-<sect1>VT Switching
-<p>
-
-    When a VT switch event is received, &s.code;xf86VTSwitch()&e.code;
-    is called.  &s.code;xf86VTSwitch()&e.code; does the following:
-
-    <descrip>
-    <tag>On ENTER:</tag>
-    <itemize>
-      <item>enable port I/O access
-
-      <item>save and initialise the bus/resource state
-
-      <item>enter the SETUP server state
-
-      <item>calls &s.code;ChipEnterVT()&e.code; for each screen
-
-      <item>enter the OPERATING server state
-
-      <item>validate GCs
-
-      <item>Restore fb from saved pixmap for each screen
-
-      <item>Enable all input devices
-    </itemize>
-    <tag>On LEAVE:</tag>
-    <itemize>
-      <item>Save fb to pixmap for each screen
-
-      <item>validate GCs
-
-      <item>enter the SETUP server state
-
-      <item>calls &s.code;ChipLeaveVT()&e.code; for each screen
-
-      <item>disable all input devices
-
-      <item>restore bus/resource state
-
-      <item>disables port I/O access
-    </itemize>
-    </descrip>
-
-    <quote><p>
-    &s.code;Bool ChipEnterVT(int index, int flags)&e.code;
-    <quote><p>
-      This function should initialise the current video mode and
-      initialise the viewport, turn on the HW cursor if appropriate,
-      etc.
-
-      Should it re-save the video state before initialising the video
-      mode?
-
-    </quote>
-
-    &s.code;void ChipLeaveVT(int index, int flags)&e.code;
-    <quote><p>
-      This function should restore the saved video state.  If
-      appropriate it should also turn off the HW cursor, and invalidate
-      any pixmap/font caches.
-
-    </quote>
-
-    Optionally, &s.code;ChipLeaveVT()&e.code; may also unmap memory
-    regions.  If so, &s.code;ChipEnterVT()&e.code; will need to remap
-    them.  Additionally, if an aperture used to access video memory is
-    unmapped and remapped in this fashion, &s.code;ChipEnterVT()&e.code;
-    will also need to notify the framebuffer layers of the aperture's new
-    location in virtual memory.  This is done with a call to the screen's
-    &s.code;ModifyPixmapHeader()&e.code; function, as follows
-
-    <quote><p>
-    &s.code;(*pScreen->ModifyPixmapHeader)(pScrn->ppix,
-        &f.indent;-1, -1, -1, -1, -1, <it>NewApertureAddress</it>);&e.code;
-    <quote><p>
-        where the &s.code``ppix''&e.code; field in a ScrnInfoRec
-        points to the pixmap used by the screen's
-        &s.code;SaveRestoreImage()&e.code; function to hold the screen's
-        contents while switched out.
-
-    </quote>
-    </quote>
-
-    Currently, aperture remapping, as described here, should not be
-    attempted if the driver uses the &s.code;xf8_16bpp&e.code; or
-    &s.code;xf8_32bpp&e.code; framebuffer layers.  A pending
-    restructuring of VT switching will address this restriction in
-    the near future.
-
-    </quote>
-
-    Other layers may wrap the &s.code;ChipEnterVT()&e.code; and
-    &s.code;ChipLeaveVT()&e.code; functions if they need to take some
-    action when these events are received.
-
-<sect1>End of server generation
-<p>
-
-    At the end of each server generation, the DIX layer calls
-    &s.code;ChipCloseScreen()&e.code; for each screen:
-
-    <quote><p>
-    &s.code;Bool ChipCloseScreen(int index, ScreenPtr pScreen)&e.code;
-    <quote><p>
-      This function should restore the saved video state and unmap the
-      memory regions.
-
-      It should also free per-screen data structures allocated by the
-      driver.  Note that the persistent data held in the
-      &s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; field
-      should not be freed here because it is needed by subsequent server
-      generations.
-
-      The &s.code;ScrnInfoRec&e.code;'s &s.code;vtSema&e.code; field
-      should be set to &s.code;FALSE&e.code; once the video HW state
-      has been restored.
-
-      Before freeing the per-screen driver data the saved
-      &s.code;CloseScreen&e.code; value should be restored to
-      &s.code;pScreen-&gt;CloseScreen&e.code;, and that function should
-      be called after freeing the data.
-
-    </quote>
-    </quote>
-
-<sect>Optional Driver Functions
-<p>
-
-The functions outlined here can be called from the XFree86 common layer,
-but their presence is optional.
-
-<sect1>Mode Validation
-<p>
-
-    When a mode validation helper supplied by the XFree86-common layer is
-    being used, it can be useful to provide a function to check for hw
-    specific mode constraints:
-
-    <quote><p>
-    &s.code;ModeStatus ChipValidMode(int index, DisplayModePtr mode,
-                   &f.indent;Bool verbose, int flags)&e.code;
-    <quote><p>
-      Check the passed mode for hw-specific constraints, and return the
-      appropriate status value.
-
-    </quote>
-    </quote>
-
-<p>
-This function may also modify the effective timings and clock of the passed
-mode.  These have been stored in the mode's &s.code;Crtc*&e.code; and
-&s.code;SynthClock&e.code; elements, and have already been adjusted for
-interlacing, doublescanning, multiscanning and clock multipliers and dividers.
-The function should not modify any other mode field, unless it wants to modify
-the mode timings reported to the user by &s.code;xf86PrintModes()&e.code;.
-
-<p>
-The function is called once for every mode in the xorg.conf Monitor section
-assigned to the screen, with &s.code;flags&e.code; set to
-&s.code;MODECHECK_INITIAL&e.code;.  It is subsequently called for every mode
-in the xorg.conf Display subsection assigned to the screen, with
-&s.code;flags&e.code; set to &s.code;MODECHECK_FINAL&e.code;.  In the second
-case, the mode will have successfully passed all other tests.  In addition,
-the &s.code;ScrnInfoRec&e.code;'s &s.code;virtualX&e.code;,
-&s.code;virtualY&e.code; and &s.code;displayWidth&e.code; fields will have been
-set as if the mode to be validated were to be the last mode accepted.
-
-<p>
-In effect, calls with MODECHECK_INITIAL are intended for checks that do not
-depend on any mode other than the one being validated, while calls with
-MODECHECK_FINAL are intended for checks that may involve more than one mode.
-
-<sect1>Free screen data
-<p>
-
-    When a screen is deleted prior to the completion of the ScreenInit
-    phase the &s.code;ChipFreeScreen()&e.code; function is called when defined.
-
-    <quote><p>
-    &s.code;void ChipFreeScreen(int scrnindex, int flags)&e.code;
-    <quote><p>
-      Free any driver-allocated data that may have been allocated up to
-      and including an unsuccessful &s.code;ChipScreenInit()&e.code;
-      call.  This would predominantly be data allocated by
-      &s.code;ChipPreInit()&e.code; that persists across server
-      generations.  It would include the &s.code;driverPrivate&e.code;,
-      and any ``privates'' entries that modules may have allocated.
-
-    </quote>
-    </quote>
-
-
-<sect>Recommended driver functions
-<p>
-
-The functions outlined here are for internal use by the driver only.
-They are entirely optional, and are never accessed directly from higher
-layers.  The sample function declarations shown here are just examples.
-The interface (if any) used is up to the driver.
-
-<sect1>Save
-<p>
-
-    Save the video state.  This could be called from &s.code;ChipScreenInit()&e.code; and
-    (possibly) &s.code;ChipEnterVT()&e.code;.
-
-    <quote><p>
-    &s.code;void ChipSave(ScrnInfoPtr pScrn)&e.code;
-    <quote><p>
-      Saves the current state.  This will only be saving pre-server
-      states or states before returning to the server.  There is only
-      one current saved state per screen and it is stored in private
-      storage in the screen.
-
-    </quote>
-    </quote>
-
-<sect1>Restore
-<p>
-
-    Restore the original video state.  This could be called from the
-    &s.code;ChipLeaveVT()&e.code; and &s.code;ChipCloseScreen()&e.code;
-    functions.
-
-    <quote><p>
-    &s.code;void ChipRestore(ScrnInfoPtr pScrn)&e.code;
-    <quote><p>
-      Restores the saved state from the private storage.  Usually only
-      used for restoring text modes.
-
-    </quote>
-    </quote>
-
-
-<sect1>Initialise Mode
-<p>
-
-    Initialise a video mode.  This could be called from the
-    &s.code;ChipScreenInit()&e.code;, &s.code;ChipSwitchMode()&e.code;
-    and &s.code;ChipEnterVT()&e.code; functions.
-
-    <quote><p>
-    &s.code;Bool ChipModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)&e.code;
-    <quote><p>
-      Programs the hardware for the given video mode.
-
-    </quote>
-    </quote>
-
-
-<sect>Data and Data Structures
-<p>
-
-<sect1>Command line data
-<p>
-
-Command line options are typically global, and are stored in global
-variables.  These variables are read-only and are available to drivers
-via a function call interface.  Most of these command line values are
-processed via helper functions to ensure that they are treated consistently
-by all drivers.  The other means of access is provided for cases where
-the supplied helper functions might not be appropriate.
-
-Some of them are:
-
-<quote><verb>
-    xf86Verbose               verbosity level
-    xf86Bpp                   -bpp from the command line
-    xf86Depth                 -depth from the command line
-    xf86Weight                -weight from the command line
-    xf86Gamma                 -{r,g,b,}gamma from the command line
-    xf86FlipPixels            -flippixels from the command line
-    xf86ProbeOnly             -probeonly from the command line
-    defaultColorVisualClass   -cc from the command line
-</verb></quote>
-
-If we ever do allow for screen-specific command line options, we may
-need to rethink this.
-
-These can be accessed in a read-only manner by drivers with the following
-functions:
-
-    <quote><p>
-    &s.code;int xf86GetVerbosity()&e.code;
-    <quote><p>
-      Returns the value of &s.code;xf86Verbose&e.code;.
-
-    </quote>
-
-    &s.code;int xf86GetDepth()&e.code;
-    <quote><p>
-      Returns the &s.cmd;-depth&e.cmd; command line setting.  If not
-      set on the command line, &s.code;-1&e.code; is returned.
-
-    </quote>
-
-    &s.code;rgb xf86GetWeight()&e.code;
-    <quote><p>
-      Returns the &s.cmd;-weight&e.cmd; command line setting.  If not
-      set on the command line, &s.code;{0, 0, 0}&e.code; is returned.
-
-    </quote>
-
-    &s.code;Gamma xf86GetGamma()&e.code;
-    <quote><p>
-      Returns the &s.cmd;-gamma&e.cmd; or &s.cmd;-rgamma&e.cmd;,
-      &s.cmd;-ggamma&e.cmd;, &s.cmd;-bgamma&e.cmd; command line settings.
-      If not set on the command line, &s.code;{0.0, 0.0, 0.0}&e.code;
-      is returned.
-
-    </quote>
-
-    &s.code;Bool xf86GetFlipPixels()&e.code;
-    <quote><p>
-      Returns &s.code;TRUE&e.code; if &s.cmd;-flippixels&e.cmd; is
-      present on the command line, and &s.code;FALSE&e.code; otherwise.
-
-    </quote>
-
-    &s.code;const char *xf86GetServerName()&e.code;
-    <quote><p>
-      Returns the name of the X server from the command line.
-
-    </quote>
-    </quote>
-
-<sect1>Data handling
-<p>
-
-Config file data contains parts that are global, and parts that are
-Screen specific.  All of it is parsed into data structures that neither
-the drivers or most other parts of the server need to know about.
-
-The global data is typically not required by drivers, and as such, most
-of it is stored in the private &s.code;xf86InfoRec&e.code;.
-
-The screen-specific data collected from the config file is stored in
-screen, device, display, monitor-specific data structures that are separate
-from the &s.code;ScrnInfoRecs&e.code;, with the appropriate elements/fields
-hooked into the &s.code;ScrnInfoRecs&e.code; as required.  The screen
-config data is held in &s.code;confScreenRec&e.code;, device data in
-the &s.code;GDevRec&e.code;, monitor data in the &s.code;MonRec&e.code;,
-and display data in the &s.code;DispRec&e.code;.
-
-The XFree86 common layer's screen specific data (the actual data in use
-for each screen) is held in the &s.code;ScrnInfoRecs&e.code;.  As has
-been outlined above, the &s.code;ScrnInfoRecs&e.code; are allocated at probe
-time, and it is the responsibility of the Drivers' &s.code;Probe()&e.code;
-and &s.code;PreInit()&e.code; functions to finish filling them in based
-on both data provided on the command line and data provided from the
-Config file.  The precedence for this is:
-
-    <quote>
-    command line  -&gt;  config file  -&gt;  probed/default data
-    </quote>
-
-For most things in this category there are helper functions that the
-drivers can use to ensure that the above precedence is consistently
-used.
-
-As well as containing screen-specific data that the XFree86 common layer
-(including essential parts of the server infrastructure as well as helper
-functions) needs to access, it also contains some data that drivers use
-internally.  When considering whether to add a new field to the
-&s.code;ScrnInfoRec&e.code;, consider the balance between the convenience
-of things that lots of drivers need and the size/obscurity of the
-&s.code;ScrnInfoRec&e.code;.
-
-Per-screen driver specific data that cannot be accommodated with the
-static &s.code;ScrnInfoRec&e.code; fields is held in a driver-defined
-data structure, a pointer to which is assigned to the
-&s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; field.  This
-is per-screen data that persists across server generations (as does the
-bulk of the static &s.code;ScrnInfoRec&e.code; data).  It would typically
-also include the video card's saved state.
-
-Per-screen data for other modules that the driver uses (for example,
-the XAA module) that is reset for each server generation is hooked into
-the &s.code;ScrnInfoRec&e.code; through it's &s.code;privates&e.code;
-field.
-
-Once it has stabilised, the data structures and variables accessible to
-video drivers will be documented here.  In the meantime, those things
-defined in the &s.code;xf86.h&e.code; and &s.code;xf86str.h&e.code;
-files are visible to video drivers.  Things defined in
-&s.code;xf86Priv.h&e.code; and &s.code;xf86Privstr.h&e.code; are NOT
-intended to be visible to video drivers, and it is an error for a driver
-to include those files.
-
-
-<sect1>Accessing global data
-<p>
-
-Some other global state information that the drivers may access via
-functions is as follows:
-
-    <quote><p>
-    &s.code;Bool xf86ServerIsExiting()&e.code;
-    <quote><p>
-      Returns &s.code;TRUE&e.code; if the server is at the end of a
-      generation and is in the process of exiting, and
-      &s.code;FALSE&e.code; otherwise.
-
-    </quote>
-
-    &s.code;Bool xf86ServerIsResetting()&e.code;
-    <quote><p>
-      Returns &s.code;TRUE&e.code; if the server is at the end of a
-      generation and is in the process of resetting, and
-      &s.code;FALSE&e.code; otherwise.
-
-    </quote>
-
-    &s.code;Bool xf86ServerIsInitialising()&e.code;
-    <quote><p>
-      Returns &s.code;TRUE&e.code; if the server is at the beginning of
-      a generation and is in the process of initialising, and
-      &s.code;FALSE&e.code; otherwise.
-
-    </quote>
-
-    &s.code;Bool xf86ServerIsOnlyProbing()&e.code;
-    <quote><p>
-      Returns &s.code;TRUE&e.code; if the -probeonly command line flag
-      was specified, and &s.code;FALSE&e.code; otherwise.
-
-    </quote>
-
-    &s.code;Bool xf86CaughtSignal()&e.code;
-    <quote><p>
-      Returns &s.code;TRUE&e.code; if the server has caught a signal,
-      and &s.code;FALSE&e.code; otherwise.
-
-    </quote>
-    </quote>
-
-<sect1>Allocating private data
-<p>
-
-A driver and any module it uses may allocate per-screen private storage
-in either the &s.code;ScreenRec&e.code; (DIX level) or
-&s.code;ScrnInfoRec&e.code; (XFree86 common layer level).
-&s.code;ScreenRec&e.code; storage persists only for a single server
-generation, and &s.code;ScrnInfoRec&e.code; storage persists across
-generations for the lifetime of the server.
-
-The &s.code;ScreenRec&e.code; &s.code;devPrivates&e.code; data must be
-reallocated/initialised at the start of each new generation.  This is
-normally done from the &s.code;ChipScreenInit()&e.code; function, and
-Init functions for other modules that it calls.  Data allocated in this
-way should be freed by the driver's &s.code;ChipCloseScreen()&e.code;
-functions, and Close functions for other modules that it calls.  A new
-&s.code;devPrivates&e.code; entry is allocated by calling the
-&s.code;AllocateScreenPrivateIndex()&e.code; function.
-
-    <quote><p>
-    &s.code;int AllocateScreenPrivateIndex()&e.code;
-    <quote><p>
-      This function allocates a new element in the
-      &s.code;devPrivates&e.code; field of all currently existing
-      &s.code;ScreenRecs&e.code;.  The return value is the index of this
-      new element in the &s.code;devPrivates&e.code; array.  The
-      &s.code;devPrivates&e.code; field is of type
-      &s.code;DevUnion&e.code;:
-
-	<verb>
-        typedef union _DevUnion {
-            pointer             ptr;
-            long                val;
-            unsigned long       uval;
-            pointer             (*fptr)(void);
-        } DevUnion;
-	</verb>
-
-      which allows the element to be used for any of the above types.
-      It is commonly used as a pointer to data that the caller allocates
-      after the new index has been allocated.
-
-      This function will return &s.code;-1&e.code; when there is an
-      error allocating the new index.
-
-    </quote>
-    </quote>
-
-The &s.code;ScrnInfoRec&e.code; &s.code;privates&e.code; data persists
-for the life of the server, so only needs to be allocated once.  This
-should be done from the &s.code;ChipPreInit()&e.code; function, and Init
-functions for other modules that it calls.  Data allocated in this way
-should be freed by the driver's &s.code;ChipFreeScreen()&e.code; functions,
-and Free functions for other modules that it calls.  A new
-&s.code;privates&e.code; entry is allocated by calling the
-&s.code;xf86AllocateScrnInfoPrivateIndex()&e.code; function.
-
-
-    <quote><p>
-    &s.code;int xf86AllocateScrnInfoPrivateIndex()&e.code;
-    <quote><p>
-      This function allocates a new element in the &s.code;privates&e.code;
-      field of all currently existing &s.code;ScrnInfoRecs&e.code;.
-      The return value is the index of this new element in the
-      &s.code;privates&e.code; array.  The &s.code;privates&e.code;
-      field is of type &s.code;DevUnion&e.code;:
-
-        <verb>
-        typedef union _DevUnion {
-            pointer             ptr;
-            long                val;
-            unsigned long       uval;
-            pointer             (*fptr)(void);
-        } DevUnion;
-        </verb>
-
-      which allows the element to be used for any of the above types.
-      It is commonly used as a pointer to data that the caller allocates
-      after the new index has been allocated.
-
-      This function will not return when there is an error allocating
-      the new index.  When there is an error it will cause the server
-      to exit with a fatal error.  The similar function for allocation
-      privates in the &s.code;ScreenRec&e.code;
-      (&s.code;AllocateScreenPrivateIndex()&e.code;) differs in this
-      respect by returning &s.code;-1&e.code; when the allocation fails.
-
-    </quote>
-    </quote>
-
-<sect>Keeping Track of Bus Resources<label id="rac">
-<p>
-
-<sect1>Theory of Operation
-<p>
-
-The XFree86 common layer has knowledge of generic access control mechanisms
-for devices on certain bus systems (currently the PCI bus) as well as
-of methods to enable or disable access to the buses itself.  Furthermore
-it can access information on resources decoded by these devices and if
-necessary modify it.
-
-When first starting the Xserver collects all this information, saves it
-for restoration, checks it for consistency, and if necessary, corrects
-it.  Finally it disables all resources on a generic level prior to
-calling any driver function.
-
-When the &s.code;Probe()&e.code; function of each driver is called the
-device sections are matched against the devices found in the system.
-The driver may probe devices at this stage that cannot be identified by
-using device independent methods.  Access to all resources that can be
-controlled in a device independent way is disabled.  The
-&s.code;Probe()&e.code; function should register all non-relocatable
-resources at this stage.  If a resource conflict is found between
-exclusive resources the driver will fail immediately.  Optionally the
-driver might specify an &s.code;EntityInit()&e.code;,
-&s.code;EntityLeave()&e.code; and &s.code;EntityEnter()&e.code; function.
-
-&s.code;EntityInit()&e.code; can be used to disable any shared resources
-that are not controlled by the generic access control functions.  It is
-called prior to the PreInit phase regardless if an entity is active or
-not.  When calling the &s.code;EntityInit()&e.code;,
-&s.code;EntityEnter()&e.code; and &s.code;EntityLeave()&e.code; functions
-the common level will disable access to all other entities on a generic
-level.  Since the common level has no knowledge of device specific
-methods to disable access to resources it cannot be guaranteed that
-certain resources are not decoded by any other entity until the
-&s.code;EntityInit()&e.code; or &s.code;EntityEnter()&e.code; phase is
-finished.  Device drivers should therefore register all those resources
-which they are going to disable.  If these resources are never to be
-used by any driver function they may be flagged &s.code;ResInit&e.code;
-so that they can be removed from the resource list after processing all
-&s.code;EntityInit()&e.code; functions.  &s.code;EntityEnter()&e.code;
-should disable decoding of all resources which are not registered as
-exclusive and which are not handled by the generic access control in
-the common level.  The difference to &s.code;EntityInit()&e.code; is
-that the latter one is only called once during lifetime of the server.
-It can therefore be used to set up variables prior to disabling resources.
-&s.code;EntityLeave()&e.code; should restore the original state when
-exiting the server or switching to a different VT.  It also needs to
-disable device specific access functions if they need to be disabled on
-server exit or VT switch.  The default state is to enable them before
-giving up the VT.
-
-In &s.code;PreInit()&e.code; phase each driver should check if any
-sharable resources it has registered during &s.code;Probe()&e.code; has
-been denied and take appropriate action which could simply be to fail.
-If it needs to access resources it has disabled during
-&s.code;EntitySetup()&e.code; it can do so provided it has registered
-these and will disable them before returning from
-&s.code;PreInit()&e.code;.  This also applies to all other driver
-functions.  Several functions are provided to request resource ranges,
-register these, correct PCI config space and add replacements for the
-generic access functions.  Resources may be marked ``disabled'' or
-``unused'' during OPERATING stage.  Although these steps could also be
-performed in &s.code;ScreenInit()&e.code;, this is not desirable.
-
-Following &s.code;PreInit()&e.code; phase the common level determines
-if resource access control is needed.  This is the case if more than
-one screen is used.  If necessary the RAC wrapper module is loaded.  In
-&s.code;ScreenInit()&e.code; the drivers can decide which operations
-need to be placed under RAC.  Available are the frame buffer operations,
-the pointer operations and the colormap operations.  Any operation that
-requires resources which might be disabled during OPERATING state should
-be set to use RAC.  This can be specified separately for memory and IO
-resources.
-
-When &s.code;ScreenInit()&e.code; phase is done the common level will
-determine which shared resources are requested by more than one driver
-and set the access functions accordingly.  This is done following these
-rules:
-
-<enum>
-<item>The sharable resources registered by each entity are compared.  If
-   a resource is registered by more than one entity the entity will be
-   marked to need to share this resources type (&s.code;IO&e.code; or
-   &s.code;MEM&e.code;).
-
-<item>A resource marked ``disabled'' during OPERATING state will be ignored
-   entirely.
-
-<item>A resource marked ``unused'' will only conflicts with an overlapping
-   resource of an other entity if the second is actually in use during
-   OPERATING state.
-
-<item>If an ``unused'' resource was found to conflict however the entity
-   does not use any other resource of this type the entire resource type
-   will be disabled for that entity.
-</enum>
-
-The driver has the choice among different ways to control access to
-certain resources:
-
-<enum>
-<item>It can rely on the generic access functions.  This is probably the
-   most common case.  Here the driver only needs to register any resource
-   it is going to use.
-
-<item>It can replace the generic access functions by driver specific
-   ones.  This will mostly be used in cases where no generic access
-   functions are available.  In this case the driver has to make sure
-   these resources are disabled when entering the &s.code;PreInit()&e.code;
-   stage.  Since the replacement functions are registered in
-   &s.code;PreInit()&e.code; the driver will have to enable these
-   resources itself if it needs to access them during this state.  The
-   driver can specify if the replacement functions can control memory
-   and/or I/O resources separately.
-
-<item>The driver can enable resources itself when it needs them.  Each
-   driver function enabling them needs to disable them before it will
-   return.  This should be used if a resource which can be controlled
-   in a device dependent way is only required during SETUP state.  This
-   way it can be marked ``unused'' during OPERATING state.
-</enum>
-
-A resource which is decoded during OPERATING state however never accessed
-by the driver should be marked unused.
-
-Since access switching latencies are an issue during Xserver operation,
-the common level attempts to minimize the number of entities that need
-to be placed under RAC control.  When a wrapped operation is called,
-the &s.code;EnableAccess()&e.code; function is called before control is
-passed on.  &s.code;EnableAccess()&e.code; checks if a screen is under
-access control.  If not it just establishes bus routing and returns.
-If the screen needs to be under access control,
-&s.code;EnableAccess()&e.code; determines which resource types
-(&s.code;MEM&e.code;, &s.code;IO&e.code;) are required.  Then it tests
-if this access is already established.  If so it simply returns.  If
-not it disables the currently established access, fixes bus routing and
-enables access to all entities registered for this screen.
-
-Whenever a mode switch or a VT-switch is performed the common level will
-return to SETUP state.
-
-<sect1>Resource Types
-<p>
-
-Resource have certain properties.  When registering resources each range
-is accompanied by a flag consisting of the ORed flags of the different
-properties the resource has.  Each resource range may be classified
-according to
-
-<itemize>
-  <item>its physical properties i.e., if it addresses
-       memory (&s.code;ResMem&e.code;)  or
-       I/O space (&s.code;ResIo&e.code;),
-  <item>if it addresses a
-       block (&s.code;ResBlock&e.code;) or
-       sparse (&s.code;ResSparse&e.code;)
-    range,
-  <item>its access properties.
-</itemize>
-
-There are two known access properties:
-
-<itemize>
-  <item>&s.code;ResExclusive&e.code;
-    for resources which may not be shared with any other device and
-  <item>&s.code;ResShared&e.code;
-    for resources which can be disabled and therefore can be shared.
-</itemize>
-
-If it is necessary to test a resource against any type a generic access
-type &s.code;ResAny&e.code; is provided.  If this is set the resource
-will conflict with any resource of a different entity intersecting its
-range.  Further it can be specified that a resource is decoded however
-never used during any stage (&s.code;ResUnused&e.code;) or during
-OPERATING state (&s.code;ResUnusedOpr&e.code;).  A resource only visible
-during the init functions (ie.  &s.code;EntityInit()&e.code;,
-&s.code;EntityEnter()&e.code; and &s.code;EntityLeave()&e.code; should
-be registered with the flag &s.code;ResInit&e.code;.  A resource that
-might conflict with background resource ranges may be flagged with
-&s.code;ResBios&e.code;.  This might be useful when registering resources
-ranges that were assigned by the system Bios.
-
-Several predefined resource lists are available for VGA and 8514/A
-resources in &s.code;common/xf86Resources.h&e.code;.
-
-<sect1>Available Functions<label id="avail">
-<p>
-
-The functions provided for resource management are listed in their order
-of use in the driver.
-
-
-<sect2>Probe Phase
-<p>
-
-In this phase each driver detects those resources it is able to drive,
-creates an entity record for each of them, registers non-relocatable
-resources and allocates screens and adds the resources to screens.
-
-Two helper functions are provided for matching device sections in the
-xorg.conf file to the devices:
-
-    <quote><p>
-    &s.code;int xf86MatchPciInstances(const char *driverName, int vendorID,
-		&f.indent;SymTabPtr chipsets, PciChipsets *PCIchipsets,
-                &f.indent;GDevPtr *devList, int numDevs, DriverPtr drvp,
-                &f.indent;int **foundEntities)&e.code;
-    <quote><p>
-      This function finds matches between PCI cards that a driver supports
-      and config file device sections.  It is intended for use in the
-      &s.code;ChipProbe()&e.code; function of drivers for PCI cards.
-      Only probed PCI devices with a vendor ID matching
-      &s.code;vendorID&e.code; are considered.  &s.code;devList&e.code;
-      and &s.code;numDevs&e.code; are typically those found from
-      calling &s.code;xf86MatchDevice()&e.code;, and represent the active
-      config file device sections relevant to the driver.
-      &s.code;PCIchipsets&e.code; is a table that provides a mapping
-      between the PCI device IDs, the driver's internal chipset tokens
-      and a list of fixed resources.
-
-      When a device section doesn't have a &s.key;BusID&e.key; entry it
-      can only match the primary video device.  Secondary devices are
-      only matched with device sections that have a matching
-      &s.key;BusID&e.key; entry.
-
-      Once the preliminary matches have been found, a final match is
-      confirmed by checking if the chipset override, ChipID override or
-      probed PCI chipset type match one of those given in the
-      &s.code;chipsets&e.code; and &s.code;PCIchipsets&e.code; lists.
-      The &s.code;PCIchipsets&e.code; list includes a list of the PCI
-      device IDs supported by the driver.  The list should be terminated
-      with an entry with PCI ID &s.code;-1&e.code;".  The
-      &s.code;chipsets&e.code; list is a table mapping the driver's
-      internal chipset tokens to names, and should be terminated with
-      a &s.code;NULL&e.code; entry.  Only those entries with a
-      corresponding entry in the &s.code;PCIchipsets&e.code; list are
-      considered.  The order of precedence is: config file chipset,
-      config file ChipID, probed PCI device ID.
-
-      In cases where a driver handles PCI chipsets with more than one
-      vendor ID, it may set &s.code;vendorID&e.code; to
-      &s.code;0&e.code;, and OR each devID in the list with (the
-      vendor&nbsp;ID&nbsp;&lt;&lt;&nbsp;16).
-
-      Entity index numbers for confirmed matches are returned as an
-      array via &s.code;foundEntities&e.code;.  The PCI information,
-      chipset token and device section for each match are found in the
-      &s.code;EntityInfoRec&e.code; referenced by the indices.
-
-      The function return value is the number of confirmed matches.  A
-      return value of &s.code;-1&e.code; indicates an internal error.
-      The returned &s.code;foundEntities&e.code; array should be freed
-      by the driver with &s.code;xfree()&e.code; when it is no longer
-      needed in cases where the return value is greater than zero.
-
-    </quote>
-
-    &s.code;int xf86MatchIsaInstances(const char *driverName,
-		     &f.indent;SymTabPtr chipsets, IsaChipsets *ISAchipsets,
-		     &f.indent;DriverPtr drvp, FindIsaDevProc FindIsaDevice,
-		     &f.indent;GDevPtr *devList, int numDevs,
-					int **foundEntities)&e.code;
-    <quote><p>
-      This function finds matches between ISA cards that a driver supports
-      and config file device sections.  It is intended for use in the
-      &s.code;ChipProbe()&e.code; function of drivers for ISA cards.
-      &s.code;devList&e.code; and &s.code;numDevs&e.code; are
-      typically those found from calling &s.code;xf86MatchDevice()&e.code;,
-      and represent the active config file device sections relevant to
-      the driver.  &s.code;ISAchipsets&e.code; is a table that provides
-      a mapping between the driver's internal chipset tokens and the
-      resource classes.  &s.code;FindIsaDevice&e.code; is a
-      driver-provided function that probes the hardware and returns the
-      chipset token corresponding to what was detected, and
-      &s.code;-1&e.code; if nothing was detected.
-
-      If the config file device section contains a chipset entry, then
-      it is checked against the &s.code;chipsets&e.code; list.  When
-      no chipset entry is present, the &s.code;FindIsaDevice&e.code;
-      function is called instead.
-
-      Entity index numbers for confirmed matches are returned as an
-      array via &s.code;foundEntities&e.code;.  The chipset token and
-      device section for each match are found in the
-      &s.code;EntityInfoRec&e.code; referenced by the indices.
-
-      The function return value is the number of confirmed matches.  A
-      return value of &s.code;-1&e.code; indicates an internal error.
-      The returned &s.code;foundEntities&e.code; array should be freed
-      by the driver with &s.code;xfree()&e.code; when it is no longer
-      needed in cases where the return value is greater than zero.
-
-    </quote>
-    </quote>
-
-These two helper functions make use of several core functions that are
-available at the driver level:
-
-    <quote><p>
-    &s.code;Bool xf86ParsePciBusString(const char *busID, int *bus,
-			&f.indent;int *device, int *func)&e.code;
-    <quote><p>
-      Takes a &s.code;BusID&e.code; string, and if it is in the correct
-      format, returns the PCI &s.code;bus&e.code;, &s.code;device&e.code;,
-      &s.code;func&e.code; values that it indicates.  The format of the
-      string is expected to be "PCI:bus:device:func" where each of `bus',
-      `device' and `func' are decimal integers.  The ":func" part may
-      be omitted, and the func value assumed to be zero, but this isn't
-      encouraged.  The "PCI" prefix may also be omitted.  The prefix
-      "AGP" is currently equivalent to the "PCI" prefix.  If the string
-      isn't a valid PCI BusID, the return value is &s.code;FALSE&e.code;.
-
-    </quote>
-
-
-    &s.code;Bool xf86ComparePciBusString(const char *busID, int bus,
-			&f.indent;int device, int func)&e.code;
-    <quote><p>
-      Compares a &s.code;BusID&e.code; string with PCI &s.code;bus&e.code;,
-      &s.code;device&e.code;, &s.code;func&e.code; values.  If they
-      match &s.code;TRUE&e.code; is returned, and &s.code;FALSE&e.code;
-      if they don't.
-
-    </quote>
-
-    &s.code;Bool xf86ParseIsaBusString(const char *busID)&e.code;
-    <quote><p>
-      Compares a &s.code;BusID&e.code; string with the ISA bus ID string
-      ("ISA" or "ISA:").  If they match &s.code;TRUE&e.code; is returned,
-      and &s.code;FALSE&e.code; if they don't.
-
-    </quote>
-
-    &s.code;Bool xf86CheckPciSlot(int bus, int device, int func)&e.code;
-    <quote><p>
-      Checks if the PCI slot &s.code;bus:device:func&e.code; has been
-      claimed.  If so, it returns &s.code;FALSE&e.code;, and otherwise
-      &s.code;TRUE&e.code;.
-
-    </quote>
-
-    &s.code;int xf86ClaimPciSlot(int bus, int device, int func, DriverPtr drvp,
-			&f.indent;int chipset, GDevPtr dev, Bool active)&e.code;
-    <quote><p>
-      This function is used to claim a PCI slot, allocate the associated
-      entity record and initialise their data structures.  The return
-      value is the index of the newly allocated entity record, or
-      &s.code;-1&e.code; if the claim fails.  This function should always
-      succeed if &s.code;xf86CheckPciSlot()&e.code; returned
-      &s.code;TRUE&e.code; for the same PCI slot.
-
-    </quote>
-
-    &s.code;Bool xf86IsPrimaryPci(void)&e.code;
-    <quote><p>
-      This function returns &s.code;TRUE&e.code; if the primary card is
-      a PCI device, and &s.code;FALSE&e.code; otherwise.
-
-    </quote>
-
-    &s.code;int xf86ClaimIsaSlot(DriverPtr drvp, int chipset,
-			&f.indent;GDevPtr dev, Bool active)&e.code;
-    <quote><p>
-      This allocates an entity record entity and initialise the data
-      structures.  The return value is the index of the newly allocated
-      entity record.
-
-    </quote>
-
-    &s.code;Bool xf86IsPrimaryIsa(void)&e.code;
-    <quote><p>
-      This function returns &s.code;TRUE&e.code; if the primary card is
-      an ISA (non-PCI) device, and &s.code;FALSE&e.code; otherwise.
-
-    </quote>
-    </quote>
-
-Two helper functions are provided to aid configuring entities:
-    <quote><p>
-    &s.code;ScrnInfoPtr xf86ConfigPciEntity(ScrnInfoPtr pScrn,
-                                 &f.indent;int scrnFlag, int entityIndex,
-                                 &f.indent;PciChipsets *p_chip,
-                                 &f.indent;resList res, EntityProc init,
-                                 &f.indent;EntityProc enter, EntityProc leave,
-                                 &f.indent;pointer private)&e.code;
-    <p>
-    &s.code;ScrnInfoPtr xf86ConfigIsaEntity(ScrnInfoPtr pScrn,
-                                 &f.indent;int scrnFlag, int entityIndex,
-                                 &f.indent;IsaChipsets *i_chip,
-                                 &f.indent;resList res, EntityProc init,
-                                 &f.indent;EntityProc enter, EntityProc leave,
-                                 &f.indent;pointer private)&e.code;
-    <quote><p>
-      These functions are used to register the non-relocatable resources
-      for an entity, and the optional entity-specific &s.code;Init&e.code;, &s.code;Enter&e.code; and
-      &s.code;Leave&e.code; functions.  Usually the list of fixed resources is obtained
-      from the Isa/PciChipsets lists.  However an additional list of
-      resources may be passed.  Generally this is not required.
-      For active entities a &s.code;ScrnInfoRec&e.code; is allocated
-      if the &s.code;pScrn&e.code; argument is &s.code;NULL&e.code;.
-The
-      return value is &s.code;TRUE&e.code; when successful.  The init, enter, leave
-      functions are defined as follows:
-
-        <quote>
-        &s.code;typedef void (*EntityProc)(int entityIndex,
-			&f.indent;pointer private)&e.code;
-        </quote>
-
-      They are passed the entity index and a pointer to a private scratch
-      area.  This can be set up during &s.code;Probe()&e.code; and
-      its address can be passed to
-      &s.code;xf86ConfigIsaEntity()&e.code; and
-      &s.code;xf86ConfigPciEntity()&e.code; as the last argument.
-
-    </quote>
-    </quote>
-
-These two helper functions make use of several core functions that are
-available at the driver level:
-    <quote><p>
-    &s.code;void xf86ClaimFixedResources(resList list, int entityIndex)&e.code;
-    <quote><p>
-      This function registers the non-relocatable resources which cannot
-      be disabled and which therefore would cause the server to fail
-      immediately if they were found to conflict.  It also records
-      non-relocatable but sharable resources for processing after the
-      &s.code;Probe()&e.code; phase.
-
-    </quote>
-
-    &s.code;Bool xf86SetEntityFuncs(int entityIndex, EntityProc init,
-			&f.indent;EntityProc enter, EntityProc leave, pointer)&e.code;
-    <quote><p>
-      This function registers with an entity the &s.code;init&e.code;,
-      &s.code;enter&e.code;, &s.code;leave&e.code; functions along
-      with the pointer to their private area.
-
-    </quote>
-
-    &s.code;void xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex)&e.code;
-    <quote><p>
-      This function associates the entity referenced by
-      &s.code;entityIndex&e.code; with the screen.
-
-    </quote>
-    </quote>
-
-<sect2>PreInit Phase
-<p>
-
-During this phase the remaining resources should be registered.
-&s.code;PreInit()&e.code; should call &s.code;xf86GetEntityInfo()&e.code;
-to obtain a pointer to an &s.code;EntityInfoRec&e.code; for each entity
-it is able to drive and check if any resource are listed in its
-&s.code;resources&e.code; field.  If resources registered in the Probe
-phase have been rejected in the post-Probe phase
-(&s.code;resources&e.code; is non-&s.code;NULL&e.code;), then the driver should
-decide if it can continue without using these or if it should fail.
-
-    <quote><p>
-    &s.code;EntityInfoPtr xf86GetEntityInfo(int entityIndex)&e.code;
-    <quote><p>
-      This function returns a pointer to the &s.code;EntityInfoRec&e.code;
-      referenced by &s.code;entityIndex&e.code;.  The returned
-      &s.code;EntityInfoRec&e.code; should be freed with
-      &s.code;xfree()&e.code; when no longer needed.
-
-    </quote>
-    </quote>
-Several functions are provided to simplify resource registration:
-    <quote><p>
-    &s.code;Bool xf86IsEntityPrimary(int entityIndex)&e.code;
-    <quote><p>
-      This function returns &s.code;TRUE&e.code; if the entity referenced
-      by &s.code;entityIndex&e.code; is the primary display device (i.e.,
-      the one initialised at boot time and used in text mode).
-
-    </quote>
-
-    &s.code;Bool xf86IsScreenPrimary(int scrnIndex)&e.code;
-    <quote><p>
-      This function returns &s.code;TRUE&e.code; if the primary entity
-      is registered with the screen referenced by
-      &s.code;scrnIndex&e.code;.
-
-    </quote>
-
-    &s.code;pciVideoPtr xf86GetPciInfoForEntity(int entityIndex)&e.code;
-    <quote><p>
-      This function returns a pointer to the &s.code;pciVideoRec&e.code;
-      for the specified entity.  If the entity is not a PCI device,
-      &s.code;NULL&e.code; is returned.
-
-    </quote>
-    </quote>
-
-The primary function for registration of resources is:
-    <quote><p>
-    &s.code;resPtr xf86RegisterResources(int entityIndex, resList list,
-			&f.indent;int access)&e.code;
-    <quote><p>
-      This function tries to register the resources in
-      &s.code;list&e.code;.  If list is &s.code;NULL&e.code; it tries
-      to determine the resources automatically.  This only works for
-      entities that provide a generic way to read out the resource ranges
-      they decode.  So far this is only the case for PCI devices.  By
-      default the PCI resources are registered as shared
-      (&s.code;ResShared&e.code;) if the driver wants to set a different
-      access type it can do so by specifying the access flags in the
-      third argument.  A value of &s.code;0&e.code; means to use the
-      default settings.  If for any reason the resource broker is not
-      able to register some of the requested resources the function will
-      return a pointer to a list of the failed ones.  In this case the
-      driver may be able to move the resource to different locations.
-      In case of PCI bus entities this is done by passing the list of
-      failed resources to &s.code;xf86ReallocatePciResources()&e.code;.
-      When the registration succeeds, the return value is
-      &s.code;NULL&e.code;.
-
-    </quote>
-
-    &s.code;resPtr xf86ReallocatePciResources(int entityIndex, resPtr pRes)&e.code;
-    <quote><p>
-      This function takes a list of PCI resources that need to be
-      reallocated and returns &s.code;NULL&e.code when all relocations are
-      successful.
-      &s.code;xf86RegisterResources()&e.code; should be called again to
-      register the relocated resources with the broker.
-      If the reallocation fails, a list of the resources that could not be
-      relocated is returned.
-
-    </quote>
-    </quote>
-
-Two functions are provided to obtain a resource range of a given type:
-    <quote><p>
-    &s.code;resRange xf86GetBlock(long type, memType size,
-			&f.indent;memType window_start, memType window_end,
-			&f.indent;memType align_mask, resPtr avoid)&e.code;
-    <quote><p>
-      This function tries to find a block range of size
-      &s.code;size&e.code; and type &s.code;type&e.code; in a window
-      bound by &s.code;window_start&e.code; and &s.code;window_end&e.code;
-      with the alignment specified in &s.code;align_mask&e.code;.
-      Optionally a list of resource ranges which should be avoided within
-      the window can be supplied.  On failure a zero-length range of
-      type &s.code;ResEnd&e.code; will be returned.
-
-    </quote>
-    &s.code;resRange xf86GetSparse(long type, memType fixed_bits,
-			&f.indent;memType decode_mask, memType address_mask,
-			&f.indent;resPtr avoid)&e.code;
-    <quote><p>
-      This function is like the previous one, but attempts to find a
-      sparse range instead of a block range.  Here three values have to
-      be specified: the &s.code;address_mask&e.code; which marks all
-      bits of the mask part of the address, the &s.code;decode_mask&e.code;
-      which masks out the bits which are hardcoded and are therefore
-      not available for relocation and the values of the fixed bits.
-      The function tries to find a base that satisfies the given condition.
-      If the function fails it will return a zero range of type
-      &s.code;ResEnd&e.code;.  Optionally it might be passed a list of
-      resource ranges to avoid.
-
-    </quote>
-    </quote>
-
-Some PCI devices are broken in the sense that they return invalid size
-information for a certain resource.  In this case the driver can supply
-the correct size and make sure that the resource range allocated for
-the card is large enough to hold the address range decoded by the card.
-The function &s.code;xf86FixPciResource()&e.code; can be used to do this:
-    <quote><p>
-    &s.code;Bool xf86FixPciResource(int entityIndex, unsigned int prt,
-				&f.indent;CARD32 alignment, long type)&e.code;
-    <quote><p>
-      This function fixes a PCI resource allocation.  The
-      &s.code;prt&e.code; parameter contains the number of the PCI base
-      register that needs to be fixed (&s.code;0-5&e.code;, and
-      &s.code;6&e.code; for the BIOS base register).  The size is
-      specified by the alignment.  Since PCI resources need to span an
-      integral range of size &s.code;2^n&e.code;, the alignment also
-      specifies the number of addresses that will be decoded.  If the
-      driver specifies a type mask it can override the default type for
-      PCI resources which is &s.code;ResShared&e.code;.  The resource
-      broker needs to know that to find a matching resource range.  This
-      function should be called before calling
-      &s.code;xf86RegisterResources()&e.code;.  The return value is
-      &s.code;TRUE&e.code; when the function succeeds.
-
-    </quote>
-
-    &s.code;Bool xf86CheckPciMemBase(pciVideoPtr pPci, memType base)&e.code;
-    <quote><p>
-      This function checks that the memory base address specified matches
-      one of the PCI base address register values for the given PCI
-      device.  This is mostly used to check that an externally provided
-      base address (e.g., from a config file) matches an actual value
-      allocated to a device.
-
-    </quote>
-    </quote>
-
-The driver may replace the generic access control functions for an entity.
-This is done with the &s.code;xf86SetAccessFuncs()&e.code;:
-    <quote><p>
-    &s.code;void xf86SetAccessFuncs(EntityInfoPtr pEnt,
-                        &f.indent;xf86SetAccessFuncPtr funcs,
-			&f.indent;xf86SetAccessFuncPtr oldFuncs)&e.code;
-    <quote><p>
-     with:
-    </quote>
-
-    <verb>
-      typedef struct {
-          xf86AccessPtr mem;
-          xf86AccessPtr io;
-          xf86AccessPtr io_mem;
-      } xf86SetAccessFuncRec, *xf86SetAccessFuncPtr;
-    </verb>
-
-    <quote><p>
-      The driver can pass three functions: one for I/O access, one for
-      memory access and one for combined memory and I/O access.  If the
-      memory access and combined access functions are identical the
-      common level assumes that the memory access cannot be controlled
-      independently of I/O access, if the I/O access function and the
-      combined access functions are the same it is assumed that I/O can
-      not be controlled independently.  If memory and I/O have to be
-      controlled together all three values should be the same.  If a
-      non &s.code;NULL&e.code; value is passed as third argument it is
-      interpreted as an address where to store the old access record.
-      If the third argument is &s.code;NULL&e.code; it will be assumed
-      that the generic access should be enabled before replacing the
-      access functions.  Otherwise it will be disabled.  The driver may
-      enable them itself using the returned values.  It should do this
-      from its replacement access functions as the generic access may
-      be disabled by the common level on certain occasions.  If replacement
-      functions are specified they must control all resources of the
-      specific type registered for the entity.
-
-    </quote>
-    </quote>
-
-To find out if a specific resource range conflicts with another
-resource the &s.code;xf86ChkConflict()&e.code; function may be used:
-    <quote><p>
-    &s.code;memType xf86ChkConflict(resRange *rgp, int entityIndex)&e.code;
-    <quote><p>
-      This function checks if the resource range &s.code;rgp&e.code; of
-      for the specified entity conflicts with with another resource.
-      If a conflict is found, the address of the start of the conflict
-      is returned.  The return value is zero when there is no conflict.
-
-    </quote>
-    </quote>
-
-The OPERATING state properties of previously registered fixed resources
-can be set with the &s.code;xf86SetOperatingState()&e.code; function:
-    <quote><p>
-    &s.code;resPtr xf86SetOperatingState(resList list, int entityIndex,
-			&f.indent;int mask)&e.code;
-    <quote><p>
-      This function is used to set the status of a resource during
-      OPERATING state.  &s.code;list&e.code; holds a list to which
-      &s.code;mask&e.code; is to be applied.  The parameter
-      &s.code;mask&e.code; may have the value &s.code;ResUnusedOpr&e.code;
-      and &s.code;ResDisableOpr&e.code;.  The first one should be used
-      if a resource isn't used by the driver during OPERATING state
-      although it is decoded by the device, while the latter one indicates
-      that the resource is not decoded during OPERATING state.  Note
-      that the resource ranges have to match those specified during
-      registration.  If a range has been specified starting at
-      &s.code;A&e.code; and ending at &s.code;B&e.code; and suppose
-      &s.code;C&e.code; us a value satisfying
-      &s.code;A&nbsp;&lt;&nbsp;C&nbsp;&lt;&nbsp;B&e.code; one may not
-      specify the resource range &s.code;(A,B)&e.code; by splitting it
-      into two ranges &s.code;(A,C)&e.code; and &s.code;(C,B)&e.code;.
-
-    </quote>
-    </quote>
-
-The following two functions are provided for special cases:
-    <quote><p>
-    &s.code;void xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex)&e.code;
-    <quote><p>
-      This function may be used to remove an entity from a screen.  This
-      only makes sense if a screen has more than one entity assigned or
-      the screen is to be deleted.  No test is made if the screen has
-      any entities left.
-
-    </quote>
-
-    &s.code;void xf86DeallocateResourcesForEntity(int entityIndex, long type)&e.code;
-    <quote><p>
-      This function deallocates all resources of a given type registered
-      for a certain entity from the resource broker list.
-
-    </quote>
-    </quote>
-
-<sect2>ScreenInit Phase
-<p>
-
-All that is required in this phase is to setup the RAC flags.  Note that
-it is also permissible to set these flags up in the PreInit phase.  The
-RAC flags are held in the &s.code;racIoFlags&e.code; and &s.code;racMemFlags&e.code; fields of the
-&s.code;ScrnInfoRec&e.code; for each screen.  They specify which graphics operations
-might require the use of shared resources.  This can be specified
-separately for memory and I/O resources.  The available flags are defined
-in &s.code;rac/xf86RAC.h&e.code;.  They are:
-
-    &s.code;RAC_FB&e.code;
-	<quote>
-	for framebuffer operations (including hw acceleration)
-	</quote>
-    &s.code;RAC_CURSOR&e.code;
-	<quote>
-	for Cursor operations
-        (??? I'm not sure if we need this for SW cursor it depends
-         on which level the sw cursor is drawn)
-	</quote>
-    &s.code;RAC_COLORMAP&e.code;
-	<quote>
-	for colormap operations
-	</quote>
-    &s.code;RAC_VIEWPORT&e.code;
-	<quote>
-	for the call to &s.code;ChipAdjustFrame()&e.code; </quote>
-
-
-The flags are ORed together.
-
-<sect>Config file ``Option'' entries<label id="options">
-<p>
-
-Option entries are permitted in most sections and subsections of the
-config file.  There are two forms of option entries:
-
-<descrip>
-<tag>Option "option-name"</tag>
-	A boolean option.
-<tag>Option "option-name" "option-value"</tag>
-	An option with an arbitrary value.
-</descrip>
-
-The option entries are handled by the parser, and a list of the parsed
-options is included with each of the appropriate data structures that
-the drivers have access to.  The data structures used to hold the option
-information are opaque to the driver, and a driver must not access the
-option data directly.  Instead, the common layer provides a set of
-functions that may be used to access, check and manipulate the option
-data.
-
-First, the low level option handling functions.  In most cases drivers
-would not need to use these directly.
-
-    <quote><p>
-    &s.code;pointer xf86FindOption(pointer options, const char *name)&e.code;
-    <quote><p>
-      Takes a list of options and an option name, and returns a handle
-      for the first option entry in the list matching the name.  Returns
-      &s.code;NULL&e.code; if no match is found.
-
-    </quote>
-
-    &s.code;char *xf86FindOptionValue(pointer options, const char *name)&e.code;
-    <quote><p>
-      Takes a list of options and an option name, and returns the value
-      associated with the first option entry in the list matching the
-      name.  If the matching option has no value, an empty string
-      (&s.code;""&e.code;) is returned.  Returns &s.code;NULL&e.code;
-      if no match is found.
-
-    </quote>
-
-    &s.code;void xf86MarkOptionUsed(pointer option)&e.code;
-    <quote><p>
-      Takes a handle for an option, and marks that option as used.
-
-    </quote>
-
-    &s.code;void xf86MarkOptionUsedByName(pointer options, const char *name)&e.code;
-    <quote><p>
-      Takes a list of options and an option name and marks the first
-      option entry in the list matching the name as used.
-
-    </quote>
-    </quote>
-
-
-Next, the higher level functions that most drivers would use.
-    <quote><p>
-    &s.code;void xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts)&e.code;
-    <quote><p>
-      Collect the options from each of the config file sections used by
-      the screen (&s.code;pScrn&e.code;) and return the merged list as
-      &s.code;pScrn-&gt;options&e.code;.  This function requires that
-      &s.code;pScrn-&gt;confScreen&e.code;, &s.code;pScrn-&gt;display&e.code;,
-      &s.code;pScrn-&gt;monitor&e.code;,
-      &s.code;pScrn-&gt;numEntities&e.code;, and
-      &s.code;pScrn-&gt;entityList&e.code; are initialised.
-      &s.code;extraOpts&e.code; may optionally be set to an additional
-      list of options to be combined with the others.  The order of
-      precedence for options is &s.code;extraOpts&e.code;, display,
-      confScreen, monitor, device.
-
-    </quote>
-
-    &s.code;void xf86ProcessOptions(int scrnIndex, pointer options,
-			&f.indent;OptionInfoPtr optinfo)&e.code;
-    <quote><p>
-      Processes a list of options according to the information in the
-      array of &s.code;OptionInfoRecs&e.code; (&s.code;optinfo&e.code;).
-      The resulting information is stored in the &s.code;value&e.code;
-      fields of the appropriate &s.code;optinfo&e.code; entries.  The
-      &s.code;found&e.code; fields are set to &s.code;TRUE&e.code;
-      when an option with a value of the correct type if found, and
-      &s.code;FALSE&e.code; otherwise.  The &s.code;type&e.code; field
-      is used to determine the expected value type for each option.
-      Each option in the list of options for which there is a name match
-      (but not necessarily a value type match) is marked as used.
-      Warning messages are printed when option values don't match the
-      types specified in the optinfo data.
-
-      NOTE: If this function is called before a driver's screen number
-      is known (e.g., from the &s.code;ChipProbe()&e.code; function) a
-      &s.code;scrnIndex&e.code; value of &s.code;-1&e.code; should be
-      used.
-
-      NOTE 2: Given that this function stores into the
-      &s.code;OptionInfoRecs&e.code; pointed to by &s.code;optinfo&e.code,
-      the caller should ensure the &s.code;OptionInfoRecs&e.code; are
-      (re-)initialised before the call, especially if the caller expects
-      to use the predefined option values as defaults.
-
-      The &s.code;OptionInfoRec&e.code; is defined as follows:
-
-      <verb>
-      typedef struct {
-          double freq;
-          int units;
-      } OptFrequency;
-
-      typedef union {
-          unsigned long       num;
-          char *              str;
-          double              realnum;
-          Bool                bool;
-          OptFrequency        freq;
-      } ValueUnion;
-
-      typedef enum {
-          OPTV_NONE = 0,
-          OPTV_INTEGER,
-          OPTV_STRING,  /* a non-empty string */
-          OPTV_ANYSTR,  /* Any string, including an empty one */
-          OPTV_REAL,
-          OPTV_BOOLEAN,
-          OPTV_PERCENT,
-          OPTV_FREQ
-      } OptionValueType;
-
-      typedef enum {
-          OPTUNITS_HZ = 1,
-          OPTUNITS_KHZ,
-          OPTUNITS_MHZ
-      } OptFreqUnits;
-
-      typedef struct {
-          int                 token;
-          const char*         name;
-          OptionValueType     type;
-          ValueUnion          value;
-          Bool                found;
-      } OptionInfoRec, *OptionInfoPtr;
-      </verb>
-
-      &s.code;OPTV_FREQ&e.code; can be used for options values that are
-      frequencies.  These values are a floating point number with an
-      optional unit name appended.  The unit name can be one of "Hz",
-      "kHz", "k", "MHz", "M".  The multiplier associated with the unit
-      is stored in &s.code;freq.units&e.code;, and the scaled frequency
-      is stored in &s.code;freq.freq&e.code;.  When no unit is specified,
-      &s.code;freq.units&e.code; is set to &s.code;0&e.code;, and
-      &s.code;freq.freq&e.code; is unscaled.
-
-      &s.code;OPTV_PERCENT&e.code; can be used for option values that are
-      specified in percent (e.g. "20%"). These values are a floating point
-      number with a percent sign appended. If the percent sign is missing,
-      the parser will fail to match the value.
-
-      Typical usage is to setup an array of
-      &s.code;OptionInfoRecs&e.code; with all fields initialised.
-      The &s.code;value&e.code; and &s.code;found&e.code; fields get
-      set by &s.code;xf86ProcessOptions()&e.code;.  For cases where the
-      value parsing is more complex, the driver should specify
-      &s.code;OPTV_STRING&e.code;, and parse the string itself.  An
-      example of using this option handling is included in the
-      <ref id="sample" name="Sample Driver"> section.
-
-    </quote>
-
-    &s.code;void xf86ShowUnusedOptions(int scrnIndex, pointer options)&e.code;
-    <quote><p>
-      Prints out warning messages for each option in the list of options
-      that isn't marked as used.  This is intended to show options that
-      the driver hasn't recognised.  It would normally be called near
-      the end of the &s.code;ChipScreenInit()&e.code; function, but only
-      when &s.code;serverGeneration&nbsp;==&nbsp;1&e.code;.
-
-    </quote>
-
-    &s.code;OptionInfoPtr xf86TokenToOptinfo(const OptionInfoRec *table,
-			&f.indent;int token)&e.code;
-
-    <quote><p>
-      Returns a pointer to the &s.code;OptionInfoRec&e.code; in
-      &s.code;table&e.code; with a token field matching
-      &s.code;token&e.code;.  Returns &s.code;NULL&e.code; if no match
-      is found.
-
-    </quote>
-
-    &s.code;Bool xf86IsOptionSet(const OptionInfoRec *table, int token)&e.code;
-    <quote><p>
-      Returns the &s.code;found&e.code; field of the
-      &s.code;OptionInfoRec&e.code; in &s.code;table&e.code; with a
-      &s.code;token&e.code; field matching &s.code;token&e.code;.  This
-      can be used for options of all types.  Note that for options of
-      type &s.code;OPTV_BOOLEAN&e.code;, it isn't sufficient to check
-      this to determine the value of the option.  Returns
-      &s.code;FALSE&e.code; if no match is found.
-
-    </quote>
-
-    &s.code;char *xf86GetOptValString(const OptionInfoRec *table, int token)&e.code;
-    <quote><p>
-      Returns the &s.code;value.str&e.code; field of the
-      &s.code;OptionInfoRec&e.code; in &s.code;table&e.code; with a
-      token field matching &s.code;token&e.code;.  Returns
-      &s.code;NULL&e.code; if no match is found.
-
-    </quote>
-
-    &s.code;Bool xf86GetOptValInteger(const OptionInfoRec *table, int token,
-			&f.indent;int *value)&e.code;
-    <quote><p>
-      Returns via &s.code;*value&e.code; the &s.code;value.num&e.code;
-      field of the &s.code;OptionInfoRec&e.code; in &s.code;table&e.code;
-      with a &s.code;token&e.code; field matching &s.code;token&e.code;.
-      &s.code;*value&e.code; is only changed when a match is found so
-      it can be safely initialised with a default prior to calling this
-      function.  The function return value is as for
-      &s.code;xf86IsOptionSet()&e.code;.
-
-    </quote>
-
-    &s.code;Bool xf86GetOptValULong(const OptionInfoRec *table, int token,
-			&f.indent;unsigned long *value)&e.code;
-    <quote><p>
-      Like &s.code;xf86GetOptValInteger()&e.code;, except the value is
-      treated as an &s.code;unsigned long&e.code;.
-
-    </quote>
-
-    &s.code;Bool xf86GetOptValReal(const OptionInfoRec *table, int token,
-			&f.indent;double *value)&e.code;
-    <quote><p>
-      Like &s.code;xf86GetOptValInteger()&e.code;, except that
-      &s.code;value.realnum&e.code; is used.
-
-    </quote>
-
-    &s.code;Bool xf86GetOptValFreq(const OptionInfoRec *table, int token,
-			&f.indent;OptFreqUnits expectedUnits, double *value)&e.code;
-    <quote><p>
-      Like &s.code;xf86GetOptValInteger()&e.code;, except that the
-      &s.code;value.freq&e.code; data is returned.  The frequency value
-      is scaled to the units indicated by &s.code;expectedUnits&e.code;.
-      The scaling is exact when the units were specified explicitly in
-      the option's value.  Otherwise, the &s.code;expectedUnits&e.code;
-      field is used as a hint when doing the scaling.  In this case,
-      values larger than &s.code;1000&e.code; are assumed to have be
-      specified in the next smallest units.  For example, if the Option
-      value is "10000" and expectedUnits is &s.code;OPTUNITS_MHZ&e.code;,
-      the value returned is &s.code;10&e.code;.
-
-    </quote>
-
-    &s.code;Bool xf86GetOptValBool(const OptionInfoRec *table, int token, Bool *value)&e.code;
-    <quote><p>
-      This function is used to check boolean options
-      (&s.code;OPTV_BOOLEAN&e.code;).  If the function return value is
-      &s.code;FALSE&e.code;, it means the option wasn't set.  Otherwise
-      &s.code;*value&e.code; is set to the boolean value indicated by
-      the option's value.  No option &s.code;value&e.code; is interpreted
-      as &s.code;TRUE&e.code;.  Option values meaning &s.code;TRUE&e.code;
-      are "1", "yes", "on", "true", and option values meaning
-      &s.code;FALSE&e.code; are "0", "no", "off", "false".  Option names
-      both with the "no" prefix in their names, and with that prefix
-      removed are also checked and handled in the obvious way.
-      &s.code;*value&e.code; is not changed when the option isn't present.
-      It should normally be set to a default value before calling this
-      function.
-
-    </quote>
-
-    &s.code;Bool xf86ReturnOptValBool(const OptionInfoRec *table, int token, Bool def)&e.code;
-    <quote><p>
-      This function is used to check boolean options
-      (&s.code;OPTV_BOOLEAN&e.code;).  If the option is set, its value
-      is returned.  If the options is not set, the default value specified
-      by &s.code;def&e.code; is returned.  The option interpretation is
-      the same as for &s.code;xf86GetOptValBool()&e.code;.
-
-    </quote>
-
-    &s.code;int xf86NameCmp(const char *s1, const char *s2)&e.code;
-    <quote><p>
-      This function should be used when comparing strings from the config
-      file with expected values.  It works like &s.code;strcmp()&e.code;,
-      but is not case sensitive and space, tab, and `<tt>_</tt>' characters
-      are ignored in the comparison.  The use of this function isn't
-      restricted to parsing option values.  It may be used anywhere
-      where this functionality required.
-
-    </quote>
-    </quote>
-
-<sect>Modules, Drivers, Include Files and Interface Issues
-<p>
-
-NOTE: this section is incomplete.
-
-
-<sect1>Include files
-<p>
-
-The following include files are typically required by video drivers:
-
-  <quote><p>
-  All drivers should include these:
-  <quote>
-    &s.code;"xf86.h"&nl;
-    "xf86_OSproc.h"&nl;
-    "xf86_ansic.h"&nl;
-    "xf86Resources.h"&e.code;
-  </quote>
-  Wherever inb/outb (and related things) are used the following should be
-  included:
-  <quote>
-    &s.code;"compiler.h"&e.code;
-  </quote>
-  Note: in drivers, this must be included after &s.code;"xf86_ansic.h"&e.code;.
-
-  Drivers that need to access PCI vendor/device definitions need this:
-  <quote>
-    &s.code;"xf86PciInfo.h"&e.code;
-  </quote>
-
-  Drivers that need to access the PCI config space need this:
-  <quote>
-    &s.code;"xf86Pci.h"&e.code;
-  </quote>
-
-  Drivers that initialise a SW cursor need this:
-  <quote>
-    &s.code;"mipointer.h"&e.code;
-  </quote>
-
-  All drivers implementing backing store need this:
-  <quote>
-    &s.code;"mibstore.h"&e.code;
-  </quote>
-
-  All drivers using the mi colourmap code need this:
-  <quote>
-    &s.code;"micmap.h"&e.code;
-  </quote>
-
-  If a driver uses the vgahw module, it needs this:
-  <quote>
-    &s.code;"vgaHW.h"&e.code;
-  </quote>
-
-  Drivers supporting VGA or Hercules monochrome screens need:
-  <quote>
-    &s.code;"xf1bpp.h"&e.code;
-  </quote>
-
-  Drivers supporting VGA or EGC 16-colour screens need:
-  <quote>
-    &s.code;"xf4bpp.h"&e.code;
-  </quote>
-
-  Drivers using cfb need:
-  <quote>
-    &s.code;#define PSZ 8&nl;
-    #include "cfb.h"&nl;
-    #undef PSZ&e.code;
-  </quote>
-
-  Drivers supporting bpp 16, 24 or 32 with cfb need one or more of:
-  <quote>
-    &s.code;"cfb16.h"&nl;
-    "cfb24.h"&nl;
-    "cfb32.h"&e.code;
-  </quote>
-
-  If a driver uses XAA, it needs these:
-  <quote>
-    &s.code;"xaa.h"&nl;
-    "xaalocal.h"&e.code;
-  </quote>
-
-  If a driver uses the fb manager, it needs this:
-  <quote>
-    &s.code;"xf86fbman.h"&e.code;
-  </quote>
-  </quote>
-
-Non-driver modules should include &s.code;"xf86_ansic.h"&e.code; to get the correct
-wrapping of ANSI C/libc functions.
-
-All modules must NOT include any system include files, or the following:
-
- <quote>
-    &s.code;"xf86Priv.h"&nl;
-    "xf86Privstr.h"&nl;
-    "xf86_OSlib.h"&nl;
-    "Xos.h"&e.code;
- </quote>
-
-In addition, "xf86_libc.h" must not be included explicitly.  It is
-included implicitly by "xf86_ansic.h".
-
-
-<sect>Offscreen Memory Manager
-<p>
-
-Management of offscreen video memory may be handled by the XFree86
-framebuffer manager.  Once the offscreen memory manager is running,
-drivers or extensions may allocate, free or resize areas of offscreen
-video memory using the following functions (definitions taken from
-&s.code;xf86fbman.h&e.code;):
-
-<code>
-    typedef struct _FBArea {
-        ScreenPtr    pScreen;
-        BoxRec       box;
-        int          granularity;
-        void         (*MoveAreaCallback)(struct _FBArea*, struct _FBArea*)
-        void         (*RemoveAreaCallback)(struct _FBArea*)
-        DevUnion     devPrivate;
-    } FBArea, *FBAreaPtr;
-
-    typedef void (*MoveAreaCallbackProcPtr)(FBAreaPtr from, FBAreaPtr to)
-    typedef void (*RemoveAreaCallbackProcPtr)(FBAreaPtr)
-
-    FBAreaPtr xf86AllocateOffscreenArea (
-        ScreenPtr pScreen,
-        int width, int height,
-        int granularity,
-        MoveAreaCallbackProcPtr MoveAreaCallback,
-        RemoveAreaCallbackProcPtr RemoveAreaCallback,
-        pointer privData
-    )
-
-    void xf86FreeOffscreenArea (FBAreaPtr area)
-
-    Bool xf86ResizeOffscreenArea (
-	FBAreaPtr area
-	int w, int h
-    )
-</code>
-
-The function:
-<quote>
-    &s.code;Bool xf86FBManagerRunning(ScreenPtr pScreen)&e.code;
-</quote>
-
-can be used by an extension to check if the driver has initialized
-the memory manager.  The manager is not available if this returns
-&s.code;FALSE&e.code; and the functions above will all fail.
-
-
-&s.code;xf86AllocateOffscreenArea()&e.code; can be used to request a
-rectangle of dimensions &s.code;width&e.code; x &s.code;height&e.code;
-(in pixels) from unused offscreen memory.  &s.code;granularity&e.code;
-specifies that the leftmost edge of the rectangle must lie on some
-multiple of &s.code;granularity&e.code; pixels.  A granularity of zero
-means the same thing as a granularity of one - no alignment preference.
-A &s.code;MoveAreaCallback&e.code; can be provided to notify the requester
-when the offscreen area is moved.  If no &s.code;MoveAreaCallback&e.code;
-is supplied then the area is considered to be immovable.  The
-&s.code;privData&e.code; field will be stored in the manager's internal
-structure for that allocated area and will be returned to the requester
-in the &s.code;FBArea&e.code; passed via the
-&s.code;MoveAreaCallback&e.code;.  An optional
-&s.code;RemoveAreaCallback&e.code; is provided.  If the driver provides
-this it indicates that the area should be allocated with a lower priority.
-Such an area may be removed when a higher priority request (one that
-doesn't have a &s.code;RemoveAreaCallback&e.code;) is made.  When this
-function is called, the driver will have an opportunity to do whatever
-cleanup it needs to do to deal with the loss of the area, but it must
-finish its cleanup before the function exits since the offscreen memory
-manager will free the area immediately after.
-
-&s.code;xf86AllocateOffscreenArea()&e.code; returns &s.code;NULL&e.code;
-if it was unable to allocate the requested area.  When no longer needed,
-areas should be freed with &s.code;xf86FreeOffscreenArea()&e.code;.
-
-&s.code;xf86ResizeOffscreenArea()&e.code; resizes an existing
-&s.code;FBArea&e.code;.  &s.code;xf86ResizeOffscreenArea()&e.code;
-returns &s.code;TRUE&e.code; if the resize was successful.  If
-&s.code;xf86ResizeOffscreenArea()&e.code; returns &s.code;FALSE&e.code;,
-the original &s.code;FBArea&e.code; is left unmodified.  Resizing an
-area maintains the area's original &s.code;granularity&e.code;,
-&s.code;devPrivate&e.code;, and &s.code;MoveAreaCallback&e.code;.
-&s.code;xf86ResizeOffscreenArea()&e.code; has considerably less overhead
-than freeing the old area then reallocating the new size, so it should
-be used whenever possible.
-
-The function:
-  <quote>
-   &s.code;Bool xf86QueryLargestOffscreenArea(
-     &f.indent;ScreenPtr pScreen,
-     &f.indent;int *width, int *height,
-     &f.indent;int granularity,
-     &f.indent;int preferences,
-     &f.indent;int priority
-   &nl)&e.code;
-  </quote>
-
-is provided to query the width and height of the largest single
-&s.code;FBArea&e.code; allocatable given a particular priority.
-&s.code;preferences&e.code; can be one of the following to indicate
-whether width, height or area should be considered when determining
-which is the largest single &s.code;FBArea&e.code; available.
-
-  <quote>
-  &s.code;FAVOR_AREA_THEN_WIDTH&nl;
-  FAVOR_AREA_THEN_HEIGHT&nl;
-  FAVOR_WIDTH_THEN_AREA&nl;
-  FAVOR_HEIGHT_THEN_AREA&e.code;
-  </quote>
-
-&s.code;priority&e.code; is one of the following:
-
-  <quote><p>
-  &s.code;PRIORITY_LOW&e.code;
-  <quote><p>
-     Return the largest block available without stealing anyone else's
-     space.  This corresponds to the priority of allocating a
-     &s.code;FBArea&e.code; when a &s.code;RemoveAreaCallback&e.code;
-     is provided.
-
-  </quote>
-  &s.code;PRIORITY_NORMAL&e.code;
-  <quote><p>
-     Return the largest block available if it is acceptable to steal a
-     lower priority area from someone.  This corresponds to the priority
-     of allocating a &s.code;FBArea&e.code; without providing a
-     &s.code;RemoveAreaCallback&e.code;.
-
-  </quote>
-  &s.code;PRIORITY_EXTREME&e.code;
-  <quote><p>
-     Return the largest block available if all &s.code;FBAreas&e.code;
-     that aren't locked down were expunged from memory first.  This
-     corresponds to any allocation made directly after a call to
-     &s.code;xf86PurgeUnlockedOffscreenAreas()&e.code;.
-
-  </quote>
-  </quote>
-
-
-The function:
-
-  <quote>
-    &s.code;Bool xf86PurgeUnlockedOffscreenAreas(ScreenPtr pScreen)&e.code;
-  </quote>
-
-is provided as an extreme method to free up offscreen memory.  This
-will remove all removable &s.code;FBArea&e.code; allocations.
-
-
-Initialization of the XFree86 framebuffer manager is done via
-
-  <quote>
-    &s.code;Bool xf86InitFBManager(ScreenPtr pScreen, BoxPtr FullBox)&e.code;
-  </quote>
-
-&s.code;FullBox&e.code; represents the area of the framebuffer that the
-manager is allowed to manage.  This is typically a box with a width of
-&s.code;pScrn-&gt;displayWidth&e.code; and a height of as many lines as
-can be fit within the total video memory, however, the driver can reserve
-areas at the extremities by passing a smaller area to the manager.
-
-&s.code;xf86InitFBManager()&e.code; must be called before XAA is
-initialized since XAA uses the manager for it's pixmap cache.
-
-An alternative function is provided to allow the driver to initialize
-the framebuffer manager with a Region rather than a box.
-
-  <quote>
-   &s.code;Bool xf86InitFBManagerRegion(ScreenPtr pScreen,
-	&f.indent;RegionPtr FullRegion)&e.code;
-  </quote>
-
-&s.code;xf86InitFBManagerRegion()&e.code;, unlike
-&s.code;xf86InitFBManager()&e.code;, does not remove the area used for
-the visible screen so that area should not be included in the region
-passed to the function.  &s.code;xf86InitFBManagerRegion()&e.code; is
-useful when non-contiguous areas are available to be managed, and is
-required when multiple framebuffers are stored in video memory (as in
-the case where an overlay of a different depth is stored as a second
-framebuffer in offscreen memory).
-
-
-<sect>Colormap Handling<label id="cmap">
-<p>
-
-A generic colormap handling layer is provided within the XFree86 common
-layer.  This layer takes care of most of the details, and only requires
-a function from the driver that loads the hardware palette when required.
-To use the colormap layer, a driver calls the
-&s.code;xf86HandleColormaps()&e.code; function.
-
-    <quote><p>
-    &s.code;Bool xf86HandleColormaps(ScreenPtr pScreen, int maxColors,
-		&f.indent;int sigRGBbits, LoadPaletteFuncPtr loadPalette,
-		&f.indent;SetOverscanFuncPtr setOverscan,
-		unsigned int flags)&e.code;
-    <quote><p>
-      This function must be called after the default colormap has been
-      initialised.  The &s.code;pScrn-&gt;gamma&e.code; field must also
-      be initialised, preferably by calling &s.code;xf86SetGamma()&e.code;.
-      &s.code;maxColors&e.code; is the number of entries in the palette.
-      &s.code;sigRGBbits&e.code; is the size in bits of each color
-      component in the DAC's palette.  &s.code;loadPalette&e.code;
-      is a driver-provided function for loading a colormap into the
-      hardware, and is described below.  &s.code;setOverscan&e.code; is
-      an optional function that may be provided when the overscan color
-      is an index from the standard LUT and when it needs to be adjusted
-      to keep it as close to black as possible.  The
-      &s.code;setOverscan&e.code; function programs the overscan index.
-      It shouldn't normally be used for depths other than 8.
-      &s.code;setOverscan&e.code; should be set to &s.code;NULL&e.code;
-      when it isn't needed.  &s.code;flags&e.code; may be set to the
-      following (which may be ORed together):
-
-      &s.code;CMAP_PALETTED_TRUECOLOR&e.code;
-      <quote><p>
-				    the TrueColor visual is paletted and is
-				    just a special case of DirectColor.
-				    This flag is only valid for
-				    &s.code;bpp&nbsp;&gt;&nbsp;8&e.code;.
-
-      </quote>
-
-      &s.code;CMAP_RELOAD_ON_MODE_SWITCH&e.code;
-      <quote><p>
-				    reload the colormap automatically
-                                    after mode switches.  This is useful
-                                    for when the driver is resetting the
-                                    hardware during mode switches and
-                                    corrupting or erasing the hardware
-                                    palette.
-
-      </quote>
-
-      &s.code;CMAP_LOAD_EVEN_IF_OFFSCREEN&e.code;
-      <quote><p>
-				    reload the colormap even if the screen
-				    is switched out of the server's VC.
-				    The palette is <it>not</it> reloaded when
-				    the screen is switched back in, nor after
-				    mode switches.  This is useful when the
-				    driver needs to keep track of palette
-				    changes.
-
-      </quote>
-
-      The colormap layer normally reloads the palette after VT enters so it
-      is not necessary for the driver to save and restore the palette
-      when switching VTs.  The driver must, however, still save the
-      initial palette during server start up and restore it during
-      server exit.
-
-    </quote>
-
-    &s.code;void LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
-		&f.indent;LOCO *colors, VisualPtr pVisual)&e.code;
-    <quote><p>
-      &s.code;LoadPalette()&e.code; is a driver-provided function for
-      loading a colormap into hardware.  &s.code;colors&e.code; is the
-      array of RGB values that represent the full colormap.
-      &s.code;indices&e.code; is a list of index values into the colors
-      array.  These indices indicate the entries that need to be updated.
-      &s.code;numColors&e.code; is the number of the indices to be
-      updated.
-
-    </quote>
-
-    &s.code;void SetOverscan(ScrnInfoPtr pScrn, int overscan)&e.code;
-    <quote><p>
-      &s.code;SetOverscan()&e.code; is a driver-provided function for
-      programming the &s.code;overscan&e.code; index.  As described
-      above, it is normally only appropriate for LUT modes where all
-      colormap entries are available for the display, but where one of
-      them is also used for the overscan (typically 8bpp for VGA compatible
-      LUTs).  It isn't required in cases where the overscan area is
-      never visible.
-
-    </quote>
-    </quote>
-
-
-<sect>DPMS Extension
-<p>
-
-Support code for the DPMS extension is included in the XFree86 common layer.
-This code provides an interface between the main extension code, and a means
-for drivers to initialise DPMS when they support it.  One function is
-available to drivers to do this initialisation, and it is always available,
-even when the DPMS extension is not supported by the core server (in
-which case it returns a failure result).
-
-
-    <quote><p>
-    &s.code;Bool xf86DPMSInit(ScreenPtr pScreen, DPMSSetProcPtr set, int flags)&e.code;
-    <quote><p>
-      This function registers a driver's DPMS level programming function
-      &s.code;set&e.code;.  It also checks
-      &s.code;pScrn-&gt;options&e.code; for the "dpms" option, and when
-      present marks DPMS as being enabled for that screen.  The
-      &s.code;set&e.code; function is called whenever the DPMS level
-      changes, and is used to program the requested level.
-      &s.code;flags&e.code; is currently not used, and should be
-      &s.code;0&e.code;.  If the initialisation fails for any reason,
-      including when there is no DPMS support in the core server, the
-      function returns &s.code;FALSE&e.code;.
-
-    </quote>
-    </quote>
-
-
-Drivers that implement DPMS support must provide the following function,
-that gets called when the DPMS level is changed:
-
-
-    <quote><p>
-    &s.code;void ChipDPMSSet(ScrnInfoPtr pScrn, int level, int flags)&e.code;
-    <quote><p>
-      Program the DPMS level specified by &s.code;level&e.code;.  Valid
-      values of &s.code;level&e.code; are &s.code;DPMSModeOn&e.code;,
-      &s.code;DPMSModeStandby&e.code;, &s.code;DPMSModeSuspend&e.code;,
-      &s.code;DPMSModeOff&e.code;.  These values are defined in
-      &s.code;"extensions/dpms.h"&e.code;.
-
-    </quote>
-    </quote>
-
-
-<sect>DGA Extension
-<p>
-
-Drivers can support the XFree86 Direct Graphics Architecture (DGA) by
-filling out a structure of function pointers and a list of modes and
-passing them to DGAInit.
-
-    <quote><p>
-    &s.code;Bool DGAInit(ScreenPtr pScreen, DGAFunctionPtr funcs,
-			&f.indent;DGAModePtr modes, int num)&e.code;
-    <quote><p>
-    <verb>
-/** The DGAModeRec **/
-
-typedef struct {
-  int num;
-  DisplayModePtr mode;
-  int flags;
-  int imageWidth;
-  int imageHeight;
-  int pixmapWidth;
-  int pixmapHeight;
-  int bytesPerScanline;
-  int byteOrder;
-  int depth;
-  int bitsPerPixel;
-  unsigned long red_mask;
-  unsigned long green_mask;
-  unsigned long blue_mask;
-  int viewportWidth;
-  int viewportHeight;
-  int xViewportStep;
-  int yViewportStep;
-  int maxViewportX;
-  int maxViewportY;
-  int viewportFlags;
-  int offset;
-  unsigned char *address;
-  int reserved1;
-  int reserved2;
-} DGAModeRec, *DGAModePtr;
-</verb>
-
-      &s.code;num&e.code;
-	<quote>
-	 Can be ignored.  The DGA DDX will assign these numbers.
-	</quote>
-
-      &s.code;mode&e.code;
-	<quote>
-	A pointer to the &s.code;DisplayModeRec&e.code; for this mode.
-	</quote>
-
-      &s.code;flags&e.code;
-	<quote><p>
-	The following flags are defined and may be OR'd together:
-
-        &s.code;DGA_CONCURRENT_ACCESS&e.code;
-	    <quote><p>
-            Indicates that the driver supports concurrent graphics
-            accelerator and linear framebuffer access.
-
-	    </quote>
-
-        &s.code;DGA_FILL_RECT&nl;
-	DGA_BLIT_RECT&nl;
-        DGA_BLIT_RECT_TRANS&e.code;
-	    <quote><p>
-	    Indicates that the driver supports the FillRect, BlitRect
-            or BlitTransRect functions in this mode.
-
-	    </quote>
-
-        &s.code;DGA_PIXMAP_AVAILABLE&e.code;
-	    <quote><p>
-	    Indicates that Xlib may be used on the framebuffer.
-            This flag will usually be set unless the driver wishes
-            to prohibit this for some reason.
-
-	    </quote>
-
-        &s.code;DGA_INTERLACED&nl;
-        DGA_DOUBLESCAN&e.code;
-	    <quote><p>
-            Indicates that these are interlaced or double scan modes.
-
-	    </quote>
-	</quote>
-
-      &s.code;imageWidth&nl;
-      imageHeight&e.code;
-	<quote><p>
-		    These are the dimensions of the linear framebuffer
-                     accessible by the client.
-
-	</quote>
-
-      &s.code;pixmapWidth&nl;
-      pixmapHeight&e.code;
-	<quote><p>
-		     These are the dimensions of the area of the
-                     framebuffer accessible by the graphics accelerator.
-
-	</quote>
-
-      &s.code;bytesPerScanline&e.code;
-	<quote><p>
-		      Pitch of the framebuffer in bytes.
-
-	</quote>
-
-      &s.code;byteOrder&e.code;
-	<quote><p>
-		     Usually the same as
-		     &s.code;pScrn-&gt;imageByteOrder&e.code;.
-
-	</quote>
-
-      &s.code;depth&e.code;
-	<quote><p>
-		     The depth of the framebuffer in this mode.
-
-	</quote>
-
-      &s.code;bitsPerPixel&e.code;
-	<quote><p>
-		      The number of bits per pixel in this mode.
-
-	</quote>
-
-      &s.code;red_mask&nl;
-      green_mask&nl;
-      blue_mask&e.code;
-	<quote><p>
-		      The RGB masks for this mode, if applicable.
-
-	</quote>
-
-      &s.code;viewportWidth&nl;
-      viewportHeight&e.code;
-	<quote><p>
-		      Dimensions of the visible part of the framebuffer.
-		      Usually &s.code;mode-&gt;HDisplay&e.code; and
-		      &s.code;mode-&gt;VDisplay&e.code;.
-
-	</quote>
-
-      &s.code;xViewportStep&nl;
-      yViewportStep&e.code;
-	<quote><p>
-		     The granularity of x and y viewport positions that
-                     the driver supports in this mode.
-
-	</quote>
-
-      &s.code;maxViewportX&nl;
-      maxViewportY&e.code;
-	<quote><p>
-		      The maximum viewport position supported by the
-                       driver in this mode.
-
-	</quote>
-
-      &s.code;viewportFlags&e.code;
-	<quote><p>
-		     The following may be OR'd together:
-
-       &s.code;DGA_FLIP_IMMEDIATE&e.code;
-	    <quote><p>
-		The driver supports immediate viewport changes.
-
-	    </quote>
-       &s.code;DGA_FLIP_RETRACE&e.code;
-	    <quote<p>
-		The driver supports viewport changes at retrace.
-
-	    </quote>
-	</quote>
-
-      &s.code;offset&e.code;
-	<quote><p>
-	        The offset into the linear framebuffer that corresponds to
-                pixel (0,0) for this mode.
-
-	</quote>
-
-      &s.code;address&e.code;
-        <quote><p>
-                The virtual address of the framebuffer as mapped by the driver.
-                This is needed when DGA_PIXMAP_AVAILABLE is set.
-
-        </quote>
-
-      <verb>
-/** The DGAFunctionRec **/
-
-typedef struct {
-  Bool (*OpenFramebuffer)(
-       ScrnInfoPtr pScrn,
-       char **name,
-       unsigned char **mem,
-       int *size,
-       int *offset,
-       int *extra
-  );
-  void (*CloseFramebuffer)(ScrnInfoPtr pScrn);
-  Bool (*SetMode)(ScrnInfoPtr pScrn, DGAModePtr pMode);
-  void (*SetViewport)(ScrnInfoPtr pScrn, int x, int y, int flags);
-  int  (*GetViewport)(ScrnInfoPtr pScrn);
-  void (*Sync)(ScrnInfoPtr);
-  void (*FillRect)(
-       ScrnInfoPtr pScrn,
-       int x, int y, int w, int h,
-       unsigned long color
-  );
-  void (*BlitRect)(
-       ScrnInfoPtr pScrn,
-       int srcx, int srcy,
-       int w, int h,
-       int dstx, int dsty
-  );
-  void (*BlitTransRect)(
-       ScrnInfoPtr pScrn,
-       int srcx, int srcy,
-       int w, int h,
-       int dstx, int dsty,
-       unsigned long color
-  );
-} DGAFunctionRec, *DGAFunctionPtr;
-</verb>
-
-    </quote>
-
-    &s.code;Bool OpenFramebuffer (pScrn, name, mem, size, offset, extra)&e.code;
-    <quote><p>
-      &s.code;OpenFramebuffer()&e.code; should pass the client everything
-      it needs to know to be able to open the framebuffer.  These
-      parameters are OS specific and their meanings are to be interpreted
-      by an OS specific client library.
-
-      &s.code;name&e.code;
-	<quote><p>
-	      The name of the device to open or &s.code;NULL&e.code; if
-	      there is no special device to open.  A &s.code;NULL&e.code;
-	      name tells the client that it should open whatever device
-	      one would usually open to access physical memory.
-
-	</quote>
-      &s.code;mem&e.code;
-	<quote><p>
-	       The physical address of the start of the framebuffer.
-
-	</quote>
-      &s.code;size&e.code;
-	<quote><p>
-	      The size of the framebuffer in bytes.
-
-	</quote>
-      &s.code;offset&e.code;
-	<quote><p>
-	      Any offset into the device, if applicable.
-
-	</quote>
-      &s.code;flags&e.code;
-	<quote><p>
-	      Any additional information that the client may need.
-	      Currently, only the &s.code;DGA_NEED_ROOT&e.code; flag is
-	      defined.
-
-	</quote>
-   </quote>
-
-    &s.code;void CloseFramebuffer (pScrn)&e.code;
-    <quote><p>
-      &s.code;CloseFramebuffer()&e.code; merely informs the driver (if it
-      even cares) that client no longer needs to access the framebuffer
-      directly.  This function is optional.
-
-    </quote>
-
-    &s.code;Bool SetMode (pScrn, pMode)&e.code;
-    <quote><p>
-      &s.code;SetMode()&e.code; tells the driver to initialize the mode
-      passed to it.  If &s.code;pMode&e.code; is &s.code;NULL&e.code;,
-      then the driver should restore the original pre-DGA mode.
-
-    </quote>
-
-    &s.code;void SetViewport (pScrn, x, y, flags)&e.code;
-    <quote><p>
-      &s.code;SetViewport()&e.code; tells the driver to make the upper
-      left-hand corner of the visible screen correspond to coordinate
-      &s.code;(x,y)&e.code; on the framebuffer.  &s.code;Flags&e.code;
-      currently defined are:
-
-       &s.code;DGA_FLIP_IMMEDIATE&e.code;
-	<quote><p>
-	    The viewport change should occur immediately.
-
-	</quote>
-       &s.code;DGA_FLIP_RETRACE&e.code;
-	<quote><p>
-	    The viewport change should occur at the
-            vertical retrace, but this function should
-            return sooner if possible.
-
-	</quote>
-      The &s.code;(x,y)&e.code; locations will be passed as the client
-      specified them, however, the driver is expected to round these
-      locations down to the next supported location as specified by the
-      &s.code;xViewportStep&e.code; and &s.code;yViewportStep&e.code;
-      for the current mode.
-
-    </quote>
-
-    &s.code;int GetViewport (pScrn)&e.code;
-    <quote><p>
-      &s.code;GetViewport()&e.code; gets the current page flip status.
-      Set bits in the returned int correspond to viewport change requests
-      still pending.  For instance, set bit zero if the last SetViewport
-      request is still pending, bit one if the one before that is still
-      pending, etc.
-
-    </quote>
-
-    &s.code;void Sync (pScrn)&e.code;
-    <quote><p>
-      This function should ensure that any graphics accelerator operations
-      have finished.  This function should not return until the graphics
-      accelerator is idle.
-
-    </quote>
-
-    &s.code;void FillRect (pScrn, x, y, w, h, color)&e.code;
-    <quote><p>
-      This optional function should fill a rectangle
-      &s.code;w&nbsp;&times;&nbsp;h&e.code; located at
-      &s.code;(x,y)&e.code; in the given color.
-
-    </quote>
-
-    &s.code;void BlitRect (pScrn, srcx, srcy, w, h, dstx, dsty)&e.code;
-    <quote><p>
-      This optional function should copy an area
-      &s.code;w&nbsp;&times;&nbsp;h&e.code; located at
-      &s.code;(srcx,srcy)&e.code; to location &s.code;(dstx,dsty)&e.code;.
-      This function will need to handle copy directions as appropriate.
-
-    </quote>
-
-    &s.code;void BlitTransRect (pScrn, srcx, srcy, w, h, dstx, dsty, color)&e.code;
-    <quote><p>
-      This optional function is the same as BlitRect except that pixels
-      in the source corresponding to the color key &s.code;color&e.code;
-      should be skipped.
-
-    </quote>
-    </quote>
-
-<sect>The XFree86 X Video Extension (Xv) Device Dependent Layer
-<p>
-
-XFree86 offers the X Video Extension which allows clients to treat video
-as any another primitive and ``Put'' video into drawables.  By default,
-the extension reports no video adaptors as being available since the
-DDX layer has not been initialized.  The driver can initialize the DDX
-layer by filling out one or more &s.code;XF86VideoAdaptorRecs&e.code;
-as described later in this document and passing a list of
-&s.code;XF86VideoAdaptorPtr&e.code; pointers to the following function:
-
-  <quote>
-  &s.code;Bool xf86XVScreenInit(
-	&f.indent;ScreenPtr pScreen,
-	&f.indent;XF86VideoAdaptorPtr *adaptPtrs,
-	&f.indent;int num)&e.code;
-  </quote>
-
-After doing this, the extension will report video adaptors as being
-available, providing the data in their respective
-&s.code;XF86VideoAdaptorRecs&e.code; was valid.
-&s.code;xf86XVScreenInit()&e.code; <em>copies</em> data from the structure
-passed to it so the driver may free it after the initialization.  At
-the moment, the DDX only supports rendering into Window drawables.
-Pixmap rendering will be supported after a sufficient survey of suitable
-hardware is completed.
-
-The &s.code;XF86VideoAdaptorRec&e.code;:
-
-<quote><p>
-<verb>
-typedef struct {
-	unsigned int type;
-	int flags;
-	char *name;
-	int nEncodings;
-	XF86VideoEncodingPtr pEncodings;
-	int nFormats;
-	XF86VideoFormatPtr pFormats;
-	int nPorts;
-	DevUnion *pPortPrivates;
-	int nAttributes;
-	XF86AttributePtr pAttributes;
-	int nImages;
-	XF86ImagePtr pImages;
-	PutVideoFuncPtr PutVideo;
-	PutStillFuncPtr PutStill;
-	GetVideoFuncPtr GetVideo;
-	GetStillFuncPtr GetStill;
-	StopVideoFuncPtr StopVideo;
-	SetPortAttributeFuncPtr SetPortAttribute;
-	GetPortAttributeFuncPtr GetPortAttribute;
-	QueryBestSizeFuncPtr QueryBestSize;
-	PutImageFuncPtr PutImage;
-	QueryImageAttributesFuncPtr QueryImageAttributes;
-} XF86VideoAdaptorRec, *XF86VideoAdaptorPtr;
-</verb>
-
-   Each adaptor will have its own XF86VideoAdaptorRec.  The fields are
-   as follows:
-
-     &s.code;type&e.code;
-     <quote><p>
-	This can be any of the following flags OR'd together.
-
-	&s.code;XvInputMask&e.code;
-	&s.code;XvOutputMask&e.code;
-	<quote><p>
-	    These refer to the target drawable and are similar to a Window's
-	    class. &s.code;XvInputMask&e.code; indicates that the adaptor
-	    can put video into a drawable.  &s.code;XvOutputMask&e.code;
-	    indicates that the adaptor can get video from a drawable.
-	</quote>
-
-	&s.code;XvVideoMask&e.code;
-	&s.code;XvStillMask&e.code;
-	&s.code;XvImageMask&e.code;
-	<quote><p>
-	    These indicate that the adaptor supports video, still or
-	    image primitives respectively.
-	</quote>
-
-	&s.code;XvWindowMask&e.code;
-	&s.code;XvPixmapMask&e.code;
-	<quote><p>
-	    These indicate the types of drawables the adaptor is capable
-	    of rendering into.  At the moment, Pixmap rendering is not
-	    supported and the &s.code;XvPixmapMask&e.code; flag is ignored.
-	</quote>
-
-     </quote>
-
-     &s.code;flags&e.code;
-     <quote><p>
-	Currently, the following flags are defined:
-
-	&s.code;VIDEO_NO_CLIPPING&e.code;
-	<quote><p>
-	   This indicates that the video adaptor does not support
-	   clipping.  The driver will never receive ``Put'' requests
-	   where less than the entire area determined by
-	   &s.code;drw_x&e.code;, &s.code;drw_y&e.code;,
-	   &s.code;drw_w&e.code; and &s.code;drw_h&e.code; is visible.
-	   This flag does not apply to ``Get'' requests.  Hardware
-	   that is incapable of clipping ``Gets'' may punt or get
-	   the extents of the clipping region passed to it.
-
-	</quote>
-
-	&s.code;VIDEO_INVERT_CLIPLIST&e.code;
-	<quote><p>
-	   This indicates that the video driver requires the clip
-	   list to contain the regions which are obscured rather
-	   than the regions which are are visible.
-
-	</quote>
-
-	&s.code;VIDEO_OVERLAID_STILLS&e.code;
-	<quote><p>
-	   Implementing PutStill for hardware that does video as an
-	   overlay can be awkward since it's unclear how long to leave
-	   the video up for.  When this flag is set, StopVideo will be
-	   called whenever the destination gets clipped or moved so that
-	   the still can be left up until then.
-
-	</quote>
-
-	&s.code;VIDEO_OVERLAID_IMAGES&e.code;
-	<quote><p>
-	    Same as &s.code;VIDEO_OVERLAID_STILLS&e.code; but for images.
-	</quote>
-
-	&s.code;VIDEO_CLIP_TO_VIEWPORT&e.code;
-	<quote><p>
-	    Indicates that the clip region passed to the driver functions
-	    should be clipped to the visible portion of the screen in the
-	    case where the viewport is smaller than the virtual desktop.
-	</quote>
-
-     </quote>
-
-     &s.code;name&e.code;
-     <quote><p>
-	The name of the adaptor.
-
-     </quote>
-
-     &s.code;nEncodings&nl;
-     pEncodings&e.code;
-     <quote><p>
-	The number of encodings the adaptor is capable of and pointer
-	to the &s.code;XF86VideoEncodingRec&e.code; array.  The
-	&s.code;XF86VideoEncodingRec&e.code; is described later on.
-	For drivers that only support XvImages there should be an encoding
-	named "XV_IMAGE" and the width and height should specify
-	the maximum size source image supported.
-
-     </quote>
-
-     &s.code;nFormats&nl;
-     pFormats&e.code;
-     <quote><p>
-	The number of formats the adaptor is capable of and pointer to
-	the &s.code;XF86VideoFormatRec&e.code; array.  The
-	&s.code;XF86VideoFormatRec&e.code; is described later on.
-
-     </quote>
-
-     &s.code;nPorts&nl;
-     pPortPrivates&e.code;
-     <quote><p>
-	The number of ports is the number of separate data streams which
-	the adaptor can handle simultaneously.  If you have more than
-	one port, the adaptor is expected to be able to render into more
-	than one window at a time.  &s.code;pPortPrivates&e.code; is
-	an array of pointers or ints - one for each port.  A port's
-	private data will be passed to the driver any time the port is
-	requested to do something like put the video or stop the video.
-	In the case where there may be many ports, this enables the
-	driver to know which port the request is intended for.  Most
-	commonly, this will contain a pointer to the data structure
-	containing information about the port.  In Xv, all ports on
-	a particular adaptor are expected to be identical in their
-	functionality.
-
-     </quote>
-
-     &s.code;nAttributes&nl;
-     pAttributes&e.code;
-     <quote><p>
-	The number of attributes recognized by the adaptor and a pointer to
-	the array of &s.code;XF86AttributeRecs&e.code;.  The
-	&s.code;XF86AttributeRec&e.code; is described later on.
-
-     </quote>
-
-     &s.code;nImages&nl;
-     pImages&e.code;
-     <quote><p>
-	The number of &s.code;XF86ImageRecs&e.code; supported by the adaptor
-	and a pointer to the array of &s.code;XF86ImageRecs&e.code;. The
-	&s.code;XF86ImageRec&e.code; is described later on.
-
-     </quote>
-
-
-     &s.code;PutVideo PutStill GetVideo GetStill StopVideo
-     SetPortAttribute GetPortAttribute QueryBestSize PutImage
-     QueryImageAttributes&e.code;
-     <quote><p>
-	These functions define the DDX-&gt;driver interface.  In each
-	case, the pointer &s.code;data&e.code; is passed to the driver.
-	This is the port private for that port as described above.  All
-	fields are required except under the following conditions:
-
-	<enum>
-	 <item>&s.code;PutVideo&e.code;, &s.code;PutStill&e.code; and
-	     the image routines &s.code;PutImage&e.code; and
-	     &s.code;QueryImageAttributes&e.code; are not required when the
-	     adaptor type does not contain &s.code;XvInputMask&e.code;.
-
-	 <item>&s.code;GetVideo&e.code; and &s.code;GetStill&e.code;
-	     are not required when the adaptor type does not contain
-	     &s.code;XvOutputMask&e.code;.
-
-	 <item>&s.code;GetVideo&e.code; and &s.code;PutVideo&e.code;
-	     are not required when the adaptor type does not contain
-	     &s.code;XvVideoMask&e.code;.
-
-	 <item>&s.code;GetStill&e.code; and &s.code;PutStill&e.code;
-	     are not required when the adaptor type does not contain
-	     &s.code;XvStillMask&e.code;.
-
-	 <item>&s.code;PutImage&e.code; and &s.code;QueryImageAttributes&e.code;
-	     are not required when the adaptor type does not contain
-	     &s.code;XvImageMask&e.code;.
-
-	</enum>
-
-	With the exception of &s.code;QueryImageAttributes&e.code;, these
-	functions should return &s.code;Success&e.code; if the operation was
-	completed successfully.  They can return &s.code;XvBadAlloc&e.code;
-	otherwise. &s.code;QueryImageAttributes&e.code; returns the size
-	of the XvImage queried.
-
-	If the &s.code;VIDEO_NO_CLIPPING&e.code;
-	flag is set, the &s.code;clipBoxes&e.code; may be ignored by
-	the driver.  &s.code;ClipBoxes&e.code; is an &s.code;X-Y&e.code;
-	banded region identical to those used throughout the server.
-	The clipBoxes represent the visible portions of the area determined
-	by &s.code;drw_x&e.code;, &s.code;drw_y&e.code;,
-	&s.code;drw_w&e.code; and &s.code;drw_h&e.code; in the Get/Put
-	function.  The boxes are in screen coordinates, are guaranteed
-	not to overlap and an empty region will never be passed.
-	If the driver has specified &s.code;VIDEO_INVERT_CLIPLIST&e.code;,
-	&s.code;clipBoxes&e.code; will indicate the areas of the primitive
-	which are obscured rather than the areas visible.
-
-    </quote>
-
-	&s.code;typedef  int (* PutVideoFuncPtr)( ScrnInfoPtr pScrn,
-		&f.indent;short vid_x, short vid_y, short drw_x, short drw_y,
-		&f.indent;short vid_w, short vid_h, short drw_w, short drw_h,
-		&f.indent;RegionPtr clipBoxes, pointer data )&e.code;
-    <quote><p>
-	  This indicates that the driver should take a subsection
-	  &s.code;vid_w&e.code; by &s.code;vid_h&e.code; at location
-	  &s.code;(vid_x,vid_y)&e.code; from the video stream and direct
-	  it into the rectangle &s.code;drw_w&e.code; by &s.code;drw_h&e.code;
-	  at location &s.code;(drw_x,drw_y)&e.code; on the screen, scaling as
-	  necessary.  Due to the large variations in capabilities of
-	  the various hardware expected to be used with this extension,
-	  it is not expected that all hardware will be able to do this
-	  exactly as described.  In that case the driver should just do
-	  ``the best it can,'' scaling as closely to the target rectangle
-	  as it can without rendering outside of it.  In the worst case,
-	  the driver can opt to just not turn on the video.
-
-    </quote>
-
-	&s.code;typedef  int (* PutStillFuncPtr)( ScrnInfoPtr pScrn,
-		&f.indent;short vid_x, short vid_y, short drw_x, short drw_y,
-		&f.indent;short vid_w, short vid_h, short drw_w, short drw_h,
-		&f.indent;RegionPtr clipBoxes, pointer data )&e.code;
-    <quote><p>
-	  This is same as &s.code;PutVideo&e.code; except that the driver
-	  should place only one frame from the stream on the screen.
-
-    </quote>
-
-	&s.code;typedef int (* GetVideoFuncPtr)( ScrnInfoPtr pScrn,
-		&f.indent;short vid_x, short vid_y, short drw_x, short drw_y,
-		&f.indent;short vid_w, short vid_h, short drw_w, short drw_h,
-		&f.indent;RegionPtr clipBoxes, pointer data )&e.code;
-    <quote><p>
-	  This is same as &s.code;PutVideo&e.code; except that the driver
-	  gets video from the screen and outputs it.  The driver should
-	  do the best it can to get the requested dimensions correct
-	  without reading from an area larger than requested.
-
-    </quote>
-
-	&s.code;typedef int (* GetStillFuncPtr)( ScrnInfoPtr pScrn,
-		&f.indent;short vid_x, short vid_y, short drw_x, short drw_y,
-		&f.indent;short vid_w, short vid_h, short drw_w, short drw_h,
-		&f.indent;RegionPtr clipBoxes, pointer data )&e.code;
-    <quote><p>
-	  This is the same as &s.code;GetVideo&e.code; except that the
-	  driver should place only one frame from the screen into the
-	  output stream.
-
-    </quote>
-
-	&s.code;typedef void (* StopVideoFuncPtr)(ScrnInfoPtr pScrn,
-			&f.indent;pointer data, Bool cleanup)&e.code;
-    <quote><p>
-	  This indicates the driver should stop displaying the video.
-	  This is used to stop both input and output video.  The
-	  &s.code;cleanup&e.code; field indicates that the video is
-	  being stopped because the client requested it to stop or
-	  because the server is exiting the current VT.  In that case
-	  the driver should deallocate any offscreen memory areas (if
-	  there are any) being used to put the video to the screen.  If
-	  &s.code;cleanup&e.code; is not set, the video is being stopped
-	  temporarily due to clipping or moving of the window, etc...
-	  and video will likely be restarted soon so the driver should
-	  not deallocate any offscreen areas associated with that port.
-
-    </quote>
-	&s.code;typedef int (* SetPortAttributeFuncPtr)(ScrnInfoPtr pScrn,
-		 &f.indent;Atom attribute,INT32 value, pointer data)&e.code;
-
-	&s.code;typedef int (* GetPortAttributeFuncPtr)(ScrnInfoPtr pScrn,
-		&f.indent;Atom attribute,INT32 *value, pointer data)&e.code;
-
-    <quote><p>
-	  A port may have particular attributes such as hue,
-	  saturation, brightness or contrast.  Xv clients set and
-	  get these attribute values by sending attribute strings
-	  (Atoms) to the server.  Such requests end up at these
-	  driver functions.  It is recommended that the driver provide
-	  at least the following attributes mentioned in the Xv client
-	  library docs:
-	  <quote>
-		&s.code;XV_ENCODING&nl;
-		XV_HUE&nl;
-		XV_SATURATION&nl;
-		XV_BRIGHTNESS&nl;
-  		XV_CONTRAST&e.code;
-	  </quote>
-	  but the driver may recognize as many atoms as it wishes.  If
-	  a requested attribute is unknown by the driver it should return
-	  &s.code;BadMatch&e.code;.  &s.code;XV_ENCODING&e.code; is the
-	  attribute intended to let the client specify which video
-	  encoding the particular port should be using (see the description
-	  of &s.code;XF86VideoEncodingRec&e.code; below).  If the
-	  requested encoding is unsupported, the driver should return
-	  &s.code;XvBadEncoding&e.code;.  If the value lies outside the
-	  advertised range &s.code;BadValue&e.code; may be returned.
-	  &s.code;Success&e.code; should be returned otherwise.
-
-    </quote>
-
-	&s.code;typedef void (* QueryBestSizeFuncPtr)(ScrnInfoPtr pScrn,
-		&f.indent;Bool motion, short vid_w, short vid_h,
-		&f.indent;short drw_w, short drw_h,
-		&f.indent;unsigned int *p_w, unsigned int *p_h, pointer data)&e.code;
-    <quote><p>
-	   &s.code;QueryBestSize&e.code; provides the client with a way
-	   to query what the destination dimensions would end up being
-	   if they were to request that an area
-	   &s.code;vid_w&e.code by &s.code;vid_h&e.code; from the video
-	   stream be scaled to rectangle of
-	   &s.code;drw_w&e.code; by &s.code;drw_h&e.code; on the screen.
-	   Since it is not expected that all hardware will be able to
-	   get the target dimensions exactly, it is important that the
-	   driver provide this function.
-
-    </quote>
-
-	&s.code;typedef  int (* PutImageFuncPtr)( ScrnInfoPtr pScrn,
-		&f.indent;short src_x, short src_y, short drw_x, short drw_y,
-		&f.indent;short src_w, short src_h, short drw_w, short drw_h,
-		&f.indent;int image, char *buf, short width, short height,
-		&f.indent;Bool sync, RegionPtr clipBoxes, pointer data )&e.code;
-    <quote><p>
-	  This is similar to &s.code;PutStill&e.code; except that the
-	  source of the video is not a port but the data stored in a system
-	  memory buffer at &s.code;buf&e.code;.  The data is in the format
-	  indicated by the &s.code;image&e.code; descriptor and represents a
-	  source of size &s.code;width&e.code; by &s.code;height&e.code;.
-	  If &s.code;sync&e.code; is TRUE the driver should not return
-	  from this function until it is through reading the data
-	  from &s.code;buf&e.code;.  Returning when &s.code;sync&e.code;
-	  is TRUE indicates that it is safe for the data at &s.code;buf&e.code;
-	  to be replaced, freed, or modified.
-
-    </quote>
-
-	&s.code;typedef  int (* QueryImageAttributesFuncPtr)( ScrnInfoPtr pScrn,
-		&f.indent;int image, short *width, short *height,
-		&f.indent;int *pitches, int *offsets)&e.code;
-    <quote><p>
-	  This function is called to let the driver specify how data for
-	  a particular &s.code;image&e.code; of size &s.code;width&e.code;
-	  by &s.code;height&e.code; should be stored.  Sometimes only
-	  the size and corrected width and height are needed.  In that
-	  case &s.code;pitches&e.code; and &s.code;offsets&e.code; are
-	  NULL.  The size of the memory required for the image is returned
-	  by this function.  The &s.code;width&e.code; and
-	  &s.code;height&e.code; of the requested image can be altered by
-	  the driver to reflect format limitations (such as component
-	  sampling periods that are larger than one).  If
-	  &s.code;pitches&e.code; and &s.code;offsets&e.code; are not NULL,
-	  these will be arrays with as many elements in them as there
-	  are planes in the &s.code;image&e.code; format.  The driver
-	  should specify the pitch (in bytes) of each scanline in the
-	  particular plane as well as the offset to that plane (in bytes)
-	  from the beginning of the image.
-
-    </quote>
-
-    </quote>
-
-The XF86VideoEncodingRec:
-<quote><p>
-<verb>
-typedef struct {
-	int id;
-	char *name;
-	unsigned short width, height;
-	XvRationalRec rate;
-} XF86VideoEncodingRec, *XF86VideoEncodingPtr;
-
-</verb>
-   The &s.code;XF86VideoEncodingRec&e.code; specifies what encodings
-   the adaptor can support.  Most of this data is just informational
-   and for the client's benefit, and is what will be reported by
-   &s.code;XvQueryEncodings&e.code;.  The &s.code;id&e.code; field is
-   expected to be a unique identifier to allow the client to request a
-   certain encoding via the &s.code;XV_ENCODING&e.code; attribute string.
-
-</quote>
-
-The XF86VideoFormatRec:
-
-<quote><p>
-<verb>
-typedef struct {
-	char  depth;
-	short class;
-} XF86VideoFormatRec, *XF86VideoFormatPtr;
-</verb>
-
-    This specifies what visuals the video is viewable in.
-    &s.code;depth&e.code; is the depth of the visual (not bpp).
-    &s.code;class&e.code; is the visual class such as
-    &s.code;TrueColor&e.code;, &s.code;DirectColor&e.code; or
-    &s.code;PseudoColor&e.code;.  Initialization of an adaptor will fail
-    if none of the visuals on that screen are supported.
-
-</quote>
-
-The XF86AttributeRec:
-
-<quote><p>
-<verb>
-typedef struct {
-	int   flags;
-	int   min_value;
-	int   max_value;
-	char  *name;
-} XF86AttributeListRec, *XF86AttributeListPtr;
-
-</verb>
-
-   Each adaptor may have an array of these advertising the attributes
-   for its ports.  Currently defined flags are &s.code;XvGettable&e.code;
-   and &s.code;XvSettable&e.code; which may be OR'd together indicating that
-   attribute is ``gettable'' or ``settable'' by the client.  The
-   &s.code;min&e.code; and &s.code;max&e.code; field specify the valid range
-   for the value.  &s.code;Name&e.code; is a text string describing the
-   attribute by name.
-
-</quote>
-
-The XF86ImageRec:
-
-<quote><p>
-<verb>
-typedef struct {
-	int id;
-	int type;
-	int byte_order;
-	char guid[16];
-	int bits_per_pixel;
-	int format;
-	int num_planes;
-
-	/* for RGB formats */
-	int depth;
-	unsigned int red_mask;
-	unsigned int green_mask;
-	unsigned int blue_mask;
-
-	/* for YUV formats */
-	unsigned int y_sample_bits;
-	unsigned int u_sample_bits;
-	unsigned int v_sample_bits;
-	unsigned int horz_y_period;
-	unsigned int horz_u_period;
-	unsigned int horz_v_period;
-	unsigned int vert_y_period;
-	unsigned int vert_u_period;
-	unsigned int vert_v_period;
-	char component_order[32];
-	int scanline_order;
-} XF86ImageRec, *XF86ImagePtr;
-</verb>
-
-   XF86ImageRec describes how video source data is laid out in memory.
-   The fields are as follows:
-
-    &s.code;id&e.code;
-    <quote><p>
-	This is a unique descriptor for the format.  It is often good to
-        set this value to the FOURCC for the format when applicable.
-    </quote>
-
-    &s.code;type&e.code;
-    <quote><p>
-	This is &s.code;XvRGB&e.code; or &s.code;XvYUV&e.code;.
-    </quote>
-
-    &s.code;byte_order&e.code;
-    <quote><p>
-	This is &s.code;LSBFirst&e.code; or &s.code;MSBFirst&e.code;.
-    </quote>
-
-    &s.code;guid&e.code;
-    <quote><p>
-	This is the Globally Unique IDentifier for the format.  When
-	not applicable, all characters should be NULL.
-    </quote>
-
-    &s.code;bits_per_pixel&e.code;
-    <quote><p>
-	The number of bits taken up (but not necessarily used) by each
-	pixel.  Note that for some planar formats which have fractional
-	bits per pixel (such as IF09) this number may be rounded _down_.
-    </quote>
-
-    &s.code;format&e.code;
-    <quote><p>
-	This is &s.code;XvPlanar&e.code; or &s.code;XvPacked&e.code;.
-    </quote>
-
-   &s.code;num_planes&e.code;
-    <quote><p>
-	The number of planes in planar formats.  This should be set to
-	one for packed formats.
-    </quote>
-
-   &s.code;depth&e.code;
-    <quote><p>
-	The significant bits per pixel in RGB formats (analgous to the
-	depth of a pixmap format).
-    </quote>
-
-   &s.code;red_mask&e.code;
-   &s.code;green_mask&e.code;
-   &s.code;blue_mask&e.code;
-    <quote><p>
-	The red, green and blue bitmasks for packed RGB formats.
-    </quote>
-
-   &s.code;y_sample_bits&e.code;
-   &s.code;u_sample_bits&e.code;
-   &s.code;v_sample_bits&e.code;
-    <quote><p>
-	The y, u and v sample sizes (in bits).
-    </quote>
-
-   &s.code;horz_y_period&e.code;
-   &s.code;horz_u_period&e.code;
-   &s.code;horz_v_period&e.code;
-    <quote><p>
-	The y, u and v sampling periods in the horizontal direction.
-    </quote>
-
-   &s.code;vert_y_period&e.code;
-   &s.code;vert_u_period&e.code;
-   &s.code;vert_v_period&e.code;
-    <quote><p>
-	The y, u and v sampling periods in the vertical direction.
-    </quote>
-
-   &s.code;component_order&e.code;
-    <quote><p>
-	Uppercase ascii characters representing the order that
-	samples are stored within packed formats.  For planar formats
-	this represents the ordering of the planes.  Unused characters
-	in the 32 byte string should be set to NULL.
-    </quote>
-
-   &s.code;scanline_order&e.code;
-    <quote><p>
-	This is &s.code;XvTopToBottom&e.code; or &s.code;XvBottomToTop&e.code;.
-    </quote>
-
-  Since some formats (particular some planar YUV formats) may not
-be completely defined by the parameters above, the guid, when
-available, should provide the most accurate description of the
-format.
-
-</quote>
-
-<sect>The Loader
-<p>
-
-This section describes the interfaces to the module loader.  The loader
-interfaces can be divided into two groups: those that are only available to
-the XFree86 common layer, and those that are also available to modules.
-
-<sect1>Loader Overview
-<p>
-
-The loader is capable of loading modules in a range of object formats,
-and knowledge of these formats is built in to the loader.  Knowledge of
-new object formats can be added to the loader in a straightforward
-manner.  This makes it possible to provide OS-independent modules (for
-a given CPU architecture type).  In addition to this, the loader can
-load modules via the OS-provided &s.code;dlopen(3)&e.code; service where
-available.  Such modules are not platform independent, and the semantics
-of &s.code;dlopen()&e.code; on most systems results in significant
-limitations in the use of modules of this type.  Support for
-&s.code;dlopen()&e.code; modules in the loader is primarily for
-experimental and development purposes.
-
-Symbols exported by the loader (on behalf of the core X server) to
-modules are determined at compile time.  Only those symbols explicitly
-exported are available to modules.  All external symbols of loaded
-modules are exported to other modules, and to the core X server.  The
-loader can be requested to check for unresolved symbols at any time,
-and the action to be taken for unresolved symbols can be controlled by
-the caller of the loader.  Typically the caller identifies which symbols
-can safely remain unresolved and which cannot.
-
-NOTE:  Now that ISO-C allows pointers to functions and pointers to data to
-have different internal representations, some of the following interfaces
-will need to be revisited.
-
-<sect1>Semi-private Loader Interface
-<p>
-
-The following is the semi-private loader interface that is available to the
-XFree86 common layer.
-
-  <quote><p>
-  &s.code;void LoaderInit(void)&e.code;
-  <quote><p>
-    The &s.code;LoaderInit()&e.code; function initialises the loader,
-    and it must be called once before calling any other loader functions.
-    This function initialises the tables of exported symbols, and anything
-    else that might need to be initialised.
-
-  </quote>
-
-  &s.code;void LoaderSetPath(const char *path)&e.code;
-  <quote><p>
-    The &s.code;LoaderSetPath()&e.code; function initialises a default
-    module search path.  This must be called if calls to other functions
-    are to be made without explicitly specifying a module search path.
-    The search path &s.code;path&e.code; must be a string of one or more
-    comma separated absolute paths.  Modules are expected to be located
-    below these paths, possibly in subdirectories of these paths.
-
-  </quote>
-
-  &s.code;pointer LoadModule(const char *module, const char *path,
-		&f.indent;const char **subdirlist, const char **patternlist,
-		&f.indent;pointer options, const XF86ModReqInfo * modreq,
-		&f.indent;int *errmaj, int *errmin)&e.code;
-  <quote><p>
-    The &s.code;LoadModule()&e.code; function loads the module called
-    &s.code;module&e.code;.  The return value is a module handle, and
-    may be used in future calls to the loader that require a reference
-    to a loaded module.  The module name &s.code;module&e.code; is
-    normally the module's canonical name, which doesn't contain any
-    directory path information, or any object/library file prefixes of
-    suffixes.  Currently a full pathname and/or filename is also accepted.
-    This might change.  The other parameters are:
-
-      &s.code;path&e.code;
-	<quote><p>
-		  An optional comma-separated list of module search paths.
-                  When &s.code;NULL&e.code;, the default search path is used.
-
-	</quote>
-
-      &s.code;subdirlist&e.code;
-	<quote><p>
-		  An optional &s.code;NULL&e.code; terminated list of
-		  subdirectories to search.  When &s.code;NULL&e.code;,
-		  the default built-in list is used (refer to
-		  &s.code;stdSubdirs&e.code; in &s.code;loadmod.c&e.code;).
-		  The default list is also substituted for entries in
-		  &s.code;subdirlist&e.code; with the value
-		  &s.code;DEFAULT_LIST&e.code;.  This makes is possible
-		  to augment the default list instead of replacing it.
-		  Subdir elements must be relative, and must not contain
-		  &s.code;".."&e.code;.  If any violate this requirement,
-		  the load fails.
-
-	</quote>
-
-      &s.code;patternlist&e.code;
-	<quote><p>
-		  An optional &s.code;NULL&e.code; terminated list of
-		  POSIX regular expressions used to connect module
-		  filenames with canonical module names.  Each regex
-		  should contain exactly one subexpression that corresponds
-		  to the canonical module name.  When &s.code;NULL&e.code;,
-		  the default built-in list is used (refer to
-		  &s.code;stdPatterns&e.code; in
-		  &s.code;loadmod.c&e.code;).  The default list is also
-		  substituted for entries in &s.code;patternlist&e.code;
-		  with the value &s.code;DEFAULT_LIST&e.code;.  This
-		  makes it possible to augment the default list instead
-		  of replacing it.
-
-	</quote>
-
-      &s.code;options&e.code;
-	<quote><p>
-		  An optional parameter that is passed to the newly
-		  loaded module's &s.code;SetupProc&e.code; function
-		  (if it has one).  This argument is normally a
-		  &s.code;NULL&e.code; terminated list of
-		  &s.code;Options&e.code;, and must be interpreted that
-		  way by modules loaded directly by the XFree86 common
-		  layer.  However, it may be used for application-specific
-		  parameter passing in other situations.
-
-		  When loading ``external'' modules (modules that don't
-		  have the standard entry point, for example a
-		  special shared library) the options parameter can be
-		  set to &s.code;EXTERN_MODULE&e.code; to tell the
-		  loader not to reject the module when it doesn't find
-		  the standard entry point.
-
-	</quote>
-
-      &s.code;modreq&e.code;
-	<quote><p>
-		  An optional &s.code;XF86ModReqInfo*&e.code; containing
-		  version/ABI/vendor information to requirements to
-		  check the newly loaded module against.  The main
-		  purpose of this is to allow the loader to verify that
-		  a module of the correct type/version before running
-		  its &s.code;SetupProc&e.code; function.
-
-		  The &s.code;XF86ModReqInfo&e.code; struct is defined
-		  as follows:
-<verb>
-typedef struct {
-	CARD8        majorversion;  /* MAJOR_UNSPEC */
-	CARD8        minorversion;  /* MINOR_UNSPEC */
-	CARD16       patchlevel;    /* PATCH_UNSPEC */
-	const char * abiclass;      /* ABI_CLASS_NONE */
-	CARD32       abiversion;    /* ABI_VERS_UNSPEC */
-	const char * moduleclass;   /* MOD_CLASS_NONE */
-} XF86ModReqInfo;
-</verb>
-
-		  The information here is compared against the equivalent
-		  information in the module's
-		  &s.code;XF86ModuleVersionInfo&e.code; record (which
-		  is described below).  The values in comments above
-		  indicate ``don't care'' settings for each of the fields.
-		  The comparisons made are as follows:
-
-                    &s.code;majorversion&e.code;
-			<quote><p>
-				   Must match the module's majorversion
-				   exactly.
-
-			</quote>
-                    &s.code;minorversion&e.code;
-			<quote><p>
-				   The module's minor version must be
-				   no less than this value.  This
-				   comparison is only made if
-				   &s.code;majorversion&e.code; is
-				   specified and matches.
-
-			</quote>
-                    &s.code;patchlevel&e.code;
-			<quote><p>
-				   The module's patchlevel must be no
-				   less than this value.  This comparison
-				   is only made if
-				   &s.code;minorversion&e.code; is
-				   specified and matches.
-
-			</quote>
-                    &s.code;abiclass&e.code;
-			<quote><p>
-				   String must match the module's abiclass
-				   string.
-
-			</quote>
-                    &s.code;abiversion&e.code;
-			<quote><p>
-				   Must be consistent with the module's
-				   abiversion (major equal, minor no
-				   older).
-
-			</quote>
-                    &s.code;moduleclass&e.code;
-			<quote><p>
-				   String must match the module's
-				   moduleclass string.
-
-			</quote>
-
-	</quote>
-
-      &s.code;errmaj&e.code;
-	<quote><p>
-		  An optional pointer to a variable holding the major
-		  part or the error code.  When provided,
-		  &s.code;*errmaj&e.code; is filled in when
-		  &s.code;LoadModule()&e.code; fails.
-
-	</quote>
-
-      &s.code;errmin&e.code;
-	<quote><p>
-		  Like &s.code;errmaj&e.code;, but for the minor part
-		  of the error code.
-
-	</quote>
-
-  </quote>
-
-  &s.code;void UnloadModule(pointer mod)&e.code;
-  <quote><p>
-    This function unloads the module referred to by the handle mod.
-    All child modules are also unloaded recursively.  This function must
-    not be used to directly unload modules that are child modules (i.e.,
-    those that have been loaded with the &s.code;LoadSubModule()&e.code;
-    described below).
-
-  </quote>
-  </quote>
-
-<sect1>Module Requirements
-<p>
-
-Modules must provide information about themselves to the loader, and
-may optionally provide entry points for "setup" and "teardown" functions
-(those two functions are referred to here as &s.code;SetupProc&e.code;
-and &s.code;TearDownProc&e.code;).
-
-The module information is contained in the
-&s.code;XF86ModuleVersionInfo&e.code; struct, which is defined as follows:
-
-<quote><p><verb>
-typedef struct {
-    const char * modname;      /* name of module, e.g. "foo" */
-    const char * vendor;       /* vendor specific string */
-    CARD32       _modinfo1_;   /* constant MODINFOSTRING1/2 to find */
-    CARD32       _modinfo2_;   /* infoarea with a binary editor/sign tool */
-    CARD32       xf86version;  /* contains XF86_VERSION_CURRENT */
-    CARD8        majorversion; /* module-specific major version */
-    CARD8        minorversion; /* module-specific minor version */
-    CARD16       patchlevel;   /* module-specific patch level */
-    const char * abiclass;     /* ABI class that the module uses */
-    CARD32       abiversion;   /* ABI version */
-    const char * moduleclass;  /* module class */
-    CARD32       checksum[4];  /* contains a digital signature of the */
-                               /* version info structure */
-} XF86ModuleVersionInfo;
-</verb>
-
-The fields are used as follows:
-
-  &s.code;modname&e.code;
-	<quote><p>
-		The module's name.  This field is currently only for
-		informational purposes, but the loader may be modified
-		in future to require it to match the module's canonical
-                name.
-
-	</quote>
-
-  &s.code;vendor&e.code;
-	<quote><p>
-		The module vendor.  This field is for informational purposes
-                only.
-
-	</quote>
-
-  &s.code;_modinfo1_&e.code;
-	<quote><p>
-		This field holds the first part of a signature that can
-                be used to locate this structure in the binary.  It should
-                always be initialised to &s.code;MODINFOSTRING1&e.code;.
-
-	</quote>
-
-  &s.code;_modinfo2_&e.code;
-	<quote><p>
-		This field holds the second part of a signature that can
-                be used to locate this structure in the binary.  It should
-                always be initialised to &s.code;MODINFOSTRING2&e.code;.
-
-	</quote>
-
-  &s.code;xf86version&e.code;
-	<quote><p>
-		The XFree86 version against which the module was compiled.
-                This is mostly for informational/diagnostic purposes.  It
-                should be initialised to &s.code;XF86_VERSION_CURRENT&e.code;, which is
-                defined in &s.code;xf86Version.h&e.code;.
-
-	</quote>
-
-  &s.code;majorversion&e.code;
-	<quote><p>
-		The module-specific major version.  For modules where this
-		version is used for more than simply informational
-		purposes, the major version should only change (be
-		incremented) when ABI incompatibilities are introduced,
-		or ABI components are removed.
-
-	</quote>
-
-  &s.code;minorversion&e.code;
-	<quote><p>
-		The module-specific minor version.  For modules where this
-		version is used for more than simply informational
-		purposes, the minor version should only change (be
-		incremented) when ABI additions are made in a backward
-		compatible way.  It should be reset to zero when the major
-                version is increased.
-
-	</quote>
-
-  &s.code;patchlevel&e.code;
-	<quote><p>
-		The module-specific patch level.  The patch level should
-		increase with new revisions of the module where there
-		are no ABI changes, and it should be reset to zero when
-		the minor version is increased.
-
-	</quote>
-
-  &s.code;abiclass&e.code;
-	<quote><p>
-		The ABI class that the module requires.  The class is
-                specified as a string for easy extensibility.  It should
-		indicate which (if any) of the X server's built-in ABI
-		classes that the module relies on, or a third-party ABI
-                if appropriate.  Built-in ABI classes currently defined are:
-
-		<quote>
-                   &s.code;ABI_CLASS_NONE&e.code;
-			<quote>no class</quote>
-                   &s.code;ABI_CLASS_ANSIC&e.code;
-			<quote>only requires the ANSI C interfaces</quote>
-                   &s.code;ABI_CLASS_VIDEODRV&e.code;
-			<quote>requires the video driver ABI</quote>
-                   &s.code;ABI_CLASS_XINPUT&e.code;
-			<quote>requires the XInput driver ABI</quote>
-                   &s.code;ABI_CLASS_EXTENSION&e.code;
-			<quote>requires the extension module ABI</quote>
-                   &s.code;ABI_CLASS_FONT&e.code;
-			<quote>requires the font module ABI</quote>
-		</quote>
-
-	</quote>
-
-  &s.code;abiversion&e.code;
-	<quote><p>
-		The version of abiclass that the module requires.  The
-		version consists of major and minor components.  The
-		major version must match and the minor version must be
-		no newer than that provided by the server or parent
-		module.  Version identifiers for the built-in classes
-		currently defined are:
-
-		<quote>
-                   &s.code;ABI_ANSIC_VERSION&nl;
-                   ABI_VIDEODRV_VERSION&nl;
-                   ABI_XINPUT_VERSION&nl;
-                   ABI_EXTENSION_VERSION&nl;
-                   ABI_FONT_VERSION&e.code;
-		</quote>
-
-	</quote>
-
-  &s.code;moduleclass&e.code;
-	<quote><p>
-		This is similar to the abiclass field, except that it
-		defines the type of module rather than the ABI it
-		requires.  For example, although all video drivers require
-		the video driver ABI, not all modules that require the
-		video driver ABI are video drivers.  This distinction
-		can be made with the moduleclass.  Currently pre-defined
-		module classes are:
-
-		<quote>
-                   &s.code;MOD_CLASS_NONE&nl;
-                   MOD_CLASS_VIDEODRV&nl;
-                   MOD_CLASS_XINPUT&nl;
-                   MOD_CLASS_FONT&nl;
-                   MOD_CLASS_EXTENSION&e.code;
-		</quote>
-
-	</quote>
-
-  &s.code;checksum&e.code;
-	<quote><p>
-		Not currently used.
-
-	</quote>
-
-</quote>
-
-The module version information, and the optional &s.code;SetupProc&e.code;
-and &s.code;TearDownProc&e.code; entry points are found by the loader
-by locating a data object in the module called "modnameModuleData",
-where "modname" is the canonical name of the module.  Modules must
-contain such a data object, and it must be declared with global scope,
-be compile-time initialised, and is of the following type:
-
-<quote>
-<verb>
-typedef struct {
-    XF86ModuleVersionInfo *     vers;
-    ModuleSetupProc             setup;
-    ModuleTearDownProc          teardown;
-} XF86ModuleData;
-</verb>
-</quote>
-
-The vers parameter must be initialised to a pointer to a correctly
-initialised &s.code;XF86ModuleVersionInfo&e.code; struct.  The other
-two parameter are optional, and should be initialised to
-&s.code;NULL&e.code; when not required.  The other parameters are defined
-as
-
-  <quote><p>
-  &s.code;typedef pointer (*ModuleSetupProc)(pointer, pointer, int *, int *)&e.code;
-
-  &s.code;typedef void (*ModuleTearDownProc)(pointer)&e.code;
-
-
-  &s.code;pointer SetupProc(pointer module, pointer options,
-		&f.indent;int *errmaj, int *errmin)&e.code;
-  <quote><p>
-    When defined, this function is called by the loader after successfully
-    loading a module.  module is a handle for the newly loaded module,
-    and maybe used by the &s.code;SetupProc&e.code; if it calls other
-    loader functions that require a reference to it.   The remaining
-    arguments are those that were passed to the
-    &s.code;LoadModule()&e.code; (or &s.code;LoadSubModule()&e.code;),
-    and are described above. When the &s.code;SetupProc&e.code; is
-    successful it must return a non-&s.code;NULL&e.code; value.  The
-    loader checks this, and if it is &s.code;NULL&e.code; it unloads
-    the module and reports the failure to the caller of
-    &s.code;LoadModule()&e.code;.  If the &s.code;SetupProc&e.code;
-    does things that need to be undone when the module is unloaded,
-    it should define a &s.code;TearDownProc&e.code;, and return a
-    pointer that the &s.code;TearDownProc&e.code; can use to undo what
-    has been done.
-
-    When a module is loaded multiple times, the &s.code;SetupProc&e.code;
-    is called once for each time it is loaded.
-
-  </quote>
-
-  &s.code;void TearDownProc(pointer tearDownData)&e.code;
-  <quote><p>
-    When defined, this function is called when the loader unloads a
-    module.  The &s.code;tearDownData&e.code; parameter is the return
-    value of the &s.code;SetupProc()&e.code; that was called when the
-    module was loaded.  The purpose of this function is to clean up
-    before the module is unloaded (for example, by freeing allocated
-    resources).
-
-  </quote>
-  </quote>
-
-<sect1>Public Loader Interface
-<p>
-
-The following is the Loader interface that is available to any part of
-the server, and may also be used from within modules.
-
-  <quote><p>
-  &s.code;pointer LoadSubModule(pointer parent, const char *module,
-		&f.indent;const char **subdirlist, const char **patternlist,
-		&f.indent;pointer options, const XF86ModReqInfo * modreq,
-		&f.indent;int *errmaj, int *errmin)&e.code;
-  <quote><p>
-    This function is like the &s.code;LoadModule()&e.code; function
-    described above, except that the module loaded is registered as a
-    child of the calling module.  The &s.code;parent&e.code; parameter
-    is the calling module's handle.  Modules loaded with this function
-    are automatically unloaded when the parent module is unloaded.  The
-    other difference is that the path parameter may not be specified.
-    The module search path used for modules loaded with this function
-    is the default search path as initialised with
-    &s.code;LoaderSetPath()&e.code;.
-
-  </quote>
-
-  &s.code;void UnloadSubModule(pointer module)&e.code;
-  <quote><p>
-    This function unloads the module with handle &s.code;module&e.code;.
-    If that module itself has children, they are also unloaded.  It is
-    like &s.code;UnloadModule()&e.code;, except that it is safe to use
-    for unloading child modules.
-
-  </quote>
-
-  &s.code;pointer LoaderSymbol(const char *symbol)&e.code;
-  <quote><p>
-    This function returns the address of the symbol with name
-    &s.code;symbol&e.code;.  This may be used to locate a module entry
-    point with a known name.
-
-  </quote>
-
-  &s.code;char **LoaderlistDirs(const char **subdirlist,
-			&f.indent;const char **patternlist)&e.code;
-  <quote><p>
-    This function returns a &s.code;NULL&e.code; terminated list of
-    canonical modules names for modules found in the default module
-    search path.  The &s.code;subdirlist&e.code; and
-    &s.code;patternlist&e.code; parameters are as described above, and
-    can be used to control the locations and names that are searched.
-    If no modules are found, the return value is &s.code;NULL&e.code;.
-    The returned list should be freed by calling
-    &s.code;LoaderFreeDirList()&e.code; when it is no longer needed.
-
-  </quote>
-
-  &s.code;void LoaderFreeDirList(char **list)&e.code;
-  <quote><p>
-    This function frees a module list created by
-    &s.code;LoaderlistDirs()&e.code;.
-
-  </quote>
-
-  &s.code;void LoaderReqSymLists(const char **list0, ...)&e.code;
-  <quote><p>
-    This function allows the registration of required symbols with the
-    loader.  It is normally used by a caller of
-    &s.code;LoadSubModule()&e.code;.  If any symbols registered in this
-    way are found to be unresolved when
-    &s.code;LoaderCheckUnresolved()&e.code; is called then
-    &s.code;LoaderCheckUnresolved()&e.code; will report a failure.
-    The function takes one or more &s.code;NULL&e.code; terminated
-    lists of symbols.  The end of the argument list is indicated by a
-    &s.code;NULL&e.code; argument.
-
-  </quote>
-
-  &s.code;void LoaderReqSymbols(const char *sym0, ...)&e.code;
-  <quote><p>
-    This function is like &s.code;LoaderReqSymLists()&e.code; except
-    that its arguments are symbols rather than lists of symbols.  This
-    function is more convenient when single functions are to be registered,
-    especially when the single function might depend on runtime factors.
-    The end of the argument list is indicated by a &s.code;NULL&e.code;
-    argument.
-
-  </quote>
-
-  &s.code;void LoaderRefSymLists(const char **list0, ...)&e.code;
-  <quote><p>
-    This function allows the registration of possibly unresolved symbols
-    with the loader.  When &s.code;LoaderCheckUnresolved()&e.code; is
-    run it won't generate warnings for symbols registered in this way
-    unless they were also registered as required symbols.
-    The function takes one or more &s.code;NULL&e.code; terminated
-    lists of symbols.  The end of the argument list is indicated by a
-    &s.code;NULL&e.code; argument.
-
-  </quote>
-
-  &s.code;void LoaderRefSymbols(const char *sym0, ...)&e.code;
-  <quote><p>
-    This function is like &s.code;LoaderRefSymLists()&e.code; except
-    that its arguments are symbols rather than lists of symbols.  This
-    function is more convenient when single functions are to be registered,
-    especially when the single function might depend on runtime factors.
-    The end of the argument list is indicated by a &s.code;NULL&e.code;
-    argument.
-
-  </quote>
-
-  &s.code;int LoaderCheckUnresolved(int delayflag)&e.code;
-  <quote><p>
-    This function checks for unresolved symbols.  It generates warnings
-    for unresolved symbols that have not been registered with
-    &s.code;LoaderRefSymLists()&e.code;, and maps them to a dummy
-    function.  This behaviour may change in future.  If unresolved
-    symbols are found that have been registered with
-    &s.code;LoaderReqSymLists()&e.code; or
-    &s.code;LoaderReqSymbols()&e.code; then this function returns a
-    non-zero value.  If none of these symbols are unresolved the return
-    value is zero, indicating success.
-
-    The &s.code;delayflag&e.code; parameter should normally be set to
-    &s.code;LD_RESOLV_IFDONE&e.code;.
-
-  </quote>
-
-  &s.code;LoaderErrorMsg(const char *name, const char *modname,
-			&f.indent;int errmaj, int errmin)&e.code;
-  <quote><p>
-    This function prints an error message that includes the text ``Failed
-    to load module'', the module name &s.code;modname&e.code;, a message
-    specific to the &s.code;errmaj&e.code; value, and the value if
-    &s.code;errmin&e.code;.  If &s.code;name&e.code; is
-    non-&s.code;NULL&e.code;, it is printed as an identifying prefix
-    to the message (followed by a `:').
-
-  </quote>
-  </quote>
-
-<sect1>Special Registration Functions
-<p>
-
-The loader contains some functions for registering some classes of modules.
-These may be moved out of the loader at some point.
-
-  <quote><p>
-  &s.code;void LoadExtension(ExtensionModule *ext)&e.code;
-  <quote><p>
-    This registers the entry points for the extension identified by
-    &s.code;ext&e.code;.  The &s.code;ExtensionModule&e.code; struct is
-    defined as:
-
-<quote>
-<verb>
-typedef struct {
-    InitExtension       initFunc;
-    char *              name;
-    Bool                *disablePtr;
-    InitExtension       setupFunc;
-} ExtensionModule;
-</verb>
-</quote>
-
-  </quote>
-
-  &s.code;void LoadFont(FontModule *font)&e.code;
-  <quote><p>
-    This registers the entry points for the font rasteriser module
-    identified by &s.code;font&e.code;.  The &s.code;FontModule&e.code;
-    struct is defined as:
-
-<quote>
-<verb>
-typedef struct {
-    InitFont    initFunc;
-    char *      name;
-    pointer     module;
-} FontModule;
-</verb>
-</quote>
-
-  </quote>
-  </quote>
-
-</sect>
-
-
-<sect>Helper Functions
-<p>
-
-This section describe ``helper'' functions that video driver
-might find useful.  While video drivers are not required to use any of
-these to be considered ``compliant'', the use of appropriate helpers is
-strongly encouraged to improve the consistency of driver behaviour.
-
-<sect1>Functions for printing messages
-<p>
-
-  <quote><p>
-    &s.code;ErrorF(const char *format, ...)&e.code;
-    <quote><p>
-      This is the basic function for writing to the error log (typically
-      stderr and/or a log file).  Video drivers should usually avoid
-      using this directly in favour of the more specialised functions
-      described below.  This function is useful for printing messages
-      while debugging a driver.
-
-    </quote>
-
-    &s.code;FatalError(const char *format, ...)&e.code;
-    <quote><p>
-      This prints a message and causes the Xserver to abort.  It should
-      rarely be used within a video driver, as most error conditions
-      should be flagged by the return values of the driver functions.
-      This allows the higher layers to decide how to proceed.  In rare
-      cases, this can be used within a driver if a fatal unexpected
-      condition is found.
-
-    </quote>
-
-    &s.code;xf86ErrorF(const char *format, ...)&e.code;
-    <quote><p>
-      This is like &s.code;ErrorF()&e.code;, except that the message is
-      only printed when the Xserver's verbosity level is set to the
-      default (&s.code;1&e.code;) or higher.  It means that the messages
-      are not printed when the server is started with the
-      &s.cmd;-quiet&e.cmd; flag.  Typically this function would only be
-      used for continuing messages started with one of the more specialised
-      functions described below.
-
-    </quote>
-
-    &s.code;xf86ErrorFVerb(int verb, const char *format, ...)&e.code;
-    <quote><p>
-      Like &s.code;xf86ErrorF()&e.code;, except the minimum verbosity
-      level for which the message is to be printed is given explicitly.
-      Passing a &s.code;verb&e.code; value of zero means the message
-      is always printed.  A value higher than &s.code;1&e.code; can be
-      used for information would normally not be needed, but which might
-      be useful when diagnosing problems.
-
-    </quote>
-
-    &s.code;xf86Msg(MessageType type, const char *format, ...)&e.code;
-    <quote><p>
-      This is like &s.code;xf86ErrorF()&e.code;, except that the message
-      is prefixed with a marker determined by the value of
-      &s.code;type&e.code;.  The marker is used to indicate the type of
-      message (warning, error, probed value, config value, etc).  Note
-      the &s.code;xf86Verbose&e.code; value is ignored for messages of
-      type &s.code;X_ERROR&e.code;.
-
-      The marker values are:
-
-      <quote>
-      &s.code;X_PROBED&e.code;
-	<quote>Value was probed.</quote>
-      &s.code;X_CONFIG&e.code;
-	<quote>Value was given in the config file.</quote>
-      &s.code;X_DEFAULT&e.code;
-	<quote>Value is a default.</quote>
-      &s.code;X_CMDLINE&e.code;
-	<quote>Value was given on the command line.</quote>
-      &s.code;X_NOTICE&e.code;
-	<quote>Notice.</quote>
-      &s.code;X_ERROR&e.code;
-	<quote>Error message.</quote>
-      &s.code;X_WARNING&e.code;
-	<quote>Warning message.</quote>
-      &s.code;X_INFO&e.code;
-	<quote>Informational message.</quote>
-      &s.code;X_NONE&e.code;
-	<quote>No prefix.</quote>
-      &s.code;X_NOT_IMPLEMENTED&e.code;
-	<quote>The message relates to functionality that is not yet
-               implemented.</quote>
-      </quote>
-
-
-    </quote>
-
-    &s.code;xf86MsgVerb(MessageType type, int verb, const char *format, ...)&e.code;
-    <quote><p>
-      Like &s.code;xf86Msg()&e.code;, but with the verbosity level given
-      explicitly.
-
-    </quote>
-
-    &s.code;xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...)&e.code;
-    <quote><p>
-      This is like &s.code;xf86Msg()&e.code; except that the driver's
-      name (the &s.code;name&e.code; field of the
-      &s.code;ScrnInfoRec&e.code;) followed by the
-      &s.code;scrnIndex&e.code; in parentheses is printed following the
-      prefix.  This should be used by video drivers in most cases as it
-      clearly indicates which driver/screen the message is for.  If
-      &s.code;scrnIndex&e.code; is negative, this function behaves
-      exactly like &s.code;xf86Msg()&e.code;.
-
-      NOTE: This function can only be used after the
-      &s.code;ScrnInfoRec&e.code; and its &s.code;name&e.code; field
-      have been allocated.  Normally, this means that it can not be
-      used before the END of the &s.code;ChipProbe()&e.code; function.
-      Prior to that, use &s.code;xf86Msg()&e.code;, providing the
-      driver's name explicitly.  No screen number can be supplied at
-      that point.
-
-    </quote>
-
-    &s.code;xf86DrvMsgVerb(int scrnIndex, MessageType type, int verb,
-		&f.indent;const char *format, ...)&e.code;
-    <quote><p>
-      Like &s.code;xf86DrvMsg()&e.code;, but with the verbosity level
-      given explicitly.
-
-    </quote>
-  </quote>
-
-
-<sect1>Functions for setting values based on command line and config file
-<p>
-
-  <quote><p>
-    &s.code;Bool xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int bpp,
-                        &f.indent;int fbbpp, int depth24flags)&e.code;
-    <quote><p>
-      This function sets the &s.code;depth&e.code;, &s.code;pixmapBPP&e.code; and &s.code;bitsPerPixel&e.code; fields
-      of the &s.code;ScrnInfoRec&e.code;.  It also determines the defaults for display-wide
-      attributes and pixmap formats the screen will support, and finds
-      the Display subsection that matches the depth/bpp.  This function
-      should normally be called very early from the
-      &s.code;ChipPreInit()&e.code; function.
-
-      It requires that the &s.code;confScreen&e.code; field of the &s.code;ScrnInfoRec&e.code; be
-      initialised prior to calling it.  This is done by the XFree86
-      common layer prior to calling &s.code;ChipPreInit()&e.code;.
-
-      The parameters passed are:
-
-        &s.code;depth&e.code;
-	<quote><p>
-		driver's preferred default depth if no other is given.
-                If zero, use the overall server default.
-
-	</quote>
-        &s.code;bpp&e.code;
-	<quote><p>
-		Same, but for the pixmap bpp.
-
-	</quote>
-        &s.code;fbbpp&e.code;
-	<quote><p>
-		Same, but for the framebuffer bpp.
-
-	</quote>
-        &s.code;depth24flags&e.code;
-	<quote><p>
-		Flags that indicate the level of 24/32bpp support
-                and whether conversion between different framebuffer
-                and pixmap formats is supported.  The flags for this
-                argument are defined as follows, and multiple flags
-                may be ORed together:
-
-               &s.code;NoDepth24Support&e.code;
-		<quote>No depth 24 formats supported</quote>
-               &s.code;Support24bppFb&e.code;
-		<quote>24bpp framebuffer supported</quote>
-               &s.code;Support32bppFb&e.code;
-		<quote>32bpp framebuffer supported</quote>
-               &s.code;SupportConvert24to32&e.code;
-		<quote>Can convert 24bpp pixmap to 32bpp fb</quote>
-               &s.code;SupportConvert32to24&e.code;
-		<quote>Can convert 32bpp pixmap to 24bpp fb</quote>
-               &s.code;ForceConvert24to32&e.code;
-		<quote>Force 24bpp pixmap to 32bpp fb conversion</quote>
-               &s.code;ForceConvert32to24&e.code;
-		<quote>Force 32bpp pixmap to 24bpp fb conversion</quote>
-
-	</quote>
-
-      It uses the command line, config file, and default values in the
-      correct order of precedence to determine the depth and bpp values.
-      It is up to the driver to check the results to see that it supports
-      them.  If not the &s.code;ChipPreInit()&e.code; function should
-      return &s.code;FALSE&e.code;.
-
-      If only one of depth/bpp is given, the other is set to a reasonable
-      (and consistent) default.
-
-      If a driver finds that the initial &s.code;depth24flags&e.code;
-      it uses later results in a fb format that requires more video
-      memory than is available it may call this function a second time
-      with a different &s.code;depth24flags&e.code; setting.
-
-      On success, the return value is &s.code;TRUE&e.code;.  On failure
-      it prints an error message and returns &s.code;FALSE&e.code;.
-
-      The following fields of the &s.code;ScrnInfoRec&e.code; are
-      initialised by this function:
-
-	<quote>
-	&s.code;depth&e.code;, &s.code;bitsPerPixel&e.code;,
-	&s.code;display&e.code;, &s.code;imageByteOrder&e.code;,
-	&s.code;bitmapScanlinePad&e.code;,
-	&s.code;bitmapScanlineUnit&e.code;, &s.code;bitmapBitOrder&e.code;,
-	&s.code;numFormats&e.code;, &s.code;formats&e.code;,
-	&s.code;fbFormat&e.code;.
-	</quote>
-
-    </quote>
-
-    &s.code;void xf86PrintDepthBpp(scrnInfoPtr scrp)&e.code;
-    <quote><p>
-      This function can be used to print out the depth and bpp settings.
-      It should be called after the final call to
-      &s.code;xf86SetDepthBpp()&e.code;.
-
-    </quote>
-
-    &s.code;Bool xf86SetWeight(ScrnInfoPtr scrp, rgb weight, rgb mask)&e.code;
-    <quote><p>
-      This function sets the &s.code;weight&e.code;, &s.code;mask&e.code;,
-      &s.code;offset&e.code; and &s.code;rgbBits&e.code; fields of the
-      &s.code;ScrnInfoRec&e.code;.  It would normally be called fairly
-      early in the &s.code;ChipPreInit()&e.code; function for
-      depths&nbsp;>&nbsp;8bpp.
-
-      It requires that the &s.code;depth&e.code; and
-      &s.code;display&e.code; fields of the &s.code;ScrnInfoRec&e.code;
-      be initialised prior to calling it.
-
-      The parameters passed are:
-
-        &s.code;weight&e.code;
-	<quote><p>
-		driver's preferred default weight if no other is given.
-                If zero, use the overall server default.
-
-	</quote>
-
-        &s.code;mask&e.code;
-	<quote><p>
-		Same, but for mask.
-
-	</quote>
-
-      It uses the command line, config file, and default values in the
-      correct order of precedence to determine the weight value.  It
-      derives the mask and offset values from the weight and the defaults.
-      It is up to the driver to check the results to see that it supports
-      them.  If not the &s.code;ChipPreInit()&e.code; function should
-      return &s.code;FALSE&e.code;.
-
-      On success, this function prints a message showing the weight
-      values selected, and returns &s.code;TRUE&e.code;.
-
-      On failure it prints an error message and returns &s.code;FALSE&e.code;.
-
-      The following fields of the &s.code;ScrnInfoRec&e.code; are
-      initialised by this function:
-
-	<quote>
-        &s.code;weight&e.code;, &s.code;mask&e.code;, &s.code;offset&e.code;.
-	</quote>
-
-    </quote>
-
-    &s.code;Bool xf86SetDefaultVisual(ScrnInfoPtr scrp, int visual)&e.code;
-    <quote><p>
-      This function sets the &s.code;defaultVisual&e.code; field of the
-      &s.code;ScrnInfoRec&e.code;.  It would normally be called fairly
-      early from the &s.code;ChipPreInit()&e.code; function.
-
-      It requires that the &s.code;depth&e.code; and
-      &s.code;display&e.code; fields of the &s.code;ScrnInfoRec&e.code;
-      be initialised prior to calling it.
-
-      The parameters passed are:
-
-        &s.code;visual&e.code;
-	<quote><p>
-		driver's preferred default visual if no other is given.
-		If &s.code;-1&e.code;, use the overall server default.
-
-	</quote>
-
-      It uses the command line, config file, and default values in the
-      correct order of precedence to determine the default visual value.
-      It is up to the driver to check the result to see that it supports
-      it.  If not the &s.code;ChipPreInit()&e.code; function should
-      return &s.code;FALSE&e.code;.
-
-      On success, this function prints a message showing the default visual
-      selected, and returns &s.code;TRUE&e.code;.
-
-      On failure it prints an error message and returns &s.code;FALSE&e.code;.
-
-    </quote>
-
-    &s.code;Bool xf86SetGamma(ScrnInfoPtr scrp, Gamma gamma)&e.code;
-    <quote><p>
-      This function sets the &s.code;gamma&e.code; field of the
-      &s.code;ScrnInfoRec&e.code;.  It would normally be called fairly
-      early from the &s.code;ChipPreInit()&e.code; function in cases
-      where the driver supports gamma correction.
-
-      It requires that the &s.code;monitor&e.code; field of the
-      &s.code;ScrnInfoRec&e.code; be initialised prior to calling it.
-
-      The parameters passed are:
-
-        &s.code;gamma&e.code;
-	<quote><p>
-		driver's preferred default gamma if no other is given.
-		If zero (&s.code;< 0.01&e.code;), use the overall server
-		default.
-
-	</quote>
-
-      It uses the command line, config file, and default values in the
-      correct order of precedence to determine the gamma value.  It is
-      up to the driver to check the results to see that it supports
-      them.  If not the &s.code;ChipPreInit()&e.code; function should
-      return &s.code;FALSE&e.code;.
-
-      On success, this function prints a message showing the gamma
-      value selected, and returns &s.code;TRUE&e.code;.
-
-      On failure it prints an error message and returns &s.code;FALSE&e.code;.
-
-    </quote>
-
-    &s.code;void xf86SetDpi(ScrnInfoPtr pScrn, int x, int y)&e.code;
-    <quote><p>
-      This function sets the &s.code;xDpi&e.code; and &s.code;yDpi&e.code;
-      fields of the &s.code;ScrnInfoRec&e.code;.  The driver can specify
-      preferred defaults by setting &s.code;x&e.code; and &s.code;y&e.code;
-      to non-zero values.  The &s.cmd;-dpi&e.cmd; command line option
-      overrides all other settings.  Otherwise, if the
-      &s.key;DisplaySize&e.key; entry is present in the screen's &k.monitor;
-      config file section, it is used together with the virtual size to
-      calculate the dpi values.  This function should be called after
-      all the mode resolution has been done.
-
-    </quote>
-
-    &s.code;void xf86SetBlackWhitePixels(ScrnInfoPtr pScrn)&e.code;
-    <quote><p>
-      This functions sets the &s.code;blackPixel&e.code; and
-      &s.code;whitePixel&e.code; fields of the &s.code;ScrnInfoRec&e.code;
-      according to whether or not the &s.cmd;-flipPixels&e.cmd; command
-      line options is present.
-
-    </quote>
-
-    &s.code;const char *xf86GetVisualName(int visual)&e.code;
-    <quote><p>
-      Returns a printable string with the visual name matching the
-      numerical visual class provided.  If the value is outside the
-      range of valid visual classes, &s.code;NULL&e.code; is returned.
-
-    </quote>
-  </quote>
-
-
-<sect1>Primary Mode functions
-<p>
-
-The primary mode helper functions are those which would normally be
-used by a driver, unless it has unusual requirements which cannot
-be catered for the by the helpers.
-
-  <quote><p>
-    &s.code;int xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes,
-		&f.indent;char **modeNames, ClockRangePtr clockRanges,
-		&f.indent;int *linePitches, int minPitch, int maxPitch,
-		&f.indent;int pitchInc, int minHeight, int maxHeight,
-		&f.indent;int virtualX, int virtualY,
-		&f.indent;unsigned long apertureSize,
-		&f.indent;LookupModeFlags strategy)&e.code;
-    <quote><p>
-      This function basically selects the set of modes to use based on
-      those available and the various constraints.  It also sets some
-      other related parameters.  It is normally called near the end of
-      the &s.code;ChipPreInit()&e.code; function.
-
-      The parameters passed to the function are:
-
-        &s.code;availModes&e.code;
-	<quote><p>
-		List of modes available for the monitor.
-
-	</quote>
-        &s.code;modeNames&e.code;
-	<quote><p>
-		List of mode names that the screen is requesting.
-
-	</quote>
-        &s.code;clockRanges&e.code;
-	<quote><p>
-		A list of clock ranges allowed by the driver.  Each
-		range includes whether interlaced or multiscan modes
-		are supported for that range.  See below for more on
-		&s.code;clockRanges&e.code;.
-
-	</quote>
-        &s.code;linePitches&e.code;
-	<quote><p>
-		List of line pitches supported by the driver.
-		This is optional and should be &s.code;NULL&e.code; when
-		not used.
-
-	</quote>
-        &s.code;minPitch&e.code;
-	<quote><p>
-		Minimum line pitch supported by the driver.  This must
-		be supplied when &s.code;linePitches&e.code; is
-		&s.code;NULL&e.code;, and is ignored otherwise.
-
-	</quote>
-        &s.code;maxPitch&e.code;
-	<quote><p>
-		Maximum line pitch supported by the driver.  This is
-		required when &s.code;minPitch&e.code; is required.
-
-	</quote>
-        &s.code;pitchInc&e.code;
-	<quote><p>
-		Granularity of horizontal pitch values as supported by
-		the chipset.  This is expressed in bits.  This must be
-		supplied.
-
-	</quote>
-        &s.code;minHeight&e.code;
-	<quote><p>
-		minimum virtual height allowed.  If zero, no limit is
-		imposed.
-
-	</quote>
-        &s.code;maxHeight&e.code;
-	<quote><p>
-		maximum virtual height allowed.  If zero, no limit is
-		imposed.
-
-	</quote>
-        &s.code;virtualX&e.code;
-	<quote><p>
-		If greater than zero, this is the virtual width value
-		that will be used.  Otherwise, the virtual width is
-		chosen to be the smallest that can accommodate the modes
-		selected.
-
-	</quote>
-        &s.code;virtualY&e.code;
-	<quote><p>
-		If greater than zero, this is the virtual height value
-		that will be used.  Otherwise, the virtual height is
-		chosen to be the smallest that can accommodate the modes
-		selected.
-
-	</quote>
-        &s.code;apertureSize&e.code;
-	<quote><p>
-		The size (in bytes) of the aperture used to access video
-		memory.
-
-	</quote>
-        &s.code;strategy&e.code;
-	<quote><p>
-		The strategy to use when choosing from multiple modes
-		with the same name.  The options are:
-
-                &s.code;LOOKUP_DEFAULT&e.code;
-		<quote>???</quote>
-                &s.code;LOOKUP_BEST_REFRESH&e.code;
-		<quote>mode with best refresh rate</quote>
-                &s.code;LOOKUP_CLOSEST_CLOCK&e.code;
-		<quote>mode with closest matching clock</quote>
-                &s.code;LOOKUP_LIST_ORDER&e.code;
-		<quote>first usable mode in list</quote>
-
-		The following options can also be combined (OR'ed) with
-		one of the above:
-
-                &s.code;LOOKUP_CLKDIV2&e.code;
-		<quote>Allow halved clocks</quote>
-		&s.code;LOOKUP_OPTIONAL_TOLERANCES&e.code;
-		<quote>Allow missing horizontal sync and/or vertical refresh
-		ranges in the xorg.conf Monitor section</quote>
-
-		&s.code;LOOKUP_OPTIONAL_TOLERANCES&e.code; should only be
-		specified when the driver can ensure all modes it generates
-		can sync on, or at least not damage, the monitor or digital
-		flat panel.  Horizontal sync and/or vertical refresh ranges
-		specified by the user will still be honoured (and acted upon).
-
-	</quote>
-
-      This function requires that the following fields of the
-      &s.code;ScrnInfoRec&e.code; are initialised prior to calling it:
-
-        &s.code;clock[]&e.code;
-	<quote>List of discrete clocks (when non-programmable)</quote>
-        &s.code;numClocks&e.code;
-	<quote>Number of discrete clocks (when non-programmable)</quote>
-        &s.code;progClock&e.code;
-	<quote>Whether the clock is programmable or not</quote>
-        &s.code;monitor&e.code;
-	<quote>Pointer to the applicable xorg.conf monitor section</quote>
-        &s.code;fdFormat&e.code;
-	<quote>Format of the screen buffer</quote>
-        &s.code;videoRam&e.code;
-	<quote>total video memory size (in bytes)</quote>
-        &s.code;maxHValue&e.code;
-	<quote>Maximum horizontal timing value allowed</quote>
-        &s.code;maxVValue&e.code;
-	<quote>Maximum vertical timing value allowed</quote>
-        &s.code;xInc&e.code;
-	<quote>Horizontal timing increment in pixels (defaults to 8)</quote>
-
-      This function fills in the following &s.code;ScrnInfoRec&e.code;
-      fields:
-
-        &s.code;modePool&e.code;
-	<quote><p>
-		A subset of the modes available to the monitor which
-                are compatible with the driver.
-
-	</quote>
-        &s.code;modes&e.code;
-	<quote><p>
-		One mode entry for each of the requested modes, with
-                the status field of each filled in to indicate if
-                the mode has been accepted or not.  This list of
-                modes is a circular list.
-
-	</quote>
-        &s.code;virtualX&e.code;
-	<quote><p>
-		The resulting virtual width.
-
-	</quote>
-        &s.code;virtualY&e.code;
-	<quote><p>
-		The resulting virtual height.
-
-	</quote>
-        &s.code;displayWidth&e.code;
-	<quote><p>
-		The resulting line pitch.
-
-	</quote>
-        &s.code;virtualFrom&e.code;
-	<quote><p>
-		Where the virtual size was determined from.
-
-	</quote>
-
-      The first stage of this function checks that the
-      &s.code;virtualX&e.code; and &s.code;virtualY&e.code; values
-      supplied (if greater than zero) are consistent with the line pitch
-      and &s.code;maxHeight&e.code; limitations.  If not, an error
-      message is printed, and the return value is &s.code;-1&e.code;.
-
-      The second stage sets up the mode pool, eliminating immediately
-      any modes that exceed the driver's line pitch limits, and also
-      the virtual width and height limits (if greater than zero).  For
-      each mode removed an informational message is printed at verbosity
-      level &s.code;2&e.code;.  If the mode pool ends up being empty,
-      a warning message is printed, and the return value is
-      &s.code;0&e.code;.
-
-      The final stage is to lookup each mode name, and fill in the remaining
-      parameters.  If an error condition is encountered, a message is
-      printed, and the return value is &s.code;-1&e.code;.  Otherwise,
-      the return value is the number of valid modes found
-      (&s.code;0&e.code; if none are found).
-
-      Even if the supplied mode names include duplicates, no two names will
-      ever match the same mode.  Furthermore, if the supplied mode names do not
-      yield a valid mode (including the case where no names are passed at all),
-      the function will continue looking through the mode pool until it finds
-      a mode that survives all checks, or until the mode pool is exhausted.
-
-      A message is only printed by this function when a fundamental
-      problem is found.  It is intended that this function may be called
-      more than once if there is more than one set of constraints that
-      the driver can work within.
-
-      If this function returns &s.code;-1&e.code;, the
-      &s.code;ChipPreInit()&e.code; function should return
-      &s.code;FALSE&e.code;.
-
-      &s.code;clockRanges&e.code; is a linked list of clock ranges
-      allowed by the driver.  If a mode doesn't fit in any of the defined
-      &s.code;clockRanges&e.code;, it is rejected.  The first
-      &s.code;clockRange&e.code; that matches all requirements is used.
-      This structure needs to be initialized to NULL when allocated.
-
-      &s.code;clockRanges&e.code; contains the following fields:
-
-        &s.code;minClock&nl;
-        maxClock&e.code;
-	<quote><p>
-		The lower and upper mode clock bounds for which the rest
-		of the &s.code;clockRange&e.code; parameters apply.
-		Since these are the mode clocks, they are not scaled
-		with the &s.code;ClockMulFactor&e.code; and
-		&s.code;ClockDivFactor&e.code;.  It is up to the driver
-		to adjust these values if they depend on the clock
-		scaling factors.
-
-	</quote>
-        &s.code;clockIndex&e.code;
-	<quote><p>
-		(not used yet) &s.code;-1&e.code; for programmable clocks
-
-	</quote>
-        &s.code;interlaceAllowed&e.code;
-	<quote><p>
-		&s.code;TRUE&e.code; if interlacing is allowed for this
-		range
-
-	</quote>
-        &s.code;doubleScanAllowed&e.code;
-	<quote><p>
-		&s.code;TRUE&e.code; if doublescan or multiscan is allowed
-		for this range
-
-	</quote>
-        &s.code;ClockMulFactor&nl;
-        ClockDivFactor&e.code;
-	<quote><p>
-		Scaling factors that are applied to the mode clocks ONLY
-		before selecting a clock index (when there is no
-		programmable clock) or a &s.code;SynthClock&e.code;
-		value.  This is useful for drivers that support pixel
-		multiplexing or that need to scale the clocks because
-		of hardware restrictions (like sending 24bpp data to an
-		8 bit RAMDAC using a tripled clock).
-
-		Note that these parameters describe what must be done
-		to the mode clock to achieve the data transport clock
-		between graphics controller and RAMDAC.  For example
-		for &s.code;2:1&e.code; pixel multiplexing, two pixels
-		are sent to the RAMDAC on each clock.  This allows the
-		RAMDAC clock to be half of the actual pixel clock.
-		Hence, &s.code;ClockMulFactor=1&e.code; and
-		&s.code;ClockDivFactor=2&e.code;.  This means that the
-		clock used for clock selection (ie, determining the
-		correct clock index from the list of discrete clocks)
-		or for the &s.code;SynthClock&e.code; field in case of
-		a programmable clock is:  (&s.code;mode-&gt;Clock *
-		ClockMulFactor) / ClockDivFactor&e.code;.
-
-	</quote>
-	&s.code;PrivFlags&e.code;
-	<quote><p>
-		This field is copied into the
-		&s.code;mode-&gt;PrivFlags&e.code; field when this
-		&s.code;clockRange&e.code; is selected by
-		&s.code;xf86ValidateModes()&e.code;.  It allows the
-		driver to find out what clock range was selected, so it
-		knows it needs to set up pixel multiplexing or any other
-		range-dependent feature.  This field is purely
-		driver-defined: it may contain flag bits, an index or
-		anything else (as long as it is an &s.code;INT&e.code;).
-	</quote>
-
-      Note that the &s.code;mode-&gt;SynthClock&e.code; field is always
-      filled in by &s.code;xf86ValidateModes()&e.code;: it will contain
-      the ``data transport clock'', which is the clock that will have
-      to be programmed in the chip when it has a programmable clock, or
-      the clock that will be picked from the clocks list when it is not
-      a programmable one.  Thus:
-
-         &s.code;mode-&gt;SynthClock =
-		&f.indent;(mode-&gt;Clock * ClockMulFactor) / ClockDivFactor&e.code;
-
-    </quote>
-
-    &s.code;void xf86PruneDriverModes(ScrnInfoPtr scrp)&e.code;
-    <quote><p>
-      This function deletes modes in the modes field of the
-      &s.code;ScrnInfoRec&e.code; that have been marked as invalid.
-      This is normally run after having run
-      &s.code;xf86ValidateModes()&e.code; for the last time.  For each
-      mode that is deleted, a warning message is printed out indicating
-      the reason for it being deleted.
-
-    </quote>
-
-    &s.code;void xf86SetCrtcForModes(ScrnInfoPtr scrp, int adjustFlags)&e.code;
-    <quote><p>
-      This function fills in the &s.code;Crtc*&e.code; fields for all
-      the modes in the &s.code;modes&e.code; field of the
-      &s.code;ScrnInfoRec&e.code;.  The &s.code;adjustFlags&e.code;
-      parameter determines how the vertical CRTC values are scaled for
-      interlaced modes.  They are halved if it is
-      &s.code;INTERLACE_HALVE_V&e.code;.  The vertical CRTC values are
-      doubled for doublescan modes, and are further multiplied by the
-      &s.code;VScan&e.code; value.
-
-      This function is normally called after calling
-      &s.code;xf86PruneDriverModes()&e.code;.
-
-    </quote>
-
-    &s.code;void xf86PrintModes(ScrnInfoPtr scrp)&e.code;
-    <quote><p>
-      This function prints out the virtual size setting, and the line
-      pitch being used.  It also prints out two lines for each mode being
-      used.  The first line includes the mode's pixel clock, horizontal sync
-      rate, refresh rate, and whether it is interlaced, doublescanned and/or
-      multi-scanned.  The second line is the mode's Modeline.
-
-      This function is normally called after calling
-      &s.code;xf86SetCrtcForModes()&e.code;.
-
-    </quote>
-  </quote>
-
-
-<sect1>Secondary Mode functions
-<p>
-
-The secondary mode helper functions are functions which are normally
-used by the primary mode helper functions, and which are not normally
-called directly by a driver.  If a driver has unusual requirements
-and needs to do its own mode validation, it might be able to make
-use of some of these secondary mode helper functions.
-
-  <quote><p>
-    &s.code;int xf86GetNearestClock(ScrnInfoPtr scrp, int freq, Bool allowDiv2,
-			&f.indent;int *divider)&e.code;
-    <quote><p>
-      This function returns the index of the closest clock to the
-      frequency &s.code;freq&e.code; given (in kHz).  It assumes that
-      the number of clocks is greater than zero.  It requires that the
-      &s.code;numClocks&e.code; and &s.code;clock&e.code; fields of the
-      &s.code;ScrnInfoRec&e.code; are initialised.  The
-      &s.code;allowDiv2&e.code; field determines if the clocks can be
-      halved.  The &s.code;*divider&e.code; return value indicates
-      whether clock division is used when determining the clock returned.
-
-      This function is only for non-programmable clocks.
-
-    </quote>
-
-    &s.code;const char *xf86ModeStatusToString(ModeStatus status)&e.code;
-    <quote><p>
-      This function converts the &s.code;status&e.code; value to a
-      descriptive printable string.
-
-    </quote>
-
-    &s.code;ModeStatus xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep,
-		&f.indent;ClockRangePtr clockRanges, LookupModeFlags strategy)&e.code;
-    <quote><p>
-      This function takes a pointer to a mode with the name filled in,
-      and looks for a mode in the &s.code;modePool&e.code; list which
-      matches.  The parameters of the matching mode are filled in to
-      &s.code;*modep&e.code;.  The &s.code;clockRanges&e.code; and
-      &s.code;strategy&e.code; parameters are as for the
-      &s.code;xf86ValidateModes()&e.code; function above.
-
-      This function requires the &s.code;modePool&e.code;,
-      &s.code;clock[]&e.code;, &s.code;numClocks&e.code; and
-      &s.code;progClock&e.code; fields of the &s.code;ScrnInfoRec&e.code;
-      to be initialised before being called.
-
-      The return value is &s.code;MODE_OK&e.code; if a mode was found.
-      Otherwise it indicates why a matching mode could not be found.
-
-    </quote>
-
-    &s.code;ModeStatus xf86InitialCheckModeForDriver(ScrnInfoPtr scrp,
-		&f.indent;DisplayModePtr mode, ClockRangePtr clockRanges,
-		&f.indent;LookupModeFlags strategy, int maxPitch,
-		&f.indent;int virtualX, int virtualY)&e.code;
-    <quote><p>
-      This function checks the passed mode against some basic driver
-      constraints.  Apart from the ones passed explicitly, the
-      &s.code;maxHValue&e.code; and &s.code;maxVValue&e.code; fields of
-      the &s.code;ScrnInfoRec&e.code; are also used.  If the
-      &s.code;ValidMode&e.code; field of the &s.code;ScrnInfoRec&e.code;
-      is set, that function is also called to check the mode.  Next, the
-      mode is checked against the monitor's constraints.
-
-      If the mode is consistent with all constraints, the return value
-      is &s.code;MODE_OK&e.code;.  Otherwise the return value indicates
-      which constraint wasn't met.
-
-    </quote>
-
-    &s.code;void xf86DeleteMode(DisplayModePtr *modeList, DisplayModePtr mode)&e.code;
-    <quote><p>
-      This function deletes the &s.code;mode&e.code; given from the
-      &s.code;modeList&e.code;.  It never prints any messages, so it is
-      up to the caller to print a message if required.
-
-    </quote>
-  </quote>
-
-<sect1>Functions for handling strings and tokens
-<p>
-
-    Tables associating strings and numerical tokens combined with the
-    following functions provide a compact way of handling strings from
-    the config file, and for converting tokens into printable strings.
-    The table data structure is:
-
-<quote><verb>
-typedef struct {
-    int                 token;
-    const char *        name;
-} SymTabRec, *SymTabPtr;
-</verb></quote>
-
-    A table is an initialised array of &s.code;SymTabRec&e.code;.  The
-    tokens must be non-negative integers.  Multiple names may be mapped
-    to a single token.  The table is terminated with an element with a
-    &s.code;token&e.code; value of &s.code;-1&e.code; and
-    &s.code;NULL&e.code; for the &s.code;name&e.code;.
-
-
-  <quote><p>
-    &s.code;const char *xf86TokenToString(SymTabPtr table, int token)&e.code;
-    <quote><p>
-      This function returns the first string in &s.code;table&e.code;
-      that matches &s.code;token&e.code;.  If no match is found,
-      &s.code;NULL&e.code; is returned (NOTE, older versions of this
-      function would return the string "unknown" when no match is found).
-
-    </quote>
-
-    &s.code;int xf86StringToToken(SymTabPtr table, const char *string)&e.code;
-    <quote><p>
-      This function returns the first token in &s.code;table&e.code;
-      that matches &s.code;string&e.code;.  The
-      &s.code;xf86NameCmp()&e.code; function is used to determine the
-      match.  If no match is found, &s.code;-1&e.code; is returned.
-
-    </quote>
-  </quote>
-
-
-<sect1>Functions for finding which config file entries to use
-<p>
-
-    These functions can be used to select the appropriate config file
-    entries that match the detected hardware.  They are described above
-    in the <ref id="probe" name="Probe"> and
-    <ref id="avail" name="Available Functions"> sections.
-
-
-<sect1>Probing discrete clocks on old hardware
-<p>
-
-    The &s.code;xf86GetClocks()&e.code; function may be used to assist
-    in finding the discrete pixel clock values on older hardware.
-
-
-  <quote><p>
-    &s.code;void xf86GetClocks(ScrnInfoPtr pScrn, int num,
-		&f.indent;Bool (*ClockFunc)(ScrnInfoPtr, int),
-		&f.indent;void (*ProtectRegs)(ScrnInfoPtr, Bool),
-		&f.indent;void (*BlankScreen)(ScrnInfoPtr, Bool),
-		&f.indent;int vertsyncreg, int maskval, int knownclkindex,
-		&f.indent;int knownclkvalue)&e.code;
-    <quote><p>
-      This function uses a comparative sampling method to measure the
-      discrete pixel clock values.  The number of discrete clocks to
-      measure is given by &s.code;num&e.code;.  &s.code;clockFunc&e.code;
-      is a function that selects the &s.code;n&e.code;'th clock.  It
-      should also save or restore any state affected by programming the
-      clocks when the index passed is &s.code;CLK_REG_SAVE&e.code; or
-      &s.code;CLK_REG_RESTORE&e.code;.  &s.code;ProtectRegs&e.code; is
-      a function that does whatever is required to protect the hardware
-      state while selecting a new clock.  &s.code;BlankScreen&e.code;
-      is a function that blanks the screen.  &s.code;vertsyncreg&e.code;
-      and &s.code;maskval&e.code; are the register and bitmask to
-      check for the presence of vertical sync pulses.
-      &s.code;knownclkindex&e.code; and &s.code;knownclkvalue&e.code;
-      are the index and value of a known clock.  These are the known
-      references on which the comparative measurements are based.  The
-      number of clocks probed is set in &s.code;pScrn-&gt;numClocks&e.code;,
-      and the probed clocks are set in the &s.code;pScrn-&gt;clock[]&e.code;
-      array.  All of the clock values are in units of kHz.
-
-    </quote>
-
-    &s.code;void xf86ShowClocks(ScrnInfoPtr scrp, MessageType from)&e.code;
-    <quote><p>
-      Print out the pixel clocks &s.code;scrp-&gt;clock[]&e.code;.
-      &s.code;from&e.code; indicates whether the clocks were probed
-      or from the config file.
-
-    </quote>
-  </quote>
-
-<sect1>Other helper functions
-<p>
-  <quote><p>
-    &s.code;Bool xf86IsUnblank(int mode)&e.code;
-    <quote><p>
-      Returns &s.code;TRUE&e.code; when the screen saver mode specified
-      by &s.code;mode&e.code; requires the screen be unblanked,
-      and &s.code;FALSE&e.code; otherwise.  The screen saver modes that
-      require blanking are &s.code;SCREEN_SAVER_ON&e.code; and
-      &s.code;SCREEN_SAVER_CYCLE&e.code;, and the screen saver modes that
-      require unblanking are &s.code;SCREEN_SAVER_OFF&e.code; and
-      &s.code;SCREEN_SAVER_FORCER&e.code;.  Drivers may call this helper
-      from their &s.code;SaveScreen()&e.code; function to interpret the
-      screen saver modes.
-
-    </quote>
-  </quote>
-
-<sect>The vgahw module
-<p>
-
-The vgahw modules provides an interface for saving, restoring and
-programming the standard VGA registers, and for handling VGA colourmaps.
-
-<sect1>Data Structures
-<p>
-
-    The public data structures used by the vgahw module are
-    &s.code;vgaRegRec&e.code; and &s.code;vgaHWRec&e.code;.  They are
-    defined in &s.code;vgaHW.h.&e.code;
-
-
-<sect1>General vgahw Functions
-<p>
-
-  <quote><p>
-    &s.code;Bool vgaHWGetHWRec(ScrnInfoPtr pScrn)&e.code;
-    <quote><p>
-      This function allocates a &s.code;vgaHWRec&e.code; structure, and
-      hooks it into the &s.code;ScrnInfoRec&e.code;'s
-      &s.code;privates&e.code;.  Like all information hooked into the
-      &s.code;privates&e.code;, it is persistent, and only needs to be
-      allocated once per screen.  This function should normally be called
-      from the driver's &s.code;ChipPreInit()&e.code; function.  The
-      &s.code;vgaHWRec&e.code; is zero-allocated, and the following
-      fields are explicitly initialised:
-
-        &s.code;ModeReg.DAC[]&e.code;
-	<quote>initialised with a default colourmap</quote>
-        &s.code;ModeReg.Attribute[0x11]&e.code;
-	<quote>initialised with the default overscan index</quote>
-        &s.code;ShowOverscan&e.code;
-	<quote>initialised according to the "ShowOverscan" option</quote>
-        &s.code;paletteEnabled&e.code;
-	<quote>initialised to FALSE</quote>
-        &s.code;cmapSaved&e.code;
-	<quote>initialised to FALSE</quote>
-        &s.code;pScrn&e.code;
-	<quote>initialised to pScrn</quote>
-
-      In addition to the above, &s.code;vgaHWSetStdFuncs()&e.code; is
-      called to initialise the register access function fields with the
-      standard VGA set of functions.
-
-      Once allocated, a pointer to the &s.code;vgaHWRec&e.code; can be
-      obtained from the &s.code;ScrnInfoPtr&e.code; with the
-      &s.code;VGAHWPTR(pScrn)&e.code; macro.
-
-    </quote>
-
-    &s.code;void vgaHWFreeHWRec(ScrnInfoPtr pScrn)&e.code;
-    <quote><p>
-      This function frees a &s.code;vgaHWRec&e.code; structure.  It
-      should be called from a driver's &s.code;ChipFreeScreen()&e.code;
-      function.
-
-    </quote>
-
-    &s.code;Bool vgaHWSetRegCounts(ScrnInfoPtr pScrn, int numCRTC,
-		&f.indent;int numSequencer, int numGraphics, int numAttribute)&e.code;
-    <quote><p>
-      This function allows the number of CRTC, Sequencer, Graphics and
-      Attribute registers to be changed.  This makes it possible for
-      extended registers to be saved and restored with
-      &s.code;vgaHWSave()&e.code; and &s.code;vgaHWRestore()&e.code;.
-      This function should be called after a &s.code;vgaHWRec&e.code;
-      has been allocated with &s.code;vgaHWGetHWRec()&e.code;.  The
-      default values are defined in &s.code;vgaHW.h&e.code; as follows:
-
-      <quote><verb>
-#define VGA_NUM_CRTC 25
-#define VGA_NUM_SEQ   5
-#define VGA_NUM_GFX   9
-#define VGA_NUM_ATTR 21
-      </verb></quote>
-
-    </quote>
-
-    &s.code;Bool vgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src)&e.code;
-    <quote><p>
-      This function copies the contents of the VGA saved registers in
-      &s.code;src&e.code; to &s.code;dst&e.code;.  Note that it isn't
-      possible to simply do this with &s.code;memcpy()&e.code; (or
-      similar).  This function returns &s.code;TRUE&e.code; unless there
-      is a problem allocating space for the &s.code;CRTC&e.code and
-      related fields in &s.code;dst&e.code;.
-
-    </quote>
-
-    &s.code;void vgaHWSetStdFuncs(vgaHWPtr hwp)&e.code;
-    <quote><p>
-      This function initialises the register access function fields of
-      &s.code;hwp&e.code; with the standard VGA set of functions.  This
-      is called by &s.code;vgaHWGetHWRec()&e.code;, so there is usually
-      no need to call this explicitly.  The register access functions
-      are described below.  If the registers are shadowed in some other
-      port I/O space (for example a PCI I/O region), these functions
-      can be used to access the shadowed registers if
-      &s.code;hwp-&gt;PIOOffset&e.code; is initialised with
-      &s.code;offset&e.code;, calculated in such a way that when the
-      standard VGA I/O port value is added to it the correct offset into
-      the PIO area results.  This value is initialised to zero in
-      &s.code;vgaHWGetHWRec()&e.code;.  (Note: the PIOOffset functionality
-      is present in XFree86 4.1.0 and later.)
-
-    </quote>
-
-    &s.code;void vgaHWSetMmioFuncs(vgaHWPtr hwp, CARD8 *base, int offset)&e.code;
-    <quote><p>
-      This function initialised the register access function fields of
-      hwp with a generic MMIO set of functions.
-      &s.code;hwp-&gt;MMIOBase&e.code; is initialised with
-      &s.code;base&e.code;, which must be the virtual address that the
-      start of MMIO area is mapped to.  &s.code;hwp-&gt;MMIOOffset&e.code;
-      is initialised with &s.code;offset&e.code;, which must be calculated
-      in such a way that when the standard VGA I/O port value is added
-      to it the correct offset into the MMIO area results.  That means
-      that these functions are only suitable when the VGA I/O ports are
-      made available in a direct mapping to the MMIO space.  If that is
-      not the case, the driver will need to provide its own register
-      access functions.  The register access functions are described
-      below.
-
-    </quote>
-
-    &s.code;Bool vgaHWMapMem(ScrnInfoPtr pScrn)&e.code;
-    <quote><p>
-      This function maps the VGA memory window.  It requires that the
-      &s.code;vgaHWRec&e.code; be allocated.  If a driver requires
-      non-default &s.code;MapPhys&e.code; or &s.code;MapSize&e.code;
-      settings (the physical location and size of the VGA memory window)
-      then those fields of the &s.code;vgaHWRec&e.code; must be initialised
-      before calling this function.  Otherwise, this function initialiases
-      the default values of &s.code;0xA0000&e.code; for
-      &s.code;MapPhys&e.code; and &s.code;(64&nbsp;*&nbsp;1024)&e.code; for
-      &s.code;MapSize&e.code;.  This function must be called before
-      attempting to save or restore the VGA state.  If the driver doesn't
-      call it explicitly, the &s.code;vgaHWSave()&e.code; and
-      &s.code;vgaHWRestore()&e.code; functions may call it if they need
-      to access the VGA memory (in which case they will also call
-      &s.code;vgaHWUnmapMem()&e.code; to unmap the VGA memory before
-      exiting).
-
-    </quote>
-
-    &s.code;void vgaHWUnmapMem(ScrnInfoPtr pScrn)&e.code;
-    <quote><p>
-      This function unmaps the VGA memory window.  It must only be called
-      after the memory has been mapped.  The &s.code;Base&e.code; field
-      of the &s.code;vgaHWRec&e.code; field is set to &s.code;NULL&e.code;
-      to indicate that the memory is no longer mapped.
-
-    </quote>
-
-    &s.code;void vgaHWGetIOBase(vgaHWPtr hwp)&e.code;
-    <quote><p>
-      This function initialises the &s.code;IOBase&e.code; field of the
-      &s.code;vgaHWRec&e.code;.  This function must be called before
-      using any other functions that access the video hardware.
-
-      A macro &s.code;VGAHW_GET_IOBASE()&e.code; is also available in
-      &s.code;vgaHW.h&e.code; that returns the I/O base, and this may
-      be used when the vgahw module is not loaded (for example, in the
-      &s.code;ChipProbe()&e.code; function).
-
-    </quote>
-
-    &s.code;void vgaHWUnlock(vgaHWPtr hwp)&e.code;
-    <quote><p>
-      This function unlocks the VGA &s.code;CRTC[0-7]&e.code; registers,
-      and must be called before attempting to write to those registers.
-
-    </quote>
-
-    &s.code;void vgaHWLock(vgaHWPtr hwp)&e.code;
-    <quote><p>
-      This function locks the VGA &s.code;CRTC[0-7]&e.code; registers.
-
-    </quote>
-
-    &s.code;void vgaHWEnable(vgaHWPtr hwp)&e.code;
-    <quote><p>
-      This function enables the VGA subsystem.  (Note, this function is
-      present in XFree86 4.1.0 and later.).
-
-    </quote>
-
-    &s.code;void vgaHWDisable(vgaHWPtr hwp)&e.code;
-    <quote><p>
-      This function disables the VGA subsystem.  (Note, this function is
-      present in XFree86 4.1.0 and later.).
-
-    </quote>
-
-    &s.code;void vgaHWSave(ScrnInfoPtr pScrn, vgaRegPtr save, int flags)&e.code;
-    <quote><p>
-      This function saves the VGA state.  The state is written to the
-      &s.code;vgaRegRec&e.code; pointed to by &s.code;save&e.code;.
-      &s.code;flags&e.code; is set to one or more of the following flags
-      ORed together:
-
-        &s.code;VGA_SR_MODE&e.code;
-	<quote>the mode setting registers are saved</quote>
-        &s.code;VGA_SR_FONTS&e.code;
-	<quote>the text mode font/text data is saved</quote>
-        &s.code;VGA_SR_CMAP&e.code;
-	<quote>the colourmap (LUT) is saved</quote>
-        &s.code;VGA_SR_ALL&e.code;
-	<quote>all of the above are saved</quote>
-
-      The &s.code;vgaHWRec&e.code; and its &s.code;IOBase&e.code; fields
-      must be initialised before this function is called.  If
-      &s.code;VGA_SR_FONTS&e.code; is set in &s.code;flags&e.code;, the
-      VGA memory window must be mapped.  If it isn't then
-      &s.code;vgaHWMapMem()&e.code; will be called to map it, and
-      &s.code;vgaHWUnmapMem()&e.code; will be called to unmap it
-      afterwards.  &s.code;vgaHWSave()&e.code; uses the three functions
-      below in the order &s.code;vgaHWSaveColormap()&e.code;,
-      &s.code;vgaHWSaveMode()&e.code;, &s.code;vgaHWSaveFonts()&e.code; to
-      carry out the different save phases.  It is undecided at this
-      stage whether they will remain part of the vgahw module's public
-      interface or not.
-
-    </quote>
-
-    &s.code;void vgaHWSaveMode(ScrnInfoPtr pScrn, vgaRegPtr save)&e.code;
-    <quote><p>
-      This function saves the VGA mode registers.  They are saved to
-      the &s.code;vgaRegRec&e.code; pointed to by &s.code;save&e.code;.
-      The registers saved are:
-
-	<quote>
-        &s.code;MiscOut&nl;
-        CRTC[0-0x18]&nl;
-        Attribute[0-0x14]&nl;
-        Graphics[0-8]&nl;
-        Sequencer[0-4]&e.code;
-	</quote>
-
-    The number of registers actually saved may be modified by a prior call
-    to &s.code;vgaHWSetRegCounts()&e.code;.
-
-    </quote>
-
-    &s.code;void vgaHWSaveFonts(ScrnInfoPtr pScrn, vgaRegPtr save)&e.code;
-    <quote><p>
-      This function saves the text mode font and text data held in the
-      video memory.  If called while in a graphics mode, no save is
-      done.  The VGA memory window must be mapped with
-      &s.code;vgaHWMapMem()&e.code; before to calling this function.
-
-      On some platforms, one or more of the font/text plane saves may be
-      no-ops.  This is the case when the platform's VC driver already
-      takes care of this.
-
-    </quote>
-
-    &s.code;void vgaHWSaveColormap(ScrnInfoPtr pScrn, vgaRegPtr save)&e.code;
-    <quote><p>
-      This function saves the VGA colourmap (LUT).  Before saving it, it
-      attempts to verify that the colourmap is readable.  In rare cases
-      where it isn't readable, a default colourmap is saved instead.
-
-    </quote>
-
-    &s.code;void vgaHWRestore(ScrnInfoPtr pScrn, vgaRegPtr restore, int flags)&e.code;
-    <quote><p>
-      This function programs the VGA state.  The state programmed is
-      that contained in the &s.code;vgaRegRec&e.code; pointed to by
-      &s.code;restore&e.code;.  &s.code;flags&e.code; is the same
-      as described above for the &s.code;vgaHWSave()&e.code; function.
-
-      The &s.code;vgaHWRec&e.code; and its &s.code;IOBase&e.code; fields
-      must be initialised before this function is called.  If
-      &s.code;VGA_SR_FONTS&e.code; is set in &s.code;flags&e.code;, the
-      VGA memory window must be mapped.  If it isn't then
-      &s.code;vgaHWMapMem()&e.code; will be called to map it, and
-      &s.code;vgaHWUnmapMem()&e.code; will be called to unmap it
-      afterwards.  &s.code;vgaHWRestore()&e.code; uses the three functions
-      below in the order &s.code;vgaHWRestoreFonts()&e.code;,
-      &s.code;vgaHWRestoreMode()&e.code;,
-      &s.code;vgaHWRestoreColormap()&e.code; to carry out the different
-      restore phases.  It is undecided at this stage whether they will
-      remain part of the vgahw module's public interface or not.
-
-    </quote>
-
-    &s.code;void vgaHWRestoreMode(ScrnInfoPtr pScrn, vgaRegPtr restore)&e.code;
-    <quote><p>
-      This function restores the VGA mode registers.  They are restored
-      from the data in the &s.code;vgaRegRec&e.code; pointed to by
-      &s.code;restore&e.code;.  The registers restored are:
-
-	<quote>
-        &s.code;MiscOut&nl;
-        CRTC[0-0x18]&nl;
-        Attribute[0-0x14]&nl;
-        Graphics[0-8]&nl;
-        Sequencer[0-4]&e.code;
-	</quote>
-
-    The number of registers actually restored may be modified by a prior call
-    to &s.code;vgaHWSetRegCounts()&e.code;.
-
-    </quote>
-
-    &s.code;void vgaHWRestoreFonts(ScrnInfoPtr pScrn, vgaRegPtr restore)&e.code;
-    <quote><p>
-      This function restores the text mode font and text data to the
-      video memory.  The VGA memory window must be mapped with
-      &s.code;vgaHWMapMem()&e.code; before to calling this function.
-
-      On some platforms, one or more of the font/text plane restores
-      may be no-ops.  This is the case when the platform's VC driver
-      already takes care of this.
-
-    </quote>
-
-    &s.code;void vgaHWRestoreColormap(ScrnInfoPtr pScrn, vgaRegPtr restore)&e.code;
-    <quote><p>
-      This function restores the VGA colourmap (LUT).
-
-    </quote>
-
-    &s.code;void vgaHWInit(ScrnInfoPtr pScrn, DisplayModePtr mode)&e.code;
-    <quote><p>
-      This function fills in the &s.code;vgaHWRec&e.code;'s
-      &s.code;ModeReg&e.code; field with the values appropriate for
-      programming the given video mode.  It requires that the
-      &s.code;ScrnInfoRec&e.code;'s &s.code;depth&e.code; field is
-      initialised, which determines how the registers are programmed.
-
-    </quote>
-
-    &s.code;void vgaHWSeqReset(vgaHWPtr hwp, Bool start)&e.code;
-    <quote><p>
-      Do a VGA sequencer reset.  If start is &s.code;TRUE&e.code;, the
-      reset is started.  If start is &s.code;FALSE&e.code;, the reset
-      is ended.
-
-    </quote>
-
-    &s.code;void vgaHWProtect(ScrnInfoPtr pScrn, Bool on)&e.code;
-    <quote><p>
-      This function protects VGA registers and memory from corruption
-      during loads.  It is typically called with on set to
-      &s.code;TRUE&e.code; before programming, and with on set to
-      &s.code;FALSE&e.code; after programming.
-
-    </quote>
-
-    &s.code;Bool vgaHWSaveScreen(ScreenPtr pScreen, int mode)&e.code;
-    <quote><p>
-      This function blanks and unblanks the screen.  It is blanked when
-      &s.code;mode&e.code; is &s.code;SCREEN_SAVER_ON&e.code; or
-      &s.code;SCREEN_SAVER_CYCLE&e.code;, and unblanked when
-      &s.code;mode&e.code; is &s.code;SCREEN_SAVER_OFF&e.code; or
-      &s.code;SCREEN_SAVER_FORCER&e.code;.
-
-    </quote>
-
-    &s.code;void vgaHWBlankScreen(ScrnInfoPtr pScrn, Bool on)&e.code;
-    <quote><p>
-      This function blanks and unblanks the screen.  It is blanked when
-      &s.code;on&e.code; is &s.code;FALSE&e.code;, and unblanked when
-      &s.code;on&e.code; is &s.code;TRUE&e.code;.  This function is
-      provided for use in cases where the &s.code;ScrnInfoRec&e.code;
-      can't be derived from the &s.code;ScreenRec&e.code; (while probing
-      for clocks, for example).
-
-    </quote>
-  </quote>
-
-<sect1>VGA Colormap Functions
-<p>
-
-    The vgahw module uses the standard colormap support (see the
-    <ref id="cmap" name="Colormap Handling"> section.  This is initialised
-    with the following function:
-
-  <quote>
-      &s.code;Bool vgaHWHandleColormaps(ScreenPtr pScreen)&e.code;
-  </quote>
-
-
-<sect1>VGA Register Access Functions
-<p>
-
-    The vgahw module abstracts access to the standard VGA registers by
-    using a set of functions held in the &s.code;vgaHWRec&e.code;.  When
-    the &s.code;vgaHWRec&e.code; is created these function pointers are
-    initialised with the set of standard VGA I/O register access functions.
-    In addition to these, the vgahw module includes a basic set of MMIO
-    register access functions, and the &s.code;vgaHWRec&e.code; function
-    pointers can be initialised to these by calling the
-    &s.code;vgaHWSetMmioFuncs()&e.code; function described above.  Some
-    drivers/platforms may require a different set of functions for VGA
-    access.  The access functions are described here.
-
-
-  <quote><p>
-    &s.code;void writeCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)&e.code;
-    <quote><p>
-      Write &s.code;value&e.code; to CRTC register &s.code;index&e.code;.
-
-    </quote>
-
-    &s.code;CARD8 readCrtc(vgaHWPtr hwp, CARD8 index)&e.code;
-    <quote><p>
-      Return the value read from CRTC register &s.code;index&e.code;.
-
-    </quote>
-
-    &s.code;void writeGr(vgaHWPtr hwp, CARD8 index, CARD8 value)&e.code;
-    <quote><p>
-      Write &s.code;value&e.code; to Graphics Controller register
-      &s.code;index&e.code;.
-
-    </quote>
-
-    &s.code;CARD8 readGR(vgaHWPtr hwp, CARD8 index)&e.code;
-    <quote><p>
-      Return the value read from Graphics Controller register
-      &s.code;index&e.code;.
-
-    </quote>
-
-    &s.code;void writeSeq(vgaHWPtr hwp, CARD8 index, CARD8, value)&e.code;
-    <quote><p>
-      Write &s.code;value&e.code; to Sequencer register
-      &s.code;index&e.code;.
-
-    </quote>
-
-    &s.code;CARD8 readSeq(vgaHWPtr hwp, CARD8 index)&e.code;
-    <quote><p>
-      Return the value read from Sequencer register &s.code;index&e.code;.
-
-    </quote>
-
-    &s.code;void writeAttr(vgaHWPtr hwp, CARD8 index, CARD8, value)&e.code;
-    <quote><p>
-      Write &s.code;value&e.code; to Attribute Controller register
-      &s.code;index&e.code;.  When writing out the index value this
-      function should set bit 5 (&s.code;0x20&e.code;) according to the
-      setting of &s.code;hwp-&gt;paletteEnabled&e.code; in order to
-      preserve the palette access state.  It should be cleared when
-      &s.code;hwp-&gt;paletteEnabled&e.code; is &s.code;TRUE&e.code;
-      and set when it is &s.code;FALSE&e.code;.
-
-    </quote>
-
-    &s.code;CARD8 readAttr(vgaHWPtr hwp, CARD8 index)&e.code;
-    <quote><p>
-      Return the value read from Attribute Controller register
-      &s.code;index&e.code;.  When writing out the index value this
-      function should set bit 5 (&s.code;0x20&e.code;) according to the
-      setting of &s.code;hwp-&gt;paletteEnabled&e.code; in order to
-      preserve the palette access state.  It should be cleared when
-      &s.code;hwp-&gt;paletteEnabled&e.code; is &s.code;TRUE&e.code;
-      and set when it is &s.code;FALSE&e.code;.
-
-    </quote>
-
-    &s.code;void writeMiscOut(vgaHWPtr hwp, CARD8 value)&e.code;
-    <quote><p>
-      Write `&s.code;value&e.code;' to the Miscellaneous Output register.
-
-    </quote>
-
-    &s.code;CARD8 readMiscOut(vgwHWPtr hwp)&e.code;
-    <quote><p>
-      Return the value read from the Miscellaneous Output register.
-
-    </quote>
-
-    &s.code;void enablePalette(vgaHWPtr hwp)&e.code;
-    <quote><p>
-      Clear the palette address source bit in the Attribute Controller
-      index register and set &s.code;hwp-&gt;paletteEnabled&e.code; to
-      &s.code;TRUE&e.code;.
-
-    </quote>
-
-    &s.code;void disablePalette(vgaHWPtr hwp)&e.code;
-    <quote><p>
-      Set the palette address source bit in the Attribute Controller
-      index register and set &s.code;hwp-&gt;paletteEnabled&e.code; to
-      &s.code;FALSE&e.code;.
-
-    </quote>
-
-    &s.code;void writeDacMask(vgaHWPtr hwp, CARD8 value)&e.code;
-    <quote><p>
-      Write &s.code;value&e.code; to the DAC Mask register.
-
-    </quote>
-
-    &s.code;CARD8 readDacMask(vgaHWptr hwp)&e.code;
-    <quote><p>
-      Return the value read from the DAC Mask register.
-
-    </quote>
-
-    &s.code;void writeDacReadAddress(vgaHWPtr hwp, CARD8 value)&e.code;
-    <quote><p>
-      Write &s.code;value&e.code; to the DAC Read Address register.
-
-    </quote>
-
-    &s.code;void writeDacWriteAddress(vgaHWPtr hwp, CARD8 value)&e.code;
-    <quote><p>
-      Write &s.code;value&e.code; to the DAC Write Address register.
-
-    </quote>
-
-    &s.code;void writeDacData(vgaHWPtr hwp, CARD8 value)&e.code;
-    <quote><p>
-      Write &s.code;value&e.code; to the DAC Data register.
-
-    </quote>
-
-    &s.code;CARD8 readDacData(vgaHWptr hwp)&e.code;
-    <quote><p>
-      Return the value read from the DAC Data register.
-
-    </quote>
-
-    &s.code;CARD8 readEnable(vgaHWptr hwp)&e.code;
-    <quote><p>
-      Return the value read from the VGA Enable register.  (Note: This
-      function is present in XFree86 4.1.0 and later.)
-
-    </quote>
-
-    &s.code;void writeEnable(vgaHWPtr hwp, CARD8 value)&e.code;
-    <quote><p>
-      Write &s.code;value&e.code; to the VGA Enable register.  (Note: This
-      function is present in XFree86 4.1.0 and later.)
-
-    </quote>
-  </quote>
-
-<sect>Some notes about writing a driver<label id="sample">
-<p>
-
-<em>NOTE: some parts of this are not up to date</em>
-
-The following is an outline for writing a basic unaccelerated driver
-for a PCI video card with a linear mapped framebuffer, and which has a
-VGA core.  It is includes some general information that is relevant to
-most drivers (even those which don't fit that basic description).
-
-The information here is based on the initial conversion of the Matrox
-Millennium driver to the ``new design''.  For a fleshing out and sample
-implementation of some of the bits outlined here, refer to that driver.
-Note that this is an example only.  The approach used here will not be
-appropriate for all drivers.
-
-Each driver must reserve a unique driver name, and a string that is used
-to prefix all of its externally visible symbols.  This is to avoid name
-space clashes when loading multiple drivers.  The examples here are for
-the ``ZZZ'' driver, which uses the ``ZZZ'' or ``zzz'' prefix for its externally
-visible symbols.
-
-
-<sect1>Include files
-<p>
-
-  All drivers normally include the following headers:
-  <quote>
-    &s.code;"xf86.h"&nl;
-    "xf86_OSproc.h"&nl;
-    "xf86_ansic.h"&nl;
-    "xf86Resources.h"&e.code;
-  </quote>
-  Wherever inb/outb (and related things) are used the following should be
-  included:
-  <quote>
-    &s.code;"compiler.h"&e.code;
-  </quote>
-  Note: in drivers, this must be included after &s.code;"xf86_ansic.h"&e.code;.
-
-  Drivers that need to access PCI vendor/device definitions need this:
-  <quote>
-    &s.code;"xf86PciInfo.h"&e.code;
-  </quote>
-
-  Drivers that need to access the PCI config space need this:
-  <quote>
-    &s.code;"xf86Pci.h"&e.code;
-  </quote>
-
-  Drivers using the mi banking wrapper need:
-
-  <quote>
-    &s.code;"mibank.h"&e.code;
-  </quote>
-
-  Drivers that initialise a SW cursor need this:
-  <quote>
-    &s.code;"mipointer.h"&e.code;
-  </quote>
-
-  All drivers implementing backing store need this:
-  <quote>
-    &s.code;"mibstore.h"&e.code;
-  </quote>
-
-  All drivers using the mi colourmap code need this:
-  <quote>
-    &s.code;"micmap.h"&e.code;
-  </quote>
-
-  If a driver uses the vgahw module, it needs this:
-  <quote>
-    &s.code;"vgaHW.h"&e.code;
-  </quote>
-
-  Drivers supporting VGA or Hercules monochrome screens need:
-  <quote>
-    &s.code;"xf1bpp.h"&e.code;
-  </quote>
-
-  Drivers supporting VGA or EGC 16-colour screens need:
-  <quote>
-    &s.code;"xf4bpp.h"&e.code;
-  </quote>
-
-  Drivers using cfb need:
-  <quote>
-    &s.code;#define PSZ 8&nl;
-    #include "cfb.h"&nl;
-    #undef PSZ&e.code;
-  </quote>
-
-  Drivers supporting bpp 16, 24 or 32 with cfb need one or more of:
-  <quote>
-    &s.code;"cfb16.h"&nl;
-    "cfb24.h"&nl;
-    "cfb32.h"&e.code;
-  </quote>
-
-  The driver's own header file:
-  <quote>
-    &s.code;"zzz.h"&e.code;
-  </quote>
-
-  Drivers must NOT include the following:
-
- <quote>
-    &s.code;"xf86Priv.h"&nl;
-    "xf86Privstr.h"&nl;
-    "xf86_libc.h"&nl;
-    "xf86_OSlib.h"&nl;
-    "Xos.h"&e.code;&nl;
-    any OS header
- </quote>
-
-
-<sect1>Data structures and initialisation
-<p>
-
-<itemize>
-  <item>The following macros should be defined:
-    <code>
-#define VERSION <version-as-an-int>
-#define ZZZ_NAME "ZZZ"         /* the name used to prefix messages */
-#define ZZZ_DRIVER_NAME "zzz"  /* the driver name as used in config file */
-#define ZZZ_MAJOR_VERSION <int>
-#define ZZZ_MINOR_VERSION <int>
-#define ZZZ_PATCHLEVEL    <int>
-    </code>
-<p>
-    NOTE: &s.code;ZZZ_DRIVER_NAME&e.code; should match the name of the
-    driver module without things like the "lib" prefix, the "_drv" suffix
-    or filename extensions.
-<p>
-
-  <item>A DriverRec must be defined, which includes the functions required
-    at the pre-probe phase.  The name of this DriverRec must be an
-    upper-case version of ZZZ_DRIVER_NAME (for the purposes of static
-    linking).
-<p>
-    <code>
-DriverRec ZZZ = {
-    VERSION,
-    ZZZ_DRIVER_NAME,
-    ZZZIdentify,
-    ZZZProbe,
-    ZZZAvailableOptions,
-    NULL,
-    0
-};
-    </code>
-
-  <item>Define list of supported chips and their matching ID:
-<p>
-    <code>
-static SymTabRec ZZZChipsets[] = {
-    { PCI_CHIP_ZZZ1234, "zzz1234a" },
-    { PCI_CHIP_ZZZ5678, "zzz5678a" },
-    { -1,               NULL }
-};
-    </code>
-<p>
-    The token field may be any integer value that the driver may use to
-    uniquely identify the supported chipsets.  For drivers that support
-    only PCI devices using the PCI device IDs might be a natural choice,
-    but this isn't mandatory.  For drivers that support both PCI and other
-    devices (like ISA), some other ID should probably used.  When other
-    IDs are used as the tokens it is recommended that the names be
-    defined as an &s.code;enum&e.code; type.
-<p>
-  <item>If the driver uses the &s.code;xf86MatchPciInstances(&e.code;)
-    helper (recommended for drivers that support PCI cards) a list that
-    maps PCI IDs to chip IDs and fixed resources must be defined:
-<p>
-    <code>
-static PciChipsets ZZZPciChipsets[] = {
-    { PCI_CHIP_ZZZ1234, PCI_CHIP_ZZZ1234, RES_SHARED_VGA },
-    { PCI_CHIP_ZZZ5678, PCI_CHIP_ZZZ5678, RES_SHARED_VGA },
-    { -1,               -1,               RES_UNDEFINED }
-}
-    </code>
-<p>
-  <item>Define the &s.code;XF86ModuleVersionInfo&e.code; struct for the
-    driver.  This is required for the dynamically loaded version:
-<p>
-    <code>
-static XF86ModuleVersionInfo zzzVersRec =
-{
-    "zzz",
-    MODULEVENDORSTRING,
-    MODINFOSTRING1,
-    MODINFOSTRING2,
-    XF86_VERSION_CURRENT,
-    ZZZ_MAJOR_VERSION, ZZZ_MINOR_VERSION, ZZZ_PATCHLEVEL,
-    ABI_CLASS_VIDEODRV,
-    ABI_VIDEODRV_VERSION,
-    MOD_CLASS_VIDEODRV,
-    {0,0,0,0}
-};
-    </code>
-<p>
-  <item>Define a data structure to hold the driver's screen-specific data.
-    This must be used instead of global variables.  This would be defined
-    in the &s.code;"zzz.h"&e.code; file, something like:
-<p>
-    <code>
-typedef struct {
-    type1  field1;
-    type2  field2;
-    int    fooHack;
-    Bool   pciRetry;
-    Bool   noAccel;
-    Bool   hwCursor;
-    CloseScreenProcPtr CloseScreen;
-    OptionInfoPtr Options;
-    ...
-} ZZZRec, *ZZZPtr;
-    </code>
-<p>
-  <item>Define the list of config file Options that the driver accepts.  For
-    consistency between drivers those in the list of ``standard'' options
-    should be used where appropriate before inventing new options.
-<p>
-    <code>
-typedef enum {
-    OPTION_FOO_HACK,
-    OPTION_PCI_RETRY,
-    OPTION_HW_CURSOR,
-    OPTION_NOACCEL
-} ZZZOpts;
-
-static const OptionInfoRec ZZZOptions[] = {
-  { OPTION_FOO_HACK,  "FooHack",   OPTV_INTEGER, {0}, FALSE },
-  { OPTION_PCI_RETRY, "PciRetry",  OPTV_BOOLEAN, {0}, FALSE },
-  { OPTION_HW_CURSOR, "HWcursor",  OPTV_BOOLEAN, {0}, FALSE },
-  { OPTION_NOACCEL,   "NoAccel",   OPTV_BOOLEAN, {0}, FALSE },
-  { -1,               NULL,        OPTV_NONE,    {0}, FALSE }
-};
-    </code>
-<p>
-</itemize>
-
-<sect1>Functions
-<p>
-
-
-<sect2>SetupProc
-<p>
-
-    For dynamically loaded modules, a &s.code;ModuleData&e.code;
-    variable is required.  It is should be the name of the driver
-    prepended to "ModuleData".  A &s.code;Setup()&e.code; function is
-    also required, which calls &s.code;xf86AddDriver()&e.code; to add
-    the driver to the main list of drivers.
-
-    <code>
-static MODULESETUPPROTO(zzzSetup);
-
-XF86ModuleData zzzModuleData = { &amp;zzzVersRec, zzzSetup, NULL };
-
-static pointer
-zzzSetup(pointer module, pointer opts, int *errmaj, int *errmin)
-{
-    static Bool setupDone = FALSE;
-
-    /* This module should be loaded only once, but check to be sure. */
-
-    if (!setupDone) {
-        /*
-         * Modules that this driver always requires may be loaded
-         * here  by calling LoadSubModule().
-         */
-
-        setupDone = TRUE;
-        xf86AddDriver(&amp;MGA, module, 0);
-
-        /*
-         * The return value must be non-NULL on success even though
-         * there is no TearDownProc.
-         */
-        return (pointer)1;
-    } else {
-        if (errmaj) *errmaj = LDR_ONCEONLY;
-        return NULL;
-    }
-}
-    </code>
-
-<sect2>GetRec, FreeRec
-<p>
-
-    A function is usually required to allocate the driver's
-    screen-specific data structure and hook it into the
-    &s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; field.
-    The &s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; is
-    initialised to &s.code;NULL&e.code;, so it is easy to check if the
-    initialisation has already been done.  After allocating it, initialise
-    the fields.  By using &s.code;xnfcalloc()&e.code; to do the allocation
-    it is zeroed, and if the allocation fails the server exits.
-<p>
-    NOTE:
-    When allocating structures from inside the driver which are defined
-    on the common level it is important to initialize the structure to
-    zero.
-    Only this guarantees that the server remains source compatible to
-    future changes in common level structures.
-
-    <code>
-static Bool
-ZZZGetRec(ScrnInfoPtr pScrn)
-{
-    if (pScrn->driverPrivate != NULL)
-        return TRUE;
-    pScrn->driverPrivate = xnfcalloc(sizeof(ZZZRec), 1);
-    /* Initialise as required */
-    ...
-    return TRUE;
-}
-    </code>
-
-    Define a macro in &s.code;"zzz.h"&e.code; which gets a pointer to
-    the &s.code;ZZZRec&e.code; when given &s.code;pScrn&e.code;:
-
-    <code>
-#define ZZZPTR(p) ((ZZZPtr)((p)->driverPrivate))
-    </code>
-
-    Define a function to free the above, setting it to &s.code;NULL&e.code;
-    once it has been freed:
-
-    <code>
-static void
-ZZZFreeRec(ScrnInfoPtr pScrn)
-{
-    if (pScrn->driverPrivate == NULL)
-        return;
-    xfree(pScrn->driverPrivate);
-    pScrn->driverPrivate = NULL;
-}
-    </code>
-
-<sect2>Identify
-<p>
-
-    Define the &s.code;Identify()&e.code; function.  It is run before
-    the Probe, and typically prints out an identifying message, which
-    might include the chipsets it supports.  This function is mandatory:
-
-    <code>
-static void
-ZZZIdentify(int flags)
-{
-    xf86PrintChipsets(ZZZ_NAME, "driver for ZZZ Tech chipsets",
-                      ZZZChipsets);
-}
-    </code>
-
-<sect2>Probe
-<p>
-
-    Define the &s.code;Probe()&e.code; function.  The purpose of this
-    is to find all instances of the hardware that the driver supports,
-    and for the ones not already claimed by another driver, claim the
-    slot, and allocate a &s.code;ScrnInfoRec&e.code;.  This should be
-    a minimal probe, and it should under no circumstances leave the
-    state of the hardware changed.  Because a device is found, don't
-    assume that it will be used.  Don't do any initialisations other
-    than the required &s.code;ScrnInfoRec&e.code; initialisations.
-    Don't allocate any new data structures.
-
-    This function is mandatory.
-
-    NOTE: The &s.code;xf86DrvMsg()&e.code; functions cannot be used from
-    the Probe.
-
-    <code>
-static Bool
-ZZZProbe(DriverPtr drv, int flags)
-{
-    Bool foundScreen = FALSE;
-    int numDevSections, numUsed;
-    GDevPtr *devSections;
-    int *usedChips;
-    int i;
-
-    /*
-     * Find the config file Device sections that match this
-     * driver, and return if there are none.
-     */
-    if ((numDevSections = xf86MatchDevice(ZZZ_DRIVER_NAME,
-                                          &amp;devSections)) <= 0) {
-        return FALSE;
-    }
-
-    /*
-     * Since this is a PCI card, "probing" just amounts to checking
-     * the PCI data that the server has already collected.  If there
-     * is none, return.
-     *
-     * Although the config file is allowed to override things, it
-     * is reasonable to not allow it to override the detection
-     * of no PCI video cards.
-     *
-     * The provided xf86MatchPciInstances() helper takes care of
-     * the details.
-     */
-    /* test if PCI bus present */
-    if (xf86GetPciVideoInfo()) {
-
-        numUsed = xf86MatchPciInstances(ZZZ_NAME, PCI_VENDOR_ZZZ,
-                            ZZZChipsets, ZZZPciChipsets, devSections,
-                            numDevSections, drv, &amp;usedChips);
-
-        for (i = 0; i < numUsed; i++) {
-            ScrnInfoPtr pScrn = NULL;
-            if ((pScrn = xf86ConfigPciEntity(pScrn, flags, usedChips[i],
-                                             ZZZPciChipsets, NULL, NULL,
-                                             NULL, NULL, NULL))) {
-               /* Allocate a ScrnInfoRec */
-               pScrn->driverVersion = VERSION;
-               pScrn->driverName    = ZZZ_DRIVER_NAME;
-               pScrn->name          = ZZZ_NAME;
-               pScrn->Probe         = ZZZProbe;
-               pScrn->PreInit       = ZZZPreInit;
-               pScrn->ScreenInit    = ZZZScreenInit;
-               pScrn->SwitchMode    = ZZZSwitchMode;
-               pScrn->AdjustFrame   = ZZZAdjustFrame;
-               pScrn->EnterVT       = ZZZEnterVT;
-               pScrn->LeaveVT       = ZZZLeaveVT;
-               pScrn->FreeScreen    = ZZZFreeScreen;
-               pScrn->ValidMode     = ZZZValidMode;
-               foundScreen = TRUE;
-               /* add screen to entity */
-           }
-        }
-        xfree(usedChips);
-    }
-
-#ifdef HAS_ISA_DEVS
-    /*
-     * If the driver supports ISA hardware, the following block
-     * can be included too.
-     */
-    numUsed = xf86MatchIsaInstances(ZZZ_NAME, ZZZChipsets,
-                             ZZZIsaChipsets, drv, ZZZFindIsaDevice,
-                             devSections, numDevSections, &amp;usedChips);
-    for (i = 0; i < numUsed; i++) {
-        ScrnInfoPtr pScrn = NULL;
-	if ((pScrn = xf86ConfigIsaEntity(pScrn, flags, usedChips[i],
-					 ZZZIsaChipsets, NULL, NULL, NULL,
-					 NULL, NULL))) {
-            pScrn->driverVersion = VERSION;
-            pScrn->driverName    = ZZZ_DRIVER_NAME;
-            pScrn->name          = ZZZ_NAME;
-            pScrn->Probe         = ZZZProbe;
-            pScrn->PreInit       = ZZZPreInit;
-            pScrn->ScreenInit    = ZZZScreenInit;
-            pScrn->SwitchMode    = ZZZSwitchMode;
-            pScrn->AdjustFrame   = ZZZAdjustFrame;
-            pScrn->EnterVT       = ZZZEnterVT;
-            pScrn->LeaveVT       = ZZZLeaveVT;
-            pScrn->FreeScreen    = ZZZFreeScreen;
-            pScrn->ValidMode     = ZZZValidMode;
-            foundScreen = TRUE;
-        }
-    }
-    xfree(usedChips);
-#endif /* HAS_ISA_DEVS */
-
-    xfree(devSections);
-    return foundScreen;
-    </code>
-
-<sect2>AvailableOptions
-<p>
-
-    Define the &s.code;AvailableOptions()&e.code; function. The purpose
-    of this is to return the available driver options back to the
-    -configure option, so that an xorg.conf file can be built and the
-    user can see which options are available for them to use.
-
-<sect2>PreInit
-<p>
-
-    Define the &s.code;PreInit()&e.code; function.  The purpose of
-    this is to find all the information required to determine if the
-    configuration is usable, and to initialise those parts of the
-    &s.code;ScrnInfoRec&e.code; that can be set once at the beginning
-    of the first server generation.  The information should be found in
-    the least intrusive way possible.
-
-    This function is mandatory.
-
-    NOTES:
-    <enum>
-      <item>The &s.code;PreInit()&e.code; function is only called once
-	 during the life of the X server (at the start of the first
-	 generation).
-
-      <item>Data allocated here must be of the type that persists for
-	 the life of the X server.  This means that data that hooks into
-	 the &s.code;ScrnInfoRec&e.code;'s &s.code;privates&e.code;
-	 field should be allocated here, but data that hooks into the
-	 &s.code;ScreenRec&e.code;'s &s.code;devPrivates&e.code; field
-	 should not be allocated here.  The &s.code;driverPrivate&e.code;
-	 field should also be allocated here.
-
-      <item>Although the &s.code;ScrnInfoRec&e.code; has been allocated
-	 before this function is called, the &s.code;ScreenRec&e.code;
-	 has not been allocated.  That means that things requiring it
-	 cannot be used in this function.
-
-      <item>Very little of the &s.code;ScrnInfoRec&e.code; has been
-	 initialised when this function is called.  It is important to
-	 get the order of doing things right in this function.
-
-    </enum>
-
-    <code>
-static Bool
-ZZZPreInit(ScrnInfoPtr pScrn, int flags)
-{
-    /* Fill in the monitor field */
-    pScrn->monitor = pScrn->confScreen->monitor;
-
-    /*
-     * If using the vgahw module, it will typically be loaded
-     * here by calling xf86LoadSubModule(pScrn, "vgahw");
-     */
-
-    /*
-     * Set the depth/bpp.  Use the globally preferred depth/bpp.  If the
-     * driver has special default depth/bpp requirements, the defaults should
-     * be specified here explicitly.
-     * We support both 24bpp and 32bpp framebuffer layouts.
-     * This sets pScrn->display also.
-     */
-    if (!xf86SetDepthBpp(pScrn, 0, 0, 0,
-                         Support24bppFb | Support32bppFb)) {
-        return FALSE;
-    } else {
-        if (depth/bpp isn't one we support) {
-            print error message;
-            return FALSE;
-        }
-    }
-    /* Print out the depth/bpp that was set */
-    xf86PrintDepthBpp(pScrn);
-
-    /* Set bits per RGB for 8bpp */
-    if (pScrn->depth <= 8) {
-        /* Take into account a dac_6_bit option here */
-        pScrn->rgbBits = 6 or 8;
-    }
-
-    /*
-     * xf86SetWeight() and xf86SetDefaultVisual() must be called
-     * after pScrn->display is initialised.
-     */
-
-    /* Set weight/mask/offset for depth > 8 */
-    if (pScrn->depth > 8) {
-        if (!xf86SetWeight(pScrn, defaultWeight, defaultMask)) {
-            return FALSE;
-        } else {
-            if (weight isn't one we support) {
-                print error message;
-                return FALSE;
-            }
-        }
-    }
-
-    /* Set the default visual. */
-    if (!xf86SetDefaultVisual(pScrn, -1)) {
-        return FALSE;
-    } else {
-        if (visual isn't one we support) {
-            print error message;
-            return FALSE;
-        }
-    }
-
-    /* If the driver supports gamma correction, set the gamma. */
-    if (!xf86SetGamma(pScrn, default_gamma)) {
-        return FALSE;
-    }
-
-    /* This driver uses a programmable clock */
-    pScrn->progClock = TRUE;
-
-    /* Allocate the ZZZRec driverPrivate */
-    if (!ZZZGetRec(pScrn)) {
-        return FALSE;
-    }
-
-    pZzz = ZZZPTR(pScrn);
-
-    /* Collect all of the option flags (fill in pScrn->options) */
-    xf86CollectOptions(pScrn, NULL);
-
-    /*
-     * Process the options based on the information in ZZZOptions.
-     * The results are written to pZzz->Options.  If all of the options
-     * processing is done within this function a local variable "options"
-     * can be used instead of pZzz->Options.
-     */
-    if (!(pZzz->Options = xalloc(sizeof(ZZZOptions))))
-        return FALSE;
-    (void)memcpy(pZzz->Options, ZZZOptions, sizeof(ZZZOptions));
-    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pZzz->Options);
-
-    /*
-     * Set various fields of ScrnInfoRec and/or ZZZRec based on
-     * the options found.
-     */
-    from = X_DEFAULT;
-    pZzz->hwCursor = FALSE;
-    if (xf86IsOptionSet(pZzz->Options, OPTION_HW_CURSOR)) {
-        from = X_CONFIG;
-        pZzz->hwCursor = TRUE;
-    }
-    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
-               pZzz->hwCursor ? "HW" : "SW");
-    if (xf86IsOptionSet(pZzz->Options, OPTION_NOACCEL)) {
-        pZzz->noAccel = TRUE;
-        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
-                   "Acceleration disabled\n");
-    } else {
-        pZzz->noAccel = FALSE;
-    }
-    if (xf86IsOptionSet(pZzz->Options, OPTION_PCI_RETRY)) {
-        pZzz->UsePCIRetry = TRUE;
-        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n");
-    }
-    pZzz->fooHack = 0;
-    if (xf86GetOptValInteger(pZzz->Options, OPTION_FOO_HACK,
-                             &amp;pZzz->fooHack)) {
-        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Foo Hack set to %d\n",
-                   pZzz->fooHack);
-    }
-
-    /*
-     * Find the PCI slot(s) that this screen claimed in the probe.
-     * In this case, exactly one is expected, so complain otherwise.
-     * Note in this case we're not interested in the card types so
-     * that parameter is set to NULL.
-     */
-    if ((i = xf86GetPciInfoForScreen(pScrn->scrnIndex, &amp;pciList, NULL))
-        != 1) {
-        print error message;
-        ZZZFreeRec(pScrn);
-        if (i > 0)
-            xfree(pciList);
-        return FALSE;
-    }
-    /* Note that pciList should be freed below when no longer needed */
-
-    /*
-     * Determine the chipset, allowing config file chipset and
-     * chipid values to override the probed information.  The config
-     * chipset value has precedence over its chipid value if both
-     * are present.
-     *
-     * It isn't necessary to fill in pScrn->chipset if the driver
-     * keeps track of the chipset in its ZZZRec.
-     */
-
-    ...
-
-    /*
-     * Determine video memory, fb base address, I/O addresses, etc,
-     * allowing the config file to override probed values.
-     *
-     * Set the appropriate pScrn fields (videoRam is probably the
-     * most important one that other code might require), and
-     * print out the settings.
-     */
-
-    ...
-
-    /* Initialise a clockRanges list. */
-
-    ...
-
-    /* Set any other chipset specific things in the ZZZRec */
-
-    ...
-
-    /* Select valid modes from those available */
-
-    i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
-                          pScrn->display->modes, clockRanges,
-                          NULL, minPitch, maxPitch, rounding,
-                          minHeight, maxHeight,
-                          pScrn->display->virtualX,
-                          pScrn->display->virtualY,
-                          pScrn->videoRam * 1024,
-                          LOOKUP_BEST_REFRESH);
-    if (i == -1) {
-        ZZZFreeRec(pScrn);
-        return FALSE;
-    }
-
-    /* Prune the modes marked as invalid */
-
-    xf86PruneDriverModes(pScrn);
-
-    /* If no valid modes, return */
-
-    if (i == 0 || pScrn->modes == NULL) {
-        print error message;
-        ZZZFreeRec(pScrn);
-        return FALSE;
-    }
-
-    /*
-     * Initialise the CRTC fields for the modes.  This driver expects
-     * vertical values to be halved for interlaced modes.
-     */
-    xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
-
-    /* Set the current mode to the first in the list. */
-    pScrn->currentMode = pScrn->modes;
-
-    /* Print the list of modes being used. */
-    xf86PrintModes(pScrn);
-
-    /* Set the DPI */
-    xf86SetDpi(pScrn, 0, 0);
-
-    /* Load bpp-specific modules */
-    switch (pScrn->bitsPerPixel) {
-    case 1:
-        mod = "xf1bpp";
-        break;
-    case 4:
-        mod = "xf4bpp";
-        break;
-    case 8:
-        mod = "cfb";
-        break;
-    case 16:
-        mod = "cfb16";
-        break;
-    case 24:
-        mod = "cfb24";
-        break;
-    case 32:
-        mod = "cfb32";
-        break;
-    }
-    if (mod && !xf86LoadSubModule(pScrn, mod))
-        ZZZFreeRec(pScrn);
-        return FALSE;
-
-    /* Load XAA if needed */
-    if (!pZzz->noAccel || pZzz->hwCursor)
-        if (!xf86LoadSubModule(pScrn, "xaa")) {
-            ZZZFreeRec(pScrn);
-            return FALSE;
-        }
-
-    /* Done */
-    return TRUE;
-}
-    </code>
-
-<sect2>MapMem, UnmapMem
-<p>
-
-    Define functions to map and unmap the video memory and any other
-    memory apertures required.  These functions are not mandatory, but
-    it is often useful to have such functions.
-
-    <code>
-static Bool
-ZZZMapMem(ScrnInfoPtr pScrn)
-{
-    /* Call xf86MapPciMem() to map each PCI memory area */
-    ...
-    return TRUE or FALSE;
-}
-
-static Bool
-ZZZUnmapMem(ScrnInfoPtr pScrn)
-{
-    /* Call xf86UnMapVidMem() to unmap each memory area */
-    ...
-    return TRUE or FALSE;
-}
-    </code>
-
-<sect2>Save, Restore
-<p>
-
-    Define functions to save and restore the original video state.  These
-    functions are not mandatory, but are often useful.
-
-    <code>
-static void
-ZZZSave(ScrnInfoPtr pScrn)
-{
-    /*
-     * Save state into per-screen data structures.
-     * If using the vgahw module, vgaHWSave will typically be
-     * called here.
-     */
-    ...
-}
-
-static void
-ZZZRestore(ScrnInfoPtr pScrn)
-{
-    /*
-     * Restore state from per-screen data structures.
-     * If using the vgahw module, vgaHWRestore will typically be
-     * called here.
-     */
-    ...
-}
-    </code>
-
-<sect2>ModeInit
-<p>
-
-    Define a function to initialise a new video mode.  This function isn't
-    mandatory, but is often useful.
-
-    <code>
-static Bool
-ZZZModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
-{
-    /*
-     * Program a video mode.  If using the vgahw module,
-     * vgaHWInit and vgaRestore will typically be called here.
-     * Once up to the point where there can't be a failure
-     * set pScrn->vtSema to TRUE.
-     */
-    ...
-}
-    </code>
-
-<sect2>ScreenInit
-<p>
-
-    Define the &s.code;ScreenInit()&e.code; function.  This is called
-    at the start of each server generation, and should fill in as much
-    of the &s.code;ScreenRec&e.code; as possible as well as any other
-    data that is initialised once per generation.  It should initialise
-    the framebuffer layers it is using, and initialise the initial video
-    mode.
-
-    This function is mandatory.
-
-    NOTE: The &s.code;ScreenRec&e.code; (&s.code;pScreen&e.code;) is
-	  passed to this driver, but it and the
-	  &s.code;ScrnInfoRecs&e.code; are not yet hooked into each
-	  other.  This means that in this function, and functions it
-	  calls, one cannot be found from the other.
-
-    <code>
-static Bool
-ZZZScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
-{
-    /* Get the ScrnInfoRec */
-    pScrn = xf86Screens[pScreen->myNum];
-
-    /*
-     * If using the vgahw module, its data structures and related
-     * things are typically initialised/mapped here.
-     */
-
-    /* Save the current video state */
-    ZZZSave(pScrn);
-
-    /* Initialise the first mode */
-    ZZZModeInit(pScrn, pScrn->currentMode);
-
-    /* Set the viewport if supported */
-
-    ZZZAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
-
-    /*
-     * Setup the screen's visuals, and initialise the framebuffer
-     * code.
-     */
-
-    /* Reset the visual list */
-    miClearVisualTypes();
-
-    /*
-     * Setup the visuals supported.  This driver only supports
-     * TrueColor for bpp > 8, so the default set of visuals isn't
-     * acceptable.  To deal with this, call miSetVisualTypes with
-     * the appropriate visual mask.
-     */
-
-    if (pScrn->bitsPerPixel > 8) {
-        if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
-                              pScrn->rgbBits, pScrn->defaultVisual))
-            return FALSE;
-    } else {
-        if (!miSetVisualTypes(pScrn->depth,
-                              miGetDefaultVisualMask(pScrn->depth),
-                              pScrn->rgbBits, pScrn->defaultVisual))
-            return FALSE;
-    }
-
-    /*
-     * Initialise the framebuffer.
-     */
-
-    switch (pScrn->bitsPerPixel) {
-    case 1:
-        ret = xf1bppScreenInit(pScreen, FbBase,
-                               pScrn->virtualX, pScrn->virtualY,
-                               pScrn->xDpi, pScrn->yDpi,
-                               pScrn->displayWidth);
-        break;
-    case 4:
-        ret = xf4bppScreenInit(pScreen, FbBase,
-                               pScrn->virtualX, pScrn->virtualY,
-                               pScrn->xDpi, pScrn->yDpi,
-                               pScrn->displayWidth);
-        break;
-    case 8:
-        ret = cfbScreenInit(pScreen, FbBase,
-                            pScrn->virtualX, pScrn->virtualY,
-                            pScrn->xDpi, pScrn->yDpi,
-                            pScrn->displayWidth);
-        break;
-    case 16:
-        ret = cfb16ScreenInit(pScreen, FbBase,
-                              pScrn->virtualX, pScrn->virtualY,
-                              pScrn->xDpi, pScrn->yDpi,
-                              pScrn->displayWidth);
-        break;
-    case 24:
-        ret = cfb24ScreenInit(pScreen, FbBase,
-                              pScrn->virtualX, pScrn->virtualY,
-                              pScrn->xDpi, pScrn->yDpi,
-                              pScrn->displayWidth);
-        break;
-    case 32:
-        ret = cfb32ScreenInit(pScreen, FbBase,
-                              pScrn->virtualX, pScrn->virtualY,
-                              pScrn->xDpi, pScrn->yDpi,
-                              pScrn->displayWidth);
-        break;
-    default:
-        print a message about an internal error;
-        ret = FALSE;
-        break;
-    }
-
-    if (!ret)
-        return FALSE;
-
-    /* Override the default mask/offset settings */
-    if (pScrn->bitsPerPixel > 8) {
-        for (i = 0, visual = pScreen->visuals;
-             i < pScreen->numVisuals; i++, visual++) {
-            if ((visual->class | DynamicClass) == DirectColor) {
-                visual->offsetRed = pScrn->offset.red;
-                visual->offsetGreen = pScrn->offset.green;
-                visual->offsetBlue = pScrn->offset.blue;
-                visual->redMask = pScrn->mask.red;
-                visual->greenMask = pScrn->mask.green;
-                visual->blueMask = pScrn->mask.blue;
-            }
-        }
-    }
-
-    /*
-     * If banking is needed, initialise an miBankInfoRec (defined in
-     * "mibank.h"), and call miInitializeBanking().
-     */
-    if (!miInitializeBanking(pScreen, pScrn->virtualX, pScrn->virtualY,
-                                     pScrn->displayWidth, pBankInfo))
-        return FALSE;
-
-    /*
-     * If backing store is to be supported (as is usually the case),
-     * initialise it.
-     */
-    miInitializeBackingStore(pScreen);
-
-    /*
-     * Set initial black & white colourmap indices.
-     */
-    xf86SetBlackWhitePixels(pScreen);
-
-    /*
-     * Install colourmap functions.  If using the vgahw module,
-     * vgaHandleColormaps would usually be called here.
-     */
-
-    ...
-
-    /*
-     * Initialise cursor functions.  This example is for the mi
-     * software cursor.
-     */
-    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
-
-    /* Initialise the default colourmap */
-    switch (pScrn->depth) {
-    case 1:
-        if (!xf1bppCreateDefColormap(pScreen))
-            return FALSE;
-        break;
-    case 4:
-        if (!xf4bppCreateDefColormap(pScreen))
-            return FALSE;
-        break;
-    default:
-        if (!cfbCreateDefColormap(pScreen))
-            return FALSE;
-        break;
-    }
-
-    /*
-     * Wrap the CloseScreen vector and set SaveScreen.
-     */
-    ZZZPTR(pScrn)->CloseScreen = pScreen->CloseScreen;
-    pScreen->CloseScreen = ZZZCloseScreen;
-    pScreen->SaveScreen = ZZZSaveScreen;
-
-    /* Report any unused options (only for the first generation) */
-    if (serverGeneration == 1) {
-        xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
-    }
-
-    /* Done */
-    return TRUE;
-}
-    </code>
-
-
-<sect2>SwitchMode
-<p>
-
-    Define the &s.code;SwitchMode()&e.code; function if mode switching
-    is supported by the driver.
-
-    <code>
-static Bool
-ZZZSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
-{
-    return ZZZModeInit(xf86Screens[scrnIndex], mode);
-}
-    </code>
-
-
-<sect2>AdjustFrame
-<p>
-
-    Define the &s.code;AdjustFrame()&e.code; function if the driver
-    supports this.
-
-    <code>
-static void
-ZZZAdjustFrame(int scrnIndex, int x, int y, int flags)
-{
-    /* Adjust the viewport */
-}
-    </code>
-
-
-<sect2>EnterVT, LeaveVT
-<p>
-
-    Define the &s.code;EnterVT()&e.code; and &s.code;LeaveVT()&e.code;
-    functions.
-
-    These functions are mandatory.
-
-    <code>
-static Bool
-ZZZEnterVT(int scrnIndex, int flags)
-{
-    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
-    return ZZZModeInit(pScrn, pScrn->currentMode);
-}
-
-static void
-ZZZLeaveVT(int scrnIndex, int flags)
-{
-    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
-    ZZZRestore(pScrn);
-}
-    </code>
-
-<sect2>CloseScreen
-<p>
-
-    Define the &s.code;CloseScreen()&e.code; function:
-
-    This function is mandatory.  Note that it unwraps the previously
-    wrapped &s.code;pScreen-&gt;CloseScreen&e.code;, and finishes by
-    calling it.
-
-    <code>
-static Bool
-ZZZCloseScreen(int scrnIndex, ScreenPtr pScreen)
-{
-    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
-    if (pScrn->vtSema) {
-        ZZZRestore(pScrn);
-        ZZZUnmapMem(pScrn);
-    }
-    pScrn->vtSema = FALSE;
-    pScreen->CloseScreen = ZZZPTR(pScrn)->CloseScreen;
-    return (*pScreen->CloseScreen)(scrnIndex, pScreen);
-}
-    </code>
-
-<sect2>SaveScreen
-<p>
-
-    Define the &s.code;SaveScreen()&e.code; function (the screen
-    blanking function).  When using the vgahw module, this will typically
-    be:
-
-    <code>
-static Bool
-ZZZSaveScreen(ScreenPtr pScreen, int mode)
-{
-    return vgaHWSaveScreen(pScreen, mode);
-}
-    </code>
-
-    This function is mandatory.  Before modifying any hardware register
-    directly this function needs to make sure that the Xserver is active
-    by checking if &s.code;pScrn&e.code; is non-NULL and for
-    &s.code;pScrn->vtSema == TRUE&e.code;.
-
-<sect2>FreeScreen
-<p>
-
-    Define the &s.code;FreeScreen()&e.code; function.  This function
-    is optional.  It should be defined if the &s.code;ScrnInfoRec&e.code;
-    &s.code;driverPrivate&e.code; field is used so that it can be freed
-    when a screen is deleted by the common layer for reasons possibly
-    beyond the driver's control.  This function is not used in during
-    normal (error free) operation.  The per-generation data is freed by
-    the &s.code;CloseScreen()&e.code; function.
-
-    <code>
-static void
-ZZZFreeScreen(int scrnIndex, int flags)
-{
-    /*
-     * If the vgahw module is used vgaHWFreeHWRec() would be called
-     * here.
-     */
-    ZZZFreeRec(xf86Screens[scrnIndex]);
-}
-    </code>
-
-
-</article>
diff --git a/hw/xfree86/doc/sgml/DESIGN.xml b/hw/xfree86/doc/sgml/DESIGN.xml
new file mode 100644
index 0000000..6abfa60
--- /dev/null
+++ b/hw/xfree86/doc/sgml/DESIGN.xml
@@ -0,0 +1,9376 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+ <!-- config file keyword markup -->
+ <!-- specific config file keywords -->
+ <!ENTITY k.device "<emphasis>Device</emphasis>">
+ <!ENTITY k.monitor "<emphasis>Monitor</emphasis>">
+ <!ENTITY k.display "<emphasis>Display</emphasis>">
+ <!ENTITY k.inputdevice "<emphasis>InputDevice</emphasis>">
+ <!ENTITY k.screen "<emphasis>Screen</emphasis>">
+ <!ENTITY k.serverlayout "<emphasis>ServerLayout</emphasis>">
+ <!ENTITY k.driver "<emphasis>Driver</emphasis>">
+ <!ENTITY k.module "<emphasis>Module</emphasis>">
+ <!ENTITY k.identifier "<emphasis>Identifier</emphasis>">
+ <!ENTITY k.serverflags "<emphasis>ServerFlags</emphasis>">
+] >
+
+<article>
+  <articleinfo>
+
+    <title>XFree86 server 4.x Design (DRAFT)</title>
+
+    <authorgroup>
+      <corpauthor>The XFree86 Project, Inc</corpauthor>
+
+      <othercredit>
+	<firstname>Jim</firstname><surname>Gettys</surname>
+	<contrib>Updates for X11R6.7</contrib>
+      </othercredit>
+    </authorgroup>
+
+    <pubdate>19 December 2003</pubdate>
+
+  </articleinfo>
+
+  <note><para>
+This is a DRAFT document, and the interfaces described here
+are subject to change without notice.
+    </para></note>
+
+
+  <sect1>
+    <title>Preface</title>
+
+    <para>
+The broad design principles are:
+      <itemizedlist>
+	<listitem><para>keep it reasonable
+	    <itemizedlist>
+	      <listitem><para>We cannot rewrite the complete server
+		</para></listitem>
+	      <listitem><para>We don't want to re-invent the wheel
+		</para></listitem>
+	    </itemizedlist></para></listitem>
+	<listitem><para>keep it modular
+	    <itemizedlist>
+	      <listitem><para>As many things as possible should go into modules
+		</para></listitem>
+	      <listitem><para>The basic loader binary should be minimal
+		</para></listitem>
+	      <listitem><para>A clean design with well defined layering is
+		  important</para></listitem>
+	      <listitem><para>DDX specific global variables are a nono
+		</para></listitem>
+	      <listitem><para>The structure should be flexible enough to allow
+		  future extensions</para></listitem>
+	      <listitem><para>The structure should minimize duplication of
+		  common code</para></listitem>
+	    </itemizedlist></para></listitem>
+	<listitem><para>keep important features in mind
+	    <itemizedlist>
+	      <listitem><para>multiple screens, including multiple instances
+		  of drivers</para></listitem>
+	      <listitem><para>mixing different color depths and visuals on
+		  different and ideally even on the same screen
+		</para></listitem>
+	      <listitem><para>better control of the PCI device used
+		</para></listitem>
+	      <listitem><para>better config file parser</para></listitem>
+	      <listitem><para>get rid of all VGA compatibility assumptions
+		</para></listitem>
+	    </itemizedlist></para></listitem>
+      </itemizedlist>
+    </para>
+
+    <para>
+Unless we find major deficiencies in the DIX layer, we should avoid
+making changes there.
+    </para>
+  </sect1>
+
+  <sect1>
+    <title>The xorg.conf File</title>
+
+    <para>
+The xorg.conf file format is similar to the old format, with the following
+changes:
+    </para>
+
+    <sect2>
+      <title>&k.device; section</title>
+
+      <para>
+    The &k.device; sections are similar to what they used to be, and
+    describe hardware-specific information for a single video card.
+    &k.device;
+    Some new keywords are added:
+
+
+	<variablelist>
+	  <varlistentry><term>Driver "drivername"</term>
+	    <listitem><para>
+        Specifies the name of the driver to be used for the card.  This
+        is mandatory.
+	      </para></listitem></varlistentry>
+	  <varlistentry><term>BusID "busslot"</term>
+	    <listitem><para>
+        Specifies uniquely the location of the card on the bus.  The
+        purpose is to identify particular cards in a multi-headed
+        configuration.  The format of the argument is intentionally
+        vague, and may be architecture dependent.  For a PCI bus, it
+        is something like "bus:slot:func".
+	      </para></listitem></varlistentry>
+	</variablelist>
+      </para>
+
+      <para>
+    A &k.device; section is considered ``active'' if there is a reference
+    to it in an active &k.screen; section.
+      </para>
+    </sect2>
+
+    <sect2>
+      <title>&k.screen; section</title>
+
+      <para>
+    The &k.screen; sections are similar to what they used to be.  They
+    no longer have a &k.driver; keyword, but an &k.identifier; keyword
+    is added.  (The &k.driver; keyword may be accepted in place of the
+    &k.identifier; keyword for compatibility purposes.)  The identifier
+    can be used to identify which screen is to be active when multiple
+    &k.screen; sections are present.  It is possible to specify the active
+    screen from the command line.  A default is chosen in the absence
+    of one being specified.  A &k.screen; section is considered ``active''
+    if there is a reference to it either from the command line, or from
+    an active &k.serverlayout; section.
+      </para>
+    </sect2>
+
+    <sect2>
+      <title>&k.inputdevice; section</title>
+
+      <para>
+    The &k.inputdevice; section is a new section that describes
+    configuration information for input devices.  It replaces the old
+    <emphasis>Keyboard</emphasis>, <emphasis>Pointer</emphasis> and <emphasis>XInput</emphasis>
+    sections.  Like the &k.device; section, it has two mandatory keywords:
+    &k.identifier; and &k.driver;.  For compatibility purposes the old
+    <emphasis>Keyboard</emphasis> and <emphasis>Pointer</emphasis> sections are
+    converted by the parser into &k.inputdevice; sections as follows:
+
+	<variablelist>
+	  <varlistentry><term><emphasis>Keyboard</emphasis></term>
+	    <listitem><literallayout>
+             &k.identifier; "Implicit Core Keyboard"
+             &k.driver; "keyboard"
+	      </literallayout></listitem></varlistentry>
+	  <varlistentry><term><emphasis>Pointer</emphasis></term>
+	    <listitem><literallayout>
+             &k.identifier; "Implicit Core Pointer"
+             &k.driver; "mouse"
+	      </literallayout></listitem></varlistentry>
+	</variablelist>
+      </para>
+
+      <para>
+    An &k.inputdevice; section is considered active if there is a
+    reference to it in an active &k.serverlayout; section.  An
+    &k.inputdevice; section may also be referenced implicitly if there
+    is no &k.serverlayout; section, if the <option>-screen</option> command
+    line options is used, or if the &k.serverlayout; section doesn't
+    reference any &k.inputdevice; sections.  In this case, the first
+    sections with drivers "keyboard" and "mouse" are used as the core
+    keyboard and pointer respectively.
+      </para>
+    </sect2>
+
+    <sect2>
+      <title>&k.serverlayout; section</title>
+
+      <para>
+    The &k.serverlayout; section is a new section that is used to identify
+    which &k.screen; sections are to be used in a multi-headed configuration,
+    and the relative layout of those screens.  It also identifies which
+    &k.inputdevice; sections are to be used.  Each &k.serverlayout; section
+    has an identifier, a list of &k.screen; section identifiers, and a list of
+    &k.inputdevice; section identifiers.  &k.serverflags; options may also be
+    included in a &k.serverlayout; section, making it possible to override
+    the global values in the &k.serverflags; section.
+      </para>
+
+      <para>
+    A &k.serverlayout; section can be made active by being referenced on
+    the command line.  In the absence of this, a default will be chosen
+    (the first one found).  The screen names may optionally be followed
+    by a number specifying the preferred screen number, and optionally
+    by information specifying the physical positioning of the screen,
+    either in absolute terms or relative to another screen (or screens).
+    When no screen number is specified, they are numbered according to
+    the order in which they are listed.  The old (now obsolete) method
+    of providing the positioning information is to give the names of
+    the four adjacent screens.  The order of these is top, bottom, left,
+    right.  Here is an example of a &k.serverlayout; section for two
+    screens using the old method, with the second located to the right
+    of the first:
+
+	<programlisting>
+      Section "ServerLayout"
+        Identifier "Main Layout"
+        Screen     0 "Screen 1" ""  ""  ""  "Screen 2"
+        Screen     1 "Screen 2"
+        Screen     "Screen 3"
+      EndSection
+	</programlisting>
+      </para>
+
+      <para>
+    The preferred way of specifying the layout is to explicitly specify
+    the screen's location in absolute terms or relative to another
+    screen.
+      </para>
+
+      <para>
+    In the absolute case, the upper left corner's coordinates are given
+    after the <emphasis>Absolute</emphasis> keyword.  If the coordinates are
+    omitted, a value of <code>(0,0)</code> is assumed.  An example
+    of absolute positioning follows:
+
+	<programlisting>
+      Section "ServerLayout"
+        Identifier "Main Layout"
+        Screen     0 "Screen 1" Absolute 0 0
+        Screen     1 "Screen 2" Absolute 1024 0
+        Screen     "Screen 3" Absolute 2048 0
+      EndSection
+	</programlisting>
+      </para>
+
+      <para>
+    In the relative case, the position is specified by either using one of
+    the following keywords followed by the name of the reference screen:
+
+	<simplelist type='vert' columns='1'>
+	  <member><emphasis>RightOf</emphasis></member>
+	  <member><emphasis>LeftOf</emphasis></member>
+	  <member><emphasis>Above</emphasis></member>
+	  <member><emphasis>Below</emphasis></member>
+	  <member><emphasis>Relative</emphasis></member>
+	</simplelist>
+      </para>
+
+      <para>
+    When the <emphasis>Relative</emphasis> keyword is used, the reference screen
+    name is followed by the coordinates of the new screen's origin
+    relative to reference screen.  The following example shows how to use
+    some of the relative positioning options.
+
+	<programlisting>
+      Section "ServerLayout"
+        Identifier "Main Layout"
+        Screen     0 "Screen 1"
+        Screen     1 "Screen 2" RightOf "Screen 1"
+        Screen     "Screen 3" Relative "Screen 1" 2048 0
+      EndSection
+	</programlisting>
+      </para>
+    </sect2>
+
+    <sect2>
+      <title>Options</title>
+
+      <para>
+    Options are used more extensively.  They may appear in most sections
+    now.  Options related to drivers can be present in the &k.screen;,
+    &k.device; and &k.monitor; sections and the &k.display; subsections.
+    The order of precedence is &k.display;, &k.screen;, &k.monitor;,
+    &k.device;.  Options have been extended to allow an optional value
+    to be specified in addition to the option name.  For more details
+    about options, see the <link linkend="options">Options</link> section
+    for details.
+      </para>
+    </sect2>
+  </sect1>
+
+  <sect1>
+    <title>Driver Interface</title>
+
+    <para>
+The driver interface consists of a minimal set of entry points that are
+required based on the external events that the driver must react to.
+No non-essential structure is imposed on the way they are used beyond
+that.  This is a significant difference compared with the old design.
+    </para>
+
+    <para>
+The entry points for drawing operations are already taken care of by
+the framebuffer code (including, XAA).  Extensions and enhancements to
+framebuffer code are outside the scope of this document.
+    </para>
+
+    <para>
+This approach to the driver interface provides good flexibility, but does
+increase the complexity of drivers.  To help address this, the XFree86
+common layer provides a set of ``helper'' functions to take care of things
+that most drivers need.  These helpers help minimise the amount of code
+duplication between drivers.  The use of helper functions by drivers is
+however optional, though encouraged.  The basic philosophy behind the
+helper functions is that they should be useful to many drivers, that
+they should balance this against the complexity of their interface.  It
+is inevitable that some drivers may find some helpers unsuitable and
+need to provide their own code.
+    </para>
+
+    <para>
+Events that a driver needs to react to are:
+
+      <variablelist>
+	<varlistentry><term>ScreenInit</term>
+
+	  <listitem><para>
+     An initialisation function is called from the DIX layer for each
+     screen at the start of each server generation.
+	    </para></listitem></varlistentry>
+
+	<varlistentry><term>Enter VT</term>
+
+	  <listitem><para>
+     The server takes control of the console.
+	    </para></listitem></varlistentry>
+
+	<varlistentry><term>Leave VT</term>
+
+	  <listitem><para>
+     The server releases control of the console.
+	    </para></listitem></varlistentry>
+
+	<varlistentry><term>Mode Switch</term>
+
+	  <listitem><para>
+     Change video mode.
+	    </para></listitem></varlistentry>
+
+	<varlistentry><term>ViewPort change</term>
+
+	  <listitem><para>
+     Change the origin of the physical view port.
+	    </para></listitem></varlistentry>
+
+	<varlistentry><term>ScreenSaver state change</term>
+
+	  <listitem><para>
+     Screen saver activation/deactivation.
+	    </para></listitem></varlistentry>
+
+	<varlistentry><term>CloseScreen</term>
+
+	  <listitem><para>
+     A close screen function is called from the DIX layer for each screen
+     at the end of each server generation.
+	    </para></listitem></varlistentry>
+      </variablelist>
+    </para>
+
+
+    <para>
+In addition to these events, the following functions are required by
+the XFree86 common layer:
+
+      <variablelist>
+	<varlistentry><term>Identify</term>
+
+	  <listitem><para>
+     Print a driver identifying message.
+	    </para></listitem></varlistentry>
+
+	<varlistentry><term>Probe</term>
+
+	  <listitem><para>
+     This is how a driver identifies if there is any hardware present that
+     it knows how to drive.
+	    </para></listitem></varlistentry>
+
+	<varlistentry><term>PreInit</term>
+
+	  <listitem><para>
+     Process information from the xorg.conf file, determine the
+     full characteristics of the hardware, and determine if a valid
+     configuration is present.
+	    </para></listitem></varlistentry>
+      </variablelist>
+    </para>
+
+    <para>
+The VidMode extension also requires:
+
+      <variablelist>
+	<varlistentry><term>ValidMode</term>
+
+	  <listitem><para>
+     Identify if a new mode is usable with the current configuration.
+     The PreInit function (and/or helpers it calls) may also make use
+     of the ValidMode function or something similar.
+	    </para></listitem></varlistentry>
+      </variablelist>
+    </para>
+
+
+    <para>
+Other extensions may require other entry points.  The drivers will
+inform the common layer of these in such cases.
+    </para>
+  </sect1>
+
+  <sect1>
+    <title>Resource Access Control Introduction</title>
+
+    <para>
+Graphics devices are accessed through ranges in I/O or memory space.
+While most modern graphics devices allow relocation of such ranges many
+of them still require the use of well established interfaces such as
+VGA memory and IO ranges or 8514/A IO ranges.  With modern buses (like
+PCI) it is possible for multiple video devices to share access to these
+resources.  The RAC (Resource Access Control) subsystem provides a
+mechanism for this.
+    </para>
+
+    <sect2>
+      <title>Terms and Definitions</title>
+
+      <sect3>
+	<title>Bus</title>
+
+	<para>
+    ``Bus'' is ambiguous as it is used for different things: it may refer
+    to physical incompatible extension connectors in a computer system.
+    The RAC system knows two such systems: The ISA bus and the PCI bus.
+    (On the software level EISA, MCA and VL buses are currently treated
+    like ISA buses).  ``Bus'' may also refer to logically different
+    entities on a single bus system which are connected via bridges.  A
+    PCI system may have several distinct PCI buses connecting each other
+    by PCI-PCI bridges or to the host CPU by HOST-PCI bridges.
+	</para>
+
+	<para>
+    Systems that host more than one bus system link these together using
+    bridges.  Bridges are a concern to RAC as they might block or pass
+    specific resources.  PCI-PCI bridges may be set up to pass VGA
+    resources to the secondary bus.  PCI-ISA buses pass any resources not
+    decoded on the primary PCI bus to the ISA bus.  This way VGA resources
+    (although exclusive on the ISA bus) can be shared by ISA and PCI
+    cards.  Currently HOST-PCI bridges are not yet handled by RAC as they
+    require specific drivers.
+	</para>
+      </sect3>
+
+      <sect3>
+	<title>Entity</title>
+
+	<para>
+    The smallest independently addressable unit on a system bus is
+    referred to as an entity.  So far we know ISA and PCI entities.  PCI
+    entities can be located on the PCI bus by an unique ID consisting of
+    the bus, card and function number.
+	</para>
+      </sect3>
+
+      <sect3>
+	<title>Resource</title>
+
+	<para>
+    ``Resource'' refers to a range of memory or I/O addresses an entity
+    can decode.
+	</para>
+
+	<para>
+    If a device is capable of disabling this decoding the resource is
+    called sharable.  For PCI devices a generic method is provided to
+    control resource decoding.  Other devices will have to provide a
+    device specific function to control decoding.
+	</para>
+
+	<para>
+    If the entity is capable of decoding this range at a different
+    location this resource is considered relocatable.
+	</para>
+
+	<para>
+    Resources which start at a specific address and occupy a single
+    continuous range are called block resources.
+	</para>
+
+	<para>
+    Alternatively resource addresses can be decoded in a way that they
+    satisfy the conditions:
+	  <programlisting>
+                    address &amp; mask == base
+	  </programlisting>
+    and
+	  <programlisting>
+                       base &amp; mask == base
+	  </programlisting>
+    Resources addressed in such a way are called sparse resources.
+	</para>
+
+      </sect3>
+
+      <sect3>
+	<title>Server States</title>
+
+	<para>
+    The resource access control system knows two server states: the
+    SETUP and the OPERATING state.  The SETUP state is entered whenever
+    a mode change takes place or the server exits or does VT switching.
+    During this state all entity resources are under resource access
+    control.  During OPERATING state only those entities are controlled
+    which actually have shared resources that conflict with others.
+	</para>
+      </sect3>
+    </sect2>
+  </sect1>
+
+  <sect1>
+    <title>Control Flow in the Server and Mandatory Driver Functions</title>
+
+    <para>
+At the start of each server generation, <function>main()</function>
+(<filename>dix/main.c</filename>) calls the DDX function
+<function>InitOutput()</function>.  This is the first place that the DDX gets
+control.  <function>InitOutput()</function> is expected to fill in the global
+<structname>screenInfo</structname> struct, and one
+<structfield>screenInfo.screen[]</structfield> entry for each screen present.
+Here is what <function>InitOutput()</function> does:
+    </para>
+
+    <sect2>
+      <title>Parse the xorg.conf file</title>
+
+      <para>
+    This is done at the start of the first server generation only.
+      </para>
+
+      <para>
+    The xorg.conf file is read in full, and the resulting information
+    stored in data structures.  None of the parsed information is
+    processed at this point.  The parser data structures are opaque to
+    the video drivers and to most of the common layer code.
+      </para>
+
+      <para>
+    The entire file is parsed first to remove any section ordering
+    requirements.
+      </para>
+    </sect2>
+
+
+    <sect2>
+      <title>Initial processing of parsed information and command line options
+      </title>
+
+      <para>
+    This is done at the start of the first server generation only.
+      </para>
+
+      <para>
+    The initial processing is to determine paths like the
+    <emphasis>ModulePath</emphasis>, etc, and to determine which &k.serverlayout;,
+    &k.screen; and &k.device; sections are active.
+      </para>
+    </sect2>
+
+
+    <sect2>
+      <title>Enable port I/O access</title>
+
+      <para>
+    Port I/O access is controlled from the XFree86 common layer, and is
+    ``all or nothing''.  It is enabled prior to calling driver probes, at
+    the start of subsequent server generations, and when VT switching
+    back to the Xserver.  It is disabled at the end of server generations,
+    and when VT switching away from the Xserver.
+      </para>
+
+      <para>
+    The implementation details of this may vary on different platforms.
+      </para>
+    </sect2>
+
+
+    <sect2>
+      <title>General bus probe</title>
+
+      <para>
+    This is done at the start of the first server generation only.
+      </para>
+
+      <para>
+    In the case of ix86 machines, this will be a general PCI probe.
+    The full information obtained here will be available to the drivers.
+    This information persists for the life of the Xserver.  In the PCI
+    case, the PCI information for all video cards found is available by
+    calling <function>xf86GetPciVideoInfo()</function>.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    pciVideoPtr *xf86GetPciVideoInfo(void);
+	  </programlisting>
+	  <blockquote><para>
+	returns a pointer to a list of pointers to
+	<structname>pciVideoRec</structname> entries, of which there is one for
+	each detected PCI video card.  The list is terminated with a
+	<constant>NULL</constant> pointer.  If no PCI video cards were
+	detected, the return value is <constant>NULL</constant>.
+
+	    </para></blockquote>
+	</para></blockquote>
+
+      <para>
+    After the bus probe, the resource broker is initialised.
+      </para>
+    </sect2>
+
+
+    <sect2>
+      <title>Load initial set of modules</title>
+
+      <para>
+    This is done at the start of the first server generation only.
+      </para>
+
+      <para>
+    The core server contains a list of mandatory modules.  These are loaded
+    first.  Currently the only module on this list is the bitmap font module.
+      </para>
+
+      <para>
+    The next set of modules loaded are those specified explicitly in the
+    &k.module; section of the config file.
+      </para>
+
+      <para>
+    The final set of initial modules are the driver modules referenced
+    by the active &k.device; and &k.inputdevice; sections in the config
+    file.  Each of these modules is loaded exactly once.
+      </para>
+    </sect2>
+
+
+    <sect2>
+      <title>Register Video and Input Drivers</title>
+
+      <para>
+    This is done at the start of the first server generation only.
+      </para>
+
+      <para>
+    When a driver module is loaded, the loader calls its
+    <function>Setup</function> function.  For video drivers, this function
+    calls <function>xf86AddDriver()</function> to register the driver's
+    <structname>DriverRec</structname>, which contains a small set of essential
+    details and driver entry points required during the early phase of
+    <function>InitOutput()</function>.  <function>xf86AddDriver()</function>
+    adds it to the global <varname>xf86DriverList[]</varname> array.
+      </para>
+
+      <para>
+    The <structname>DriverRec</structname> contains the driver canonical name,
+    the <function>Identify()</function>,
+    <function>Probe()</function> and <function>AvailableOptions()</function>
+    function entry points as well as a pointer
+    to the driver's module (as returned from the loader when the driver
+    was loaded) and a reference count which keeps track of how many
+    screens are using the driver.  The entry driver entry points are
+    those required prior to the driver allocating and filling in its
+    <structname>ScrnInfoRec</structname>.
+      </para>
+
+      <para>
+    For a static server, the <varname>xf86DriverList[]</varname> array is
+    initialised at build time, and the loading of modules is not done.
+      </para>
+
+      <para>
+    A similar procedure is used for input drivers.  The input driver's
+    <function>Setup</function> function calls
+    <function>xf86AddInputDriver()</function> to register the driver's
+    <structname>InputDriverRec</structname>, which contains a small set of
+    essential details and driver entry points required during the early
+    phase of <function>InitInput()</function>.
+    <function>xf86AddInputDriver()</function> adds it to the global
+    <varname>xf86InputDriverList[]</varname> array.  For a static server,
+    the <varname>xf86InputDriverList[]</varname> array is initialised at
+    build time.
+      </para>
+
+      <para>
+    Both the <varname>xf86DriverList[]</varname> and
+    <varname>xf86InputDriverList[]</varname> arrays have been initialised
+    by the end of this stage.
+      </para>
+
+      <para>
+    Once all the drivers are registered, their
+    <function>ChipIdentify()</function> functions are called.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    void ChipIdentify(int flags);
+	  </programlisting>
+	  <blockquote><para>
+      This is expected to print a message indicating the driver name,
+      a short summary of what it supports, and a list of the chipset
+      names that it supports.  It may use the xf86PrintChipsets() helper
+      to do this.
+	    </para></blockquote>
+	</para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void xf86PrintChipsets(const char *drvname, const char *drvmsg,
+                           SymTabPtr chips);
+	  </programlisting>
+	  <blockquote><para>
+      This function provides an easy way for a driver's ChipIdentify
+      function to format the identification message.
+	    </para></blockquote>
+	</para></blockquote>
+    </sect2>
+
+    <sect2>
+      <title>Initialise Access Control</title>
+
+      <para>
+    This is done at the start of the first server generation only.
+      </para>
+
+      <para>
+    The Resource Access Control (RAC) subsystem is initialised before
+    calling any driver functions that may access hardware.  All generic
+    bus information is probed and saved (for restoration later).  All
+    (shared resource) video devices are disabled at the generic bus
+    level, and a probe is done to find the ``primary'' video device.  These
+    devices remain disabled for the next step.
+      </para>
+    </sect2>
+
+
+    <sect2 id="probe">
+      <title>Video Driver Probe</title>
+
+      <para>
+    This is done at the start of the first server generation only.  The
+    <function>ChipProbe()</function> function of each registered video driver
+    is called.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool ChipProbe(DriverPtr drv, int flags);
+	  </programlisting>
+	  <blockquote><para>
+      The purpose of this is to identify all instances of hardware
+      supported by the driver.  The flags value is currently either 0,
+      <constant>PROBE_DEFAULT</constant> or <constant>PROBE_DETECT</constant>.
+      <constant>PROBE_DETECT</constant> is used if "-configure" or "-probe"
+      command line arguments are given and indicates to the
+      <function>Probe()</function> function that it should not configure the
+      bus entities and that no xorg.conf information is available.
+	    </para>
+
+	  <para>
+      The probe must find the active device sections that match the
+      driver by calling <function>xf86MatchDevice()</function>.  The number
+      of matches found limits the maximum number of instances for this
+      driver.  If no matches are found, the function should return
+      <constant>FALSE</constant> immediately.
+	  </para>
+
+	<para>
+      Devices that cannot be identified by using device-independent
+      methods should be probed at this stage (keeping in mind that access
+      to all resources that can be disabled in a device-independent way
+      are disabled during this phase).  The probe must be a minimal
+      probe.  It should just determine if there is a card present that
+      the driver can drive.  It should use the least intrusive probe
+      methods possible.  It must not do anything that is not essential,
+      like probing for other details such as the amount of memory
+      installed, etc.  It is recommended that the
+      <function>xf86MatchPciInstances()</function> helper function be used
+      for identifying matching PCI devices, and similarly the
+      <function>xf86MatchIsaInstances()</function> for ISA (non-PCI) devices
+      (see the <link linkend="rac">RAC</link> section).  These helpers also
+      checks and claims the appropriate entity.  When not using the
+      helper, that should be done with <function>xf86CheckPciSlot()</function>
+      and <function>xf86ClaimPciSlot()</function> for PCI devices and
+      <function>xf86ClaimIsaSlot()</function> for ISA devices (see the
+      <link linkend="rac">RAC</link> section).
+	</para>
+
+	<para>
+      The probe must register all non-relocatable resources at this
+      stage.  If a resource conflict is found between exclusive resources
+      the driver will fail immediately.  This is usually best done with
+      the <function>xf86ConfigPciEntity()</function> helper function
+      for PCI and <function>xf86ConfigIsaEntity()</function> for ISA
+      (see the <link linkend="rac">RAC</link> section).  It is possible to
+      register some entity specific functions with those helpers.  When
+      not using the helpers, the <function>xf86AddEntityToScreen()</function>
+      <function>xf86ClaimFixedResources()</function> and
+      <function>xf86SetEntityFuncs()</function> should be used instead (see
+      the <link linkend="rac">RAC</link> section).
+	</para>
+
+	<para>
+      If a chipset is specified in an active device section which the
+      driver considers relevant (ie it has no driver specified, or the
+      driver specified matches the driver doing the probe), the Probe
+      must return <constant>FALSE</constant> if the chipset doesn't match
+      one supported by the driver.
+	</para>
+
+	<para>
+      If there are no active device sections that the driver considers
+      relevant, it must return <constant>FALSE</constant>.
+	</para>
+
+	<para>
+      Allocate a <structname>ScrnInfoRec</structname> for each active instance of the
+      hardware found, and fill in the basic information, including the
+      other driver entry points.   This is best done with the
+      <function>xf86ConfigIsaEntity()</function> helper function for ISA
+      instances or <function>xf86ConfigPciEntity()</function> for PCI instances.
+      These functions allocate a <structname>ScrnInfoRec</structname> for active
+      entities. Optionally <function>xf86AllocateScreen()</function>
+      function may also be used to allocate the <structname>ScrnInfoRec</structname>.
+      Any of these functions take care of initialising fields to defined
+      ``unused'' values.
+	</para>
+
+	<para>
+      Claim the entities for each instance of the hardware found.  This
+      prevents other drivers from claiming the same hardware.
+	</para>
+
+	<para>
+      Must leave hardware in the same state it found it in, and must not
+      do any hardware initialisation.
+	</para>
+
+	<para>
+      All detection can be overridden via the config file, and that
+      parsed information is available to the driver at this stage.
+	</para>
+
+	<para>
+      Returns <constant>TRUE</constant> if one or more instances are found,
+      and <constant>FALSE</constant> otherwise.
+	</para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    int xf86MatchDevice(const char *drivername,
+                        GDevPtr **driversectlist)
+	  </programlisting>
+	  <blockquote><para>
+      This function takes the name of the driver and returns via
+      <parameter>driversectlist</parameter> a list of device sections that
+      match the driver name.  The function return value is the number
+      of matches found.  If a fatal error is encountered the return
+      value is <literal>-1</literal>.
+	    </para>
+
+	    <para>
+      The caller should use <function>xfree()</function> to free
+      <parameter>*driversectlist</parameter> when it is no longer needed.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    ScrnInfoPtr xf86AllocateScreen(DriverPtr drv, int flags)
+	  </programlisting>
+	  <blockquote><para>
+      This function allocates a new <structname>ScrnInfoRec</structname> in the
+      <varname>xf86Screens[]</varname> array.  This function is normally
+      called by the video driver <function>ChipProbe()</function> functions.
+      The return value is a pointer to the newly allocated
+      <structname>ScrnInfoRec</structname>.  The <structfield>scrnIndex</structfield>,
+      <structfield>origIndex</structfield>, <structfield>module</structfield> and
+      <structfield>drv</structfield> fields are initialised.  The reference count
+      in <parameter>drv</parameter> is incremented.  The storage for any
+      currently allocated ``privates'' pointers is also allocated and
+      the <structfield>privates</structfield> field initialised (the privates data
+      is of course not allocated or initialised).  This function never
+      returns on failure.  If the allocation fails, the server exits
+      with a fatal error.  The flags value is not currently used, and
+      should be set to zero.
+	    </para></blockquote>
+	</para></blockquote>
+
+      <para>
+    At the completion of this, a list of <structname>ScrnInfoRecs</structname>
+    have been allocated in the <varname>xf86Screens[]</varname> array, and
+    the associated entities and fixed resources have been claimed.  The
+    following <structname>ScrnInfoRec</structname> fields must be initialised at
+    this point:
+
+	<literallayout>
+          driverVersion
+          driverName
+          scrnIndex(*)
+          origIndex(*)
+          drv(*)
+          module(*)
+          name
+          Probe
+          PreInit
+          ScreenInit
+          EnterVT
+          LeaveVT
+          numEntities
+          entityList
+          access
+	</literallayout>
+
+    <literal>(*)</literal> These are initialised when the <structname>ScrnInfoRec</structname>
+    is allocated, and not explicitly by the driver.
+      </para>
+
+      <para>
+    The following <structname>ScrnInfoRec</structname> fields must be initialised
+    if the driver is going to use them:
+
+	<literallayout>
+          SwitchMode
+          AdjustFrame
+          FreeScreen
+          ValidMode
+	</literallayout>
+      </para>
+    </sect2>
+
+    <sect2>
+      <title>Matching Screens</title>
+
+      <para>
+    This is done at the start of the first server generation only.
+      </para>
+
+      <para>
+    After the Probe phase is finished, there will be some number of
+    <structname>ScrnInfoRec</structname>s.  These are then matched with the active
+    &k.screen; sections in the xorg.conf, and those not having an active
+    &k.screen; section are deleted.  If the number of remaining screens
+    is 0, <function>InitOutput()</function> sets
+    <structfield>screenInfo.numScreens</structfield> to <constant>0</constant> and
+    returns.
+      </para>
+
+      <para>
+    At this point the following fields of the <structname>ScrnInfoRec</structname>s
+    must be initialised:
+
+	<literallayout>
+          confScreen
+	</literallayout>
+      </para>
+
+    </sect2>
+
+    <sect2>
+      <title>Allocate non-conflicting resources</title>
+
+      <para>
+    This is done at the start of the first server generation only.
+      </para>
+
+      <para>
+    Before calling the drivers again, the resource information collected
+    from the Probe phase is processed.  This includes checking the extent
+    of PCI resources for the probed devices, and resolving any conflicts
+    in the relocatable PCI resources.  It also reports conflicts, checks
+    bus routing issues, and anything else that is needed to enable the
+    entities for the next phase.
+      </para>
+
+      <para>
+    If any drivers registered an <function>EntityInit()</function> function
+    during the Probe phase, then they are called here.
+      </para>
+
+    </sect2>
+
+    <sect2>
+      <title>Sort the Screens and pre-check Monitor Information</title>
+
+      <para>
+    This is done at the start of the first server generation only.
+      </para>
+
+      <para>
+    The list of screens is sorted to match the ordering requested in the
+    config file.
+      </para>
+
+      <para>
+    The list of modes for each active monitor is checked against the
+    monitor's parameters.  Invalid modes are pruned.
+      </para>
+
+    </sect2>
+
+    <sect2>
+      <title>PreInit</title>
+
+      <para>
+    This is done at the start of the first server generation only.
+      </para>
+
+      <para>
+    For each <structname>ScrnInfoRec</structname>, enable access to the screens entities and call
+    the <function>ChipPreInit()</function> function.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool ChipPreInit(ScrnInfoRec screen, int flags);
+	  </programlisting>
+	  <blockquote><para>
+      The purpose of this function is to find out all the information
+      required to determine if the configuration is usable, and to
+      initialise those parts of the <structname>ScrnInfoRec</structname> that
+      can be set once at the beginning of the first server generation.
+	    </para>
+
+	    <para>
+      The number of entities registered for the screen should be checked
+      against the expected number (most drivers expect only one).  The
+      entity information for each of them should be retrieved (with
+      <function>xf86GetEntityInfo()</function>) and checked for the correct
+      bus type and that none of the sharable resources registered during
+      the Probe phase was rejected.
+	    </para>
+
+	    <para>
+      Access to resources for the entities that can be controlled in a
+      device-independent way are enabled before this function is called.
+      If the driver needs to access any resources that it has disabled
+      in an <function>EntityInit()</function> function that it registered,
+      then it may enable them here providing that it disables them before
+      this function returns.
+	    </para>
+
+	    <para>
+      This includes probing for video memory, clocks, ramdac, and all
+      other HW info that is needed.  It includes determining the
+      depth/bpp/visual and related info.  It includes validating and
+      determining the set of video modes that will be used (and anything
+      that is required to determine that).
+	    </para>
+
+	    <para>
+      This information should be determined in the least intrusive way
+      possible.  The state of the HW must remain unchanged by this
+      function.  Although video memory (including MMIO) may be mapped
+      within this function, it must be unmapped before returning.  Driver
+      specific information should be stored in a structure hooked into
+      the <structname>ScrnInfoRec</structname>'s <structfield>driverPrivate</structfield>
+      field.  Any other modules which require persistent data (ie data
+      that persists across server generations) should be initialised in
+      this function, and they should allocate a ``privates'' index to
+      hook their data into by calling
+      <function>xf86AllocateScrnInfoPrivateIndex()</function>.  The ``privates''
+      data is persistent.
+	    </para>
+
+	    <para>
+      Helper functions for some of these things are provided at the
+      XFree86 common level, and the driver can choose to make use of
+      them.
+	    </para>
+
+	    <para>
+      All additional resources that the screen needs must be registered
+      here.  This should be done with
+      <function>xf86RegisterResources()</function>.  If some of the fixed
+      resources registered in the Probe phase are not needed or not
+      decoded by the hardware when in the OPERATING server state, their
+      status should be updated with
+      <function>xf86SetOperatingState()</function>.
+	    </para>
+
+	    <para>
+      Modules may be loaded at any point in this function, and all
+      modules that the driver will need must be loaded before the end
+      of this function.  Either the  <function>xf86LoadSubModule()</function>
+      or the <function>xf86LoadDrvSubModule()</function> function should be
+      used to load modules depending on whether a
+      <structname>ScrnInfoRec</structname> has been set up. A driver may unload
+      a module within this function if it was only needed temporarily,
+      and the <function>xf86UnloadSubModule()</function> function should be used
+      to do that.  Otherwise there is no need to explicitly unload modules
+      because the loader takes care of module dependencies and will
+      unload submodules automatically if/when the driver module is
+      unloaded.
+	    </para>
+
+	    <para>
+      The bulk of the <structname>ScrnInfoRec</structname> fields should be filled
+      out in this function.
+	    </para>
+
+	    <para>
+      <function>ChipPreInit()</function> returns <constant>FALSE</constant> when
+      the configuration is unusable in some way (unsupported depth, no
+      valid modes, not enough video memory, etc), and <constant>TRUE</constant>
+      if it is usable.
+	    </para>
+
+	    <para>
+      It is expected that if the <function>ChipPreInit()</function> function
+      returns <constant>TRUE</constant>, then the only reasons that subsequent
+      stages in the driver might fail are lack or resources (like xalloc
+      failures).  All other possible reasons for failure should be
+      determined by the <function>ChipPreInit()</function> function.
+	    </para></blockquote>
+	</para></blockquote>
+
+      <para>
+    The <structname>ScrnInfoRec</structname>s for screens where the <function>ChipPreInit()</function> fails are removed.
+    If none remain, <function>InitOutput()</function> sets <structfield>screenInfo.numScreens</structfield> to <constant>0</constant> and returns.
+      </para>
+
+      <para>
+    At this point, further fields of the <structname>ScrnInfoRec</structname>s would normally be
+    filled in.  Most are not strictly mandatory, but many are required
+    by other layers and/or helper functions that the driver may choose
+    to use.  The documentation for those layers and helper functions
+    indicates which they require.
+      </para>
+
+      <para>
+    The following fields of the <structname>ScrnInfoRec</structname>s should be filled in if the
+    driver is going to use them:
+
+	<literallayout>
+          monitor
+          display
+          depth
+          pixmapBPP
+          bitsPerPixel
+          weight                (&gt;8bpp only)
+          mask                  (&gt;8bpp only)
+          offset                (&gt;8bpp only)
+          rgbBits               (8bpp only)
+          gamma
+          defaultVisual
+          maxHValue
+          maxVValue
+          virtualX
+          virtualY
+          displayWidth
+          frameX0
+          frameY0
+          frameX1
+          frameY1
+          zoomLocked
+          modePool
+          modes
+          currentMode
+          progClock             (TRUE if clock is programmable)
+          chipset
+          ramdac
+          clockchip
+          numClocks             (if not programmable)
+          clock[]               (if not programmable)
+          videoRam
+          biosBase
+          memBase
+          memClk
+          driverPrivate
+          chipID
+          chipRev
+	</literallayout>
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    pointer xf86LoadSubModule(ScrnInfoPtr pScrn, const char *name);
+      and
+    pointer xf86LoadDrvSubModule(DriverPtr drv, const char *name);
+	  </programlisting>
+	  <blockquote><para>
+      Load a module that a driver depends on.  This function loads the
+      module <parameter>name</parameter> as a sub module of the driver.  The
+      return value is a handle identifying the new module.  If the load
+      fails, the return value will be <constant>NULL</constant>.  If a driver
+      needs to explicitly unload a module it has loaded in this way,
+      the return value must be saved and passed to
+      <function>xf86UnloadSubModule()</function> when unloading.
+
+	    </para></blockquote>
+	</para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void xf86UnloadSubModule(pointer module);
+	  </programlisting>
+	  <blockquote><para>
+      Unloads the module referenced by <parameter>module</parameter>.
+      <parameter>module</parameter> should be a pointer returned previously
+      by <function>xf86LoadSubModule()</function> or
+      <function>xf86LoadDrvSubModule()</function> .
+
+	    </para></blockquote>
+	</para></blockquote>
+    </sect2>
+
+    <sect2>
+      <title>Cleaning up Unused Drivers</title>
+
+      <para>
+    At this point it is known which screens will be in use, and which
+    drivers are being used.  Unreferenced drivers (and modules they
+    may have loaded) are unloaded here.
+      </para>
+
+    </sect2>
+
+    <sect2>
+      <title>Consistency Checks</title>
+
+      <para>
+    The parameters that must be global to the server, like pixmap formats,
+    bitmap bit order, bitmap scanline unit and image byte order are
+    compared for each of the screens.  If a mismatch is found, the server
+    exits with an appropriate message.
+      </para>
+
+    </sect2>
+
+    <sect2>
+      <title>Check if Resource Control is Needed</title>
+
+      <para>
+    Determine if resource access control is needed.  This is the case
+    if more than one screen is used.  If necessary the RAC wrapper module
+    is loaded.
+      </para>
+    </sect2>
+
+    <sect2>
+      <title>AddScreen (ScreenInit)</title>
+
+      <para>
+    At this point, the valid screens are known.
+    <function>AddScreen()</function> is called for each of them, passing
+    <function>ChipScreenInit()</function> as the argument.
+    <function>AddScreen()</function> is a DIX function that allocates a new
+    <structfield>screenInfo.screen[]</structfield> entry (aka
+    <varname>pScreen</varname>), and does some basic initialisation of it.
+    It then calls the <function>ChipScreenInit()</function> function, with
+    <parameter>pScreen</parameter> as one of its arguments.  If
+    <function>ChipScreenInit()</function> returns <constant>FALSE</constant>,
+    <function>AddScreen()</function> returns <constant>-1</constant>.  Otherwise
+    it returns the index of the screen.  <function>AddScreen()</function>
+    should only fail because of programming errors or failure to allocate
+    resources (like memory).  All configuration problems should be
+    detected BEFORE this point.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool ChipScreenInit(int index, ScreenPtr pScreen,
+                        int argc, char **argv);
+	  </programlisting>
+	  <blockquote><para>
+      This is called at the start of each server generation.
+	    </para>
+
+	    <para>
+      Fill in all of <parameter>pScreen</parameter>, possibly doing some of
+      this by calling ScreenInit functions from other layers like mi,
+      framebuffers (cfb, etc), and extensions.
+	    </para>
+
+	    <para>
+      Decide which operations need to be placed under resource access
+      control.  The classes of operations are the frame buffer operations
+      (<constant>RAC_FB</constant>), the pointer operations
+      (<constant>RAC_CURSOR</constant>), the viewport change operations
+      (<constant>RAC_VIEWPORT</constant>) and the colormap operations
+      (<constant>RAC_COLORMAP</constant>).  Any operation that requires
+      resources which might be disabled during OPERATING state should
+      be set to use RAC.  This can be specified separately for memory
+      and IO resources (the <structfield>racMemFlags</structfield> and
+      <structfield>racIoFlags</structfield> fields of the <structname>ScrnInfoRec</structname>
+      respectively).
+	    </para>
+
+	    <para>
+      Map any video memory or other memory regions.
+	    </para>
+
+	    <para>
+      Save the video card state.  Enough state must be saved so that
+      the original state can later be restored.
+	    </para>
+
+	    <para>
+      Initialise the initial video mode.  The <structname>ScrnInfoRec</structname>'s
+      <structfield>vtSema</structfield> field should be set to <constant>TRUE</constant>
+      just prior to changing the video hardware's state.
+
+	    </para></blockquote>
+	</para></blockquote>
+
+
+      <para>
+    The <function>ChipScreenInit()</function> function (or functions from other
+    layers that it calls) should allocate entries in the
+    <structname>ScreenRec</structname>'s <structfield>devPrivates</structfield> area by
+    calling <function>AllocateScreenPrivateIndex()</function> if it needs
+    per-generation storage.  Since the <structname>ScreenRec</structname>'s
+    <structfield>devPrivates</structfield> information is cleared for each server
+    generation, this is the correct place to initialise it.
+      </para>
+
+      <para>
+    After <function>AddScreen()</function> has successfully returned, the
+    following <structname>ScrnInfoRec</structname> fields are initialised:
+
+	<literallayout>
+          pScreen
+          racMemFlags
+          racIoFlags
+	</literallayout>
+      </para>
+
+      <para>
+    The <function>ChipScreenInit()</function> function should initialise the
+    <structfield>CloseScreen</structfield> and <structfield>SaveScreen</structfield> fields
+    of <parameter>pScreen</parameter>.  The old value of
+    <structfield>pScreen-&gt;CloseScreen</structfield> should be saved as part of
+    the driver's per-screen private data, allowing it to be called from
+    <function>ChipCloseScreen()</function>.  This means that the existing
+    <function>CloseScreen()</function> function is wrapped.
+      </para>
+    </sect2>
+
+    <sect2>
+      <title>Finalising RAC Initialisation</title>
+
+      <para>
+    After all the <function>ChipScreenInit()</function> functions have been
+    called, each screen has registered its RAC requirements.  This
+    information is used to determine which shared resources are requested
+    by more than one driver and set the access functions accordingly.
+    This is done following these rules:
+
+	<orderedlist>
+	  <listitem><para>
+	The sharable resources registered by each entity are compared.
+	If a resource is registered by more than one entity the entity
+	will be marked to indicate that it needs to share this resources
+	type (IO or MEM).
+	    </para></listitem>
+
+	  <listitem><para>
+        A resource marked ``disabled'' during OPERATING state will be
+        ignored entirely.
+	    </para></listitem>
+
+	  <listitem><para>
+	A resource marked ``unused'' will only conflict with an overlapping
+	resource of an other entity if the second is actually in use
+	during OPERATING state.
+	    </para></listitem>
+
+	  <listitem><para>
+	If an ``unused'' resource was found to conflict but the entity
+	does not use any other resource of this type the entire resource
+	type will be disabled for that entity.
+	    </para></listitem>
+	</orderedlist>
+      </para>
+
+    </sect2>
+
+    <sect2>
+      <title>Finishing InitOutput()</title>
+
+      <para>
+    At this point <function>InitOutput()</function> is finished, and all the
+    screens have been setup in their initial video mode.
+      </para>
+
+    </sect2>
+
+    <sect2>
+      <title>Mode Switching</title>
+
+      <para>
+    When a SwitchMode event is received, <function>ChipSwitchMode()</function>
+    is called (when it exists):
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool ChipSwitchMode(int index, DisplayModePtr mode, int flags);
+	  </programlisting>
+	  <blockquote><para>
+      Initialises the new mode for the screen identified by
+      <parameter>index;</parameter>.  The viewport may need to be adjusted
+      also.
+
+	    </para></blockquote>
+	</para></blockquote>
+
+    </sect2>
+
+    <sect2>
+      <title>Changing Viewport</title>
+
+      <para>
+    When a Change Viewport event is received,
+    <function>ChipAdjustFrame()</function> is called (when it exists):
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    void ChipAdjustFrame(int index, int x, int y, int flags);
+	  </programlisting>
+	  <blockquote><para>
+      Changes the viewport for the screen identified by
+      <parameter>index;</parameter>.
+	    </para>
+
+	    <para>
+      It should be noted that many chipsets impose restrictions on where the
+      viewport may be placed in the virtual resolution, either for alignment
+      reasons, or to prevent the start of the viewport from being positioned
+      within a pixel (as can happen in a 24bpp mode).  After calculating the
+      value the chipset's panning registers need to be set to for non-DGA
+      modes, this function should recalculate the ScrnInfoRec's
+      <structfield>frameX0</structfield>, <structfield>frameY0</structfield>, <structfield>frameX1</structfield>
+      and <structfield>frameY1</structfield> fields to correspond to that value.  If
+      this is not done, switching to another mode might cause the position
+      of a hardware cursor to change.
+
+	    </para></blockquote>
+	</para></blockquote>
+
+    </sect2>
+
+    <sect2>
+      <title>VT Switching</title>
+
+      <para>
+    When a VT switch event is received, <function>xf86VTSwitch()</function>
+    is called.  <function>xf86VTSwitch()</function> does the following:
+
+	<variablelist>
+	  <varlistentry><term>On ENTER:</term>
+	    <listitem>
+	      <itemizedlist>
+		<listitem><para>
+		    enable port I/O access
+		  </para></listitem>
+
+		<listitem><para>
+		    save and initialise the bus/resource state
+		  </para></listitem>
+
+		<listitem><para>
+		    enter the SETUP server state
+		  </para></listitem>
+
+		<listitem><para>
+		    calls <function>ChipEnterVT()</function> for each screen
+		  </para></listitem>
+
+		<listitem><para>
+		    enter the OPERATING server state
+		  </para></listitem>
+
+		<listitem><para>
+		    validate GCs
+		  </para></listitem>
+
+		<listitem><para>
+		    Restore fb from saved pixmap for each screen
+		  </para></listitem>
+
+		<listitem><para>
+		    Enable all input devices
+		  </para></listitem>
+	      </itemizedlist>
+	    </listitem>
+	  </varlistentry>
+	  <varlistentry>
+	    <term>On LEAVE:</term>
+	    <listitem>
+	      <itemizedlist>
+		<listitem><para>
+		    Save fb to pixmap for each screen
+		  </para></listitem>
+
+		<listitem><para>
+		    validate GCs
+		  </para></listitem>
+
+		<listitem><para>
+		    enter the SETUP server state
+		  </para></listitem>
+
+		<listitem><para>
+		    calls <function>ChipLeaveVT()</function> for each screen
+		  </para></listitem>
+
+		<listitem><para>
+		    disable all input devices
+		  </para></listitem>
+
+		<listitem><para>
+		    restore bus/resource state
+		  </para></listitem>
+
+		<listitem><para>
+		    disables port I/O access
+		  </para></listitem>
+	      </itemizedlist>
+	    </listitem>
+	  </varlistentry>
+	</variablelist>
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool ChipEnterVT(int index, int flags);
+	  </programlisting>
+	  <blockquote><para>
+      This function should initialise the current video mode and
+      initialise the viewport, turn on the HW cursor if appropriate,
+      etc.
+	    </para>
+
+	    <para>
+      Should it re-save the video state before initialising the video
+      mode?
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void ChipLeaveVT(int index, int flags);
+	  </programlisting>
+	  <blockquote><para>
+      This function should restore the saved video state.  If
+      appropriate it should also turn off the HW cursor, and invalidate
+      any pixmap/font caches.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <para>
+    Optionally, <function>ChipLeaveVT()</function> may also unmap memory
+    regions.  If so, <function>ChipEnterVT()</function> will need to remap
+    them.  Additionally, if an aperture used to access video memory is
+    unmapped and remapped in this fashion, <function>ChipEnterVT()</function>
+    will also need to notify the framebuffer layers of the aperture's new
+    location in virtual memory.  This is done with a call to the screen's
+    <function>ModifyPixmapHeader()</function> function, as follows
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    (*pScreen-&gt;ModifyPixmapHeader)(pScrn-&gt;ppix,
+                                   -1, -1, -1, -1, -1, NewApertureAddress);
+	  </programlisting>
+	  <blockquote><para>
+        where the <structfield>``ppix''</structfield> field in a ScrnInfoRec
+        points to the pixmap used by the screen's
+        <function>SaveRestoreImage()</function> function to hold the screen's
+        contents while switched out.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <para>
+    Currently, aperture remapping, as described here, should not be
+    attempted if the driver uses the <literal remap="tt">xf8_16bpp</literal> or
+    <literal remap="tt">xf8_32bpp</literal> framebuffer layers.  A pending
+    restructuring of VT switching will address this restriction in
+    the near future.
+      </para>
+
+      <para>
+    Other layers may wrap the <function>ChipEnterVT()</function> and
+    <function>ChipLeaveVT()</function> functions if they need to take some
+    action when these events are received.
+      </para>
+    </sect2>
+
+    <sect2>
+      <title>End of server generation</title>
+
+      <para>
+    At the end of each server generation, the DIX layer calls
+    <function>ChipCloseScreen()</function> for each screen:
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool ChipCloseScreen(int index, ScreenPtr pScreen);
+	  </programlisting>
+	  <blockquote><para>
+      This function should restore the saved video state and unmap the
+      memory regions.
+	    </para>
+
+	    <para>
+      It should also free per-screen data structures allocated by the
+      driver.  Note that the persistent data held in the
+      <structname>ScrnInfoRec</structname>'s <structfield>driverPrivate</structfield> field
+      should not be freed here because it is needed by subsequent server
+      generations.
+	    </para>
+
+	    <para>
+      The <structname>ScrnInfoRec</structname>'s <structfield>vtSema</structfield> field
+      should be set to <constant>FALSE</constant> once the video HW state
+      has been restored.
+	    </para>
+
+	    <para>
+      Before freeing the per-screen driver data the saved
+      <structfield>CloseScreen</structfield> value should be restored to
+      <structfield>pScreen-&gt;CloseScreen</structfield>, and that function should
+      be called after freeing the data.
+
+	    </para></blockquote>
+	</para></blockquote>
+    </sect2>
+  </sect1>
+
+  <sect1>
+    <title>Optional Driver Functions</title>
+
+    <para>
+The functions outlined here can be called from the XFree86 common layer,
+but their presence is optional.
+    </para>
+
+    <sect2>
+      <title>Mode Validation</title>
+
+      <para>
+    When a mode validation helper supplied by the XFree86-common layer is
+    being used, it can be useful to provide a function to check for hw
+    specific mode constraints:
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    ModeStatus ChipValidMode(int index, DisplayModePtr mode,
+                             Bool verbose, int flags);
+	  </programlisting>
+	  <blockquote><para>
+      Check the passed mode for hw-specific constraints, and return the
+      appropriate status value.
+
+	    </para></blockquote>
+	</para></blockquote>
+
+      <para>
+This function may also modify the effective timings and clock of the passed
+mode.  These have been stored in the mode's <structfield>Crtc*</structfield> and
+<structfield>SynthClock</structfield> elements, and have already been adjusted for
+interlacing, doublescanning, multiscanning and clock multipliers and dividers.
+The function should not modify any other mode field, unless it wants to modify
+the mode timings reported to the user by <function>xf86PrintModes()</function>.
+      </para>
+
+      <para>
+The function is called once for every mode in the xorg.conf Monitor section
+assigned to the screen, with <parameter>flags</parameter> set to
+<constant>MODECHECK_INITIAL</constant>.  It is subsequently called for every mode
+in the xorg.conf Display subsection assigned to the screen, with
+<parameter>flags</parameter> set to <constant>MODECHECK_FINAL</constant>.  In the second
+case, the mode will have successfully passed all other tests.  In addition,
+the <structname>ScrnInfoRec</structname>'s <structfield>virtualX</structfield>,
+<structfield>virtualY</structfield> and <structfield>displayWidth</structfield> fields will have been
+set as if the mode to be validated were to be the last mode accepted.
+      </para>
+
+      <para>
+In effect, calls with MODECHECK_INITIAL are intended for checks that do not
+depend on any mode other than the one being validated, while calls with
+MODECHECK_FINAL are intended for checks that may involve more than one mode.
+      </para>
+    </sect2>
+
+    <sect2>
+      <title>Free screen data</title>
+
+      <para>
+    When a screen is deleted prior to the completion of the ScreenInit
+    phase the <function>ChipFreeScreen()</function> function is called when defined.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    void ChipFreeScreen(int scrnindex, int flags);
+	  </programlisting>
+	  <blockquote><para>
+      Free any driver-allocated data that may have been allocated up to
+      and including an unsuccessful <function>ChipScreenInit()</function>
+      call.  This would predominantly be data allocated by
+      <function>ChipPreInit()</function> that persists across server
+      generations.  It would include the <structfield>driverPrivate</structfield>,
+      and any ``privates'' entries that modules may have allocated.
+
+	    </para></blockquote>
+	</para></blockquote>
+
+    </sect2>
+</sect1>
+
+  <sect1>
+    <title>Recommended driver functions</title>
+
+    <para>
+The functions outlined here are for internal use by the driver only.
+They are entirely optional, and are never accessed directly from higher
+layers.  The sample function declarations shown here are just examples.
+The interface (if any) used is up to the driver.
+    </para>
+
+    <sect2>
+      <title>Save</title>
+
+      <para>
+    Save the video state.  This could be called from <function>ChipScreenInit()</function> and
+    (possibly) <function>ChipEnterVT()</function>.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    void ChipSave(ScrnInfoPtr pScrn);
+	  </programlisting>
+	  <blockquote><para>
+      Saves the current state.  This will only be saving pre-server
+      states or states before returning to the server.  There is only
+      one current saved state per screen and it is stored in private
+      storage in the screen.
+
+	    </para></blockquote>
+	</para></blockquote>
+    </sect2>
+
+    <sect2>
+      <title>Restore</title>
+
+      <para>
+    Restore the original video state.  This could be called from the
+    <function>ChipLeaveVT()</function> and <function>ChipCloseScreen()</function>
+    functions.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    void ChipRestore(ScrnInfoPtr pScrn);
+	  </programlisting>
+	  <blockquote><para>
+      Restores the saved state from the private storage.  Usually only
+      used for restoring text modes.
+
+	    </para></blockquote>
+	</para></blockquote>
+
+    </sect2>
+
+    <sect2>
+      <title>Initialise Mode</title>
+
+      <para>
+    Initialise a video mode.  This could be called from the
+    <function>ChipScreenInit()</function>, <function>ChipSwitchMode()</function>
+    and <function>ChipEnterVT()</function> functions.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool ChipModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
+	  </programlisting>
+	  <blockquote><para>
+      Programs the hardware for the given video mode.
+
+	    </para></blockquote>
+	</para></blockquote>
+
+    </sect2>
+  </sect1>
+
+  <sect1>
+    <title>Data and Data Structures</title>
+
+    <sect2>
+      <title>Command line data</title>
+
+      <para>
+Command line options are typically global, and are stored in global
+variables.  These variables are read-only and are available to drivers
+via a function call interface.  Most of these command line values are
+processed via helper functions to ensure that they are treated consistently
+by all drivers.  The other means of access is provided for cases where
+the supplied helper functions might not be appropriate.
+      </para>
+
+      <para>
+Some of them are:
+
+	<literallayout>
+    xf86Verbose               verbosity level
+    xf86Bpp                   -bpp from the command line
+    xf86Depth                 -depth from the command line
+    xf86Weight                -weight from the command line
+    xf86Gamma                 -{r,g,b,}gamma from the command line
+    xf86FlipPixels            -flippixels from the command line
+    xf86ProbeOnly             -probeonly from the command line
+    defaultColorVisualClass   -cc from the command line
+	</literallayout>
+      </para>
+
+      <para>
+If we ever do allow for screen-specific command line options, we may
+need to rethink this.
+      </para>
+
+      <para>
+These can be accessed in a read-only manner by drivers with the following
+functions:
+      </para>
+
+     <blockquote><para>
+	  <programlisting>
+    int xf86GetVerbosity();
+	  </programlisting>
+	  <blockquote><para>
+      Returns the value of <varname>xf86Verbose</varname>.
+	    </para></blockquote>
+
+	</para></blockquote>
+
+     <blockquote><para>
+	  <programlisting>
+    int xf86GetDepth();
+	  </programlisting>
+	  <blockquote><para>
+      Returns the <option>-depth</option> command line setting.  If not
+      set on the command line, <constant>-1</constant> is returned.
+	    </para></blockquote>
+
+	</para></blockquote>
+
+     <blockquote><para>
+	  <programlisting>
+    rgb xf86GetWeight();
+	  </programlisting>
+	  <blockquote><para>
+      Returns the <option>-weight</option> command line setting.  If not
+      set on the command line, <literal remap="tt">{0, 0, 0}</literal> is returned.
+	    </para></blockquote>
+
+	</para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    Gamma xf86GetGamma();
+	  </programlisting>
+	  <blockquote><para>
+      Returns the <option>-gamma</option> or <option>-rgamma</option>,
+      <option>-ggamma</option>, <option>-bgamma</option> command line settings.
+      If not set on the command line, <literal remap="tt">{0.0, 0.0, 0.0}</literal>
+      is returned.
+	    </para></blockquote>
+
+	</para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool xf86GetFlipPixels();
+	  </programlisting>
+	  <blockquote><para>
+      Returns <constant>TRUE</constant> if <option>-flippixels</option> is
+      present on the command line, and <constant>FALSE</constant> otherwise.
+	    </para></blockquote>
+
+	</para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    const char *xf86GetServerName();
+	  </programlisting>
+	  <blockquote><para>
+      Returns the name of the X server from the command line.
+	    </para></blockquote>
+
+	</para></blockquote>
+    </sect2>
+
+    <sect2>
+      <title>Data handling</title>
+
+      <para>
+Config file data contains parts that are global, and parts that are
+Screen specific.  All of it is parsed into data structures that neither
+the drivers or most other parts of the server need to know about.
+      </para>
+
+      <para>
+The global data is typically not required by drivers, and as such, most
+of it is stored in the private <structname>xf86InfoRec</structname>.
+      </para>
+
+      <para>
+The screen-specific data collected from the config file is stored in
+screen, device, display, monitor-specific data structures that are separate
+from the <varname>ScrnInfoRecs</varname>, with the appropriate elements/fields
+hooked into the <varname>ScrnInfoRecs</varname> as required.  The screen
+config data is held in <structname>confScreenRec</structname>, device data in
+the <structname>GDevRec</structname>, monitor data in the <structname>MonRec</structname>,
+and display data in the <structname>DispRec</structname>.
+      </para>
+
+      <para>
+The XFree86 common layer's screen specific data (the actual data in use
+for each screen) is held in the <varname>ScrnInfoRecs</varname>.  As has
+been outlined above, the <varname>ScrnInfoRecs</varname> are allocated at probe
+time, and it is the responsibility of the Drivers' <function>Probe()</function>
+and <function>PreInit()</function> functions to finish filling them in based
+on both data provided on the command line and data provided from the
+Config file.  The precedence for this is:
+
+	<blockquote><para>
+    command line  -&gt;  config file  -&gt;  probed/default data
+	</para></blockquote>
+      </para>
+
+      <para>
+For most things in this category there are helper functions that the
+drivers can use to ensure that the above precedence is consistently
+used.
+      </para>
+
+      <para>
+As well as containing screen-specific data that the XFree86 common layer
+(including essential parts of the server infrastructure as well as helper
+functions) needs to access, it also contains some data that drivers use
+internally.  When considering whether to add a new field to the
+<structname>ScrnInfoRec</structname>, consider the balance between the convenience
+of things that lots of drivers need and the size/obscurity of the
+<structname>ScrnInfoRec</structname>.
+      </para>
+
+      <para>
+Per-screen driver specific data that cannot be accommodated with the
+static <structname>ScrnInfoRec</structname> fields is held in a driver-defined
+data structure, a pointer to which is assigned to the
+<structname>ScrnInfoRec</structname>'s <structfield>driverPrivate</structfield> field.  This
+is per-screen data that persists across server generations (as does the
+bulk of the static <structname>ScrnInfoRec</structname> data).  It would typically
+also include the video card's saved state.
+      </para>
+
+      <para>
+Per-screen data for other modules that the driver uses (for example,
+the XAA module) that is reset for each server generation is hooked into
+the <structname>ScrnInfoRec</structname> through it's <structfield>privates</structfield>
+field.
+      </para>
+
+      <para>
+Once it has stabilised, the data structures and variables accessible to
+video drivers will be documented here.  In the meantime, those things
+defined in the <filename>xf86.h</filename> and <filename>xf86str.h</filename>
+files are visible to video drivers.  Things defined in
+<filename>xf86Priv.h</filename> and <filename>xf86Privstr.h</filename> are NOT
+intended to be visible to video drivers, and it is an error for a driver
+to include those files.
+      </para>
+
+    </sect2>
+
+    <sect2>
+      <title>Accessing global data</title>
+
+      <para>
+Some other global state information that the drivers may access via
+functions is as follows:
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool xf86ServerIsExiting();
+	  </programlisting>
+	  <blockquote><para>
+      Returns <constant>TRUE</constant> if the server is at the end of a
+      generation and is in the process of exiting, and
+      <constant>FALSE</constant> otherwise.
+	    </para></blockquote>
+
+	</para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool xf86ServerIsResetting();
+	  </programlisting>
+	  <blockquote><para>
+      Returns <constant>TRUE</constant> if the server is at the end of a
+      generation and is in the process of resetting, and
+      <constant>FALSE</constant> otherwise.
+	    </para></blockquote>
+
+	</para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool xf86ServerIsInitialising();
+	  </programlisting>
+	  <blockquote><para>
+      Returns <constant>TRUE</constant> if the server is at the beginning of
+      a generation and is in the process of initialising, and
+      <constant>FALSE</constant> otherwise.
+	    </para></blockquote>
+
+	</para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool xf86ServerIsOnlyProbing();
+	  </programlisting>
+	  <blockquote><para>
+      Returns <constant>TRUE</constant> if the -probeonly command line flag
+      was specified, and <constant>FALSE</constant> otherwise.
+	    </para></blockquote>
+
+	</para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool xf86CaughtSignal();
+	  </programlisting>
+	  <blockquote><para>
+      Returns <constant>TRUE</constant> if the server has caught a signal,
+      and <constant>FALSE</constant> otherwise.
+	    </para></blockquote>
+
+	</para></blockquote>
+    </sect2>
+
+    <sect2>
+      <title>Allocating private data</title>
+
+      <para>
+A driver and any module it uses may allocate per-screen private storage
+in either the <structname>ScreenRec</structname> (DIX level) or
+<structname>ScrnInfoRec</structname> (XFree86 common layer level).
+<structname>ScreenRec</structname> storage persists only for a single server
+generation, and <structname>ScrnInfoRec</structname> storage persists across
+generations for the lifetime of the server.
+      </para>
+
+      <para>
+The <structname>ScreenRec</structname> <structfield>devPrivates</structfield> data must be
+reallocated/initialised at the start of each new generation.  This is
+normally done from the <function>ChipScreenInit()</function> function, and
+Init functions for other modules that it calls.  Data allocated in this
+way should be freed by the driver's <function>ChipCloseScreen()</function>
+functions, and Close functions for other modules that it calls.  A new
+<structfield>devPrivates</structfield> entry is allocated by calling the
+<function>AllocateScreenPrivateIndex()</function> function.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    int AllocateScreenPrivateIndex();
+	  </programlisting>
+	  <blockquote><para>
+      This function allocates a new element in the
+      <structfield>devPrivates</structfield> field of all currently existing
+      <literal remap="tt">ScreenRecs</literal>.  The return value is the index of this
+      new element in the <structfield>devPrivates</structfield> array.  The
+      <structfield>devPrivates</structfield> field is of type
+      <structname>DevUnion</structname>:
+
+	      <programlisting>
+        typedef union _DevUnion {
+            pointer             ptr;
+            long                val;
+            unsigned long       uval;
+            pointer             (*fptr)(void);
+        } DevUnion;
+	      </programlisting>
+
+      which allows the element to be used for any of the above types.
+      It is commonly used as a pointer to data that the caller allocates
+      after the new index has been allocated.
+	    </para>
+
+	    <para>
+      This function will return <constant>-1</constant> when there is an
+      error allocating the new index.
+	    </para>
+
+	  </blockquote>
+	</para></blockquote>
+
+      <para>
+The <structname>ScrnInfoRec</structname> <structfield>privates</structfield> data persists
+for the life of the server, so only needs to be allocated once.  This
+should be done from the <function>ChipPreInit()</function> function, and Init
+functions for other modules that it calls.  Data allocated in this way
+should be freed by the driver's <function>ChipFreeScreen()</function> functions,
+and Free functions for other modules that it calls.  A new
+<structfield>privates</structfield> entry is allocated by calling the
+<function>xf86AllocateScrnInfoPrivateIndex()</function> function.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    int xf86AllocateScrnInfoPrivateIndex();
+	  </programlisting>
+	  <blockquote><para>
+      This function allocates a new element in the <structfield>privates</structfield>
+      field of all currently existing <varname>ScrnInfoRecs</varname>.
+      The return value is the index of this new element in the
+      <structfield>privates</structfield> array.  The <structfield>privates</structfield>
+      field is of type <structfield>DevUnion</structfield>:
+
+	      <programlisting>
+        typedef union _DevUnion {
+            pointer             ptr;
+            long                val;
+            unsigned long       uval;
+            pointer             (*fptr)(void);
+        } DevUnion;
+	      </programlisting>
+
+      which allows the element to be used for any of the above types.
+      It is commonly used as a pointer to data that the caller allocates
+      after the new index has been allocated.
+	    </para>
+
+	    <para>
+      This function will not return when there is an error allocating
+      the new index.  When there is an error it will cause the server
+      to exit with a fatal error.  The similar function for allocation
+      privates in the <structname>ScreenRec</structname>
+      (<function>AllocateScreenPrivateIndex()</function>) differs in this
+      respect by returning <constant>-1</constant> when the allocation fails.
+	    </para>
+
+	  </blockquote>
+	</para></blockquote>
+    </sect2>
+  </sect1>
+
+  <sect1 id="rac">
+    <title>Keeping Track of Bus Resources</title>
+
+    <sect2>
+      <title>Theory of Operation</title>
+
+      <para>
+The XFree86 common layer has knowledge of generic access control mechanisms
+for devices on certain bus systems (currently the PCI bus) as well as
+of methods to enable or disable access to the buses itself.  Furthermore
+it can access information on resources decoded by these devices and if
+necessary modify it.
+      </para>
+
+      <para>
+When first starting the Xserver collects all this information, saves it
+for restoration, checks it for consistency, and if necessary, corrects
+it.  Finally it disables all resources on a generic level prior to
+calling any driver function.
+      </para>
+
+      <para>
+When the <function>Probe()</function> function of each driver is called the
+device sections are matched against the devices found in the system.
+The driver may probe devices at this stage that cannot be identified by
+using device independent methods.  Access to all resources that can be
+controlled in a device independent way is disabled.  The
+<function>Probe()</function> function should register all non-relocatable
+resources at this stage.  If a resource conflict is found between
+exclusive resources the driver will fail immediately.  Optionally the
+driver might specify an <function>EntityInit()</function>,
+<function>EntityLeave()</function> and <function>EntityEnter()</function> function.
+      </para>
+
+      <para>
+<function>EntityInit()</function> can be used to disable any shared resources
+that are not controlled by the generic access control functions.  It is
+called prior to the PreInit phase regardless if an entity is active or
+not.  When calling the <function>EntityInit()</function>,
+<function>EntityEnter()</function> and <function>EntityLeave()</function> functions
+the common level will disable access to all other entities on a generic
+level.  Since the common level has no knowledge of device specific
+methods to disable access to resources it cannot be guaranteed that
+certain resources are not decoded by any other entity until the
+<function>EntityInit()</function> or <function>EntityEnter()</function> phase is
+finished.  Device drivers should therefore register all those resources
+which they are going to disable.  If these resources are never to be
+used by any driver function they may be flagged <constant>ResInit</constant>
+so that they can be removed from the resource list after processing all
+<function>EntityInit()</function> functions.  <function>EntityEnter()</function>
+should disable decoding of all resources which are not registered as
+exclusive and which are not handled by the generic access control in
+the common level.  The difference to <function>EntityInit()</function> is
+that the latter one is only called once during lifetime of the server.
+It can therefore be used to set up variables prior to disabling resources.
+<function>EntityLeave()</function> should restore the original state when
+exiting the server or switching to a different VT.  It also needs to
+disable device specific access functions if they need to be disabled on
+server exit or VT switch.  The default state is to enable them before
+giving up the VT.
+      </para>
+
+      <para>
+In <function>PreInit()</function> phase each driver should check if any
+sharable resources it has registered during <function>Probe()</function> has
+been denied and take appropriate action which could simply be to fail.
+If it needs to access resources it has disabled during
+<function>EntitySetup()</function> it can do so provided it has registered
+these and will disable them before returning from
+<function>PreInit()</function>.  This also applies to all other driver
+functions.  Several functions are provided to request resource ranges,
+register these, correct PCI config space and add replacements for the
+generic access functions.  Resources may be marked ``disabled'' or
+``unused'' during OPERATING stage.  Although these steps could also be
+performed in <function>ScreenInit()</function>, this is not desirable.
+      </para>
+
+      <para>
+Following <function>PreInit()</function> phase the common level determines
+if resource access control is needed.  This is the case if more than
+one screen is used.  If necessary the RAC wrapper module is loaded.  In
+<function>ScreenInit()</function> the drivers can decide which operations
+need to be placed under RAC.  Available are the frame buffer operations,
+the pointer operations and the colormap operations.  Any operation that
+requires resources which might be disabled during OPERATING state should
+be set to use RAC.  This can be specified separately for memory and IO
+resources.
+      </para>
+
+      <para>
+When <function>ScreenInit()</function> phase is done the common level will
+determine which shared resources are requested by more than one driver
+and set the access functions accordingly.  This is done following these
+rules:
+
+	<orderedlist>
+	  <listitem><para>
+   The sharable resources registered by each entity are compared.  If
+   a resource is registered by more than one entity the entity will be
+   marked to need to share this resources type (<constant>IO</constant> or
+   <constant>MEM</constant>).
+	    </para></listitem>
+
+	  <listitem><para>
+   A resource marked ``disabled'' during OPERATING state will be ignored
+   entirely.
+	    </para></listitem>
+
+	  <listitem><para>
+   A resource marked ``unused'' will only conflicts with an overlapping
+   resource of an other entity if the second is actually in use during
+   OPERATING state.
+	    </para></listitem>
+
+	  <listitem><para>
+   If an ``unused'' resource was found to conflict however the entity
+   does not use any other resource of this type the entire resource type
+   will be disabled for that entity.
+	    </para></listitem>
+	</orderedlist>
+      </para>
+
+      <para>
+The driver has the choice among different ways to control access to
+certain resources:
+
+	<orderedlist>
+	  <listitem><para>
+   It can rely on the generic access functions.  This is probably the
+   most common case.  Here the driver only needs to register any resource
+   it is going to use.
+	    </para></listitem>
+
+	  <listitem><para>
+   It can replace the generic access functions by driver specific
+   ones.  This will mostly be used in cases where no generic access
+   functions are available.  In this case the driver has to make sure
+   these resources are disabled when entering the <function>PreInit()</function>
+   stage.  Since the replacement functions are registered in
+   <function>PreInit()</function> the driver will have to enable these
+   resources itself if it needs to access them during this state.  The
+   driver can specify if the replacement functions can control memory
+   and/or I/O resources separately.
+	    </para></listitem>
+
+	  <listitem><para>
+   The driver can enable resources itself when it needs them.  Each
+   driver function enabling them needs to disable them before it will
+   return.  This should be used if a resource which can be controlled
+   in a device dependent way is only required during SETUP state.  This
+   way it can be marked ``unused'' during OPERATING state.
+	    </para></listitem>
+	</orderedlist>
+      </para>
+
+      <para>
+A resource which is decoded during OPERATING state however never accessed
+by the driver should be marked unused.
+      </para>
+
+      <para>
+Since access switching latencies are an issue during Xserver operation,
+the common level attempts to minimize the number of entities that need
+to be placed under RAC control.  When a wrapped operation is called,
+the <function>EnableAccess()</function> function is called before control is
+passed on.  <function>EnableAccess()</function> checks if a screen is under
+access control.  If not it just establishes bus routing and returns.
+If the screen needs to be under access control,
+<function>EnableAccess()</function> determines which resource types
+(<literal remap="tt">MEM</literal>, <literal remap="tt">IO</literal>) are required.  Then it tests
+if this access is already established.  If so it simply returns.  If
+not it disables the currently established access, fixes bus routing and
+enables access to all entities registered for this screen.
+      </para>
+
+      <para>
+Whenever a mode switch or a VT-switch is performed the common level will
+return to SETUP state.
+      </para>
+    </sect2>
+
+    <sect2>
+      <title>Resource Types</title>
+
+      <para>
+Resource have certain properties.  When registering resources each range
+is accompanied by a flag consisting of the ORed flags of the different
+properties the resource has.  Each resource range may be classified
+according to
+
+	<itemizedlist>
+	  <listitem><para>
+       its physical properties i.e., if it addresses
+       memory (<constant>ResMem</constant>)  or
+       I/O space (<constant>ResIo</constant>),
+	    </para></listitem>
+	  <listitem><para>
+       if it addresses a
+       block (<constant>ResBlock</constant>) or
+       sparse (<constant>ResSparse</constant>)
+       range,
+	    </para></listitem>
+	  <listitem><para>
+       its access properties.
+	    </para></listitem>
+	</itemizedlist>
+      </para>
+
+      <para>
+There are two known access properties:
+
+	<itemizedlist>
+	  <listitem><para>
+  <constant>ResExclusive</constant>
+    for resources which may not be shared with any other device and
+	    </para></listitem>
+	  <listitem><para>
+  <constant>ResShared</constant>
+    for resources which can be disabled and therefore can be shared.
+	    </para></listitem>
+	</itemizedlist>
+      </para>
+
+      <para>
+If it is necessary to test a resource against any type a generic access
+type <constant>ResAny</constant> is provided.  If this is set the resource
+will conflict with any resource of a different entity intersecting its
+range.  Further it can be specified that a resource is decoded however
+never used during any stage (<constant>ResUnused</constant>) or during
+OPERATING state (<constant>ResUnusedOpr</constant>).  A resource only visible
+during the init functions (ie.  <function>EntityInit()</function>,
+<function>EntityEnter()</function> and <function>EntityLeave()</function> should
+be registered with the flag <constant>ResInit</constant>.  A resource that
+might conflict with background resource ranges may be flagged with
+<constant>ResBios</constant>.  This might be useful when registering resources
+ranges that were assigned by the system Bios.
+      </para>
+
+      <para>
+Several predefined resource lists are available for VGA and 8514/A
+resources in <filename>common/xf86Resources.h</filename>.
+      </para>
+    </sect2>
+
+    <sect2 id="avail">
+      <title>Available Functions</title>
+
+      <para>
+The functions provided for resource management are listed in their order
+of use in the driver.
+      </para>
+
+      <sect3>
+	<title>Probe Phase</title>
+
+	<para>
+In this phase each driver detects those resources it is able to drive,
+creates an entity record for each of them, registers non-relocatable
+resources and allocates screens and adds the resources to screens.
+	</para>
+
+	<para>
+Two helper functions are provided for matching device sections in the
+xorg.conf file to the devices:
+	</para>
+
+	<blockquote><para>
+	    <programlisting>
+    int xf86MatchPciInstances(const char *driverName, int vendorID,
+                              SymTabPtr chipsets, PciChipsets *PCIchipsets,
+                              GDevPtr *devList, int numDevs, DriverPtr drvp,
+                              int **foundEntities);
+	    </programlisting>
+	    <blockquote><para>
+      This function finds matches between PCI cards that a driver supports
+      and config file device sections.  It is intended for use in the
+      <function>ChipProbe()</function> function of drivers for PCI cards.
+      Only probed PCI devices with a vendor ID matching
+      <parameter>vendorID</parameter> are considered.  <parameter>devList</parameter>
+      and <parameter>numDevs</parameter> are typically those found from
+      calling <function>xf86MatchDevice()</function>, and represent the active
+      config file device sections relevant to the driver.
+      <parameter>PCIchipsets</parameter> is a table that provides a mapping
+      between the PCI device IDs, the driver's internal chipset tokens
+      and a list of fixed resources.
+	      </para>
+
+	      <para>
+      When a device section doesn't have a <emphasis>BusID</emphasis> entry it
+      can only match the primary video device.  Secondary devices are
+      only matched with device sections that have a matching
+      <emphasis>BusID</emphasis> entry.
+	      </para>
+
+	      <para>
+      Once the preliminary matches have been found, a final match is
+      confirmed by checking if the chipset override, ChipID override or
+      probed PCI chipset type match one of those given in the
+      <parameter>chipsets</parameter> and <parameter>PCIchipsets</parameter> lists.
+      The <parameter>PCIchipsets</parameter> list includes a list of the PCI
+      device IDs supported by the driver.  The list should be terminated
+      with an entry with PCI ID <constant>-1</constant>".  The
+      <parameter>chipsets</parameter> list is a table mapping the driver's
+      internal chipset tokens to names, and should be terminated with
+      a <constant>NULL</constant> entry.  Only those entries with a
+      corresponding entry in the <parameter>PCIchipsets</parameter> list are
+      considered.  The order of precedence is: config file chipset,
+      config file ChipID, probed PCI device ID.
+	      </para>
+
+	      <para>
+      In cases where a driver handles PCI chipsets with more than one
+      vendor ID, it may set <parameter>vendorID</parameter> to
+      <constant>0</constant>, and OR each devID in the list with (the
+      vendor&nbsp;ID&nbsp;&lt;&lt;&nbsp;16).
+	      </para>
+
+	      <para>
+      Entity index numbers for confirmed matches are returned as an
+      array via <parameter>foundEntities</parameter>.  The PCI information,
+      chipset token and device section for each match are found in the
+      <structname>EntityInfoRec</structname> referenced by the indices.
+	      </para>
+
+	      <para>
+      The function return value is the number of confirmed matches.  A
+      return value of <constant>-1</constant> indicates an internal error.
+      The returned <parameter>foundEntities</parameter> array should be freed
+      by the driver with <function>xfree()</function> when it is no longer
+      needed in cases where the return value is greater than zero.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    int xf86MatchIsaInstances(const char *driverName,
+                              SymTabPtr chipsets, IsaChipsets *ISAchipsets,
+                              DriverPtr drvp, FindIsaDevProc FindIsaDevice,
+                              GDevPtr *devList, int numDevs,
+                              int **foundEntities);
+	    </programlisting>
+	    <blockquote><para>
+      This function finds matches between ISA cards that a driver supports
+      and config file device sections.  It is intended for use in the
+      <function>ChipProbe()</function> function of drivers for ISA cards.
+      <parameter>devList</parameter> and <parameter>numDevs</parameter> are
+      typically those found from calling <function>xf86MatchDevice()</function>,
+      and represent the active config file device sections relevant to
+      the driver.  <parameter>ISAchipsets</parameter> is a table that provides
+      a mapping between the driver's internal chipset tokens and the
+      resource classes.  <parameter>FindIsaDevice</parameter> is a
+      driver-provided function that probes the hardware and returns the
+      chipset token corresponding to what was detected, and
+      <constant>-1</constant> if nothing was detected.
+	      </para>
+
+	      <para>
+      If the config file device section contains a chipset entry, then
+      it is checked against the <parameter>chipsets</parameter> list.  When
+      no chipset entry is present, the <parameter>FindIsaDevice</parameter>
+      function is called instead.
+	      </para>
+
+	      <para>
+      Entity index numbers for confirmed matches are returned as an
+      array via <parameter>foundEntities</parameter>.  The chipset token and
+      device section for each match are found in the
+      <structname>EntityInfoRec</structname> referenced by the indices.
+	      </para>
+
+	      <para>
+      The function return value is the number of confirmed matches.  A
+      return value of <constant>-1</constant> indicates an internal error.
+      The returned <parameter>foundEntities</parameter> array should be freed
+      by the driver with <function>xfree()</function> when it is no longer
+      needed in cases where the return value is greater than zero.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<para>
+These two helper functions make use of several core functions that are
+available at the driver level:
+	</para>
+
+	<blockquote><para>
+	    <programlisting>
+    Bool xf86ParsePciBusString(const char *busID, int *bus,
+                               int *device, int *func);
+	    </programlisting>
+	    <blockquote><para>
+      Takes a <parameter>BusID</parameter> string, and if it is in the correct
+      format, returns the PCI <parameter>bus</parameter>, <parameter>device</parameter>,
+      <parameter>func</parameter> values that it indicates.  The format of the
+      string is expected to be "PCI:bus:device:func" where each of `bus',
+      `device' and `func' are decimal integers.  The ":func" part may
+      be omitted, and the func value assumed to be zero, but this isn't
+      encouraged.  The "PCI" prefix may also be omitted.  The prefix
+      "AGP" is currently equivalent to the "PCI" prefix.  If the string
+      isn't a valid PCI BusID, the return value is <constant>FALSE</constant>.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    Bool xf86ComparePciBusString(const char *busID, int bus,
+                                 int device, int func);
+	    </programlisting>
+	    <blockquote><para>
+      Compares a <parameter>BusID</parameter> string with PCI <parameter>bus</parameter>,
+      <parameter>device</parameter>, <parameter>func</parameter> values.  If they
+      match <constant>TRUE</constant> is returned, and <constant>FALSE</constant>
+      if they don't.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    Bool xf86ParseIsaBusString(const char *busID);
+	    </programlisting>
+	    <blockquote><para>
+      Compares a <parameter>BusID</parameter> string with the ISA bus ID string
+      ("ISA" or "ISA:").  If they match <constant>TRUE</constant> is returned,
+      and <constant>FALSE</constant> if they don't.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    Bool xf86CheckPciSlot(int bus, int device, int func);
+	    </programlisting>
+	    <blockquote><para>
+      Checks if the PCI slot <literal remap="tt">bus:device:func</literal> has been
+      claimed.  If so, it returns <constant>FALSE</constant>, and otherwise
+      <constant>TRUE</constant>.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    int xf86ClaimPciSlot(int bus, int device, int func, DriverPtr drvp,
+                         int chipset, GDevPtr dev, Bool active);
+	    </programlisting>
+	    <blockquote><para>
+      This function is used to claim a PCI slot, allocate the associated
+      entity record and initialise their data structures.  The return
+      value is the index of the newly allocated entity record, or
+      <constant>-1</constant> if the claim fails.  This function should always
+      succeed if <function>xf86CheckPciSlot()</function> returned
+      <constant>TRUE</constant> for the same PCI slot.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    Bool xf86IsPrimaryPci(void);
+	    </programlisting>
+	    <blockquote><para>
+      This function returns <constant>TRUE</constant> if the primary card is
+      a PCI device, and <constant>FALSE</constant> otherwise.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    int xf86ClaimIsaSlot(DriverPtr drvp, int chipset,
+                         GDevPtr dev, Bool active);
+	    </programlisting>
+	    <blockquote><para>
+      This allocates an entity record entity and initialise the data
+      structures.  The return value is the index of the newly allocated
+      entity record.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    Bool xf86IsPrimaryIsa(void);
+	    </programlisting>
+	    <blockquote><para>
+      This function returns <constant>TRUE</constant> if the primary card is
+      an ISA (non-PCI) device, and <constant>FALSE</constant> otherwise.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<para>
+Two helper functions are provided to aid configuring entities:
+	</para>
+
+	<blockquote><para>
+	    <programlisting>
+    ScrnInfoPtr xf86ConfigPciEntity(ScrnInfoPtr pScrn,
+                                    int scrnFlag, int entityIndex,
+                                    PciChipsets *p_chip,
+                                    resList res, EntityProc init,
+                                    EntityProc enter, EntityProc leave,
+                                    pointer private);
+
+    ScrnInfoPtr xf86ConfigIsaEntity(ScrnInfoPtr pScrn,
+                                    int scrnFlag, int entityIndex,
+                                    IsaChipsets *i_chip,
+                                    resList res, EntityProc init,
+                                    EntityProc enter, EntityProc leave,
+                                    pointer private);
+	    </programlisting>
+	    <blockquote><para>
+      These functions are used to register the non-relocatable resources
+      for an entity, and the optional entity-specific <parameter>Init</parameter>, <parameter>Enter</parameter> and
+      <parameter>Leave</parameter> functions.  Usually the list of fixed resources is obtained
+      from the Isa/PciChipsets lists.  However an additional list of
+      resources may be passed.  Generally this is not required.
+      For active entities a <structname>ScrnInfoRec</structname> is allocated
+      if the <parameter>pScrn</parameter> argument is <constant>NULL</constant>.
+The
+      return value is <constant>TRUE</constant> when successful.  The init, enter, leave
+      functions are defined as follows:
+
+		<blockquote><para>
+		    <programlisting>
+        typedef void (*EntityProc)(int entityIndex,
+                                   pointer private);
+		    </programlisting>
+		  </para></blockquote>
+
+      They are passed the entity index and a pointer to a private scratch
+      area.  This can be set up during <function>Probe()</function> and
+      its address can be passed to
+      <function>xf86ConfigIsaEntity()</function> and
+      <function>xf86ConfigPciEntity()</function> as the last argument.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<para>
+These two helper functions make use of several core functions that are
+available at the driver level:
+
+	  <blockquote><para>
+	      <programlisting>
+    void xf86ClaimFixedResources(resList list, int entityIndex);
+	      </programlisting>
+	      <blockquote><para>
+      This function registers the non-relocatable resources which cannot
+      be disabled and which therefore would cause the server to fail
+      immediately if they were found to conflict.  It also records
+      non-relocatable but sharable resources for processing after the
+      <function>Probe()</function> phase.
+		</para>
+
+	      </blockquote></para></blockquote>
+
+	  <blockquote><para>
+	      <programlisting>
+    Bool xf86SetEntityFuncs(int entityIndex, EntityProc init,
+                            EntityProc enter, EntityProc leave, pointer);
+	      </programlisting>
+	      <blockquote><para>
+      This function registers with an entity the <parameter>init</parameter>,
+      <parameter>enter</parameter>, <parameter>leave</parameter> functions along
+      with the pointer to their private area.
+		</para>
+
+	    </blockquote></para></blockquote>
+
+	  <blockquote><para>
+	      <programlisting>
+    void xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex);
+	      </programlisting>
+	      <blockquote><para>
+      This function associates the entity referenced by
+      <parameter>entityIndex</parameter> with the screen.
+		</para>
+
+	      </blockquote></para></blockquote>
+	</para>
+      </sect3>
+
+      <sect3>
+	<title>PreInit Phase</title>
+
+	<para>
+During this phase the remaining resources should be registered.
+<function>PreInit()</function> should call <function>xf86GetEntityInfo()</function>
+to obtain a pointer to an <structname>EntityInfoRec</structname> for each entity
+it is able to drive and check if any resource are listed in its
+<structfield>resources</structfield> field.  If resources registered in the Probe
+phase have been rejected in the post-Probe phase
+(<structfield>resources</structfield> is non-<constant>NULL</constant>), then the driver should
+decide if it can continue without using these or if it should fail.
+	</para>
+
+	<blockquote><para>
+	    <programlisting>
+    EntityInfoPtr xf86GetEntityInfo(int entityIndex);
+	    </programlisting>
+	    <blockquote><para>
+      This function returns a pointer to the <structname>EntityInfoRec</structname>
+      referenced by <parameter>entityIndex</parameter>.  The returned
+      <structname>EntityInfoRec</structname> should be freed with
+      <function>xfree()</function> when no longer needed.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<para>
+Several functions are provided to simplify resource registration:
+	  <blockquote><para>
+	      <programlisting>
+    Bool xf86IsEntityPrimary(int entityIndex);
+	      </programlisting>
+	      <blockquote><para>
+      This function returns <constant>TRUE</constant> if the entity referenced
+      by <parameter>entityIndex</parameter> is the primary display device (i.e.,
+      the one initialised at boot time and used in text mode).
+		</para>
+
+	      </blockquote></para></blockquote>
+
+	  <blockquote><para>
+	      <programlisting>
+    Bool xf86IsScreenPrimary(int scrnIndex);
+	      </programlisting>
+	      <blockquote><para>
+      This function returns <constant>TRUE</constant> if the primary entity
+      is registered with the screen referenced by
+      <parameter>scrnIndex</parameter>.
+		</para>
+
+	      </blockquote></para></blockquote>
+
+	  <blockquote><para>
+	      <programlisting>
+    pciVideoPtr xf86GetPciInfoForEntity(int entityIndex);
+	      </programlisting>
+	      <blockquote><para>
+      This function returns a pointer to the <structname>pciVideoRec</structname>
+      for the specified entity.  If the entity is not a PCI device,
+      <constant>NULL</constant> is returned.
+		</para>
+
+	      </blockquote></para></blockquote>
+	</para>
+
+	<para>
+The primary function for registration of resources is:
+	  <blockquote><para>
+	      <programlisting>
+    resPtr xf86RegisterResources(int entityIndex, resList list,
+                                 int access);
+	      </programlisting>
+	      <blockquote><para>
+      This function tries to register the resources in
+      <parameter>list</parameter>.  If list is <constant>NULL</constant> it tries
+      to determine the resources automatically.  This only works for
+      entities that provide a generic way to read out the resource ranges
+      they decode.  So far this is only the case for PCI devices.  By
+      default the PCI resources are registered as shared
+      (<constant>ResShared</constant>) if the driver wants to set a different
+      access type it can do so by specifying the access flags in the
+      third argument.  A value of <constant>0</constant> means to use the
+      default settings.  If for any reason the resource broker is not
+      able to register some of the requested resources the function will
+      return a pointer to a list of the failed ones.  In this case the
+      driver may be able to move the resource to different locations.
+      In case of PCI bus entities this is done by passing the list of
+      failed resources to <function>xf86ReallocatePciResources()</function>.
+      When the registration succeeds, the return value is
+      <constant>NULL</constant>.
+		</para>
+
+	      </blockquote></para></blockquote>
+	  </para>
+
+	<blockquote><para>
+	    <programlisting>
+    resPtr xf86ReallocatePciResources(int entityIndex, resPtr pRes);
+	    </programlisting>
+	    <blockquote><para>
+      This function takes a list of PCI resources that need to be
+      reallocated and returns <constant>NULL</constant> when all relocations are
+      successful.
+      <function>xf86RegisterResources()</function> should be called again to
+      register the relocated resources with the broker.
+      If the reallocation fails, a list of the resources that could not be
+      relocated is returned.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+<para>
+Two functions are provided to obtain a resource range of a given type:
+	  <blockquote><para>
+	      <programlisting>
+    resRange xf86GetBlock(long type, memType size,
+                          memType window_start, memType window_end,
+                          memType align_mask, resPtr avoid);
+	      </programlisting>
+	      <blockquote><para>
+      This function tries to find a block range of size
+      <parameter>size</parameter> and type <parameter>type</parameter> in a window
+      bound by <parameter>window_start</parameter> and <parameter>window_end</parameter>
+      with the alignment specified in <parameter>align_mask</parameter>.
+      Optionally a list of resource ranges which should be avoided within
+      the window can be supplied.  On failure a zero-length range of
+      type <constant>ResEnd</constant> will be returned.
+		</para>
+	      </blockquote></para></blockquote>
+
+	  <blockquote><para>
+	      <programlisting>
+    resRange xf86GetSparse(long type, memType fixed_bits,
+                           memType decode_mask, memType address_mask,
+                           resPtr avoid);
+	      </programlisting>
+	      <blockquote><para>
+      This function is like the previous one, but attempts to find a
+      sparse range instead of a block range.  Here three values have to
+      be specified: the <parameter>address_mask</parameter> which marks all
+      bits of the mask part of the address, the <parameter>decode_mask</parameter>
+      which masks out the bits which are hardcoded and are therefore
+      not available for relocation and the values of the fixed bits.
+      The function tries to find a base that satisfies the given condition.
+      If the function fails it will return a zero range of type
+      <constant>ResEnd</constant>.  Optionally it might be passed a list of
+      resource ranges to avoid.
+		</para>
+
+	      </blockquote></para></blockquote>
+	</para>
+
+	<para>
+Some PCI devices are broken in the sense that they return invalid size
+information for a certain resource.  In this case the driver can supply
+the correct size and make sure that the resource range allocated for
+the card is large enough to hold the address range decoded by the card.
+The function <function>xf86FixPciResource()</function> can be used to do this:
+	  <blockquote><para>
+	      <programlisting>
+    Bool xf86FixPciResource(int entityIndex, unsigned int prt,
+                            CARD32 alignment, long type);
+	      </programlisting>
+	      <blockquote><para>
+      This function fixes a PCI resource allocation.  The
+      <parameter>prt</parameter> parameter contains the number of the PCI base
+      register that needs to be fixed (<constant>0-5</constant>, and
+      <constant>6</constant> for the BIOS base register).  The size is
+      specified by the alignment.  Since PCI resources need to span an
+      integral range of size <literal remap="tt">2&circ;n</literal>, the alignm      ent also
+      specifies the number of addresses that will be decoded.  If the
+      driver specifies a type mask it can override the default type for
+      PCI resources which is <constant>ResShared</constant>.  The resource
+      broker needs to know that to find a matching resource range.  This
+      function should be called before calling
+      <function>xf86RegisterResources()</function>.  The return value is
+      <constant>TRUE</constant> when the function succeeds.
+		</para>
+
+	      </blockquote></para></blockquote>
+
+	  <blockquote><para>
+	      <programlisting>
+    Bool xf86CheckPciMemBase(pciVideoPtr pPci, memType base);
+	      </programlisting>
+	      <blockquote><para>
+      This function checks that the memory base address specified matches
+      one of the PCI base address register values for the given PCI
+      device.  This is mostly used to check that an externally provided
+      base address (e.g., from a config file) matches an actual value
+      allocated to a device.
+		</para>
+
+	      </blockquote></para></blockquote>
+	</para>
+
+	<para>
+The driver may replace the generic access control functions for an entity.
+This is done with the <function>xf86SetAccessFuncs()</function>:
+	  <blockquote><para>
+	      <programlisting>
+    void xf86SetAccessFuncs(EntityInfoPtr pEnt,
+                            xf86SetAccessFuncPtr funcs,
+                            xf86SetAccessFuncPtr oldFuncs);
+	      </programlisting>
+     with:
+	      <programlisting>
+      typedef struct {
+          xf86AccessPtr mem;
+          xf86AccessPtr io;
+          xf86AccessPtr io_mem;
+      } xf86SetAccessFuncRec, *xf86SetAccessFuncPtr;
+	      </programlisting>
+	      <blockquote><para>
+      The driver can pass three functions: one for I/O access, one for
+      memory access and one for combined memory and I/O access.  If the
+      memory access and combined access functions are identical the
+      common level assumes that the memory access cannot be controlled
+      independently of I/O access, if the I/O access function and the
+      combined access functions are the same it is assumed that I/O can
+      not be controlled independently.  If memory and I/O have to be
+      controlled together all three values should be the same.  If a
+      non <constant>NULL</constant> value is passed as third argument it is
+      interpreted as an address where to store the old access record.
+      If the third argument is <constant>NULL</constant> it will be assumed
+      that the generic access should be enabled before replacing the
+      access functions.  Otherwise it will be disabled.  The driver may
+      enable them itself using the returned values.  It should do this
+      from its replacement access functions as the generic access may
+      be disabled by the common level on certain occasions.  If replacement
+      functions are specified they must control all resources of the
+      specific type registered for the entity.
+		</para>
+
+	      </blockquote></para></blockquote>
+	</para>
+
+	<para>
+To find out if a specific resource range conflicts with another
+resource the <function>xf86ChkConflict()</function> function may be used:
+	  <blockquote><para>
+	      <programlisting>
+    memType xf86ChkConflict(resRange *rgp, int entityIndex);
+	      </programlisting>
+	      <blockquote><para>
+      This function checks if the resource range <parameter>rgp</parameter> of
+      for the specified entity conflicts with with another resource.
+      If a conflict is found, the address of the start of the conflict
+      is returned.  The return value is zero when there is no conflict.
+		</para>
+
+	      </blockquote></para></blockquote>
+	</para>
+
+	<para>
+The OPERATING state properties of previously registered fixed resources
+can be set with the <function>xf86SetOperatingState()</function> function:
+	  <blockquote><para>
+	      <programlisting>
+    resPtr xf86SetOperatingState(resList list, int entityIndex,
+                                 int mask);
+	      </programlisting>
+	      <blockquote><para>
+      This function is used to set the status of a resource during
+      OPERATING state.  <parameter>list</parameter> holds a list to which
+      <parameter>mask</parameter> is to be applied.  The parameter
+      <parameter>mask</parameter> may have the value <constant>ResUnusedOpr</constant>
+      and <constant>ResDisableOpr</constant>.  The first one should be used
+      if a resource isn't used by the driver during OPERATING state
+      although it is decoded by the device, while the latter one indicates
+      that the resource is not decoded during OPERATING state.  Note
+      that the resource ranges have to match those specified during
+      registration.  If a range has been specified starting at
+      <literal remap="tt">A</literal> and ending at <literal remap="tt">B</literal> and suppose
+      <literal remap="tt">C</literal> us a value satisfying
+      <literal remap="tt">A&nbsp;&lt;&nbsp;C&nbsp;&lt;&nbsp;B</literal> one may not
+      specify the resource range <literal remap="tt">(A,B)</literal> by splitting it
+      into two ranges <literal remap="tt">(A,C)</literal> and <literal remap="tt">(C,B)</literal>.
+		</para>
+
+	      </blockquote></para></blockquote>
+	</para>
+
+	<para>
+The following two functions are provided for special cases:
+	  <blockquote><para>
+	      <programlisting>
+    void xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex);
+	      </programlisting>
+	      <blockquote><para>
+      This function may be used to remove an entity from a screen.  This
+      only makes sense if a screen has more than one entity assigned or
+      the screen is to be deleted.  No test is made if the screen has
+      any entities left.
+		</para>
+
+	      </blockquote></para></blockquote>
+
+	  <blockquote><para>
+	      <programlisting>
+    void xf86DeallocateResourcesForEntity(int entityIndex, long type);
+	      </programlisting>
+	      <blockquote><para>
+      This function deallocates all resources of a given type registered
+      for a certain entity from the resource broker list.
+		</para>
+
+	      </blockquote></para></blockquote>
+	</para>
+
+      </sect3>
+
+      <sect3>
+	<title>ScreenInit Phase</title>
+
+	<para>
+All that is required in this phase is to setup the RAC flags.  Note that
+it is also permissible to set these flags up in the PreInit phase.  The
+RAC flags are held in the <structfield>racIoFlags</structfield> and <structfield>racMemFlags</structfield> fields of the
+<structname>ScrnInfoRec</structname> for each screen.  They specify which graphics operations
+might require the use of shared resources.  This can be specified
+separately for memory and I/O resources.  The available flags are defined
+in <filename>rac/xf86RAC.h</filename>.  They are:
+
+	  <variablelist>
+	    <varlistentry><term><constant>RAC_FB</constant></term>
+	      <listitem><para>
+	for framebuffer operations (including hw acceleration)
+		</para></listitem></varlistentry>
+	    <varlistentry><term><constant>RAC_CURSOR</constant></term>
+	      <listitem><para>
+	for Cursor operations
+        (??? I'm not sure if we need this for SW cursor it depends
+         on which level the sw cursor is drawn)
+		</para></listitem></varlistentry>
+	    <varlistentry><term><constant>RAC_COLORMAP</constant></term>
+	      <listitem><para>
+	for colormap operations
+		</para></listitem></varlistentry>
+	    <varlistentry><term><constant>RAC_VIEWPORT</constant></term>
+	      <listitem><para>
+	for the call to <function>ChipAdjustFrame()</function>
+		</para></listitem></varlistentry>
+	    </variablelist>
+
+
+The flags are ORed together.
+	</para>
+      </sect3>
+    </sect2>
+  </sect1>
+
+  <sect1 id="options">
+    <title>Config file ``Option'' entries</title>
+
+    <para>
+Option entries are permitted in most sections and subsections of the
+config file.  There are two forms of option entries:
+
+      <variablelist>
+	<varlistentry><term>Option "option-name"</term>
+	  <listitem><para>
+	A boolean option.
+	    </para></listitem></varlistentry>
+	<varlistentry><term>Option "option-name" "option-value"</term>
+	  <listitem><para>
+	An option with an arbitrary value.
+	    </para></listitem></varlistentry>
+      </variablelist>
+    </para>
+
+    <para>
+The option entries are handled by the parser, and a list of the parsed
+options is included with each of the appropriate data structures that
+the drivers have access to.  The data structures used to hold the option
+information are opaque to the driver, and a driver must not access the
+option data directly.  Instead, the common layer provides a set of
+functions that may be used to access, check and manipulate the option
+data.
+    </para>
+
+    <para>
+First, the low level option handling functions.  In most cases drivers
+would not need to use these directly.
+    </para>
+
+    <blockquote><para>
+	<programlisting>
+    pointer xf86FindOption(pointer options, const char *name);
+	</programlisting>
+	<blockquote><para>
+      Takes a list of options and an option name, and returns a handle
+      for the first option entry in the list matching the name.  Returns
+      <constant>NULL</constant> if no match is found.
+	  </para>
+
+	</blockquote></para></blockquote>
+
+    <blockquote><para>
+	<programlisting>
+    char *xf86FindOptionValue(pointer options, const char *name);
+	</programlisting>
+	<blockquote><para>
+      Takes a list of options and an option name, and returns the value
+      associated with the first option entry in the list matching the
+      name.  If the matching option has no value, an empty string
+      (<constant>""</constant>) is returned.  Returns <constant>NULL</constant>
+      if no match is found.
+	  </para>
+
+	</blockquote></para></blockquote>
+
+    <blockquote><para>
+	<programlisting>
+    void xf86MarkOptionUsed(pointer option);
+	</programlisting>
+	<blockquote><para>
+      Takes a handle for an option, and marks that option as used.
+	  </para>
+
+	</blockquote></para></blockquote>
+
+    <blockquote><para>
+	<programlisting>
+    void xf86MarkOptionUsedByName(pointer options, const char *name);
+	</programlisting>
+	<blockquote><para>
+      Takes a list of options and an option name and marks the first
+      option entry in the list matching the name as used.
+	  </para>
+
+	</blockquote></para></blockquote>
+
+    <para>
+Next, the higher level functions that most drivers would use.
+    </para>
+    <blockquote><para>
+	<programlisting>
+    void xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts);
+	</programlisting>
+	<blockquote><para>
+      Collect the options from each of the config file sections used by
+      the screen (<parameter>pScrn</parameter>) and return the merged list as
+      <structfield>pScrn-&gt;options</structfield>.  This function requires that
+      <structfield>pScrn-&gt;confScreen</structfield>, <structfield>pScrn-&gt;display</structfield>,
+      <structfield>pScrn-&gt;monitor</structfield>,
+      <structfield>pScrn-&gt;numEntities</structfield>, and
+      <structfield>pScrn-&gt;entityList</structfield> are initialised.
+      <parameter>extraOpts</parameter> may optionally be set to an additional
+      list of options to be combined with the others.  The order of
+      precedence for options is <parameter>extraOpts</parameter>, display,
+      confScreen, monitor, device.
+	  </para>
+
+	</blockquote></para></blockquote>
+
+    <blockquote><para>
+	<programlisting>
+    void xf86ProcessOptions(int scrnIndex, pointer options,
+                            OptionInfoPtr optinfo);
+	</programlisting>
+	<blockquote><para>
+      Processes a list of options according to the information in the
+      array of <structname>OptionInfoRecs</structname> (<parameter>optinfo</parameter>).
+      The resulting information is stored in the <structfield>value</structfield>
+      fields of the appropriate <parameter>optinfo</parameter> entries.  The
+      <structfield>found</structfield> fields are set to <constant>TRUE</constant>
+      when an option with a value of the correct type if found, and
+      <constant>FALSE</constant> otherwise.  The <structfield>type</structfield> field
+      is used to determine the expected value type for each option.
+      Each option in the list of options for which there is a name match
+      (but not necessarily a value type match) is marked as used.
+      Warning messages are printed when option values don't match the
+      types specified in the optinfo data.
+	  </para>
+
+	  <para>
+      NOTE: If this function is called before a driver's screen number
+      is known (e.g., from the <function>ChipProbe()</function> function) a
+      <parameter>scrnIndex</parameter> value of <constant>-1</constant> should be
+      used.
+	  </para>
+
+	  <para>
+      NOTE 2: Given that this function stores into the
+      <literal remap="tt">OptionInfoRecs</literal> pointed to by <parameter>optinfo</parameter>,
+      the caller should ensure the <literal remap="tt">OptionInfoRecs</literal> are
+      (re-)initialised before the call, especially if the caller expects
+      to use the predefined option values as defaults.
+	  </para>
+
+	  <para>
+      The <structname>OptionInfoRec</structname> is defined as follows:
+
+	    <programlisting>
+      typedef struct {
+          double freq;
+          int units;
+      } OptFrequency;
+
+      typedef union {
+          unsigned long       num;
+          char *              str;
+          double              realnum;
+          Bool                bool;
+          OptFrequency        freq;
+      } ValueUnion;
+
+      typedef enum {
+          OPTV_NONE = 0,
+          OPTV_INTEGER,
+          OPTV_STRING,  /* a non-empty string */
+          OPTV_ANYSTR,  /* Any string, including an empty one */
+          OPTV_REAL,
+          OPTV_BOOLEAN,
+          OPTV_PERCENT,
+          OPTV_FREQ
+      } OptionValueType;
+
+      typedef enum {
+          OPTUNITS_HZ = 1,
+          OPTUNITS_KHZ,
+          OPTUNITS_MHZ
+      } OptFreqUnits;
+
+      typedef struct {
+          int                 token;
+          const char*         name;
+          OptionValueType     type;
+          ValueUnion          value;
+          Bool                found;
+      } OptionInfoRec, *OptionInfoPtr;
+	    </programlisting>
+	  </para>
+	  <para>
+      <constant>OPTV_FREQ</constant> can be used for options values that are
+      frequencies.  These values are a floating point number with an
+      optional unit name appended.  The unit name can be one of "Hz",
+      "kHz", "k", "MHz", "M".  The multiplier associated with the unit
+      is stored in <structfield>freq.units</structfield>, and the scaled frequency
+      is stored in <structfield>freq.freq</structfield>.  When no unit is specified,
+      <structfield>freq.units</structfield> is set to <constant>0</constant>, and
+      <structfield>freq.freq</structfield> is unscaled.
+	  </para>
+
+	  <para>
+      <constant>OPTV_PERCENT</constant> can be used for option values that are
+      specified in percent (e.g. "20%"). These values are a floating point
+      number with a percent sign appended. If the percent sign is missing,
+      the parser will fail to match the value.
+	  </para>
+
+	  <para>
+      Typical usage is to setup an array of
+      <structname>OptionInfoRec</structname>s with all fields initialised.
+      The <structfield>value</structfield> and <structfield>found</structfield> fields get
+      set by <function>xf86ProcessOptions()</function>.  For cases where the
+      value parsing is more complex, the driver should specify
+      <constant>OPTV_STRING</constant>, and parse the string itself.  An
+      example of using this option handling is included in the
+      <link linkend="sample">Sample Driver</link> section.
+	  </para>
+
+	</blockquote></para></blockquote>
+
+    <blockquote><para>
+	<programlisting>
+    void xf86ShowUnusedOptions(int scrnIndex, pointer options);
+	</programlisting>
+	<blockquote><para>
+      Prints out warning messages for each option in the list of options
+      that isn't marked as used.  This is intended to show options that
+      the driver hasn't recognised.  It would normally be called near
+      the end of the <function>ChipScreenInit()</function> function, but only
+      when <code>serverGeneration&nbsp;==&nbsp;1</code>
+	  </para>
+	</blockquote></para></blockquote>
+
+    <blockquote><para>
+	<programlisting>
+    OptionInfoPtr xf86TokenToOptinfo(const OptionInfoRec *table,
+                                     int token);
+	</programlisting>
+	<blockquote><para>
+      Returns a pointer to the <structname>OptionInfoRec</structname> in
+      <parameter>table</parameter> with a token field matching
+      <parameter>token</parameter>.  Returns <constant>NULL</constant> if no match
+      is found.
+	  </para>
+
+	</blockquote></para></blockquote>
+
+    <blockquote><para>
+	<programlisting>
+    Bool xf86IsOptionSet(const OptionInfoRec *table, int token);
+	</programlisting>
+	<blockquote><para>
+      Returns the <literal remap="tt">found</literal> field of the
+      <structname>OptionInfoRec</structname> in <parameter>table</parameter> with a
+      <structfield>token</structfield> field matching <parameter>token</parameter>.  This
+      can be used for options of all types.  Note that for options of
+      type <constant>OPTV_BOOLEAN</constant>, it isn't sufficient to check
+      this to determine the value of the option.  Returns
+      <constant>FALSE</constant> if no match is found.
+	  </para>
+
+	</blockquote></para></blockquote>
+
+    <blockquote><para>
+	<programlisting>
+    char *xf86GetOptValString(const OptionInfoRec *table, int token);
+	</programlisting>
+	<blockquote><para>
+      Returns the <structfield>value.str</structfield> field of the
+      <structname>OptionInfoRec</structname> in <parameter>table</parameter> with a
+      token field matching <parameter>token</parameter>.  Returns
+      <constant>NULL</constant> if no match is found.
+	  </para>
+
+	</blockquote></para></blockquote>
+
+	  <blockquote><para>
+	      <programlisting>
+    Bool xf86GetOptValInteger(const OptionInfoRec *table, int token,
+
+                                int *value);
+	      </programlisting>
+	      <blockquote><para>
+      Returns via <parameter>*value</parameter> the <structfield>value.num</structfield>
+      field of the <structname>OptionInfoRec</structname> in <parameter>table</parameter>
+      with a <structfield>token</structfield> field matching <parameter>token</parameter>.
+      <parameter>*value</parameter> is only changed when a match is found so
+      it can be safely initialised with a default prior to calling this
+      function.  The function return value is as for
+      <function>xf86IsOptionSet()</function>.
+	  </para>
+
+	</blockquote></para></blockquote>
+
+    <blockquote><para>
+	<programlisting>
+    Bool xf86GetOptValULong(const OptionInfoRec *table, int token,
+                            unsigned long *value);
+	</programlisting>
+	<blockquote><para>
+      Like <function>xf86GetOptValInteger()</function>, except the value is
+      treated as an <type>unsigned long</type>.
+	  </para>
+
+	</blockquote></para></blockquote>
+
+    <blockquote><para>
+	<programlisting>
+    Bool xf86GetOptValReal(const OptionInfoRec *table, int token,
+                           double *value);
+	</programlisting>
+	<blockquote><para>
+      Like <function>xf86GetOptValInteger()</function>, except that
+      <structfield>value.realnum</structfield> is used.
+	  </para>
+
+	</blockquote></para></blockquote>
+
+    <blockquote><para>
+	<programlisting>
+    Bool xf86GetOptValFreq(const OptionInfoRec *table, int token,
+                           OptFreqUnits expectedUnits, double *value);
+	</programlisting>
+	<blockquote><para>
+      Like <function>xf86GetOptValInteger()</function>, except that the
+      <structfield>value.freq</structfield> data is returned.  The frequency value
+      is scaled to the units indicated by <parameter>expectedUnits</parameter>.
+      The scaling is exact when the units were specified explicitly in
+      the option's value.  Otherwise, the <parameter>expectedUnits</parameter>
+      field is used as a hint when doing the scaling.  In this case,
+      values larger than <constant>1000</constant> are assumed to have be
+      specified in the next smallest units.  For example, if the Option
+      value is "10000" and expectedUnits is <constant>OPTUNITS_MHZ</constant>,
+      the value returned is <constant>10</constant>.
+	  </para>
+
+	</blockquote></para></blockquote>
+
+    <blockquote><para>
+      <programlisting>
+    Bool xf86GetOptValBool(const OptionInfoRec *table, int token, Bool *value);
+      </programlisting>
+	<blockquote><para>
+      This function is used to check boolean options
+      (<constant>OPTV_BOOLEAN</constant>).  If the function return value is
+      <constant>FALSE</constant>, it means the option wasn't set.  Otherwise
+      <parameter>*value</parameter> is set to the boolean value indicated by
+      the option's value.  No option <parameter>value</parameter> is interpreted
+      as <constant>TRUE</constant>.  Option values meaning <constant>TRUE</constant>
+      are "1", "yes", "on", "true", and option values meaning
+      <constant>FALSE</constant> are "0", "no", "off", "false".  Option names
+      both with the "no" prefix in their names, and with that prefix
+      removed are also checked and handled in the obvious way.
+      <parameter>*value</parameter> is not changed when the option isn't present.
+      It should normally be set to a default value before calling this
+      function.
+	  </para>
+
+	</blockquote></para></blockquote>
+
+    <blockquote><para>
+	<programlisting>
+    Bool xf86ReturnOptValBool(const OptionInfoRec *table, int token, Bool def);
+	</programlisting>
+	<blockquote><para>
+      This function is used to check boolean options
+      (<constant>OPTV_BOOLEAN</constant>).  If the option is set, its value
+      is returned.  If the options is not set, the default value specified
+      by <parameter>def</parameter> is returned.  The option interpretation is
+      the same as for <function>xf86GetOptValBool()</function>.
+	  </para>
+
+	</blockquote></para></blockquote>
+
+    <blockquote><para>
+	<programlisting>
+    int xf86NameCmp(const char *s1, const char *s2);
+	</programlisting>
+	<blockquote><para>
+      This function should be used when comparing strings from the config
+      file with expected values.  It works like <function>strcmp()</function>,
+      but is not case sensitive and space, tab, and `<literal>_</literal>' characters
+      are ignored in the comparison.  The use of this function isn't
+      restricted to parsing option values.  It may be used anywhere
+      where this functionality required.
+	  </para>
+
+	</blockquote></para></blockquote>
+  </sect1>
+
+  <sect1>
+    <title>Modules, Drivers, Include Files and Interface Issues</title>
+
+    <para>
+NOTE: this section is incomplete.
+    </para>
+
+
+    <sect2>
+      <title>Include files</title>
+
+      <para>
+The following include files are typically required by video drivers:
+
+	<blockquote><para>
+  All drivers should include these:
+	    <literallayout><filename>
+    "xf86.h"
+    "xf86_OSproc.h"
+    "xf86_ansic.h"
+    "xf86Resources.h"
+	    </filename></literallayout>
+  Wherever inb/outb (and related things) are used the following should be
+  included:
+	    <literallayout><filename>
+    "compiler.h"
+	      </filename></literallayout>
+  Note: in drivers, this must be included after <filename>"xf86_ansic.h"</filename>.
+	  </para>
+
+	  <para>
+  Drivers that need to access PCI vendor/device definitions need this:
+	    <literallayout><filename>
+    "xf86PciInfo.h"
+	      </filename></literallayout>
+	  </para>
+
+	  <para>
+  Drivers that need to access the PCI config space need this:
+	    <literallayout><filename>
+    "xf86Pci.h"
+	      </filename></literallayout>
+	  </para>
+
+	  <para>
+  Drivers that initialise a SW cursor need this:
+	    <literallayout><filename>
+    "mipointer.h"
+	      </filename></literallayout>
+	  </para>
+
+	  <para>
+  All drivers implementing backing store need this:
+	    <literallayout><filename>
+    "mibstore.h"
+	      </filename></literallayout>
+	  </para>
+
+	  <para>
+  All drivers using the mi colourmap code need this:
+	    <literallayout><filename>
+    "micmap.h"
+	      </filename></literallayout>
+	  </para>
+
+	  <para>
+  If a driver uses the vgahw module, it needs this:
+	    <literallayout><filename>
+    "vgaHW.h"
+	      </filename></literallayout>
+	  </para>
+
+	  <para>
+  Drivers supporting VGA or Hercules monochrome screens need:
+	    <literallayout><filename>
+    "xf1bpp.h"
+	      </filename></literallayout>
+	  </para>
+
+	  <para>
+  Drivers supporting VGA or EGC 16-colour screens need:
+	    <literallayout><filename>
+    "xf4bpp.h"
+	      </filename></literallayout>
+	  </para>
+
+	  <para>
+  Drivers using cfb need:
+	    <programlisting>
+    #define PSZ 8
+    #include "cfb.h"
+    #undef PSZ
+	    </programlisting>
+	  </para>
+
+	  <para>
+  Drivers supporting bpp 16, 24 or 32 with cfb need one or more of:
+	    <literallayout><filename>
+    "cfb16.h"
+    "cfb24.h"
+    "cfb32.h"
+	      </filename></literallayout>
+	  </para>
+
+	  <para>
+  If a driver uses XAA, it needs these:
+	    <literallayout><filename>
+    "xaa.h"
+    "xaalocal.h"
+	      </filename></literallayout>
+	  </para>
+
+	  <para>
+  If a driver uses the fb manager, it needs this:
+	    <literallayout><filename>
+    "xf86fbman.h"
+	      </filename></literallayout>
+	  </para>
+	</blockquote>
+      </para>
+
+      <para>
+Non-driver modules should include <filename>"xf86_ansic.h"</filename> to get the correct
+wrapping of ANSI C/libc functions.
+      </para>
+
+      <para>
+All modules must NOT include any system include files, or the following:
+
+	<literallayout><filename>
+    "xf86Priv.h"
+    "xf86Privstr.h"
+    "xf86_OSlib.h"
+    "Xos.h"
+	  </filename></literallayout>
+      </para>
+
+      <para>
+In addition, "xf86_libc.h" must not be included explicitly.  It is
+included implicitly by "xf86_ansic.h".
+      </para>
+
+    </sect2>
+  </sect1>
+
+  <sect1>
+    <title>Offscreen Memory Manager</title>
+
+    <para>
+Management of offscreen video memory may be handled by the XFree86
+framebuffer manager.  Once the offscreen memory manager is running,
+drivers or extensions may allocate, free or resize areas of offscreen
+video memory using the following functions (definitions taken from
+<filename>xf86fbman.h</filename>):
+
+      <programlisting>
+    typedef struct _FBArea {
+        ScreenPtr    pScreen;
+        BoxRec       box;
+        int          granularity;
+        void         (*MoveAreaCallback)(struct _FBArea*, struct _FBArea*)
+        void         (*RemoveAreaCallback)(struct _FBArea*)
+        DevUnion     devPrivate;
+    } FBArea, *FBAreaPtr;
+
+    typedef void (*MoveAreaCallbackProcPtr)(FBAreaPtr from, FBAreaPtr to)
+    typedef void (*RemoveAreaCallbackProcPtr)(FBAreaPtr)
+
+    FBAreaPtr xf86AllocateOffscreenArea (
+        ScreenPtr pScreen,
+        int width, int height,
+        int granularity,
+        MoveAreaCallbackProcPtr MoveAreaCallback,
+        RemoveAreaCallbackProcPtr RemoveAreaCallback,
+        pointer privData
+    )
+
+    void xf86FreeOffscreenArea (FBAreaPtr area)
+
+    Bool xf86ResizeOffscreenArea (
+	FBAreaPtr area
+	int w, int h
+    )
+      </programlisting>
+    </para>
+
+    <para>
+The function:
+      <programlisting>
+    Bool xf86FBManagerRunning(ScreenPtr pScreen);
+      </programlisting>
+
+can be used by an extension to check if the driver has initialized
+the memory manager.  The manager is not available if this returns
+<constant>FALSE</constant> and the functions above will all fail.
+    </para>
+
+
+    <para>
+<function>xf86AllocateOffscreenArea()</function> can be used to request a
+rectangle of dimensions <parameter>width</parameter>&nbsp;&times;&nbsp;<parameter>height</parameter>
+(in pixels) from unused offscreen memory.  <parameter>granularity</parameter>
+specifies that the leftmost edge of the rectangle must lie on some
+multiple of <parameter>granularity</parameter> pixels.  A granularity of zero
+means the same thing as a granularity of one - no alignment preference.
+A <parameter>MoveAreaCallback</parameter> can be provided to notify the requester
+when the offscreen area is moved.  If no <parameter>MoveAreaCallback</parameter>
+is supplied then the area is considered to be immovable.  The
+<parameter>privData</parameter> field will be stored in the manager's internal
+structure for that allocated area and will be returned to the requester
+in the <parameter>FBArea</parameter> passed via the
+<parameter>MoveAreaCallback</parameter>.  An optional
+<parameter>RemoveAreaCallback</parameter> is provided.  If the driver provides
+this it indicates that the area should be allocated with a lower priority.
+Such an area may be removed when a higher priority request (one that
+doesn't have a <parameter>RemoveAreaCallback</parameter>) is made.  When this
+function is called, the driver will have an opportunity to do whatever
+cleanup it needs to do to deal with the loss of the area, but it must
+finish its cleanup before the function exits since the offscreen memory
+manager will free the area immediately after.
+    </para>
+
+    <para>
+<function>xf86AllocateOffscreenArea()</function> returns <constant>NULL</constant>
+if it was unable to allocate the requested area.  When no longer needed,
+areas should be freed with <function>xf86FreeOffscreenArea()</function>.
+    </para>
+
+    <para>
+<function>xf86ResizeOffscreenArea()</function> resizes an existing
+<literal remap="tt">FBArea</literal>.  <function>xf86ResizeOffscreenArea()</function>
+returns <constant>TRUE</constant> if the resize was successful.  If
+<function>xf86ResizeOffscreenArea()</function> returns <constant>FALSE</constant>,
+the original <literal remap="tt">FBArea</literal> is left unmodified.  Resizing an
+area maintains the area's original <literal remap="tt">granularity</literal>,
+<literal remap="tt">devPrivate</literal>, and <literal remap="tt">MoveAreaCallback</literal>.
+<function>xf86ResizeOffscreenArea()</function> has considerably less overhead
+than freeing the old area then reallocating the new size, so it should
+be used whenever possible.
+    </para>
+
+    <para>
+The function:
+      <programlisting>
+    Bool xf86QueryLargestOffscreenArea(
+      ScreenPtr pScreen,
+      int *width, int *height,
+      int granularity,
+      int preferences,
+      int priority
+    );
+	</programlisting>
+
+is provided to query the width and height of the largest single
+<structname>FBArea</structname> allocatable given a particular priority.
+<parameter>preferences</parameter> can be one of the following to indicate
+whether width, height or area should be considered when determining
+which is the largest single <structname>FBArea</structname> available.
+
+      <programlisting>
+  FAVOR_AREA_THEN_WIDTH
+  FAVOR_AREA_THEN_HEIGHT
+  FAVOR_WIDTH_THEN_AREA
+  FAVOR_HEIGHT_THEN_AREA
+      </programlisting>
+    </para>
+
+    <para>
+<parameter>priority</parameter> is one of the following:
+
+      <blockquote>
+	<para>
+  <constant>PRIORITY_LOW</constant>
+	  <blockquote><para>
+     Return the largest block available without stealing anyone else's
+     space.  This corresponds to the priority of allocating a
+     <structname>FBArea</structname> when a <function>RemoveAreaCallback</function>
+     is provided.
+	    </para></blockquote>
+	</para>
+
+	<para>
+   <constant>PRIORITY_NORMAL</constant>
+	  <blockquote><para>
+     Return the largest block available if it is acceptable to steal a
+     lower priority area from someone.  This corresponds to the priority
+     of allocating a <structname>FBArea</structname> without providing a
+     <function>RemoveAreaCallback</function>.
+	    </para></blockquote>
+	</para>
+
+	<para>
+    <constant>PRIORITY_EXTREME</constant>
+	  <blockquote><para>
+     Return the largest block available if all <structname>FBArea</structname>s
+     that aren't locked down were expunged from memory first.  This
+     corresponds to any allocation made directly after a call to
+     <function>xf86PurgeUnlockedOffscreenAreas()</function>.
+	    </para></blockquote>
+	</para>
+
+      </blockquote>
+    </para>
+
+
+    <para>
+The function:
+
+      <programlisting>
+    Bool xf86PurgeUnlockedOffscreenAreas(ScreenPtr pScreen);
+      </programlisting>
+
+is provided as an extreme method to free up offscreen memory.  This
+will remove all removable <structname>FBArea</structname> allocations.
+    </para>
+
+
+    <para>
+Initialization of the XFree86 framebuffer manager is done via
+
+      <programlisting>
+    Bool xf86InitFBManager(ScreenPtr pScreen, BoxPtr FullBox);
+      </programlisting>
+
+<parameter>FullBox</parameter> represents the area of the framebuffer that the
+manager is allowed to manage.  This is typically a box with a width of
+<structfield>pScrn-&gt;displayWidth</structfield> and a height of as many lines as
+can be fit within the total video memory, however, the driver can reserve
+areas at the extremities by passing a smaller area to the manager.
+    </para>
+
+    <para>
+<function>xf86InitFBManager()</function> must be called before XAA is
+initialized since XAA uses the manager for it's pixmap cache.
+    </para>
+
+    <para>
+An alternative function is provided to allow the driver to initialize
+the framebuffer manager with a Region rather than a box.
+
+    <programlisting>
+    Bool xf86InitFBManagerRegion(ScreenPtr pScreen,
+                                 RegionPtr FullRegion);
+    </programlisting>
+
+<function>xf86InitFBManagerRegion()</function>, unlike
+<function>xf86InitFBManager()</function>, does not remove the area used for
+the visible screen so that area should not be included in the region
+passed to the function.  <function>xf86InitFBManagerRegion()</function> is
+useful when non-contiguous areas are available to be managed, and is
+required when multiple framebuffers are stored in video memory (as in
+the case where an overlay of a different depth is stored as a second
+framebuffer in offscreen memory).
+    </para>
+
+  </sect1>
+
+  <sect1 id="cmap">
+    <title>Colormap Handling</title>
+
+    <para>
+A generic colormap handling layer is provided within the XFree86 common
+layer.  This layer takes care of most of the details, and only requires
+a function from the driver that loads the hardware palette when required.
+To use the colormap layer, a driver calls the
+<function>xf86HandleColormaps()</function> function.
+
+      <blockquote><para>
+	  <programlisting>
+    Bool xf86HandleColormaps(ScreenPtr pScreen, int maxColors,
+                             int sigRGBbits, LoadPaletteFuncPtr loadPalette,
+                             SetOverscanFuncPtr setOverscan,
+                             unsigned int flags);
+	  </programlisting>
+	  <blockquote><para>
+      This function must be called after the default colormap has been
+      initialised.  The <structfield>pScrn-&gt;gamma</structfield> field must also
+      be initialised, preferably by calling <function>xf86SetGamma()</function>.
+      <parameter>maxColors</parameter> is the number of entries in the palette.
+      <parameter>sigRGBbits</parameter> is the size in bits of each color
+      component in the DAC's palette.  <parameter>loadPalette</parameter>
+      is a driver-provided function for loading a colormap into the
+      hardware, and is described below.  <parameter>setOverscan</parameter> is
+      an optional function that may be provided when the overscan color
+      is an index from the standard LUT and when it needs to be adjusted
+      to keep it as close to black as possible.  The
+      <parameter>setOverscan</parameter> function programs the overscan index.
+      It shouldn't normally be used for depths other than 8.
+      <parameter>setOverscan</parameter> should be set to <constant>NULL</constant>
+      when it isn't needed.  <parameter>flags</parameter> may be set to the
+      following (which may be ORed together):
+
+	      <variablelist>
+		<varlistentry>
+		  <term><constant>CMAP_PALETTED_TRUECOLOR</constant></term>
+		  <listitem><para>
+				    the TrueColor visual is paletted and is
+				    just a special case of DirectColor.
+				    This flag is only valid for
+				    <code>bpp&nbsp;&gt;&nbsp;8</code>.
+
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><constant>CMAP_RELOAD_ON_MODE_SWITCH</constant></term>
+		  <listitem><para>
+				    reload the colormap automatically
+                                    after mode switches.  This is useful
+                                    for when the driver is resetting the
+                                    hardware during mode switches and
+                                    corrupting or erasing the hardware
+                                    palette.
+
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><constant>CMAP_LOAD_EVEN_IF_OFFSCREEN</constant></term>
+		  <listitem><para>
+				    reload the colormap even if the screen
+				    is switched out of the server's VC.
+				    The palette is <emphasis>not</emphasis> reloaded when
+				    the screen is switched back in, nor after
+				    mode switches.  This is useful when the
+				    driver needs to keep track of palette
+				    changes.
+
+		    </para></listitem></varlistentry>
+	      </variablelist>
+	    </para>
+
+	    <para>
+      The colormap layer normally reloads the palette after VT enters so it
+      is not necessary for the driver to save and restore the palette
+      when switching VTs.  The driver must, however, still save the
+      initial palette during server start up and restore it during
+      server exit.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
+                     LOCO *colors, VisualPtr pVisual);
+	  </programlisting>
+	  <blockquote><para>
+      <function>LoadPalette()</function> is a driver-provided function for
+      loading a colormap into hardware.  <parameter>colors</parameter> is the
+      array of RGB values that represent the full colormap.
+      <parameter>indices</parameter> is a list of index values into the colors
+      array.  These indices indicate the entries that need to be updated.
+      <parameter>numColors</parameter> is the number of the indices to be
+      updated.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void SetOverscan(ScrnInfoPtr pScrn, int overscan);
+	  </programlisting>
+	  <blockquote><para>
+      <function>SetOverscan()</function> is a driver-provided function for
+      programming the <parameter>overscan</parameter> index.  As described
+      above, it is normally only appropriate for LUT modes where all
+      colormap entries are available for the display, but where one of
+      them is also used for the overscan (typically 8bpp for VGA compatible
+      LUTs).  It isn't required in cases where the overscan area is
+      never visible.
+	    </para>
+
+	  </blockquote></para>
+      </blockquote></para>
+
+  </sect1>
+
+  <sect1>
+    <title>DPMS Extension</title>
+
+    <para>
+Support code for the DPMS extension is included in the XFree86 common layer.
+This code provides an interface between the main extension code, and a means
+for drivers to initialise DPMS when they support it.  One function is
+available to drivers to do this initialisation, and it is always available,
+even when the DPMS extension is not supported by the core server (in
+which case it returns a failure result).
+    </para>
+
+    <blockquote><para>
+	<programlisting>
+    Bool xf86DPMSInit(ScreenPtr pScreen, DPMSSetProcPtr set, int flags);
+	</programlisting>
+	<blockquote><para>
+      This function registers a driver's DPMS level programming function
+      <parameter>set</parameter>.  It also checks
+      <structfield>pScrn-&gt;options</structfield> for the "dpms" option, and when
+      present marks DPMS as being enabled for that screen.  The
+      <parameter>set</parameter> function is called whenever the DPMS level
+      changes, and is used to program the requested level.
+      <parameter>flags</parameter> is currently not used, and should be
+      <constant>0</constant>.  If the initialisation fails for any reason,
+      including when there is no DPMS support in the core server, the
+      function returns <constant>FALSE</constant>.
+	  </para>
+
+	</blockquote></para></blockquote>
+
+
+    <para>
+Drivers that implement DPMS support must provide the following function,
+that gets called when the DPMS level is changed:
+
+
+      <blockquote><para>
+	  <programlisting>
+    void ChipDPMSSet(ScrnInfoPtr pScrn, int level, int flags);
+	  </programlisting>
+	  <blockquote><para>
+      Program the DPMS level specified by <parameter>level</parameter>.  Valid
+      values of <parameter>level</parameter> are <constant>DPMSModeOn</constant>,
+      <constant>DPMSModeStandby</constant>, <constant>DPMSModeSuspend</constant>,
+      <constant>DPMSModeOff</constant>.  These values are defined in
+      <filename>"extensions/dpms.h"</filename>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+    </para>
+
+  </sect1>
+
+  <sect1>
+    <title>DGA Extension</title>
+
+    <para>
+Drivers can support the XFree86 Direct Graphics Architecture (DGA) by
+filling out a structure of function pointers and a list of modes and
+passing them to DGAInit.
+    </para>
+
+    <blockquote><para>
+	<programlisting>
+    Bool DGAInit(ScreenPtr pScreen, DGAFunctionPtr funcs,
+                 DGAModePtr modes, int num);
+
+/** The DGAModeRec **/
+
+typedef struct {
+  int num;
+  DisplayModePtr mode;
+  int flags;
+  int imageWidth;
+  int imageHeight;
+  int pixmapWidth;
+  int pixmapHeight;
+  int bytesPerScanline;
+  int byteOrder;
+  int depth;
+  int bitsPerPixel;
+  unsigned long red_mask;
+  unsigned long green_mask;
+  unsigned long blue_mask;
+  int viewportWidth;
+  int viewportHeight;
+  int xViewportStep;
+  int yViewportStep;
+  int maxViewportX;
+  int maxViewportY;
+  int viewportFlags;
+  int offset;
+  unsigned char *address;
+  int reserved1;
+  int reserved2;
+} DGAModeRec, *DGAModePtr;
+	</programlisting>
+
+	<variablelist>
+	  <varlistentry>
+	    <term><structfield>num</structfield></term>
+	    <listitem><para>
+	 Can be ignored.  The DGA DDX will assign these numbers.
+	      </para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>mode</structfield></term>
+	    <listitem><para>
+	A pointer to the <structname>DisplayModeRec</structname> for this mode.
+	      </para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>flags</structfield></term>
+	      <listitem><para>
+	The following flags are defined and may be OR'd together:
+
+		  <variablelist>
+		    <varlistentry>
+		      <term><constant>DGA_CONCURRENT_ACCESS</constant></term>
+		      <listitem><para>
+            Indicates that the driver supports concurrent graphics
+            accelerator and linear framebuffer access.
+
+			</para></listitem></varlistentry>
+
+		    <varlistentry>
+		      <term><constant>DGA_FILL_RECT
+			  DGA_BLIT_RECT
+			  DGA_BLIT_RECT_TRANS</constant></term>
+		      <listitem><para>
+	    Indicates that the driver supports the FillRect, BlitRect
+            or BlitTransRect functions in this mode.
+
+			</para></listitem></varlistentry>
+
+		    <varlistentry>
+		      <term><constant>DGA_PIXMAP_AVAILABLE</constant></term>
+		      <listitem><para>
+	    Indicates that Xlib may be used on the framebuffer.
+            This flag will usually be set unless the driver wishes
+            to prohibit this for some reason.
+
+			</para></listitem></varlistentry>
+
+		    <varlistentry>
+		      <term><constant>DGA_INTERLACED
+			  DGA_DOUBLESCAN</constant></term>
+		      <listitem><para>
+            Indicates that these are interlaced or double scan modes.
+
+			</para></listitem></varlistentry>
+		  </variablelist>
+		</para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>imageWidth
+		imageHeight</structfield></term>
+	    <listitem><para>
+		    These are the dimensions of the linear framebuffer
+                     accessible by the client.
+
+	      </para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>pixmapWidth
+		pixmapHeight</structfield></term>
+	    <listitem><para>
+		     These are the dimensions of the area of the
+                     framebuffer accessible by the graphics accelerator.
+
+	      </para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>bytesPerScanline</structfield></term>
+	    <listitem><para>
+		      Pitch of the framebuffer in bytes.
+
+	      </para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>byteOrder</structfield></term>
+	    <listitem><para>
+		     Usually the same as
+		     <structfield>pScrn-&gt;imageByteOrder</structfield>.
+
+	      </para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>depth</structfield></term>
+	    <listitem><para>
+		     The depth of the framebuffer in this mode.
+
+	      </para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>bitsPerPixel</structfield></term>
+	    <listitem><para>
+		      The number of bits per pixel in this mode.
+
+	      </para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>red_mask</structfield></term>
+	    <term><structfield>green_mask</structfield></term>
+	    <term><structfield>blue_mask</structfield></term>
+	    <listitem><para>
+		      The RGB masks for this mode, if applicable.
+
+	      </para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>viewportWidth</structfield></term>
+	    <term><structfield>viewportHeight</structfield></term>
+	    <listitem><para>
+		      Dimensions of the visible part of the framebuffer.
+		      Usually <structfield>mode-&gt;HDisplay</structfield> and
+		      <structfield>mode-&gt;VDisplay</structfield>.
+
+	      </para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>xViewportStep
+		yViewportStep</structfield></term>
+	    <listitem><para>
+		     The granularity of x and y viewport positions that
+                     the driver supports in this mode.
+
+	      </para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>maxViewportX
+		maxViewportY</structfield></term>
+	    <listitem><para>
+		      The maximum viewport position supported by the
+                       driver in this mode.
+	      </para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>viewportFlags</structfield></term>
+	    <listitem><para>
+		     The following may be OR'd together:
+
+		<variablelist>
+		  <varlistentry>
+		    <term><constant>DGA_FLIP_IMMEDIATE</constant></term>
+		    <listitem><para>
+		The driver supports immediate viewport changes.
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><constant>DGA_FLIP_RETRACE</constant></term>
+
+		    <listitem><para>
+		The driver supports viewport changes at retrace.
+		      </para></listitem></varlistentry>
+		  </variablelist>
+	      </para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>offset</structfield></term>
+	    <listitem><para>
+	        The offset into the linear framebuffer that corresponds to
+                pixel (0,0) for this mode.
+	      </para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>address</structfield></term>
+	    <listitem><para>
+                The virtual address of the framebuffer as mapped by the driver.
+                This is needed when DGA_PIXMAP_AVAILABLE is set.
+	      </para></listitem></varlistentry>
+
+	</variablelist>
+
+	<programlisting>
+/** The DGAFunctionRec **/
+
+typedef struct {
+  Bool (*OpenFramebuffer)(
+       ScrnInfoPtr pScrn,
+       char **name,
+       unsigned char **mem,
+       int *size,
+       int *offset,
+       int *extra
+  );
+  void (*CloseFramebuffer)(ScrnInfoPtr pScrn);
+  Bool (*SetMode)(ScrnInfoPtr pScrn, DGAModePtr pMode);
+  void (*SetViewport)(ScrnInfoPtr pScrn, int x, int y, int flags);
+  int  (*GetViewport)(ScrnInfoPtr pScrn);
+  void (*Sync)(ScrnInfoPtr);
+  void (*FillRect)(
+       ScrnInfoPtr pScrn,
+       int x, int y, int w, int h,
+       unsigned long color
+  );
+  void (*BlitRect)(
+       ScrnInfoPtr pScrn,
+       int srcx, int srcy,
+       int w, int h,
+       int dstx, int dsty
+  );
+  void (*BlitTransRect)(
+       ScrnInfoPtr pScrn,
+       int srcx, int srcy,
+       int w, int h,
+       int dstx, int dsty,
+       unsigned long color
+  );
+} DGAFunctionRec, *DGAFunctionPtr;
+	</programlisting>
+
+
+	<blockquote><para>
+	    <programlisting>
+    Bool OpenFramebuffer (pScrn, name, mem, size, offset, extra);
+	    </programlisting>
+	    <blockquote><para>
+      <function>OpenFramebuffer()</function> should pass the client everything
+      it needs to know to be able to open the framebuffer.  These
+      parameters are OS specific and their meanings are to be interpreted
+      by an OS specific client library.
+
+		<variablelist>
+		  <varlistentry>
+		    <term><parameter>name</parameter></term>
+		    <listitem><para>
+	      The name of the device to open or <constant>NULL</constant> if
+	      there is no special device to open.  A <constant>NULL</constant>
+	      name tells the client that it should open whatever device
+	      one would usually open to access physical memory.
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><parameter>mem</parameter></term>
+		    <listitem><para>
+	      The physical address of the start of the framebuffer.
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><parameter>size</parameter></term>
+		    <listitem><para>
+	      The size of the framebuffer in bytes.
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><parameter>offset</parameter></term>
+		    <listitem><para>
+	      Any offset into the device, if applicable.
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><parameter>flags</parameter></term>
+		    <listitem><para>
+	      Any additional information that the client may need.
+	      Currently, only the <constant>DGA_NEED_ROOT</constant> flag is
+	      defined.
+		      </para></listitem></varlistentry>
+
+		</variablelist>
+	      </para></blockquote>
+	  </para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    void CloseFramebuffer (pScrn);
+	    </programlisting>
+	    <blockquote><para>
+      <function>CloseFramebuffer()</function> merely informs the driver (if it
+      even cares) that client no longer needs to access the framebuffer
+      directly.  This function is optional.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    Bool SetMode (pScrn, pMode);
+	    </programlisting>
+	    <blockquote><para>
+      <function>SetMode()</function> tells the driver to initialize the mode
+      passed to it.  If <parameter>pMode</parameter> is <constant>NULL</constant>,
+      then the driver should restore the original pre-DGA mode.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    void SetViewport (pScrn, x, y, flags);
+	    </programlisting>
+	    <blockquote><para>
+      <function>SetViewport()</function> tells the driver to make the upper
+      left-hand corner of the visible screen correspond to coordinate
+      <literal remap="tt">(x,y)</literal> on the framebuffer.  <parameter>flags</parameter>
+      currently defined are:
+
+		<variablelist>
+		  <varlistentry>
+		    <term><constant>DGA_FLIP_IMMEDIATE</constant></term>
+		    <listitem><para>
+	    The viewport change should occur immediately.
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><constant>DGA_FLIP_RETRACE</constant></term>
+		    <listitem><para>
+	    The viewport change should occur at the
+            vertical retrace, but this function should
+            return sooner if possible.
+			</para></listitem></varlistentry>
+		</variablelist>
+	      </para>
+
+	      <para>
+      The <literal remap="tt">(x,y)</literal> locations will be passed as the client
+      specified them, however, the driver is expected to round these
+      locations down to the next supported location as specified by the
+      <structfield>xViewportStep</structfield> and <structfield>yViewportStep</structfield>
+      for the current mode.
+	      </para>
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    int GetViewport (pScrn);
+	    </programlisting>
+	    <blockquote><para>
+      <function>GetViewport()</function> gets the current page flip status.
+      Set bits in the returned int correspond to viewport change requests
+      still pending.  For instance, set bit zero if the last SetViewport
+      request is still pending, bit one if the one before that is still
+      pending, etc.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    void Sync (pScrn);
+	    </programlisting>
+	    <blockquote><para>
+      This function should ensure that any graphics accelerator operations
+      have finished.  This function should not return until the graphics
+      accelerator is idle.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    void FillRect (pScrn, x, y, w, h, color);
+	    </programlisting>
+	    <blockquote><para>
+      This optional function should fill a rectangle
+      <parameter>w&nbsp;&times;&nbsp;h</parameter> located at
+      <parameter>(x,y)</parameter> in the given color.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    void BlitRect (pScrn, srcx, srcy, w, h, dstx, dsty);
+	    </programlisting>
+	    <blockquote><para>
+      This optional function should copy an area
+      <parameter>w&nbsp;&times;&nbsp;h</parameter> located at
+      <parameter>(srcx,srcy)</parameter> to location <parameter>(dstx,dsty)</parameter>.
+      This function will need to handle copy directions as appropriate.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    void BlitTransRect (pScrn, srcx, srcy, w, h, dstx, dsty, color);
+	    </programlisting>
+	    <blockquote><para>
+      This optional function is the same as BlitRect except that pixels
+      in the source corresponding to the color key <parameter>color</parameter>
+      should be skipped.
+	      </para>
+
+	    </blockquote></para></blockquote>
+    </para></blockquote>
+
+  </sect1>
+
+  <sect1>
+    <title>The XFree86 X Video Extension (Xv) Device Dependent Layer</title>
+
+    <para>
+XFree86 offers the X Video Extension which allows clients to treat video
+as any another primitive and ``Put'' video into drawables.  By default,
+the extension reports no video adaptors as being available since the
+DDX layer has not been initialized.  The driver can initialize the DDX
+layer by filling out one or more <literal remap="tt">XF86VideoAdaptorRecs</literal>
+as described later in this document and passing a list of
+<literal remap="tt">XF86VideoAdaptorPtr</literal> pointers to the following function:
+
+      <programlisting>
+    Bool xf86XVScreenInit(ScreenPtr pScreen,
+                          XF86VideoAdaptorPtr *adaptPtrs,
+                          int num);
+      </programlisting>
+    </para>
+
+    <para>
+After doing this, the extension will report video adaptors as being
+available, providing the data in their respective
+<literal remap="tt">XF86VideoAdaptorRecs</literal> was valid.
+<function>xf86XVScreenInit()</function> <emphasis>copies</emphasis> data from the structure
+passed to it so the driver may free it after the initialization.  At
+the moment, the DDX only supports rendering into Window drawables.
+Pixmap rendering will be supported after a sufficient survey of suitable
+hardware is completed.
+    </para>
+
+    <para>
+The <structname>XF86VideoAdaptorRec</structname>:
+
+      <programlisting>
+typedef struct {
+	unsigned int type;
+	int flags;
+	char *name;
+	int nEncodings;
+	XF86VideoEncodingPtr pEncodings;
+	int nFormats;
+	XF86VideoFormatPtr pFormats;
+	int nPorts;
+	DevUnion *pPortPrivates;
+	int nAttributes;
+	XF86AttributePtr pAttributes;
+	int nImages;
+	XF86ImagePtr pImages;
+	PutVideoFuncPtr PutVideo;
+	PutStillFuncPtr PutStill;
+	GetVideoFuncPtr GetVideo;
+	GetStillFuncPtr GetStill;
+	StopVideoFuncPtr StopVideo;
+	SetPortAttributeFuncPtr SetPortAttribute;
+	GetPortAttributeFuncPtr GetPortAttribute;
+	QueryBestSizeFuncPtr QueryBestSize;
+	PutImageFuncPtr PutImage;
+	QueryImageAttributesFuncPtr QueryImageAttributes;
+} XF86VideoAdaptorRec, *XF86VideoAdaptorPtr;
+      </programlisting></para>
+
+    <para>
+Each adaptor will have its own XF86VideoAdaptorRec.  The fields are
+as follows:
+
+      <variablelist>
+	<varlistentry>
+	  <term><structfield>type</structfield></term>
+	  <listitem><para>
+	This can be any of the following flags OR'd together.
+
+	      <variablelist>
+		<varlistentry>
+		  <term><constant>XvInputMask</constant>
+		    <constant>XvOutputMask</constant></term>
+		  <listitem><para>
+	    These refer to the target drawable and are similar to a Window's
+	    class. <literal remap="tt">XvInputMask</literal> indicates that the adaptor
+	    can put video into a drawable.  <literal remap="tt">XvOutputMask</literal>
+	    indicates that the adaptor can get video from a drawable.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><constant>XvVideoMask</constant>
+		    <constant>XvStillMask</constant>
+		    <constant>XvImageMask</constant></term>
+		  <listitem><para>
+	    These indicate that the adaptor supports video, still or
+	    image primitives respectively.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><constant>XvWindowMask</constant>
+		    <constant>XvPixmapMask</constant></term>
+		  <listitem><para>
+	    These indicate the types of drawables the adaptor is capable
+	    of rendering into.  At the moment, Pixmap rendering is not
+	    supported and the <constant>XvPixmapMask</constant> flag is ignored.
+		    </para></listitem></varlistentry>
+	      </variablelist>
+
+	    </para></listitem></varlistentry>
+
+	<varlistentry>
+	  <term><structfield>flags</structfield></term>
+	  <listitem><para>
+	Currently, the following flags are defined:
+
+	      <variablelist>
+		<varlistentry>
+		  <term><constant>VIDEO_NO_CLIPPING</constant></term>
+		  <listitem><para>
+	   This indicates that the video adaptor does not support
+	   clipping.  The driver will never receive ``Put'' requests
+	   where less than the entire area determined by
+	   <parameter>drw_x</parameter>, <parameter>drw_y</parameter>,
+	   <parameter>drw_w</parameter> and <parameter>drw_h</parameter> is visible.
+	   This flag does not apply to ``Get'' requests.  Hardware
+	   that is incapable of clipping ``Gets'' may punt or get
+	   the extents of the clipping region passed to it.
+		    </para></listitem>
+
+		</varlistentry>
+
+		<varlistentry>
+		  <term><constant>VIDEO_INVERT_CLIPLIST</constant></term>
+		  <listitem><para>
+	   This indicates that the video driver requires the clip
+	   list to contain the regions which are obscured rather
+	   than the regions which are are visible.
+		    </para></listitem>
+
+		</varlistentry>
+
+		<varlistentry>
+		  <term><constant>VIDEO_OVERLAID_STILLS</constant></term>
+		  <listitem><para>
+	   Implementing PutStill for hardware that does video as an
+	   overlay can be awkward since it's unclear how long to leave
+	   the video up for.  When this flag is set, StopVideo will be
+	   called whenever the destination gets clipped or moved so that
+	   the still can be left up until then.
+		    </para></listitem>
+
+		</varlistentry>
+
+		<varlistentry>
+		  <term><constant>VIDEO_OVERLAID_IMAGES</constant></term>
+		  <listitem><para>
+	   Same as <constant>VIDEO_OVERLAID_STILLS</constant> but for images.
+		    </para></listitem>
+		</varlistentry>
+
+		<varlistentry>
+		  <term><constant>VIDEO_CLIP_TO_VIEWPORT</constant></term>
+		  <listitem><para>
+	    Indicates that the clip region passed to the driver functions
+	    should be clipped to the visible portion of the screen in the
+	    case where the viewport is smaller than the virtual desktop.
+		    </para></listitem></varlistentry>
+
+	      </variablelist>
+	    </para></listitem></varlistentry>
+
+	<varlistentry>
+	  <term><structfield>name</structfield></term>
+	  <listitem><para>
+	The name of the adaptor.
+	    </para></listitem></varlistentry>
+
+
+	<varlistentry>
+	  <term><structfield>nEncodings</structfield>
+	    <structfield>pEncodings</structfield></term>
+	  <listitem><para>
+	The number of encodings the adaptor is capable of and pointer
+	to the <structname>XF86VideoEncodingRec</structname> array.  The
+	<structname>XF86VideoEncodingRec</structname> is described later on.
+	For drivers that only support XvImages there should be an encoding
+	named "XV_IMAGE" and the width and height should specify
+	the maximum size source image supported.
+	  </para></listitem></varlistentry>
+
+
+	<varlistentry>
+	  <term><structfield>nFormats</structfield>
+	      <structfield>pFormats</structfield></term>
+	  <listitem><para>
+	The number of formats the adaptor is capable of and pointer to
+	the <structname>XF86VideoFormatRec</structname> array.  The
+	<structname>XF86VideoFormatRec</structname> is described later on.
+	    </para></listitem></varlistentry>
+
+
+	<varlistentry>
+	  <term><structfield>nPorts</structfield>
+	    <structfield>pPortPrivates</structfield></term>
+	  <listitem><para>
+	The number of ports is the number of separate data streams which
+	the adaptor can handle simultaneously.  If you have more than
+	one port, the adaptor is expected to be able to render into more
+	than one window at a time.  <structfield>pPortPrivates</structfield> is
+	an array of pointers or ints - one for each port.  A port's
+	private data will be passed to the driver any time the port is
+	requested to do something like put the video or stop the video.
+	In the case where there may be many ports, this enables the
+	driver to know which port the request is intended for.  Most
+	commonly, this will contain a pointer to the data structure
+	containing information about the port.  In Xv, all ports on
+	a particular adaptor are expected to be identical in their
+	functionality.
+	    </para></listitem></varlistentry>
+
+
+	<varlistentry>
+	  <term><structfield>nAttributes</structfield>
+	    <structfield>pAttributes</structfield></term>
+	  <listitem><para>
+	The number of attributes recognized by the adaptor and a pointer to
+	the array of <structname>XF86AttributeRecs</structname>.  The
+	<structname>XF86AttributeRec</structname> is described later on.
+	    </para></listitem></varlistentry>
+
+
+	<varlistentry>
+	  <term><structfield>nImages</structfield>
+	    <structfield>pImages</structfield></term>
+	  <listitem><para>
+	The number of <structname>XF86ImageRecs</structname> supported by the adaptor
+	and a pointer to the array of <structname>XF86ImageRecs</structname>. The
+	<structname>XF86ImageRec</structname> is described later on.
+	    </para></listitem></varlistentry>
+
+
+	<varlistentry>
+	  <term><structfield>
+     PutVideo PutStill GetVideo GetStill StopVideo
+     SetPortAttribute GetPortAttribute QueryBestSize PutImage
+     QueryImageAttributes
+	    </structfield></term>
+	  <listitem><para>
+	These functions define the DDX-&gt;driver interface.  In each
+	case, the pointer <parameter>data</parameter> is passed to the driver.
+	This is the port private for that port as described above.  All
+	fields are required except under the following conditions:
+
+	      <orderedlist>
+		<listitem><para>
+	     <structfield>PutVideo</structfield>, <structfield>PutStill</structfield> and
+	     the image routines <structfield>PutImage</structfield> and
+	     <structfield>QueryImageAttributes</structfield> are not required when the
+	     adaptor type does not contain <constant>XvInputMask</constant>.
+		  </para></listitem>
+
+		<listitem><para>
+	     <structfield>GetVideo</structfield> and <structfield>GetStill</structfield>
+	     are not required when the adaptor type does not contain
+	     <constant>XvOutputMask</constant>.
+		  </para></listitem>
+
+		<listitem><para>
+	     <structfield>GetVideo</structfield> and <structfield>PutVideo</structfield>
+	     are not required when the adaptor type does not contain
+	     <constant>XvVideoMask</constant>.
+		  </para></listitem>
+
+		<listitem><para>
+	     <structfield>GetStill</structfield> and <structfield>PutStill</structfield>
+	     are not required when the adaptor type does not contain
+	     <constant>XvStillMask</constant>.
+		  </para></listitem>
+
+		<listitem><para>
+	     <structfield>PutImage</structfield> and <structfield>QueryImageAttributes</structfield>
+	     are not required when the adaptor type does not contain
+	     <constant>XvImageMask</constant>.
+		  </para></listitem>
+
+	      </orderedlist>
+
+	    </para>
+
+	    <para>
+	With the exception of <structfield>QueryImageAttributes</structfield>, these
+	functions should return <constant>Success</constant> if the operation was
+	completed successfully.  They can return <constant>XvBadAlloc</constant>
+	otherwise. <structfield>QueryImageAttributes</structfield> returns the size
+	of the XvImage queried.
+	    </para>
+
+	    <para>
+	If the <constant>VIDEO_NO_CLIPPING</constant>
+	flag is set, the <literal remap="tt">clipBoxes</literal> may be ignored by
+	the driver.  <literal remap="tt">ClipBoxes</literal> is an <literal remap="tt">X-Y</literal>
+	banded region identical to those used throughout the server.
+	The clipBoxes represent the visible portions of the area determined
+	by <literal remap="tt">drw_x</literal>, <literal remap="tt">drw_y</literal>,
+	<literal remap="tt">drw_w</literal> and <literal remap="tt">drw_h</literal> in the Get/Put
+	function.  The boxes are in screen coordinates, are guaranteed
+	not to overlap and an empty region will never be passed.
+	If the driver has specified <constant>VIDEO_INVERT_CLIPLIST</constant>,
+	<literal remap="tt">clipBoxes</literal> will indicate the areas of the primitive
+	which are obscured rather than the areas visible.
+
+	    </para></listitem></varlistentry>
+      </variablelist>
+
+      <blockquote><para>
+	  <programlisting>
+    typedef  int (* PutVideoFuncPtr)( ScrnInfoPtr pScrn,
+                   short vid_x, short vid_y, short drw_x, short drw_y,
+                   short vid_w, short vid_h, short drw_w, short drw_h,
+                   RegionPtr clipBoxes, pointer data );
+	  </programlisting>
+	      <blockquote><para>
+	  This indicates that the driver should take a subsection
+	  <parameter>vid_w</parameter> by <parameter>vid_h</parameter> at location
+	  <parameter>(vid_x,vid_y)</parameter> from the video stream and direct
+	  it into the rectangle <parameter>drw_w</parameter> by <parameter>drw_h</parameter>
+	  at location <parameter>(drw_x,drw_y)</parameter> on the screen, scaling as
+	  necessary.  Due to the large variations in capabilities of
+	  the various hardware expected to be used with this extension,
+	  it is not expected that all hardware will be able to do this
+	  exactly as described.  In that case the driver should just do
+	  ``the best it can,'' scaling as closely to the target rectangle
+	  as it can without rendering outside of it.  In the worst case,
+	  the driver can opt to just not turn on the video.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	  <blockquote><para>
+	      <programlisting>
+    typedef  int (* PutStillFuncPtr)( ScrnInfoPtr pScrn,
+                   short vid_x, short vid_y, short drw_x, short drw_y,
+                   short vid_w, short vid_h, short drw_w, short drw_h,
+                   RegionPtr clipBoxes, pointer data );
+	      </programlisting>
+	      <blockquote><para>
+	  This is same as <structfield>PutVideo</structfield> except that the driver
+	  should place only one frame from the stream on the screen.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	  <blockquote><para>
+	      <programlisting>
+    typedef int (* GetVideoFuncPtr)( ScrnInfoPtr pScrn,
+                  short vid_x, short vid_y, short drw_x, short drw_y,
+                  short vid_w, short vid_h, short drw_w, short drw_h,
+                  RegionPtr clipBoxes, pointer data );
+	      </programlisting>
+	      <blockquote><para>
+	  This is same as <structfield>PutVideo</structfield> except that the driver
+	  gets video from the screen and outputs it.  The driver should
+	  do the best it can to get the requested dimensions correct
+	  without reading from an area larger than requested.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	  <blockquote><para>
+	      <programlisting>
+    typedef int (* GetStillFuncPtr)( ScrnInfoPtr pScrn,
+                  short vid_x, short vid_y, short drw_x, short drw_y,
+                  short vid_w, short vid_h, short drw_w, short drw_h,
+                  RegionPtr clipBoxes, pointer data );
+	      </programlisting>
+	      <blockquote><para>
+	  This is the same as <literal remap="tt">GetVideo</literal> except that the
+	  driver should place only one frame from the screen into the
+	  output stream.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	  <blockquote><para>
+	      <programlisting>
+    typedef void (* StopVideoFuncPtr)(ScrnInfoPtr pScrn,
+                                      pointer data, Bool cleanup);
+	      </programlisting>
+	      <blockquote><para>
+	  This indicates the driver should stop displaying the video.
+	  This is used to stop both input and output video.  The
+	  <parameter>cleanup</parameter> field indicates that the video is
+	  being stopped because the client requested it to stop or
+	  because the server is exiting the current VT.  In that case
+	  the driver should deallocate any offscreen memory areas (if
+	  there are any) being used to put the video to the screen.  If
+	  <parameter>cleanup</parameter> is not set, the video is being stopped
+	  temporarily due to clipping or moving of the window, etc...
+	  and video will likely be restarted soon so the driver should
+	  not deallocate any offscreen areas associated with that port.
+	      </para>
+
+	    </blockquote></para></blockquote>
+	  <blockquote><para>
+	      <programlisting>
+    typedef int (* SetPortAttributeFuncPtr)(ScrnInfoPtr pScrn,
+                                Atom attribute,INT32 value, pointer data);
+	      </programlisting>
+
+	      <programlisting>
+    typedef int (* GetPortAttributeFuncPtr)(ScrnInfoPtr pScrn,
+                                Atom attribute,INT32 *value, pointer data);
+	      </programlisting>
+	      <blockquote><para>
+	  A port may have particular attributes such as hue,
+	  saturation, brightness or contrast.  Xv clients set and
+	  get these attribute values by sending attribute strings
+	  (Atoms) to the server.  Such requests end up at these
+	  driver functions.  It is recommended that the driver provide
+	  at least the following attributes mentioned in the Xv client
+	  library docs:
+		<literallayout><constant>
+		XV_ENCODING
+		XV_HUE
+		XV_SATURATION
+		XV_BRIGHTNESS
+  		XV_CONTRAST
+		  </constant></literallayout>
+	  but the driver may recognize as many atoms as it wishes.  If
+	  a requested attribute is unknown by the driver it should return
+	  <constant>BadMatch</constant>.  <constant>XV_ENCODING</constant> is the
+	  attribute intended to let the client specify which video
+	  encoding the particular port should be using (see the description
+	  of <structname>XF86VideoEncodingRec</structname> below).  If the
+	  requested encoding is unsupported, the driver should return
+	  <constant>XvBadEncoding</constant>.  If the value lies outside the
+	  advertised range <constant>BadValue</constant> may be returned.
+	  <constant>Success</constant> should be returned otherwise.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	  <blockquote><para>
+	    <programlisting>
+    typedef void (* QueryBestSizeFuncPtr)(ScrnInfoPtr pScrn,
+                   Bool motion, short vid_w, short vid_h,
+                   short drw_w, short drw_h,
+                   unsigned int *p_w, unsigned int *p_h, pointer data);
+	    </programlisting>
+	    <blockquote><para>
+	   <function>QueryBestSize</function> provides the client with a way
+	   to query what the destination dimensions would end up being
+	   if they were to request that an area
+	   <parameter>vid_w</parameter> by <parameter>vid_h</parameter> from the video
+	   stream be scaled to rectangle of
+	   <parameter>drw_w</parameter> by <parameter>drw_h</parameter> on the screen.
+	   Since it is not expected that all hardware will be able to
+	   get the target dimensions exactly, it is important that the
+	   driver provide this function.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    typedef  int (* PutImageFuncPtr)( ScrnInfoPtr pScrn,
+                   short src_x, short src_y, short drw_x, short drw_y,
+                   short src_w, short src_h, short drw_w, short drw_h,
+                   int image, char *buf, short width, short height,
+                   Bool sync, RegionPtr clipBoxes, pointer data );
+	      </programlisting>
+	      <blockquote><para>
+	  This is similar to <structfield>PutStill</structfield> except that the
+	  source of the video is not a port but the data stored in a system
+	  memory buffer at <parameter>buf</parameter>.  The data is in the format
+	  indicated by the <parameter>image</parameter> descriptor and represents a
+	  source of size <parameter>width</parameter> by <parameter>height</parameter>.
+	  If <parameter>sync</parameter> is TRUE the driver should not return
+	  from this function until it is through reading the data
+	  from <parameter>buf</parameter>.  Returning when <parameter>sync</parameter>
+	  is TRUE indicates that it is safe for the data at <parameter>buf</parameter>
+	  to be replaced, freed, or modified.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    typedef  int (* QueryImageAttributesFuncPtr)( ScrnInfoPtr pScrn,
+                                int image, short *width, short *height,
+                                int *pitches, int *offsets);
+	    </programlisting>
+	    <blockquote><para>
+	  This function is called to let the driver specify how data for
+	  a particular <parameter>image</parameter> of size <parameter>width</parameter>
+	  by <parameter>height</parameter> should be stored.  Sometimes only
+	  the size and corrected width and height are needed.  In that
+	  case <parameter>pitches</parameter> and <parameter>offsets</parameter> are
+	  NULL.  The size of the memory required for the image is returned
+	  by this function.  The <parameter>width</parameter> and
+	  <parameter>height</parameter> of the requested image can be altered by
+	  the driver to reflect format limitations (such as component
+	  sampling periods that are larger than one).  If
+	  <parameter>pitches</parameter> and <parameter>offsets</parameter> are not NULL,
+	  these will be arrays with as many elements in them as there
+	  are planes in the <parameter>image</parameter> format.  The driver
+	  should specify the pitch (in bytes) of each scanline in the
+	  particular plane as well as the offset to that plane (in bytes)
+	  from the beginning of the image.
+	      </para>
+
+	  </blockquote></para></blockquote>
+    </para>
+
+    <para>
+The XF86VideoEncodingRec:
+
+      <blockquote><para>
+	  <programlisting>
+typedef struct {
+	int id;
+	char *name;
+	unsigned short width, height;
+	XvRationalRec rate;
+} XF86VideoEncodingRec, *XF86VideoEncodingPtr;
+
+	  </programlisting>
+	  <blockquote><para>
+   The <structname>XF86VideoEncodingRec</structname> specifies what encodings
+   the adaptor can support.  Most of this data is just informational
+   and for the client's benefit, and is what will be reported by
+   <function>XvQueryEncodings</function>.  The <parameter>id</parameter> field is
+   expected to be a unique identifier to allow the client to request a
+   certain encoding via the <constant>XV_ENCODING</constant> attribute string.
+
+	    </para>
+	  </blockquote></para></blockquote>
+    </para>
+
+    <para>
+The XF86VideoFormatRec:
+
+      <blockquote><para>
+	  <programlisting>
+typedef struct {
+	char  depth;
+	short class;
+} XF86VideoFormatRec, *XF86VideoFormatPtr;
+
+	  </programlisting>
+	  <blockquote><para>
+    This specifies what visuals the video is viewable in.
+    <parameter>depth</parameter> is the depth of the visual (not bpp).
+    <parameter>class</parameter> is the visual class such as
+    <constant>TrueColor</constant>, <constant>DirectColor</constant> or
+    <constant>PseudoColor</constant>.  Initialization of an adaptor will fail
+    if none of the visuals on that screen are supported.
+	    </para>
+
+	  </blockquote></para></blockquote>
+    </para>
+
+    <para>
+The XF86AttributeRec:
+
+      <blockquote><para>
+	  <programlisting>
+typedef struct {
+	int   flags;
+	int   min_value;
+	int   max_value;
+	char  *name;
+} XF86AttributeListRec, *XF86AttributeListPtr;
+
+	  </programlisting>
+	  <blockquote><para>
+   Each adaptor may have an array of these advertising the attributes
+   for its ports.  Currently defined flags are <literal remap="tt">XvGettable</literal>
+   and <literal remap="tt">XvSettable</literal> which may be OR'd together indicating that
+   attribute is ``gettable'' or ``settable'' by the client.  The
+   <literal remap="tt">min</literal> and <literal remap="tt">max</literal> field specify the valid range
+   for the value.  <literal remap="tt">Name</literal> is a text string describing the
+   attribute by name.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+    </para>
+
+    <para>
+The XF86ImageRec:
+
+	<blockquote><para>
+	    <programlisting>
+typedef struct {
+	int id;
+	int type;
+	int byte_order;
+	char guid[16];
+	int bits_per_pixel;
+	int format;
+	int num_planes;
+
+	/* for RGB formats */
+	int depth;
+	unsigned int red_mask;
+	unsigned int green_mask;
+	unsigned int blue_mask;
+
+	/* for YUV formats */
+	unsigned int y_sample_bits;
+	unsigned int u_sample_bits;
+	unsigned int v_sample_bits;
+	unsigned int horz_y_period;
+	unsigned int horz_u_period;
+	unsigned int horz_v_period;
+	unsigned int vert_y_period;
+	unsigned int vert_u_period;
+	unsigned int vert_v_period;
+	char component_order[32];
+	int scanline_order;
+} XF86ImageRec, *XF86ImagePtr;
+
+	    </programlisting>
+	    <blockquote><para>
+   XF86ImageRec describes how video source data is laid out in memory.
+   The fields are as follows:
+
+		<variablelist>
+		  <varlistentry>
+		    <term><structfield>id</structfield></term>
+		    <listitem><para>
+	This is a unique descriptor for the format.  It is often good to
+        set this value to the FOURCC for the format when applicable.
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><structfield>type</structfield></term>
+		    <listitem><para>
+	This is <constant>XvRGB</constant> or <constant>XvYUV</constant>.
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><structfield>byte_order</structfield></term>
+		    <listitem><para>
+	This is <constant>LSBFirst</constant> or <constant>MSBFirst</constant>.
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><structfield>guid</structfield></term>
+		    <listitem><para>
+	This is the Globally Unique IDentifier for the format.  When
+	not applicable, all characters should be NULL.
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><structfield>bits_per_pixel</structfield></term>
+		    <listitem><para>
+	The number of bits taken up (but not necessarily used) by each
+	pixel.  Note that for some planar formats which have fractional
+	bits per pixel (such as IF09) this number may be rounded _down_.
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><structfield>format</structfield></term>
+		    <listitem><para>
+	This is <constant>XvPlanar</constant> or <constant>XvPacked</constant>.
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><structfield>num_planes</structfield></term>
+		    <listitem><para>
+	The number of planes in planar formats.  This should be set to
+	one for packed formats.
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><structfield>depth</structfield></term>
+		    <listitem><para>
+	The significant bits per pixel in RGB formats (analgous to the
+	depth of a pixmap format).
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><structfield>red_mask</structfield></term>
+		    <term><structfield>green_mask</structfield></term>
+		    <term><structfield>blue_mask</structfield></term>
+		    <listitem><para>
+	The red, green and blue bitmasks for packed RGB formats.
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><structfield>y_sample_bits</structfield></term>
+		    <term><structfield>u_sample_bits</structfield></term>
+		    <term><structfield>v_sample_bits</structfield></term>
+		    <listitem><para>
+	The y, u and v sample sizes (in bits).
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><structfield>horz_y_period</structfield></term>
+		    <term><structfield>horz_u_period</structfield></term>
+		    <term><structfield>horz_v_period</structfield></term>
+		    <listitem><para>
+	The y, u and v sampling periods in the horizontal direction.
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><structfield>vert_y_period</structfield></term>
+		    <term><structfield>vert_u_period</structfield></term>
+		    <term><structfield>vert_v_period</structfield></term>
+		    <listitem><para>
+	The y, u and v sampling periods in the vertical direction.
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><structfield>component_order</structfield></term>
+		    <listitem><para>
+	Uppercase ascii characters representing the order that
+	samples are stored within packed formats.  For planar formats
+	this represents the ordering of the planes.  Unused characters
+	in the 32 byte string should be set to NULL.
+		      </para></listitem></varlistentry>
+
+		  <varlistentry>
+		    <term><structfield>scanline_order</structfield></term>
+		    <listitem><para>
+	This is <constant>XvTopToBottom</constant> or <constant>XvBottomToTop</constant>.
+		      </para></listitem></varlistentry>
+
+		  </variablelist>
+	    </para>
+
+	    <para>
+  Since some formats (particular some planar YUV formats) may not
+be completely defined by the parameters above, the guid, when
+available, should provide the most accurate description of the
+format.
+	    </para>
+
+	  </blockquote></para></blockquote>
+    </para>
+  </sect1>
+
+  <sect1>
+    <title>The Loader</title>
+
+    <para>
+This section describes the interfaces to the module loader.  The loader
+interfaces can be divided into two groups: those that are only available to
+the XFree86 common layer, and those that are also available to modules.
+    </para>
+
+    <sect2>
+      <title>Loader Overview</title>
+
+      <para>
+The loader is capable of loading modules in a range of object formats,
+and knowledge of these formats is built in to the loader.  Knowledge of
+new object formats can be added to the loader in a straightforward
+manner.  This makes it possible to provide OS-independent modules (for
+a given CPU architecture type).  In addition to this, the loader can
+load modules via the OS-provided <function>dlopen(3)</function> service where
+available.  Such modules are not platform independent, and the semantics
+of <function>dlopen()</function> on most systems results in significant
+limitations in the use of modules of this type.  Support for
+<function>dlopen()</function> modules in the loader is primarily for
+experimental and development purposes.
+      </para>
+
+      <para>
+Symbols exported by the loader (on behalf of the core X server) to
+modules are determined at compile time.  Only those symbols explicitly
+exported are available to modules.  All external symbols of loaded
+modules are exported to other modules, and to the core X server.  The
+loader can be requested to check for unresolved symbols at any time,
+and the action to be taken for unresolved symbols can be controlled by
+the caller of the loader.  Typically the caller identifies which symbols
+can safely remain unresolved and which cannot.
+      </para>
+
+      <para>
+NOTE:  Now that ISO-C allows pointers to functions and pointers to data to
+have different internal representations, some of the following interfaces
+will need to be revisited.
+      </para>
+    </sect2>
+
+    <sect2>
+      <title>Semi-private Loader Interface</title>
+
+      <para>
+The following is the semi-private loader interface that is available to the
+XFree86 common layer.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    void LoaderInit(void);
+	  </programlisting>
+	  <blockquote><para>
+    The <function>LoaderInit()</function> function initialises the loader,
+    and it must be called once before calling any other loader functions.
+    This function initialises the tables of exported symbols, and anything
+    else that might need to be initialised.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void LoaderSetPath(const char *path);
+	  </programlisting>
+	  <blockquote><para>
+    The <function>LoaderSetPath()</function> function initialises a default
+    module search path.  This must be called if calls to other functions
+    are to be made without explicitly specifying a module search path.
+    The search path <parameter>path</parameter> must be a string of one or more
+    comma separated absolute paths.  Modules are expected to be located
+    below these paths, possibly in subdirectories of these paths.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    pointer LoadModule(const char *module, const char *path,
+                       const char **subdirlist, const char **patternlist,
+                       pointer options, const XF86ModReqInfo * modreq,
+                       int *errmaj, int *errmin);
+	  </programlisting>
+	  <blockquote><para>
+    The <function>LoadModule()</function> function loads the module called
+    <parameter>module</parameter>.  The return value is a module handle, and
+    may be used in future calls to the loader that require a reference
+    to a loaded module.  The module name <parameter>module</parameter> is
+    normally the module's canonical name, which doesn't contain any
+    directory path information, or any object/library file prefixes of
+    suffixes.  Currently a full pathname and/or filename is also accepted.
+    This might change.  The other parameters are:
+
+	      <variablelist>
+		<varlistentry>
+		  <term><parameter>path</parameter></term>
+		  <listitem><para>
+		  An optional comma-separated list of module search paths.
+		  When <constant>NULL</constant>, the default search path is used.
+		    </para></listitem></varlistentry>
+
+
+		<varlistentry>
+		  <term><parameter>subdirlist</parameter></term>
+		  <listitem><para>
+		  An optional <constant>NULL</constant> terminated list of
+		  subdirectories to search.  When <constant>NULL</constant>,
+		  the default built-in list is used (refer to
+		  <varname>stdSubdirs</varname> in <filename>loadmod.c</filename>).
+		  The default list is also substituted for entries in
+		  <parameter>subdirlist</parameter> with the value
+		  <constant>DEFAULT_LIST</constant>.  This makes is possible
+		  to augment the default list instead of replacing it.
+		  Subdir elements must be relative, and must not contain
+		  <literal remap="tt">".."</literal>.  If any violate this requirement,
+		  the load fails.
+		    </para></listitem></varlistentry>
+
+
+		<varlistentry>
+		  <term><parameter>patternlist</parameter></term>
+		  <listitem><para>
+		  An optional <constant>NULL</constant> terminated list of
+		  POSIX regular expressions used to connect module
+		  filenames with canonical module names.  Each regex
+		  should contain exactly one subexpression that corresponds
+		  to the canonical module name.  When <constant>NULL</constant>,
+		  the default built-in list is used (refer to
+		  <varname>stdPatterns</varname> in
+		  <filename>loadmod.c</filename>).  The default list is also
+		  substituted for entries in <parameter>patternlist</parameter>
+		  with the value <constant>DEFAULT_LIST</constant>.  This
+		  makes it possible to augment the default list instead
+		  of replacing it.
+		    </para></listitem></varlistentry>
+
+
+		<varlistentry>
+		  <term><parameter>options</parameter></term>
+		  <listitem><para>
+		  An optional parameter that is passed to the newly
+		  loaded module's <literal remap="tt">SetupProc</literal> function
+		  (if it has one).  This argument is normally a
+		  <constant>NULL</constant> terminated list of
+		  <structname>Options</structname>, and must be interpreted that
+		  way by modules loaded directly by the XFree86 common
+		  layer.  However, it may be used for application-specific
+		  parameter passing in other situations.
+		    </para>
+
+		    <para>
+		  When loading ``external'' modules (modules that don't
+		  have the standard entry point, for example a
+		  special shared library) the options parameter can be
+		  set to <constant>EXTERN_MODULE</constant> to tell the
+		  loader not to reject the module when it doesn't find
+		  the standard entry point.
+		    </para></listitem></varlistentry>
+
+
+		<varlistentry>
+		  <term><parameter>modreq</parameter></term>
+		  <listitem><para>
+		  An optional <structname>XF86ModReqInfo*</structname> containing
+		  version/ABI/vendor information to requirements to
+		  check the newly loaded module against.  The main
+		  purpose of this is to allow the loader to verify that
+		  a module of the correct type/version before running
+		  its <function>SetupProc</function> function.
+		      </para>
+
+		    <para>
+		  The <literal remap="tt">XF86ModReqInfo</literal> struct is defined
+		  as follows:
+		      <programlisting>
+typedef struct {
+	CARD8        majorversion;  /* MAJOR_UNSPEC */
+	CARD8        minorversion;  /* MINOR_UNSPEC */
+	CARD16       patchlevel;    /* PATCH_UNSPEC */
+	const char * abiclass;      /* ABI_CLASS_NONE */
+	CARD32       abiversion;    /* ABI_VERS_UNSPEC */
+	const char * moduleclass;   /* MOD_CLASS_NONE */
+} XF86ModReqInfo;
+			</programlisting>
+
+		  The information here is compared against the equivalent
+		  information in the module's
+		  <structname>XF86ModuleVersionInfo</structname> record (which
+		  is described below).  The values in comments above
+		  indicate ``don't care'' settings for each of the fields.
+		  The comparisons made are as follows:
+
+		      <variablelist>
+			<varlistentry>
+			  <term><structfield>majorversion</structfield></term>
+			  <listitem><para>
+				   Must match the module's majorversion
+				   exactly.
+			    </para></listitem></varlistentry>
+
+			<varlistentry>
+			  <term><structfield>minorversion</structfield></term>
+			  <listitem><para>
+				   The module's minor version must be
+				   no less than this value.  This
+				   comparison is only made if
+				   <structfield>majorversion</structfield> is
+				   specified and matches.
+			    </para></listitem></varlistentry>
+
+			<varlistentry>
+			  <term><structfield>patchlevel</structfield></term>
+			  <listitem><para>
+				   The module's patchlevel must be no
+				   less than this value.  This comparison
+				   is only made if
+				   <structfield>minorversion</structfield> is
+				   specified and matches.
+			    </para></listitem></varlistentry>
+
+			<varlistentry>
+			  <term><structfield>abiclass</structfield></term>
+			  <listitem><para>
+				   String must match the module's abiclass
+				   string.
+			    </para></listitem></varlistentry>
+
+			<varlistentry>
+			  <term><structfield>abiversion</structfield></term>
+			  <listitem><para>
+				   Must be consistent with the module's
+				   abiversion (major equal, minor no
+				   older).
+			    </para></listitem></varlistentry>
+
+			<varlistentry>
+			  <term><structfield>moduleclass</structfield></term>
+			  <listitem><para>
+				   String must match the module's
+				   moduleclass string.
+			    </para></listitem></varlistentry>
+
+		      </variablelist>
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>errmaj</parameter></term>
+		  <listitem><para>
+		  An optional pointer to a variable holding the major
+		  part or the error code.  When provided,
+		  <parameter>*errmaj</parameter> is filled in when
+		  <function>LoadModule()</function> fails.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>errmin</parameter></term>
+		  <listitem><para>
+		  Like <parameter>errmaj</parameter>, but for the minor part
+		  of the error code.
+		    </para></listitem></varlistentry>
+
+	      </variablelist>
+
+	    </para></blockquote>
+	</para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void UnloadModule(pointer mod);
+	  </programlisting>
+	  <blockquote><para>
+    This function unloads the module referred to by the handle mod.
+    All child modules are also unloaded recursively.  This function must
+    not be used to directly unload modules that are child modules (i.e.,
+    those that have been loaded with the <function>LoadSubModule()</function>
+    described below).
+	    </para>
+
+	  </blockquote></para></blockquote>
+    </sect2>
+
+    <sect2>
+      <title>Module Requirements</title>
+
+      <para>
+Modules must provide information about themselves to the loader, and
+may optionally provide entry points for "setup" and "teardown" functions
+(those two functions are referred to here as <function>SetupProc</function>
+and <function>TearDownProc</function>).
+      </para>
+
+      <para>
+The module information is contained in the
+<structname>XF86ModuleVersionInfo</structname> struct, which is defined as follows:
+
+	<programlisting>
+typedef struct {
+    const char * modname;      /* name of module, e.g. "foo" */
+    const char * vendor;       /* vendor specific string */
+    CARD32       _modinfo1_;   /* constant MODINFOSTRING1/2 to find */
+    CARD32       _modinfo2_;   /* infoarea with a binary editor/sign tool */
+    CARD32       xf86version;  /* contains XF86_VERSION_CURRENT */
+    CARD8        majorversion; /* module-specific major version */
+    CARD8        minorversion; /* module-specific minor version */
+    CARD16       patchlevel;   /* module-specific patch level */
+    const char * abiclass;     /* ABI class that the module uses */
+    CARD32       abiversion;   /* ABI version */
+    const char * moduleclass;  /* module class */
+    CARD32       checksum[4];  /* contains a digital signature of the */
+                               /* version info structure */
+} XF86ModuleVersionInfo;
+	</programlisting>
+
+The fields are used as follows:
+
+	<variablelist>
+	  <varlistentry>
+	    <term><structfield>modname</structfield></term>
+	    <listitem><para>
+		The module's name.  This field is currently only for
+		informational purposes, but the loader may be modified
+		in future to require it to match the module's canonical
+                name.
+	      </para></listitem></varlistentry>
+
+
+	  <varlistentry>
+	    <term><structfield>vendor</structfield></term>
+	    <listitem><para>
+		The module vendor.  This field is for informational purposes
+                only.
+	      </para></listitem></varlistentry>
+
+
+	  <varlistentry>
+	    <term><structfield>_modinfo1_</structfield></term>
+	    <listitem><para>
+		This field holds the first part of a signature that can
+                be used to locate this structure in the binary.  It should
+		always be initialised to <constant>MODINFOSTRING1</constant>.
+	      </para></listitem></varlistentry>
+
+
+	  <varlistentry>
+	    <term><structfield>_modinfo2_</structfield></term>
+	    <listitem><para>
+		This field holds the second part of a signature that can
+                be used to locate this structure in the binary.  It should
+		always be initialised to <constant>MODINFOSTRING2</constant>.
+	      </para></listitem></varlistentry>
+
+
+	  <varlistentry>
+	    <term><structfield>xf86version</structfield></term>
+	    <listitem><para>
+		The XFree86 version against which the module was compiled.
+                This is mostly for informational/diagnostic purposes.  It
+		should be initialised to <constant>XF86_VERSION_CURRENT</constant>, which is
+		defined in <filename>xf86Version.h</filename>.
+	      </para></listitem></varlistentry>
+
+
+	  <varlistentry>
+	    <term><structfield>majorversion</structfield></term>
+	    <listitem><para>
+		The module-specific major version.  For modules where this
+		version is used for more than simply informational
+		purposes, the major version should only change (be
+		incremented) when ABI incompatibilities are introduced,
+		or ABI components are removed.
+	      </para></listitem></varlistentry>
+
+
+	  <varlistentry>
+	    <term><structfield>minorversion</structfield></term>
+	    <listitem><para>
+		The module-specific minor version.  For modules where this
+		version is used for more than simply informational
+		purposes, the minor version should only change (be
+		incremented) when ABI additions are made in a backward
+		compatible way.  It should be reset to zero when the major
+                version is increased.
+	      </para></listitem></varlistentry>
+
+
+	  <varlistentry>
+	    <term><structfield>patchlevel</structfield></term>
+	    <listitem><para>
+		The module-specific patch level.  The patch level should
+		increase with new revisions of the module where there
+		are no ABI changes, and it should be reset to zero when
+		the minor version is increased.
+	      </para></listitem></varlistentry>
+
+
+	  <varlistentry>
+	    <term><structfield>abiclass</structfield></term>
+	    <listitem><para>
+		The ABI class that the module requires.  The class is
+                specified as a string for easy extensibility.  It should
+		indicate which (if any) of the X server's built-in ABI
+		classes that the module relies on, or a third-party ABI
+                if appropriate.  Built-in ABI classes currently defined are:
+
+		<variablelist>
+		  <varlistentry>
+		    <term><constant>ABI_CLASS_NONE</constant></term>
+		    <listitem><para>no class
+		      </para></listitem></varlistentry>
+		  <varlistentry>
+		    <term><constant>ABI_CLASS_ANSIC</constant></term>
+		    <listitem><para>only requires the ANSI C interfaces
+		      </para></listitem></varlistentry>
+		  <varlistentry>
+		    <term><constant>ABI_CLASS_VIDEODRV</constant></term>
+		    <listitem><para>requires the video driver ABI
+		      </para></listitem></varlistentry>
+		  <varlistentry>
+		    <term><constant>ABI_CLASS_XINPUT</constant></term>
+		    <listitem><para>requires the XInput driver ABI
+		      </para></listitem></varlistentry>
+		  <varlistentry>
+		    <term><constant>ABI_CLASS_EXTENSION</constant></term>
+		    <listitem><para>requires the extension module ABI
+		      </para></listitem></varlistentry>
+		  <varlistentry>
+		    <term><constant>ABI_CLASS_FONT</constant></term>
+		    <listitem><para>requires the font module ABI
+		      </para></listitem></varlistentry>
+		</variablelist>
+
+	      </para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>abiversion</structfield></term>
+	    <listitem><para>
+		The version of abiclass that the module requires.  The
+		version consists of major and minor components.  The
+		major version must match and the minor version must be
+		no newer than that provided by the server or parent
+		module.  Version identifiers for the built-in classes
+		currently defined are:
+
+		<literallayout><constant>
+                   ABI_ANSIC_VERSION
+                   ABI_VIDEODRV_VERSION
+                   ABI_XINPUT_VERSION
+                   ABI_EXTENSION_VERSION
+                   ABI_FONT_VERSION
+		  </constant></literallayout>
+
+	      </para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>moduleclass</structfield></term>
+	    <listitem><para>
+		This is similar to the abiclass field, except that it
+		defines the type of module rather than the ABI it
+		requires.  For example, although all video drivers require
+		the video driver ABI, not all modules that require the
+		video driver ABI are video drivers.  This distinction
+		can be made with the moduleclass.  Currently pre-defined
+		module classes are:
+
+		<literallayout><constant>
+                   MOD_CLASS_NONE
+                   MOD_CLASS_VIDEODRV
+                   MOD_CLASS_XINPUT
+                   MOD_CLASS_FONT
+                   MOD_CLASS_EXTENSION
+		  </constant></literallayout>
+
+	      </para></listitem></varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>checksum</structfield></term>
+	    <listitem><para>
+		Not currently used.
+	      </para></listitem></varlistentry>
+
+	</variablelist>
+      </para>
+
+      <para>
+The module version information, and the optional <function>SetupProc</function>
+and <function>TearDownProc</function> entry points are found by the loader
+by locating a data object in the module called "modnameModuleData",
+where "modname" is the canonical name of the module.  Modules must
+contain such a data object, and it must be declared with global scope,
+be compile-time initialised, and is of the following type:
+
+	<programlisting>
+typedef struct {
+    XF86ModuleVersionInfo *     vers;
+    ModuleSetupProc             setup;
+    ModuleTearDownProc          teardown;
+} XF86ModuleData;
+	</programlisting>
+      </para>
+
+      <para>
+The vers parameter must be initialised to a pointer to a correctly
+initialised <structname>XF86ModuleVersionInfo</structname> struct.  The other
+two parameter are optional, and should be initialised to
+<constant>NULL</constant> when not required.  The other parameters are defined
+as
+
+	<blockquote><para>
+	    <programlisting>
+    typedef pointer (*ModuleSetupProc)(pointer, pointer, int *, int *);
+
+    typedef void (*ModuleTearDownProc)(pointer);
+
+    pointer SetupProc(pointer module, pointer options,
+                      int *errmaj, int *errmin);
+	    </programlisting>
+	    <blockquote><para>
+    When defined, this function is called by the loader after successfully
+    loading a module.  module is a handle for the newly loaded module,
+    and maybe used by the <function>SetupProc</function> if it calls other
+    loader functions that require a reference to it.   The remaining
+    arguments are those that were passed to the
+    <function>LoadModule()</function> (or <function>LoadSubModule()</function>),
+    and are described above. When the <function>SetupProc</function> is
+    successful it must return a non-<constant>NULL</constant> value.  The
+    loader checks this, and if it is <constant>NULL</constant> it unloads
+    the module and reports the failure to the caller of
+    <function>LoadModule()</function>.  If the <function>SetupProc</function>
+    does things that need to be undone when the module is unloaded,
+    it should define a <function>TearDownProc</function>, and return a
+    pointer that the <function>TearDownProc</function> can use to undo what
+    has been done.
+	      </para>
+
+	      <para>
+    When a module is loaded multiple times, the <function>SetupProc</function>
+    is called once for each time it is loaded.
+	      </para>
+
+	    </blockquote></para></blockquote>
+
+	<blockquote><para>
+	    <programlisting>
+    void TearDownProc(pointer tearDownData);
+	    </programlisting>
+	    <blockquote><para>
+    When defined, this function is called when the loader unloads a
+    module.  The <parameter>tearDownData</parameter> parameter is the return
+    value of the <function>SetupProc()</function> that was called when the
+    module was loaded.  The purpose of this function is to clean up
+    before the module is unloaded (for example, by freeing allocated
+    resources).
+	      </para>
+
+	    </blockquote></para></blockquote>
+      </para>
+    </sect2>
+
+    <sect2>
+      <title>Public Loader Interface</title>
+
+      <para>
+The following is the Loader interface that is available to any part of
+the server, and may also be used from within modules.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    pointer LoadSubModule(pointer parent, const char *module,
+                          const char **subdirlist, const char **patternlist,
+                          pointer options, const XF86ModReqInfo * modreq,
+                          int *errmaj, int *errmin);
+	  </programlisting>
+	  <blockquote><para>
+    This function is like the <function>LoadModule()</function> function
+    described above, except that the module loaded is registered as a
+    child of the calling module.  The <parameter>parent</parameter> parameter
+    is the calling module's handle.  Modules loaded with this function
+    are automatically unloaded when the parent module is unloaded.  The
+    other difference is that the path parameter may not be specified.
+    The module search path used for modules loaded with this function
+    is the default search path as initialised with
+    <function>LoaderSetPath()</function>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void UnloadSubModule(pointer module);
+	  </programlisting>
+	  <blockquote><para>
+    This function unloads the module with handle <parameter>module</parameter>.
+    If that module itself has children, they are also unloaded.  It is
+    like <function>UnloadModule()</function>, except that it is safe to use
+    for unloading child modules.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    pointer LoaderSymbol(const char *symbol);
+	  </programlisting>
+	<blockquote><para>
+    This function returns the address of the symbol with name
+    <parameter>symbol</parameter>.  This may be used to locate a module entry
+    point with a known name.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    char **LoaderlistDirs(const char **subdirlist,
+                          const char **patternlist);
+	  </programlisting>
+	  <blockquote><para>
+    This function returns a <constant>NULL</constant> terminated list of
+    canonical modules names for modules found in the default module
+    search path.  The <parameter>subdirlist</parameter> and
+    <parameter>patternlist</parameter> parameters are as described above, and
+    can be used to control the locations and names that are searched.
+    If no modules are found, the return value is <constant>NULL</constant>.
+    The returned list should be freed by calling
+    <function>LoaderFreeDirList()</function> when it is no longer needed.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void LoaderFreeDirList(char **list);
+	  </programlisting>
+	  <blockquote><para>
+    This function frees a module list created by
+    <function>LoaderlistDirs()</function>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void LoaderReqSymLists(const char **list0, ...);
+	  </programlisting>
+	  <blockquote><para>
+    This function allows the registration of required symbols with the
+    loader.  It is normally used by a caller of
+    <function>LoadSubModule()</function>.  If any symbols registered in this
+    way are found to be unresolved when
+    <function>LoaderCheckUnresolved()</function> is called then
+    <function>LoaderCheckUnresolved()</function> will report a failure.
+    The function takes one or more <constant>NULL</constant> terminated
+    lists of symbols.  The end of the argument list is indicated by a
+    <constant>NULL</constant> argument.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void LoaderReqSymbols(const char *sym0, ...);
+	  </programlisting>
+	<blockquote><para>
+    This function is like <function>LoaderReqSymLists()</function> except
+    that its arguments are symbols rather than lists of symbols.  This
+    function is more convenient when single functions are to be registered,
+    especially when the single function might depend on runtime factors.
+    The end of the argument list is indicated by a <constant>NULL</constant>
+    argument.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void LoaderRefSymLists(const char **list0, ...);
+	  </programlisting>
+	  <blockquote><para>
+    This function allows the registration of possibly unresolved symbols
+    with the loader.  When <function>LoaderCheckUnresolved()</function> is
+    run it won't generate warnings for symbols registered in this way
+    unless they were also registered as required symbols.
+    The function takes one or more <constant>NULL</constant> terminated
+    lists of symbols.  The end of the argument list is indicated by a
+    <constant>NULL</constant> argument.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void LoaderRefSymbols(const char *sym0, ...);
+	  </programlisting>
+	  <blockquote><para>
+    This function is like <function>LoaderRefSymLists()</function> except
+    that its arguments are symbols rather than lists of symbols.  This
+    function is more convenient when single functions are to be registered,
+    especially when the single function might depend on runtime factors.
+    The end of the argument list is indicated by a <constant>NULL</constant>
+    argument.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    int LoaderCheckUnresolved(int delayflag);
+	  </programlisting>
+	  <blockquote><para>
+    This function checks for unresolved symbols.  It generates warnings
+    for unresolved symbols that have not been registered with
+    <function>LoaderRefSymLists()</function>, and maps them to a dummy
+    function.  This behaviour may change in future.  If unresolved
+    symbols are found that have been registered with
+    <function>LoaderReqSymLists()</function> or
+    <function>LoaderReqSymbols()</function> then this function returns a
+    non-zero value.  If none of these symbols are unresolved the return
+    value is zero, indicating success.
+	    </para>
+
+	    <para>
+    The <parameter>delayflag</parameter> parameter should normally be set to
+    <constant>LD_RESOLV_IFDONE</constant>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    LoaderErrorMsg(const char *name, const char *modname,
+                   int errmaj, int errmin);
+	  </programlisting>
+	  <blockquote><para>
+    This function prints an error message that includes the text ``Failed
+    to load module'', the module name <parameter>modname</parameter>, a message
+    specific to the <parameter>errmaj</parameter> value, and the value if
+    <parameter>errmin</parameter>.  If <parameter>name</parameter> is
+    non-<constant>NULL</constant>, it is printed as an identifying prefix
+    to the message (followed by a `:').
+	    </para>
+
+	  </blockquote></para></blockquote>
+    </sect2>
+
+    <sect2>
+      <title>Special Registration Functions</title>
+
+      <para>
+The loader contains some functions for registering some classes of modules.
+These may be moved out of the loader at some point.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    void LoadExtension(ExtensionModule *ext);
+	  </programlisting>
+	  <blockquote><para>
+    This registers the entry points for the extension identified by
+    <parameter>ext</parameter>.  The <structname>ExtensionModule</structname> struct is
+    defined as:
+
+	      <programlisting>
+typedef struct {
+    InitExtension       initFunc;
+    char *              name;
+    Bool                *disablePtr;
+    InitExtension       setupFunc;
+} ExtensionModule;
+	      </programlisting>
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void LoadFont(FontModule *font);
+	  </programlisting>
+	  <blockquote><para>
+    This registers the entry points for the font rasteriser module
+    identified by <parameter>font</parameter>.  The <structname>FontModule</structname>
+    struct is defined as:
+
+	      <programlisting>
+ typedef struct {
+    InitFont    initFunc;
+    char *      name;
+    pointer     module;
+} FontModule;
+	      </programlisting>
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+    </sect2>
+
+  </sect1>
+
+  <sect1>
+    <title>Helper Functions</title>
+
+    <para>
+This section describe ``helper'' functions that video driver
+might find useful.  While video drivers are not required to use any of
+these to be considered ``compliant'', the use of appropriate helpers is
+strongly encouraged to improve the consistency of driver behaviour.
+    </para>
+
+    <sect2>
+      <title>Functions for printing messages</title>
+
+      <blockquote><para>
+	  <programlisting>
+    ErrorF(const char *format, ...);
+	  </programlisting>
+	  <blockquote><para>
+      This is the basic function for writing to the error log (typically
+      stderr and/or a log file).  Video drivers should usually avoid
+      using this directly in favour of the more specialised functions
+      described below.  This function is useful for printing messages
+      while debugging a driver.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    FatalError(const char *format, ...);
+	  </programlisting>
+	  <blockquote><para>
+      This prints a message and causes the Xserver to abort.  It should
+      rarely be used within a video driver, as most error conditions
+      should be flagged by the return values of the driver functions.
+      This allows the higher layers to decide how to proceed.  In rare
+      cases, this can be used within a driver if a fatal unexpected
+      condition is found.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    xf86ErrorF(const char *format, ...);
+	  </programlisting>
+	  <blockquote><para>
+      This is like <function>ErrorF()</function>, except that the message is
+      only printed when the Xserver's verbosity level is set to the
+      default (<constant>1</constant>) or higher.  It means that the messages
+      are not printed when the server is started with the
+      <option>-quiet</option> flag.  Typically this function would only be
+      used for continuing messages started with one of the more specialised
+      functions described below.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    xf86ErrorFVerb(int verb, const char *format, ...);
+	  </programlisting>
+	  <blockquote><para>
+      Like <function>xf86ErrorF()</function>, except the minimum verbosity
+      level for which the message is to be printed is given explicitly.
+      Passing a <parameter>verb</parameter> value of zero means the message
+      is always printed.  A value higher than <constant>1</constant> can be
+      used for information would normally not be needed, but which might
+      be useful when diagnosing problems.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+
+      <blockquote><para>
+	  <programlisting>
+    xf86Msg(MessageType type, const char *format, ...);
+	  </programlisting>
+	  <blockquote><para>
+      This is like <function>xf86ErrorF()</function>, except that the message
+      is prefixed with a marker determined by the value of
+      <parameter>type</parameter>.  The marker is used to indicate the type of
+      message (warning, error, probed value, config value, etc).  Note
+      the <varname>xf86Verbose</varname> value is ignored for messages of
+      type <constant>X_ERROR</constant>.
+	    </para>
+
+	    <para>
+      The marker values are:
+
+	      <variablelist>
+		<varlistentry>
+		  <term><constant>X_PROBED</constant></term>
+		  <listitem><para>Value was probed.
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><constant>X_CONFIG</constant></term>
+		  <listitem><para>Value was given in the config file.
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><constant>X_DEFAULT</constant></term>
+		  <listitem><para>Value is a default.
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><constant>X_CMDLINE</constant></term>
+		  <listitem><para>Value was given on the command line.
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><constant>X_NOTICE</constant></term>
+		  <listitem><para>Notice.
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><constant>X_ERROR</constant></term>
+		  <listitem><para>Error message.
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><constant>X_WARNING</constant></term>
+		  <listitem><para>Warning message.
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><constant>X_INFO</constant></term>
+		  <listitem><para>Informational message.
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><constant>X_NONE</constant></term>
+		  <listitem><para>No prefix.
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><constant>X_NOT_IMPLEMENTED</constant></term>
+		  <listitem><para>The message relates to functionality
+		      that is not yetimplemented.
+		    </para></listitem></varlistentry>
+		</variablelist>
+
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    xf86MsgVerb(MessageType type, int verb, const char *format, ...);
+	  </programlisting>
+	  <blockquote><para>
+      Like <function>xf86Msg()</function>, but with the verbosity level given
+      explicitly.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...);
+	  </programlisting>
+	  <blockquote><para>
+      This is like <function>xf86Msg()</function> except that the driver's
+      name (the <structfield>name</structfield> field of the
+      <structname>ScrnInfoRec</structname>) followed by the
+      <parameter>scrnIndex</parameter> in parentheses is printed following the
+      prefix.  This should be used by video drivers in most cases as it
+      clearly indicates which driver/screen the message is for.  If
+      <parameter>scrnIndex</parameter> is negative, this function behaves
+      exactly like <function>xf86Msg()</function>.
+	    </para>
+
+	    <para>
+      NOTE: This function can only be used after the
+      <structname>ScrnInfoRec</structname> and its <structfield>name</structfield> field
+      have been allocated.  Normally, this means that it can not be
+      used before the END of the <function>ChipProbe()</function> function.
+      Prior to that, use <function>xf86Msg()</function>, providing the
+      driver's name explicitly.  No screen number can be supplied at
+      that point.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    xf86DrvMsgVerb(int scrnIndex, MessageType type, int verb,
+                                const char *format, ...);
+	  </programlisting>
+	  <blockquote><para>
+      Like <function>xf86DrvMsg()</function>, but with the verbosity level
+      given explicitly.
+	    </para>
+
+	  </blockquote></para></blockquote>
+    </sect2>
+
+
+    <sect2>
+      <title>Functions for setting values based on command line and config file</title>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int bpp,
+
+                                int fbbpp, int depth24flags);
+	  </programlisting>
+	  <blockquote><para>
+      This function sets the <structfield>depth</structfield>, <structfield>pixmapBPP</structfield> and <structfield>bitsPerPixel</structfield> fields
+      of the <structname>ScrnInfoRec</structname>.  It also determines the defaults for display-wide
+      attributes and pixmap formats the screen will support, and finds
+      the Display subsection that matches the depth/bpp.  This function
+      should normally be called very early from the
+      <function>ChipPreInit()</function> function.
+	    </para>
+
+	    <para>
+      It requires that the <structfield>confScreen</structfield> field of the <structname>ScrnInfoRec</structname> be
+      initialised prior to calling it.  This is done by the XFree86
+      common layer prior to calling <function>ChipPreInit()</function>.
+	    </para>
+
+	    <para>
+      The parameters passed are:
+
+	      <variablelist>
+		<varlistentry>
+		  <term><parameter>depth</parameter></term>
+		  <listitem><para>
+		driver's preferred default depth if no other is given.
+                If zero, use the overall server default.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>bpp</parameter></term>
+		  <listitem><para>
+		Same, but for the pixmap bpp.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>fbbpp</parameter></term>
+		  <listitem><para>
+		Same, but for the framebuffer bpp.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>depth24flags</parameter></term>
+		  <listitem><para>
+		Flags that indicate the level of 24/32bpp support
+                and whether conversion between different framebuffer
+                and pixmap formats is supported.  The flags for this
+                argument are defined as follows, and multiple flags
+                may be ORed together:
+
+		      <variablelist>
+			<varlistentry>
+			  <term><constant>NoDepth24Support</constant></term>
+			  <listitem><para>No depth 24 formats supported
+			    </para></listitem></varlistentry>
+			<varlistentry>
+			  <term><constant>Support24bppFb</constant></term>
+			  <listitem><para>24bpp framebuffer supported
+			    </para></listitem></varlistentry>
+			<varlistentry>
+			  <term><constant>Support32bppFb</constant></term>
+			  <listitem><para>32bpp framebuffer supported
+			    </para></listitem></varlistentry>
+			<varlistentry>
+			  <term><constant>SupportConvert24to32</constant></term>
+			  <listitem><para>Can convert 24bpp pixmap to 32bpp fb
+			    </para></listitem></varlistentry>
+			<varlistentry>
+			  <term><constant>SupportConvert32to24</constant></term>
+			  <listitem><para>Can convert 32bpp pixmap to 24bpp fb
+			    </para></listitem></varlistentry>
+			<varlistentry>
+			  <term><constant>ForceConvert24to32</constant></term>
+			  <listitem><para>Force 24bpp pixmap to 32bpp fb conversion
+			    </para></listitem></varlistentry>
+			<varlistentry>
+			  <term><constant>ForceConvert32to24</constant></term>
+			  <listitem><para>Force 32bpp pixmap to 24bpp fb conversion
+			    </para></listitem></varlistentry>
+		      </variablelist>
+		    </para></listitem></varlistentry>
+
+	      </variablelist>
+	    </para>
+
+	    <para>
+      It uses the command line, config file, and default values in the
+      correct order of precedence to determine the depth and bpp values.
+      It is up to the driver to check the results to see that it supports
+      them.  If not the <function>ChipPreInit()</function> function should
+      return <constant>FALSE</constant>.
+	    </para>
+
+	    <para>
+      If only one of depth/bpp is given, the other is set to a reasonable
+      (and consistent) default.
+	    </para>
+
+	    <para>
+      If a driver finds that the initial <parameter>depth24flags</parameter>
+      it uses later results in a fb format that requires more video
+      memory than is available it may call this function a second time
+      with a different <parameter>depth24flags</parameter> setting.
+	    </para>
+
+	    <para>
+      On success, the return value is <constant>TRUE</constant>.  On failure
+      it prints an error message and returns <constant>FALSE</constant>.
+	    </para>
+
+	    <para>
+      The following fields of the <structname>ScrnInfoRec</structname> are
+      initialised by this function:
+
+	      <blockquote><para>
+<structfield>depth</structfield>, <structfield>bitsPerPixel</structfield>,
+<structfield>display</structfield>, <structfield>imageByteOrder</structfield>,
+<structfield>bitmapScanlinePad</structfield>,
+<structfield>bitmapScanlineUnit</structfield>, <structfield>bitmapBitOrder</structfield>,
+<structfield>numFormats</structfield>, <structfield>formats</structfield>,
+<structfield>fbFormat</structfield>.
+		</para></blockquote>
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void xf86PrintDepthBpp(scrnInfoPtr scrp);
+	  </programlisting>
+	  <blockquote><para>
+      This function can be used to print out the depth and bpp settings.
+      It should be called after the final call to
+      <function>xf86SetDepthBpp()</function>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool xf86SetWeight(ScrnInfoPtr scrp, rgb weight, rgb mask);
+	  </programlisting>
+	  <blockquote><para>
+      This function sets the <structfield>weight</structfield>, <structfield>mask</structfield>,
+      <structfield>offset</structfield> and <structfield>rgbBits</structfield> fields of the
+      <structname>ScrnInfoRec</structname>.  It would normally be called fairly
+      early in the <function>ChipPreInit()</function> function for
+      depths&nbsp;&gt;&nbsp;8bpp.
+	    </para>
+
+	    <para>
+      It requires that the <structfield>depth</structfield> and
+      <structfield>display</structfield> fields of the <structname>ScrnInfoRec</structname>
+      be initialised prior to calling it.
+	    </para>
+
+	    <para>
+      The parameters passed are:
+
+	      <variablelist>
+		<varlistentry>
+		  <term><parameter>weight</parameter></term>
+		  <listitem><para>
+		driver's preferred default weight if no other is given.
+                If zero, use the overall server default.
+
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>mask</parameter></term>
+		  <listitem><para>
+		Same, but for mask.
+
+		    </para></listitem></varlistentry>
+	      </variablelist>
+	    </para>
+
+	    <para>
+      It uses the command line, config file, and default values in the
+      correct order of precedence to determine the weight value.  It
+      derives the mask and offset values from the weight and the defaults.
+      It is up to the driver to check the results to see that it supports
+      them.  If not the <function>ChipPreInit()</function> function should
+      return <constant>FALSE</constant>.
+	    </para>
+
+	    <para>
+      On success, this function prints a message showing the weight
+      values selected, and returns <constant>TRUE</constant>.
+	    </para>
+
+	    <para>
+      On failure it prints an error message and returns <constant>FALSE</constant>.
+	    </para>
+
+	    <para>
+      The following fields of the <structname>ScrnInfoRec</structname> are
+      initialised by this function:
+
+	      <blockquote><para>
+		  <structfield>weight</structfield>,
+		  <structfield>mask</structfield>,
+		  <structfield>offset</structfield>.
+		</para></blockquote>
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool xf86SetDefaultVisual(ScrnInfoPtr scrp, int visual);
+	  </programlisting>
+	  <blockquote><para>
+      This function sets the <structfield>defaultVisual</structfield> field of the
+      <structname>ScrnInfoRec</structname>.  It would normally be called fairly
+      early from the <function>ChipPreInit()</function> function.
+	    </para>
+
+	    <para>
+      It requires that the <structfield>depth</structfield> and
+      <structfield>display</structfield> fields of the <structname>ScrnInfoRec</structname>
+      be initialised prior to calling it.
+	    </para>
+
+	    <para>
+      The parameters passed are:
+
+	      <variablelist>
+		<varlistentry>
+		  <term><parameter>visual</parameter></term>
+		  <listitem><para>
+		driver's preferred default visual if no other is given.
+		If <constant>-1</constant>, use the overall server default.
+		    </para></listitem></varlistentry>
+
+	      </variablelist>
+	    </para>
+
+	    <para>
+      It uses the command line, config file, and default values in the
+      correct order of precedence to determine the default visual value.
+      It is up to the driver to check the result to see that it supports
+      it.  If not the <function>ChipPreInit()</function> function should
+      return <constant>FALSE</constant>.
+	    </para>
+
+	    <para>
+      On success, this function prints a message showing the default visual
+      selected, and returns <constant>TRUE</constant>.
+	    </para>
+
+	    <para>
+      On failure it prints an error message and returns <constant>FALSE</constant>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool xf86SetGamma(ScrnInfoPtr scrp, Gamma gamma);
+	  </programlisting>
+	  <blockquote><para>
+      This function sets the <structfield>gamma</structfield> field of the
+      <structname>ScrnInfoRec</structname>.  It would normally be called fairly
+      early from the <function>ChipPreInit()</function> function in cases
+      where the driver supports gamma correction.
+	    </para>
+
+	    <para>
+      It requires that the <structfield>monitor</structfield> field of the
+      <structname>ScrnInfoRec</structname> be initialised prior to calling it.
+	    </para>
+
+	    <para>
+      The parameters passed are:
+
+	      <variablelist>
+		<varlistentry>
+		  <term><parameter>gamma</parameter></term>
+		  <listitem><para>
+		driver's preferred default gamma if no other is given.
+		If zero (<code>&lt; 0.01</code>), use the overall server
+		default.
+		    </para></listitem></varlistentry>
+
+	      </variablelist>
+	    </para>
+
+	    <para>
+      It uses the command line, config file, and default values in the
+      correct order of precedence to determine the gamma value.  It is
+      up to the driver to check the results to see that it supports
+      them.  If not the <function>ChipPreInit()</function> function should
+      return <constant>FALSE</constant>.
+	    </para>
+
+	    <para>
+      On success, this function prints a message showing the gamma
+      value selected, and returns <constant>TRUE</constant>.
+	    </para>
+
+	    <para>
+      On failure it prints an error message and returns <constant>FALSE</constant>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+
+      <blockquote><para>
+	  <programlisting>
+    void xf86SetDpi(ScrnInfoPtr pScrn, int x, int y);
+	  </programlisting>
+	  <blockquote><para>
+      This function sets the <structfield>xDpi</structfield> and <structfield>yDpi</structfield>
+      fields of the <structname>ScrnInfoRec</structname>.  The driver can specify
+      preferred defaults by setting <parameter>x</parameter> and <parameter>y</parameter>
+      to non-zero values.  The <option>-dpi</option> command line option
+      overrides all other settings.  Otherwise, if the
+      <emphasis>DisplaySize</emphasis> entry is present in the screen's &k.monitor;
+      config file section, it is used together with the virtual size to
+      calculate the dpi values.  This function should be called after
+      all the mode resolution has been done.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void xf86SetBlackWhitePixels(ScrnInfoPtr pScrn);
+	  </programlisting>
+	  <blockquote><para>
+      This functions sets the <structfield>blackPixel</structfield> and
+      <structfield>whitePixel</structfield> fields of the <structname>ScrnInfoRec</structname>
+      according to whether or not the <option>-flipPixels</option> command
+      line options is present.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    const char *xf86GetVisualName(int visual);
+	  </programlisting>
+	  <blockquote><para>
+      Returns a printable string with the visual name matching the
+      numerical visual class provided.  If the value is outside the
+      range of valid visual classes, <constant>NULL</constant> is returned.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+    </sect2>
+
+    <sect2>
+      <title>Primary Mode functions</title>
+
+      <para>
+The primary mode helper functions are those which would normally be
+used by a driver, unless it has unusual requirements which cannot
+be catered for the by the helpers.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    int xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes,
+                          char **modeNames, ClockRangePtr clockRanges,
+                          int *linePitches, int minPitch, int maxPitch,
+                          int pitchInc, int minHeight, int maxHeight,
+                          int virtualX, int virtualY,
+                          unsigned long apertureSize,
+                          LookupModeFlags strategy);
+	  </programlisting>
+	  <blockquote><para>
+      This function basically selects the set of modes to use based on
+      those available and the various constraints.  It also sets some
+      other related parameters.  It is normally called near the end of
+      the <function>ChipPreInit()</function> function.
+	    </para>
+
+	    <para>
+      The parameters passed to the function are:
+
+	      <variablelist>
+		<varlistentry>
+		  <term><parameter>availModes</parameter></term>
+		  <listitem><para>
+		List of modes available for the monitor.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>modeNames</parameter></term>
+		  <listitem><para>
+		List of mode names that the screen is requesting.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>clockRanges</parameter></term>
+		  <listitem><para>
+		A list of clock ranges allowed by the driver.  Each
+		range includes whether interlaced or multiscan modes
+		are supported for that range.  See below for more on
+		<parameter>clockRanges</parameter>.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>linePitches</parameter></term>
+		  <listitem><para>
+		List of line pitches supported by the driver.
+		This is optional and should be <constant>NULL</constant> when
+		not used.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>minPitch</parameter></term>
+		  <listitem><para>
+		Minimum line pitch supported by the driver.  This must
+		be supplied when <parameter>linePitches</parameter> is
+		<constant>NULL</constant>, and is ignored otherwise.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>maxPitch</parameter></term>
+		  <listitem><para>
+		Maximum line pitch supported by the driver.  This is
+		required when <parameter>minPitch</parameter> is required.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>pitchInc</parameter></term>
+		  <listitem><para>
+		Granularity of horizontal pitch values as supported by
+		the chipset.  This is expressed in bits.  This must be
+		supplied.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>minHeight</parameter></term>
+		  <listitem><para>
+		minimum virtual height allowed.  If zero, no limit is
+		imposed.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>maxHeight</parameter></term>
+		  <listitem><para>
+		maximum virtual height allowed.  If zero, no limit is
+		imposed.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>virtualX</parameter></term>
+		  <listitem><para>
+		If greater than zero, this is the virtual width value
+		that will be used.  Otherwise, the virtual width is
+		chosen to be the smallest that can accommodate the modes
+		selected.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>virtualY</parameter></term>
+		  <listitem><para>
+		If greater than zero, this is the virtual height value
+		that will be used.  Otherwise, the virtual height is
+		chosen to be the smallest that can accommodate the modes
+		selected.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>apertureSize</parameter></term>
+		  <listitem><para>
+		The size (in bytes) of the aperture used to access video
+		memory.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><parameter>strategy</parameter></term>
+		  <listitem><para>
+		The strategy to use when choosing from multiple modes
+		with the same name.  The options are:
+
+		      <variablelist>
+			<varlistentry>
+			  <term><constant>LOOKUP_DEFAULT</constant></term>
+			  <listitem><para>???
+			    </para></listitem></varlistentry>
+			<varlistentry>
+			  <term><constant>LOOKUP_BEST_REFRESH</constant></term>
+			  <listitem><para>mode with best refresh rate
+			    </para></listitem></varlistentry>
+			<varlistentry>
+			  <term><constant>LOOKUP_CLOSEST_CLOCK</constant></term>
+			  <listitem><para>mode with closest matching clock
+			    </para></listitem></varlistentry>
+			<varlistentry>
+			  <term><constant>LOOKUP_LIST_ORDER</constant></term>
+			  <listitem><para>first usable mode in list
+			    </para></listitem></varlistentry>
+		      </variablelist>
+
+		The following options can also be combined (OR'ed) with
+		one of the above:
+
+		      <variablelist>
+			<varlistentry>
+			  <term><constant>LOOKUP_CLKDIV2</constant></term>
+			  <listitem><para>Allow halved clocks
+			    </para></listitem></varlistentry>
+			<varlistentry>
+			  <term><constant>LOOKUP_OPTIONAL_TOLERANCES</constant></term>
+			  <listitem><para>
+		      Allow missing horizontal sync and/or vertical refresh
+		      ranges in the xorg.conf Monitor section
+			    </para></listitem></varlistentry>
+		      </variablelist>
+
+		<constant>LOOKUP_OPTIONAL_TOLERANCES</constant> should only be
+		specified when the driver can ensure all modes it generates
+		can sync on, or at least not damage, the monitor or digital
+		flat panel.  Horizontal sync and/or vertical refresh ranges
+		specified by the user will still be honoured (and acted upon).
+
+		    </para></listitem></varlistentry>
+	      </variablelist>
+	    </para>
+
+	    <para>
+      This function requires that the following fields of the
+      <structname>ScrnInfoRec</structname> are initialised prior to calling it:
+
+	      <variablelist>
+		<varlistentry>
+		  <term><structfield>clock[]</structfield></term>
+		  <listitem><para>
+		      List of discrete clocks (when non-programmable)
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><structfield>numClocks</structfield></term>
+		  <listitem><para>
+		      Number of discrete clocks (when non-programmable)
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><structfield>progClock</structfield></term>
+		  <listitem><para>
+		      Whether the clock is programmable or not
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><structfield>monitor</structfield></term>
+		  <listitem><para>
+		      Pointer to the applicable xorg.conf monitor section
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><structfield>fdFormat</structfield></term>
+		  <listitem><para>
+		      Format of the screen buffer
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><structfield>videoRam</structfield></term>
+		  <listitem><para>
+		      total video memory size (in bytes)
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><structfield>maxHValue</structfield></term>
+		  <listitem><para>
+		      Maximum horizontal timing value allowed
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><structfield>maxVValue</structfield></term>
+		  <listitem><para>
+		      Maximum vertical timing value allowed
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><structfield>xInc</structfield></term>
+		  <listitem><para>
+		      Horizontal timing increment in pixels (defaults to 8)
+		    </para></listitem></varlistentry>
+	      </variablelist>
+	    </para>
+
+	    <para>
+      This function fills in the following <structname>ScrnInfoRec</structname>
+      fields:
+
+	      <variablelist>
+		<varlistentry>
+		  <term><structfield>modePool</structfield></term>
+		  <listitem><para>
+		A subset of the modes available to the monitor which
+                are compatible with the driver.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><structfield>modes</structfield></term>
+		  <listitem><para>
+		One mode entry for each of the requested modes, with
+                the status field of each filled in to indicate if
+                the mode has been accepted or not.  This list of
+                modes is a circular list.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><structfield>virtualX</structfield></term>
+		  <listitem><para>
+		The resulting virtual width.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><structfield>virtualY</structfield></term>
+		  <listitem><para>
+		The resulting virtual height.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><structfield>displayWidth</structfield></term>
+		  <listitem><para>
+		The resulting line pitch.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><structfield>virtualFrom</structfield></term>
+		  <listitem><para>
+		Where the virtual size was determined from.
+		    </para></listitem></varlistentry>
+
+	      </variablelist>
+	    </para>
+
+	    <para>
+      The first stage of this function checks that the
+      <parameter>virtualX</parameter> and <parameter>virtualY</parameter> values
+      supplied (if greater than zero) are consistent with the line pitch
+      and <parameter>maxHeight</parameter> limitations.  If not, an error
+      message is printed, and the return value is <constant>-1</constant>.
+	    </para>
+
+	    <para>
+      The second stage sets up the mode pool, eliminating immediately
+      any modes that exceed the driver's line pitch limits, and also
+      the virtual width and height limits (if greater than zero).  For
+      each mode removed an informational message is printed at verbosity
+      level <constant>2</constant>.  If the mode pool ends up being empty,
+      a warning message is printed, and the return value is
+      <constant>0</constant>.
+	    </para>
+
+	    <para>
+      The final stage is to lookup each mode name, and fill in the remaining
+      parameters.  If an error condition is encountered, a message is
+      printed, and the return value is <constant>-1</constant>.  Otherwise,
+      the return value is the number of valid modes found
+      (<constant>0</constant> if none are found).
+	    </para>
+
+	    <para>
+      Even if the supplied mode names include duplicates, no two names will
+      ever match the same mode.  Furthermore, if the supplied mode names do not
+      yield a valid mode (including the case where no names are passed at all),
+      the function will continue looking through the mode pool until it finds
+      a mode that survives all checks, or until the mode pool is exhausted.
+	    </para>
+
+	    <para>
+      A message is only printed by this function when a fundamental
+      problem is found.  It is intended that this function may be called
+      more than once if there is more than one set of constraints that
+      the driver can work within.
+	    </para>
+
+	    <para>
+      If this function returns <constant>-1</constant>, the
+      <function>ChipPreInit()</function> function should return
+      <constant>FALSE</constant>.
+	    </para>
+
+	    <para>
+      <parameter>clockRanges</parameter> is a linked list of clock ranges
+      allowed by the driver.  If a mode doesn't fit in any of the defined
+      <parameter>clockRanges</parameter>, it is rejected.  The first
+      <literal remap="tt">clockRange</literal> that matches all requirements is used.
+      This structure needs to be initialized to NULL when allocated.
+	    </para>
+
+	    <para>
+      <parameter>clockRanges</parameter> contains the following fields:
+
+	      <variablelist>
+		<varlistentry>
+		  <term><structfield>minClock</structfield></term>
+		  <term><structfield>maxClock</structfield></term>
+		  <listitem><para>
+		The lower and upper mode clock bounds for which the rest
+		of the <structname>clockRange</structname> parameters apply.
+		Since these are the mode clocks, they are not scaled
+		with the <structfield>ClockMulFactor</structfield> and
+		<structfield>ClockDivFactor</structfield>.  It is up to the driver
+		to adjust these values if they depend on the clock
+		scaling factors.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><structfield>clockIndex</structfield></term>
+		  <listitem><para>
+		(not used yet) <constant>-1</constant> for programmable clocks
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><structfield>interlaceAllowed</structfield></term>
+		  <listitem><para>
+		<constant>TRUE</constant> if interlacing is allowed for this
+		range
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><structfield>doubleScanAllowed</structfield></term>
+		  <listitem><para>
+		<constant>TRUE</constant> if doublescan or multiscan is allowed
+		for this range
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><structfield>ClockMulFactor</structfield></term>
+		  <term><structfield>ClockDivFactor</structfield></term>
+		  <listitem><para>
+		Scaling factors that are applied to the mode clocks ONLY
+		before selecting a clock index (when there is no
+		programmable clock) or a <structfield>SynthClock</structfield>
+		value.  This is useful for drivers that support pixel
+		multiplexing or that need to scale the clocks because
+		of hardware restrictions (like sending 24bpp data to an
+		8 bit RAMDAC using a tripled clock).
+		    </para>
+
+		    <para>
+		Note that these parameters describe what must be done
+		to the mode clock to achieve the data transport clock
+		between graphics controller and RAMDAC.  For example
+		for <literal remap="tt">2:1</literal> pixel multiplexing, two pixels
+		are sent to the RAMDAC on each clock.  This allows the
+		RAMDAC clock to be half of the actual pixel clock.
+		Hence, <code>ClockMulFactor=1</code> and
+		<code>ClockDivFactor=2</code>.  This means that the
+		clock used for clock selection (ie, determining the
+		correct clock index from the list of discrete clocks)
+		or for the <structfield>SynthClock</structfield> field in case of
+		a programmable clock is:  (<code>mode-&gt;Clock *
+		ClockMulFactor) / ClockDivFactor</code>.
+		    </para></listitem></varlistentry>
+
+		<varlistentry>
+		  <term><structfield>PrivFlags</structfield></term>
+		  <listitem><para>
+		This field is copied into the
+		<literal remap="tt">mode-&gt;PrivFlags</literal> field when this
+		<literal remap="tt">clockRange</literal> is selected by
+		<function>xf86ValidateModes()</function>.  It allows the
+		driver to find out what clock range was selected, so it
+		knows it needs to set up pixel multiplexing or any other
+		range-dependent feature.  This field is purely
+		driver-defined: it may contain flag bits, an index or
+		anything else (as long as it is an <literal remap="tt">INT</literal>).
+		    </para></listitem></varlistentry>
+	      </variablelist>
+	    </para>
+
+	    <para>
+      Note that the <structfield>mode-&gt;SynthClock</structfield> field is always
+      filled in by <function>xf86ValidateModes()</function>: it will contain
+      the ``data transport clock'', which is the clock that will have
+      to be programmed in the chip when it has a programmable clock, or
+      the clock that will be picked from the clocks list when it is not
+      a programmable one.  Thus:
+
+	      <programlisting>
+    mode-&gt;SynthClock = (mode-&gt;Clock * ClockMulFactor) / ClockDivFactor
+	      </programlisting>
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void xf86PruneDriverModes(ScrnInfoPtr scrp);
+	  </programlisting>
+	  <blockquote><para>
+      This function deletes modes in the modes field of the
+      <structname>ScrnInfoRec</structname> that have been marked as invalid.
+      This is normally run after having run
+      <function>xf86ValidateModes()</function> for the last time.  For each
+      mode that is deleted, a warning message is printed out indicating
+      the reason for it being deleted.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void xf86SetCrtcForModes(ScrnInfoPtr scrp, int adjustFlags);
+	  </programlisting>
+	  <blockquote><para>
+      This function fills in the <structname>Crtc*</structname> fields for all
+      the modes in the <structfield>modes</structfield> field of the
+      <structname>ScrnInfoRec</structname>.  The <parameter>adjustFlags</parameter>
+      parameter determines how the vertical CRTC values are scaled for
+      interlaced modes.  They are halved if it is
+      <constant>INTERLACE_HALVE_V</constant>.  The vertical CRTC values are
+      doubled for doublescan modes, and are further multiplied by the
+      <literal remap="tt">VScan</literal> value.
+	    </para>
+
+	    <para>
+      This function is normally called after calling
+      <function>xf86PruneDriverModes()</function>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void xf86PrintModes(ScrnInfoPtr scrp);
+	  </programlisting>
+	  <blockquote><para>
+      This function prints out the virtual size setting, and the line
+      pitch being used.  It also prints out two lines for each mode being
+      used.  The first line includes the mode's pixel clock, horizontal sync
+      rate, refresh rate, and whether it is interlaced, doublescanned and/or
+      multi-scanned.  The second line is the mode's Modeline.
+	    </para>
+
+	    <para>
+      This function is normally called after calling
+      <function>xf86SetCrtcForModes()</function>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+    </sect2>
+
+    <sect2>
+      <title>Secondary Mode functions</title>
+
+      <para>
+The secondary mode helper functions are functions which are normally
+used by the primary mode helper functions, and which are not normally
+called directly by a driver.  If a driver has unusual requirements
+and needs to do its own mode validation, it might be able to make
+use of some of these secondary mode helper functions.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    int xf86GetNearestClock(ScrnInfoPtr scrp, int freq, Bool allowDiv2,
+                            int *divider);
+	  </programlisting>
+	  <blockquote><para>
+      This function returns the index of the closest clock to the
+      frequency <parameter>freq</parameter> given (in kHz).  It assumes that
+      the number of clocks is greater than zero.  It requires that the
+      <structfield>numClocks</structfield> and <structfield>clock</structfield> fields of the
+      <structname>ScrnInfoRec</structname> are initialised.  The
+      <structfield>allowDiv2</structfield> field determines if the clocks can be
+      halved.  The <parameter>*divider</parameter> return value indicates
+      whether clock division is used when determining the clock returned.
+	    </para>
+
+	    <para>
+      This function is only for non-programmable clocks.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    const char *xf86ModeStatusToString(ModeStatus status);
+	  </programlisting>
+	  <blockquote><para>
+      This function converts the <parameter>status</parameter> value to a
+      descriptive printable string.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    ModeStatus xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep,
+                     ClockRangePtr clockRanges, LookupModeFlags strategy);
+	  </programlisting>
+	  <blockquote><para>
+      This function takes a pointer to a mode with the name filled in,
+      and looks for a mode in the <structfield>modePool</structfield> list which
+      matches.  The parameters of the matching mode are filled in to
+      <parameter>*modep</parameter>.  The <parameter>clockRanges</parameter> and
+      <parameter>strategy</parameter> parameters are as for the
+      <function>xf86ValidateModes()</function> function above.
+	    </para>
+
+	    <para>
+      This function requires the <structfield>modePool</structfield>,
+      <structfield>clock[]</structfield>, <structfield>numClocks</structfield> and
+      <structfield>progClock</structfield> fields of the <structname>ScrnInfoRec</structname>
+      to be initialised before being called.
+	    </para>
+
+	    <para>
+      The return value is <constant>MODE_OK</constant> if a mode was found.
+      Otherwise it indicates why a matching mode could not be found.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    ModeStatus xf86InitialCheckModeForDriver(ScrnInfoPtr scrp,
+                                DisplayModePtr mode, ClockRangePtr clockRanges,
+                                LookupModeFlags strategy, int maxPitch,
+                                int virtualX, int virtualY);
+	  </programlisting>
+	  <blockquote><para>
+      This function checks the passed mode against some basic driver
+      constraints.  Apart from the ones passed explicitly, the
+      <structfield>maxHValue</structfield> and <structfield>maxVValue</structfield> fields of
+      the <structname>ScrnInfoRec</structname> are also used.  If the
+      <structfield>ValidMode</structfield> field of the <structname>ScrnInfoRec</structname>
+      is set, that function is also called to check the mode.  Next, the
+      mode is checked against the monitor's constraints.
+	    </para>
+
+	    <para>
+      If the mode is consistent with all constraints, the return value
+      is <constant>MODE_OK</constant>.  Otherwise the return value indicates
+      which constraint wasn't met.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void xf86DeleteMode(DisplayModePtr *modeList, DisplayModePtr mode);
+	  </programlisting>
+	  <blockquote><para>
+      This function deletes the <parameter>mode</parameter> given from the
+      <parameter>modeList</parameter>.  It never prints any messages, so it is
+      up to the caller to print a message if required.
+	    </para>
+
+	  </blockquote></para></blockquote>
+    </sect2>
+
+    <sect2>
+      <title>Functions for handling strings and tokens</title>
+
+      <para>
+    Tables associating strings and numerical tokens combined with the
+    following functions provide a compact way of handling strings from
+    the config file, and for converting tokens into printable strings.
+    The table data structure is:
+
+	<programlisting>
+typedef struct {
+    int                 token;
+    const char *        name;
+} SymTabRec, *SymTabPtr;
+	</programlisting>
+      </para>
+
+      <para>
+    A table is an initialised array of <structname>SymTabRec</structname>.  The
+    tokens must be non-negative integers.  Multiple names may be mapped
+    to a single token.  The table is terminated with an element with a
+    <structfield>token</structfield> value of <constant>-1</constant> and
+    <constant>NULL</constant> for the <structfield>name</structfield>.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    const char *xf86TokenToString(SymTabPtr table, int token);
+	  </programlisting>
+	  <blockquote><para>
+      This function returns the first string in <parameter>table</parameter>
+      that matches <parameter>token</parameter>.  If no match is found,
+      <constant>NULL</constant> is returned (NOTE, older versions of this
+      function would return the string "unknown" when no match is found).
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    int xf86StringToToken(SymTabPtr table, const char *string);
+	  </programlisting>
+	  <blockquote><para>
+      This function returns the first token in <parameter>table</parameter>
+      that matches <parameter>string</parameter>.  The
+      <function>xf86NameCmp()</function> function is used to determine the
+      match.  If no match is found, <constant>-1</constant> is returned.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+    </sect2>
+
+    <sect2>
+      <title>Functions for finding which config file entries to use</title>
+
+      <para>
+    These functions can be used to select the appropriate config file
+    entries that match the detected hardware.  They are described above
+    in the <link linkend="probe">Probe</link> and
+    <link linkend="avail">Available Functions</link> sections.
+      </para>
+
+    </sect2>
+
+    <sect2>
+      <title>Probing discrete clocks on old hardware</title>
+
+      <para>
+    The <function>xf86GetClocks()</function> function may be used to assist
+    in finding the discrete pixel clock values on older hardware.
+      </para>
+
+      <blockquote><para>
+	  <programlisting>
+    void xf86GetClocks(ScrnInfoPtr pScrn, int num,
+                       Bool (*ClockFunc)(ScrnInfoPtr, int),
+                       void (*ProtectRegs)(ScrnInfoPtr, Bool),
+                       void (*BlankScreen)(ScrnInfoPtr, Bool),
+                       int vertsyncreg, int maskval, int knownclkindex,
+                       int knownclkvalue);
+	  </programlisting>
+	  <blockquote><para>
+      This function uses a comparative sampling method to measure the
+      discrete pixel clock values.  The number of discrete clocks to
+      measure is given by <parameter>num</parameter>.  <parameter>clockFunc</parameter>
+      is a function that selects the <parameter>n</parameter>'th clock.  It
+      should also save or restore any state affected by programming the
+      clocks when the index passed is <constant>CLK_REG_SAVE</constant> or
+      <constant>CLK_REG_RESTORE</constant>.  <parameter>ProtectRegs</parameter> is
+      a function that does whatever is required to protect the hardware
+      state while selecting a new clock.  <parameter>BlankScreen</parameter>
+      is a function that blanks the screen.  <parameter>vertsyncreg</parameter>
+      and <parameter>maskval</parameter> are the register and bitmask to
+      check for the presence of vertical sync pulses.
+      <parameter>knownclkindex</parameter> and <parameter>knownclkvalue</parameter>
+      are the index and value of a known clock.  These are the known
+      references on which the comparative measurements are based.  The
+      number of clocks probed is set in <structfield>pScrn-&gt;numClocks</structfield>,
+      and the probed clocks are set in the <structfield>pScrn-&gt;clock[]</structfield>
+      array.  All of the clock values are in units of kHz.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void xf86ShowClocks(ScrnInfoPtr scrp, MessageType from);
+	  </programlisting>
+	  <blockquote><para>
+      Print out the pixel clocks <parameter>scrp-&gt;clock[]</parameter>.
+      <parameter>from</parameter> indicates whether the clocks were probed
+      or from the config file.
+	    </para>
+
+	  </blockquote></para></blockquote>
+    </sect2>
+
+    <sect2>
+      <title>Other helper functions</title>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool xf86IsUnblank(int mode);
+	  </programlisting>
+	  <blockquote><para>
+      Returns <constant>TRUE</constant> when the screen saver mode specified
+      by <parameter>mode</parameter> requires the screen be unblanked,
+      and <constant>FALSE</constant> otherwise.  The screen saver modes that
+      require blanking are <constant>SCREEN_SAVER_ON</constant> and
+      <constant>SCREEN_SAVER_CYCLE</constant>, and the screen saver modes that
+      require unblanking are <constant>SCREEN_SAVER_OFF</constant> and
+      <constant>SCREEN_SAVER_FORCER</constant>.  Drivers may call this helper
+      from their <function>SaveScreen()</function> function to interpret the
+      screen saver modes.
+	    </para>
+
+	  </blockquote></para></blockquote>
+    </sect2>
+  </sect1>
+
+  <sect1>
+    <title>The vgahw module</title>
+
+    <para>
+The vgahw modules provides an interface for saving, restoring and
+programming the standard VGA registers, and for handling VGA colourmaps.
+    </para>
+
+    <sect2>
+      <title>Data Structures</title>
+
+      <para>
+    The public data structures used by the vgahw module are
+    <structname>vgaRegRec</structname> and <structname>vgaHWRec</structname>.  They are
+    defined in <filename>vgaHW.h.</filename>
+      </para>
+
+    </sect2>
+
+    <sect2>
+      <title>General vgahw Functions</title>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool vgaHWGetHWRec(ScrnInfoPtr pScrn);
+	  </programlisting>
+	  <blockquote><para>
+      This function allocates a <structname>vgaHWRec</structname> structure, and
+      hooks it into the <structname>ScrnInfoRec</structname>'s
+      <structfield>privates</structfield>.  Like all information hooked into the
+      <structfield>privates</structfield>, it is persistent, and only needs to be
+      allocated once per screen.  This function should normally be called
+      from the driver's <function>ChipPreInit()</function> function.  The
+      <structname>vgaHWRec</structname> is zero-allocated, and the following
+      fields are explicitly initialised:
+
+	      <variablelist>
+		<varlistentry>
+		  <term><structfield>ModeReg.DAC[]</structfield></term>
+		  <listitem><para>initialised with a default colourmap
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><structfield>ModeReg.Attribute[0x11]</structfield></term>
+		  <listitem><para>initialised with the default overscan index
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><structfield>ShowOverscan</structfield></term>
+		  <listitem><para>initialised according to the "ShowOverscan" option
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><structfield>paletteEnabled</structfield></term>
+		  <listitem><para>initialised to FALSE
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><structfield>cmapSaved</structfield></term>
+		  <listitem><para>initialised to FALSE
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><structfield>pScrn</structfield></term>
+		  <listitem><para>initialised to pScrn
+		    </para></listitem></varlistentry>
+	      </variablelist>
+	    </para>
+
+	    <para>
+      In addition to the above, <function>vgaHWSetStdFuncs()</function> is
+      called to initialise the register access function fields with the
+      standard VGA set of functions.
+	    </para>
+
+	    <para>
+      Once allocated, a pointer to the <structname>vgaHWRec</structname> can be
+      obtained from the <literal remap="tt">ScrnInfoPtr</literal> with the
+      <literal remap="tt">VGAHWPTR(pScrn)</literal> macro.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWFreeHWRec(ScrnInfoPtr pScrn);
+	  </programlisting>
+	  <blockquote><para>
+      This function frees a <structname>vgaHWRec</structname> structure.  It
+      should be called from a driver's <function>ChipFreeScreen()</function>
+      function.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool vgaHWSetRegCounts(ScrnInfoPtr pScrn, int numCRTC,
+                          int numSequencer, int numGraphics, int numAttribute);
+	  </programlisting>
+	  <blockquote><para>
+      This function allows the number of CRTC, Sequencer, Graphics and
+      Attribute registers to be changed.  This makes it possible for
+      extended registers to be saved and restored with
+      <function>vgaHWSave()</function> and <function>vgaHWRestore()</function>.
+      This function should be called after a <structname>vgaHWRec</structname>
+      has been allocated with <function>vgaHWGetHWRec()</function>.  The
+      default values are defined in <filename>vgaHW.h</filename> as follows:
+
+	      <programlisting>
+#define VGA_NUM_CRTC 25
+#define VGA_NUM_SEQ   5
+#define VGA_NUM_GFX   9
+#define VGA_NUM_ATTR 21
+	      </programlisting>
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool vgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src);
+	  </programlisting>
+	  <blockquote><para>
+      This function copies the contents of the VGA saved registers in
+      <parameter>src</parameter> to <parameter>dst</parameter>.  Note that it isn't
+      possible to simply do this with <function>memcpy()</function> (or
+      similar).  This function returns <constant>TRUE</constant> unless there
+      is a problem allocating space for the <structfield>CRTC</structfield> and
+      related fields in <parameter>dst</parameter>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWSetStdFuncs(vgaHWPtr hwp);
+	  </programlisting>
+	  <blockquote><para>
+      This function initialises the register access function fields of
+      <parameter>hwp</parameter> with the standard VGA set of functions.  This
+      is called by <function>vgaHWGetHWRec()</function>, so there is usually
+      no need to call this explicitly.  The register access functions
+      are described below.  If the registers are shadowed in some other
+      port I/O space (for example a PCI I/O region), these functions
+      can be used to access the shadowed registers if
+      <structfield>hwp-&gt;PIOOffset</structfield> is initialised with
+      <literal remap="tt">offset</literal>, calculated in such a way that when the
+      standard VGA I/O port value is added to it the correct offset into
+      the PIO area results.  This value is initialised to zero in
+      <function>vgaHWGetHWRec()</function>.  (Note: the PIOOffset functionality
+      is present in XFree86 4.1.0 and later.)
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWSetMmioFuncs(vgaHWPtr hwp, CARD8 *base, int offset);
+	  </programlisting>
+	  <blockquote><para>
+      This function initialised the register access function fields of
+      hwp with a generic MMIO set of functions.
+      <structfield>hwp-&gt;MMIOBase</structfield> is initialised with
+      <parameter>base</parameter>, which must be the virtual address that the
+      start of MMIO area is mapped to.  <structfield>hwp-&gt;MMIOOffset</structfield>
+      is initialised with <parameter>offset</parameter>, which must be calculated
+      in such a way that when the standard VGA I/O port value is added
+      to it the correct offset into the MMIO area results.  That means
+      that these functions are only suitable when the VGA I/O ports are
+      made available in a direct mapping to the MMIO space.  If that is
+      not the case, the driver will need to provide its own register
+      access functions.  The register access functions are described
+      below.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool vgaHWMapMem(ScrnInfoPtr pScrn);
+	  </programlisting>
+	  <blockquote><para>
+      This function maps the VGA memory window.  It requires that the
+      <structname>vgaHWRec</structname> be allocated.  If a driver requires
+      non-default <structfield>MapPhys</structfield> or <structfield>MapSize</structfield>
+      settings (the physical location and size of the VGA memory window)
+      then those fields of the <structname>vgaHWRec</structname> must be initialised
+      before calling this function.  Otherwise, this function initialiases
+      the default values of <constant>0xA0000</constant> for
+      <structfield>MapPhys</structfield> and <code>(64&nbsp;*&nbsp;1024)</code> for
+      <structfield>MapSize</structfield>.  This function must be called before
+      attempting to save or restore the VGA state.  If the driver doesn't
+      call it explicitly, the <function>vgaHWSave()</function> and
+      <function>vgaHWRestore()</function> functions may call it if they need
+      to access the VGA memory (in which case they will also call
+      <function>vgaHWUnmapMem()</function> to unmap the VGA memory before
+      exiting).
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWUnmapMem(ScrnInfoPtr pScrn);
+	  </programlisting>
+	  <blockquote><para>
+      This function unmaps the VGA memory window.  It must only be called
+      after the memory has been mapped.  The <structfield>Base</structfield> field
+      of the <structname>vgaHWRec</structname> field is set to <constant>NULL</constant>
+      to indicate that the memory is no longer mapped.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWGetIOBase(vgaHWPtr hwp);
+	  </programlisting>
+	  <blockquote><para>
+      This function initialises the <structfield>IOBase</structfield> field of the
+      <structname>vgaHWRec</structname>.  This function must be called before
+      using any other functions that access the video hardware.
+	    </para>
+
+	    <para>
+      A macro <function>VGAHW_GET_IOBASE()</function> is also available in
+      <filename>vgaHW.h</filename> that returns the I/O base, and this may
+      be used when the vgahw module is not loaded (for example, in the
+      <function>ChipProbe()</function> function).
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWUnlock(vgaHWPtr hwp);
+	  </programlisting>
+	  <blockquote><para>
+      This function unlocks the VGA <literal remap="tt">CRTC[0-7]</literal> registers,
+      and must be called before attempting to write to those registers.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWLock(vgaHWPtr hwp);
+	  </programlisting>
+	  <blockquote><para>
+      This function locks the VGA <literal remap="tt">CRTC[0-7]</literal> registers.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWEnable(vgaHWPtr hwp);
+	  </programlisting>
+	  <blockquote><para>
+      This function enables the VGA subsystem.  (Note, this function is
+      present in XFree86 4.1.0 and later.).
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWDisable(vgaHWPtr hwp);
+	  </programlisting>
+	  <blockquote><para>
+      This function disables the VGA subsystem.  (Note, this function is
+      present in XFree86 4.1.0 and later.).
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWSave(ScrnInfoPtr pScrn, vgaRegPtr save, int flags);
+	  </programlisting>
+	  <blockquote><para>
+      This function saves the VGA state.  The state is written to the
+      <structname>vgaRegRec</structname> pointed to by <parameter>save</parameter>.
+      <parameter>flags</parameter> is set to one or more of the following flags
+      ORed together:
+
+	      <variablelist>
+		<varlistentry>
+		  <term><constant>VGA_SR_MODE</constant></term>
+		  <listitem><para>the mode setting registers are saved
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><constant>VGA_SR_FONTS</constant></term>
+		  <listitem><para>the text mode font/text data is saved
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><constant>VGA_SR_CMAP</constant></term>
+		  <listitem><para>the colourmap (LUT) is saved
+		    </para></listitem></varlistentry>
+		<varlistentry>
+		  <term><constant>VGA_SR_ALL</constant></term>
+		  <listitem><para>all of the above are saved
+		    </para></listitem></varlistentry>
+	      </variablelist>
+	    </para>
+
+	    <para>
+      The <structname>vgaHWRec</structname> and its <structfield>IOBase</structfield> fields
+      must be initialised before this function is called.  If
+      <constant>VGA_SR_FONTS</constant> is set in <parameter>flags</parameter>, the
+      VGA memory window must be mapped.  If it isn't then
+      <function>vgaHWMapMem()</function> will be called to map it, and
+      <function>vgaHWUnmapMem()</function> will be called to unmap it
+      afterwards.  <function>vgaHWSave()</function> uses the three functions
+      below in the order <function>vgaHWSaveColormap()</function>,
+      <function>vgaHWSaveMode()</function>, <function>vgaHWSaveFonts()</function> to
+      carry out the different save phases.  It is undecided at this
+      stage whether they will remain part of the vgahw module's public
+      interface or not.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWSaveMode(ScrnInfoPtr pScrn, vgaRegPtr save);
+	  </programlisting>
+	  <blockquote><para>
+      This function saves the VGA mode registers.  They are saved to
+      the <structname>vgaRegRec</structname> pointed to by <parameter>save</parameter>.
+      The registers saved are:
+
+	      <literallayout>
+        MiscOut
+        CRTC[0-0x18]
+        Attribute[0-0x14]
+        Graphics[0-8]
+        Sequencer[0-4]
+	      </literallayout>
+	    </para>
+
+	    <para>
+    The number of registers actually saved may be modified by a prior call
+    to <function>vgaHWSetRegCounts()</function>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWSaveFonts(ScrnInfoPtr pScrn, vgaRegPtr save);
+	  </programlisting>
+	  <blockquote><para>
+      This function saves the text mode font and text data held in the
+      video memory.  If called while in a graphics mode, no save is
+      done.  The VGA memory window must be mapped with
+      <function>vgaHWMapMem()</function> before to calling this function.
+	    </para>
+
+	    <para>
+      On some platforms, one or more of the font/text plane saves may be
+      no-ops.  This is the case when the platform's VC driver already
+      takes care of this.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWSaveColormap(ScrnInfoPtr pScrn, vgaRegPtr save);
+	  </programlisting>
+	  <blockquote><para>
+      This function saves the VGA colourmap (LUT).  Before saving it, it
+      attempts to verify that the colourmap is readable.  In rare cases
+      where it isn't readable, a default colourmap is saved instead.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWRestore(ScrnInfoPtr pScrn, vgaRegPtr restore, int flags);
+	  </programlisting>
+	  <blockquote><para>
+      This function programs the VGA state.  The state programmed is
+      that contained in the <structname>vgaRegRec</structname> pointed to by
+      <parameter>restore</parameter>.  <parameter>flags</parameter> is the same
+      as described above for the <function>vgaHWSave()</function> function.
+	    </para>
+
+	    <para>
+      The <structname>vgaHWRec</structname> and its <structfield>IOBase</structfield> fields
+      must be initialised before this function is called.  If
+      <constant>VGA_SR_FONTS</constant> is set in <parameter>flags</parameter>, the
+      VGA memory window must be mapped.  If it isn't then
+      <function>vgaHWMapMem()</function> will be called to map it, and
+      <function>vgaHWUnmapMem()</function> will be called to unmap it
+      afterwards.  <function>vgaHWRestore()</function> uses the three functions
+      below in the order <function>vgaHWRestoreFonts()</function>,
+      <function>vgaHWRestoreMode()</function>,
+      <function>vgaHWRestoreColormap()</function> to carry out the different
+      restore phases.  It is undecided at this stage whether they will
+      remain part of the vgahw module's public interface or not.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWRestoreMode(ScrnInfoPtr pScrn, vgaRegPtr restore);
+	  </programlisting>
+	  <blockquote><para>
+      This function restores the VGA mode registers.  They are restored
+      from the data in the <structname>vgaRegRec</structname> pointed to by
+      <parameter>restore</parameter>.  The registers restored are:
+
+	      <literallayout>
+        MiscOut
+        CRTC[0-0x18]
+        Attribute[0-0x14]
+        Graphics[0-8]
+        Sequencer[0-4]
+	      </literallayout>
+	    </para>
+
+	    <para>
+    The number of registers actually restored may be modified by a prior call
+    to <function>vgaHWSetRegCounts()</function>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWRestoreFonts(ScrnInfoPtr pScrn, vgaRegPtr restore);
+	  </programlisting>
+	  <blockquote><para>
+      This function restores the text mode font and text data to the
+      video memory.  The VGA memory window must be mapped with
+      <function>vgaHWMapMem()</function> before to calling this function.
+	    </para>
+
+	    <para>
+      On some platforms, one or more of the font/text plane restores
+      may be no-ops.  This is the case when the platform's VC driver
+      already takes care of this.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWRestoreColormap(ScrnInfoPtr pScrn, vgaRegPtr restore);
+	  </programlisting>
+	  <blockquote><para>
+      This function restores the VGA colourmap (LUT).
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
+	  </programlisting>
+	  <blockquote><para>
+      This function fills in the <structname>vgaHWRec</structname>'s
+      <structfield>ModeReg</structfield> field with the values appropriate for
+      programming the given video mode.  It requires that the
+      <structname>ScrnInfoRec</structname>'s <structfield>depth</structfield> field is
+      initialised, which determines how the registers are programmed.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWSeqReset(vgaHWPtr hwp, Bool start);
+	  </programlisting>
+	  <blockquote><para>
+      Do a VGA sequencer reset.  If start is <constant>TRUE</constant>, the
+      reset is started.  If start is <constant>FALSE</constant>, the reset
+      is ended.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWProtect(ScrnInfoPtr pScrn, Bool on);
+	  </programlisting>
+	  <blockquote><para>
+      This function protects VGA registers and memory from corruption
+      during loads.  It is typically called with on set to
+      <constant>TRUE</constant> before programming, and with on set to
+      <constant>FALSE</constant> after programming.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    Bool vgaHWSaveScreen(ScreenPtr pScreen, int mode);
+	  </programlisting>
+	  <blockquote><para>
+      This function blanks and unblanks the screen.  It is blanked when
+      <parameter>mode</parameter> is <constant>SCREEN_SAVER_ON</constant> or
+      <constant>SCREEN_SAVER_CYCLE</constant>, and unblanked when
+      <parameter>mode</parameter> is <constant>SCREEN_SAVER_OFF</constant> or
+      <constant>SCREEN_SAVER_FORCER</constant>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void vgaHWBlankScreen(ScrnInfoPtr pScrn, Bool on);
+	  </programlisting>
+	  <blockquote><para>
+      This function blanks and unblanks the screen.  It is blanked when
+      <parameter>on</parameter> is <constant>FALSE</constant>, and unblanked when
+      <parameter>on</parameter> is <constant>TRUE</constant>.  This function is
+      provided for use in cases where the <structname>ScrnInfoRec</structname>
+      can't be derived from the <structname>ScreenRec</structname> (while probing
+      for clocks, for example).
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+    </sect2>
+
+    <sect2>
+      <title>VGA Colormap Functions</title>
+
+      <para>
+    The vgahw module uses the standard colormap support (see the
+    <link linkend="cmap">Colormap Handling</link> section.  This is initialised
+    with the following function:
+
+	<blockquote><para>
+	  <programlisting>
+    Bool vgaHWHandleColormaps(ScreenPtr pScreen);
+	    </programlisting>
+	  </para></blockquote>
+      </para>
+
+    </sect2>
+
+    <sect2>
+      <title>VGA Register Access Functions</title>
+
+      <para>
+    The vgahw module abstracts access to the standard VGA registers by
+    using a set of functions held in the <structname>vgaHWRec</structname>.  When
+    the <structname>vgaHWRec</structname> is created these function pointers are
+    initialised with the set of standard VGA I/O register access functions.
+    In addition to these, the vgahw module includes a basic set of MMIO
+    register access functions, and the <structname>vgaHWRec</structname> function
+    pointers can be initialised to these by calling the
+    <function>vgaHWSetMmioFuncs()</function> function described above.  Some
+    drivers/platforms may require a different set of functions for VGA
+    access.  The access functions are described here.
+      </para>
+
+
+      <blockquote><para>
+	  <programlisting>
+    void writeCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value);
+	  </programlisting>
+	  <blockquote><para>
+      Write <parameter>value</parameter> to CRTC register <parameter>index</parameter>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    CARD8 readCrtc(vgaHWPtr hwp, CARD8 index);
+	  </programlisting>
+	  <blockquote><para>
+      Return the value read from CRTC register <parameter>index</parameter>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void writeGr(vgaHWPtr hwp, CARD8 index, CARD8 value);
+	  </programlisting>
+	  <blockquote><para>
+      Write <parameter>value</parameter> to Graphics Controller register
+      <parameter>index</parameter>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    CARD8 readGR(vgaHWPtr hwp, CARD8 index);
+	  </programlisting>
+	  <blockquote><para>
+      Return the value read from Graphics Controller register
+      <parameter>index</parameter>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void writeSeq(vgaHWPtr hwp, CARD8 index, CARD8, value);
+	  </programlisting>
+	  <blockquote><para>
+      Write <parameter>value</parameter> to Sequencer register
+      <parameter>index</parameter>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    CARD8 readSeq(vgaHWPtr hwp, CARD8 index);
+	  </programlisting>
+	  <blockquote><para>
+      Return the value read from Sequencer register <parameter>index</parameter>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void writeAttr(vgaHWPtr hwp, CARD8 index, CARD8, value);
+	  </programlisting>
+	  <blockquote><para>
+      Write <parameter>value</parameter> to Attribute Controller register
+      <parameter>index</parameter>.  When writing out the index value this
+      function should set bit 5 (<constant>0x20</constant>) according to the
+      setting of <structfield>hwp-&gt;paletteEnabled</structfield> in order to
+      preserve the palette access state.  It should be cleared when
+      <structfield>hwp-&gt;paletteEnabled</structfield> is <constant>TRUE</constant>
+      and set when it is <constant>FALSE</constant>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    CARD8 readAttr(vgaHWPtr hwp, CARD8 index);
+	  </programlisting>
+	  <blockquote><para>
+      Return the value read from Attribute Controller register
+      <parameter>index</parameter>.  When writing out the index value this
+      function should set bit 5 (<constant>0x20</constant>) according to the
+      setting of <structfield>hwp-&gt;paletteEnabled</structfield> in order to
+      preserve the palette access state.  It should be cleared when
+      <structfield>hwp-&gt;paletteEnabled</structfield> is <constant>TRUE</constant>
+      and set when it is <constant>FALSE</constant>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void writeMiscOut(vgaHWPtr hwp, CARD8 value);
+	  </programlisting>
+	  <blockquote><para>
+      Write `<parameter>value</parameter>' to the Miscellaneous Output register.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    CARD8 readMiscOut(vgwHWPtr hwp);
+	  </programlisting>
+	  <blockquote><para>
+      Return the value read from the Miscellaneous Output register.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void enablePalette(vgaHWPtr hwp);
+	  </programlisting>
+	  <blockquote><para>
+      Clear the palette address source bit in the Attribute Controller
+      index register and set <literal remap="tt">hwp-&gt;paletteEnabled</literal> to
+      <constant>TRUE</constant>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void disablePalette(vgaHWPtr hwp);
+	  </programlisting>
+	  <blockquote><para>
+      Set the palette address source bit in the Attribute Controller
+      index register and set <literal remap="tt">hwp-&gt;paletteEnabled</literal> to
+      <constant>FALSE</constant>.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void writeDacMask(vgaHWPtr hwp, CARD8 value);
+	  </programlisting>
+	  <blockquote><para>
+      Write <parameter>value</parameter> to the DAC Mask register.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    CARD8 readDacMask(vgaHWptr hwp);
+	  </programlisting>
+	  <blockquote><para>
+      Return the value read from the DAC Mask register.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void writeDacReadAddress(vgaHWPtr hwp, CARD8 value);
+	  </programlisting>
+	  <blockquote><para>
+      Write <parameter>value</parameter> to the DAC Read Address register.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void writeDacWriteAddress(vgaHWPtr hwp, CARD8 value);
+	  </programlisting>
+	  <blockquote><para>
+      Write <parameter>value</parameter> to the DAC Write Address register.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void writeDacData(vgaHWPtr hwp, CARD8 value);
+	  </programlisting>
+	  <blockquote><para>
+      Write <parameter>value</parameter> to the DAC Data register.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    CARD8 readDacData(vgaHWptr hwp);
+	  </programlisting>
+	  <blockquote><para>
+      Return the value read from the DAC Data register.
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    CARD8 readEnable(vgaHWptr hwp);
+	  </programlisting>
+	  <blockquote><para>
+      Return the value read from the VGA Enable register.  (Note: This
+      function is present in XFree86 4.1.0 and later.)
+	    </para>
+
+	  </blockquote></para></blockquote>
+
+      <blockquote><para>
+	  <programlisting>
+    void writeEnable(vgaHWPtr hwp, CARD8 value);
+	  </programlisting>
+	  <blockquote><para>
+      Write <parameter>value</parameter> to the VGA Enable register.  (Note: This
+      function is present in XFree86 4.1.0 and later.)
+	    </para>
+
+	  </blockquote></para></blockquote>
+    </sect2>
+  </sect1>
+
+  <sect1 id="sample">
+    <title>Some notes about writing a driver</title>
+
+    <note><para>NOTE: some parts of this are not up to date</para></note>
+
+    <para>
+The following is an outline for writing a basic unaccelerated driver
+for a PCI video card with a linear mapped framebuffer, and which has a
+VGA core.  It is includes some general information that is relevant to
+most drivers (even those which don't fit that basic description).
+    </para>
+
+    <para>
+The information here is based on the initial conversion of the Matrox
+Millennium driver to the ``new design''.  For a fleshing out and sample
+implementation of some of the bits outlined here, refer to that driver.
+Note that this is an example only.  The approach used here will not be
+appropriate for all drivers.
+    </para>
+
+    <para>
+Each driver must reserve a unique driver name, and a string that is used
+to prefix all of its externally visible symbols.  This is to avoid name
+space clashes when loading multiple drivers.  The examples here are for
+the ``ZZZ'' driver, which uses the ``ZZZ'' or ``zzz'' prefix for its externally
+visible symbols.
+    </para>
+
+    <sect2>
+      <title>Include files</title>
+
+      <para>
+  All drivers normally include the following headers:
+	<literallayout><filename>
+    "xf86.h"
+    "xf86_OSproc.h"
+    "xf86_ansic.h"
+    "xf86Resources.h"
+	  </filename></literallayout>
+  Wherever inb/outb (and related things) are used the following should be
+  included:
+	<literallayout><filename>
+    "compiler.h"
+	  </filename></literallayout>
+  Note: in drivers, this must be included after <filename>"xf86_ansic.h"</filename>.
+      </para>
+
+      <para>
+  Drivers that need to access PCI vendor/device definitions need this:
+	<literallayout><filename>
+    "xf86PciInfo.h"
+	  </filename></literallayout>
+      </para>
+
+      <para>
+  Drivers that need to access the PCI config space need this:
+	<literallayout><filename>
+    "xf86Pci.h"
+	  </filename></literallayout>
+      </para>
+
+      <para>
+  Drivers using the mi banking wrapper need:
+
+	<literallayout><filename>
+    "mibank.h"
+	  </filename></literallayout>
+      </para>
+
+      <para>
+  Drivers that initialise a SW cursor need this:
+	<literallayout><filename>
+    "mipointer.h"
+	  </filename></literallayout>
+      </para>
+
+      <para>
+  All drivers implementing backing store need this:
+	<literallayout><filename>
+    "mibstore.h"
+	  </filename></literallayout>
+      </para>
+
+      <para>
+  All drivers using the mi colourmap code need this:
+	<literallayout><filename>
+    "micmap.h"
+	  </filename></literallayout>
+      </para>
+
+      <para>
+  If a driver uses the vgahw module, it needs this:
+	<literallayout><filename>
+    "vgaHW.h"
+	  </filename></literallayout>
+      </para>
+
+      <para>
+  Drivers supporting VGA or Hercules monochrome screens need:
+	<literallayout><filename>
+    "xf1bpp.h"
+	  </filename></literallayout>
+      </para>
+
+      <para>
+  Drivers supporting VGA or EGC 16-colour screens need:
+	<literallayout><filename>
+    "xf4bpp.h"
+	  </filename></literallayout>
+      </para>
+
+      <para>
+  Drivers using cfb need:
+	<programlisting>
+    #define PSZ 8
+    #include "cfb.h"
+    #undef PSZ
+	</programlisting>
+      </para>
+
+      <para>
+  Drivers supporting bpp 16, 24 or 32 with cfb need one or more of:
+	<literallayout><filename>
+    "cfb16.h"
+    "cfb24.h"
+    "cfb32.h"
+	  </filename></literallayout>
+      </para>
+
+      <para>
+  The driver's own header file:
+	<literallayout><filename>
+    "zzz.h"
+	  </filename></literallayout>
+      </para>
+
+      <para>
+  Drivers must NOT include the following:
+
+	<literallayout><filename>
+    "xf86Priv.h"
+    "xf86Privstr.h"
+    "xf86_libc.h"
+    "xf86_OSlib.h"
+    "Xos.h"</filename>
+    any OS header
+	</literallayout>
+      </para>
+
+    </sect2>
+
+    <sect2>
+      <title>Data structures and initialisation</title>
+
+      <itemizedlist>
+	<listitem>
+	  <para>The following macros should be defined:
+	    <programlisting>
+#define VERSION &lt;version-as-an-int&gt;
+#define ZZZ_NAME "ZZZ"         /* the name used to prefix messages */
+#define ZZZ_DRIVER_NAME "zzz"  /* the driver name as used in config file */
+#define ZZZ_MAJOR_VERSION &lt;int&gt;
+#define ZZZ_MINOR_VERSION &lt;int&gt;
+#define ZZZ_PATCHLEVEL    &lt;int&gt;
+	    </programlisting>
+	  </para>
+	  <para>
+    NOTE: <constant>ZZZ_DRIVER_NAME</constant> should match the name of the
+    driver module without things like the "lib" prefix, the "_drv" suffix
+    or filename extensions.
+	  </para>
+	</listitem>
+
+	<listitem>
+	  <para>
+    A DriverRec must be defined, which includes the functions required
+    at the pre-probe phase.  The name of this DriverRec must be an
+    upper-case version of ZZZ_DRIVER_NAME (for the purposes of static
+    linking).
+	    <programlisting>
+DriverRec ZZZ = {
+    VERSION,
+    ZZZ_DRIVER_NAME,
+    ZZZIdentify,
+    ZZZProbe,
+    ZZZAvailableOptions,
+    NULL,
+    0
+};
+	    </programlisting>
+	  </para>
+	</listitem>
+
+	<listitem>
+	  <para>Define list of supported chips and their matching ID:
+	    <programlisting>
+static SymTabRec ZZZChipsets[] = {
+    { PCI_CHIP_ZZZ1234, "zzz1234a" },
+    { PCI_CHIP_ZZZ5678, "zzz5678a" },
+    { -1,               NULL }
+};
+	    </programlisting>
+	  </para>
+	  <para>
+    The token field may be any integer value that the driver may use to
+    uniquely identify the supported chipsets.  For drivers that support
+    only PCI devices using the PCI device IDs might be a natural choice,
+    but this isn't mandatory.  For drivers that support both PCI and other
+    devices (like ISA), some other ID should probably used.  When other
+    IDs are used as the tokens it is recommended that the names be
+    defined as an <type>enum</type> type.
+	  </para>
+	</listitem>
+
+	<listitem>
+	  <para>
+    If the driver uses the <function>xf86MatchPciInstances()</function>
+    helper (recommended for drivers that support PCI cards) a list that
+    maps PCI IDs to chip IDs and fixed resources must be defined:
+	    <programlisting>
+static PciChipsets ZZZPciChipsets[] = {
+    { PCI_CHIP_ZZZ1234, PCI_CHIP_ZZZ1234, RES_SHARED_VGA },
+    { PCI_CHIP_ZZZ5678, PCI_CHIP_ZZZ5678, RES_SHARED_VGA },
+    { -1,               -1,               RES_UNDEFINED }
+}
+	    </programlisting>
+	  </para>
+	</listitem>
+
+	<listitem>
+	  <para>
+    Define the <structname>XF86ModuleVersionInfo</structname> struct for the
+    driver.  This is required for the dynamically loaded version:
+	    <programlisting>
+static XF86ModuleVersionInfo zzzVersRec =
+{
+    "zzz",
+    MODULEVENDORSTRING,
+    MODINFOSTRING1,
+    MODINFOSTRING2,
+    XF86_VERSION_CURRENT,
+    ZZZ_MAJOR_VERSION, ZZZ_MINOR_VERSION, ZZZ_PATCHLEVEL,
+    ABI_CLASS_VIDEODRV,
+    ABI_VIDEODRV_VERSION,
+    MOD_CLASS_VIDEODRV,
+    {0,0,0,0}
+};
+	    </programlisting>
+	  </para>
+	</listitem>
+
+	<listitem>
+	  <para>
+    Define a data structure to hold the driver's screen-specific data.
+    This must be used instead of global variables.  This would be defined
+    in the <filename>"zzz.h"</filename> file, something like:
+	    <programlisting>
+typedef struct {
+    type1  field1;
+    type2  field2;
+    int    fooHack;
+    Bool   pciRetry;
+    Bool   noAccel;
+    Bool   hwCursor;
+    CloseScreenProcPtr CloseScreen;
+    OptionInfoPtr Options;
+    ...
+} ZZZRec, *ZZZPtr;
+	    </programlisting>
+	  </para>
+	</listitem>
+
+	<listitem>
+	  <para>
+    Define the list of config file Options that the driver accepts.  For
+    consistency between drivers those in the list of ``standard'' options
+    should be used where appropriate before inventing new options.
+
+	    <programlisting>
+typedef enum {
+    OPTION_FOO_HACK,
+    OPTION_PCI_RETRY,
+    OPTION_HW_CURSOR,
+    OPTION_NOACCEL
+} ZZZOpts;
+
+static const OptionInfoRec ZZZOptions[] = {
+  { OPTION_FOO_HACK,  "FooHack",   OPTV_INTEGER, {0}, FALSE },
+  { OPTION_PCI_RETRY, "PciRetry",  OPTV_BOOLEAN, {0}, FALSE },
+  { OPTION_HW_CURSOR, "HWcursor",  OPTV_BOOLEAN, {0}, FALSE },
+  { OPTION_NOACCEL,   "NoAccel",   OPTV_BOOLEAN, {0}, FALSE },
+  { -1,               NULL,        OPTV_NONE,    {0}, FALSE }
+};
+	    </programlisting>
+	  </para>
+	</listitem>
+      </itemizedlist>
+    </sect2>
+
+    <sect2>
+      <title>Functions</title>
+
+
+      <sect3>
+	<title>SetupProc</title>
+
+	<para>
+    For dynamically loaded modules, a <varname>ModuleData</varname>
+    variable is required.  It is should be the name of the driver
+    prepended to "ModuleData".  A <function>Setup()</function> function is
+    also required, which calls <function>xf86AddDriver()</function> to add
+    the driver to the main list of drivers.
+	</para>
+
+	<programlisting>
+static MODULESETUPPROTO(zzzSetup);
+
+XF86ModuleData zzzModuleData = { &amp;zzzVersRec, zzzSetup, NULL };
+
+static pointer
+zzzSetup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+    static Bool setupDone = FALSE;
+
+    /* This module should be loaded only once, but check to be sure. */
+
+    if (!setupDone) {
+        /*
+         * Modules that this driver always requires may be loaded
+         * here  by calling LoadSubModule().
+         */
+
+        setupDone = TRUE;
+        xf86AddDriver(&amp;MGA, module, 0);
+
+        /*
+         * The return value must be non-NULL on success even though
+         * there is no TearDownProc.
+         */
+        return (pointer)1;
+    } else {
+        if (errmaj) *errmaj = LDR_ONCEONLY;
+        return NULL;
+    }
+}
+	</programlisting>
+      </sect3>
+
+      <sect3>
+	<title>GetRec, FreeRec</title>
+
+	<para>
+    A function is usually required to allocate the driver's
+    screen-specific data structure and hook it into the
+    <structname>ScrnInfoRec</structname>'s <structfield>driverPrivate</structfield> field.
+    The <structname>ScrnInfoRec</structname>'s <structfield>driverPrivate</structfield> is
+    initialised to <constant>NULL</constant>, so it is easy to check if the
+    initialisation has already been done.  After allocating it, initialise
+    the fields.  By using <function>xnfcalloc()</function> to do the allocation
+    it is zeroed, and if the allocation fails the server exits.
+	</para>
+
+	<para>
+    NOTE:
+    When allocating structures from inside the driver which are defined
+    on the common level it is important to initialize the structure to
+    zero.
+    Only this guarantees that the server remains source compatible to
+    future changes in common level structures.
+	</para>
+
+	<programlisting>
+static Bool
+ZZZGetRec(ScrnInfoPtr pScrn)
+{
+    if (pScrn-&gt;driverPrivate != NULL)
+        return TRUE;
+    pScrn-&gt;driverPrivate = xnfcalloc(sizeof(ZZZRec), 1);
+    /* Initialise as required */
+    ...
+    return TRUE;
+}
+	</programlisting>
+
+	<para>
+    Define a macro in <filename>"zzz.h"</filename> which gets a pointer to
+    the <structname>ZZZRec</structname> when given <parameter>pScrn</parameter>:
+
+	  <programlisting>
+#define ZZZPTR(p) ((ZZZPtr)((p)-&gt;driverPrivate))
+	  </programlisting>
+	</para>
+
+	<para>
+    Define a function to free the above, setting it to <constant>NULL</constant>
+    once it has been freed:
+
+	  <programlisting>
+static void
+ZZZFreeRec(ScrnInfoPtr pScrn)
+{
+    if (pScrn-&gt;driverPrivate == NULL)
+        return;
+    xfree(pScrn-&gt;driverPrivate);
+    pScrn-&gt;driverPrivate = NULL;
+}
+	  </programlisting>
+	</para>
+      </sect3>
+
+      <sect3>
+	<title>Identify</title>
+
+	<para>
+    Define the <function>Identify()</function> function.  It is run before
+    the Probe, and typically prints out an identifying message, which
+    might include the chipsets it supports.  This function is mandatory:
+
+	  <programlisting>
+static void
+ZZZIdentify(int flags)
+{
+    xf86PrintChipsets(ZZZ_NAME, "driver for ZZZ Tech chipsets",
+                      ZZZChipsets);
+}
+	  </programlisting>
+	</para>
+      </sect3>
+
+      <sect3>
+	<title>Probe</title>
+
+	<para>
+    Define the <function>Probe()</function> function.  The purpose of this
+    is to find all instances of the hardware that the driver supports,
+    and for the ones not already claimed by another driver, claim the
+    slot, and allocate a <structname>ScrnInfoRec</structname>.  This should be
+    a minimal probe, and it should under no circumstances leave the
+    state of the hardware changed.  Because a device is found, don't
+    assume that it will be used.  Don't do any initialisations other
+    than the required <structname>ScrnInfoRec</structname> initialisations.
+    Don't allocate any new data structures.
+	</para>
+
+	<para>
+    This function is mandatory.
+	</para>
+
+	<para>
+    NOTE: The <function>xf86DrvMsg()</function> functions cannot be used from
+    the Probe.
+	</para>
+
+	<programlisting>
+static Bool
+ZZZProbe(DriverPtr drv, int flags)
+{
+    Bool foundScreen = FALSE;
+    int numDevSections, numUsed;
+    GDevPtr *devSections;
+    int *usedChips;
+    int i;
+
+    /*
+     * Find the config file Device sections that match this
+     * driver, and return if there are none.
+     */
+    if ((numDevSections = xf86MatchDevice(ZZZ_DRIVER_NAME,
+                                          &amp;devSections)) &lt;= 0) {
+        return FALSE;
+    }
+
+    /*
+     * Since this is a PCI card, "probing" just amounts to checking
+     * the PCI data that the server has already collected.  If there
+     * is none, return.
+     *
+     * Although the config file is allowed to override things, it
+     * is reasonable to not allow it to override the detection
+     * of no PCI video cards.
+     *
+     * The provided xf86MatchPciInstances() helper takes care of
+     * the details.
+     */
+    /* test if PCI bus present */
+    if (xf86GetPciVideoInfo()) {
+
+        numUsed = xf86MatchPciInstances(ZZZ_NAME, PCI_VENDOR_ZZZ,
+                            ZZZChipsets, ZZZPciChipsets, devSections,
+                            numDevSections, drv, &amp;usedChips);
+
+        for (i = 0; i &lt; numUsed; i++) {
+            ScrnInfoPtr pScrn = NULL;
+            if ((pScrn = xf86ConfigPciEntity(pScrn, flags, usedChips[i],
+                                             ZZZPciChipsets, NULL, NULL,
+                                             NULL, NULL, NULL))) {
+               /* Allocate a ScrnInfoRec */
+               pScrn-&gt;driverVersion = VERSION;
+               pScrn-&gt;driverName    = ZZZ_DRIVER_NAME;
+               pScrn-&gt;name          = ZZZ_NAME;
+               pScrn-&gt;Probe         = ZZZProbe;
+               pScrn-&gt;PreInit       = ZZZPreInit;
+               pScrn-&gt;ScreenInit    = ZZZScreenInit;
+               pScrn-&gt;SwitchMode    = ZZZSwitchMode;
+               pScrn-&gt;AdjustFrame   = ZZZAdjustFrame;
+               pScrn-&gt;EnterVT       = ZZZEnterVT;
+               pScrn-&gt;LeaveVT       = ZZZLeaveVT;
+               pScrn-&gt;FreeScreen    = ZZZFreeScreen;
+               pScrn-&gt;ValidMode     = ZZZValidMode;
+               foundScreen = TRUE;
+               /* add screen to entity */
+           }
+        }
+        xfree(usedChips);
+    }
+
+#ifdef HAS_ISA_DEVS
+    /*
+     * If the driver supports ISA hardware, the following block
+     * can be included too.
+     */
+    numUsed = xf86MatchIsaInstances(ZZZ_NAME, ZZZChipsets,
+                             ZZZIsaChipsets, drv, ZZZFindIsaDevice,
+                             devSections, numDevSections, &amp;usedChips);
+    for (i = 0; i &lt; numUsed; i++) {
+        ScrnInfoPtr pScrn = NULL;
+	if ((pScrn = xf86ConfigIsaEntity(pScrn, flags, usedChips[i],
+					 ZZZIsaChipsets, NULL, NULL, NULL,
+					 NULL, NULL))) {
+            pScrn-&gt;driverVersion = VERSION;
+            pScrn-&gt;driverName    = ZZZ_DRIVER_NAME;
+            pScrn-&gt;name          = ZZZ_NAME;
+            pScrn-&gt;Probe         = ZZZProbe;
+            pScrn-&gt;PreInit       = ZZZPreInit;
+            pScrn-&gt;ScreenInit    = ZZZScreenInit;
+            pScrn-&gt;SwitchMode    = ZZZSwitchMode;
+            pScrn-&gt;AdjustFrame   = ZZZAdjustFrame;
+            pScrn-&gt;EnterVT       = ZZZEnterVT;
+            pScrn-&gt;LeaveVT       = ZZZLeaveVT;
+            pScrn-&gt;FreeScreen    = ZZZFreeScreen;
+            pScrn-&gt;ValidMode     = ZZZValidMode;
+            foundScreen = TRUE;
+        }
+    }
+    xfree(usedChips);
+#endif /* HAS_ISA_DEVS */
+
+    xfree(devSections);
+    return foundScreen;
+	</programlisting>
+      </sect3>
+
+      <sect3>
+	<title>AvailableOptions</title>
+
+	<para>
+    Define the <function>AvailableOptions()</function> function. The purpose
+    of this is to return the available driver options back to the
+    -configure option, so that an xorg.conf file can be built and the
+    user can see which options are available for them to use.
+	</para>
+      </sect3>
+
+      <sect3>
+	<title>PreInit</title>
+
+	<para>
+    Define the <function>PreInit()</function> function.  The purpose of
+    this is to find all the information required to determine if the
+    configuration is usable, and to initialise those parts of the
+    <structname>ScrnInfoRec</structname> that can be set once at the beginning
+    of the first server generation.  The information should be found in
+    the least intrusive way possible.
+	</para>
+
+	<para>
+    This function is mandatory.
+	</para>
+
+	<para>
+    NOTES:
+	  <orderedlist>
+	    <listitem><para>
+	 The <function>PreInit()</function> function is only called once
+	 during the life of the X server (at the start of the first
+	 generation).
+	      </para></listitem>
+
+	    <listitem><para>
+	 Data allocated here must be of the type that persists for
+	 the life of the X server.  This means that data that hooks into
+	 the <structname>ScrnInfoRec</structname>'s <structfield>privates</structfield>
+	 field should be allocated here, but data that hooks into the
+	 <structname>ScreenRec</structname>'s <structfield>devPrivates</structfield> field
+	 should not be allocated here.  The <structfield>driverPrivate</structfield>
+	 field should also be allocated here.
+	      </para></listitem>
+
+	    <listitem><para>
+	 Although the <structname>ScrnInfoRec</structname> has been allocated
+	 before this function is called, the <structname>ScreenRec</structname>
+	 has not been allocated.  That means that things requiring it
+	 cannot be used in this function.
+	      </para></listitem>
+
+	    <listitem><para>
+	 Very little of the <structname>ScrnInfoRec</structname> has been
+	 initialised when this function is called.  It is important to
+	 get the order of doing things right in this function.
+	      </para></listitem>
+
+	  </orderedlist>
+	</para>
+
+	<programlisting>
+static Bool
+ZZZPreInit(ScrnInfoPtr pScrn, int flags)
+{
+    /* Fill in the monitor field */
+    pScrn-&gt;monitor = pScrn-&gt;confScreen-&gt;monitor;
+
+    /*
+     * If using the vgahw module, it will typically be loaded
+     * here by calling xf86LoadSubModule(pScrn, "vgahw");
+     */
+
+    /*
+     * Set the depth/bpp.  Use the globally preferred depth/bpp.  If the
+     * driver has special default depth/bpp requirements, the defaults should
+     * be specified here explicitly.
+     * We support both 24bpp and 32bpp framebuffer layouts.
+     * This sets pScrn-&gt;display also.
+     */
+    if (!xf86SetDepthBpp(pScrn, 0, 0, 0,
+                         Support24bppFb | Support32bppFb)) {
+        return FALSE;
+    } else {
+        if (depth/bpp isn't one we support) {
+            print error message;
+            return FALSE;
+        }
+    }
+    /* Print out the depth/bpp that was set */
+    xf86PrintDepthBpp(pScrn);
+
+    /* Set bits per RGB for 8bpp */
+    if (pScrn-&gt;depth &lt;= 8) {
+        /* Take into account a dac_6_bit option here */
+        pScrn-&gt;rgbBits = 6 or 8;
+    }
+
+    /*
+     * xf86SetWeight() and xf86SetDefaultVisual() must be called
+     * after pScrn-&gt;display is initialised.
+     */
+
+    /* Set weight/mask/offset for depth &gt; 8 */
+    if (pScrn-&gt;depth &gt; 8) {
+        if (!xf86SetWeight(pScrn, defaultWeight, defaultMask)) {
+            return FALSE;
+        } else {
+            if (weight isn't one we support) {
+                print error message;
+                return FALSE;
+            }
+        }
+    }
+
+    /* Set the default visual. */
+    if (!xf86SetDefaultVisual(pScrn, -1)) {
+        return FALSE;
+    } else {
+        if (visual isn't one we support) {
+            print error message;
+            return FALSE;
+        }
+    }
+
+    /* If the driver supports gamma correction, set the gamma. */
+    if (!xf86SetGamma(pScrn, default_gamma)) {
+        return FALSE;
+    }
+
+    /* This driver uses a programmable clock */
+    pScrn-&gt;progClock = TRUE;
+
+    /* Allocate the ZZZRec driverPrivate */
+    if (!ZZZGetRec(pScrn)) {
+        return FALSE;
+    }
+
+    pZzz = ZZZPTR(pScrn);
+
+    /* Collect all of the option flags (fill in pScrn-&gt;options) */
+    xf86CollectOptions(pScrn, NULL);
+
+    /*
+     * Process the options based on the information in ZZZOptions.
+     * The results are written to pZzz-&gt;Options.  If all of the options
+     * processing is done within this function a local variable "options"
+     * can be used instead of pZzz-&gt;Options.
+     */
+    if (!(pZzz-&gt;Options = xalloc(sizeof(ZZZOptions))))
+        return FALSE;
+    (void)memcpy(pZzz-&gt;Options, ZZZOptions, sizeof(ZZZOptions));
+    xf86ProcessOptions(pScrn-&gt;scrnIndex, pScrn-&gt;options, pZzz-&gt;Options);
+
+    /*
+     * Set various fields of ScrnInfoRec and/or ZZZRec based on
+     * the options found.
+     */
+    from = X_DEFAULT;
+    pZzz-&gt;hwCursor = FALSE;
+    if (xf86IsOptionSet(pZzz-&gt;Options, OPTION_HW_CURSOR)) {
+        from = X_CONFIG;
+        pZzz-&gt;hwCursor = TRUE;
+    }
+    xf86DrvMsg(pScrn-&gt;scrnIndex, from, "Using %s cursor\n",
+               pZzz-&gt;hwCursor ? "HW" : "SW");
+    if (xf86IsOptionSet(pZzz-&gt;Options, OPTION_NOACCEL)) {
+        pZzz-&gt;noAccel = TRUE;
+        xf86DrvMsg(pScrn-&gt;scrnIndex, X_CONFIG,
+                   "Acceleration disabled\n");
+    } else {
+        pZzz-&gt;noAccel = FALSE;
+    }
+    if (xf86IsOptionSet(pZzz-&gt;Options, OPTION_PCI_RETRY)) {
+        pZzz-&gt;UsePCIRetry = TRUE;
+        xf86DrvMsg(pScrn-&gt;scrnIndex, X_CONFIG, "PCI retry enabled\n");
+    }
+    pZzz-&gt;fooHack = 0;
+    if (xf86GetOptValInteger(pZzz-&gt;Options, OPTION_FOO_HACK,
+                             &amp;pZzz-&gt;fooHack)) {
+        xf86DrvMsg(pScrn-&gt;scrnIndex, X_CONFIG, "Foo Hack set to %d\n",
+                   pZzz-&gt;fooHack);
+    }
+
+    /*
+     * Find the PCI slot(s) that this screen claimed in the probe.
+     * In this case, exactly one is expected, so complain otherwise.
+     * Note in this case we're not interested in the card types so
+     * that parameter is set to NULL.
+     */
+    if ((i = xf86GetPciInfoForScreen(pScrn-&gt;scrnIndex, &amp;pciList, NULL))
+        != 1) {
+        print error message;
+        ZZZFreeRec(pScrn);
+        if (i &gt; 0)
+            xfree(pciList);
+        return FALSE;
+    }
+    /* Note that pciList should be freed below when no longer needed */
+
+    /*
+     * Determine the chipset, allowing config file chipset and
+     * chipid values to override the probed information.  The config
+     * chipset value has precedence over its chipid value if both
+     * are present.
+     *
+     * It isn't necessary to fill in pScrn-&gt;chipset if the driver
+     * keeps track of the chipset in its ZZZRec.
+     */
+
+    ...
+
+    /*
+     * Determine video memory, fb base address, I/O addresses, etc,
+     * allowing the config file to override probed values.
+     *
+     * Set the appropriate pScrn fields (videoRam is probably the
+     * most important one that other code might require), and
+     * print out the settings.
+     */
+
+    ...
+
+    /* Initialise a clockRanges list. */
+
+    ...
+
+    /* Set any other chipset specific things in the ZZZRec */
+
+    ...
+
+    /* Select valid modes from those available */
+
+    i = xf86ValidateModes(pScrn, pScrn-&gt;monitor-&gt;Modes,
+                          pScrn-&gt;display-&gt;modes, clockRanges,
+                          NULL, minPitch, maxPitch, rounding,
+                          minHeight, maxHeight,
+                          pScrn-&gt;display-&gt;virtualX,
+                          pScrn-&gt;display-&gt;virtualY,
+                          pScrn-&gt;videoRam * 1024,
+                          LOOKUP_BEST_REFRESH);
+    if (i == -1) {
+        ZZZFreeRec(pScrn);
+        return FALSE;
+    }
+
+    /* Prune the modes marked as invalid */
+
+    xf86PruneDriverModes(pScrn);
+
+    /* If no valid modes, return */
+
+    if (i == 0 || pScrn-&gt;modes == NULL) {
+        print error message;
+        ZZZFreeRec(pScrn);
+        return FALSE;
+    }
+
+    /*
+     * Initialise the CRTC fields for the modes.  This driver expects
+     * vertical values to be halved for interlaced modes.
+     */
+    xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
+
+    /* Set the current mode to the first in the list. */
+    pScrn-&gt;currentMode = pScrn-&gt;modes;
+
+    /* Print the list of modes being used. */
+    xf86PrintModes(pScrn);
+
+    /* Set the DPI */
+    xf86SetDpi(pScrn, 0, 0);
+
+    /* Load bpp-specific modules */
+    switch (pScrn-&gt;bitsPerPixel) {
+    case 1:
+        mod = "xf1bpp";
+        break;
+    case 4:
+        mod = "xf4bpp";
+        break;
+    case 8:
+        mod = "cfb";
+        break;
+    case 16:
+        mod = "cfb16";
+        break;
+    case 24:
+        mod = "cfb24";
+        break;
+    case 32:
+        mod = "cfb32";
+        break;
+    }
+    if (mod &amp;&amp; !xf86LoadSubModule(pScrn, mod))
+        ZZZFreeRec(pScrn);
+        return FALSE;
+
+    /* Load XAA if needed */
+    if (!pZzz-&gt;noAccel || pZzz-&gt;hwCursor)
+        if (!xf86LoadSubModule(pScrn, "xaa")) {
+            ZZZFreeRec(pScrn);
+            return FALSE;
+        }
+
+    /* Done */
+    return TRUE;
+}
+	</programlisting>
+      </sect3>
+
+      <sect3>
+	<title>MapMem, UnmapMem</title>
+
+	<para>
+    Define functions to map and unmap the video memory and any other
+    memory apertures required.  These functions are not mandatory, but
+    it is often useful to have such functions.
+	</para>
+
+	<programlisting>
+static Bool
+ZZZMapMem(ScrnInfoPtr pScrn)
+{
+    /* Call xf86MapPciMem() to map each PCI memory area */
+    ...
+    return TRUE or FALSE;
+}
+
+static Bool
+ZZZUnmapMem(ScrnInfoPtr pScrn)
+{
+    /* Call xf86UnMapVidMem() to unmap each memory area */
+    ...
+    return TRUE or FALSE;
+}
+	</programlisting>
+      </sect3>
+
+      <sect3>
+	<title>Save, Restore</title>
+
+	<para>
+    Define functions to save and restore the original video state.  These
+    functions are not mandatory, but are often useful.
+	</para>
+
+	<programlisting>
+static void
+ZZZSave(ScrnInfoPtr pScrn)
+{
+    /*
+     * Save state into per-screen data structures.
+     * If using the vgahw module, vgaHWSave will typically be
+     * called here.
+     */
+    ...
+}
+
+static void
+ZZZRestore(ScrnInfoPtr pScrn)
+{
+    /*
+     * Restore state from per-screen data structures.
+     * If using the vgahw module, vgaHWRestore will typically be
+     * called here.
+     */
+    ...
+}
+	</programlisting>
+      </sect3>
+
+      <sect3>
+	<title>ModeInit</title>
+
+	<para>
+    Define a function to initialise a new video mode.  This function isn't
+    mandatory, but is often useful.
+	</para>
+
+	<programlisting>
+static Bool
+ZZZModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+    /*
+     * Program a video mode.  If using the vgahw module,
+     * vgaHWInit and vgaRestore will typically be called here.
+     * Once up to the point where there can't be a failure
+     * set pScrn-&gt;vtSema to TRUE.
+     */
+    ...
+}
+	</programlisting>
+      </sect3>
+
+      <sect3>
+	<title>ScreenInit</title>
+
+	<para>
+    Define the <function>ScreenInit()</function> function.  This is called
+    at the start of each server generation, and should fill in as much
+    of the <structname>ScreenRec</structname> as possible as well as any other
+    data that is initialised once per generation.  It should initialise
+    the framebuffer layers it is using, and initialise the initial video
+    mode.
+	</para>
+
+	<para>
+    This function is mandatory.
+	</para>
+
+	<para>
+    NOTE: The <structname>ScreenRec</structname> (<parameter>pScreen</parameter>) is
+	  passed to this driver, but it and the
+	  <varname>ScrnInfoRecs</varname> are not yet hooked into each
+	  other.  This means that in this function, and functions it
+	  calls, one cannot be found from the other.
+	</para>
+
+	<programlisting>
+static Bool
+ZZZScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
+{
+    /* Get the ScrnInfoRec */
+    pScrn = xf86Screens[pScreen-&gt;myNum];
+
+    /*
+     * If using the vgahw module, its data structures and related
+     * things are typically initialised/mapped here.
+     */
+
+    /* Save the current video state */
+    ZZZSave(pScrn);
+
+    /* Initialise the first mode */
+    ZZZModeInit(pScrn, pScrn-&gt;currentMode);
+
+    /* Set the viewport if supported */
+
+    ZZZAdjustFrame(scrnIndex, pScrn-&gt;frameX0, pScrn-&gt;frameY0, 0);
+
+    /*
+     * Setup the screen's visuals, and initialise the framebuffer
+     * code.
+     */
+
+    /* Reset the visual list */
+    miClearVisualTypes();
+
+    /*
+     * Setup the visuals supported.  This driver only supports
+     * TrueColor for bpp &gt; 8, so the default set of visuals isn't
+     * acceptable.  To deal with this, call miSetVisualTypes with
+     * the appropriate visual mask.
+     */
+
+    if (pScrn-&gt;bitsPerPixel &gt; 8) {
+        if (!miSetVisualTypes(pScrn-&gt;depth, TrueColorMask,
+                              pScrn-&gt;rgbBits, pScrn-&gt;defaultVisual))
+            return FALSE;
+    } else {
+        if (!miSetVisualTypes(pScrn-&gt;depth,
+                              miGetDefaultVisualMask(pScrn-&gt;depth),
+                              pScrn-&gt;rgbBits, pScrn-&gt;defaultVisual))
+            return FALSE;
+    }
+
+    /*
+     * Initialise the framebuffer.
+     */
+
+    switch (pScrn-&gt;bitsPerPixel) {
+    case 1:
+        ret = xf1bppScreenInit(pScreen, FbBase,
+                               pScrn-&gt;virtualX, pScrn-&gt;virtualY,
+                               pScrn-&gt;xDpi, pScrn-&gt;yDpi,
+                               pScrn-&gt;displayWidth);
+        break;
+    case 4:
+        ret = xf4bppScreenInit(pScreen, FbBase,
+                               pScrn-&gt;virtualX, pScrn-&gt;virtualY,
+                               pScrn-&gt;xDpi, pScrn-&gt;yDpi,
+                               pScrn-&gt;displayWidth);
+        break;
+    case 8:
+        ret = cfbScreenInit(pScreen, FbBase,
+                            pScrn-&gt;virtualX, pScrn-&gt;virtualY,
+                            pScrn-&gt;xDpi, pScrn-&gt;yDpi,
+                            pScrn-&gt;displayWidth);
+        break;
+    case 16:
+        ret = cfb16ScreenInit(pScreen, FbBase,
+                              pScrn-&gt;virtualX, pScrn-&gt;virtualY,
+                              pScrn-&gt;xDpi, pScrn-&gt;yDpi,
+                              pScrn-&gt;displayWidth);
+        break;
+    case 24:
+        ret = cfb24ScreenInit(pScreen, FbBase,
+                              pScrn-&gt;virtualX, pScrn-&gt;virtualY,
+                              pScrn-&gt;xDpi, pScrn-&gt;yDpi,
+                              pScrn-&gt;displayWidth);
+        break;
+    case 32:
+        ret = cfb32ScreenInit(pScreen, FbBase,
+                              pScrn-&gt;virtualX, pScrn-&gt;virtualY,
+                              pScrn-&gt;xDpi, pScrn-&gt;yDpi,
+                              pScrn-&gt;displayWidth);
+        break;
+    default:
+        print a message about an internal error;
+        ret = FALSE;
+        break;
+    }
+
+    if (!ret)
+        return FALSE;
+
+    /* Override the default mask/offset settings */
+    if (pScrn-&gt;bitsPerPixel &gt; 8) {
+        for (i = 0, visual = pScreen-&gt;visuals;
+             i &lt; pScreen-&gt;numVisuals; i++, visual++) {
+            if ((visual-&gt;class | DynamicClass) == DirectColor) {
+                visual-&gt;offsetRed = pScrn-&gt;offset.red;
+                visual-&gt;offsetGreen = pScrn-&gt;offset.green;
+                visual-&gt;offsetBlue = pScrn-&gt;offset.blue;
+                visual-&gt;redMask = pScrn-&gt;mask.red;
+                visual-&gt;greenMask = pScrn-&gt;mask.green;
+                visual-&gt;blueMask = pScrn-&gt;mask.blue;
+            }
+        }
+    }
+
+    /*
+     * If banking is needed, initialise an miBankInfoRec (defined in
+     * "mibank.h"), and call miInitializeBanking().
+     */
+    if (!miInitializeBanking(pScreen, pScrn-&gt;virtualX, pScrn-&gt;virtualY,
+                                     pScrn-&gt;displayWidth, pBankInfo))
+        return FALSE;
+
+    /*
+     * If backing store is to be supported (as is usually the case),
+     * initialise it.
+     */
+    miInitializeBackingStore(pScreen);
+
+    /*
+     * Set initial black &amp; white colourmap indices.
+     */
+    xf86SetBlackWhitePixels(pScreen);
+
+    /*
+     * Install colourmap functions.  If using the vgahw module,
+     * vgaHandleColormaps would usually be called here.
+     */
+
+    ...
+
+    /*
+     * Initialise cursor functions.  This example is for the mi
+     * software cursor.
+     */
+    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+    /* Initialise the default colourmap */
+    switch (pScrn-&gt;depth) {
+    case 1:
+        if (!xf1bppCreateDefColormap(pScreen))
+            return FALSE;
+        break;
+    case 4:
+        if (!xf4bppCreateDefColormap(pScreen))
+            return FALSE;
+        break;
+    default:
+        if (!cfbCreateDefColormap(pScreen))
+            return FALSE;
+        break;
+    }
+
+    /*
+     * Wrap the CloseScreen vector and set SaveScreen.
+     */
+    ZZZPTR(pScrn)-&gt;CloseScreen = pScreen-&gt;CloseScreen;
+    pScreen-&gt;CloseScreen = ZZZCloseScreen;
+    pScreen-&gt;SaveScreen = ZZZSaveScreen;
+
+    /* Report any unused options (only for the first generation) */
+    if (serverGeneration == 1) {
+        xf86ShowUnusedOptions(pScrn-&gt;scrnIndex, pScrn-&gt;options);
+    }
+
+    /* Done */
+    return TRUE;
+}
+	</programlisting>
+      </sect3>
+
+      <sect3>
+	<title>SwitchMode</title>
+
+	<para>
+    Define the <function>SwitchMode()</function> function if mode switching
+    is supported by the driver.
+	</para>
+
+	<programlisting>
+static Bool
+ZZZSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+    return ZZZModeInit(xf86Screens[scrnIndex], mode);
+}
+	</programlisting>
+      </sect3>
+
+      <sect3>
+	<title>AdjustFrame</title>
+
+	<para>
+    Define the <function>AdjustFrame()</function> function if the driver
+    supports this.
+	</para>
+
+	<programlisting>
+static void
+ZZZAdjustFrame(int scrnIndex, int x, int y, int flags)
+{
+    /* Adjust the viewport */
+}
+	</programlisting>
+      </sect3>
+
+      <sect3>
+	<title>EnterVT, LeaveVT</title>
+
+	<para>
+    Define the <function>EnterVT()</function> and <function>LeaveVT()</function>
+    functions.
+	</para>
+
+	<para>
+    These functions are mandatory.
+	</para>
+
+	<programlisting>
+static Bool
+ZZZEnterVT(int scrnIndex, int flags)
+{
+    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+    return ZZZModeInit(pScrn, pScrn-&gt;currentMode);
+}
+
+static void
+ZZZLeaveVT(int scrnIndex, int flags)
+{
+    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+    ZZZRestore(pScrn);
+}
+	</programlisting>
+      </sect3>
+
+      <sect3>
+	<title>CloseScreen</title>
+
+	<para>
+    Define the <function>CloseScreen()</function> function:
+	</para>
+
+	<para>
+    This function is mandatory.  Note that it unwraps the previously
+    wrapped <structfield>pScreen-&gt;CloseScreen</structfield>, and finishes by
+    calling it.
+	</para>
+
+	<programlisting>
+static Bool
+ZZZCloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+    if (pScrn-&gt;vtSema) {
+        ZZZRestore(pScrn);
+        ZZZUnmapMem(pScrn);
+    }
+    pScrn-&gt;vtSema = FALSE;
+    pScreen-&gt;CloseScreen = ZZZPTR(pScrn)-&gt;CloseScreen;
+    return (*pScreen-&gt;CloseScreen)(scrnIndex, pScreen);
+}
+	</programlisting>
+      </sect3>
+
+      <sect3>
+	<title>SaveScreen</title>
+
+	<para>
+    Define the <function>SaveScreen()</function> function (the screen
+    blanking function).  When using the vgahw module, this will typically
+    be:
+
+	  <programlisting>
+static Bool
+ZZZSaveScreen(ScreenPtr pScreen, int mode)
+{
+    return vgaHWSaveScreen(pScreen, mode);
+}
+	  </programlisting>
+	</para>
+
+	<para>
+    This function is mandatory.  Before modifying any hardware register
+    directly this function needs to make sure that the Xserver is active
+    by checking if <parameter>pScrn</parameter> is non-NULL and for
+    <literal remap="tt">pScrn-&gt;vtSema == TRUE</literal>.
+	</para>
+      </sect3>
+
+      <sect3>
+	<title>FreeScreen</title>
+
+	<para>
+    Define the <function>FreeScreen()</function> function.  This function
+    is optional.  It should be defined if the <structname>ScrnInfoRec</structname>
+    <structfield>driverPrivate</structfield> field is used so that it can be freed
+    when a screen is deleted by the common layer for reasons possibly
+    beyond the driver's control.  This function is not used in during
+    normal (error free) operation.  The per-generation data is freed by
+    the <function>CloseScreen()</function> function.
+	</para>
+
+	<programlisting>
+static void
+ZZZFreeScreen(int scrnIndex, int flags)
+{
+    /*
+     * If the vgahw module is used vgaHWFreeHWRec() would be called
+     * here.
+     */
+    ZZZFreeRec(xf86Screens[scrnIndex]);
+}
+
+	</programlisting>
+
+      </sect3>
+
+    </sect2>
+
+  </sect1>
+
+</article>
diff --git a/hw/xfree86/doc/sgml/Makefile.am b/hw/xfree86/doc/sgml/Makefile.am
index 09b64f7..5322b42 100644
--- a/hw/xfree86/doc/sgml/Makefile.am
+++ b/hw/xfree86/doc/sgml/Makefile.am
@@ -19,36 +19,13 @@
 #  NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 #  CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-SGML_FILES = DESIGN.sgml
+XML_FILES = DESIGN.xml
 
-if BUILD_LINUXDOC
-TXT_FILES  = $(SGML_FILES:%.sgml=%.txt)
-PS_FILES   = $(SGML_FILES:%.sgml=%.ps)
-if BUILD_PDFDOC
-PDF_FILES  = $(SGML_FILES:%.sgml=%.pdf)
-endif
-HTML_FILES = $(SGML_FILES:%.sgml=%.html)
-
-SUFFIXES = .sgml .txt .html .ps .pdf
-
-.sgml.txt:
-	@rm -f $@
-	$(AM_V_GEN)$(MAKE_TEXT) $<
-
-.sgml.ps:
-	@rm -f $@
-	$(AM_V_GEN)$(MAKE_PS) $<
-
-.ps.pdf:
-	@rm -f $@
-	$(AM_V_GEN)$(MAKE_PDF) $<
-
-.sgml.html:
-	@rm -f $@
-	$(AM_V_GEN)$(MAKE_HTML) $<
+include ../../../../doc/xml/xmlrules.in
 
-noinst_DATA = $(TXT_FILES) $(PS_FILES) $(PDF_FILES) $(HTML_FILES)
-CLEANFILES = $(TXT_FILES) $(PS_FILES) $(PDF_FILES) $(HTML_FILES)
+if ENABLE_DEVEL_DOCS
+noinst_DATA = $(BUILT_DOC_FILES)
 endif
+CLEANFILES = $(CLEAN_DOC_FILES)
 
-EXTRA_DIST = $(SGML_FILES)
+EXTRA_DIST = $(XML_FILES)
commit ebd745ced89b2a2d9f6b4dcbd9f5f7e7f3b35451
Author: Simon Farnsworth <simon.farnsworth at onelan.com>
Date:   Thu May 20 09:58:38 2010 +0100

    Add documentation for the new DefaultModes option
    
    This patch adds documentation for the DefaultModes monitor option
    added in the previous patch.
    
    Signed-off-by: Simon Farnsworth <simon.farnsworth at onelan.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/doc/man/xorg.conf.man.pre b/hw/xfree86/doc/man/xorg.conf.man.pre
index f7ff6f6..5ff4ff2 100644
--- a/hw/xfree86/doc/man/xorg.conf.man.pre
+++ b/hw/xfree86/doc/man/xorg.conf.man.pre
@@ -1654,6 +1654,14 @@ at startup.  By default, the server will attempt to enable all connected
 monitors.
 (RandR 1.2-supporting drivers only)
 .TP 7
+.BI "Option " "\*qDefaultModes\*q  " \*qbool\*q
+This optional entry specifies whether the server should add supported default
+modes to the list of modes offered on this monitor. By default, the server
+will add default modes; you should only disable this if you can guarantee
+that EDID will be available at all times, or if you have added custom modelines
+which the server can use.
+(RandR 1.2-supporting drivers only)
+.TP 7
 .BI "Option " "\*qMinClock\*q  " \*qfrequency\*q
 This optional entry specifies the minimum dot clock, in kHz, that is supported
 by the monitor.
commit cfc629148891be317ba60f2495abcda485780191
Author: Simon Farnsworth <simon.farnsworth at onelan.com>
Date:   Thu May 20 09:58:37 2010 +0100

    Add configuration option to disable default modes on an output
    
    Setting 'Option "DefaultModes" "No"' in an output will guarantee that
    X will omit the default modes, just picking up modes from the
    configuration file and modes provided by the output.
    
    Signed-off-by: Simon Farnsworth <simon.farnsworth at onelan.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index ef7ed58..8b9ec41 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -439,6 +439,7 @@ typedef enum {
     OPTION_ROTATE,
     OPTION_PANNING,
     OPTION_PRIMARY,
+    OPTION_DEFAULT_MODES,
 } OutputOpts;
 
 static OptionInfoRec xf86OutputOptions[] = {
@@ -456,6 +457,7 @@ static OptionInfoRec xf86OutputOptions[] = {
     {OPTION_ROTATE,	    "Rotate",		OPTV_STRING,  {0}, FALSE },
     {OPTION_PANNING,	    "Panning",		OPTV_STRING,  {0}, FALSE },
     {OPTION_PRIMARY,	    "Primary",		OPTV_BOOLEAN, {0}, FALSE },
+    {OPTION_DEFAULT_MODES,  "DefaultModes",	OPTV_BOOLEAN, {0}, FALSE },
     {-1,		    NULL,		OPTV_NONE,    {0}, FALSE },
 };
 
@@ -1560,7 +1562,7 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
 	int		    min_clock = 0;
 	int		    max_clock = 0;
 	double		    clock;
-	Bool                add_default_modes = TRUE;
+	Bool		    add_default_modes = xf86ReturnOptValBool(output->options, OPTION_DEFAULT_MODES, TRUE);
 	Bool		    debug_modes = config->debug_modes ||
 					  xf86Initialising;
 	enum det_monrec_source sync_source = sync_default;
commit a1c2bdb6ab7a4f374844f80e83620b155991e817
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Thu May 20 10:13:06 2010 +0200

    EXA: Wrap Glyphs even without Composite acceleration.
    
    In order to avoid migration ping-pong when accumulating glyphs in a mask
    picture.
    
    Signed-off-by: Michel Dänzer <daenzer at vmware.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/exa/exa.c b/exa/exa.c
index 7b3b9a0..46a850f 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -932,8 +932,11 @@ exaDriverInit (ScreenPtr		pScreen,
 
     if (ps) {
 	wrap(pExaScr, ps, Composite, exaComposite);
-	if (pScreenInfo->PrepareComposite)
+	if (pScreenInfo->PrepareComposite) {
 	    wrap(pExaScr, ps, Glyphs, exaGlyphs);
+	} else {
+	    wrap(pExaScr, ps, Glyphs, ExaCheckGlyphs);
+	}
 	wrap(pExaScr, ps, Trapezoids, exaTrapezoids);
 	wrap(pExaScr, ps, Triangles, exaTriangles);
 	wrap(pExaScr, ps, AddTraps, ExaCheckAddTraps);
diff --git a/exa/exa_priv.h b/exa/exa_priv.h
index ed8be31..14c99e9 100644
--- a/exa/exa_priv.h
+++ b/exa/exa_priv.h
@@ -509,6 +509,17 @@ ExaCheckComposite (CARD8      op,
 		  CARD16     width,
 		  CARD16     height);
 
+void
+ExaCheckGlyphs (CARD8	      op,
+		PicturePtr    pSrc,
+		PicturePtr    pDst,
+		PictFormatPtr maskFormat,
+		INT16	      xSrc,
+		INT16	      ySrc,
+		int	      nlist,
+		GlyphListPtr  list,
+		GlyphPtr      *glyphs);
+
 /* exa_offscreen.c */
 void
 ExaOffscreenSwapOut (ScreenPtr pScreen);
diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c
index 2f8c462..402d76d 100644
--- a/exa/exa_unaccel.c
+++ b/exa/exa_unaccel.c
@@ -680,6 +680,28 @@ out_no_clip:
     EXA_POST_FALLBACK(pScreen);
 }
 
+/**
+ * Avoid migration ping-pong when using a mask.
+ */
+void
+ExaCheckGlyphs (CARD8	      op,
+		PicturePtr    pSrc,
+		PicturePtr    pDst,
+		PictFormatPtr maskFormat,
+		INT16	      xSrc,
+		INT16	      ySrc,
+		int	      nlist,
+		GlyphListPtr  list,
+		GlyphPtr      *glyphs)
+{
+    ScreenPtr pScreen = pDst->pDrawable->pScreen;
+    EXA_PRE_FALLBACK(pScreen);
+
+    miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
+
+    EXA_POST_FALLBACK(pScreen);
+}
+
 void
 ExaCheckAddTraps (PicturePtr	pPicture,
 		  INT16		x_off,
commit 00581d4a42e2a0e7652834973645a4a9ed59cf93
Author: Tiago Vignatti <tiago.vignatti at nokia.com>
Date:   Fri May 14 19:31:56 2010 +0300

    configure: force new xproto version dependency
    
    commit bca85e2e127a8a23e3a2debcfeb3ae07cd3c66ac introduced it.
    
    Use the version that includes _X_NORETURN
    
    Signed-off-by: Tiago Vignatti <tiago.vignatti at nokia.com>
    Reviewed-by: Julien Cristau <jcristau at debian.org>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index 1c7875e..4aafceb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -793,7 +793,7 @@ WINDOWSWMPROTO="windowswmproto"
 APPLEWMPROTO="applewmproto >= 1.4"
 
 dnl Core modules for most extensions, et al.
-REQUIRED_MODULES="[randrproto >= 1.2.99.3] [renderproto >= 0.11] [fixesproto >= 4.1] [damageproto >= 1.1] [xcmiscproto >= 1.2.0] [xextproto >= 7.0.99.3] [xproto >= 7.0.13] [xtrans >= 1.2.2] [bigreqsproto >= 1.1.0] fontsproto [inputproto >= 1.9.99.902] [kbproto >= 1.0.3]"
+REQUIRED_MODULES="[randrproto >= 1.2.99.3] [renderproto >= 0.11] [fixesproto >= 4.1] [damageproto >= 1.1] [xcmiscproto >= 1.2.0] [xextproto >= 7.0.99.3] [xproto >= 7.0.17] [xtrans >= 1.2.2] [bigreqsproto >= 1.1.0] fontsproto [inputproto >= 1.9.99.902] [kbproto >= 1.0.3]"
 REQUIRED_LIBS="xfont xau [pixman-1 >= 0.15.20]"
 
 dnl List of libraries that require a specific version
commit 103507af0c0ce7d7482a67163249864af36a2374
Merge: 8bd8d81... 99fcf65...
Author: Keith Packard <keithp at keithp.com>
Date:   Wed May 19 22:27:53 2010 -0700

    Merge remote branch 'vignatti/bus-cleanup'

commit 8bd8d81dc473bf72ea108b1896a55e32defa02e2
Merge: c620a1c... 66d5ecc...
Author: Keith Packard <keithp at keithp.com>
Date:   Wed May 19 22:27:20 2010 -0700

    Merge remote branch 'vignatti/animcursor-state-fix'

commit c620a1c0a4ca564e778cce019dd30046c6969956
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu May 20 10:26:56 2010 +1000

    xfree86: fix typo in optionTypeToSting.
    
    Because we don't want anyone to get hurt.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Dan Nicholson <dbn.lists at gmail.com>
    Reviewed-by: Matt Turner <mattst88 at gmail.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/common/xf86Configure.c b/hw/xfree86/common/xf86Configure.c
index c590bda..7d4c341 100644
--- a/hw/xfree86/common/xf86Configure.c
+++ b/hw/xfree86/common/xf86Configure.c
@@ -322,7 +322,7 @@ configureScreenSection (int screennum)
 }
 
 static const char* 
-optionTypeToSting(OptionValueType type)
+optionTypeToString(OptionValueType type)
 {
     switch (type) {
     case OPTV_NONE:
@@ -397,7 +397,7 @@ configureDeviceSection (int screennum)
 		const char *prefix = "        #Option     ";
 		const char *middle = " \t# ";
 		const char *suffix = "\n";
-		const char *opttype = optionTypeToSting(p->type);
+		const char *opttype = optionTypeToString(p->type);
 		char *optname;
 		int len = strlen(ptr->dev_comment) + strlen(prefix) +
 			  strlen(middle) + strlen(suffix) + 1;
commit 8b6c1809c09f832051327d86e1a25dc0ec5cc878
Merge: d88ba77... c38552d...
Author: Keith Packard <keithp at keithp.com>
Date:   Wed May 19 12:58:02 2010 -0700

    Merge remote branch 'jamey/for-keith'

commit c38552d115e3bc71ad6179a8ad0d68778e943793
Author: Jamey Sharp <jamey at minilop.net>
Date:   Sat Apr 24 23:56:36 2010 -0700

    Add typed resource-lookup errors for non-core resource types.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/Xext/panoramiX.c b/Xext/panoramiX.c
index 31286d4..edcbb49 100644
--- a/Xext/panoramiX.c
+++ b/Xext/panoramiX.c
@@ -519,6 +519,10 @@ void PanoramiXExtensionInit(int argc, char *argv[])
 	    panoramiXGeneration = serverGeneration;
 	    success = TRUE;
 	}
+	SetResourceTypeErrorValue(XRT_WINDOW, BadWindow);
+	SetResourceTypeErrorValue(XRT_PIXMAP, BadPixmap);
+	SetResourceTypeErrorValue(XRT_GC, BadGC);
+	SetResourceTypeErrorValue(XRT_COLORMAP, BadColor);
     }
 
     if (!success) {
diff --git a/Xext/panoramiXprocs.c b/Xext/panoramiXprocs.c
index dbaae26..8752ca5 100644
--- a/Xext/panoramiXprocs.c
+++ b/Xext/panoramiXprocs.c
@@ -74,7 +74,7 @@ int PanoramiXCreateWindow(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&parent, stuff->parent,
 				     XRT_WINDOW, client, DixWriteAccess);
     if (result != Success)
-        return (result == BadValue) ? BadWindow : result;
+        return result;
 
     if(stuff->class == CopyFromParent)
 	stuff->class = parent->u.win.class;
@@ -89,7 +89,7 @@ int PanoramiXCreateWindow(ClientPtr client)
 	    result = dixLookupResourceByType((pointer *)&backPix, tmp,
 					     XRT_PIXMAP, client, DixReadAccess);
 	    if (result != Success)
-		return (result == BadValue) ? BadPixmap : result;
+		return result;
 	}
     }
     if ((Mask)stuff->mask & CWBorderPixmap) {
@@ -99,7 +99,7 @@ int PanoramiXCreateWindow(ClientPtr client)
 	    result = dixLookupResourceByType((pointer *)&bordPix, tmp,
 					     XRT_PIXMAP, client, DixReadAccess);
 	    if (result != Success)
-		return (result == BadValue) ? BadPixmap : result;
+		return result;
 	}
     }
     if ((Mask)stuff->mask & CWColormap) {
@@ -109,7 +109,7 @@ int PanoramiXCreateWindow(ClientPtr client)
 	    result = dixLookupResourceByType((pointer *)&cmap, tmp,
 					     XRT_COLORMAP, client, DixReadAccess);
 	    if (result != Success)
-		return (result == BadValue) ? BadColor : result;
+		return result;
 	}
     }
 
@@ -179,7 +179,7 @@ int PanoramiXChangeWindowAttributes(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&win, stuff->window,
 				     XRT_WINDOW, client, DixWriteAccess);
     if (result != Success)
-        return (result == BadValue) ? BadWindow : result;
+        return result;
 
     if((win->u.win.class == InputOnly) && 
        (stuff->valueMask & (~INPUTONLY_LEGAL_MASK)))
@@ -192,7 +192,7 @@ int PanoramiXChangeWindowAttributes(ClientPtr client)
 	    result = dixLookupResourceByType((pointer *)&backPix, tmp,
 					     XRT_PIXMAP, client, DixReadAccess);
 	    if (result != Success)
-		return (result == BadValue) ? BadPixmap : result;
+		return result;
 	}
     }
     if ((Mask)stuff->valueMask & CWBorderPixmap) {
@@ -202,7 +202,7 @@ int PanoramiXChangeWindowAttributes(ClientPtr client)
 	    result = dixLookupResourceByType((pointer *)&bordPix, tmp,
 					     XRT_PIXMAP, client, DixReadAccess);
 	    if (result != Success)
-		return (result == BadValue) ? BadPixmap : result;
+		return result;
 	}
     }
     if ((Mask)stuff->valueMask & CWColormap) {
@@ -212,7 +212,7 @@ int PanoramiXChangeWindowAttributes(ClientPtr client)
 	    result = dixLookupResourceByType((pointer *)&cmap, tmp,
 					     XRT_COLORMAP, client, DixReadAccess);
 	    if (result != Success)
-		return (result == BadValue) ? BadColor : result;
+		return result;
 	}
     }
 
@@ -242,7 +242,7 @@ int PanoramiXDestroyWindow(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&win, stuff->id, XRT_WINDOW,
 				     client, DixDestroyAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     FOR_NSCREENS_BACKWARD(j) {
 	stuff->id = win->info[j].id;
@@ -268,7 +268,7 @@ int PanoramiXDestroySubwindows(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&win, stuff->id, XRT_WINDOW,
 				     client, DixDestroyAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     FOR_NSCREENS_BACKWARD(j) {
 	stuff->id = win->info[j].id;
@@ -294,7 +294,7 @@ int PanoramiXChangeSaveSet(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&win, stuff->window,
 				     XRT_WINDOW, client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     FOR_NSCREENS_BACKWARD(j) {
 	stuff->window = win->info[j].id;
@@ -319,12 +319,12 @@ int PanoramiXReparentWindow(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&win, stuff->window,
 				     XRT_WINDOW, client, DixWriteAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     result = dixLookupResourceByType((pointer *)&parent, stuff->parent,
 				     XRT_WINDOW, client, DixWriteAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     x = stuff->x;
     y = stuff->y;
@@ -356,7 +356,7 @@ int PanoramiXMapWindow(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&win, stuff->id,
 				     XRT_WINDOW, client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     FOR_NSCREENS_FORWARD(j) {
 	stuff->id = win->info[j].id;
@@ -379,7 +379,7 @@ int PanoramiXMapSubwindows(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&win, stuff->id,
 				     XRT_WINDOW, client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     FOR_NSCREENS_FORWARD(j) {
 	stuff->id = win->info[j].id;
@@ -402,7 +402,7 @@ int PanoramiXUnmapWindow(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&win, stuff->id,
 				     XRT_WINDOW, client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     FOR_NSCREENS_FORWARD(j) {
 	stuff->id = win->info[j].id;
@@ -425,7 +425,7 @@ int PanoramiXUnmapSubwindows(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&win, stuff->id,
 				     XRT_WINDOW, client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     FOR_NSCREENS_FORWARD(j) {
 	stuff->id = win->info[j].id;
@@ -462,7 +462,7 @@ int PanoramiXConfigureWindow(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&win, stuff->window,
 				     XRT_WINDOW, client, DixWriteAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     if ((Mask)stuff->mask & CWSibling) {
 	XID tmp;
@@ -471,7 +471,7 @@ int PanoramiXConfigureWindow(ClientPtr client)
 	    result = dixLookupResourceByType((pointer *)&sib, tmp, XRT_WINDOW,
 					     client, DixReadAccess);
 	    if (result != Success)
-		return (result == BadValue) ? BadWindow : result;
+		return result;
 	}
     }
 
@@ -517,7 +517,7 @@ int PanoramiXCirculateWindow(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&win, stuff->window,
 				     XRT_WINDOW, client, DixWriteAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     FOR_NSCREENS_FORWARD(j) {
 	stuff->window = win->info[j].id;
@@ -697,7 +697,7 @@ int PanoramiXFreePixmap(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&pix, stuff->id, XRT_PIXMAP,
 				     client, DixDestroyAccess);
     if (result != Success)
-	return (result == BadValue) ? BadPixmap : result;
+	return result;
 
     FOR_NSCREENS_BACKWARD(j) {
 	stuff->id = pix->info[j].id;
@@ -742,7 +742,7 @@ int PanoramiXCreateGC(ClientPtr client)
 	    result = dixLookupResourceByType((pointer *)&tile, tmp, XRT_PIXMAP,
 					     client, DixReadAccess);
 	    if (result != Success)
-		return (result == BadValue) ? BadPixmap : result;
+		return result;
 	}
     }
     if ((Mask)stuff->mask & GCStipple) {
@@ -751,7 +751,7 @@ int PanoramiXCreateGC(ClientPtr client)
 	    result = dixLookupResourceByType((pointer *)&stip, tmp, XRT_PIXMAP,
 					     client, DixReadAccess);
 	    if (result != Success)
-		return (result == BadValue) ? BadPixmap : result;
+		return result;
 	}
     }
     if ((Mask)stuff->mask & GCClipMask) {
@@ -760,7 +760,7 @@ int PanoramiXCreateGC(ClientPtr client)
 	    result = dixLookupResourceByType((pointer *)&clip, tmp, XRT_PIXMAP,
 					     client, DixReadAccess);
 	    if (result != Success)
-		return (result == BadValue) ? BadPixmap : result;
+		return result;
 	}
     }
 
@@ -813,7 +813,7 @@ int PanoramiXChangeGC(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				     client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     if ((Mask)stuff->mask & GCTile) {
 	tile_offset = Ones((Mask)stuff->mask & (GCTile - 1));
@@ -821,7 +821,7 @@ int PanoramiXChangeGC(ClientPtr client)
 	    result = dixLookupResourceByType((pointer *)&tile, tmp, XRT_PIXMAP,
 					     client, DixReadAccess);
 	    if (result != Success)
-		return (result == BadValue) ? BadPixmap : result;
+		return result;
 	}
     }
     if ((Mask)stuff->mask & GCStipple) {
@@ -830,7 +830,7 @@ int PanoramiXChangeGC(ClientPtr client)
 	    result = dixLookupResourceByType((pointer *)&stip, tmp, XRT_PIXMAP,
 					     client, DixReadAccess);
 	    if (result != Success)
-		return (result == BadValue) ? BadPixmap : result;
+		return result;
 	}
     }
     if ((Mask)stuff->mask & GCClipMask) {
@@ -839,7 +839,7 @@ int PanoramiXChangeGC(ClientPtr client)
 	    result = dixLookupResourceByType((pointer *)&clip, tmp, XRT_PIXMAP,
 					     client, DixReadAccess);
 	    if (result != Success)
-		return (result == BadValue) ? BadPixmap : result;
+		return result;
 	}
     }
 
@@ -871,12 +871,12 @@ int PanoramiXCopyGC(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&srcGC, stuff->srcGC, XRT_GC,
 				     client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     result = dixLookupResourceByType((pointer *)&dstGC, stuff->dstGC, XRT_GC,
 				     client, DixWriteAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     FOR_NSCREENS(j) {
 	stuff->srcGC = srcGC->info[j].id;
@@ -900,7 +900,7 @@ int PanoramiXSetDashes(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				     client, DixWriteAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     FOR_NSCREENS_BACKWARD(j) {
 	stuff->gc = gc->info[j].id;
@@ -923,7 +923,7 @@ int PanoramiXSetClipRectangles(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				     client, DixWriteAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     FOR_NSCREENS_BACKWARD(j) {
 	stuff->gc = gc->info[j].id;
@@ -946,7 +946,7 @@ int PanoramiXFreeGC(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->id, XRT_GC,
 				     client, DixDestroyAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     FOR_NSCREENS_BACKWARD(j) {
 	stuff->id = gc->info[j].id;
@@ -973,7 +973,7 @@ int PanoramiXClearToBackground(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&win, stuff->window,
 				     XRT_WINDOW, client, DixWriteAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     x = stuff->x;
     y = stuff->y;
@@ -1033,7 +1033,7 @@ int PanoramiXCopyArea(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				     client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     if((dst->type == XRT_WINDOW) && dst->u.win.root)
 	dstIsRoot = TRUE;
@@ -1188,7 +1188,7 @@ int PanoramiXCopyPlane(ClientPtr client)
     rc = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				 client, DixReadAccess);
     if (rc != Success)
-	return (rc == BadValue) ? BadGC : rc;
+	return rc;
 
     if((dst->type == XRT_WINDOW) && dst->u.win.root)
 	dstIsRoot = TRUE;
@@ -1285,7 +1285,7 @@ int PanoramiXPolyPoint(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				     client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
     npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq));
@@ -1345,7 +1345,7 @@ int PanoramiXPolyLine(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				     client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
     npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq));
@@ -1405,7 +1405,7 @@ int PanoramiXPolySegment(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				     client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
 
@@ -1468,7 +1468,7 @@ int PanoramiXPolyRectangle(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				     client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
 
@@ -1530,7 +1530,7 @@ int PanoramiXPolyArc(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				     client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
 
@@ -1590,7 +1590,7 @@ int PanoramiXFillPoly(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				     client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
 
@@ -1651,7 +1651,7 @@ int PanoramiXPolyFillRectangle(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				     client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
 
@@ -1712,7 +1712,7 @@ int PanoramiXPolyFillArc(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				     client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
 
@@ -1772,7 +1772,7 @@ int PanoramiXPutImage(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				     client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
 
@@ -1973,7 +1973,7 @@ PanoramiXPolyText8(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				     client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
 
@@ -2014,7 +2014,7 @@ PanoramiXPolyText16(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				     client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
 
@@ -2055,7 +2055,7 @@ int PanoramiXImageText8(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				     client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
 
@@ -2096,7 +2096,7 @@ int PanoramiXImageText16(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				     client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadGC : result;
+	return result;
 
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
 
@@ -2128,7 +2128,7 @@ int PanoramiXCreateColormap(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&win, stuff->window,
 				     XRT_WINDOW, client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     if(!(newCmap = malloc(sizeof(PanoramiXRes))))
         return BadAlloc;
@@ -2169,7 +2169,7 @@ int PanoramiXFreeColormap(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&cmap, stuff->id, XRT_COLORMAP,
 				     client, DixDestroyAccess);
     if (result != Success)
-        return (result == BadValue) ? BadColor : result;
+        return result;
 
     FOR_NSCREENS_BACKWARD(j) {
         stuff->id = cmap->info[j].id;
@@ -2199,7 +2199,7 @@ PanoramiXCopyColormapAndFree(ClientPtr client)
 				     XRT_COLORMAP, client,
 				     DixReadAccess | DixWriteAccess);
     if (result != Success)
-        return (result == BadValue) ? BadColor : result;
+        return result;
 
     if(!(newCmap = malloc(sizeof(PanoramiXRes))))
         return BadAlloc;
@@ -2238,7 +2238,7 @@ int PanoramiXInstallColormap(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&cmap, stuff->id, XRT_COLORMAP,
 				     client, DixReadAccess);
     if (result != Success)
-        return (result == BadValue) ? BadColor : result;
+        return result;
 
     FOR_NSCREENS_BACKWARD(j){
 	stuff->id = cmap->info[j].id;
@@ -2262,7 +2262,7 @@ int PanoramiXUninstallColormap(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&cmap, stuff->id, XRT_COLORMAP,
 				     client, DixReadAccess);
     if (result != Success)
-        return (result == BadValue) ? BadColor : result;
+        return result;
 
     FOR_NSCREENS_BACKWARD(j) {
 	stuff->id = cmap->info[j].id;
@@ -2286,7 +2286,7 @@ int PanoramiXAllocColor(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap,
 				     XRT_COLORMAP, client, DixWriteAccess);
     if (result != Success)
-        return (result == BadValue) ? BadColor : result;
+        return result;
 
     FOR_NSCREENS_BACKWARD(j){
 	stuff->cmap = cmap->info[j].id;
@@ -2310,7 +2310,7 @@ int PanoramiXAllocNamedColor(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap,
 				     XRT_COLORMAP, client, DixWriteAccess);
     if (result != Success)
-        return (result == BadValue) ? BadColor : result;
+        return result;
 
     FOR_NSCREENS_BACKWARD(j){
         stuff->cmap = cmap->info[j].id;
@@ -2334,7 +2334,7 @@ int PanoramiXAllocColorCells(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap,
 				     XRT_COLORMAP, client, DixWriteAccess);
     if (result != Success)
-        return (result == BadValue) ? BadColor : result;
+        return result;
 	
     FOR_NSCREENS_BACKWARD(j){
 	stuff->cmap = cmap->info[j].id;
@@ -2358,7 +2358,7 @@ int PanoramiXAllocColorPlanes(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap,
 				     XRT_COLORMAP, client, DixWriteAccess);
     if (result != Success)
-        return (result == BadValue) ? BadColor : result;
+        return result;
 	
     FOR_NSCREENS_BACKWARD(j){
 	stuff->cmap = cmap->info[j].id;
@@ -2383,7 +2383,7 @@ int PanoramiXFreeColors(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap,
 				     XRT_COLORMAP, client, DixWriteAccess);
     if (result != Success)
-        return (result == BadValue) ? BadColor : result;
+        return result;
 
     FOR_NSCREENS_BACKWARD(j) {
         stuff->cmap = cmap->info[j].id;
@@ -2406,7 +2406,7 @@ int PanoramiXStoreColors(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap,
 				     XRT_COLORMAP, client, DixWriteAccess);
     if (result != Success)
-        return (result == BadValue) ? BadColor : result;
+        return result;
 
     FOR_NSCREENS_BACKWARD(j){
 	stuff->cmap = cmap->info[j].id;
@@ -2430,7 +2430,7 @@ int PanoramiXStoreNamedColor(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap,
 				     XRT_COLORMAP, client, DixWriteAccess);
     if (result != Success)
-        return (result == BadValue) ? BadColor : result;
+        return result;
 
     FOR_NSCREENS_BACKWARD(j){
 	stuff->cmap = cmap->info[j].id;
diff --git a/Xext/saver.c b/Xext/saver.c
index 63a41d6..fdcbac5 100644
--- a/Xext/saver.c
+++ b/Xext/saver.c
@@ -1272,7 +1272,7 @@ ProcScreenSaverSetAttributes (ClientPtr client)
 					       XRT_PIXMAP, client,
 					       DixReadAccess);
 	      if (status != Success)
-		  return (status == BadValue) ? BadPixmap : status;
+		  return status;
           }
        }
 
@@ -1284,7 +1284,7 @@ ProcScreenSaverSetAttributes (ClientPtr client)
 					       XRT_PIXMAP, client,
 					       DixReadAccess);
 	      if (status != Success)
-		  return (status == BadValue) ? BadPixmap : status;
+		  return status;
           }
        }
 
@@ -1296,7 +1296,7 @@ ProcScreenSaverSetAttributes (ClientPtr client)
 						XRT_COLORMAP, client,
 						DixReadAccess);
 	       if (status != Success)
-		   return (status == BadValue) ? BadColor : status;
+		   return status;
            }
        }
 
diff --git a/Xext/security.c b/Xext/security.c
index 32730e2..e58ba10 100644
--- a/Xext/security.c
+++ b/Xext/security.c
@@ -623,8 +623,7 @@ ProcSecurityRevokeAuthorization(
 				 SecurityAuthorizationResType, client,
 				 DixDestroyAccess);
     if (rc != Success)
-	return (rc == BadValue) ?
-	    SecurityErrorBase + XSecurityBadAuthorization : rc;
+	return rc;
 
     FreeResource(stuff->authId, RT_NONE);
     return Success;
@@ -1140,6 +1139,8 @@ SecurityExtensionInit(INITARGS)
     EventSwapVector[SecurityEventBase + XSecurityAuthorizationRevoked] =
 	(EventSwapPtr)SwapSecurityAuthorizationRevokedEvent;
 
+    SetResourceTypeErrorValue(SecurityAuthorizationResType, SecurityErrorBase + XSecurityBadAuthorization);
+
     /* Label objects that were created before we could register ourself */
     SecurityLabelInitial();
 }
diff --git a/Xext/shape.c b/Xext/shape.c
index f49e9a0..93e4703 100644
--- a/Xext/shape.c
+++ b/Xext/shape.c
@@ -360,7 +360,7 @@ ProcPanoramiXShapeRectangles(
     result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW,
 				     client, DixWriteAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     FOR_NSCREENS(j) {
 	stuff->dest = win->info[j].id;
@@ -459,13 +459,13 @@ ProcPanoramiXShapeMask(
     result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW,
 				     client, DixWriteAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     if(stuff->src != None) {
 	result = dixLookupResourceByType((pointer *)&pmap, stuff->src,
 					 XRT_PIXMAP, client, DixReadAccess);
 	if (result != Success)
-	    return (result == BadValue) ? BadPixmap : result;
+	    return result;
     } else
 	pmap = NULL;
 
@@ -589,12 +589,12 @@ ProcPanoramiXShapeCombine(
     result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW,
 				     client, DixWriteAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     result = dixLookupResourceByType((pointer *)&win2, stuff->src, XRT_WINDOW,
 				     client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     FOR_NSCREENS(j) {
 	stuff->dest = win->info[j].id;
@@ -663,7 +663,7 @@ ProcPanoramiXShapeOffset(
     result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW,
 				     client, DixWriteAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     FOR_NSCREENS(j) {
 	stuff->dest = win->info[j].id;
diff --git a/Xext/shm.c b/Xext/shm.c
index b2c4208..3d9c633 100644
--- a/Xext/shm.c
+++ b/Xext/shm.c
@@ -156,7 +156,7 @@ static ShmFuncs fbFuncs = {fbShmCreatePixmap, NULL};
     rc = dixLookupResourceByType((pointer *)&(shmdesc), shmseg, ShmSegType, \
                                  client, DixReadAccess); \
     if (rc != Success) \
-	return (rc == BadValue) ? BadShmSegCode : rc; \
+	return rc; \
 }
 
 #define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \
@@ -286,6 +286,7 @@ ShmExtensionInit(INITARGS)
 	ShmReqCode = (unsigned char)extEntry->base;
 	ShmCompletionCode = extEntry->eventBase;
 	BadShmSegCode = extEntry->errorBase;
+	SetResourceTypeErrorValue(ShmSegType, BadShmSegCode);
 	EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent;
     }
 }
@@ -584,7 +585,7 @@ ProcPanoramiXShmPutImage(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
 				     XRT_GC, client, DixReadAccess);
     if (result != Success)
-        return (result == BadValue) ? BadGC : result;
+        return result;
 
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
 
diff --git a/Xext/sync.c b/Xext/sync.c
index f7ac405..a51262a 100644
--- a/Xext/sync.c
+++ b/Xext/sync.c
@@ -264,7 +264,7 @@ SyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XSyncCounter counter,
 				counter, RTCounter, client, DixReadAccess)))
 	{
 	    client->errorValue = counter;
-	    return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc;
+	    return rc;
 	}
 	if (pCounter != pTrigger->pCounter)
 	{ /* new counter for trigger */
@@ -1328,7 +1328,7 @@ ProcSyncSetCounter(ClientPtr client)
     rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter,
 				 client, DixWriteAccess);
     if (rc != Success)
-	return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc;
+	return rc;
 
     if (IsSystemCounter(pCounter))
     {
@@ -1358,7 +1358,7 @@ ProcSyncChangeCounter(ClientPtr client)
     rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter,
 				 client, DixWriteAccess);
     if (rc != Success)
-	return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc;
+	return rc;
 
     if (IsSystemCounter(pCounter))
     {
@@ -1393,7 +1393,7 @@ ProcSyncDestroyCounter(ClientPtr client)
     rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, RTCounter,
 				 client, DixDestroyAccess);
     if (rc != Success)
-	return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc;
+	return rc;
 
     if (IsSystemCounter(pCounter))
     {
@@ -1536,7 +1536,7 @@ ProcSyncQueryCounter(ClientPtr client)
     rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter,
 				 RTCounter, client, DixReadAccess);
     if (rc != Success)
-	return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc;
+	return rc;
 
     rep.type = X_Reply;
     rep.length = 0;
@@ -1660,7 +1660,7 @@ ProcSyncChangeAlarm(ClientPtr client)
     status = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
 				     client, DixWriteAccess);
     if (status != Success)
-	return (status == BadValue) ? SyncErrorBase + XSyncBadAlarm : status;
+	return status;
 
     vmask = stuff->valueMask;
     len = client->req_len - bytes_to_int32(sizeof(xSyncChangeAlarmReq));
@@ -1699,7 +1699,7 @@ ProcSyncQueryAlarm(ClientPtr client)
     rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
 				 client, DixReadAccess);
     if (rc != Success)
-	return (rc == BadValue) ? SyncErrorBase + XSyncBadAlarm : rc;
+	return rc;
 
     rep.type = X_Reply;
     rep.length = bytes_to_int32(sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply));
@@ -1756,7 +1756,7 @@ ProcSyncDestroyAlarm(ClientPtr client)
     rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
 				 client, DixDestroyAccess);
     if (rc != Success)
-	return (rc == BadValue) ? SyncErrorBase + XSyncBadAlarm : rc;
+	return rc;
 
     FreeResource(stuff->alarm, RT_NONE);
     return Success;
@@ -2127,6 +2127,9 @@ SyncExtensionInit(void)
     EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent;
     EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent;
 
+    SetResourceTypeErrorValue(RTCounter, SyncErrorBase + XSyncBadCounter);
+    SetResourceTypeErrorValue(RTAlarm, SyncErrorBase + XSyncBadAlarm);
+
     /*
      * Although SERVERTIME is implemented by the OS layer, we initialise it
      * here because doing it in OsInit() is too early. The resource database
diff --git a/Xext/xvdisp.c b/Xext/xvdisp.c
index 250a994..d7338ad 100644
--- a/Xext/xvdisp.c
+++ b/Xext/xvdisp.c
@@ -1025,7 +1025,6 @@ typedef struct _ShmDesc {
 } ShmDescRec, *ShmDescPtr;
 
 extern RESTYPE ShmSegType;
-extern int BadShmSegCode;
 extern int ShmCompletionCode;
 
 static int 
@@ -1077,7 +1076,7 @@ ProcXvShmPutImage(ClientPtr client)
   status = dixLookupResourceByType((pointer *)&shmdesc, stuff->shmseg,
 				   ShmSegType, serverClient, DixReadAccess);
   if (status != Success)
-      return (status == BadValue) ? BadShmSegCode : status;
+      return status;
  
   width = stuff->width;
   height = stuff->height;
@@ -1615,7 +1614,7 @@ XineramaXvStopVideo(ClientPtr client)
    result = dixLookupResourceByType((pointer *)&port, stuff->port,
 				    XvXRTPort, client, DixReadAccess);
    if (result != Success)
-       return (result == BadValue) ? _XvBadPort : result;
+       return result;
 
    FOR_NSCREENS_BACKWARD(i) {
 	if(port->info[i].id) {
@@ -1640,7 +1639,7 @@ XineramaXvSetPortAttribute(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&port, stuff->port,
 				     XvXRTPort, client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? _XvBadPort : result;
+	return result;
 
     FOR_NSCREENS_BACKWARD(i) {
 	if(port->info[i].id) {
@@ -1671,12 +1670,12 @@ XineramaXvShmPutImage(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
 				     XRT_GC, client, DixReadAccess);
     if (result != Success)
-        return (result == BadValue) ? BadGC : result;
+        return result;
 
     result = dixLookupResourceByType((pointer *)&port, stuff->port,
 				     XvXRTPort, client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? _XvBadPort : result;
+	return result;
  
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
 
@@ -1723,12 +1722,12 @@ XineramaXvPutImage(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
 				     XRT_GC, client, DixReadAccess);
     if (result != Success)
-        return (result == BadValue) ? BadGC : result;
+        return result;
 
     result = dixLookupResourceByType((pointer *)&port, stuff->port,
 				     XvXRTPort, client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? _XvBadPort : result;
+	return result;
  
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
 
@@ -1771,12 +1770,12 @@ XineramaXvPutVideo(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
 				     XRT_GC, client, DixReadAccess);
     if (result != Success)
-        return (result == BadValue) ? BadGC : result;
+        return result;
 
     result = dixLookupResourceByType((pointer *)&port, stuff->port,
 				     XvXRTPort, client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? _XvBadPort : result;
+	return result;
 
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
 
@@ -1819,12 +1818,12 @@ XineramaXvPutStill(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
 				     XRT_GC, client, DixReadAccess);
     if (result != Success)
-        return (result == BadValue) ? BadGC : result;
+        return result;
 
     result = dixLookupResourceByType((pointer *)&port, stuff->port,
 				     XvXRTPort, client, DixReadAccess);
     if (result != Success)
-	return (result == BadValue) ? _XvBadPort : result;
+	return result;
 
     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
 
@@ -1910,6 +1909,7 @@ void XineramifyXv(void)
    XvXRTPort = CreateNewResourceType(XineramaDeleteResource, "XvXRTPort");
 
    if (!xvsp0 || !XvXRTPort) return;
+   SetResourceTypeErrorValue(XvXRTPort, _XvBadPort);
 
    for(i = 0; i < xvsp0->nAdaptors; i++) {
       Bool isOverlay;
diff --git a/Xext/xvdix.h b/Xext/xvdix.h
index 44f8f6b..a210615 100644
--- a/Xext/xvdix.h
+++ b/Xext/xvdix.h
@@ -206,7 +206,7 @@ typedef struct _XvPortRec {
 	int rc = dixLookupResourceByType((pointer *)&(pPort), portID,\
 	                                 XvRTPort, client, mode);\
 	if (rc != Success)\
-	    return (rc == BadValue) ? _XvBadPort : rc;\
+	    return rc;\
     }
 
 typedef struct {
diff --git a/Xext/xvmain.c b/Xext/xvmain.c
index f6d39d0..9a367bd 100644
--- a/Xext/xvmain.c
+++ b/Xext/xvmain.c
@@ -192,6 +192,7 @@ XvExtensionInit(void)
       EventSwapVector[XvEventBase+XvPortNotify] = 
 	(EventSwapPtr)WriteSwappedPortNotifyEvent;
 
+      SetResourceTypeErrorValue(XvRTPort, _XvBadPort);
       (void)MakeAtom(XvName, strlen(XvName), xTrue);
 
     }
diff --git a/Xext/xvmc.c b/Xext/xvmc.c
index abb8e02..7550386 100644
--- a/Xext/xvmc.c
+++ b/Xext/xvmc.c
@@ -40,7 +40,6 @@ unsigned long XvMCGeneration = 0;
 
 int XvMCReqCode;
 int XvMCEventBase;
-int XvMCErrorBase;
 
 unsigned long XvMCRTContext;
 unsigned long XvMCRTSurface;
@@ -276,7 +275,7 @@ ProcXvMCDestroyContext(ClientPtr client)
     rc = dixLookupResourceByType(&val, stuff->context_id, XvMCRTContext,
 				 client, DixDestroyAccess);
     if (rc != Success)
-	return (rc == BadValue) ? XvMCBadContext + XvMCErrorBase : rc;
+	return rc;
 
     FreeResource(stuff->context_id, RT_NONE); 
 
@@ -299,7 +298,7 @@ ProcXvMCCreateSurface(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&pContext, stuff->context_id,
 				     XvMCRTContext, client, DixUseAccess);
     if (result != Success)
-        return (result == BadValue) ? XvMCBadContext + XvMCErrorBase : result;
+        return result;
 
     pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
 
@@ -346,7 +345,7 @@ ProcXvMCDestroySurface(ClientPtr client)
     rc = dixLookupResourceByType(&val, stuff->surface_id, XvMCRTSurface,
 				 client, DixDestroyAccess);
     if (rc != Success)
-        return (rc == BadValue) ? XvMCBadSurface + XvMCErrorBase : rc;
+        return rc;
 
     FreeResource(stuff->surface_id, RT_NONE);
 
@@ -371,7 +370,7 @@ ProcXvMCCreateSubpicture(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&pContext, stuff->context_id,
 				     XvMCRTContext, client, DixUseAccess);
     if (result != Success)
-        return (result == BadValue) ? XvMCBadContext + XvMCErrorBase : result;
+        return result;
 
     pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
 
@@ -463,7 +462,7 @@ ProcXvMCDestroySubpicture(ClientPtr client)
     rc = dixLookupResourceByType(&val, stuff->subpicture_id, XvMCRTSubpicture,
 				 client, DixDestroyAccess);
     if (rc != Success)
-        return (rc == BadValue) ? XvMCBadSubpicture + XvMCErrorBase : rc;
+        return rc;
 
     FreeResource(stuff->subpicture_id, RT_NONE);
 
@@ -694,7 +693,9 @@ XvMCExtensionInit(void)
   
    XvMCReqCode = extEntry->base;
    XvMCEventBase = extEntry->eventBase;
-   XvMCErrorBase = extEntry->errorBase;
+   SetResourceTypeErrorValue(XvMCRTContext, extEntry->errorBase + XvMCBadContext);
+   SetResourceTypeErrorValue(XvMCRTSurface, extEntry->errorBase + XvMCBadSurface);
+   SetResourceTypeErrorValue(XvMCRTSubpicture, extEntry->errorBase + XvMCBadSubpicture);
 }
 
 static Bool
diff --git a/damageext/damageext.c b/damageext/damageext.c
index d923434..e4eda5e 100644
--- a/damageext/damageext.c
+++ b/damageext/damageext.c
@@ -29,7 +29,6 @@
 
 static unsigned char	DamageReqCode;
 static int		DamageEventBase;
-static int		DamageErrorBase;
 static RESTYPE		DamageExtType;
 static RESTYPE		DamageExtWinType;
 
@@ -515,8 +514,8 @@ DamageExtensionInit(void)
     {
 	DamageReqCode = (unsigned char)extEntry->base;
 	DamageEventBase = extEntry->eventBase;
-	DamageErrorBase = extEntry->errorBase;
 	EventSwapVector[DamageEventBase + XDamageNotify] =
 			(EventSwapPtr) SDamageNotifyEvent;
+	SetResourceTypeErrorValue(DamageExtType, extEntry->errorBase + BadDamage);
     }
 }
diff --git a/damageext/damageextint.h b/damageext/damageextint.h
index d40ba3e..a235cb9 100644
--- a/damageext/damageextint.h
+++ b/damageext/damageextint.h
@@ -62,7 +62,7 @@ typedef struct _DamageExt {
     int rc = dixLookupResourceByType((pointer *)&(pDamageExt), rid, \
                                      DamageExtType, client, mode); \
     if (rc != Success) \
-        return (rc == BadValue) ? DamageErrorBase + BadDamage : rc; \
+        return rc; \
 }
 
 void
diff --git a/dbe/dbe.c b/dbe/dbe.c
index a49a46d..fba10d6 100644
--- a/dbe/dbe.c
+++ b/dbe/dbe.c
@@ -422,12 +422,12 @@ ProcDbeDeallocateBackBufferName(ClientPtr client)
 				 dbeWindowPrivResType, client,
 				 DixDestroyAccess);
     if (rc != Success)
-	return (rc == BadValue) ? dbeErrorBase + DbeBadBuffer : rc;
+	return rc;
 
     rc = dixLookupResourceByType(&val, stuff->buffer, dbeDrawableResType,
 				 client, DixDestroyAccess);
     if (rc != Success)
-	return (rc == BadValue) ? dbeErrorBase + DbeBadBuffer : rc;
+	return rc;
 
     /* Make sure that the id is valid for the window.
      * This is paranoid code since we already looked up the ID by type
@@ -1672,6 +1672,8 @@ DbeExtensionInit(void)
                             DbeResetProc, StandardMinorOpcode);
 
     dbeErrorBase = extEntry->errorBase;
+    SetResourceTypeErrorValue(dbeWindowPrivResType, dbeErrorBase + DbeBadBuffer);
+    SetResourceTypeErrorValue(dbeDrawableResType, dbeErrorBase + DbeBadBuffer);
 
 } /* DbeExtensionInit() */
 
diff --git a/dix/resource.c b/dix/resource.c
index fb4473a..a6d115f 100644
--- a/dix/resource.c
+++ b/dix/resource.c
@@ -268,6 +268,12 @@ CreateNewResourceType(DeleteType deleteFunc, char *name)
     return next;
 }
 
+void
+SetResourceTypeErrorValue(RESTYPE type, int errorValue)
+{
+    resourceTypes[type & TypeMask].errorValue = errorValue;
+}
+
 RESTYPE
 CreateNewResourceClass(void)
 {
diff --git a/include/resource.h b/include/resource.h
index 96f852a..0c5a59d 100644
--- a/include/resource.h
+++ b/include/resource.h
@@ -157,6 +157,9 @@ typedef Bool (*FindComplexResType)(
 extern _X_EXPORT RESTYPE CreateNewResourceType(
     DeleteType /*deleteFunc*/, char * /*name*/);
 
+extern _X_EXPORT void SetResourceTypeErrorValue(
+    RESTYPE /*type*/, int /*errorValue*/);
+
 extern _X_EXPORT RESTYPE CreateNewResourceClass(void);
 
 extern _X_EXPORT Bool InitClientResources(
diff --git a/randr/randrstr.h b/randr/randrstr.h
index b163a73..a18c834 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -344,7 +344,7 @@ extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType;
 	                                 RROutputType, client, a);\
 	if (rc != Success) {\
 	    client->errorValue = id;\
-	    return (rc == BadValue) ? RRErrorBase + BadRROutput : rc;\
+	    return rc;\
 	}\
     }
 
@@ -354,7 +354,7 @@ extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType;
 	                                 RRCrtcType, client, a);\
 	if (rc != Success) {\
 	    client->errorValue = id;\
-	    return (rc == BadValue) ? RRErrorBase + BadRRCrtc : rc;\
+	    return rc;\
 	}\
     }
 
@@ -364,7 +364,7 @@ extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType;
 	                                 RRModeType, client, a);\
 	if (rc != Success) {\
 	    client->errorValue = id;\
-	    return (rc == BadValue) ? RRErrorBase + BadRRMode : rc;\
+	    return rc;\
 	}\
     }
 
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 95e74c5..987f772 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -634,6 +634,7 @@ RRCrtcInit (void)
     RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource, "CRTC");
     if (!RRCrtcType)
 	return FALSE;
+    SetResourceTypeErrorValue(RRCrtcType, RRErrorBase + BadRRCrtc);
     return TRUE;
 }
 
@@ -806,7 +807,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	{
 	    if (outputs)
 		free(outputs);
-	    return (rc == BadValue) ? RRErrorBase + BadRROutput : rc;
+	    return rc;
 	}
 	/* validate crtc for this output */
 	for (j = 0; j < outputs[i]->numCrtcs; j++)
diff --git a/randr/rrmode.c b/randr/rrmode.c
index e73d1ac..deddd3c 100644
--- a/randr/rrmode.c
+++ b/randr/rrmode.c
@@ -268,6 +268,7 @@ RRModeInit (void)
     RRModeType = CreateNewResourceType (RRModeDestroyResource, "MODE");
     if (!RRModeType)
 	return FALSE;
+    SetResourceTypeErrorValue(RRModeType, RRErrorBase + BadRRMode);
     return TRUE;
 }
 
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 445c318..7822c0d 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -423,6 +423,7 @@ RROutputInit (void)
     RROutputType = CreateNewResourceType (RROutputDestroyResource, "OUTPUT");
     if (!RROutputType)
 	return FALSE;
+    SetResourceTypeErrorValue(RROutputType, RRErrorBase + BadRROutput);
     return TRUE;
 }
 
diff --git a/record/record.c b/record/record.c
index 1b55d6b..3724dc7 100644
--- a/record/record.c
+++ b/record/record.c
@@ -58,7 +58,6 @@ and Jim Haggerty of Metheus.
 #include "protocol-versions.h"
 
 static RESTYPE RTContext;   /* internal resource type for Record contexts */
-static int RecordErrorBase; /* first Record error number */
 
 /* How many bytes of protocol data to buffer in a context. Don't set to less
  * than 32.
@@ -133,7 +132,7 @@ static int numEnabledRCAPs;
     int rc = dixLookupResourceByType((pointer *)&(_pContext), _contextid, \
                                      RTContext, _client, DixUseAccess); \
     if (rc != Success) \
-	return (rc == BadValue) ? RecordErrorBase + XRecordBadContext : rc; \
+	return rc; \
 }
 
 static int RecordDeleteContext(
@@ -2911,7 +2910,7 @@ RecordExtensionInit(void)
 	DeleteCallback(&ClientStateCallback, RecordAClientStateChange, NULL);
 	return;
     }
-    RecordErrorBase = extentry->errorBase;
+    SetResourceTypeErrorValue(RTContext, extentry->errorBase + XRecordBadContext);
 
 } /* RecordExtensionInit */
 
diff --git a/render/picture.c b/render/picture.c
index 86e2e0f..211fa38 100644
--- a/render/picture.c
+++ b/render/picture.c
@@ -1115,7 +1115,6 @@ ChangePicture (PicturePtr	pPicture,
 			if (error != Success)
 			{
 			    client->errorValue = pid;
-			    error = (error == BadValue) ? RenderErrBase + BadPicture : error;
 			    break;
 			}
 			if (pAlpha->pDrawable == NULL ||
diff --git a/render/picturestr.h b/render/picturestr.h
index 5a796f4..a401108 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -412,7 +412,7 @@ extern _X_EXPORT RESTYPE	GlyphSetType;
     int rc = dixLookupResourceByType((pointer)&(pPicture), pid,\
 	                             PictureType, client, mode);\
     if (rc != Success)\
-	return (rc == BadValue) ? RenderErrBase + BadPicture : rc;\
+	return rc;\
 }
 
 #define VERIFY_ALPHA(pPicture, pid, client, mode) {\
diff --git a/render/render.c b/render/render.c
index fc6dbb1..b58dd3e 100644
--- a/render/render.c
+++ b/render/render.c
@@ -233,6 +233,10 @@ RenderClientCallback (CallbackListPtr	*list,
     pRenderClient->minor_version = 0;
 }
 
+#ifdef PANORAMIX
+unsigned long	XRT_PICTURE;
+#endif
+
 void
 RenderExtensionInit (void)
 {
@@ -253,6 +257,13 @@ RenderExtensionInit (void)
     if (!extEntry)
 	return;
     RenderErrBase = extEntry->errorBase;
+#ifdef PANORAMIX
+    if (XRT_PICTURE)
+	SetResourceTypeErrorValue(XRT_PICTURE, RenderErrBase + BadPicture);
+#endif
+    SetResourceTypeErrorValue(PictureType, RenderErrBase + BadPicture);
+    SetResourceTypeErrorValue(PictFormatType, RenderErrBase + BadPictFormat);
+    SetResourceTypeErrorValue(GlyphSetType, RenderErrBase + BadGlyphSet);
 }
 
 static int
@@ -532,7 +543,7 @@ ProcRenderQueryPictIndexValues (ClientPtr client)
     rc = dixLookupResourceByType((pointer *)&pFormat, stuff->format,
 				 PictFormatType, client, DixReadAccess);
     if (rc != Success)
-	return (rc == BadValue) ? RenderErrBase + BadPictFormat : rc;
+	return rc;
 
     if (pFormat->type != PictTypeIndexed)
     {
@@ -601,7 +612,7 @@ ProcRenderCreatePicture (ClientPtr client)
     rc = dixLookupResourceByType((pointer *)&pFormat, stuff->format,
 				 PictFormatType, client, DixReadAccess);
     if (rc != Success)
-	return (rc == BadValue) ? RenderErrBase + BadPictFormat : rc;
+	return rc;
 
     if (pFormat->depth != pDrawable->depth)
 	return BadMatch;
@@ -755,7 +766,7 @@ ProcRenderTrapezoids (ClientPtr client)
 	rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat,
 				     PictFormatType, client, DixReadAccess);
 	if (rc != Success)
-	    return (rc == BadValue) ? RenderErrBase + BadPictFormat : rc;
+	    return rc;
     }
     else
 	pFormat = 0;
@@ -795,7 +806,7 @@ ProcRenderTriangles (ClientPtr client)
 	rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat,
 				     PictFormatType, client, DixReadAccess);
 	if (rc != Success)
-	    return (rc == BadValue) ? RenderErrBase + BadPictFormat : rc;
+	    return rc;
     }
     else
 	pFormat = 0;
@@ -835,7 +846,7 @@ ProcRenderTriStrip (ClientPtr client)
 	rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat,
 				     PictFormatType, client, DixReadAccess);
 	if (rc != Success)
-	    return (rc == BadValue) ? RenderErrBase + BadPictFormat : rc;
+	    return rc;
     }
     else
 	pFormat = 0;
@@ -875,7 +886,7 @@ ProcRenderTriFan (ClientPtr client)
 	rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat,
 				     PictFormatType, client, DixReadAccess);
 	if (rc != Success)
-	    return (rc == BadValue) ? RenderErrBase + BadPictFormat : rc;
+	    return rc;
     }
     else
 	pFormat = 0;
@@ -922,7 +933,7 @@ ProcRenderCreateGlyphSet (ClientPtr client)
     rc = dixLookupResourceByType((pointer *)&format, stuff->format,
 				 PictFormatType, client, DixReadAccess);
     if (rc != Success)
-	return (rc == BadValue) ? RenderErrBase + BadPictFormat : rc;
+	return rc;
 
     switch (format->depth) {
     case 1:
@@ -974,7 +985,7 @@ ProcRenderReferenceGlyphSet (ClientPtr client)
     if (rc != Success)
     {
 	client->errorValue = stuff->existing;
-	return (rc == BadValue) ? RenderErrBase + BadGlyphSet : rc;
+	return rc;
     }
     glyphSet->refcnt++;
     if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet))
@@ -998,7 +1009,7 @@ ProcRenderFreeGlyphSet (ClientPtr client)
     if (rc != Success)
     {
 	client->errorValue = stuff->glyphset;
-	return (rc == BadValue) ? RenderErrBase + BadGlyphSet : rc;
+	return rc;
     }
     FreeResource (stuff->glyphset, RT_NONE);
     return Success;
@@ -1037,7 +1048,7 @@ ProcRenderAddGlyphs (ClientPtr client)
     if (err != Success)
     {
 	client->errorValue = stuff->glyphset;
-	return (err == BadValue) ? RenderErrBase + BadGlyphSet : err;
+	return err;
     }
 
     err = BadAlloc;
@@ -1238,7 +1249,7 @@ ProcRenderFreeGlyphs (ClientPtr client)
     if (rc != Success)
     {
 	client->errorValue = stuff->glyphset;
-	return (rc == BadValue) ? RenderErrBase + BadGlyphSet : rc;
+	return rc;
     }
     nglyph = bytes_to_int32((client->req_len << 2) - sizeof (xRenderFreeGlyphsReq));
     gids = (CARD32 *) (stuff + 1);
@@ -1300,7 +1311,7 @@ ProcRenderCompositeGlyphs (ClientPtr client)
 	rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat,
 				     PictFormatType, client, DixReadAccess);
 	if (rc != Success)
-	    return (rc == BadValue) ? RenderErrBase + BadPictFormat : rc;
+	    return rc;
     }
     else
 	pFormat = 0;
@@ -1308,7 +1319,7 @@ ProcRenderCompositeGlyphs (ClientPtr client)
     rc = dixLookupResourceByType((pointer *)&glyphSet, stuff->glyphset,
 				 GlyphSetType, client, DixUseAccess);
     if (rc != Success)
-	return (rc == BadValue) ? RenderErrBase + BadGlyphSet : rc;
+	return rc;
 
     buffer = (CARD8 *) (stuff + 1);
     end = (CARD8 *) stuff + (client->req_len << 2);
@@ -1371,7 +1382,7 @@ ProcRenderCompositeGlyphs (ClientPtr client)
 			free(glyphsBase);
 		    if (listsBase != listsLocal)
 			free(listsBase);
-		    return (rc == BadValue) ? RenderErrBase + BadGlyphSet : rc;
+		    return rc;
 		}
 	    }
 	    buffer += 4;
@@ -2639,7 +2650,7 @@ SProcRenderDispatch (ClientPtr client)
     int rc = dixLookupResourceByType((pointer *)&(pPicture), pid,\
                                      XRT_PICTURE, client, mode);\
     if (rc != Success)\
-	return (rc == BadValue) ? RenderErrBase + BadPicture : rc;\
+	return rc;\
 }
 
 #define VERIFY_XIN_ALPHA(pPicture, pid, client, mode) {\
@@ -2652,8 +2663,6 @@ SProcRenderDispatch (ClientPtr client)
 
 int	    (*PanoramiXSaveRenderVector[RenderNumberRequests])(ClientPtr);
 
-unsigned long	XRT_PICTURE;
-
 static int
 PanoramiXRenderCreatePicture (ClientPtr client)
 {
@@ -3330,6 +3339,8 @@ PanoramiXRenderInit (void)
     
     XRT_PICTURE = CreateNewResourceType (XineramaDeleteResource,
 					 "XineramaPicture");
+    if (RenderErrBase)
+	SetResourceTypeErrorValue(XRT_PICTURE, RenderErrBase + BadPicture);
     for (i = 0; i < RenderNumberRequests; i++)
 	PanoramiXSaveRenderVector[i] = ProcRenderVector[i];
     /*
@@ -3365,6 +3376,7 @@ PanoramiXRenderReset (void)
     int	    i;
     for (i = 0; i < RenderNumberRequests; i++)
 	ProcRenderVector[i] = PanoramiXSaveRenderVector[i];
+    RenderErrBase = 0;
 }
 
 #endif	/* PANORAMIX */
diff --git a/xfixes/xfixes.c b/xfixes/xfixes.c
index 49ed5a0..2f64a04 100644
--- a/xfixes/xfixes.c
+++ b/xfixes/xfixes.c
@@ -259,5 +259,6 @@ XFixesExtensionInit(void)
 	    (EventSwapPtr) SXFixesSelectionNotifyEvent;
 	EventSwapVector[XFixesEventBase + XFixesCursorNotify] =
 	    (EventSwapPtr) SXFixesCursorNotifyEvent;
+	SetResourceTypeErrorValue(RegionResType, XFixesErrorBase + BadRegion);
     }
 }
diff --git a/xfixes/xfixes.h b/xfixes/xfixes.h
index 69d162f..1638350 100644
--- a/xfixes/xfixes.h
+++ b/xfixes/xfixes.h
@@ -37,10 +37,7 @@ extern _X_EXPORT int XFixesErrorBase;
 	int err;							\
 	err = dixLookupResourceByType((pointer *) &pRegion, rid,	\
 				      RegionResType, client, mode);	\
-	if (err == BadValue) {						\
-	    client->errorValue = rid;					\
-	    return XFixesErrorBase + BadRegion;				\
-	} else if (err != Success) {					\
+	if (err != Success) {						\
 	    client->errorValue = rid;					\
 	    return err;							\
 	}								\
commit e291c561821ae86b7dd74269d5cd29bc31703962
Author: Jamey Sharp <jamey at minilop.net>
Date:   Sat Apr 24 23:26:40 2010 -0700

    Return an appropriately-typed error from dixLookupResourceByType.
    
    Rather than always returning BadValue, associate an error status like
    BadWindow with a resource type like RT_WINDOW, and return the
    appropriate one for the requested type.
    
    This patch only touches the core protocol resource types. Others still
    return BadValue and need to be mapped appropriately.
    
    dixLookupResourceByType can now return BadImplementation, if the caller
    asked for a resource type that has not been allocated in the server.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/Xext/panoramiXprocs.c b/Xext/panoramiXprocs.c
index a181695..dbaae26 100644
--- a/Xext/panoramiXprocs.c
+++ b/Xext/panoramiXprocs.c
@@ -457,7 +457,7 @@ int PanoramiXConfigureWindow(ClientPtr client)
     result = dixLookupResourceByType((pointer *)&pWin, stuff->window,
 				     RT_WINDOW, client, DixWriteAccess);
     if (result != Success)
-	return (result == BadValue) ? BadWindow : result;
+	return result;
 
     result = dixLookupResourceByType((pointer *)&win, stuff->window,
 				     XRT_WINDOW, client, DixWriteAccess);
diff --git a/Xext/saver.c b/Xext/saver.c
index 30c4a8c..63a41d6 100644
--- a/Xext/saver.c
+++ b/Xext/saver.c
@@ -1043,7 +1043,6 @@ ScreenSaverSetAttributes (ClientPtr client)
 		}
 	        else
 		{
-		    ret = (ret == BadValue) ? BadPixmap : ret;
 		    client->errorValue = pixID;
 		    goto PatchUp;
 		}
@@ -1081,7 +1080,6 @@ ScreenSaverSetAttributes (ClientPtr client)
 		}
     	        else
 		{
-		    ret = (ret == BadValue) ? BadPixmap : ret;
 		    client->errorValue = pixID;
 		    goto PatchUp;
 		}
@@ -1163,7 +1161,6 @@ ScreenSaverSetAttributes (ClientPtr client)
 				    client, DixUseAccess);
 	    if (ret != Success)
 	    {
-		ret = (ret == BadValue) ? BadColor : ret;
 		client->errorValue = cmap;
 		goto PatchUp;
 	    }
@@ -1187,7 +1184,6 @@ ScreenSaverSetAttributes (ClientPtr client)
 					RT_CURSOR, client, DixUseAccess);
 	    	if (ret != Success)
 	    	{
-		    ret = (ret == BadValue) ? BadCursor : ret;
 		    client->errorValue = cursorID;
 		    goto PatchUp;
 	    	}
diff --git a/Xext/shape.c b/Xext/shape.c
index 10ac283..f49e9a0 100644
--- a/Xext/shape.c
+++ b/Xext/shape.c
@@ -415,7 +415,7 @@ ProcShapeMask (ClientPtr client)
 	rc = dixLookupResourceByType((pointer *)&pPixmap, stuff->src, RT_PIXMAP,
 			       client, DixReadAccess);
         if (rc != Success)
-	    return (rc == BadValue) ? BadPixmap : rc;
+	    return rc;
 	if (pPixmap->drawable.pScreen != pScreen ||
 	    pPixmap->drawable.depth != 1)
 	    return BadMatch;
diff --git a/Xext/xtest.c b/Xext/xtest.c
index 09c4677..263d0c1 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -153,7 +153,7 @@ ProcXTestCompareCursor(ClientPtr client)
         if (rc != Success)
         {
             client->errorValue = stuff->cursor;
-            return (rc == BadValue) ? BadCursor : rc;
+            return rc;
         }
     }
     rep.type = X_Reply;
diff --git a/Xi/exevents.c b/Xi/exevents.c
index b24204d..41b396c 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1445,7 +1445,7 @@ GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
 	if (rc != Success)
 	{
 	    client->errorValue = param->cursor;
-	    return (rc == BadValue) ? BadCursor : rc;
+	    return rc;
 	}
 	access_mode |= DixForceAccess;
     }
@@ -1543,7 +1543,7 @@ GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
 	if (rc != Success)
 	{
 	    client->errorValue = param->cursor;
-	    return (rc == BadValue) ? BadCursor : rc;
+	    return rc;
 	}
 	access_mode |= DixForceAccess;
     }
diff --git a/Xi/xichangecursor.c b/Xi/xichangecursor.c
index f071e84..e72cfac 100644
--- a/Xi/xichangecursor.c
+++ b/Xi/xichangecursor.c
@@ -103,7 +103,7 @@ int ProcXIChangeCursor(ClientPtr client)
 	rc = dixLookupResourceByType((pointer *)&pCursor, stuff->cursor,
 				     RT_CURSOR, client, DixUseAccess);
 	if (rc != Success)
-	    return (rc == BadValue) ? BadCursor : rc;
+	    return rc;
     }
 
     ChangeWindowDeviceCursor(pWin, pDev, pCursor);
diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c
index a62fe79..2966145 100644
--- a/Xi/xipassivegrab.c
+++ b/Xi/xipassivegrab.c
@@ -147,7 +147,7 @@ ProcXIPassiveGrabDevice(ClientPtr client)
 	if (status != Success)
 	{
 	    client->errorValue = stuff->cursor;
-	    return (status == BadValue) ? BadCursor : status;
+	    return status;
 	}
     }
 
diff --git a/composite/compext.c b/composite/compext.c
index 3bb9a37..ed43775 100644
--- a/composite/compext.c
+++ b/composite/compext.c
@@ -140,10 +140,7 @@ ProcCompositeQueryVersion (ClientPtr client)
 	int err;							\
 	err = dixLookupResourceByType((pointer *) &pWindow, wid,	\
 				      RT_WINDOW, client, mode);		\
-	if (err == BadValue) {						\
-	    client->errorValue = wid;					\
-	    return BadWindow;						\
-	} else if (err != Success) {					\
+	if (err != Success) {						\
 	    client->errorValue = wid;					\
 	    return err;							\
 	}								\
diff --git a/dix/cursor.c b/dix/cursor.c
index a512309..7ff0a93 100644
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@ -316,14 +316,14 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
     if (rc != Success)
     {
 	client->errorValue = source;
-	return (rc == BadValue) ? BadFont : rc;
+	return rc;
     }
     rc = dixLookupResourceByType((pointer *)&maskfont, mask, RT_FONT, client,
 				 DixUseAccess);
     if (rc != Success && mask != None)
     {
 	client->errorValue = mask;
-	return (rc == BadValue) ? BadFont : rc;
+	return rc;
     }
     if (sourcefont != maskfont)
 	pShare = (GlyphSharePtr)NULL;
diff --git a/dix/dispatch.c b/dix/dispatch.c
index c9e3188..c86011a 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -1240,7 +1240,7 @@ ProcCloseFont(ClientPtr client)
     else
     {
 	client->errorValue = stuff->id;
-        return (rc == BadValue) ? BadFont : rc;
+        return rc;
     }
 }
 
@@ -1453,7 +1453,7 @@ ProcFreePixmap(ClientPtr client)
     else 
     {
 	client->errorValue = stuff->id;
-	return (rc == BadValue) ? BadPixmap : rc;
+	return rc;
     }
 }
 
@@ -2407,7 +2407,7 @@ ProcFreeColormap(ClientPtr client)
     else 
     {
 	client->errorValue = stuff->id;
-	return (rc == BadValue) ? BadColor : rc;
+	return rc;
     }
 }
 
@@ -2428,7 +2428,7 @@ ProcCopyColormapAndFree(ClientPtr client)
     if (rc == Success)
 	return CopyColormapAndFree(mid, pSrcMap, client->index);
     client->errorValue = stuff->srcCmap;
-    return (rc == BadValue) ? BadColor : rc;
+    return rc;
 }
 
 int
@@ -2445,15 +2445,18 @@ ProcInstallColormap(ClientPtr client)
 	goto out;
 
     rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
-    if (rc != Success)
+    if (rc != Success) {
+	if (rc == BadValue)
+	    rc = BadColor;
 	goto out;
+    }
 
     (*(pcmp->pScreen->InstallColormap)) (pcmp);
     return Success;
 
 out:
     client->errorValue = stuff->id;
-    return (rc == BadValue) ? BadColor : rc;
+    return rc;
 }
 
 int
@@ -2470,8 +2473,11 @@ ProcUninstallColormap(ClientPtr client)
 	goto out;
 
     rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
-    if (rc != Success)
+    if (rc != Success) {
+	if (rc == BadValue)
+	    rc = BadColor;
 	goto out;
+    }
 
     if(pcmp->mid != pcmp->pScreen->defColormap)
 	(*(pcmp->pScreen->UninstallColormap)) (pcmp);
@@ -2479,7 +2485,7 @@ ProcUninstallColormap(ClientPtr client)
 
 out:
     client->errorValue = stuff->id;
-    return (rc == BadValue) ? BadColor : rc;
+    return rc;
 }
 
 int
@@ -2552,7 +2558,7 @@ ProcAllocColor (ClientPtr client)
     else
     {
         client->errorValue = stuff->cmap;
-        return (rc == BadValue) ? BadColor : rc;
+        return rc;
     }
 }
 
@@ -2598,7 +2604,7 @@ ProcAllocNamedColor (ClientPtr client)
     else
     {
         client->errorValue = stuff->cmap;
-        return (rc == BadValue) ? BadColor : rc;
+        return rc;
     }
 }
 
@@ -2662,7 +2668,7 @@ ProcAllocColorCells (ClientPtr client)
     else
     {
         client->errorValue = stuff->cmap;
-        return (rc == BadValue) ? BadColor : rc;
+        return rc;
     }
 }
 
@@ -2724,7 +2730,7 @@ ProcAllocColorPlanes(ClientPtr client)
     else
     {
         client->errorValue = stuff->cmap;
-        return (rc == BadValue) ? BadColor : rc;
+        return rc;
     }
 }
 
@@ -2751,7 +2757,7 @@ ProcFreeColors(ClientPtr client)
     else
     {
         client->errorValue = stuff->cmap;
-        return (rc == BadValue) ? BadColor : rc;
+        return rc;
     }
 }
 
@@ -2778,7 +2784,7 @@ ProcStoreColors (ClientPtr client)
     else
     {
         client->errorValue = stuff->cmap;
-        return (rc == BadValue) ? BadColor : rc;
+        return rc;
     }
 }
 
@@ -2808,7 +2814,7 @@ ProcStoreNamedColor (ClientPtr client)
     else
     {
         client->errorValue = stuff->cmap;
-        return (rc == BadValue) ? BadColor : rc;
+        return rc;
     }
 }
 
@@ -2855,7 +2861,7 @@ ProcQueryColors(ClientPtr client)
     else
     {
         client->errorValue = stuff->cmap;
-        return (rc == BadValue) ? BadColor : rc;
+        return rc;
     }
 } 
 
@@ -2894,7 +2900,7 @@ ProcLookupColor(ClientPtr client)
     else
     {
         client->errorValue = stuff->cmap;
-        return (rc == BadValue) ? BadColor : rc;
+        return rc;
     }
 }
 
@@ -2920,7 +2926,7 @@ ProcCreateCursor (ClientPtr client)
 			   DixReadAccess);
     if (rc != Success) {
 	client->errorValue = stuff->source;
-	return (rc == BadValue) ? BadPixmap : rc;
+	return rc;
     }
 
     rc = dixLookupResourceByType((pointer *)&msk, stuff->mask, RT_PIXMAP, client,
@@ -2930,7 +2936,7 @@ ProcCreateCursor (ClientPtr client)
 	if (stuff->mask != None)
 	{
 	    client->errorValue = stuff->mask;
-	    return (rc == BadValue) ? BadPixmap : rc;
+	    return rc;
 	}
     }
     else if (  src->drawable.width != msk->drawable.width
@@ -3031,7 +3037,7 @@ ProcFreeCursor (ClientPtr client)
     else 
     {
 	client->errorValue = stuff->id;
-	return (rc == BadValue) ? BadCursor : rc;
+	return rc;
     }
 }
 
diff --git a/dix/dixfonts.c b/dix/dixfonts.c
index 585754b..ba1d0e2 100644
--- a/dix/dixfonts.c
+++ b/dix/dixfonts.c
@@ -1238,7 +1238,6 @@ doPolyText(ClientPtr client, PTclosurePtr c)
 					  client, DixUseAccess);
 	    if (err != Success)
 	    {
-		err = (err == BadValue) ? BadFont : err;
 		/* restore pFont and fid for step 4 (described below) */
 		pFont = oldpFont;
 		fid = oldfid;
diff --git a/dix/dixutils.c b/dix/dixutils.c
index 5955eb8..51dbd14 100644
--- a/dix/dixutils.c
+++ b/dix/dixutils.c
@@ -231,9 +231,7 @@ dixLookupWindow(WindowPtr *pWin, XID id, ClientPtr client, Mask access)
 int
 dixLookupGC(GCPtr *pGC, XID id, ClientPtr client, Mask access)
 {
-    int rc;
-    rc = dixLookupResourceByType((pointer *)pGC, id, RT_GC, client, access);
-    return (rc == BadValue) ? BadGC : rc;
+    return dixLookupResourceByType((pointer *)pGC, id, RT_GC, client, access);
 }
 
 int
@@ -243,10 +241,10 @@ dixLookupFontable(FontPtr *pFont, XID id, ClientPtr client, Mask access)
     GC *pGC;
     client->errorValue = id;		/* EITHER font or gc */
     rc = dixLookupResourceByType((pointer *) pFont, id, RT_FONT, client, access);
-    if (rc != BadValue)
+    if (rc != BadFont)
 	return rc;
     rc = dixLookupResourceByType((pointer *) &pGC, id, RT_GC, client, access);
-    if (rc == BadValue)
+    if (rc == BadGC)
 	return BadFont;
     if (rc == Success)
 	*pFont = pGC->font;
diff --git a/dix/events.c b/dix/events.c
index 39ad400..9e05dc9 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4697,7 +4697,7 @@ ProcChangeActivePointerGrab(ClientPtr client)
 	if (rc != Success)
 	{
 	    client->errorValue = stuff->cursor;
-	    return (rc == BadValue) ? BadCursor : rc;
+	    return rc;
 	}
     }
 
@@ -4820,7 +4820,7 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev,
 	if (rc != Success)
 	{
 	    client->errorValue = curs;
-	    return (rc == BadValue) ? BadCursor : rc;
+	    return rc;
 	}
 	access_mode |= DixForceAccess;
     }
@@ -5345,7 +5345,7 @@ ProcGrabButton(ClientPtr client)
 	if (rc != Success)
 	{
 	    client->errorValue = stuff->cursor;
-	    return (rc == BadValue) ? BadCursor : rc;
+	    return rc;
 	}
 	access_mode |= DixForceAccess;
     }
@@ -5608,7 +5608,7 @@ ProcRecolorCursor(ClientPtr client)
     if (rc != Success)
     {
 	client->errorValue = stuff->cursor;
-	return (rc == BadValue) ? BadCursor : rc;
+	return rc;
     }
 
     pCursor->foreRed = stuff->foreRed;
diff --git a/dix/gc.c b/dix/gc.c
index 6281f25..65d05eb 100644
--- a/dix/gc.c
+++ b/dix/gc.c
@@ -458,8 +458,6 @@ ChangeGCXIDs(ClientPtr client, GC *pGC, BITS32 mask, CARD32 *pC32)
 	if (rc != Success)
 	{
 	    client->errorValue = vals[offset].val;
-	    if (rc == BadValue)
-		rc = (xidfields[i].type == RT_PIXMAP) ? BadPixmap : BadFont;
 	    return rc;
 	}
     }
diff --git a/dix/resource.c b/dix/resource.c
index 143b51a..fb4473a 100644
--- a/dix/resource.c
+++ b/dix/resource.c
@@ -183,7 +183,54 @@ RESTYPE lastResourceType;
 static RESTYPE lastResourceClass;
 RESTYPE TypeMask;
 
-static DeleteType *DeleteFuncs = (DeleteType *)NULL;
+struct ResourceType {
+    DeleteType deleteFunc;
+    int errorValue;
+};
+
+static struct ResourceType *resourceTypes;
+static const struct ResourceType predefTypes[] = {
+    [RT_NONE & (RC_LASTPREDEF - 1)] = {
+	.deleteFunc = (DeleteType)NoopDDA,
+	.errorValue = BadValue,
+    },
+    [RT_WINDOW & (RC_LASTPREDEF - 1)] = {
+	.deleteFunc = DeleteWindow,
+	.errorValue = BadWindow,
+    },
+    [RT_PIXMAP & (RC_LASTPREDEF - 1)] = {
+	.deleteFunc = dixDestroyPixmap,
+	.errorValue = BadPixmap,
+    },
+    [RT_GC & (RC_LASTPREDEF - 1)] = {
+	.deleteFunc = FreeGC,
+	.errorValue = BadGC,
+    },
+    [RT_FONT & (RC_LASTPREDEF - 1)] = {
+	.deleteFunc = CloseFont,
+	.errorValue = BadFont,
+    },
+    [RT_CURSOR & (RC_LASTPREDEF - 1)] = {
+	.deleteFunc = FreeCursor,
+	.errorValue = BadCursor,
+    },
+    [RT_COLORMAP & (RC_LASTPREDEF - 1)] = {
+	.deleteFunc = FreeColormap,
+	.errorValue = BadColor,
+    },
+    [RT_CMAPENTRY & (RC_LASTPREDEF - 1)] = {
+	.deleteFunc = FreeClientPixels,
+	.errorValue = BadColor,
+    },
+    [RT_OTHERCLIENT & (RC_LASTPREDEF - 1)] = {
+	.deleteFunc = OtherClientGone,
+	.errorValue = BadValue,
+    },
+    [RT_PASSIVEGRAB & (RC_LASTPREDEF - 1)] = {
+	.deleteFunc = DeletePassiveGrab,
+	.errorValue = BadValue,
+    },
+};
 
 CallbackListPtr ResourceStateCallback;
 
@@ -200,20 +247,20 @@ RESTYPE
 CreateNewResourceType(DeleteType deleteFunc, char *name)
 {
     RESTYPE next = lastResourceType + 1;
-    DeleteType *funcs;
+    struct ResourceType *types;
 
     if (next & lastResourceClass)
 	return 0;
-    funcs = (DeleteType *)realloc(DeleteFuncs,
-				   (next + 1) * sizeof(DeleteType));
-    if (!funcs)
+    types = realloc(resourceTypes, (next + 1) * sizeof(*resourceTypes));
+    if (!types)
 	return 0;
     if (!dixRegisterPrivateOffset(next, -1))
 	return 0;
 
     lastResourceType = next;
-    DeleteFuncs = funcs;
-    DeleteFuncs[next] = deleteFunc;
+    resourceTypes = types;
+    resourceTypes[next].deleteFunc = deleteFunc;
+    resourceTypes[next].errorValue = BadValue;
 
     /* Called even if name is NULL, to remove any previous entry */
     RegisterResourceName(next, name);
@@ -251,21 +298,11 @@ InitClientResources(ClientPtr client)
 	lastResourceType = RT_LASTPREDEF;
 	lastResourceClass = RC_LASTPREDEF;
 	TypeMask = RC_LASTPREDEF - 1;
-	if (DeleteFuncs)
-	    free(DeleteFuncs);
-	DeleteFuncs = malloc((lastResourceType + 1) * sizeof(DeleteType));
-	if (!DeleteFuncs)
+	free(resourceTypes);
+	resourceTypes = malloc(sizeof(predefTypes));
+	if (!resourceTypes)
 	    return FALSE;
-	DeleteFuncs[RT_NONE & TypeMask] = (DeleteType)NoopDDA;
-	DeleteFuncs[RT_WINDOW & TypeMask] = DeleteWindow;
-	DeleteFuncs[RT_PIXMAP & TypeMask] = dixDestroyPixmap;
-	DeleteFuncs[RT_GC & TypeMask] = FreeGC;
-	DeleteFuncs[RT_FONT & TypeMask] = CloseFont;
-	DeleteFuncs[RT_CURSOR & TypeMask] = FreeCursor;
-	DeleteFuncs[RT_COLORMAP & TypeMask] = FreeColormap;
-	DeleteFuncs[RT_CMAPENTRY & TypeMask] = FreeClientPixels;
-	DeleteFuncs[RT_OTHERCLIENT & TypeMask] = OtherClientGone;
-	DeleteFuncs[RT_PASSIVEGRAB & TypeMask] = DeletePassiveGrab;
+	memcpy(resourceTypes, predefTypes, sizeof(predefTypes));
     }
     clientTable[i = client->index].resources =
 	malloc(INITBUCKETS*sizeof(ResourcePtr));
@@ -462,7 +499,7 @@ AddResource(XID id, RESTYPE type, pointer value)
     res = malloc(sizeof(ResourceRec));
     if (!res)
     {
-	(*DeleteFuncs[type & TypeMask])(value, id);
+	(*resourceTypes[type & TypeMask].deleteFunc)(value, id);
 	return FALSE;
     }
     res->next = *head;
@@ -557,7 +594,7 @@ FreeResource(XID id, RESTYPE skipDeleteFuncType)
 		CallResourceStateCallback(ResourceStateFreeing, res);
 
 		if (rtype != skipDeleteFuncType)
-		    (*DeleteFuncs[rtype & TypeMask])(res->value, res->id);
+		    (*resourceTypes[rtype & TypeMask].deleteFunc)(res->value, res->id);
 		free(res);
 		if (*eltptr != elements)
 		    prev = head; /* prev may no longer be valid */
@@ -594,7 +631,7 @@ FreeResourceByType(XID id, RESTYPE type, Bool skipFree)
 		CallResourceStateCallback(ResourceStateFreeing, res);
 
 		if (!skipFree)
-		    (*DeleteFuncs[type & TypeMask])(res->value, res->id);
+		    (*resourceTypes[type & TypeMask].deleteFunc)(res->value, res->id);
 		free(res);
 		break;
 	    }
@@ -761,7 +798,7 @@ FreeClientNeverRetainResources(ClientPtr client)
 		CallResourceStateCallback(ResourceStateFreeing, this);
 
 		elements = *eltptr;
-		(*DeleteFuncs[rtype & TypeMask])(this->value, this->id);
+		(*resourceTypes[rtype & TypeMask].deleteFunc)(this->value, this->id);
 		free(this);
 		if (*eltptr != elements)
 		    prev = &resources[j]; /* prev may no longer be valid */
@@ -815,7 +852,7 @@ FreeClientResources(ClientPtr client)
 
 	    CallResourceStateCallback(ResourceStateFreeing, this);
 
-	    (*DeleteFuncs[rtype & TypeMask])(this->value, this->id);
+	    (*resourceTypes[rtype & TypeMask].deleteFunc)(this->value, this->id);
 	    free(this);
 	}
     }
@@ -873,6 +910,8 @@ dixLookupResourceByType(pointer *result, XID id, RESTYPE rtype,
     ResourcePtr res = NULL;
 
     *result = NULL;
+    if ((rtype & TypeMask) > lastResourceType)
+	return BadImplementation;
 
     if ((cid < MAXCLIENTS) && clientTable[cid].buckets) {
 	res = clientTable[cid].resources[Hash(cid, id)];
@@ -882,12 +921,14 @@ dixLookupResourceByType(pointer *result, XID id, RESTYPE rtype,
 		break;
     }
     if (!res)
-	return BadValue;
+	return resourceTypes[rtype & TypeMask].errorValue;
 
     if (client) {
 	client->errorValue = id;
 	cid = XaceHook(XACE_RESOURCE_ACCESS, client, id, res->type,
 		       res->value, RT_NONE, NULL, mode);
+	if (cid == BadValue)
+	    return resourceTypes[rtype & TypeMask].errorValue;
 	if (cid != Success)
 	    return cid;
     }
diff --git a/dix/window.c b/dix/window.c
index 20cf452..00854c6 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -1056,7 +1056,7 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client)
 		}
 		else
 		{
-		    error = (rc == BadValue) ? BadPixmap : rc;
+		    error = rc;
 		    client->errorValue = pixID;
 		    goto PatchUp;
 		}
@@ -1116,7 +1116,7 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client)
 	    }
 	    else
 	    {
-		error = (rc == BadValue) ? BadPixmap : rc;
+		error = rc;
 		client->errorValue = pixID;
 		goto PatchUp;
 	    }
@@ -1264,7 +1264,7 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client)
 				   client, DixUseAccess);
 	    if (rc != Success)
 	    {
-		error = (rc == BadValue) ? BadColor : rc;
+		error = rc;
 		client->errorValue = cmap;
 		goto PatchUp;
 	    }
@@ -1340,7 +1340,7 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client)
 				       RT_CURSOR, client, DixUseAccess);
 		if (rc != Success)
 		{
-		    error = (rc == BadValue) ? BadCursor : rc;
+		    error = rc;
 		    client->errorValue = cursorID;
 		    goto PatchUp;
 		}
diff --git a/hw/xfree86/dixmods/extmod/xf86dga2.c b/hw/xfree86/dixmods/extmod/xf86dga2.c
index 6587af9..906f4d5 100644
--- a/hw/xfree86/dixmods/extmod/xf86dga2.c
+++ b/hw/xfree86/dixmods/extmod/xf86dga2.c
@@ -436,7 +436,7 @@ ProcXDGAInstallColormap(ClientPtr client)
     rc = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, RT_COLORMAP,
 				 client, DixInstallAccess);
     if (rc != Success)
-        return (rc == BadValue) ? BadColor : rc;
+        return rc;
     DGAInstallCmap(cmap);
     return Success;
 }
@@ -878,7 +878,7 @@ ProcXF86DGAInstallColormap(ClientPtr client)
 	DGAInstallCmap(pcmp);
         return Success;
     } else {
-        return (rc == BadValue) ? BadColor : rc;
+        return rc;
     }
 }
 
diff --git a/render/picture.c b/render/picture.c
index aab9391..86e2e0f 100644
--- a/render/picture.c
+++ b/render/picture.c
@@ -1176,7 +1176,6 @@ ChangePicture (PicturePtr	pPicture,
 			if (error != Success)
 			{
 			    client->errorValue = pid;
-			    error = (error == BadValue) ? BadPixmap : error;
 			    break;
 			}
 		    }
diff --git a/render/render.c b/render/render.c
index 9aabcfb..fc6dbb1 100644
--- a/render/render.c
+++ b/render/render.c
@@ -1856,7 +1856,7 @@ ProcRenderCreateAnimCursor (ClientPtr client)
 	if (ret != Success)
 	{
 	    free(cursors);
-	    return (ret == BadValue) ? BadCursor : ret;
+	    return ret;
 	}
 	deltas[i] = elt->delay;
 	elt++;
diff --git a/xfixes/cursor.c b/xfixes/cursor.c
index e963e37..52bdb27 100644
--- a/xfixes/cursor.c
+++ b/xfixes/cursor.c
@@ -70,10 +70,7 @@ static void deleteCursorHideCountsForScreen (ScreenPtr pScreen);
 	int err;							\
 	err = dixLookupResourceByType((pointer *) &pCursor, cursor,	\
 				      RT_CURSOR, client, access);	\
-	if (err == BadValue) {						\
-	    client->errorValue = cursor;				\
-	    return BadCursor;						\
-	} else if (err != Success) {					\
+	if (err != Success) {						\
 	    client->errorValue = cursor;				\
 	    return err;							\
 	}								\
@@ -882,7 +879,7 @@ ProcXFixesHideCursor (ClientPtr client)
 			    client, DixGetAttrAccess);
     if (ret != Success) {
 	client->errorValue = stuff->window;
-	return (ret == BadValue) ? BadWindow : ret;
+	return ret;
     }
 
     /* 
@@ -945,7 +942,7 @@ ProcXFixesShowCursor (ClientPtr client)
 			   client, DixGetAttrAccess);
     if (rc != Success) {
 	client->errorValue = stuff->window;
-	return (rc == BadValue) ? BadWindow : rc;
+	return rc;
     }
 
     /* 
diff --git a/xfixes/region.c b/xfixes/region.c
index 5f0c2c4..7a71c78 100644
--- a/xfixes/region.c
+++ b/xfixes/region.c
@@ -119,7 +119,7 @@ ProcXFixesCreateRegionFromBitmap (ClientPtr client)
     if (rc != Success)
     {
 	client->errorValue = stuff->bitmap;
-	return (rc == BadValue) ? BadPixmap : rc;
+	return rc;
     }
     if (pPixmap->drawable.depth != 1)
 	return BadMatch;
@@ -164,7 +164,7 @@ ProcXFixesCreateRegionFromWindow (ClientPtr client)
     if (rc != Success)
     {
 	client->errorValue = stuff->window;
-	return (rc == BadValue) ? BadWindow : rc;
+	return rc;
     }
     switch (stuff->kind) {
     case WindowRegionBounding:
@@ -675,7 +675,7 @@ ProcXFixesSetWindowShapeRegion (ClientPtr client)
     if (rc != Success)
     {
 	client->errorValue = stuff->dest;
-	return (rc == BadValue) ? BadWindow : rc;
+	return rc;
     }
     VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixWriteAccess);
     pScreen = pWin->drawable.pScreen;
commit 90e612dcbe370da095d317fac62c80ac2447fa0b
Author: Jamey Sharp <jamey at minilop.net>
Date:   Sat May 15 15:51:32 2010 -0700

    Use WriteEventsToClient rather than TryClientEvents where possible.
    
    If filter is NoEventMask (aka CantBeFiltered), grab is null, and the
    first event is not in the set of "critical events", then TryClientEvents
    simply calls WriteEventsToClient. In that case, it returns 0 for fake or
    dead clients, and 1 otherwise. Inline for this special case.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>
    Reviewed-by: Julien Cristau <jcristau at debian.org>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/Xext/xvmain.c b/Xext/xvmain.c
index 45d5946..f6d39d0 100644
--- a/Xext/xvmain.c
+++ b/Xext/xvmain.c
@@ -535,8 +535,7 @@ XvdiSendVideoNotify(XvPortPtr pPort, DrawablePtr pDraw, int reason)
       event.u.videoNotify.drawable = pDraw->id;
       event.u.videoNotify.port = pPort->id;
       event.u.videoNotify.reason = reason;
-      TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1,
-		      NoEventMask, NoEventMask, NullGrab);
+      WriteEventsToClient(pn->client, 1, (xEventPtr)&event);
       pn = pn->next;
     }
 
@@ -563,8 +562,7 @@ XvdiSendPortNotify(
       event.u.portNotify.port = pPort->id;
       event.u.portNotify.attribute = attribute;
       event.u.portNotify.value = value;
-      TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1,
-		      NoEventMask, NoEventMask, NullGrab);
+      WriteEventsToClient(pn->client, 1, (xEventPtr)&event);
       pn = pn->next;
     }
 
diff --git a/dix/selection.c b/dix/selection.c
index 4f592d1..f52638c 100644
--- a/dix/selection.c
+++ b/dix/selection.c
@@ -189,8 +189,7 @@ ProcSetSelectionOwner(ClientPtr client)
 	    event.u.selectionClear.time = time.milliseconds;
 	    event.u.selectionClear.window = pSel->window;
 	    event.u.selectionClear.atom = pSel->selection;
-	    TryClientEvents(pSel->client, NULL, &event, 1, NoEventMask,
-			    NoEventMask /* CantBeFiltered */, NullGrab);
+	    WriteEventsToClient(pSel->client, 1, &event);
 	}
     }
     else if (rc == BadMatch)
@@ -296,9 +295,11 @@ ProcConvertSelection(ClientPtr client)
 	event.u.selectionRequest.selection = stuff->selection;
 	event.u.selectionRequest.target = stuff->target;
 	event.u.selectionRequest.property = stuff->property;
-	if (TryClientEvents(pSel->client, NULL, &event, 1, NoEventMask,
-			    NoEventMask /* CantBeFiltered */, NullGrab))
+	if (pSel->client && pSel->client != serverClient && !pSel->client->clientGone)
+	{
+	    WriteEventsToClient(pSel->client, 1, &event);
 	    return Success;
+	}
     }
 
     event.u.u.type = SelectionNotify;
@@ -307,7 +308,6 @@ ProcConvertSelection(ClientPtr client)
     event.u.selectionNotify.selection = stuff->selection;
     event.u.selectionNotify.target = stuff->target;
     event.u.selectionNotify.property = None;
-    TryClientEvents(client, NULL, &event, 1, NoEventMask,
-		    NoEventMask /* CantBeFiltered */, NullGrab);
+    WriteEventsToClient(client, 1, &event);
     return Success;
 }
diff --git a/mi/miexpose.c b/mi/miexpose.c
index a50dc5e..57968dd 100644
--- a/mi/miexpose.c
+++ b/mi/miexpose.c
@@ -374,6 +374,8 @@ miSendGraphicsExpose (ClientPtr client, RegionPtr pRgn, XID drawable,
 	    pe->u.graphicsExposure.majorEvent = major;
 	    pe->u.graphicsExposure.minorEvent = minor;
 	}
+	/* GraphicsExpose is a "critical event", which TryClientEvents
+	 * handles specially. */
 	TryClientEvents(client, NULL, pEvent, numRects,
 			    (Mask)0, NoEventMask, NullGrab);
 	free(pEvent);
@@ -386,8 +388,7 @@ miSendGraphicsExpose (ClientPtr client, RegionPtr pRgn, XID drawable,
 	event.u.noExposure.drawable = drawable;
 	event.u.noExposure.majorEvent = major;
 	event.u.noExposure.minorEvent = minor;
-	TryClientEvents(client, NULL, &event, 1,
-	    (Mask)0, NoEventMask, NullGrab);
+	WriteEventsToClient(client, 1, &event);
     }
 }
 
commit 8033fb6c9792820a82fbdff6a14ff8a7a141ba74
Author: Jamey Sharp <jamey at minilop.net>
Date:   Sat May 15 13:12:44 2010 -0700

    Set event sequence number in WriteEventsToClient instead of at callers.
    
    TryClientEvents already did this; this commit just moves the assignment
    one level down so that no event source has to worry about sequence
    numbers.
    
    ...No event source, that is, except XKB, which inexplicably calls
    WriteToClient directly for several events.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>
    Reviewed-by: Julien Cristau <jcristau at debian.org>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/Xext/saver.c b/Xext/saver.c
index 42fc632..30c4a8c 100644
--- a/Xext/saver.c
+++ b/Xext/saver.c
@@ -480,7 +480,6 @@ SendScreenSaverNotify (ScreenPtr pScreen, int state, Bool forced)
     ScreenSaverEventPtr		pEv;
     unsigned long		mask;
     xScreenSaverNotifyEvent	ev;
-    ClientPtr			client;
     int				kind;
 
     UpdateCurrentTimeIf ();
@@ -499,18 +498,16 @@ SendScreenSaverNotify (ScreenPtr pScreen, int state, Bool forced)
 	kind = ScreenSaverInternal;
     for (pEv = pPriv->events; pEv; pEv = pEv->next)
     {
-	client = pEv->client;
 	if (!(pEv->mask & mask))
 	    continue;
 	ev.type = ScreenSaverNotify + ScreenSaverEventBase;
 	ev.state = state;
-	ev.sequenceNumber = client->sequence;
 	ev.timestamp = currentTime.milliseconds;
 	ev.root = WindowTable[pScreen->myNum]->drawable.id;
 	ev.window = savedScreenInfo[pScreen->myNum].wid;
 	ev.kind = kind;
 	ev.forced = forced;
-	WriteEventsToClient (client, 1, (xEvent *) &ev);
+	WriteEventsToClient (pEv->client, 1, (xEvent *) &ev);
     }
 }
 
diff --git a/Xext/security.c b/Xext/security.c
index 16aac05..32730e2 100644
--- a/Xext/security.c
+++ b/Xext/security.c
@@ -198,12 +198,10 @@ SecurityDeleteAuthorization(
     while ((pEventClient = pAuth->eventClients))
     {
 	/* send revocation event event */
-	ClientPtr client = rClient(pEventClient);
 	xSecurityAuthorizationRevokedEvent are;
 	are.type = SecurityEventBase + XSecurityAuthorizationRevoked;
-	are.sequenceNumber = client->sequence;
 	are.authId = pAuth->id;
-	WriteEventsToClient(client, 1, (xEvent *)&are);
+	WriteEventsToClient(rClient(pEventClient), 1, (xEvent *)&are);
 	FreeResource(pEventClient->resource, RT_NONE);
     }
 
diff --git a/Xext/shape.c b/Xext/shape.c
index 10437f4..10ac283 100644
--- a/Xext/shape.c
+++ b/Xext/shape.c
@@ -885,7 +885,6 @@ void
 SendShapeNotify (WindowPtr pWin, int which)
 {
     ShapeEventPtr	*pHead, pShapeEvent;
-    ClientPtr		client;
     xShapeNotifyEvent	se;
     BoxRec		extents;
     RegionPtr		region;
@@ -940,18 +939,16 @@ SendShapeNotify (WindowPtr pWin, int which)
 	return;
     }
     for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) {
-	client = pShapeEvent->client;
 	se.type = ShapeNotify + ShapeEventBase;
 	se.kind = which;
 	se.window = pWin->drawable.id;
-	se.sequenceNumber = client->sequence;
 	se.x = extents.x1;
 	se.y = extents.y1;
 	se.width = extents.x2 - extents.x1;
 	se.height = extents.y2 - extents.y1;
 	se.time = currentTime.milliseconds;
 	se.shaped = shaped;
-	WriteEventsToClient (client, 1, (xEvent *) &se);
+	WriteEventsToClient (pShapeEvent->client, 1, (xEvent *) &se);
     }
 }
 
diff --git a/Xext/shm.c b/Xext/shm.c
index 25043fa..b2c4208 100644
--- a/Xext/shm.c
+++ b/Xext/shm.c
@@ -943,7 +943,6 @@ ProcShmPutImage(ClientPtr client)
 
 	ev.type = ShmCompletionCode;
 	ev.drawable = stuff->drawable;
-	ev.sequenceNumber = client->sequence;
 	ev.minorEvent = X_ShmPutImage;
 	ev.majorEvent = ShmReqCode;
 	ev.shmseg = stuff->shmseg;
diff --git a/Xext/sync.c b/Xext/sync.c
index 3729f1b..f7ac405 100644
--- a/Xext/sync.c
+++ b/Xext/sync.c
@@ -372,7 +372,6 @@ SyncSendAlarmNotifyEvents(SyncAlarm *pAlarm)
 
     ane.type = SyncEventBase + XSyncAlarmNotify;
     ane.kind = XSyncAlarmNotify;
-    ane.sequenceNumber = pAlarm->client->sequence;
     ane.alarm = pAlarm->alarm_id;
     if (pTrigger->pCounter)
     {
@@ -395,10 +394,7 @@ SyncSendAlarmNotifyEvents(SyncAlarm *pAlarm)
 
     /* send to other interested clients */
     for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
-    {
-	ane.sequenceNumber = pcl->client->sequence;
 	WriteEventsToClient(pcl->client, 1, (xEvent *) &ane);
-    }
 }
 
 
@@ -423,7 +419,6 @@ SyncSendCounterNotifyEvents(ClientPtr client, SyncAwait **ppAwait,
 	SyncTrigger *pTrigger = &(*ppAwait)->trigger;
 	pev->type = SyncEventBase + XSyncCounterNotify;
 	pev->kind = XSyncCounterNotify;
-	pev->sequenceNumber = client->sequence;
 	pev->counter = pTrigger->pCounter->id;
 	pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value);
 	pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
diff --git a/Xext/xcalibrate.c b/Xext/xcalibrate.c
index 8659384..bff1c31 100644
--- a/Xext/xcalibrate.c
+++ b/Xext/xcalibrate.c
@@ -54,7 +54,6 @@ xcalibrate_event_hook (int x, int y, int pressure, void *closure)
   xXCalibrateRawTouchscreenEvent	ev;
 
   ev.type = XCalibrateEventBase + X_XCalibrateRawTouchscreen;
-  ev.sequenceNumber = pClient->sequence;
   ev.x = x;
   ev.y = y;
   ev.pressure = pressure;
diff --git a/Xext/xvdisp.c b/Xext/xvdisp.c
index fd633f1..250a994 100644
--- a/Xext/xvdisp.c
+++ b/Xext/xvdisp.c
@@ -1100,7 +1100,6 @@ ProcXvShmPutImage(ClientPtr client)
 
         ev.type = ShmCompletionCode;
         ev.drawable = stuff->drawable;
-        ev.sequenceNumber = client->sequence;
         ev.minorEvent = xv_ShmPutImage;
         ev.majorEvent = XvReqCode;
         ev.shmseg = stuff->shmseg;
diff --git a/damageext/damageext.c b/damageext/damageext.c
index c80554e..d923434 100644
--- a/damageext/damageext.c
+++ b/damageext/damageext.c
@@ -50,7 +50,6 @@ DamageExtNotify (DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes)
     UpdateCurrentTimeIf ();
     ev.type = DamageEventBase + XDamageNotify;
     ev.level = pDamageExt->level;
-    ev.sequenceNumber = pClient->sequence;
     ev.drawable = pDamageExt->drawable;
     ev.damage = pDamageExt->id;
     ev.timestamp = currentTime.milliseconds;
diff --git a/dix/dispatch.c b/dix/dispatch.c
index fe9ddb2..c9e3188 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3741,7 +3741,6 @@ SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode,
 
     memset(&rep, 0, sizeof(xError));
     rep.type = X_Error;
-    rep.sequenceNumber = client->sequence;
     rep.errorCode = errorCode;
     rep.majorCode = majorCode;
     rep.minorCode = minorCode;
diff --git a/dix/events.c b/dix/events.c
index a00ecd9..39ad400 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1841,7 +1841,6 @@ int
 TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
                  int count, Mask mask, Mask filter, GrabPtr grab)
 {
-    int i;
     int type;
 
 #ifdef DEBUG_EVENTS
@@ -1908,7 +1907,6 @@ TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
             {
                 xEvent release = *pEvents;
                 release.u.u.type = KeyRelease;
-                release.u.u.sequenceNumber = client->sequence;
                 WriteEventsToClient(client, 1, &release);
 #ifdef DEBUG_EVENTS
                 ErrorF(" (plus fake core release for repeat)");
@@ -1929,7 +1927,6 @@ TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
             {
                 deviceKeyButtonPointer release = *(deviceKeyButtonPointer *)pEvents;
                 release.type = DeviceKeyRelease;
-                release.sequenceNumber = client->sequence;
 #ifdef DEBUG_EVENTS
                 ErrorF(" (plus fake xi1 release for repeat)");
 #endif
@@ -1943,14 +1940,6 @@ TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
         }
     }
 
-    type &= 0177;
-    if (type != KeymapNotify)
-    {
-        /* all extension events must have a sequence number */
-        for (i = 0; i < count; i++)
-            pEvents[i].u.u.sequenceNumber = client->sequence;
-    }
-
     if (BitIsOn(criticalEvents, type))
     {
         if (client->smart_priority < SMART_MAX_PRIORITY)
@@ -5672,6 +5661,10 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
     if (!pClient || pClient == serverClient || pClient->clientGone)
 	return;
 
+    for (i = 0; i < count; i++)
+	if ((events[i].u.u.type & 0x7f) != KeymapNotify)
+	    events[i].u.u.sequenceNumber = pClient->sequence;
+
     /* Let XKB rewrite the state, as it depends on client preferences. */
     XkbFilterEvents(pClient, count, events);
 
diff --git a/dix/inpututils.c b/dix/inpututils.c
index e3b44fc..8e75372 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -88,7 +88,6 @@ do_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client)
         if (!XIShouldNotify(clients[i], dev))
             continue;
 
-        core_mn.u.u.sequenceNumber = clients[i]->sequence;
         WriteEventsToClient(clients[i], 1, &core_mn);
     }
 
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index 9df682e..b971102 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -187,7 +187,6 @@ __glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust,
 	/* unknown swap completion type */
 	break;
     }
-    wire.sequenceNumber = client->sequence;
     wire.drawable = drawable->drawId;
     wire.ust_hi = ust >> 32;
     wire.ust_lo = ust & 0xffffffff;
diff --git a/hw/xfree86/dixmods/extmod/xf86vmode.c b/hw/xfree86/dixmods/extmod/xf86vmode.c
index 0b7f75e..754fe37 100644
--- a/hw/xfree86/dixmods/extmod/xf86vmode.c
+++ b/hw/xfree86/dixmods/extmod/xf86vmode.c
@@ -331,7 +331,6 @@ SendXF86VidModeNotify(ScreenPtr pScreen, int state, Bool forced)
     XF86VidModeEventPtr		pEv;
     unsigned long		mask;
     xXF86VidModeNotifyEvent	ev;
-    ClientPtr			client;
     int				kind;
 
     UpdateCurrentTimeIf ();
@@ -343,17 +342,15 @@ SendXF86VidModeNotify(ScreenPtr pScreen, int state, Bool forced)
     kind = XF86VidModeModeChange;
     for (pEv = pPriv->events; pEv; pEv = pEv->next)
     {
-	client = pEv->client;
 	if (!(pEv->mask & mask))
 	    continue;
 	ev.type = XF86VidModeNotify + XF86VidModeEventBase;
 	ev.state = state;
-	ev.sequenceNumber = client->sequence;
 	ev.timestamp = currentTime.milliseconds;
 	ev.root = WindowTable[pScreen->myNum]->drawable.id;
 	ev.kind = kind;
 	ev.forced = forced;
-	WriteEventsToClient (client, 1, (xEvent *) &ev);
+	WriteEventsToClient (pEv->client, 1, (xEvent *) &ev);
     }
 }
 
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
index 444751d..e6d98f5 100644
--- a/hw/xfree86/dri2/dri2ext.c
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -161,7 +161,6 @@ DRI2InvalidateBuffersEvent(DrawablePtr pDraw, void *priv)
     ClientPtr client = priv;
 
     event.type = DRI2EventBase + DRI2_InvalidateBuffers;
-    event.sequenceNumber = client->sequence;
     event.drawable = pDraw->id;
 
     WriteEventsToClient(client, 1, (xEvent *)&event);
@@ -363,7 +362,6 @@ DRI2SwapEvent(ClientPtr client, void *data, int type, CARD64 ust, CARD64 msc,
     DrawablePtr pDrawable = data;
 
     event.type = DRI2EventBase + DRI2_BufferSwapComplete;
-    event.sequenceNumber = client->sequence;
     event.event_type = type;
     event.drawable = pDrawable->id;
     event.ust_hi = (CARD64)ust >> 32;
diff --git a/hw/xquartz/applewm.c b/hw/xquartz/applewm.c
index 8c248ed..0845f67 100644
--- a/hw/xquartz/applewm.c
+++ b/hw/xquartz/applewm.c
@@ -341,7 +341,6 @@ ProcAppleWMSelectInput (register ClientPtr client)
 void
 AppleWMSendEvent (int type, unsigned int mask, int which, int arg) {
     WMEventPtr      *pHead, pEvent;
-    ClientPtr       client;
     xAppleWMNotifyEvent se;
     int             i;
 
@@ -349,15 +348,13 @@ AppleWMSendEvent (int type, unsigned int mask, int which, int arg) {
     if (i != Success || !pHead)
         return;
     for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
-        client = pEvent->client;
         if ((pEvent->mask & mask) == 0)
             continue;
         se.type = type + WMEventBase;
         se.kind = which;
         se.arg = arg;
-        se.sequenceNumber = client->sequence;
         se.time = currentTime.milliseconds;
-        WriteEventsToClient (client, 1, (xEvent *) &se);
+        WriteEventsToClient (pEvent->client, 1, (xEvent *) &se);
     }
 }
 
diff --git a/hw/xquartz/xpr/appledri.c b/hw/xquartz/xpr/appledri.c
index 0fbe850..3afe244 100644
--- a/hw/xquartz/xpr/appledri.c
+++ b/hw/xquartz/xpr/appledri.c
@@ -192,22 +192,16 @@ static void surface_notify(
 {
     DRISurfaceNotifyArg *arg = _arg;
     int client_index = (int) x_cvt_vptr_to_uint(data);
-    ClientPtr client;
     xAppleDRINotifyEvent se;
 
     if (client_index < 0 || client_index >= currentMaxClients)
         return;
 
-    client = clients[client_index];
-    if (client == NULL)
-        return;
-
     se.type = DRIEventBase + AppleDRISurfaceNotify;
     se.kind = arg->kind;
     se.arg = arg->id;
-    se.sequenceNumber = client->sequence;
     se.time = currentTime.milliseconds;
-    WriteEventsToClient (client, 1, (xEvent *) &se);
+    WriteEventsToClient (clients[client_index], 1, (xEvent *) &se);
 }
 
 static int
diff --git a/hw/xwin/winwindowswm.c b/hw/xwin/winwindowswm.c
index b534bd5..99329c3 100755
--- a/hw/xwin/winwindowswm.c
+++ b/hw/xwin/winwindowswm.c
@@ -319,7 +319,6 @@ winWindowsWMSendEvent (int type, unsigned int mask, int which, int arg,
       se.y = y;
       se.w = w;
       se.h = h;
-      se.sequenceNumber = client->sequence;
       se.time = currentTime.milliseconds;
       WriteEventsToClient (client, 1, (xEvent *) &se);
     }
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 8543535..95e74c5 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -254,7 +254,6 @@ RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc)
     
     ce.type = RRNotify + RREventBase;
     ce.subCode = RRNotify_CrtcChange;
-    ce.sequenceNumber = client->sequence;
     ce.timestamp = pScrPriv->lastSetTime.milliseconds;
     ce.window = pWin->drawable.id;
     ce.crtc = crtc->id;
diff --git a/randr/rroutput.c b/randr/rroutput.c
index e9ab2b9..445c318 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -337,7 +337,6 @@ RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output)
     
     oe.type = RRNotify + RREventBase;
     oe.subCode = RRNotify_OutputChange;
-    oe.sequenceNumber = client->sequence;
     oe.timestamp = pScrPriv->lastSetTime.milliseconds;
     oe.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
     oe.window = pWin->drawable.id;
diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index 3aab37a..5e37577 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -40,7 +40,6 @@ DeliverPropertyEvent(WindowPtr pWin, void *value)
 	if (!(pRREvent->mask & RROutputPropertyNotifyMask))
 	    continue;
 
-	event->sequenceNumber = pRREvent->client->sequence;
 	event->window = pRREvent->window->drawable.id;
 	WriteEventsToClient(pRREvent->client, 1, (xEvent *)event);
     }
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index 051d514..a940f8a 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -102,13 +102,11 @@ RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen)
     se.type = RRScreenChangeNotify + RREventBase;
     se.rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0);
     se.timestamp = pScrPriv->lastSetTime.milliseconds;
-    se.sequenceNumber = client->sequence;
     se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
     se.root =  pRoot->drawable.id;
     se.window = pWin->drawable.id;
     se.subpixelOrder = PictureGetSubpixelOrder (pScreen);
 
-    se.sequenceNumber = client->sequence;
     se.sizeID = RR10CurrentSizeID (pScreen);
 
     if (se.rotation & (RR_Rotate_90 | RR_Rotate_270)) {
diff --git a/xfixes/cursor.c b/xfixes/cursor.c
index e963069..e963e37 100644
--- a/xfixes/cursor.c
+++ b/xfixes/cursor.c
@@ -169,7 +169,6 @@ CursorDisplayCursor (DeviceIntPtr pDev,
 		xXFixesCursorNotifyEvent	ev;
 		ev.type = XFixesEventBase + XFixesCursorNotify;
 		ev.subtype = XFixesDisplayCursorNotify;
-		ev.sequenceNumber = e->pClient->sequence;
 		ev.window = e->pWindow->drawable.id;
 		ev.cursorSerial = pCursor->serialNumber;
 		ev.timestamp = currentTime.milliseconds;
diff --git a/xfixes/select.c b/xfixes/select.c
index ffd1c69..3aa26d3 100644
--- a/xfixes/select.c
+++ b/xfixes/select.c
@@ -85,7 +85,6 @@ XFixesSelectionCallback (CallbackListPtr *callbacks, pointer data, pointer args)
 	    memset(&ev, 0, sizeof(xXFixesSelectionNotifyEvent));
 	    ev.type = XFixesEventBase + XFixesSelectionNotify;
 	    ev.subtype = subtype;
-	    ev.sequenceNumber = e->pClient->sequence;
 	    ev.window = e->pWindow->drawable.id;
 	    if (subtype == XFixesSetSelectionOwnerNotify)
 		ev.owner = selection->window;
diff --git a/xkb/xkbEvents.c b/xkb/xkbEvents.c
index 0a6a76c..8028502 100644
--- a/xkb/xkbEvents.c
+++ b/xkb/xkbEvents.c
@@ -102,7 +102,6 @@ XkbSendLegacyMapNotify(DeviceIntPtr kbd, CARD16 xkb_event, CARD16 changed,
         if (!XIShouldNotify(clients[i], kbd))
             continue;
 
-        core_mn.u.u.sequenceNumber = clients[i]->sequence;
         if (keymap_changed) {
             core_mn.u.mappingNotify.request = MappingKeyboard;
 
commit 4b9600a4167427a8fe88bca9b738c9a99cac9469
Author: Jamey Sharp <jamey at minilop.net>
Date:   Sat May 15 12:31:34 2010 -0700

    Make WriteEventsToClient/WriteToClient no-op on fake or dead clients.
    
    This matches the test in TryClientEvents, and is a superset of tests
    done by the callers of these functions. The consequence of forgetting
    these tests is a server crash, so they're always desirable. In my
    opinion, it's better to not require the callers to remember to do these
    checks.
    
    For callers that don't do very much work before calling WriteToClient or
    WriteEventsToClient, I've removed the redundant checks.
    
    hw/xquartz/xpr/appledri.c has an interesting case: While its check for
    "client == NULL" appears redundant with the test in WriteEventsToClient,
    it dereferences client to get the sequence number.
    
    Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=27497
    Signed-off-by: Jamey Sharp <jamey at minilop.net>
    Cc: Chris Wilson <chris at chris-wilson.co.uk>
    Reviewed-by: Julien Cristau <jcristau at debian.org>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/Xext/saver.c b/Xext/saver.c
index 4b43a30..42fc632 100644
--- a/Xext/saver.c
+++ b/Xext/saver.c
@@ -500,8 +500,6 @@ SendScreenSaverNotify (ScreenPtr pScreen, int state, Bool forced)
     for (pEv = pPriv->events; pEv; pEv = pEv->next)
     {
 	client = pEv->client;
-	if (client->clientGone)
-	    continue;
 	if (!(pEv->mask & mask))
 	    continue;
 	ev.type = ScreenSaverNotify + ScreenSaverEventBase;
diff --git a/Xext/security.c b/Xext/security.c
index 7995ff2..16aac05 100644
--- a/Xext/security.c
+++ b/Xext/security.c
@@ -199,15 +199,11 @@ SecurityDeleteAuthorization(
     {
 	/* send revocation event event */
 	ClientPtr client = rClient(pEventClient);
-
-	if (!client->clientGone)
-	{
-	    xSecurityAuthorizationRevokedEvent are;
-	    are.type = SecurityEventBase + XSecurityAuthorizationRevoked;
-	    are.sequenceNumber = client->sequence;
-	    are.authId = pAuth->id;
-	    WriteEventsToClient(client, 1, (xEvent *)&are);
-	}
+	xSecurityAuthorizationRevokedEvent are;
+	are.type = SecurityEventBase + XSecurityAuthorizationRevoked;
+	are.sequenceNumber = client->sequence;
+	are.authId = pAuth->id;
+	WriteEventsToClient(client, 1, (xEvent *)&are);
 	FreeResource(pEventClient->resource, RT_NONE);
     }
 
diff --git a/Xext/shape.c b/Xext/shape.c
index cd75658..10437f4 100644
--- a/Xext/shape.c
+++ b/Xext/shape.c
@@ -941,8 +941,6 @@ SendShapeNotify (WindowPtr pWin, int which)
     }
     for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) {
 	client = pShapeEvent->client;
-	if (client == serverClient || client->clientGone)
-	    continue;
 	se.type = ShapeNotify + ShapeEventBase;
 	se.kind = which;
 	se.window = pWin->drawable.id;
diff --git a/Xext/sync.c b/Xext/sync.c
index d46087a..3729f1b 100644
--- a/Xext/sync.c
+++ b/Xext/sync.c
@@ -390,17 +390,14 @@ SyncSendAlarmNotifyEvents(SyncAlarm *pAlarm)
     ane.state = pAlarm->state;
 
     /* send to owner */
-    if (pAlarm->events && !pAlarm->client->clientGone)
+    if (pAlarm->events)
 	WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane);
 
     /* send to other interested clients */
     for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
     {
-	if (!pcl->client->clientGone)
-	{
-	    ane.sequenceNumber = pcl->client->sequence;
-	    WriteEventsToClient(pcl->client, 1, (xEvent *) &ane);
-	}
+	ane.sequenceNumber = pcl->client->sequence;
+	WriteEventsToClient(pcl->client, 1, (xEvent *) &ane);
     }
 }
 
diff --git a/Xext/xcalibrate.c b/Xext/xcalibrate.c
index 364b92a..8659384 100644
--- a/Xext/xcalibrate.c
+++ b/Xext/xcalibrate.c
@@ -59,8 +59,7 @@ xcalibrate_event_hook (int x, int y, int pressure, void *closure)
   ev.y = y;
   ev.pressure = pressure;
 
-  if (!pClient->clientGone)
-    WriteEventsToClient (pClient, 1, (xEvent *) &ev);
+  WriteEventsToClient (pClient, 1, (xEvent *) &ev);
 }
 
 static int
diff --git a/damageext/damageext.c b/damageext/damageext.c
index af4fef6..c80554e 100644
--- a/damageext/damageext.c
+++ b/damageext/damageext.c
@@ -69,8 +69,7 @@ DamageExtNotify (DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes)
 	    ev.area.y = pBoxes[i].y1;
 	    ev.area.width = pBoxes[i].x2 - pBoxes[i].x1;
 	    ev.area.height = pBoxes[i].y2 - pBoxes[i].y1;
-	    if (!pClient->clientGone)
-		WriteEventsToClient (pClient, 1, (xEvent *) &ev);
+	    WriteEventsToClient (pClient, 1, (xEvent *) &ev);
 	}
     }
     else
@@ -79,8 +78,7 @@ DamageExtNotify (DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes)
 	ev.area.y = 0;
 	ev.area.width = pDrawable->width;
 	ev.area.height = pDrawable->height;
-	if (!pClient->clientGone)
-	    WriteEventsToClient (pClient, 1, (xEvent *) &ev);
+	WriteEventsToClient (pClient, 1, (xEvent *) &ev);
     }
     /* Composite extension marks clients with manual Subwindows as critical */
     if (pDamageClient->critical > 0)
diff --git a/dix/events.c b/dix/events.c
index 3ed344d..a00ecd9 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -5669,6 +5669,9 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
     int       i,
               eventlength = sizeof(xEvent);
 
+    if (!pClient || pClient == serverClient || pClient->clientGone)
+	return;
+
     /* Let XKB rewrite the state, as it depends on client preferences. */
     XkbFilterEvents(pClient, count, events);
 
diff --git a/hw/xfree86/dixmods/extmod/xf86vmode.c b/hw/xfree86/dixmods/extmod/xf86vmode.c
index 665f743..0b7f75e 100644
--- a/hw/xfree86/dixmods/extmod/xf86vmode.c
+++ b/hw/xfree86/dixmods/extmod/xf86vmode.c
@@ -344,8 +344,6 @@ SendXF86VidModeNotify(ScreenPtr pScreen, int state, Bool forced)
     for (pEv = pPriv->events; pEv; pEv = pEv->next)
     {
 	client = pEv->client;
-	if (client->clientGone)
-	    continue;
 	if (!(pEv->mask & mask))
 	    continue;
 	ev.type = XF86VidModeNotify + XF86VidModeEventBase;
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
index 44a47cc..444751d 100644
--- a/hw/xfree86/dri2/dri2ext.c
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -160,9 +160,6 @@ DRI2InvalidateBuffersEvent(DrawablePtr pDraw, void *priv)
     xDRI2InvalidateBuffers event;
     ClientPtr client = priv;
 
-    if (client->clientGone)
-	return;
-
     event.type = DRI2EventBase + DRI2_InvalidateBuffers;
     event.sequenceNumber = client->sequence;
     event.drawable = pDraw->id;
diff --git a/hw/xquartz/applewm.c b/hw/xquartz/applewm.c
index 53d167e..8c248ed 100644
--- a/hw/xquartz/applewm.c
+++ b/hw/xquartz/applewm.c
@@ -350,11 +350,8 @@ AppleWMSendEvent (int type, unsigned int mask, int which, int arg) {
         return;
     for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
         client = pEvent->client;
-        if ((pEvent->mask & mask) == 0
-            || client == serverClient || client->clientGone)
-        {
+        if ((pEvent->mask & mask) == 0)
             continue;
-        }
         se.type = type + WMEventBase;
         se.kind = which;
         se.arg = arg;
diff --git a/hw/xquartz/xpr/appledri.c b/hw/xquartz/xpr/appledri.c
index 71cfb59..0fbe850 100644
--- a/hw/xquartz/xpr/appledri.c
+++ b/hw/xquartz/xpr/appledri.c
@@ -199,7 +199,7 @@ static void surface_notify(
         return;
 
     client = clients[client_index];
-    if (client == NULL || client == serverClient || client->clientGone)
+    if (client == NULL)
         return;
 
     se.type = DRIEventBase + AppleDRISurfaceNotify;
diff --git a/hw/xwin/winwindowswm.c b/hw/xwin/winwindowswm.c
index d09e983..b534bd5 100755
--- a/hw/xwin/winwindowswm.c
+++ b/hw/xwin/winwindowswm.c
@@ -304,8 +304,7 @@ winWindowsWMSendEvent (int type, unsigned int mask, int which, int arg,
 #if CYGMULTIWINDOW_DEBUG
       ErrorF ("winWindowsWMSendEvent - x%08x\n", (int) client);
 #endif
-      if ((pEvent->mask & mask) == 0
-	  || client == serverClient || client->clientGone)
+      if ((pEvent->mask & mask) == 0)
 	{
 	  continue;
 	}
diff --git a/os/io.c b/os/io.c
index 8335102..02e1ca3 100644
--- a/os/io.c
+++ b/os/io.c
@@ -698,15 +698,17 @@ SetCriticalOutputPending(void)
 int
 WriteToClient (ClientPtr who, int count, const void *__buf)
 {
-    OsCommPtr oc = (OsCommPtr)who->osPrivate;
-    ConnectionOutputPtr oco = oc->output;
+    OsCommPtr oc;
+    ConnectionOutputPtr oco;
     int padBytes;
     const char *buf = __buf;
 #ifdef DEBUG_COMMUNICATION
     Bool multicount = FALSE;
 #endif
-    if (!count)
+    if (!count || !who || who == serverClient || who->clientGone)
 	return(0);
+    oc = who->osPrivate;
+    oco = oc->output;
 #ifdef DEBUG_COMMUNICATION
     {
 	char info[128];
diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index ff0bca0..3aab37a 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -29,7 +29,6 @@ DeliverPropertyEvent(WindowPtr pWin, void *value)
 {
     xRROutputPropertyNotifyEvent *event = value;
     RREventPtr *pHead, pRREvent;
-    ClientPtr client;
 
     dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
 			    RREventType, serverClient, DixReadAccess);
@@ -38,14 +37,10 @@ DeliverPropertyEvent(WindowPtr pWin, void *value)
 
     for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
     {
-	client = pRREvent->client;
-	if (client == serverClient || client->clientGone)
-	    continue;
-
 	if (!(pRREvent->mask & RROutputPropertyNotifyMask))
 	    continue;
 
-	event->sequenceNumber = client->sequence;
+	event->sequenceNumber = pRREvent->client->sequence;
 	event->window = pRREvent->window->drawable.id;
 	WriteEventsToClient(pRREvent->client, 1, (xEvent *)event);
     }
diff --git a/xfixes/cursor.c b/xfixes/cursor.c
index d5f8b29..e963069 100644
--- a/xfixes/cursor.c
+++ b/xfixes/cursor.c
@@ -164,8 +164,7 @@ CursorDisplayCursor (DeviceIntPtr pDev,
 	CursorCurrent[pDev->id] = pCursor;
 	for (e = cursorEvents; e; e = e->next)
 	{
-	    if ((e->eventMask & XFixesDisplayCursorNotifyMask) &&
-		!e->pClient->clientGone)
+	    if ((e->eventMask & XFixesDisplayCursorNotifyMask))
 	    {
 		xXFixesCursorNotifyEvent	ev;
 		ev.type = XFixesEventBase + XFixesCursorNotify;
diff --git a/xfixes/select.c b/xfixes/select.c
index 6d86f63..ffd1c69 100644
--- a/xfixes/select.c
+++ b/xfixes/select.c
@@ -78,8 +78,7 @@ XFixesSelectionCallback (CallbackListPtr *callbacks, pointer data, pointer args)
     for (e = selectionEvents; e; e = e->next)
     {
 	if (e->selection == selection->selection && 
-	    (e->eventMask & eventMask) &&
-	    !e->pClient->clientGone)
+	    (e->eventMask & eventMask))
 	{
 	    xXFixesSelectionNotifyEvent	ev;
 
commit ee9cd2df4a5af66c6b7073563785b8aef61fcdb8
Author: Jamey Sharp <jamey at minilop.net>
Date:   Sat May 15 13:37:34 2010 -0700

    xv: TryClientEvents already checks client and sets sequenceNumber.
    
    So don't bother doing those steps again.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>
    Reviewed-by: Julien Cristau <jcristau at debian.org>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/Xext/xvmain.c b/Xext/xvmain.c
index 72678f7..45d5946 100644
--- a/Xext/xvmain.c
+++ b/Xext/xvmain.c
@@ -530,17 +530,13 @@ XvdiSendVideoNotify(XvPortPtr pPort, DrawablePtr pDraw, int reason)
 
   while (pn) 
     {
-      if (pn->client)
-	{
-	  event.u.u.type = XvEventBase + XvVideoNotify;
-	  event.u.u.sequenceNumber = pn->client->sequence;
-	  event.u.videoNotify.time = currentTime.milliseconds;
-	  event.u.videoNotify.drawable = pDraw->id;
-	  event.u.videoNotify.port = pPort->id;
-	  event.u.videoNotify.reason = reason;
-	  TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1,
-                          NoEventMask, NoEventMask, NullGrab);
-	}
+      event.u.u.type = XvEventBase + XvVideoNotify;
+      event.u.videoNotify.time = currentTime.milliseconds;
+      event.u.videoNotify.drawable = pDraw->id;
+      event.u.videoNotify.port = pPort->id;
+      event.u.videoNotify.reason = reason;
+      TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1,
+		      NoEventMask, NoEventMask, NullGrab);
       pn = pn->next;
     }
 
@@ -562,17 +558,13 @@ XvdiSendPortNotify(
 
   while (pn) 
     {
-      if (pn->client)
-	{
-	  event.u.u.type = XvEventBase + XvPortNotify;
-	  event.u.u.sequenceNumber = pn->client->sequence;
-	  event.u.portNotify.time = currentTime.milliseconds;
-	  event.u.portNotify.port = pPort->id;
-	  event.u.portNotify.attribute = attribute;
-	  event.u.portNotify.value = value;
-	  TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1,
-                          NoEventMask, NoEventMask, NullGrab);
-	}
+      event.u.u.type = XvEventBase + XvPortNotify;
+      event.u.portNotify.time = currentTime.milliseconds;
+      event.u.portNotify.port = pPort->id;
+      event.u.portNotify.attribute = attribute;
+      event.u.portNotify.value = value;
+      TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1,
+		      NoEventMask, NoEventMask, NullGrab);
       pn = pn->next;
     }
 
commit e1e7deefb59cfdd82c9de46a7ca241d42436b2f8
Author: Jamey Sharp <jamey at minilop.net>
Date:   Tue May 18 16:49:21 2010 -0700

    mi/misprite.c: Delete unused private lookups.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/mi/misprite.c b/mi/misprite.c
index 385f67a..3d10bc8 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -257,12 +257,9 @@ static void
 miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
 {
     ScreenPtr		    pScreen = closure;
-    miSpriteScreenPtr	    pScreenPriv;
     miCursorInfoPtr         pCursorInfo;
     DeviceIntPtr            pDev;
 
-    pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
-
     for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
         if (DevHasCursor(pDev))
@@ -394,7 +391,6 @@ miSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h,
                   char *pdstLine)
 {
     ScreenPtr	    pScreen = pDrawable->pScreen;
-    miSpriteScreenPtr    pScreenPriv;
     DeviceIntPtr    pDev;
     miCursorInfoPtr pCursorInfo;
 
@@ -402,7 +398,6 @@ miSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h,
 
     if (pDrawable->type == DRAWABLE_WINDOW)
     {
-        pScreenPriv = dixLookupPrivate(&pScreen->devPrivates,miSpriteScreenKey);
         for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
         {
             if (DevHasCursor(pDev))
@@ -430,7 +425,6 @@ miSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
                   int *pwidth, int nspans, char *pdstStart)
 {
     ScreenPtr		    pScreen = pDrawable->pScreen;
-    miSpriteScreenPtr	    pScreenPriv;
     DeviceIntPtr            pDev;
     miCursorInfoPtr         pCursorInfo;
 
@@ -438,8 +432,6 @@ miSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
 
     if (pDrawable->type == DRAWABLE_WINDOW)
     {
-        pScreenPriv = dixLookupPrivate(&pScreen->devPrivates,miSpriteScreenKey);
-
         for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
         {
             if (DevHasCursor(pDev))
@@ -484,7 +476,6 @@ miSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width,
                         int height)
 {
     ScreenPtr		    pScreen = pDrawable->pScreen;
-    miSpriteScreenPtr	    pScreenPriv;
     DeviceIntPtr            pDev;
     miCursorInfoPtr         pCursorInfo;
 
@@ -492,8 +483,6 @@ miSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width,
 
     if (pDrawable->type == DRAWABLE_WINDOW)
     {
-	pScreenPriv = dixLookupPrivate(&pScreen->devPrivates,miSpriteScreenKey);
-
 	for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
 	{
 	    if (DevHasCursor(pDev))
@@ -520,14 +509,11 @@ static void
 miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
 {
     ScreenPtr	pScreen = pWindow->drawable.pScreen;
-    miSpriteScreenPtr	    pScreenPriv;
     DeviceIntPtr            pDev;
     miCursorInfoPtr         pCursorInfo;
 
     SCREEN_PROLOGUE (pScreen, CopyWindow);
 
-    pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
-
     for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
         if (DevHasCursor(pDev))
@@ -893,10 +879,8 @@ miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
 static void
 miSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
-    miSpriteScreenPtr	pScreenPriv;
     CursorPtr pCursor;
 
-    pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
     if (!IsMaster(pDev) && !pDev->u.master)
         return;
 
@@ -1068,7 +1052,6 @@ miSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
 static void
 miSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen)
 {
-    miSpriteScreenPtr   pScreenPriv;
     int		    x, y, w, h;
     int		    wpad, hpad;
     CursorPtr	    pCursor;
@@ -1077,7 +1060,6 @@ miSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen)
     if (!IsMaster(pDev) && !pDev->u.master)
         return;
 
-    pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
     pCursorInfo = MISPRITE(pDev);
 
     pCursor = pCursorInfo->pCursor;
commit 936b09f2a3e31afe41050c00736bbb6b812c7003
Author: Jamey Sharp <jamey at minilop.net>
Date:   Tue May 18 16:48:08 2010 -0700

    Replace miSpriteCursorFuncRec with direct calls to midispcur.c.
    
    Nobody wraps the mi software-cursor sprite rendering implementations.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/mi/midispcur.c b/mi/midispcur.c
index 1acc469..61e3133 100644
--- a/mi/midispcur.c
+++ b/mi/midispcur.c
@@ -97,44 +97,6 @@ typedef struct {
 #endif
 } miDCCursorRec, *miDCCursorPtr;
 
-/*
- * sprite/cursor method table
- */
-
-static Bool	miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
-static Bool	miDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
-static Bool	miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
-                                CursorPtr pCursor, int x, int y, 
-                                unsigned long source, unsigned long mask);
-static Bool	miDCSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
-                                    int x, int y,
-				    int w, int h);
-static Bool	miDCRestoreUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
-                                       int x, int y,
-				       int w, int h);
-static Bool	miDCMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
-                               CursorPtr pCursor, int x, int y, 
-                               int w, int h, int dx, int dy,
-			       unsigned long source, unsigned long mask);
-static Bool	miDCChangeSave(DeviceIntPtr pDev, ScreenPtr pScreen, 
-                               int x, int y, int w, int h,	
-                               int dx, int dy);
-
-static Bool     miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
-static void     miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen);
-
-static miSpriteCursorFuncRec miDCFuncs = {
-    miDCRealizeCursor,
-    miDCUnrealizeCursor,
-    miDCPutUpCursor,
-    miDCSaveUnderCursor,
-    miDCRestoreUnderCursor,
-    miDCMoveCursor,
-    miDCChangeSave,
-    miDCDeviceInitialize,
-    miDCDeviceCleanup
-};
-
 Bool
 miDCInitialize (ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs)
 {
@@ -150,7 +112,7 @@ miDCInitialize (ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs)
 
     dixSetPrivate(&pScreen->devPrivates, miDCScreenKey, pScreenPriv);
 
-    if (!miSpriteInitialize (pScreen, &miDCFuncs, screenFuncs))
+    if (!miSpriteInitialize (pScreen, screenFuncs))
     {
 	free((pointer) pScreenPriv);
 	return FALSE;
@@ -170,7 +132,7 @@ miDCCloseScreen (int index, ScreenPtr pScreen)
     return (*pScreen->CloseScreen) (index, pScreen);
 }
 
-static Bool
+Bool
 miDCRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
 {
     if (pCursor->bits->refcnt <= 1)
@@ -329,7 +291,7 @@ miDCRealize (ScreenPtr pScreen, CursorPtr pCursor)
     return pPriv;
 }
 
-static Bool
+Bool
 miDCUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
 {
     miDCCursorPtr   pPriv;
@@ -426,7 +388,7 @@ miDCMakeGC(WindowPtr pWin)
 }
 
 
-static Bool
+Bool
 miDCPutUpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
                  int x, int y, unsigned long source, unsigned long mask)
 {
@@ -471,7 +433,7 @@ miDCPutUpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
     return TRUE;
 }
 
-static Bool
+Bool
 miDCSaveUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
                      int x, int y, int w, int h)
 {
@@ -505,7 +467,7 @@ miDCSaveUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
     return TRUE;
 }
 
-static Bool
+Bool
 miDCRestoreUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
                         int x, int y, int w, int h)
 {
@@ -532,7 +494,7 @@ miDCRestoreUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
     return TRUE;
 }
 
-static Bool
+Bool
 miDCChangeSave (DeviceIntPtr pDev, ScreenPtr pScreen,
                 int x, int y, int w, int h, int dx, int dy)
 {
@@ -665,7 +627,7 @@ miDCChangeSave (DeviceIntPtr pDev, ScreenPtr pScreen,
     return TRUE;
 }
 
-static Bool
+Bool
 miDCMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
                 int x, int y, int w, int h, int dx, int dy,
                 unsigned long source, unsigned long mask)
@@ -764,7 +726,7 @@ miDCMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
     return TRUE;
 }
 
-static Bool
+Bool
 miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
 {
     miDCBufferPtr   pBuffer;
@@ -839,7 +801,7 @@ failure:
     return FALSE;
 }
 
-static void
+void
 miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
 {
     miDCBufferPtr   pBuffer;
diff --git a/mi/misprite.c b/mi/misprite.c
index 9f10a2b..385f67a 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -94,7 +94,6 @@ typedef struct {
     ColormapPtr     pInstalledMap;
     ColormapPtr     pColormap;
     VisualPtr	    pVisual;
-    miSpriteCursorFuncPtr    funcs;
     DamagePtr	    pDamage;		/* damage tracking structure */
     Bool            damageRegistered;
 } miSpriteScreenRec, *miSpriteScreenPtr;
@@ -289,7 +288,6 @@ miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
 
 Bool
 miSpriteInitialize (ScreenPtr               pScreen,
-                    miSpriteCursorFuncPtr   cursorFuncs,
                     miPointerScreenFuncPtr  screenFuncs)
 {
     miSpriteScreenPtr	pScreenPriv;
@@ -336,7 +334,6 @@ miSpriteInitialize (ScreenPtr               pScreen,
 
     pScreenPriv->pInstalledMap = NULL;
     pScreenPriv->pColormap = NULL;
-    pScreenPriv->funcs = cursorFuncs;
     pScreenPriv->colors[SOURCE_COLOR].red = 0;
     pScreenPriv->colors[SOURCE_COLOR].green = 0;
     pScreenPriv->colors[SOURCE_COLOR].blue = 0;
@@ -760,10 +757,8 @@ miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
 static Bool
 miSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
 {
-    miSpriteScreenPtr	pScreenPriv;
     miCursorInfoPtr pCursorInfo;
 
-    pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
     if (!IsMaster(pDev) && !pDev->u.master)
         return FALSE;
 
@@ -772,27 +767,21 @@ miSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
     if (pCursor == pCursorInfo->pCursor)
 	pCursorInfo->checkPixels = TRUE;
 
-    return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor);
+    return miDCRealizeCursor(pScreen, pCursor);
 }
 
 static Bool
 miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
 {
-    miSpriteScreenPtr	pScreenPriv;
-
-    pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
-    return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor);
+    return miDCUnrealizeCursor(pScreen, pCursor);
 }
 
 static void
 miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
                    CursorPtr pCursor, int x, int y)
 {
-    miSpriteScreenPtr	pScreenPriv;
     miCursorInfoPtr pPointer;
 
-    pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
-
     if (!IsMaster(pDev) && !pDev->u.master)
         return;
 
@@ -861,7 +850,7 @@ miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
 		pointer->saved.y1 -= dy;
 		pointer->saved.x2 -= dx;
 		pointer->saved.y2 -= dy;
-		(void) (*pScreenPriv->funcs->ChangeSave) (pScreen,
+		(void) miDCChangeSave(pScreen,
 				pointer->saved.x1,
  				pointer->saved.y1,
                                 pointer->saved.x2 -
@@ -870,7 +859,7 @@ miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
                                 pointer->saved.y1,
 				dx, dy);
 	    }
-	    (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor,
+	    (void) miDCMoveCursor(pScreen, pCursor,
 				  pointer->saved.x1,
  				  pointer->saved.y1,
                                   pointer->saved.x2 -
@@ -920,12 +909,9 @@ miSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 static Bool
 miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
 {
-    miSpriteScreenPtr pScreenPriv;
     miCursorInfoPtr pCursorInfo;
     int ret = FALSE;
 
-    pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
-
     pCursorInfo = malloc(sizeof(miCursorInfoRec));
     if (!pCursorInfo)
         return FALSE;
@@ -940,7 +926,7 @@ miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
     pCursorInfo->checkPixels = TRUE;
     pCursorInfo->pScreen = FALSE;
 
-    ret = (*pScreenPriv->funcs->DeviceCursorInitialize)(pDev, pScreen);
+    ret = miDCDeviceInitialize(pDev, pScreen);
     if (!ret)
     {
         free(pCursorInfo);
@@ -954,13 +940,7 @@ static void
 miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
 {
     if (DevHasCursor(pDev))
-    {
-        miSpriteScreenPtr pScreenPriv;
-        pScreenPriv = dixLookupPrivate(&pScreen->devPrivates,
-                                       miSpriteScreenKey);
-
-        (*pScreenPriv->funcs->DeviceCursorCleanup)(pDev, pScreen);
-    }
+        miDCDeviceCleanup(pDev, pScreen);
 }
 
 /*
@@ -984,16 +964,16 @@ miSpriteRemoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
     miSpriteIsDown(pCursorInfo);
     pCursorInfo->pCacheWin = NullWindow;
     miSpriteDisableDamage(pScreen, pScreenPriv);
-    if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pDev,
-                                         pScreen,
-					 pCursorInfo->saved.x1,
-                                         pCursorInfo->saved.y1,
-                                         pCursorInfo->saved.x2 -
-                                         pCursorInfo->saved.x1,
-                                         pCursorInfo->saved.y2 -
-                                         pCursorInfo->saved.y1))
+    if (!miDCRestoreUnderCursor(pDev,
+                                pScreen,
+                                pCursorInfo->saved.x1,
+                                pCursorInfo->saved.y1,
+                                pCursorInfo->saved.x2 -
+                                pCursorInfo->saved.x1,
+                                pCursorInfo->saved.y2 -
+                                pCursorInfo->saved.y1))
     {
-	miSpriteIsUp(pCursorInfo);
+        miSpriteIsUp(pCursorInfo);
     }
     miSpriteEnableDamage(pScreen, pScreenPriv);
     DamageDrawInternal (pScreen, FALSE);
@@ -1026,14 +1006,14 @@ miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
     y = pCursorInfo->y - (int)pCursor->bits->yhot;
     miSpriteDisableDamage(pScreen, pScreenPriv);
 
-    (*pScreenPriv->funcs->SaveUnderCursor) (pDev,
-                                      pScreen,
-				      pCursorInfo->saved.x1,
-				      pCursorInfo->saved.y1,
-                                      pCursorInfo->saved.x2 -
-                                      pCursorInfo->saved.x1,
-                                      pCursorInfo->saved.y2 -
-                                      pCursorInfo->saved.y1);
+    miDCSaveUnderCursor(pDev,
+                        pScreen,
+                        pCursorInfo->saved.x1,
+                        pCursorInfo->saved.y1,
+                        pCursorInfo->saved.x2 -
+                        pCursorInfo->saved.x1,
+                        pCursorInfo->saved.y2 -
+                        pCursorInfo->saved.y1);
     SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id));
     miSpriteEnableDamage(pScreen, pScreenPriv);
     DamageDrawInternal (pScreen, FALSE);
@@ -1069,7 +1049,7 @@ miSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
     SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id));
     if (pCursorInfo->checkPixels)
         miSpriteFindColors (pCursorInfo, pScreen);
-    if ((*pScreenPriv->funcs->PutUpCursor) (pDev, pScreen,
+    if (miDCPutUpCursor(pDev, pScreen,
                 pCursor, x, y,
                 pScreenPriv->colors[SOURCE_COLOR].pixel,
                 pScreenPriv->colors[MASK_COLOR].pixel))
diff --git a/mi/misprite.h b/mi/misprite.h
index 72dc06f..78bf52c 100644
--- a/mi/misprite.h
+++ b/mi/misprite.h
@@ -32,76 +32,26 @@ used in advertising or otherwise to promote the sale, use or other dealings
 in this Software without prior written authorization from The Open Group.
 */
 
-typedef struct {
-    Bool	(*RealizeCursor)(
-		ScreenPtr /*pScreen*/,
-		CursorPtr /*pCursor*/
-);
-    Bool	(*UnrealizeCursor)(
-		ScreenPtr /*pScreen*/,
-		CursorPtr /*pCursor*/
-);
-    Bool	(*PutUpCursor)(
-                DeviceIntPtr /*pDev*/,
-		ScreenPtr /*pScreen*/,
-		CursorPtr /*pCursor*/,
-		int /*x*/,
-		int /*y*/,
-		unsigned long /*source*/,
-		unsigned long /*mask*/
-);
-    Bool	(*SaveUnderCursor)(
-                DeviceIntPtr /*pDev*/,
-		ScreenPtr /*pScreen*/,
-		int /*x*/,
-		int /*y*/,
-		int /*w*/,
-		int /*h*/
-);
-    Bool	(*RestoreUnderCursor)(
-                DeviceIntPtr /*pDev*/,
-		ScreenPtr /*pScreen*/,
-		int /*x*/,
-		int /*y*/,
-		int /*w*/,
-		int /*h*/
-);
-    Bool	(*MoveCursor)(
-                DeviceIntPtr /*pDev*/,
-		ScreenPtr /*pScreen*/,
-		CursorPtr /*pCursor*/,
-		int /*x*/,
-		int /*y*/,
-		int /*w*/,
-		int /*h*/,
-		int /*dx*/,
-		int /*dy*/,
-		unsigned long /*source*/,
-		unsigned long /*mask*/
-);
-    Bool	(*ChangeSave)(
-                DeviceIntPtr /*pDev*/,
-		ScreenPtr /*pScreen*/,
-		int /*x*/,
-		int /*y*/,
-		int /*w*/,
-		int /*h*/,
-		int /*dx*/,
-		int /*dy*/
-);
-    Bool	(*DeviceCursorInitialize)(
-                DeviceIntPtr /*pDev*/,
-		ScreenPtr /*pScreen*/
-);
-    void	(*DeviceCursorCleanup)(
-                DeviceIntPtr /*pDev*/,
-		ScreenPtr /*pScreen*/
-);
-
-} miSpriteCursorFuncRec, *miSpriteCursorFuncPtr;
-
 extern Bool miSpriteInitialize(
     ScreenPtr /*pScreen*/,
-    miSpriteCursorFuncPtr /*cursorFuncs*/,
     miPointerScreenFuncPtr /*screenFuncs*/
 );
+
+extern Bool miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
+extern Bool miDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
+extern Bool miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+                            CursorPtr pCursor, int x, int y,
+                            unsigned long source, unsigned long mask);
+extern Bool miDCSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+                                int x, int y, int w, int h);
+extern Bool miDCRestoreUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+                                   int x, int y, int w, int h);
+extern Bool miDCMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+                           CursorPtr pCursor, int x, int y,
+                           int w, int h, int dx, int dy,
+                           unsigned long source, unsigned long mask);
+extern Bool miDCChangeSave(DeviceIntPtr pDev, ScreenPtr pScreen,
+                           int x, int y, int w, int h,
+                           int dx, int dy);
+extern Bool miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
+extern void miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen);
commit 66d5ecc5fd36e21715531a39ac83dc2b6b988a7e
Author: Tiago Vignatti <tiago.vignatti at nokia.com>
Date:   Tue May 18 13:53:29 2010 +0300

    render: set anim cursor state for pointer enabled devices only
    
    The structure containing the state of animated cursor was amended within
    SpriteInfoRec, removing all previously privates logic to keep such state.
    
    API change: It was removed MAXDEVICES dependency \o/
    
    Signed-off-by: Tiago Vignatti <tiago.vignatti at nokia.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/include/inputstr.h b/include/inputstr.h
index 6da3f38..c5b9ff7 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -477,6 +477,14 @@ typedef struct _SpriteInfoRec {
     DeviceIntPtr        paired;      /* The paired device. Keyboard if
                                         spriteOwner is TRUE, otherwise the
                                         pointer that owns the sprite. */ 
+
+    /* keep states for animated cursor */
+    struct {
+        CursorPtr       pCursor;
+        ScreenPtr       pScreen;
+        int             elt;
+        CARD32          time;
+    } anim;
 } SpriteInfoRec, *SpriteInfoPtr;
 
 /* device types */
diff --git a/render/animcur.c b/render/animcur.c
index 83211cc..ad126fb 100644
--- a/render/animcur.c
+++ b/render/animcur.c
@@ -70,24 +70,12 @@ typedef struct _AnimScrPriv {
     RecolorCursorProcPtr	RecolorCursor;
 } AnimCurScreenRec, *AnimCurScreenPtr;
 
-typedef struct _AnimCurState {
-    CursorPtr			pCursor;
-    ScreenPtr			pScreen;
-    int				elt;
-    CARD32			time;
-} AnimCurStateRec, *AnimCurStatePtr;
-
-/* What a waste. But we need an API change to alloc it per device only. */
-static AnimCurStateRec animCurState[MAXDEVICES];
-
 static unsigned char empty[4];
 
 static CursorBits   animCursorBits = {
     empty, empty, 2, 1, 1, 0, 0, 1
 };
 
-static int AnimCurGeneration;
-
 static int AnimCurScreenPrivateKeyIndex;
 static DevPrivateKey AnimCurScreenPrivateKey = &AnimCurScreenPrivateKeyIndex;
 
@@ -167,14 +155,14 @@ AnimCurScreenBlockHandler (int screenNum,
 
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
-	if (IsPointerDevice(dev) && pScreen == animCurState[dev->id].pScreen)
+	if (IsPointerDevice(dev) && pScreen == dev->spriteInfo->anim.pScreen)
 	{
 	    if (!now) now = GetTimeInMillis (); 
 
-	    if ((INT32) (now - animCurState[dev->id].time) >= 0)
+	    if ((INT32) (now - dev->spriteInfo->anim.time) >= 0)
 	    {
-		AnimCurPtr ac  = GetAnimCur(animCurState[dev->id].pCursor);
-		int        elt = (animCurState[dev->id].elt + 1) % ac->nelt;
+		AnimCurPtr ac  = GetAnimCur(dev->spriteInfo->anim.pCursor);
+		int        elt = (dev->spriteInfo->anim.elt + 1) % ac->nelt;
 		DisplayCursorProcPtr DisplayCursor;
 
 		/*
@@ -190,12 +178,12 @@ AnimCurScreenBlockHandler (int screenNum,
 		as->DisplayCursor = pScreen->DisplayCursor;
 		pScreen->DisplayCursor = DisplayCursor;
 
-		animCurState[dev->id].elt = elt;
-		animCurState[dev->id].time = now + ac->elts[elt].delay;
+		dev->spriteInfo->anim.elt = elt;
+		dev->spriteInfo->anim.time = now + ac->elts[elt].delay;
 	    }
 
-	    if (soonest > animCurState[dev->id].time)
-		soonest = animCurState[dev->id].time;
+	    if (soonest > dev->spriteInfo->anim.time)
+		soonest = dev->spriteInfo->anim.time;
 	}
     }
 
@@ -218,7 +206,7 @@ AnimCurDisplayCursor (DeviceIntPtr pDev,
     Unwrap (as, pScreen, DisplayCursor);
     if (IsAnimCur(pCursor))
     {
-	if (pCursor != animCurState[pDev->id].pCursor)
+	if (pCursor != pDev->spriteInfo->anim.pCursor)
 	{
 	    AnimCurPtr		ac = GetAnimCur(pCursor);
 
@@ -226,10 +214,10 @@ AnimCurDisplayCursor (DeviceIntPtr pDev,
                 (pDev, pScreen, ac->elts[0].pCursor);
 	    if (ret)
 	    {
-		animCurState[pDev->id].elt = 0;
-		animCurState[pDev->id].time = GetTimeInMillis () + ac->elts[0].delay;
-		animCurState[pDev->id].pCursor = pCursor;
-		animCurState[pDev->id].pScreen = pScreen;
+		pDev->spriteInfo->anim.elt = 0;
+		pDev->spriteInfo->anim.time = GetTimeInMillis () + ac->elts[0].delay;
+		pDev->spriteInfo->anim.pCursor = pCursor;
+		pDev->spriteInfo->anim.pScreen = pScreen;
 	    }
 	}
 	else
@@ -237,8 +225,8 @@ AnimCurDisplayCursor (DeviceIntPtr pDev,
     }
     else
     {
-        animCurState[pDev->id].pCursor = 0;
-	animCurState[pDev->id].pScreen = 0;
+	pDev->spriteInfo->anim.pCursor = 0;
+	pDev->spriteInfo->anim.pScreen = 0;
 	ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor);
     }
     Wrap (as, pScreen, DisplayCursor, AnimCurDisplayCursor);
@@ -256,8 +244,8 @@ AnimCurSetCursorPosition (DeviceIntPtr pDev,
     Bool		ret;
     
     Unwrap (as, pScreen, SetCursorPosition);
-    if (animCurState[pDev->id].pCursor)
-	animCurState[pDev->id].pScreen = pScreen;
+    if (pDev->spriteInfo->anim.pCursor)
+	pDev->spriteInfo->anim.pScreen = pScreen;
     ret = (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent);
     Wrap (as, pScreen, SetCursorPosition, AnimCurSetCursorPosition);
     return ret;
@@ -322,7 +310,7 @@ AnimCurRecolorCursor (DeviceIntPtr pDev,
         for (i = 0; i < ac->nelt; i++)
 	    (*pScreen->RecolorCursor) (pDev, pScreen, ac->elts[i].pCursor,
 				       displayed && 
-				       animCurState[pDev->id].elt == i);
+				       pDev->spriteInfo->anim.elt == i);
     }
     else
 	(*pScreen->RecolorCursor) (pDev, pScreen, pCursor, displayed);
@@ -334,17 +322,6 @@ AnimCurInit (ScreenPtr pScreen)
 {
     AnimCurScreenPtr    as;
 
-    if (AnimCurGeneration != serverGeneration)
-    {
-        int i;
-	AnimCurGeneration = serverGeneration;
-        for (i = 0; i < MAXDEVICES; i++) {
-            animCurState[i].pCursor = 0;
-            animCurState[i].pScreen = 0;
-            animCurState[i].elt = 0;
-            animCurState[i].time = 0;
-        }
-    }
     as = (AnimCurScreenPtr) malloc(sizeof (AnimCurScreenRec));
     if (!as)
 	return FALSE;
commit 99fcf655bdc96f7e5b2249b05da51ba4fc9190c7
Author: Tiago Vignatti <tiago.vignatti at nokia.com>
Date:   Sun May 2 22:34:44 2010 +0300

    xfree86: remove PCI dependency from InitOutput
    
    All functions that touch PCI and BUS were moved to their own files, organizing
    the mess inside the InitOutput. Now, inside InitOutput, mostly accesses to
    buses are coordinated by the new xf86BusConfig.
    
    Two PCI probe functions just changed the name and a procedure to receive the
    isolate devices parameters was created also, named xf86PciIsolateDevice.
    
    Signed-off-by: Tiago Vignatti <tiago.vignatti at nokia.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
index 153fc74..8a73925 100644
--- a/hw/xfree86/common/xf86Bus.c
+++ b/hw/xfree86/common/xf86Bus.c
@@ -58,6 +58,140 @@ static int xf86EntityPrivateCount = 0;
 
 BusRec primaryBus = { BUS_NONE, { 0 } };
 
+/**
+ * Call the driver's correct probe function.
+ *
+ * If the driver implements the \c DriverRec::PciProbe entry-point and an
+ * appropriate PCI device (with matching Device section in the xorg.conf file)
+ * is found, it is called.  If \c DriverRec::PciProbe or no devices can be
+ * successfully probed with it (e.g., only non-PCI devices are available),
+ * the driver's \c DriverRec::Probe function is called.
+ *
+ * \param drv   Driver to probe
+ *
+ * \return
+ * If a device can be successfully probed by the driver, \c TRUE is
+ * returned.  Otherwise, \c FALSE is returned.
+ */
+Bool
+xf86CallDriverProbe( DriverPtr drv, Bool detect_only )
+{
+    Bool     foundScreen = FALSE;
+
+    if (drv->PciProbe != NULL) {
+        if (xf86DoConfigure && xf86DoConfigurePass1) {
+            assert(detect_only);
+            foundScreen = xf86PciAddMatchingDev(drv);
+        }
+        else {
+            assert(! detect_only);
+            foundScreen = xf86PciProbeDev(drv);
+        }
+    }
+
+    if (!foundScreen && (drv->Probe != NULL)) {
+        xf86Msg( X_WARNING, "Falling back to old probe method for %s\n",
+                             drv->driverName);
+        foundScreen = (*drv->Probe)(drv, (detect_only) ? PROBE_DETECT
+                                    : PROBE_DEFAULT);
+    }
+
+    return foundScreen;
+}
+
+/**
+ * @return TRUE if all buses are configured and set up correctly and FALSE
+ * otherwise.
+ */
+Bool
+xf86BusConfig(void)
+{
+    screenLayoutPtr layout;
+    int i, j;
+
+    /* Enable full I/O access */
+    if (xorgHWAccess)
+        xorgHWAccess = xf86EnableIO();
+
+    /* Locate bus slot that had register IO enabled at server startup */
+    if (xorgHWAccess)
+        xf86FindPrimaryDevice();
+
+    /*
+     * Now call each of the Probe functions.  Each successful probe will
+     * result in an extra entry added to the xf86Screens[] list for each
+     * instance of the hardware found.
+     */
+    for (i = 0; i < xf86NumDrivers; i++) {
+        xorgHWFlags flags;
+        if (!xorgHWAccess) {
+            if (!xf86DriverList[i]->driverFunc
+            || !xf86DriverList[i]->driverFunc(NULL,
+                             GET_REQUIRED_HW_INTERFACES,
+                              &flags)
+            || NEED_IO_ENABLED(flags))
+            continue;
+        }
+
+        xf86CallDriverProbe(xf86DriverList[i], FALSE);
+    }
+
+    /* If nothing was detected, return now */
+    if (xf86NumScreens == 0) {
+        xf86Msg(X_ERROR, "No devices detected.\n");
+        return FALSE;
+    }
+
+    xf86VGAarbiterInit();
+
+    /*
+     * Match up the screens found by the probes against those specified
+     * in the config file.  Remove the ones that won't be used.  Sort
+     * them in the order specified.
+     *
+     * What is the best way to do this?
+     *
+     * For now, go through the screens allocated by the probes, and
+     * look for screen config entry which refers to the same device
+     * section as picked out by the probe.
+     *
+     */
+    for (i = 0; i < xf86NumScreens; i++) {
+        for (layout = xf86ConfigLayout.screens; layout->screen != NULL;
+             layout++) {
+            Bool found = FALSE;
+            for (j = 0; j < xf86Screens[i]->numEntities; j++) {
+
+                GDevPtr dev = xf86GetDevFromEntity(
+                                xf86Screens[i]->entityList[j],
+                                xf86Screens[i]->entityInstanceList[j]);
+                if (dev == layout->screen->device) {
+                    /* A match has been found */
+                    xf86Screens[i]->confScreen = layout->screen;
+                    found = TRUE;
+                    break;
+                }
+            }
+            if (found) break;
+        }
+        if (layout->screen == NULL) {
+            /* No match found */
+            xf86Msg(X_ERROR,
+            "Screen %d deleted because of no matching config section.\n", i);
+            xf86DeleteScreen(i--, 0);
+        }
+    }
+
+    /* If no screens left, return now.  */
+    if (xf86NumScreens == 0) {
+        xf86Msg(X_ERROR,
+        "Device(s) detected, but none match those in the config file.\n");
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
 /*
  * Call the bus probes relevant to the architecture.
  *
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index 15b6bdc..db88f70 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -76,6 +76,7 @@
 #include "xf86InPriv.h"
 #include "picturestr.h"
 
+#include "xf86Bus.h"
 #include "xf86VGAarbiter.h"
 #include "globals.h"
 
@@ -83,16 +84,8 @@
 #include <X11/extensions/dpmsconst.h>
 #include "dpmsproc.h"
 #endif
-
-#include <pciaccess.h>
-#include "Pci.h"
-#include "xf86Bus.h"
-
 #include <hotplug.h>
 
-/* forward declarations */
-static Bool probe_devices_from_device_sections(DriverPtr drvp);
-static Bool add_matching_devices_to_configure_list(DriverPtr drvp);
 
 #ifdef XF86PM
 void (*xf86OSPMClose)(void) = NULL;
@@ -335,201 +328,6 @@ InstallSignalHandlers(void)
     }
 }
 
-
-#define END_OF_MATCHES(m) \
-    (((m).vendor_id == 0) && ((m).device_id == 0) && ((m).subvendor_id == 0))
-
-Bool
-probe_devices_from_device_sections(DriverPtr drvp)
-{
-    int i, j;
-    struct pci_device * pPci;
-    Bool foundScreen = FALSE;
-    const struct pci_id_match * const devices = drvp->supported_devices;
-    GDevPtr *devList;
-    const unsigned numDevs = xf86MatchDevice(drvp->driverName, & devList);
-
-
-    for ( i = 0 ; i < numDevs ; i++ ) {
-	struct pci_device_iterator *iter;
-	unsigned device_id;
-
-
-	/* Find the pciVideoRec associated with this device section.
-	 */
-	iter = pci_id_match_iterator_create(NULL);
-	while ((pPci = pci_device_next(iter)) != NULL) {
-	    if (devList[i]->busID && *devList[i]->busID) {
-		if (xf86ComparePciBusString(devList[i]->busID,
-					    ((pPci->domain << 8)
-					     | pPci->bus),
-					    pPci->dev,
-					    pPci->func)) {
-		    break;
-		}
-	    }
-	    else if (xf86IsPrimaryPci(pPci)) {
-		break;
-	    }
-	}
-
-	pci_iterator_destroy(iter);
-
-	if (pPci == NULL) {
-	    continue;
-	}
-
-	device_id = (devList[i]->chipID > 0)
-	  ? devList[i]->chipID : pPci->device_id;
-
-
-	/* Once the pciVideoRec is found, determine if the device is supported
-	 * by the driver.  If it is, probe it!
-	 */
-	for ( j = 0 ; ! END_OF_MATCHES( devices[j] ) ; j++ ) {
-	    if ( PCI_ID_COMPARE( devices[j].vendor_id, pPci->vendor_id )
-		 && PCI_ID_COMPARE( devices[j].device_id, device_id )
-		 && ((devices[j].device_class_mask & pPci->device_class)
-		      == devices[j].device_class) ) {
-		int  entry;
-
-		/* Allow the same entity to be used more than once for
-		 * devices with multiple screens per entity.  This assumes
-		 * implicitly that there will be a screen == 0 instance.
-		 *
-		 * FIXME Need to make sure that two different drivers don't
-		 * FIXME claim the same screen > 0 instance.
-		 */
-		if ( (devList[i]->screen == 0) && !xf86CheckPciSlot( pPci ) )
-		  continue;
-
-		DebugF("%s: card at %d:%d:%d is claimed by a Device section\n",
-		       drvp->driverName, pPci->bus, pPci->dev, pPci->func);
-
-		/* Allocate an entry in the lists to be returned */
-		entry = xf86ClaimPciSlot(pPci, drvp, device_id,
-					  devList[i], devList[i]->active);
-
-		if ((entry == -1) && (devList[i]->screen > 0)) {
-		    unsigned k;
-
-		    for ( k = 0; k < xf86NumEntities; k++ ) {
-			EntityPtr pEnt = xf86Entities[k];
-			if (pEnt->bus.type != BUS_PCI)
-			  continue;
-
-			if (pEnt->bus.id.pci == pPci) {
-			    entry = k;
-			    xf86AddDevToEntity(k, devList[i]);
-			    break;
-			}
-		    }
-		}
-
-		if (entry != -1) {
-		    if ((*drvp->PciProbe)(drvp, entry, pPci,
-					  devices[j].match_data)) {
-			foundScreen = TRUE;
-		    } else
-			xf86UnclaimPciSlot(pPci);
-		}
-
-		break;
-	    }
-	}
-    }
-    free(devList);
-
-    return foundScreen;
-}
-
-
-Bool
-add_matching_devices_to_configure_list(DriverPtr drvp)
-{
-    const struct pci_id_match * const devices = drvp->supported_devices;
-    int j;
-    struct pci_device *pPci;
-    struct pci_device_iterator *iter;
-    int numFound = 0;
-
-
-    iter = pci_id_match_iterator_create(NULL);
-    while ((pPci = pci_device_next(iter)) != NULL) {
-	/* Determine if this device is supported by the driver.  If it is,
-	 * add it to the list of devices to configure.
-	 */
-	for (j = 0 ; ! END_OF_MATCHES(devices[j]) ; j++) {
-	    if ( PCI_ID_COMPARE( devices[j].vendor_id, pPci->vendor_id )
-		 && PCI_ID_COMPARE( devices[j].device_id, pPci->device_id )
-		 && ((devices[j].device_class_mask & pPci->device_class)
-		     == devices[j].device_class) ) {
-		if (xf86CheckPciSlot(pPci)) {
-		    GDevPtr pGDev = xf86AddBusDeviceToConfigure(
-					drvp->driverName, BUS_PCI, pPci, -1);
-		    if (pGDev != NULL) {
-			/* After configure pass 1, chipID and chipRev are
-			 * treated as over-rides, so clobber them here.
-			 */
-			pGDev->chipID = -1;
-			pGDev->chipRev = -1;
-		    }
-
-		    numFound++;
-		}
-
-		break;
-	    }
-	}
-    }
-
-    pci_iterator_destroy(iter);
-
-
-    return (numFound != 0);
-}
-
-/**
- * Call the driver's correct probe function.
- *
- * If the driver implements the \c DriverRec::PciProbe entry-point and an
- * appropriate PCI device (with matching Device section in the xorg.conf file)
- * is found, it is called.  If \c DriverRec::PciProbe or no devices can be
- * successfully probed with it (e.g., only non-PCI devices are available),
- * the driver's \c DriverRec::Probe function is called.
- *
- * \param drv   Driver to probe
- *
- * \return
- * If a device can be successfully probed by the driver, \c TRUE is
- * returned.  Otherwise, \c FALSE is returned.
- */
-Bool
-xf86CallDriverProbe( DriverPtr drv, Bool detect_only )
-{
-    Bool     foundScreen = FALSE;
-
-    if ( drv->PciProbe != NULL ) {
-	if ( xf86DoConfigure && xf86DoConfigurePass1 ) {
-	    assert( detect_only );
-	    foundScreen = add_matching_devices_to_configure_list( drv );
-	}
-	else {
-	    assert( ! detect_only );
-	    foundScreen = probe_devices_from_device_sections( drv );
-	}
-    }
-
-    if ( ! foundScreen && (drv->Probe != NULL) ) {
-	xf86Msg( X_WARNING, "Falling back to old probe method for %s\n",
-		 drv->driverName );
-	foundScreen = (*drv->Probe)( drv, (detect_only) ? PROBE_DETECT
-				     : PROBE_DEFAULT );
-    }
-
-    return foundScreen;
-}
-
 /*
  * InitOutput --
  *	Initialize screenInfo for all actually accessible framebuffers.
@@ -542,7 +340,6 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv)
   int                    i, j, k, scr_index;
   char                   **modulelist;
   pointer                *optionlist;
-  screenLayoutPtr	 layout;
   Pix24Flags		 screenpix24, pix24;
   MessageType		 pix24From = X_DEFAULT;
   Bool			 pix24Fail = FALSE;
@@ -693,97 +490,8 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv)
     else
 	xf86Info.dontVTSwitch = TRUE;
 
-    /* Enable full I/O access */
-    if (xorgHWAccess)
-	xorgHWAccess = xf86EnableIO();
-
-    /*
-     * Locate bus slot that had register IO enabled at server startup
-     */
-    if (xorgHWAccess)
-        xf86FindPrimaryDevice();
-    /*
-     * Now call each of the Probe functions.  Each successful probe will
-     * result in an extra entry added to the xf86Screens[] list for each
-     * instance of the hardware found.
-     */
-
-    for (i = 0; i < xf86NumDrivers; i++) {
-	xorgHWFlags flags;
-	if (!xorgHWAccess) {
-	    if (!xf86DriverList[i]->driverFunc
-		|| !xf86DriverList[i]->driverFunc(NULL,
-						 GET_REQUIRED_HW_INTERFACES,
-						  &flags)
-		|| NEED_IO_ENABLED(flags))
-		continue;
-	}
-
-	xf86CallDriverProbe( xf86DriverList[i], FALSE );
-    }
-
-    /*
-     * If nothing was detected, return now.
-     */
-
-    if (xf86NumScreens == 0) {
-      xf86Msg(X_ERROR, "No devices detected.\n");
-      return;
-    }
-
-    xf86VGAarbiterInit();
-
-    /*
-     * Match up the screens found by the probes against those specified
-     * in the config file.  Remove the ones that won't be used.  Sort
-     * them in the order specified.
-     */
-
-    /*
-     * What is the best way to do this?
-     *
-     * For now, go through the screens allocated by the probes, and
-     * look for screen config entry which refers to the same device
-     * section as picked out by the probe.
-     *
-     */
-
-    for (i = 0; i < xf86NumScreens; i++) {
-      for (layout = xf86ConfigLayout.screens; layout->screen != NULL;
-	   layout++) {
-	  Bool found = FALSE;
-	  for (j = 0; j < xf86Screens[i]->numEntities; j++) {
-
-	      GDevPtr dev =
-		xf86GetDevFromEntity(xf86Screens[i]->entityList[j],
-				     xf86Screens[i]->entityInstanceList[j]);
-
-	      if (dev == layout->screen->device) {
-		  /* A match has been found */
-		  xf86Screens[i]->confScreen = layout->screen;
-		  found = TRUE;
-		  break;
-	      }
-	  }
-	  if (found) break;
-      }
-      if (layout->screen == NULL) {
-	/* No match found */
-	xf86Msg(X_ERROR,
-	    "Screen %d deleted because of no matching config section.\n", i);
-        xf86DeleteScreen(i--, 0);
-      }
-    }
-
-    /*
-     * If no screens left, return now.
-     */
-
-    if (xf86NumScreens == 0) {
-      xf86Msg(X_ERROR,
-	      "Device(s) detected, but none match those in the config file.\n");
-      return;
-    }
+    if (xf86BusConfig() == FALSE)
+        return;
 
     xf86PostProbe();
 
@@ -1632,20 +1340,12 @@ ddxProcessArgument(int argc, char **argv, int i)
   }
   if (!strcmp(argv[i], "-isolateDevice"))
   {
-    int bus, device, func;
     CHECK_FOR_REQUIRED_ARGUMENT();
     if (strncmp(argv[++i], "PCI:", 4)) {
        FatalError("Bus types other than PCI not yet isolable\n");
     }
-    if (sscanf(argv[i], "PCI:%d:%d:%d", &bus, &device, &func) == 3) {
-       xf86IsolateDevice.domain = PCI_DOM_FROM_BUS(bus);
-       xf86IsolateDevice.bus = PCI_BUS_NO_DOMAIN(bus);
-       xf86IsolateDevice.dev = device;
-       xf86IsolateDevice.func = func;
-       return 2;
-    } else {
-       FatalError("Invalid isolated device specification\n");
-    }
+    xf86PciIsolateDevice(argv[i]);
+    return 2;
   }
   /* Notice cmdline xkbdir, but pass to dix as well */
   if (!strcmp(argv[i], "-xkbdir"))
diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h
index a8169e9..d2073ae 100644
--- a/hw/xfree86/common/xf86Priv.h
+++ b/hw/xfree86/common/xf86Priv.h
@@ -111,6 +111,7 @@ extern _X_EXPORT  RootWinPropPtr *xf86RegisteredPropertiesTable;
 
 /* xf86Bus.c */
 
+extern _X_EXPORT Bool xf86BusConfig(void);
 extern _X_EXPORT void xf86BusProbe(void);
 extern _X_EXPORT void xf86AccessEnter(void);
 extern _X_EXPORT void xf86AccessLeave(void);
diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c
index 3b30d72..4656f1a 100644
--- a/hw/xfree86/common/xf86pciBus.c
+++ b/hw/xfree86/common/xf86pciBus.c
@@ -420,4 +420,164 @@ xf86CheckPciSlot(const struct pci_device *d)
     return TRUE;
 }
 
+#define END_OF_MATCHES(m) \
+    (((m).vendor_id == 0) && ((m).device_id == 0) && ((m).subvendor_id == 0))
 
+Bool
+xf86PciAddMatchingDev(DriverPtr drvp)
+{
+    const struct pci_id_match * const devices = drvp->supported_devices;
+    int j;
+    struct pci_device *pPci;
+    struct pci_device_iterator *iter;
+    int numFound = 0;
+
+
+    iter = pci_id_match_iterator_create(NULL);
+    while ((pPci = pci_device_next(iter)) != NULL) {
+    /* Determine if this device is supported by the driver.  If it is,
+     * add it to the list of devices to configure.
+     */
+    for (j = 0 ; ! END_OF_MATCHES(devices[j]) ; j++) {
+        if ( PCI_ID_COMPARE( devices[j].vendor_id, pPci->vendor_id )
+         && PCI_ID_COMPARE( devices[j].device_id, pPci->device_id )
+         && ((devices[j].device_class_mask & pPci->device_class)
+             == devices[j].device_class) ) {
+        if (xf86CheckPciSlot(pPci)) {
+            GDevPtr pGDev = xf86AddBusDeviceToConfigure(
+                    drvp->driverName, BUS_PCI, pPci, -1);
+            if (pGDev != NULL) {
+            /* After configure pass 1, chipID and chipRev are
+             * treated as over-rides, so clobber them here.
+             */
+            pGDev->chipID = -1;
+            pGDev->chipRev = -1;
+            }
+
+            numFound++;
+        }
+
+        break;
+        }
+    }
+    }
+
+    pci_iterator_destroy(iter);
+
+    return (numFound != 0);
+}
+
+Bool
+xf86PciProbeDev(DriverPtr drvp)
+{
+    int i, j;
+    struct pci_device * pPci;
+    Bool foundScreen = FALSE;
+    const struct pci_id_match * const devices = drvp->supported_devices;
+    GDevPtr *devList;
+    const unsigned numDevs = xf86MatchDevice(drvp->driverName, & devList);
+
+    for ( i = 0 ; i < numDevs ; i++ ) {
+       struct pci_device_iterator *iter;
+       unsigned device_id;
+
+
+       /* Find the pciVideoRec associated with this device section.
+        */
+       iter = pci_id_match_iterator_create(NULL);
+       while ((pPci = pci_device_next(iter)) != NULL) {
+           if (devList[i]->busID && *devList[i]->busID) {
+               if (xf86ComparePciBusString(devList[i]->busID,
+                                           ((pPci->domain << 8)
+                                            | pPci->bus),
+                                           pPci->dev,
+                                           pPci->func)) {
+                   break;
+               }
+           }
+           else if (xf86IsPrimaryPci(pPci)) {
+               break;
+           }
+       }
+
+       pci_iterator_destroy(iter);
+
+       if (pPci == NULL) {
+           continue;
+       }
+       device_id = (devList[i]->chipID > 0)
+         ? devList[i]->chipID : pPci->device_id;
+
+
+       /* Once the pciVideoRec is found, determine if the device is supported
+        * by the driver.  If it is, probe it!
+        */
+       for ( j = 0 ; ! END_OF_MATCHES( devices[j] ) ; j++ ) {
+           if ( PCI_ID_COMPARE( devices[j].vendor_id, pPci->vendor_id )
+                && PCI_ID_COMPARE( devices[j].device_id, device_id )
+                && ((devices[j].device_class_mask & pPci->device_class)
+                     == devices[j].device_class) ) {
+               int  entry;
+
+               /* Allow the same entity to be used more than once for
+                * devices with multiple screens per entity.  This assumes
+                * implicitly that there will be a screen == 0 instance.
+                *
+                * FIXME Need to make sure that two different drivers don't
+                * FIXME claim the same screen > 0 instance.
+                */
+               if ((devList[i]->screen == 0) && !xf86CheckPciSlot(pPci))
+                   continue;
+
+               DebugF("%s: card at %d:%d:%d is claimed by a Device section\n",
+                      drvp->driverName, pPci->bus, pPci->dev, pPci->func);
+
+               /* Allocate an entry in the lists to be returned */
+               entry = xf86ClaimPciSlot(pPci, drvp, device_id,
+                                         devList[i], devList[i]->active);
+
+               if ((entry == -1) && (devList[i]->screen > 0)) {
+                   unsigned k;
+
+                   for (k = 0; k < xf86NumEntities; k++ ) {
+                       EntityPtr pEnt = xf86Entities[k];
+                       if (pEnt->bus.type != BUS_PCI)
+                           continue;
+                       if (pEnt->bus.id.pci == pPci) {
+                           entry = k;
+                           xf86AddDevToEntity(k, devList[i]);
+                           break;
+                       }
+                   }
+               }
+
+               if (entry != -1) {
+                   if ((*drvp->PciProbe)(drvp, entry, pPci,
+                                         devices[j].match_data)) {
+                       foundScreen = TRUE;
+                   } else
+                       xf86UnclaimPciSlot(pPci);
+               }
+
+               break;
+           }
+       }
+    }
+    free(devList);
+
+    return foundScreen;
+}
+
+void
+xf86PciIsolateDevice(char *argument)
+{
+    int bus, device, func;
+
+    if (sscanf(argument, "PCI:%d:%d:%d", &bus, &device, &func) == 3) {
+        xf86IsolateDevice.domain = PCI_DOM_FROM_BUS(bus);
+        xf86IsolateDevice.bus = PCI_BUS_NO_DOMAIN(bus);
+        xf86IsolateDevice.dev = device;
+        xf86IsolateDevice.func = func;
+    } else
+        FatalError("Invalid isolated device specification\n");
+}
diff --git a/hw/xfree86/common/xf86pciBus.h b/hw/xfree86/common/xf86pciBus.h
index 3125e0d..69c005a 100644
--- a/hw/xfree86/common/xf86pciBus.h
+++ b/hw/xfree86/common/xf86pciBus.h
@@ -34,5 +34,8 @@
 #define _XF86_PCI_BUS_H
 
 void xf86PciProbe(void);
+Bool xf86PciAddMatchingDev(DriverPtr drvp);
+Bool xf86PciProbeDev(DriverPtr drvp);
+void xf86PciIsolateDevice(char *argument);
 
 #endif /* _XF86_PCI_BUS_H */
commit 0dd299864a133d478e4635bd1cd305b67fc3964d
Author: Tiago Vignatti <tiago.vignatti at nokia.com>
Date:   Sun May 2 21:33:26 2010 +0300

    xfree86: remove xf86EnableAccess
    
    It's RAC remnant. This was substituted by xf86VGAarbiter{Lock, Unlock}
    mechanism.
    
    It's an API break, but the few drivers using it were covered already with
    macros to avoid problems.
    
    Signed-off-by: Tiago Vignatti <tiago.vignatti at nokia.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/common/xf86.h b/hw/xfree86/common/xf86.h
index d889057..68c3744 100644
--- a/hw/xfree86/common/xf86.h
+++ b/hw/xfree86/common/xf86.h
@@ -104,7 +104,6 @@ extern _X_EXPORT void xf86FormatPciBusNumber(int busnum, char *buffer);
 extern _X_EXPORT int  xf86GetFbInfoForScreen(int scrnIndex);
 extern _X_EXPORT int xf86ClaimFbSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool active);
 extern _X_EXPORT int xf86ClaimNoSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool active);
-extern _X_EXPORT void xf86EnableAccess(ScrnInfoPtr pScrn);
 extern _X_EXPORT Bool xf86IsPrimaryPci(struct pci_device * pPci);
 /* new RAC */
 extern _X_EXPORT Bool xf86DriverHasEntities(DriverPtr drvp);
diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
index 2a0c5c8..153fc74 100644
--- a/hw/xfree86/common/xf86Bus.c
+++ b/hw/xfree86/common/xf86Bus.c
@@ -371,29 +371,6 @@ xf86AccessLeave(void)
 }
 
 /*
- * xf86EnableAccess() -- enable access to controlled resources.
- * To reduce latency when switching access the ScrnInfoRec has
- * a linked list of the EntityAccPtr of all screen entities.
- */
-/*
- * switching access needs to be done in te following oder:
- * disable
- * 1. disable old entity
- * 2. reroute bus
- * 3. enable new entity
- * Otherwise resources needed for access control might be shadowed
- * by other resources!
- */
-
-void
-xf86EnableAccess(ScrnInfoPtr pScrn)
-{
-    DebugF("Enable access %i\n",pScrn->scrnIndex);
-
-    return;
-}
-
-/*
  * xf86EnterServerState() -- set state the server is in.
  */
 
diff --git a/hw/xfree86/common/xf86Configure.c b/hw/xfree86/common/xf86Configure.c
index 87d40e0..f84feec 100644
--- a/hw/xfree86/common/xf86Configure.c
+++ b/hw/xfree86/common/xf86Configure.c
@@ -833,7 +833,6 @@ DoConfigure(void)
 
 	ConfiguredMonitor = NULL;
 
-	xf86EnableAccess(xf86Screens[dev2screen[j]]);
 	if ((*xf86Screens[dev2screen[j]]->PreInit)(xf86Screens[dev2screen[j]], 
 						   PROBE_DETECT) &&
 	    ConfiguredMonitor) {
commit f28515b5f774b83e0481acbcdda2f682738079b9
Author: Tiago Vignatti <tiago.vignatti at nokia.com>
Date:   Sun May 2 21:24:46 2010 +0300

    xfree86: bus: remove SetSIGIOForState and simplify the code
    
    Also removed some dumb debug messages.
    
    Signed-off-by: Tiago Vignatti <tiago.vignatti at nokia.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
index 9bf4514..2a0c5c8 100644
--- a/hw/xfree86/common/xf86Bus.c
+++ b/hw/xfree86/common/xf86Bus.c
@@ -399,12 +399,17 @@ xf86EnableAccess(ScrnInfoPtr pScrn)
 
 typedef enum { TRI_UNSET, TRI_TRUE, TRI_FALSE } TriState;
 
-static void
-SetSIGIOForState(xf86State state)
+void
+xf86EnterServerState(xf86State state)
 {
     static int sigio_state;
     static TriState sigio_blocked = TRI_UNSET;
 
+    /*
+     * This is a good place to block SIGIO during SETUP state. SIGIO should be
+     * blocked in SETUP state otherwise (u)sleep() might get interrupted
+     * early. We take care not to call xf86BlockSIGIO() twice.
+     */
     if ((state == SETUP) && (sigio_blocked != TRI_TRUE)) {
         sigio_state = xf86BlockSIGIO();
 	sigio_blocked = TRI_TRUE;
@@ -414,24 +419,6 @@ SetSIGIOForState(xf86State state)
     }
 }
 
-void
-xf86EnterServerState(xf86State state)
-{
-    /* 
-     * This is a good place to block SIGIO during SETUP state.
-     * SIGIO should be blocked in SETUP state otherwise (u)sleep()
-     * might get interrupted early. 
-     * We take care not to call xf86BlockSIGIO() twice. 
-     */
-    SetSIGIOForState(state);
-    if (state == SETUP)
-	DebugF("Entering SETUP state\n");
-    else
-	DebugF("Entering OPERATING state\n");
-
-    return;
-}
-
 /*
  * xf86PostProbe() -- Allocate all non conflicting resources
  * This function gets called by xf86Init().
@@ -458,13 +445,6 @@ void
 xf86PostScreenInit(void)
 {
     xf86VGAarbiterWrapFunctions();
-
-    if (fbSlotClaimed) {
-	SetSIGIOForState(OPERATING);
-	return;
-    }
-
-    DebugF("PostScreenInit  generation: %i\n",serverGeneration);
     xf86EnterServerState(OPERATING);
 }
 
commit 211ca67e4d8d00b20a74a78304a61d4dbea62706
Author: Tiago Vignatti <tiago.vignatti at nokia.com>
Date:   Sun May 2 21:16:23 2010 +0300

    xfree86: bus: fb drivers might want to use vga arbitration either
    
    Signed-off-by: Tiago Vignatti <tiago.vignatti at nokia.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
index 910c884..9bf4514 100644
--- a/hw/xfree86/common/xf86Bus.c
+++ b/hw/xfree86/common/xf86Bus.c
@@ -457,13 +457,13 @@ xf86PostProbe(void)
 void
 xf86PostScreenInit(void)
 {
+    xf86VGAarbiterWrapFunctions();
+
     if (fbSlotClaimed) {
 	SetSIGIOForState(OPERATING);
 	return;
     }
 
-    xf86VGAarbiterWrapFunctions();
-
     DebugF("PostScreenInit  generation: %i\n",serverGeneration);
     xf86EnterServerState(OPERATING);
 }
commit 2464eb7d56407422e033ab3b94634ba802a119d5
Author: Tiago Vignatti <tiago.vignatti at nokia.com>
Date:   Sun May 2 21:14:53 2010 +0300

    xfree86: bus: simplify entity related hooks
    
    Remove some out dated commentaries either.
    
    Signed-off-by: Tiago Vignatti <tiago.vignatti at nokia.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
index 2296ee8..910c884 100644
--- a/hw/xfree86/common/xf86Bus.c
+++ b/hw/xfree86/common/xf86Bus.c
@@ -108,21 +108,6 @@ StringToBusType(const char* busID, const char **retID)
     return ret;
 }
 
-/*
- * Entity related code.
- */
-
-void
-xf86EntityInit(void)
-{
-    int i;
-    
-    for (i = 0; i < xf86NumEntities; i++)
-	if (xf86Entities[i]->entityInit) {
-	    xf86Entities[i]->entityInit(i,xf86Entities[i]->private);
-	}
-}
-
 int
 xf86AllocateEntity(void)
 {
@@ -135,28 +120,6 @@ xf86AllocateEntity(void)
     return (xf86NumEntities - 1);
 }
 
-static void
-EntityEnter(void)
-{
-    int i;
-    
-    for (i = 0; i < xf86NumEntities; i++)
-	if (xf86Entities[i]->entityEnter) {
-	    xf86Entities[i]->entityEnter(i,xf86Entities[i]->private);
-	}
-}
-
-static void
-EntityLeave(void)
-{
-    int i;
-
-    for (i = 0; i < xf86NumEntities; i++)
-	if (xf86Entities[i]->entityLeave) {
-	    xf86Entities[i]->entityLeave(i,xf86Entities[i]->private);
-	}
-}
-
 Bool
 xf86IsEntityPrimary(int entityIndex)
 {
@@ -388,27 +351,23 @@ xf86GetDevFromEntity(int entityIndex, int instance)
 void
 xf86AccessEnter(void)
 {
-    /*
-     * on enter we simply disable routing of special resources
-     * to any bus and let the RAC code to "open" the right bridges.
-     */
-    EntityEnter();
+    int i;
+
+    for (i = 0; i < xf86NumEntities; i++)
+        if (xf86Entities[i]->entityEnter)
+		xf86Entities[i]->entityEnter(i,xf86Entities[i]->private);
+
     xf86EnterServerState(SETUP);
 }
 
-/*
- * xf86AccessLeave() -- prepares access for and calls the
- * entityLeave() functions.
- * xf86AccessLeaveState() --- gets called to restore the
- * access to the VGA IO resources when switching VT or on
- * server exit.
- * This was split to call xf86AccessLeaveState() from
- * ddxGiveUp().
- */
 void
 xf86AccessLeave(void)
 {
-    EntityLeave();
+    int i;
+
+    for (i = 0; i < xf86NumEntities; i++)
+        if (xf86Entities[i]->entityLeave)
+		xf86Entities[i]->entityLeave(i,xf86Entities[i]->private);
 }
 
 /*
@@ -480,6 +439,8 @@ xf86EnterServerState(xf86State state)
 void
 xf86PostProbe(void)
 {
+    int i;
+
     if (fbSlotClaimed && (pciSlotClaimed
 #if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
 	    || sbusSlotClaimed
@@ -487,6 +448,10 @@ xf86PostProbe(void)
 	    ))
 	    FatalError("Cannot run in framebuffer mode. Please specify busIDs "
 		       "       for all framebuffer devices\n");
+
+    for (i = 0; i < xf86NumEntities; i++)
+        if (xf86Entities[i]->entityInit)
+	    xf86Entities[i]->entityInit(i,xf86Entities[i]->private);
 }
 
 void
diff --git a/hw/xfree86/common/xf86Configure.c b/hw/xfree86/common/xf86Configure.c
index ef61e46..87d40e0 100644
--- a/hw/xfree86/common/xf86Configure.c
+++ b/hw/xfree86/common/xf86Configure.c
@@ -818,7 +818,6 @@ DoConfigure(void)
     }
 
     xf86PostProbe();
-    xf86EntityInit();
 
     for (j = 0; j < xf86NumScreens; j++) {
 	xf86Screens[j]->scrnIndex = j;
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index 80877e7..15b6bdc 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -786,7 +786,6 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv)
     }
 
     xf86PostProbe();
-    xf86EntityInit();
 
     /*
      * Sort the drivers to match the requested ording.  Using a slow
diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h
index 6faf4d5..a8169e9 100644
--- a/hw/xfree86/common/xf86Priv.h
+++ b/hw/xfree86/common/xf86Priv.h
@@ -114,7 +114,6 @@ extern _X_EXPORT  RootWinPropPtr *xf86RegisteredPropertiesTable;
 extern _X_EXPORT void xf86BusProbe(void);
 extern _X_EXPORT void xf86AccessEnter(void);
 extern _X_EXPORT void xf86AccessLeave(void);
-extern _X_EXPORT void xf86EntityInit(void);
 
 extern _X_EXPORT void xf86FindPrimaryDevice(void);
 /* new RAC */
commit 971768e6884f20981652da09a1617c51a760fb86
Author: Tiago Vignatti <tiago.vignatti at nokia.com>
Date:   Fri May 7 15:25:48 2010 +0300

    xfree86: bus: enable declaration of sparc function as its code usage
    
    The code in xf86sbusBus.c seems too OS-specific to be usable on OpenBSD.
    
    Signed-off-by: Tiago Vignatti <tiago.vignatti at nokia.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/common/xf86.h b/hw/xfree86/common/xf86.h
index 4544a4f..d889057 100644
--- a/hw/xfree86/common/xf86.h
+++ b/hw/xfree86/common/xf86.h
@@ -64,7 +64,7 @@ extern _X_EXPORT ScrnInfoPtr *xf86Screens;	/* List of pointers to ScrnInfoRecs *
 extern _X_EXPORT const unsigned char byte_reversed[256];
 extern _X_EXPORT Bool pciSlotClaimed;
 extern _X_EXPORT Bool fbSlotClaimed;
-#if defined(__sparc__) || defined(__sparc)
+#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
 extern _X_EXPORT Bool sbusSlotClaimed;
 #endif
 extern _X_EXPORT confDRIRec xf86ConfigDRI;
commit a70ec0d136bbb9efb6f4e683d7ebcea00375083b
Author: Tiago Vignatti <tiago.vignatti at nokia.com>
Date:   Sun May 2 20:48:01 2010 +0300

    xfree86: bus: rework xf86PostProbe logic and remove useless log info
    
    Signed-off-by: Tiago Vignatti <tiago.vignatti at nokia.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
index a4df1f2..2296ee8 100644
--- a/hw/xfree86/common/xf86Bus.c
+++ b/hw/xfree86/common/xf86Bus.c
@@ -480,21 +480,13 @@ xf86EnterServerState(xf86State state)
 void
 xf86PostProbe(void)
 {
-    if (fbSlotClaimed) {
-        if (pciSlotClaimed
+    if (fbSlotClaimed && (pciSlotClaimed
 #if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
 	    || sbusSlotClaimed
 #endif
-	    ) { 
+	    ))
 	    FatalError("Cannot run in framebuffer mode. Please specify busIDs "
 		       "       for all framebuffer devices\n");
-	    return;
-	} else  {
-	    xf86Msg(X_INFO,"Running in FRAMEBUFFER Mode\n");
-
-	    return;
-	}
-    }
 }
 
 void
commit 2f7d630a1ee446711288af69711d57ea3054b594
Author: Tiago Vignatti <tiago.vignatti at nokia.com>
Date:   Sun May 2 20:29:11 2010 +0300

    xfree86: bus: reuse already assigned variable when fb driver claimed
    
    Signed-off-by: Tiago Vignatti <tiago.vignatti at nokia.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
index 4013a67..a4df1f2 100644
--- a/hw/xfree86/common/xf86Bus.c
+++ b/hw/xfree86/common/xf86Bus.c
@@ -58,8 +58,6 @@ static int xf86EntityPrivateCount = 0;
 
 BusRec primaryBus = { BUS_NONE, { 0 } };
 
-static Bool doFramebufferMode = FALSE;
-
 /*
  * Call the bus probes relevant to the architecture.
  *
@@ -493,7 +491,6 @@ xf86PostProbe(void)
 	    return;
 	} else  {
 	    xf86Msg(X_INFO,"Running in FRAMEBUFFER Mode\n");
-	    doFramebufferMode = TRUE;
 
 	    return;
 	}
@@ -503,7 +500,7 @@ xf86PostProbe(void)
 void
 xf86PostScreenInit(void)
 {
-    if (doFramebufferMode) {
+    if (fbSlotClaimed) {
 	SetSIGIOForState(OPERATING);
 	return;
     }
commit 964f29bb80c1bb05508a27969c3ac34cbf072ee9
Author: Tiago Vignatti <tiago.vignatti at nokia.com>
Date:   Sun May 2 20:14:40 2010 +0300

    xfree86: bus: fix Enter/Leave accesses behaviour
    
    Okay, seems we're not using extensively such hooks in fact. But fix the
    expected behaviour at least.
    
    Signed-off-by: Tiago Vignatti <tiago.vignatti at nokia.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
index 7d4853a..4013a67 100644
--- a/hw/xfree86/common/xf86Bus.c
+++ b/hw/xfree86/common/xf86Bus.c
@@ -390,8 +390,6 @@ xf86GetDevFromEntity(int entityIndex, int instance)
 void
 xf86AccessEnter(void)
 {
-    return;
-
     /*
      * on enter we simply disable routing of special resources
      * to any bus and let the RAC code to "open" the right bridges.
@@ -412,7 +410,6 @@ xf86AccessEnter(void)
 void
 xf86AccessLeave(void)
 {
-    return;
     EntityLeave();
 }
 
commit b37462b4da7c389ec7bbcfd800e5f88bded79330
Author: Tiago Vignatti <tiago.vignatti at nokia.com>
Date:   Sun May 2 19:53:37 2010 +0300

    xfree86: remove unused xf86AccessInit()
    
    The function was only initializing the boolean xf86ResAccessEnter, which
    couldn't get any other value in the life of the server.
    
    The only possible, though suspicious, code was in xf86AccessLeave(), which
    could be triggered if AbortDDX is called before xf86AccessInit(). Even so,
    such change is safety because no driver would have configured any entity leave
    procedure at this point.
    
    Signed-off-by: Tiago Vignatti <tiago.vignatti at nokia.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
index 39e531a..7d4853a 100644
--- a/hw/xfree86/common/xf86Bus.c
+++ b/hw/xfree86/common/xf86Bus.c
@@ -58,8 +58,6 @@ static int xf86EntityPrivateCount = 0;
 
 BusRec primaryBus = { BUS_NONE, { 0 } };
 
-static Bool xf86ResAccessEnter = FALSE;
-
 static Bool doFramebufferMode = FALSE;
 
 /*
@@ -386,24 +384,13 @@ xf86GetDevFromEntity(int entityIndex, int instance)
 }
 
 /*
- * xf86AccessInit() - set up everything needed for access control
- * called only once on first server generation.
- */
-void
-xf86AccessInit(void)
-{
-    xf86ResAccessEnter = TRUE;
-}
-
-/*
  * xf86AccessEnter() -- gets called to save the text mode VGA IO 
  * resources when reentering the server after a VT switch.
  */
 void
 xf86AccessEnter(void)
 {
-    if (xf86ResAccessEnter) 
-	return;
+    return;
 
     /*
      * on enter we simply disable routing of special resources
@@ -411,7 +398,6 @@ xf86AccessEnter(void)
      */
     EntityEnter();
     xf86EnterServerState(SETUP);
-    xf86ResAccessEnter = TRUE;
 }
 
 /*
@@ -426,8 +412,7 @@ xf86AccessEnter(void)
 void
 xf86AccessLeave(void)
 {
-    if (!xf86ResAccessEnter)
-	return;
+    return;
     EntityLeave();
 }
 
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index 39d229b..80877e7 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -700,10 +700,8 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv)
     /*
      * Locate bus slot that had register IO enabled at server startup
      */
-    if (xorgHWAccess) {
-        xf86AccessInit();
+    if (xorgHWAccess)
         xf86FindPrimaryDevice();
-    }
     /*
      * Now call each of the Probe functions.  Each successful probe will
      * result in an extra entry added to the xf86Screens[] list for each
diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h
index 0612c9c..6faf4d5 100644
--- a/hw/xfree86/common/xf86Priv.h
+++ b/hw/xfree86/common/xf86Priv.h
@@ -112,7 +112,6 @@ extern _X_EXPORT  RootWinPropPtr *xf86RegisteredPropertiesTable;
 /* xf86Bus.c */
 
 extern _X_EXPORT void xf86BusProbe(void);
-extern _X_EXPORT void xf86AccessInit(void);
 extern _X_EXPORT void xf86AccessEnter(void);
 extern _X_EXPORT void xf86AccessLeave(void);
 extern _X_EXPORT void xf86EntityInit(void);
commit d88ba7721d2d3b58cdc664fd4c23a3c5e2a5f909
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue May 18 11:12:49 2010 +1000

    xfree86: Add option parsing for percent options.
    
    In some cases, an option of "50%" would be preferable over fixed value
    configuration - especially if the actual values are autoprobed.
    Add a new set of functions to parse percent values from configurations.
    
    The percent value parsing differs slightly - if the option is not to marked
    as used (e.g. xf86CheckPercentOption()), no warning is emitted to the log
    file if the value is not a percent value. This allows double-options (either
    as % or as absolute number) without warnings.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Dan Nicholson <dbn.lists at gmail.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/common/xf86Configure.c b/hw/xfree86/common/xf86Configure.c
index ef61e46..c590bda 100644
--- a/hw/xfree86/common/xf86Configure.c
+++ b/hw/xfree86/common/xf86Configure.c
@@ -339,6 +339,8 @@ optionTypeToSting(OptionValueType type)
         return "[<bool>]";
     case OPTV_FREQ:
         return "<freq>";
+    case OPTV_PERCENT:
+        return "<percent>";
     default:
         return "";
     }
@@ -384,7 +386,8 @@ configureDeviceSection (int screennum)
 	    "        ### Available Driver options are:-\n"
 	    "        ### Values: <i>: integer, <f>: float, "
 			"<bool>: \"True\"/\"False\",\n"
-	    "        ### <string>: \"String\", <freq>: \"<f> Hz/kHz/MHz\"\n"
+	    "        ### <string>: \"String\", <freq>: \"<f> Hz/kHz/MHz\",\n"
+	    "        ### <percent>: \"<f>%\"\n"
 	    "        ### [arg]: arg optional\n";
 	ptr->dev_comment = xstrdup(descrip);
 	if (ptr->dev_comment) {
diff --git a/hw/xfree86/common/xf86Opt.h b/hw/xfree86/common/xf86Opt.h
index ce3d767..d75d3bf 100644
--- a/hw/xfree86/common/xf86Opt.h
+++ b/hw/xfree86/common/xf86Opt.h
@@ -51,6 +51,7 @@ typedef enum {
     OPTV_ANYSTR,                /* Any string, including an empty one */
     OPTV_REAL,
     OPTV_BOOLEAN,
+    OPTV_PERCENT,
     OPTV_FREQ
 } OptionValueType;
 
@@ -72,10 +73,12 @@ extern _X_EXPORT int xf86SetIntOption(pointer optlist, const char *name, int def
 extern _X_EXPORT double xf86SetRealOption(pointer optlist, const char *name, double deflt);
 extern _X_EXPORT char *xf86SetStrOption(pointer optlist, const char *name, char *deflt);
 extern _X_EXPORT int xf86SetBoolOption(pointer list, const char *name, int deflt );
+extern _X_EXPORT double xf86SetPercentOption(pointer list, const char *name, double deflt );
 extern _X_EXPORT int xf86CheckIntOption(pointer optlist, const char *name, int deflt);
 extern _X_EXPORT double xf86CheckRealOption(pointer optlist, const char *name, double deflt);
 extern _X_EXPORT char *xf86CheckStrOption(pointer optlist, const char *name, char *deflt);
 extern _X_EXPORT int xf86CheckBoolOption(pointer list, const char *name, int deflt );
+extern _X_EXPORT double xf86CheckPercentOption(pointer list, const char *name, double deflt );
 extern _X_EXPORT pointer xf86AddNewOption(pointer head, const char *name, const char *val );
 extern _X_EXPORT pointer xf86NewOption(char *name, char *value );
 extern _X_EXPORT pointer xf86NextOption(pointer list );
@@ -109,5 +112,6 @@ extern _X_EXPORT char *xf86NormalizeName(const char *s);
 extern _X_EXPORT pointer xf86ReplaceIntOption(pointer optlist,  const char *name, const int val);
 extern _X_EXPORT pointer xf86ReplaceRealOption(pointer optlist,  const char *name, const double val);
 extern _X_EXPORT pointer xf86ReplaceBoolOption(pointer optlist, const char *name, const Bool val);
+extern _X_EXPORT pointer xf86ReplacePercentOption(pointer optlist, const char *name, const double val);
 extern _X_EXPORT pointer xf86ReplaceStrOption(pointer optlist,  const char *name, const char* val);
 #endif
diff --git a/hw/xfree86/common/xf86Option.c b/hw/xfree86/common/xf86Option.c
index 699204c..8be893c 100644
--- a/hw/xfree86/common/xf86Option.c
+++ b/hw/xfree86/common/xf86Option.c
@@ -223,6 +223,18 @@ LookupBoolOption(pointer optlist, const char *name, int deflt, Bool markUsed)
     return deflt;
 }
 
+static int
+LookupPercentOption(pointer optlist, const char *name, double deflt, Bool markUsed)
+{
+    OptionInfoRec o;
+
+    o.name = name;
+    o.type = OPTV_PERCENT;
+    if (ParseOptionValue(-1, optlist, &o, markUsed))
+	deflt = o.value.realnum;
+    return deflt;
+}
+
 /* These xf86Set* functions are intended for use by non-screen specific code */
 
 int
@@ -252,6 +264,12 @@ xf86SetBoolOption(pointer optlist, const char *name, int deflt)
     return LookupBoolOption(optlist, name, deflt, TRUE);
 }
 
+double
+xf86SetPercentOption(pointer optlist, const char *name, double deflt)
+{
+    return LookupPercentOption(optlist, name, deflt, TRUE);
+}
+
 /*
  * These are like the Set*Option functions, but they don't mark the options
  * as used.
@@ -283,6 +301,12 @@ xf86CheckBoolOption(pointer optlist, const char *name, int deflt)
     return LookupBoolOption(optlist, name, deflt, FALSE);
 }
 
+
+double
+xf86CheckPercentOption(pointer optlist, const char *name, double deflt)
+{
+    return LookupPercentOption(optlist, name, deflt, FALSE);
+}
 /*
  * addNewOption() has the required property of replacing the option value
  * if the option is already present.
@@ -310,6 +334,14 @@ xf86ReplaceBoolOption(pointer optlist, const char *name, const Bool val)
 }
 
 pointer
+xf86ReplacePercentOption(pointer optlist, const char *name, const double val)
+{
+    char tmp[16];
+    sprintf(tmp, "%lf%%", val);
+    return xf86AddNewOption(optlist,name,tmp);
+}
+
+pointer
 xf86ReplaceStrOption(pointer optlist, const char *name, const char* val)
 {
       return xf86AddNewOption(optlist,name,val);
@@ -533,6 +565,21 @@ ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p,
 		p->found = FALSE;
 	    }
 	    break;
+	case OPTV_PERCENT:
+	    {
+		char tmp = 0;
+		/* awkward match, but %% doesn't increase the match counter,
+		 * hence 100 looks the same as 100% to the caller of sccanf
+		 */
+		if (sscanf(s, "%lf%c", &p->value.realnum, &tmp) != 2 || tmp != '%') {
+		    xf86DrvMsg(scrnIndex, X_WARNING,
+			       "Option \"%s\" requires a percent value\n", p->name);
+		    p->found = FALSE;
+		} else {
+		    p->found = TRUE;
+		}
+	    }
+	    break;
 	case OPTV_FREQ:	
 	    if (*s == '\0') {
 		xf86DrvMsg(scrnIndex, X_WARNING,
diff --git a/hw/xfree86/common/xf86ShowOpts.c b/hw/xfree86/common/xf86ShowOpts.c
index ff4b651..eac25d7 100644
--- a/hw/xfree86/common/xf86ShowOpts.c
+++ b/hw/xfree86/common/xf86ShowOpts.c
@@ -70,6 +70,8 @@ optionTypeToSting(OptionValueType type)
         return "<bool>";
     case OPTV_FREQ:
         return "<freq>";
+    case OPTV_PERCENT:
+        return "<percent>";
     default:
         return "<undef>";
     }
diff --git a/hw/xfree86/doc/sgml/DESIGN.sgml b/hw/xfree86/doc/sgml/DESIGN.sgml
index e95df79..8999e0c 100644
--- a/hw/xfree86/doc/sgml/DESIGN.sgml
+++ b/hw/xfree86/doc/sgml/DESIGN.sgml
@@ -2528,6 +2528,7 @@ Next, the higher level functions that most drivers would use.
           OPTV_ANYSTR,  /* Any string, including an empty one */
           OPTV_REAL,
           OPTV_BOOLEAN,
+          OPTV_PERCENT,
           OPTV_FREQ
       } OptionValueType;
 
@@ -2555,6 +2556,11 @@ Next, the higher level functions that most drivers would use.
       &s.code;freq.units&e.code; is set to &s.code;0&e.code;, and
       &s.code;freq.freq&e.code; is unscaled.
 
+      &s.code;OPTV_PERCENT&e.code; can be used for option values that are
+      specified in percent (e.g. "20%"). These values are a floating point
+      number with a percent sign appended. If the percent sign is missing,
+      the parser will fail to match the value.
+
       Typical usage is to setup an array of
       &s.code;OptionInfoRecs&e.code; with all fields initialised.
       The &s.code;value&e.code; and &s.code;found&e.code; fields get
diff --git a/hw/xwin/winconfig.c b/hw/xwin/winconfig.c
index 971d381..c2dd056 100644
--- a/hw/xwin/winconfig.c
+++ b/hw/xwin/winconfig.c
@@ -673,6 +673,18 @@ winSetRealOption (pointer optlist, const char *name, double deflt)
     deflt = o.value.realnum;
   return deflt;
 }
+
+double
+winSetPercentOption (pointer optlist, const char *name, double deflt)
+{
+  OptionInfoRec o;
+
+  o.name = name;
+  o.type = OPTV_PERCENT;
+  if (ParseOptionValue (-1, optlist, &o))
+    deflt = o.value.realnum;
+  return deflt;
+}
 #endif
 
 
@@ -851,6 +863,31 @@ ParseOptionValue (int scrnIndex, pointer options, OptionInfoPtr p)
 	      p->found = FALSE;
 	    }
 	  break;
+	case OPTV_PERCENT:
+	  if (*s == '\0')
+	    {
+	      winDrvMsg (scrnIndex, X_WARNING,
+			 "Option \"%s\" requires a percent value\n",
+			 p->name);
+	      p->found = FALSE;
+	    }
+	  else
+	    {
+	       double percent = strtod (s, &end);
+
+	       if (end != s && winNameCompare (end, "%"))
+		 {
+		   p->found = TRUE;
+		   p->value.realnum = percent;
+		 }
+	       else
+		 {
+		   winDrvMsg (scrnIndex, X_WARNING,
+			      "Option \"%s\" requires a frequency value\n",
+			       p->name);
+		   p->found = FALSE;
+		 }
+	    }
 	case OPTV_FREQ:
 	  if (*s == '\0')
 	    {
diff --git a/hw/xwin/winconfig.h b/hw/xwin/winconfig.h
index 058884a..4699ca8 100644
--- a/hw/xwin/winconfig.h
+++ b/hw/xwin/winconfig.h
@@ -256,6 +256,7 @@ typedef enum
   OPTV_ANYSTR,			/* Any string, including an empty one */
   OPTV_REAL,
   OPTV_BOOLEAN,
+  OPTV_PERCENT,
   OPTV_FREQ
 }
 OptionValueType;
@@ -289,6 +290,7 @@ char *winSetStrOption (pointer optlist, const char *name, char *deflt);
 int winSetBoolOption (pointer optlist, const char *name, int deflt);
 int winSetIntOption (pointer optlist, const char *name, int deflt);
 double winSetRealOption (pointer optlist, const char *name, double deflt);
+double winSetPercentOption (pointer optlist, const char *name, double deflt);
 #ifdef XWIN_XF86CONFIG
 XF86OptionPtr winFindOption (XF86OptionPtr list, const char *name);
 char *winFindOptionValue (XF86OptionPtr list, const char *name);
commit 673eb707ce6737284c4886265ba149c5587a74e2
Author: Jamey Sharp <jamey at minilop.net>
Date:   Sat May 15 12:06:25 2010 -0700

    SyncSendAlarmNotifyEvents: check the correct client's clientGone flag.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/Xext/sync.c b/Xext/sync.c
index 0534728..d46087a 100644
--- a/Xext/sync.c
+++ b/Xext/sync.c
@@ -396,7 +396,7 @@ SyncSendAlarmNotifyEvents(SyncAlarm *pAlarm)
     /* send to other interested clients */
     for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
     {
-	if (!pAlarm->client->clientGone)
+	if (!pcl->client->clientGone)
 	{
 	    ane.sequenceNumber = pcl->client->sequence;
 	    WriteEventsToClient(pcl->client, 1, (xEvent *) &ane);
commit c3ba199aa643e59abd30170c53fbb4e03077c377
Author: Tiago Vignatti <tiago.vignatti at nokia.com>
Date:   Tue Apr 27 16:27:55 2010 +0300

    render: remove unused animcursor fields from private rec
    
    Signed-off-by: Tiago Vignatti <tiago.vignatti at nokia.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/render/animcur.c b/render/animcur.c
index f1e86f2..83211cc 100644
--- a/render/animcur.c
+++ b/render/animcur.c
@@ -58,10 +58,6 @@ typedef struct _AnimCur {
 } AnimCurRec, *AnimCurPtr;
 
 typedef struct _AnimScrPriv {
-    CursorPtr			pCursor;
-    int				elt;
-    CARD32			time;
-
     CloseScreenProcPtr		CloseScreen;
 
     ScreenBlockHandlerProcPtr	BlockHandler;
commit 9db63e4766bde07ebc375c4390bcc5c854b46ac3
Author: Tiago Vignatti <tiago.vignatti at nokia.com>
Date:   Tue Apr 27 16:18:50 2010 +0300

    render: removed unused macro from animcursor
    
    Signed-off-by: Tiago Vignatti <tiago.vignatti at nokia.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/render/animcur.c b/render/animcur.c
index d207bcc..f1e86f2 100644
--- a/render/animcur.c
+++ b/render/animcur.c
@@ -98,7 +98,6 @@ static DevPrivateKey AnimCurScreenPrivateKey = &AnimCurScreenPrivateKeyIndex;
 #define IsAnimCur(c)	    ((c) && ((c)->bits == &animCursorBits))
 #define GetAnimCur(c)	    ((AnimCurPtr) ((c) + 1))
 #define GetAnimCurScreen(s) ((AnimCurScreenPtr)dixLookupPrivate(&(s)->devPrivates, AnimCurScreenPrivateKey))
-#define GetAnimCurScreenIfSet(s) GetAnimCurScreen(s)
 #define SetAnimCurScreen(s,p) dixSetPrivate(&(s)->devPrivates, AnimCurScreenPrivateKey, p)
 
 #define Wrap(as,s,elt,func) (((as)->elt = (s)->elt), (s)->elt = func)
@@ -375,7 +374,7 @@ AnimCursorCreate (CursorPtr *cursors, CARD32 *deltas, int ncursor, CursorPtr *pp
     AnimCurPtr	ac;
 
     for (i = 0; i < screenInfo.numScreens; i++)
-	if (!GetAnimCurScreenIfSet (screenInfo.screens[i]))
+	if (!GetAnimCurScreen (screenInfo.screens[i]))
 	    return BadImplementation;
 
     for (i = 0; i < ncursor; i++)
commit cba9942f7716b12c329616a9994c5bce857617fa
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Mon May 17 17:40:30 2010 -0400

    dri2: Fix NULL check in allocation error handling
    
    1461b31e40a3e44f6327199d23cf2ab70d8f5176 tests to see if the allocation
    of buffer[i] failed after i has been incremented, causing it to look
    at the wrong pointer.
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Tested-by: Eric Anholt <eric at anholt.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 68982fe..29c917f 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -421,22 +421,24 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
     if (need_real_front > 0) {
 	if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFrontLeft,
 				     front_format, dimensions_match,
-				     &buffers[i++]))
+				     &buffers[i]))
 	    buffers_changed = 1;
 
 	if (buffers[i] == NULL)
 	    goto err_out;
+	i++;
     }
 
     if (need_fake_front > 0) {
 	if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFakeFrontLeft,
 				     front_format, dimensions_match,
-				     &buffers[i++]))
+				     &buffers[i]))
 	    buffers_changed = 1;
 
 	if (buffers[i] == NULL)
 	    goto err_out;
 
+	i++;
 	have_fake_front = 1;
     }
 
commit 27cec0a0501369a68031c048e691bda4c7095f72
Author: Julien Cristau <jcristau at debian.org>
Date:   Mon May 17 19:23:44 2010 +0200

    Fix build without XACE
    
    dix/colormap.c and dix/gc.c now dereference a ClientPtr, so they need to
    include dixstruct.h.  Regression introduced by commit
    11c69880c7c48ef9e755c4e09fadef7a629d7bc7.
    
    Reported-by: Robert Hooker <sarvatt at ubuntu.com>
    Signed-off-by: Julien Cristau <jcristau at debian.org>
    Reviewed-by: Jamey Sharp <jamey at minilop.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/dix/colormap.c b/dix/colormap.c
index f75eefe..12197ac 100644
--- a/dix/colormap.c
+++ b/dix/colormap.c
@@ -57,6 +57,7 @@ SOFTWARE.
 #include <strings.h>
 #include "misc.h"
 #include "dix.h"
+#include "dixstruct.h"
 #include "colormapst.h"
 #include "os.h"
 #include "scrnintstr.h"
diff --git a/dix/gc.c b/dix/gc.c
index 5a0d00d..6281f25 100644
--- a/dix/gc.c
+++ b/dix/gc.c
@@ -60,6 +60,7 @@ SOFTWARE.
 #include "dixfontstr.h"
 #include "scrnintstr.h"
 #include "region.h"
+#include "dixstruct.h"
 
 #include "privates.h"
 #include "dix.h"
commit 5a387cf6d248e3cb3337a938200ed5a09fc1d8cb
Author: Julien Cristau <jcristau at debian.org>
Date:   Sun May 16 21:29:02 2010 +0200

    Only link Xorg with libconfig.la
    
    Other DDXs don't use input hotplugging since config_init was moved to
    the DDX in commit d33adcdf03c69407d151e732fa0cf9947151eb19, so there's
    no need to link this in.
    
    Signed-off-by: Julien Cristau <jcristau at debian.org>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index cf2a358..1c7875e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -869,7 +869,6 @@ if test "x$CONFIG_NEED_DBUS" = xyes; then
         AC_DEFINE(CONFIG_NEED_DBUS, 1, [Use D-Bus for input hotplug])
 fi
 AM_CONDITIONAL(CONFIG_NEED_DBUS, [test "x$CONFIG_NEED_DBUS" = xyes])
-CONFIG_LIB='$(top_builddir)/config/libconfig.la'
 
 if test "x$USE_SIGIO_BY_DEFAULT" = xyes; then
 	USE_SIGIO_BY_DEFAULT_VALUE=TRUE
@@ -1454,7 +1453,7 @@ PKG_CHECK_MODULES([XSERVERLIBS], [$REQUIRED_LIBS])
 # require.
 #
 XSERVER_CFLAGS="${XSERVER_CFLAGS} ${XSERVERCFLAGS_CFLAGS}"
-XSERVER_LIBS="$DIX_LIB $CONFIG_LIB $MI_LIB $OS_LIB"
+XSERVER_LIBS="$DIX_LIB $MI_LIB $OS_LIB"
 XSERVER_SYS_LIBS="${XSERVERLIBS_LIBS} ${SYS_LIBS} ${LIBS}"
 AC_SUBST([XSERVER_LIBS])
 AC_SUBST([XSERVER_SYS_LIBS])
@@ -1492,7 +1491,7 @@ AC_MSG_RESULT([$XVFB])
 AM_CONDITIONAL(XVFB, [test "x$XVFB" = xyes])
 
 if test "x$XVFB" = xyes; then
-	XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB"
+	XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB"
 	XVFB_SYS_LIBS="$XVFBMODULES_LIBS $GLX_SYS_LIBS"
 	AC_SUBST([XVFB_LIBS])
 	AC_SUBST([XVFB_SYS_LIBS])
@@ -1513,7 +1512,7 @@ if test "x$XNEST" = xyes; then
 	if test "x$have_xnest" = xno; then
 		AC_MSG_ERROR([Xnest build explicitly requested, but required modules not found.])
 	fi
-	XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DIX_LIB $MAIN_LIB $OS_LIB $CONFIG_LIB"
+	XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DIX_LIB $MAIN_LIB $OS_LIB"
 	XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS"
 	AC_SUBST([XNEST_LIBS])
 	AC_SUBST([XNEST_SYS_LIBS])
@@ -1876,7 +1875,7 @@ if test "x$XWIN" = xyes; then
 			XWIN_SYS_LIBS=-lwinsock2
 			;;
 	esac
-	XWIN_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $RANDR_LIB $RENDER_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $OS_LIB"
+	XWIN_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $RANDR_LIB $RENDER_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $OS_LIB"
 	XWIN_SYS_LIBS="$XWIN_SYS_LIBS $XWINMODULES_LIBS"
 	AC_SUBST(XWIN_LIBS)
 	AC_SUBST(XWIN_SERVER_NAME)
@@ -1906,7 +1905,7 @@ if test "x$XQUARTZ" = xyes; then
 	AC_DEFINE(XQUARTZ,1,[Have Quartz])
 	AC_DEFINE(ROOTLESS,1,[Build Rootless code])
 
-	DARWIN_LIBS="$MI_LIB $OS_LIB $DIX_LIB $MAIN_LIB $FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB"
+	DARWIN_LIBS="$MI_LIB $OS_LIB $DIX_LIB $MAIN_LIB $FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB"
 	AC_SUBST([DARWIN_LIBS])
 
 	AC_CHECK_LIB([Xplugin],[xp_init],[:])
@@ -1967,7 +1966,7 @@ if test "x$DMX" = xyes; then
 	fi
 	DMX_INCLUDES="$XEXT_INC $RENDER_INC $RECORD_INC"
 	XDMX_CFLAGS="$DMXMODULES_CFLAGS"
-	XDMX_LIBS="$FB_LIB $MI_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $XEXT_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB"
+	XDMX_LIBS="$FB_LIB $MI_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $XEXT_LIB $MAIN_LIB $DIX_LIB $OS_LIB $FIXES_LIB"
 	XDMX_SYS_LIBS="$DMXMODULES_LIBS"
 	AC_SUBST([XDMX_CFLAGS])
 	AC_SUBST([XDMX_LIBS])
@@ -2101,7 +2100,7 @@ if test "$KDRIVE" = yes; then
 	    ;;
     esac
     KDRIVE_STUB_LIB='$(top_builddir)/hw/kdrive/src/libkdrivestubs.la'
-    KDRIVE_LOCAL_LIBS="$MAIN_LIB $DIX_LIB $KDRIVE_LIB $KDRIVE_STUB_LIB $CONFIG_LIB"
+    KDRIVE_LOCAL_LIBS="$MAIN_LIB $DIX_LIB $KDRIVE_LIB $KDRIVE_STUB_LIB"
     KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $FB_LIB $MI_LIB $KDRIVE_PURE_LIBS"
     KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $KDRIVE_OS_LIB $OS_LIB"
     KDRIVE_LIBS="$TSLIB_LIBS $KDRIVE_LOCAL_LIBS $XSERVER_SYS_LIBS $GLX_SYS_LIBS $DLOPEN_LIBS"
diff --git a/hw/xfree86/common/Makefile.am b/hw/xfree86/common/Makefile.am
index ad27210..821a2b5 100644
--- a/hw/xfree86/common/Makefile.am
+++ b/hw/xfree86/common/Makefile.am
@@ -41,6 +41,7 @@ libcommon_la_SOURCES = xf86Configure.c xf86ShowOpts.c xf86Bus.c xf86Config.c \
                       xf86Mode.c xorgHelper.c \
                       $(XVSOURCES) $(BUSSOURCES) $(RANDRSOURCES)
 nodist_libcommon_la_SOURCES = xf86DefModeSet.c xf86Build.h
+libcommon_la_LIBADD = $(top_builddir)/config/libconfig.la
 
 INCLUDES = $(XORG_INCS) -I$(srcdir)/../ddc -I$(srcdir)/../i2c \
 	   -I$(srcdir)/../loader -I$(srcdir)/../parser \


More information about the Xquartz-changes mailing list