[RFC] Make MAXSCREENS run-time configurable

Tiago Vignatti tiago.vignatti at nokia.com
Thu Apr 1 09:19:11 PDT 2010


Allows MAXSCREENS to be determined at run time instead of compile time, adding
a new -maxscreens command line flag.

*** Attention ABI broken everywhere! ***

There's also a tiny work needed on driver side, to change some DGA structure.
And if you don't, some really weird pointers will get lost everywhere.

The original authors of this patch are Kevin Martin and Rik Faith, which
created it against XFree86, back in 2005:
    https://bugs.freedesktop.org/show_bug.cgi?id=3876
    https://bugs.freedesktop.org/attachment.cgi?id=5708

Signed-off-by: Tiago Vignatti <tiago.vignatti at nokia.com>
---
- it's an alternative for "[PATCH] configure: dix: support a variable number
  of screen structures", sent some weeks ago to xorg-devel:
      http://lists.x.org/archives/xorg-devel/2010-March/006147.html

- we might want to set the default of maxscreens (MAXSCREENSDEFAULT) to 16,
  and not change any behaviour of the server. I vote 'yes' here to avoid
  people screaming..

- this patch has a (weak) dependency on "[PATCH] Death to Multibuffer
  extension", sent some days ago to the list.

- I removed one unused field from ClientRec (in fact ajax was already
  documented this intention in commit 252ec504). So again: ABI changes
  everywhere!!!

- there're some weird indentations all over the patch. We can fix this later.

- we need to expand this idea to all DDX. Easy tho.

- The "tiny work" required on the driver side is something like this:

  @@ -301,11 +301,13 @@ MGA_SetMode(
      ScrnInfoPtr pScrn,
      DGAModePtr pMode
   ){
  -   static MGAFBLayout SavedLayouts[MAXSCREENS];
  +   static MGAFBLayout *SavedLayouts;
      int index = pScrn->pScreen->myNum;
   
      MGAPtr pMga = MGAPTR(pScrn);
   
  +   MAXSCREENSALLOC_FATAL(SavedLayouts);
  +

- The really cool thing now would be to prototype some dynamic way to increase
  MAXSCREENS while output devices are hotplugged. We would remove -maxscreens
  option, count some calls to AddScreen and reallocate structures all over the
  code. The latter is the tough exercise because it touches MPX, randr, DGA,
  xinerama, etc.

 Xext/panoramiX.c                      |   12 +++-
 Xext/panoramiX.h                      |    2 +-
 Xext/panoramiXprocs.c                 |  118 ++++++++++++++++++++++++++-------
 Xext/panoramiXsrv.h                   |    2 +-
 Xext/xvdisp.c                         |    8 ++-
 dix/events.c                          |    1 +
 dix/globals.c                         |    7 +-
 dix/main.c                            |   47 +++++++++++++
 dix/window.c                          |    2 +-
 fb/fbcmap.c                           |   11 ++-
 hw/xfree86/common/xf86Cursor.c        |   67 ++++++++++--------
 hw/xfree86/common/xf86xv.c            |    3 +-
 hw/xfree86/dixmods/extmod/xf86dga2.c  |    4 +-
 hw/xfree86/os-support/bsd/arm_video.c |    5 +-
 include/cursor.h                      |    2 +-
 include/dixstruct.h                   |    1 -
 include/globals.h                     |    9 ++-
 include/inputstr.h                    |    2 +-
 include/misc.h                        |   44 +++++++++++-
 include/scrnintstr.h                  |    2 +-
 include/windowstr.h                   |    2 +-
 mi/micmap.c                           |    4 +-
 mi/micmap.h                           |    2 +-
 os/utils.c                            |   14 ++++
 render/render.c                       |   10 +++-
 25 files changed, 300 insertions(+), 81 deletions(-)

diff --git a/Xext/panoramiX.c b/Xext/panoramiX.c
index cfeba01..7d1b849 100644
--- a/Xext/panoramiX.c
+++ b/Xext/panoramiX.c
@@ -122,7 +122,7 @@ typedef struct {
   CloseScreenProcPtr	CloseScreen;
 } PanoramiXScreenRec, *PanoramiXScreenPtr;
 
-RegionRec XineramaScreenRegions[MAXSCREENS];
+RegionRec *XineramaScreenRegions;
 
 static void XineramaValidateGC(GCPtr, unsigned long, DrawablePtr);
 static void XineramaChangeGC(GCPtr, unsigned long);
@@ -330,6 +330,8 @@ XineramaDestroyClip(GCPtr pGC)
 int
 XineramaDeleteResource(pointer data, XID id)
 {
+    PanoramiXRes *res = (PanoramiXRes *)data;
+    MAXSCREENSFREE(res->info);
     xfree(data);
     return 1;
 }
@@ -456,6 +458,8 @@ void PanoramiXExtensionInit(int argc, char *argv[])
     if (noPanoramiXExtension) 
 	return;
 
+    MAXSCREENSALLOC_FATAL(XineramaScreenRegions);
+
     PanoramiXNumScreens = screenInfo.numScreens;
     if (PanoramiXNumScreens == 1) {		/* Only 1 screen 	*/
 	noPanoramiXExtension = TRUE;
@@ -829,10 +833,16 @@ PanoramiXConsolidate(void)
 
     root = xalloc(sizeof(PanoramiXRes));
     root->type = XRT_WINDOW;
+    root->info = NULL; /* NOTE above alloc unchecked */
+    MAXSCREENSALLOC_FATAL(root->info);
     defmap = xalloc(sizeof(PanoramiXRes));
     defmap->type = XRT_COLORMAP;
+    defmap->info = NULL; /* NOTE above alloc unchecked */
+    MAXSCREENSALLOC_FATAL(defmap->info);
     saver = xalloc(sizeof(PanoramiXRes));
     saver->type = XRT_WINDOW;
+    saver->info = NULL; /* NOTE above alloc unchecked */
+    MAXSCREENSALLOC_FATAL(saver->info);
 
     for (i =  0; i < PanoramiXNumScreens; i++) {
 	root->info[i].id = WindowTable[i]->drawable.id;
diff --git a/Xext/panoramiX.h b/Xext/panoramiX.h
index cca4c52..5d8926d 100644
--- a/Xext/panoramiX.h
+++ b/Xext/panoramiX.h
@@ -58,7 +58,7 @@ typedef struct _PanoramiXInfo {
 } PanoramiXInfo;
 
 typedef struct {
-    PanoramiXInfo info[MAXSCREENS];
+    PanoramiXInfo *info;
     RESTYPE type;
     union {
 	struct {
diff --git a/Xext/panoramiXprocs.c b/Xext/panoramiXprocs.c
index 6834efb..f3a1e60 100644
--- a/Xext/panoramiXprocs.c
+++ b/Xext/panoramiXprocs.c
@@ -124,6 +124,13 @@ int PanoramiXCreateWindow(ClientPtr client)
         return BadAlloc;
 
     newWin->type = XRT_WINDOW;
+    newWin->info = NULL;
+    MAXSCREENSALLOC(newWin->info);
+    if (!newWin->info) {
+        xfree(newWin);
+        return BadAlloc;
+    }
+
     newWin->u.win.visibility = VisibilityNotViewable;
     newWin->u.win.class = stuff->class;
     newWin->u.win.root = FALSE;
@@ -159,8 +166,10 @@ int PanoramiXCreateWindow(ClientPtr client)
 
     if (result == Success)
         AddResource(newWin->info[0].id, XRT_WINDOW, newWin);
-    else 
+    else {
+        MAXSCREENSFREE(newWin->info);
         xfree(newWin);
+    }
 
     return (result);
 }
@@ -670,6 +679,12 @@ int PanoramiXCreatePixmap(ClientPtr client)
 	return BadAlloc;
 
     newPix->type = XRT_PIXMAP;
+    newPix->info = NULL;
+    MAXSCREENSALLOC(newPix->info);
+    if (!newPix->info) {
+        xfree(newPix);
+        return BadAlloc;
+    }
     newPix->u.pix.shared = FALSE;
     newPix->info[0].id = stuff->pid;
     for(j = 1; j < PanoramiXNumScreens; j++)
@@ -684,8 +699,10 @@ int PanoramiXCreatePixmap(ClientPtr client)
 
     if (result == Success)
 	AddResource(newPix->info[0].id, XRT_PIXMAP, newPix);
-    else 
-	xfree(newPix);
+    else {
+        MAXSCREENSFREE(newPix->info);
+        xfree(newPix);
+    }
 
     return (result);
 }
@@ -775,6 +792,12 @@ int PanoramiXCreateGC(ClientPtr client)
         return BadAlloc;
 
     newGC->type = XRT_GC;
+    newGC->info = NULL;
+    MAXSCREENSALLOC(newGC->info);
+    if (!newGC->info) {
+        xfree(newGC);
+        return BadAlloc;
+    }
     newGC->info[0].id = stuff->gc;
     for(j = 1; j < PanoramiXNumScreens; j++)
         newGC->info[j].id = FakeClientID(client->index);
@@ -794,8 +817,10 @@ int PanoramiXCreateGC(ClientPtr client)
 
     if (result == Success)
         AddResource(newGC->info[0].id, XRT_GC, newGC);
-    else 
+    else {
+        MAXSCREENSFREE(newGC->info);
         xfree(newGC);
+    }
 
     return (result);
 }
@@ -1050,12 +1075,14 @@ int PanoramiXCopyArea(ClientPtr client)
     srcx = stuff->srcX; srcy = stuff->srcY;
     dstx = stuff->dstX; dsty = stuff->dstY;
     if((dst->type == XRT_PIXMAP) && (src->type == XRT_WINDOW)) {
-	DrawablePtr drawables[MAXSCREENS];
+	DrawablePtr *drawables;
 	DrawablePtr pDst;
 	GCPtr pGC;
         char *data;
 	int pitch, rc;
 
+    MAXSCREENSALLOC_RETURN(drawables, BadAlloc);
+
 	FOR_NSCREENS(j) {
 	    rc = dixLookupDrawable(drawables+j, src->info[j].id, client, 0,
 				   DixGetAttrAccess);
@@ -1064,8 +1091,10 @@ int PanoramiXCopyArea(ClientPtr client)
 	}
 
 	pitch = PixmapBytePad(stuff->width, drawables[0]->depth); 
-	if(!(data = xcalloc(1, stuff->height * pitch)))
+	if(!(data = xcalloc(1, stuff->height * pitch))) {
+        MAXSCREENSFREE(drawables);
 	    return BadAlloc;
+    }
 
 	XineramaGetImageData(drawables, srcx, srcy, 
 		stuff->width, stuff->height, ZPixmap, ~0, data, pitch, 
@@ -1076,6 +1105,7 @@ int PanoramiXCopyArea(ClientPtr client)
 	    VALIDATE_DRAWABLE_AND_GC(dst->info[j].id, pDst, DixWriteAccess);
 	    if(drawables[0]->depth != pDst->depth) {
 		client->errorValue = stuff->dstDrawable;
+        MAXSCREENSFREE(drawables);
 		xfree(data);
 		return (BadMatch);
 	    }
@@ -1087,15 +1117,18 @@ int PanoramiXCopyArea(ClientPtr client)
 	    if(dstShared) break;
 	}
 
+    MAXSCREENSFREE(drawables);
 	xfree(data);
 
 	result = Success;
     } else {
 	DrawablePtr pDst = NULL, pSrc = NULL;
 	GCPtr pGC = NULL;
-	RegionPtr pRgn[MAXSCREENS];
+	RegionPtr *pRgn;
 	int rc;
 
+    MAXSCREENSALLOC_RETURN(pRgn, BadAlloc);
+
 	FOR_NSCREENS_BACKWARD(j) {
 	    stuff->dstDrawable = dst->info[j].id;
 	    stuff->srcDrawable = src->info[j].id;
@@ -1120,6 +1153,7 @@ int PanoramiXCopyArea(ClientPtr client)
 		if ((pDst->pScreen != pSrc->pScreen) || 
 		    (pDst->depth != pSrc->depth)) {
 			client->errorValue = stuff->dstDrawable;
+            MAXSCREENSFREE(pRgn);
 			return (BadMatch);
    		}
  	    } else
@@ -1157,7 +1191,9 @@ int PanoramiXCopyArea(ClientPtr client)
 		client, &totalReg, stuff->dstDrawable, X_CopyArea, 0);
 	    REGION_UNINIT(pScreen, &totalReg);
 	}
-	
+
+    MAXSCREENSFREE(pRgn);
+
 	result = client->noClientException;
     }
 
@@ -1174,32 +1210,42 @@ int PanoramiXCopyPlane(ClientPtr client)
     Bool		srcShared, dstShared;
     DrawablePtr 	psrcDraw, pdstDraw = NULL;
     GCPtr 		pGC = NULL;
-    RegionPtr 		pRgn[MAXSCREENS];
+    RegionPtr		*pRgn;
     REQUEST(xCopyPlaneReq);
 
     REQUEST_SIZE_MATCH(xCopyPlaneReq);
 
+    MAXSCREENSALLOC_RETURN(pRgn, BadAlloc);
+
     rc = dixLookupResourceByClass((pointer *)&src, stuff->srcDrawable,
 				  XRC_DRAWABLE, client, DixReadAccess);
-    if (rc != Success)
-	return (rc == BadValue) ? BadDrawable : rc;
+    if (rc != Success) {
+        MAXSCREENSFREE(pRgn);
+        return (rc == BadValue) ? BadDrawable : rc;
+    }
 
     srcShared = IS_SHARED_PIXMAP(src);
 
     rc = dixLookupResourceByClass((pointer *)&dst, stuff->dstDrawable,
 				  XRC_DRAWABLE, client, DixWriteAccess);
-    if (rc != Success)
-	return (rc == BadValue) ? BadDrawable : rc;
+    if (rc != Success) {
+        MAXSCREENSFREE(pRgn);
+        return (rc == BadValue) ? BadDrawable : rc;
+    }
 
     dstShared = IS_SHARED_PIXMAP(dst);
 
-    if(dstShared && srcShared)
-	return (* SavedProcVector[X_CopyPlane])(client);
+    if(dstShared && srcShared) {
+        MAXSCREENSFREE(pRgn);
+        return (* SavedProcVector[X_CopyPlane])(client);
+    }
 
     rc = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
 				 client, DixReadAccess);
-    if (rc != Success)
-	return (rc == BadValue) ? BadGC : rc;
+    if (rc != Success) {
+        MAXSCREENSFREE(pRgn);
+        return (rc == BadValue) ? BadGC : rc;
+    }
 
     if((dst->type == XRT_WINDOW) && dst->u.win.root)
 	dstIsRoot = TRUE;
@@ -1231,6 +1277,7 @@ int PanoramiXCopyPlane(ClientPtr client)
 
             if (pdstDraw->pScreen != psrcDraw->pScreen) {
 		client->errorValue = stuff->dstDrawable;
+        MAXSCREENSFREE(pRgn);
 		return (BadMatch);
 	    }
 	} else
@@ -1239,6 +1286,7 @@ int PanoramiXCopyPlane(ClientPtr client)
 	if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) ||
 		(stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) {
 	    client->errorValue = stuff->bitPlane;
+        MAXSCREENSFREE(pRgn);
 	    return(BadValue);
 	}
 
@@ -1271,6 +1319,7 @@ int PanoramiXCopyPlane(ClientPtr client)
 	REGION_UNINIT(pScreen, &totalReg);
     }
 
+    MAXSCREENSFREE(pRgn);
     return (client->noClientException);
 }
 
@@ -1805,7 +1854,7 @@ int PanoramiXPutImage(ClientPtr client)
 
 int PanoramiXGetImage(ClientPtr client)
 {
-    DrawablePtr 	drawables[MAXSCREENS];
+    DrawablePtr 	*drawables;
     DrawablePtr 	pDraw;
     PanoramiXRes	*draw;
     xGetImageReply	xgi;
@@ -1869,12 +1918,14 @@ int PanoramiXGetImage(ClientPtr client)
 	    return(BadMatch);
     }
 
+    MAXSCREENSALLOC_RETURN(drawables, BadAlloc);
     drawables[0] = pDraw;
     for(i = 1; i < PanoramiXNumScreens; i++) {
 	rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0,
 			       DixGetAttrAccess);
 	if (rc != Success)
-	    return rc;
+        MAXSCREENSFREE(drawables);
+        return rc;
     }
 
     xgi.visual = wVisual (((WindowPtr) pDraw));
@@ -1907,8 +1958,10 @@ int PanoramiXGetImage(ClientPtr client)
 	    linesPerBuf = h;
     }
     length = linesPerBuf * widthBytesLine;
-    if(!(pBuf = xalloc(length)))
-	return (BadAlloc);
+    if(!(pBuf = xalloc(length))) {
+        MAXSCREENSFREE(drawables);
+        return (BadAlloc);
+    }
 
     WriteReplyToClient(client, sizeof (xGetImageReply), &xgi);
 
@@ -1953,6 +2006,7 @@ int PanoramiXGetImage(ClientPtr client)
             }
 	}
     }
+    MAXSCREENSFREE(drawables);
     xfree(pBuf);
     return (client->noClientException);
 }
@@ -2144,6 +2198,13 @@ int PanoramiXCreateColormap(ClientPtr client)
     if(!(newCmap = xalloc(sizeof(PanoramiXRes))))
         return BadAlloc;
 
+    newCmap->info = NULL;
+    MAXSCREENSALLOC(newCmap->info);
+    if (!newCmap->info) {
+        xfree(newCmap);
+        return BadAlloc;
+    }
+
     newCmap->type = XRT_COLORMAP;
     newCmap->info[0].id = stuff->mid;
     for(j = 1; j < PanoramiXNumScreens; j++)
@@ -2160,8 +2221,10 @@ int PanoramiXCreateColormap(ClientPtr client)
  
     if (result == Success)
         AddResource(newCmap->info[0].id, XRT_COLORMAP, newCmap);
-    else 
+    else {
+        MAXSCREENSFREE(newCmap->info);
         xfree(newCmap);
+    }
 
     return (result);
 }
@@ -2215,6 +2278,13 @@ PanoramiXCopyColormapAndFree(ClientPtr client)
     if(!(newCmap = xalloc(sizeof(PanoramiXRes))))
         return BadAlloc;
 
+    newCmap->info = NULL;
+    MAXSCREENSALLOC(newCmap->info);
+    if (!newCmap->info) {
+        xfree(newCmap);
+        return BadAlloc;
+    }
+
     newCmap->type = XRT_COLORMAP;
     newCmap->info[0].id = stuff->mid;
     for(j = 1; j < PanoramiXNumScreens; j++)
@@ -2229,8 +2299,10 @@ PanoramiXCopyColormapAndFree(ClientPtr client)
 
     if (result == Success)
         AddResource(newCmap->info[0].id, XRT_COLORMAP, newCmap);
-    else 
+    else {
+        MAXSCREENSFREE(newCmap->info);
         xfree(newCmap);
+    }
 
     return (result);
 }
diff --git a/Xext/panoramiXsrv.h b/Xext/panoramiXsrv.h
index c77b119..2288508 100644
--- a/Xext/panoramiXsrv.h
+++ b/Xext/panoramiXsrv.h
@@ -22,7 +22,7 @@ extern _X_EXPORT int XineramaDeleteResource(pointer, XID);
 
 extern _X_EXPORT void XineramaReinitData(ScreenPtr);
 
-extern _X_EXPORT RegionRec XineramaScreenRegions[MAXSCREENS];
+extern _X_EXPORT RegionRec *XineramaScreenRegions;
 
 extern _X_EXPORT unsigned long XRC_DRAWABLE;
 extern _X_EXPORT unsigned long XRT_WINDOW;
diff --git a/Xext/xvdisp.c b/Xext/xvdisp.c
index b6fc34f..60088d3 100644
--- a/Xext/xvdisp.c
+++ b/Xext/xvdisp.c
@@ -1860,13 +1860,15 @@ void XineramifyXv(void)
    XvScreenPtr xvsp;
    Bool isOverlay, hasOverlay;
    PanoramiXRes *port;
-   XvAdaptorPtr MatchingAdaptors[MAXSCREENS];
+   XvAdaptorPtr *MatchingAdaptors;
    int i, j, k, l;
 
    XvXRTPort = CreateNewResourceType(XineramaDeleteResource, "XvXRTPort");
 
    if (!xvsp0 || !XvXRTPort) return;
 
+   MAXSCREENSALLOC_FATAL(MatchingAdaptors);
+
    for(i = 0; i < xvsp0->nAdaptors; i++) {
       refAdapt = xvsp0->pAdaptors + i;
 
@@ -1945,6 +1947,8 @@ void XineramifyXv(void)
       for(j = 0; j < refAdapt->nPorts; j++) {
          if(!(port = xalloc(sizeof(PanoramiXRes))))
 	    break;
+	 port->info = NULL;
+	 MAXSCREENSALLOC_FATAL(port->info);
 	 port->info[0].id = MatchingAdaptors[0]->base_id + j;
 	 AddResource(port->info[0].id, XvXRTPort, port);
 
@@ -1964,6 +1968,8 @@ void XineramifyXv(void)
    XvProcVector[xv_SetPortAttribute]	= XineramaXvSetPortAttribute;
    XvProcVector[xv_PutImage]		= XineramaXvPutImage;
    XvProcVector[xv_ShmPutImage]		= XineramaXvShmPutImage;
+
+   MAXSCREENSFREE(MatchingAdaptors);
 }
 #endif /* PANORAMIX */
 
diff --git a/dix/events.c b/dix/events.c
index 6541652..7d19424 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2945,6 +2945,7 @@ InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
         DeviceIntPtr it;
 
         pDev->spriteInfo->sprite = (SpritePtr)xcalloc(1, sizeof(SpriteRec));
+        MAXSCREENSALLOC_FATAL(pDev->spriteInfo->sprite->windows);
         if (!pDev->spriteInfo->sprite)
             FatalError("InitializeSprite: failed to allocate sprite struct");
 
diff --git a/dix/globals.c b/dix/globals.c
index c24a94f..0158b2d 100644
--- a/dix/globals.c
+++ b/dix/globals.c
@@ -78,12 +78,13 @@ PtrCtrl defaultPointerControl = {
 	DEFAULT_PTR_THRESHOLD,
 	0};
 
+int        MAXSCREENS;
 ClientPtr  clients[MAXCLIENTS];
 ClientPtr  serverClient;
 int  currentMaxClients;   /* current size of clients array */
 long maxBigRequestSize = MAX_BIG_REQUEST_SIZE;
 
-WindowPtr WindowTable[MAXSCREENS];
+WindowPtr *WindowTable;
 
 unsigned long globalSerialNumber = 0;
 unsigned long serverGeneration = 0;
@@ -125,7 +126,7 @@ CursorPtr rootCursor;
 Bool party_like_its_1989 = FALSE;
 Bool whiteRoot = FALSE;
 
-int cursorScreenDevPriv[MAXSCREENS];
+int *cursorScreenDevPriv;
 
 TimeStamp currentTime;
 TimeStamp lastDeviceEventTime;
@@ -138,4 +139,4 @@ char *ConnectionInfo;
 
 CARD32 TimeOutValue = DEFAULT_TIMEOUT * MILLI_PER_SECOND;
 
-DDXPointRec dixScreenOrigins[MAXSCREENS];
+DDXPointRec *dixScreenOrigins;
diff --git a/dix/main.c b/dix/main.c
index f023536..edd66a1 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -120,6 +120,44 @@ extern void Dispatch(void);
 
 extern void InitProcVectors(void);
 
+static int MAXSCREENS_USED;
+void *MaxScreensAlloc(unsigned long size)
+{
+    void *buf;
+
+    if (!MAXSCREENS)
+        FatalError("MaxScreensAlloc called before SetMaxScreens");
+
+    MAXSCREENS_USED = 1;
+    buf = xalloc(size);
+    if (buf)
+        memset(buf, 0, size);
+
+    return buf;
+}
+
+void MaxScreensFree(void *object)
+{
+    if (object) xfree(object);
+}
+
+void SetMaxScreens(int maxscreens)
+{
+    if (MAXSCREENS_USED)
+        FatalError("SetMaxScreens called after first use");
+    MAXSCREENS = maxscreens > 0 ? maxscreens : MAXSCREENSDEFAULT;
+}
+
+static void InitGlobals(void)
+{
+    if (!MAXSCREENS) SetMaxScreens(MAXSCREENSDEFAULT);
+
+    MAXSCREENSALLOC_FATAL(dixScreenOrigins);
+    MAXSCREENSALLOC_FATAL(cursorScreenDevPriv);
+    MAXSCREENSALLOC_FATAL(savedScreenInfo);
+    MAXSCREENSALLOC_FATAL(screenInfo.screens);
+}
+
 #ifdef XQUARTZ
 #include <pthread.h>
 
@@ -151,6 +189,8 @@ int main(int argc, char *argv[], char *envp[])
 
     ProcessCommandLine(argc, argv);
 
+    InitGlobals();
+
     alwaysCheckForInput[0] = 0;
     alwaysCheckForInput[1] = 1;
     while(1)
@@ -193,6 +233,10 @@ int main(int argc, char *argv[], char *envp[])
 	screenInfo.arraySize = MAXSCREENS;
 	screenInfo.numScreens = 0;
 
+	MAXSCREENSALLOC(WindowTable);
+	if (!WindowTable)
+	    FatalError("couldn't create root window table");
+
 	InitAtoms();
 	InitEvents();
 	InitSelections();
@@ -320,6 +364,9 @@ int main(int argc, char *argv[], char *envp[])
 	    xfree(screenInfo.screens[i]);
 	    screenInfo.numScreens = i;
 	}
+
+	xfree(WindowTable);
+	WindowTable = NULL;
 	FreeFonts();
 
 	FreeAuditTimer();
diff --git a/dix/window.c b/dix/window.c
index c7201df..6237188 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -151,7 +151,7 @@ WindowSeekDeviceCursor(WindowPtr pWin,
 
 int screenIsSaved = SCREEN_SAVER_OFF;
 
-ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
+ScreenSaverStuffRec *savedScreenInfo;
 
 static int FocusPrivatesKeyIndex;
 DevPrivateKey FocusPrivatesKey = &FocusPrivatesKeyIndex;
diff --git a/fb/fbcmap.c b/fb/fbcmap.c
index 2ff3234..3b0d1f4 100644
--- a/fb/fbcmap.c
+++ b/fb/fbcmap.c
@@ -38,13 +38,14 @@
 
 
 
-ColormapPtr FbInstalledMaps[MAXSCREENS];
+ColormapPtr *FbInstalledMaps;
 
 int
 fbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
 {
     /* By the time we are processing requests, we can guarantee that there
      * is always a colormap installed */
+    MAXSCREENSALLOC_FATAL(FbInstalledMaps);
     *pmaps = FbInstalledMaps[pScreen->myNum]->mid;
     return (1);
 }
@@ -54,8 +55,10 @@ void
 fbInstallColormap(ColormapPtr pmap)
 {
     int index = pmap->pScreen->myNum;
-    ColormapPtr oldpmap = FbInstalledMaps[index];
+    ColormapPtr oldpmap;
 
+    MAXSCREENSALLOC_FATAL(FbInstalledMaps);
+    oldpmap = FbInstalledMaps[index];
     if(pmap != oldpmap)
     {
 	/* Uninstall pInstalledMap. No hardware changes required, just
@@ -72,8 +75,10 @@ void
 fbUninstallColormap(ColormapPtr pmap)
 {
     int index = pmap->pScreen->myNum;
-    ColormapPtr curpmap = FbInstalledMaps[index];
+    ColormapPtr curpmap;
 
+    MAXSCREENSALLOC_FATAL(FbInstalledMaps);
+    curpmap = FbInstalledMaps[index];
     if(pmap == curpmap)
     {
 	if (pmap->mid != pmap->pScreen->defColormap)
diff --git a/hw/xfree86/common/xf86Cursor.c b/hw/xfree86/common/xf86Cursor.c
index 6740faf..1bdcaaf 100644
--- a/hw/xfree86/common/xf86Cursor.c
+++ b/hw/xfree86/common/xf86Cursor.c
@@ -77,7 +77,7 @@ static miPointerScreenFuncRec xf86PointerScreenFuncs = {
   NULL
 };
 
-static xf86ScreenLayoutRec xf86ScreenLayout[MAXSCREENS];
+static xf86ScreenLayoutRec *xf86ScreenLayout;
 
 static Bool HardEdges;
 
@@ -572,14 +572,18 @@ FillOutEdge(xf86EdgePtr pEdge, int limit)
 }
 
 /*
- * xf86InitOrigins() can deal with a maximum of 32 screens
- * on 32 bit architectures, 64 on 64 bit architectures.
+ * xf86InitOrigins() used to use a bitmask so that it was limited to 32
+ * screens on a 32-bit architecture, and 64 screens on a 64-bit
+ * architecture.  Instead of using a bitmask, we use an array; instead
+ * of copying screensLeft to prevScreensLeft and comparing to see if
+ * anything changed, we introduce the "changed" variable.  Another way
+ * to implement this function is presented in
+ * Xserver/hw/dmx/dmxcursor.c.
  */
-
 void
 xf86InitOrigins(void)
 {
-    unsigned long screensLeft, prevScreensLeft, mask;
+    int *screensLeft = NULL;
     screenLayoutPtr screen;
     ScreenPtr pScreen;
     int x1, x2, y1, y2, left, right, top, bottom;
@@ -590,19 +594,21 @@ xf86InitOrigins(void)
     /* need to have this set up with a config file option */
     HardEdges = FALSE;
 
-    bzero(xf86ScreenLayout, MAXSCREENS * sizeof(xf86ScreenLayoutRec));
-	
-    screensLeft = prevScreensLeft = (1 << xf86NumScreens) - 1;
+    MAXSCREENSALLOC_FATAL(xf86ScreenLayout);
+    MAXSCREENSALLOC_FATAL(screensLeft);
+    for (i = 0; i < xf86NumScreens; i++)
+        screensLeft[i] = 1;
 
     while(1) {
-	for(mask = screensLeft, i = 0; mask; mask >>= 1, i++) {
-	    if(!(mask & 1L)) continue;
+        int changed = 0;
+        for (i = 0; i < xf86NumScreens; i++) {
+            if (!screensLeft[i]) continue;
 
 	    screen = &xf86ConfigLayout.screens[i];
 
 	    if (screen->refscreen != NULL &&
 		screen->refscreen->screennum >= xf86NumScreens) {
-		screensLeft &= ~(1 << i);
+        ++changed, screensLeft[i] = 0;
 	        xf86Msg(X_WARNING, "Not including screen \"%s\" in origins calculation.\n",
 			screen->screen->id);
 	        continue;
@@ -660,7 +666,7 @@ xf86InitOrigins(void)
 	    case PosAbsolute:
 		dixScreenOrigins[i].x = screen->x;
 		dixScreenOrigins[i].y = screen->y;
-		screensLeft &= ~(1 << i);
+		++changed, screensLeft[i] = 0;
 		break;
 	    case PosRelative:
 		ref = screen->refscreen->screennum;
@@ -668,10 +674,10 @@ xf86InitOrigins(void)
 		    ErrorF("Referenced uninitialized screen in Layout!\n");
 		    break;
 		}
-		if(screensLeft & (1 << ref)) break;
+		if(screensLeft[ref]) break;
 		dixScreenOrigins[i].x = dixScreenOrigins[ref].x + screen->x;
 		dixScreenOrigins[i].y = dixScreenOrigins[ref].y + screen->y;
-		screensLeft &= ~(1 << i);
+		++changed, screensLeft[i] = 0;;
 		break;
 	    case PosRightOf:
 		ref = screen->refscreen->screennum;
@@ -679,12 +685,12 @@ xf86InitOrigins(void)
 		    ErrorF("Referenced uninitialized screen in Layout!\n");
 		    break;
 		}
-		if(screensLeft & (1 << ref)) break;
+		if(screensLeft[ref]) break;
 		pScreen = xf86Screens[ref]->pScreen;
 		dixScreenOrigins[i].x = 
 			dixScreenOrigins[ref].x + pScreen->width;
 		dixScreenOrigins[i].y = dixScreenOrigins[ref].y;
-		screensLeft &= ~(1 << i);
+		++changed, screensLeft[i] = 0;
 		break;
 	    case PosLeftOf:
 		ref = screen->refscreen->screennum;
@@ -692,12 +698,12 @@ xf86InitOrigins(void)
 		    ErrorF("Referenced uninitialized screen in Layout!\n");
 		    break;
 		}
-		if(screensLeft & (1 << ref)) break;
+		if(screensLeft[ref]) break;
 		pScreen = xf86Screens[i]->pScreen;
 		dixScreenOrigins[i].x = 
 			dixScreenOrigins[ref].x - pScreen->width;
 		dixScreenOrigins[i].y = dixScreenOrigins[ref].y;
-		screensLeft &= ~(1 << i);
+		++changed, screensLeft[i] = 0;
 		break;
 	    case PosBelow:
 		ref = screen->refscreen->screennum;
@@ -705,12 +711,12 @@ xf86InitOrigins(void)
 		    ErrorF("Referenced uninitialized screen in Layout!\n");
 		    break;
 		}
-		if(screensLeft & (1 << ref)) break;
+		if(screensLeft[ref]) break;
 		pScreen = xf86Screens[ref]->pScreen;
 		dixScreenOrigins[i].x = dixScreenOrigins[ref].x;
 		dixScreenOrigins[i].y = 
 			dixScreenOrigins[ref].y + pScreen->height;
-		screensLeft &= ~(1 << i);
+		++changed, screensLeft[i] = 0;
 		break;
 	    case PosAbove:
 		ref = screen->refscreen->screennum;
@@ -718,12 +724,12 @@ xf86InitOrigins(void)
 		    ErrorF("Referenced uninitialized screen in Layout!\n");
 		    break;
 		}
-		if(screensLeft & (1 << ref)) break;
+		if(screensLeft[ref]) break;
 		pScreen = xf86Screens[i]->pScreen;
 		dixScreenOrigins[i].x = dixScreenOrigins[ref].x;
 		dixScreenOrigins[i].y = 
 			dixScreenOrigins[ref].y - pScreen->height;
-		screensLeft &= ~(1 << i);
+		++changed, screensLeft[i] = 0;
 		break;
 	    default:
 		ErrorF("Illegal placement keyword in Layout!\n");
@@ -732,21 +738,21 @@ xf86InitOrigins(void)
 
 	}
 
-	if(!screensLeft) break;
-
-	if(screensLeft == prevScreensLeft) {
+    if(!changed) {
+        int n, count;
 	/* All the remaining screens are referencing each other.
 	   Assign a value to one of them and go through again */
-	    i = 0;
-	    while(!((1 << i) & screensLeft)){ i++; }
+        for (i = 0; i < xf86NumScreens; i++)
+            if (screensLeft[i]) break;
+
+        if (i >= xf86NumScreens) break; /* Finished */
 
 	    ref = xf86ConfigLayout.screens[i].refscreen->screennum;
 	    dixScreenOrigins[ref].x = dixScreenOrigins[ref].y = 0;
-	    screensLeft &= ~(1 << ref);
+	    screensLeft[ref] = 0;
 	}
-
-	prevScreensLeft = screensLeft;
     }
+    MAXSCREENSFREE(screensLeft);
 
     /* justify the topmost and leftmost to (0,0) */
     minX = dixScreenOrigins[0].x;
@@ -847,6 +853,7 @@ xf86ReconfigureLayout(void)
 {
     int i;
 
+    MAXSCREEN_ASSERT_INIT();
     for (i = 0; i < MAXSCREENS; i++) {
 	xf86ScreenLayoutPtr sl = &xf86ScreenLayout[i];
 	/* we don't have to zero these, xf86InitOrigins() takes care of that */
diff --git a/hw/xfree86/common/xf86xv.c b/hw/xfree86/common/xf86xv.c
index bdcc4fc..3aaa623 100644
--- a/hw/xfree86/common/xf86xv.c
+++ b/hw/xfree86/common/xf86xv.c
@@ -186,7 +186,7 @@ typedef struct {
    int num;
 } OffscreenImageRec;
 
-static OffscreenImageRec OffscreenImages[MAXSCREENS];
+static OffscreenImageRec *OffscreenImages;
 
 Bool
 xf86XVRegisterOffscreenImages(
@@ -194,6 +194,7 @@ xf86XVRegisterOffscreenImages(
     XF86OffscreenImagePtr images,
     int num
 ){
+    MAXSCREENSALLOC_FATAL(OffscreenImages);
     OffscreenImages[pScreen->myNum].num = num;
     OffscreenImages[pScreen->myNum].images = images;
 
diff --git a/hw/xfree86/dixmods/extmod/xf86dga2.c b/hw/xfree86/dixmods/extmod/xf86dga2.c
index 5367bcc..96732e8 100644
--- a/hw/xfree86/dixmods/extmod/xf86dga2.c
+++ b/hw/xfree86/dixmods/extmod/xf86dga2.c
@@ -27,6 +27,7 @@
 #include "dgaproc.h"
 #include "xf86dgaext.h"
 #include "protocol-versions.h"
+#include "globals.h"
 
 #include <string.h>
 
@@ -57,7 +58,7 @@ static void XDGAResetProc(ExtensionEntry *extEntry);
 
 static void DGAClientStateChange (CallbackListPtr*, pointer, pointer);
 
-static ClientPtr DGAClients[MAXSCREENS];
+static ClientPtr *DGAClients;
 
 unsigned char DGAReqCode = 0;
 int DGAErrorBase;
@@ -93,6 +94,7 @@ XFree86DGAExtensionInit(INITARGS)
 				StandardMinorOpcode))) {
 	int i;
 
+    MAXSCREENSALLOC_FATAL(DGAClients);
 	for(i = 0; i < MAXSCREENS; i++)
 	     DGAClients[i] = NULL;
 
diff --git a/hw/xfree86/os-support/bsd/arm_video.c b/hw/xfree86/os-support/bsd/arm_video.c
index 466a8a0..c68591a 100644
--- a/hw/xfree86/os-support/bsd/arm_video.c
+++ b/hw/xfree86/os-support/bsd/arm_video.c
@@ -533,7 +533,7 @@ xf86DisableIO()
 #define	DEV_MEM_IOBASE	0x43000000
 #endif
 
-static Bool ScreenEnabled[MAXSCREENS];
+static Bool *ScreenEnabled;
 static Bool ExtendedEnabled = FALSE;
 static Bool InitDone = FALSE;
 
@@ -549,7 +549,7 @@ int ScreenNum;
 	struct memAccess *memInfoP;
 	int *Size;
 #endif
-
+    MAXSCREENSALLOC_FATAL(ScreenEnabled);
 	ScreenEnabled[ScreenNum] = TRUE;
 
 	if (ExtendedEnabled)
@@ -635,6 +635,7 @@ int ScreenNum;
         struct memAccess *memInfoP;
 #endif
 
+    MAXSCREENSALLOC_FATAL(ScreenEnabled);
 	ScreenEnabled[ScreenNum] = FALSE;
 
 #ifdef __arm32__
diff --git a/include/cursor.h b/include/cursor.h
index acc95c3..e9a79d2 100644
--- a/include/cursor.h
+++ b/include/cursor.h
@@ -64,7 +64,7 @@ struct _DeviceIntRec;
 typedef struct _Cursor *CursorPtr;
 typedef struct _CursorMetric *CursorMetricPtr;
 
-extern _X_EXPORT int cursorScreenDevPriv[MAXSCREENS];
+extern _X_EXPORT int *cursorScreenDevPriv;
 #define CursorScreenKey(pScreen) (cursorScreenDevPriv + (pScreen)->myNum)
 
 extern _X_EXPORT CursorPtr rootCursor;
diff --git a/include/dixstruct.h b/include/dixstruct.h
index 696b793..2a2317a 100644
--- a/include/dixstruct.h
+++ b/include/dixstruct.h
@@ -101,7 +101,6 @@ typedef struct _Client {
 					 * killed */
     SaveSetElt	*saveSet;
     int         numSaved;
-    void	*unused_screenPrivate[16];
     int         (**requestVector) (
 		ClientPtr /* pClient */);
     CARD32	req_len;		/* length of current request */
diff --git a/include/globals.h b/include/globals.h
index 82e86c3..32e05ac 100644
--- a/include/globals.h
+++ b/include/globals.h
@@ -6,6 +6,11 @@
 
 /* Global X server variables that are visible to mi, dix, os, and ddx */
 
+extern _X_EXPORT int    MAXSCREENS;
+extern _X_EXPORT void   *MaxScreensAlloc(unsigned long size);
+extern _X_EXPORT void   MaxScreensFree(void *object);
+extern _X_EXPORT void   SetMaxScreens(int maxscreens);
+
 extern _X_EXPORT CARD32 defaultScreenSaverTime;
 extern _X_EXPORT CARD32 defaultScreenSaverInterval;
 extern _X_EXPORT CARD32 ScreenSaverTime;
@@ -19,11 +24,11 @@ extern _X_EXPORT char *defaultFontPath;
 extern _X_EXPORT int monitorResolution;
 extern _X_EXPORT int defaultColorVisualClass;
 
-extern _X_EXPORT WindowPtr WindowTable[MAXSCREENS];
+extern _X_EXPORT WindowPtr *WindowTable;
 extern _X_EXPORT int GrabInProgress;
 extern _X_EXPORT Bool noTestExtensions;
 
-extern _X_EXPORT DDXPointRec dixScreenOrigins[MAXSCREENS];
+extern _X_EXPORT DDXPointRec *dixScreenOrigins;
 
 extern _X_EXPORT char *ConnectionInfo;
 
diff --git a/include/inputstr.h b/include/inputstr.h
index de4026c..8f2899b 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -374,7 +374,7 @@ typedef struct {
     ScreenPtr	screen;		/* all others are in Screen 0 coordinates */
     RegionRec   Reg1;	        /* Region 1 for confining motion */
     RegionRec   Reg2;		/* Region 2 for confining virtual motion */
-    WindowPtr   windows[MAXSCREENS];
+    WindowPtr   *windows;
     WindowPtr	confineWin;	/* confine window */ 
 #endif
     /* The window trace information is used at dix/events.c to avoid having
diff --git a/include/misc.h b/include/misc.h
index 62d813e..9da359f 100644
--- a/include/misc.h
+++ b/include/misc.h
@@ -80,9 +80,47 @@ OF THIS SOFTWARE.
 
 #include <stddef.h>
 
-#ifndef MAXSCREENS
-#define MAXSCREENS	16
-#endif
+#define MAXSCREENSDEFAULT 1
+
+/* assert that init has been done */
+#define MAXSCREEN_ASSERT_INIT() do {                                    \
+    MaxScreensFree(MaxScreensAlloc(1)); } while (0)
+
+#define MAXSCREEN_MAKECONSTSTR1(x) #x
+#define MAXSCREEN_MAKECONSTSTR2(x) MAXSCREEN_MAKECONSTSTR1(x)
+
+#define MAXSCREEN_FAILED_TXT "Failed at ["                              \
+   MAXSCREEN_MAKECONSTSTR2(__LINE__) ":" __FILE__ "] to allocate object: "
+
+#define _MAXSCREENSALLOCF(o,size,fatal)                                 \
+    do {                                                                \
+        if (!o) {                                                       \
+            o = MaxScreensAlloc((size) * sizeof(*(o)));                 \
+            if (!o && fatal) FatalError(MAXSCREEN_FAILED_TXT #o);       \
+        }                                                               \
+    } while (0)
+#define _MAXSCREENSALLOCR(o,size,retval)                                \
+    do {                                                                \
+        if (!o) {                                                       \
+            o = MaxScreensAlloc((size) * sizeof(*(o)));                 \
+            if (!o) return retval;                                      \
+        }                                                               \
+    } while (0)
+
+#define MAXSCREENSFREE(o)                                               \
+    do {                                                                \
+        if (o) MaxScreensFree(o);                                       \
+        o = NULL;                                                       \
+    } while (0)
+
+#define MAXSCREENSALLOC(o)              _MAXSCREENSALLOCF(o,MAXSCREENS,  0)
+#define MAXSCREENSALLOC_FATAL(o)        _MAXSCREENSALLOCF(o,MAXSCREENS,  1)
+#define MAXSCREENSALLOC_RETURN(o,r)     _MAXSCREENSALLOCR(o,MAXSCREENS, (r))
+#define MAXSCREENSALLOCPLUSONE(o)       _MAXSCREENSALLOCF(o,MAXSCREENS+1,0)
+#define MAXSCREENSALLOCPLUSONE_FATAL(o) _MAXSCREENSALLOCF(o,MAXSCREENS+1,1)
+#define MAXSCREENSCALLOC(o,m)           _MAXSCREENSALLOCF(o,MAXSCREENS*(m),0)
+#define MAXSCREENSCALLOC_FATAL(o,m)     _MAXSCREENSALLOCF(o,MAXSCREENS*(m),1)
+
 #define MAXCLIENTS	256
 #define MAXEXTENSIONS   128
 #define MAXFORMATS	8
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index c42119d..df64ac1 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -617,7 +617,7 @@ typedef struct _ScreenInfo {
 		formats[MAXFORMATS];
     int		arraySize;
     int		numScreens;
-    ScreenPtr	screens[MAXSCREENS];
+    ScreenPtr	*screens;
     int		unused;
 } ScreenInfo;
 
diff --git a/include/windowstr.h b/include/windowstr.h
index 96bee9b..1c90410 100644
--- a/include/windowstr.h
+++ b/include/windowstr.h
@@ -222,6 +222,6 @@ typedef struct _ScreenSaverStuff {
 #define HasSaverWindow(i)   (savedScreenInfo[i].pWindow != NullWindow)
 
 extern _X_EXPORT int screenIsSaved;
-extern _X_EXPORT ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
+extern _X_EXPORT ScreenSaverStuffRec *savedScreenInfo;
 
 #endif /* WINDOWSTRUCT_H */
diff --git a/mi/micmap.c b/mi/micmap.c
index e832be7..d506e3f 100644
--- a/mi/micmap.c
+++ b/mi/micmap.c
@@ -40,7 +40,7 @@
 #include "globals.h"
 #include "micmap.h"
 
-ColormapPtr miInstalledMaps[MAXSCREENS];
+ColormapPtr *miInstalledMaps;
 
 int
 miListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
@@ -512,6 +512,8 @@ miInitVisuals(VisualPtr *visualp, DepthPtr *depthp, int *nvisualp,
     int		*preferredCVCs, *prefp;
     int		first_depth;
 
+    MAXSCREENSALLOC_RETURN(miInstalledMaps, FALSE);
+
     /* none specified, we'll guess from pixmap formats */
     if (!miVisuals) 
     {
diff --git a/mi/micmap.h b/mi/micmap.h
index 5c8448a..5e12502 100644
--- a/mi/micmap.h
+++ b/mi/micmap.h
@@ -4,7 +4,7 @@
 #ifndef _MICMAP_H_
 #define _MICMAP_H_
 
-extern _X_EXPORT ColormapPtr miInstalledMaps[MAXSCREENS];
+extern _X_EXPORT ColormapPtr *miInstalledMaps;
 
 typedef Bool (* miInitVisualsProcPtr)(VisualPtr *, DepthPtr *, int *, int *,
 					int *, VisualID *, unsigned long, int,
diff --git a/os/utils.c b/os/utils.c
index 127b47b..500855f 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -506,6 +506,7 @@ void UseMsg(void)
     ErrorF("-logo                  enable logo in screen saver\n");
     ErrorF("nologo                 disable logo in screen saver\n");
 #endif
+    ErrorF("-maxscreens int        maximum number of screens available\n");
     ErrorF("-nolisten string       don't listen on protocol\n");
     ErrorF("-noreset               don't reset after last client exists\n");
     ErrorF("-reset                 reset after last client exists\n");
@@ -847,6 +848,19 @@ ProcessCommandLine(int argc, char *argv[])
 	    defaultScreenSaverBlanking = DontPreferBlanking;
 	else if ( strcmp( argv[i], "-wm") == 0)
 	    defaultBackingStore = WhenMapped;
+        else if ( strcmp( argv[i], "-maxscreens") == 0) {
+            if(++i < argc) {
+                int maxscreens = atoi(argv[i]);
+
+                if (maxscreens > 0) {
+                    SetMaxScreens(maxscreens);
+                } else {
+                    UseMsg();
+                }
+            } else {
+                UseMsg();
+            }
+        }
         else if ( strcmp( argv[i], "-wr") == 0)
             whiteRoot = TRUE;
         else if ( strcmp( argv[i], "-maxbigreqsize") == 0) {
diff --git a/render/render.c b/render/render.c
index 2d9e47a..3c29b33 100644
--- a/render/render.c
+++ b/render/render.c
@@ -2693,6 +2693,12 @@ PanoramiXRenderCreatePicture (ClientPtr client)
     if(!(newPict = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes))))
 	return BadAlloc;
     newPict->type = XRT_PICTURE;
+    newPict->info = NULL;
+    MAXSCREENSALLOC(newPict->info);
+    if (!newPict->info) {
+	xfree(newPict);
+	return BadAlloc;
+    }
     newPict->info[0].id = stuff->pid;
     
     if (refDraw->type == XRT_WINDOW &&
@@ -2715,8 +2721,10 @@ PanoramiXRenderCreatePicture (ClientPtr client)
 
     if (result == Success)
 	AddResource(newPict->info[0].id, XRT_PICTURE, newPict);
-    else 
+    else {
+	xfree(newPict->info);
 	xfree(newPict);
+    }
 
     return (result);
 }
-- 
1.6.0.4



More information about the xorg-devel mailing list