]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/dix/main.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / programs / Xserver / dix / main.c
1 /***********************************************************
2
3 Copyright (c) 1987  X Consortium
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of the X Consortium shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from the X Consortium.
25
26
27 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
28
29                         All Rights Reserved
30
31 Permission to use, copy, modify, and distribute this software and its 
32 documentation for any purpose and without fee is hereby granted, 
33 provided that the above copyright notice appear in all copies and that
34 both that copyright notice and this permission notice appear in 
35 supporting documentation, and that the name of Digital not be
36 used in advertising or publicity pertaining to distribution of the
37 software without specific, written prior permission.  
38
39 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45 SOFTWARE.
46
47 ******************************************************************/
48 /* $XConsortium: main.c /main/82 1996/09/28 17:12:09 rws $ */
49 /* $XFree86: xc/programs/Xserver/dix/main.c,v 3.10.2.2 1998/01/22 10:47:08 dawes Exp $ */
50
51 #define NEED_EVENTS
52 #include "X.h"
53 #include "Xproto.h"
54 #include "scrnintstr.h"
55 #include "misc.h"
56 #include "os.h"
57 #include "windowstr.h"
58 #include "resource.h"
59 #include "dixstruct.h"
60 #include "gcstruct.h"
61 #include "extension.h"
62 #include "extnsionst.h"
63 #include "colormap.h"
64 #include "colormapst.h"
65 #include "cursorstr.h"
66 #include "font.h"
67 #include "opaque.h"
68 #include "servermd.h"
69 #include "site.h"
70 #include "dixfont.h"
71 #include "dixevents.h"          /* InitEvents() */
72 #include "dispatch.h"           /* InitProcVectors() */
73
74 extern CARD32 defaultScreenSaverTime;
75 extern CARD32 defaultScreenSaverInterval;
76 extern int defaultScreenSaverBlanking;
77 extern int defaultScreenSaverAllowExposures;
78
79 #ifdef DPMSExtension
80 #include "dpms.h"
81 #endif
82
83 void ddxGiveUp();
84
85 extern int InitClientPrivates(
86 #if NeedFunctionPrototypes
87     ClientPtr /*client*/
88 #endif
89 );
90
91 extern void Dispatch(
92 #if NeedFunctionPrototypes
93     void
94 #endif
95 );
96
97 extern char *display;
98 char *ConnectionInfo;
99 xConnSetupPrefix connSetupPrefix;
100
101 extern WindowPtr *WindowTable;
102 extern FontPtr defaultFont;
103 extern int screenPrivateCount;
104
105 static Bool CreateConnectionBlock(
106 #if NeedFunctionPrototypes
107     void
108 #endif
109 );
110
111 static void FreeScreen(
112 #if NeedFunctionPrototypes
113     ScreenPtr /*pScreen*/
114 #endif
115 );
116
117 PaddingInfo PixmapWidthPaddingInfo[33];
118
119 #ifdef INTERNAL_VS_EXTERNAL_PADDING
120 /* add padding info for 32-bit interface. PutImage and GetImage will
121  * work on 32-bit padding while the rest of the server will work
122  * on 64-bit padding (Alpha).
123  */
124 PaddingInfo PixmapWidthPaddingInfoProto[33];
125 #endif
126
127 int connBlockScreenStart;
128
129 static int restart = 0;
130
131 /*
132  * Dummy entry for EventSwapVector[]
133  */
134 /*ARGSUSED*/
135 void
136 NotImplemented(
137 #if NeedFunctionPrototypes && defined(EVENT_SWAP_PTR)
138         xEvent * from,
139         xEvent * to
140 #endif
141         )
142 {
143     FatalError("Not implemented");
144 }
145
146 /*
147  * Dummy entry for ReplySwapVector[]
148  */
149 /*ARGSUSED*/
150 void
151 ReplyNotSwappd(
152 #if NeedNestedPrototypes
153         ClientPtr pClient ,
154         int size ,
155         void * pbuf
156 #endif
157         )
158 {
159     FatalError("Not implemented");
160 }
161
162 /*
163  * This array encodes the answer to the question "what is the log base 2
164  * of the number of pixels that fit in a scanline pad unit?"
165  * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
166  */
167 static int answer[6][4] = {
168         /* pad   pad   pad     pad*/
169         /*  8     16    32    64 */
170
171         {   3,     4,    5 ,   6 },     /* 1 bit per pixel */
172         {   1,     2,    3 ,   4 },     /* 4 bits per pixel */
173         {   0,     1,    2 ,   3 },     /* 8 bits per pixel */
174         {   ~0,    0,    1 ,   2 },     /* 16 bits per pixel */
175         {   ~0,    ~0,   0 ,   1 },     /* 24 bits per pixel */
176         {   ~0,    ~0,   0 ,   1 }      /* 32 bits per pixel */
177 };
178
179 /*
180  * This array gives the answer to the question "what is the first index for
181  * the answer array above given the number of bits per pixel?"
182  * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
183  */
184 static int indexForBitsPerPixel[ 33 ] = {
185         ~0, 0, ~0, ~0,  /* 1 bit per pixel */
186         1, ~0, ~0, ~0,  /* 4 bits per pixel */
187         2, ~0, ~0, ~0,  /* 8 bits per pixel */
188         ~0,~0, ~0, ~0,
189         3, ~0, ~0, ~0,  /* 16 bits per pixel */
190         ~0,~0, ~0, ~0,
191         4, ~0, ~0, ~0,  /* 24 bits per pixel */
192         ~0,~0, ~0, ~0,
193         5               /* 32 bits per pixel */
194 };
195
196 /*
197  * This array gives the bytesperPixel value for cases where the number
198  * of bits per pixel is a multiple of 8 but not a power of 2.
199  */
200 static int answerBytesPerPixel[ 33 ] = {
201         ~0, 0, ~0, ~0,  /* 1 bit per pixel */
202         0, ~0, ~0, ~0,  /* 4 bits per pixel */
203         0, ~0, ~0, ~0,  /* 8 bits per pixel */
204         ~0,~0, ~0, ~0,
205         0, ~0, ~0, ~0,  /* 16 bits per pixel */
206         ~0,~0, ~0, ~0,
207         3, ~0, ~0, ~0,  /* 24 bits per pixel */
208         ~0,~0, ~0, ~0,
209         0               /* 32 bits per pixel */
210 };
211
212 /*
213  * This array gives the answer to the question "what is the second index for
214  * the answer array above given the number of bits per scanline pad unit?"
215  * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
216  */
217 static int indexForScanlinePad[ 65 ] = {
218         ~0, ~0, ~0, ~0,
219         ~0, ~0, ~0, ~0,
220          0, ~0, ~0, ~0, /* 8 bits per scanline pad unit */
221         ~0, ~0, ~0, ~0,
222          1, ~0, ~0, ~0, /* 16 bits per scanline pad unit */
223         ~0, ~0, ~0, ~0,
224         ~0, ~0, ~0, ~0,
225         ~0, ~0, ~0, ~0,
226          2, ~0, ~0, ~0, /* 32 bits per scanline pad unit */
227         ~0, ~0, ~0, ~0,
228         ~0, ~0, ~0, ~0,
229         ~0, ~0, ~0, ~0,
230         ~0, ~0, ~0, ~0,
231         ~0, ~0, ~0, ~0,
232         ~0, ~0, ~0, ~0,
233         ~0, ~0, ~0, ~0,
234          3              /* 64 bits per scanline pad unit */
235 };
236
237
238 int
239 main(argc, argv)
240     int         argc;
241     char        *argv[];
242 {
243     int         i, j, k;
244     HWEventQueueType    alwaysCheckForInput[2];
245
246     /* Notice if we're restart.  Probably this is because we jumped through
247      * uninitialized pointer */
248     if (restart)
249         FatalError("server restarted. Jumped through uninitialized pointer?\n");
250     else
251         restart = 1;
252
253 #if 0
254     ExpandCommandLine(&argc, &argv);
255 #endif
256
257     /* These are needed by some routines which are called from interrupt
258      * handlers, thus have no direct calling path back to main and thus
259      * can't be passed argc, argv as parameters */
260     argcGlobal = argc;
261     argvGlobal = argv;
262     display = "0";
263     ProcessCommandLine(argc, argv);
264
265     alwaysCheckForInput[0] = 0;
266     alwaysCheckForInput[1] = 1;
267     while(1)
268     {
269         serverGeneration++;
270         ScreenSaverTime = defaultScreenSaverTime;
271         ScreenSaverInterval = defaultScreenSaverInterval;
272         ScreenSaverBlanking = defaultScreenSaverBlanking;
273         ScreenSaverAllowExposures = defaultScreenSaverAllowExposures;
274 #ifdef DPMSExtension
275         DPMSStandbyTime = defaultDPMSStandbyTime;
276         DPMSSuspendTime = defaultDPMSSuspendTime;
277         DPMSOffTime = defaultDPMSOffTime;
278         DPMSEnabled = defaultDPMSEnabled;
279         DPMSPowerLevel = 0;
280 #endif
281         InitBlockAndWakeupHandlers();
282         /* Perform any operating system dependent initializations you'd like */
283         OsInit();               
284         if(serverGeneration == 1)
285         {
286             CreateWellKnownSockets();
287             InitProcVectors();
288             clients = (ClientPtr *)xalloc(MAXCLIENTS * sizeof(ClientPtr));
289             if (!clients)
290                 FatalError("couldn't create client array");
291             for (i=1; i<MAXCLIENTS; i++) 
292                 clients[i] = NullClient;
293             serverClient = (ClientPtr)xalloc(sizeof(ClientRec));
294             if (!serverClient)
295                 FatalError("couldn't create server client");
296             InitClient(serverClient, 0, (pointer)NULL);
297         }
298         else
299             ResetWellKnownSockets ();
300         clients[0] = serverClient;
301         currentMaxClients = 1;
302
303         if (!InitClientResources(serverClient))      /* for root resources */
304             FatalError("couldn't init server resources");
305
306         SetInputCheck(&alwaysCheckForInput[0], &alwaysCheckForInput[1]);
307         screenInfo.arraySize = MAXSCREENS;
308         screenInfo.numScreens = 0;
309         screenInfo.numVideoScreens = -1;
310         WindowTable = (WindowPtr *)xalloc(MAXSCREENS * sizeof(WindowPtr));
311         if (!WindowTable)
312             FatalError("couldn't create root window table");
313
314         /*
315          * Just in case the ddx doesnt supply a format for depth 1 (like qvss).
316          */
317         j = indexForBitsPerPixel[ 1 ];
318         k = indexForScanlinePad[ BITMAP_SCANLINE_PAD ];
319         PixmapWidthPaddingInfo[1].padRoundUp = BITMAP_SCANLINE_PAD-1;
320         PixmapWidthPaddingInfo[1].padPixelsLog2 = answer[j][k];
321         j = indexForBitsPerPixel[8]; /* bits per byte */
322         PixmapWidthPaddingInfo[1].padBytesLog2 = answer[j][k];
323
324 #ifdef INTERNAL_VS_EXTERNAL_PADDING
325         /* Fake out protocol interface to make them believe we support
326          * a different padding than the actual internal padding.
327          */
328         j = indexForBitsPerPixel[ 1 ];
329         k = indexForScanlinePad[ BITMAP_SCANLINE_PAD_PROTO ];
330         PixmapWidthPaddingInfoProto[1].padRoundUp = BITMAP_SCANLINE_PAD_PROTO-1;
331         PixmapWidthPaddingInfoProto[1].padPixelsLog2 = answer[j][k];
332         j = indexForBitsPerPixel[8]; /* bits per byte */
333         PixmapWidthPaddingInfoProto[1].padBytesLog2 = answer[j][k];
334 #endif /* INTERNAL_VS_EXTERNAL_PADDING */
335
336         InitAtoms();
337         InitEvents();
338         InitGlyphCaching();
339         ResetClientPrivates();
340         ResetScreenPrivates();
341         ResetWindowPrivates();
342         ResetGCPrivates();
343 #ifdef PIXPRIV
344         ResetPixmapPrivates();
345 #endif
346         ResetColormapPrivates();
347         ResetFontPrivateIndex();
348         InitCallbackManager();
349         InitOutput(&screenInfo, argc, argv);
350         if (screenInfo.numScreens < 1)
351             FatalError("no screens found");
352         if (screenInfo.numVideoScreens < 0)
353             screenInfo.numVideoScreens = screenInfo.numScreens;
354 #ifdef XPRINT
355         PrinterInitOutput(&screenInfo, argc, argv);
356 #endif
357         InitExtensions(argc, argv);
358         if (!InitClientPrivates(serverClient))
359             FatalError("failed to allocate serverClient devprivates");
360         for (i = 0; i < screenInfo.numScreens; i++)
361         {
362             ScreenPtr pScreen = screenInfo.screens[i];
363             if (!CreateScratchPixmapsForScreen(i))
364                 FatalError("failed to create scratch pixmaps");
365             if (pScreen->CreateScreenResources &&
366                 !(*pScreen->CreateScreenResources)(pScreen))
367                 FatalError("failed to create screen resources");
368             if (!CreateGCperDepth(i))
369                 FatalError("failed to create scratch GCs");
370             if (!CreateDefaultStipple(i))
371                 FatalError("failed to create default stipple");
372             if (!CreateRootWindow(pScreen))
373                 FatalError("failed to create root window");
374         }
375         InitInput(argc, argv);
376         if (InitAndStartDevices() != Success)
377             FatalError("failed to initialize core devices");
378
379         InitFonts();
380         if (SetDefaultFontPath(defaultFontPath) != Success)
381             ErrorF("failed to set default font path '%s'", defaultFontPath);
382         if (!SetDefaultFont(defaultTextFont))
383             FatalError("could not open default font '%s'", defaultTextFont);
384         if (!(rootCursor = CreateRootCursor(defaultCursorFont, 0)))
385             FatalError("could not open default cursor font '%s'",
386                        defaultCursorFont);
387 #ifdef DPMSExtension
388         /* check all screens, looking for DPMS Capabilities */
389         DPMSCapableFlag = DPMSSupported();
390         if (!DPMSCapableFlag)
391             DPMSEnabled = FALSE;
392 #endif
393         for (i = 0; i < screenInfo.numScreens; i++)
394             InitRootWindow(WindowTable[i]);
395         DefineInitialRootWindow(WindowTable[0]);
396
397         if (!CreateConnectionBlock())
398             FatalError("could not create connection block info");
399
400         Dispatch();
401
402         /* Now free up whatever must be freed */
403         if (screenIsSaved == SCREEN_SAVER_ON)
404             SaveScreens(SCREEN_SAVER_OFF, ScreenSaverReset);
405         CloseDownExtensions();
406         FreeAllResources();
407         CloseDownDevices();
408         for (i = screenInfo.numScreens - 1; i >= 0; i--)
409         {
410             FreeScratchPixmapsForScreen(i);
411             FreeGCperDepth(i);
412             FreeDefaultStipple(i);
413             (* screenInfo.screens[i]->CloseScreen)(i, screenInfo.screens[i]);
414             FreeScreen(screenInfo.screens[i]);
415             screenInfo.numScreens = i;
416         }
417         xfree(WindowTable);
418         FreeFonts ();
419         xfree(serverClient->devPrivates);
420
421         if (dispatchException & DE_TERMINATE)
422         {
423             OsCleanup();
424             ddxGiveUp();
425             break;
426         }
427
428         xfree(ConnectionInfo);
429     }
430     return(0);
431 }
432
433 static int padlength[4] = {0, 3, 2, 1};
434
435 static Bool
436 CreateConnectionBlock()
437 {
438     xConnSetup setup;
439     xWindowRoot root;
440     xDepth      depth;
441     xVisualType visual;
442     xPixmapFormat format;
443     unsigned long vid;
444     int i, j, k,
445         lenofblock,
446         sizesofar = 0;
447     char *pBuf;
448
449     
450     /* Leave off the ridBase and ridMask, these must be sent with 
451        connection */
452
453     setup.release = VENDOR_RELEASE;
454     /*
455      * per-server image and bitmap parameters are defined in Xmd.h
456      */
457     setup.imageByteOrder = screenInfo.imageByteOrder;
458
459 #ifdef INTERNAL_VS_EXTERNAL_PADDING
460     if ( screenInfo.bitmapScanlineUnit > 32 )
461         setup.bitmapScanlineUnit  = 32;
462     else
463 #endif 
464         setup.bitmapScanlineUnit  = screenInfo.bitmapScanlineUnit;
465 #ifdef INTERNAL_VS_EXTERNAL_PADDING
466     if ( screenInfo.bitmapScanlinePad > 32 )
467         setup.bitmapScanlinePad = 32;
468     else
469 #endif 
470         setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad;
471
472     setup.bitmapBitOrder = screenInfo.bitmapBitOrder;
473     setup.motionBufferSize = NumMotionEvents();
474     setup.numRoots = screenInfo.numScreens;
475     setup.nbytesVendor = strlen(VENDOR_STRING); 
476     setup.numFormats = screenInfo.numPixmapFormats;
477     setup.maxRequestSize = MAX_REQUEST_SIZE;
478     QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode);
479     
480     lenofblock = sizeof(xConnSetup) + 
481             ((setup.nbytesVendor + 3) & ~3) +
482             (setup.numFormats * sizeof(xPixmapFormat)) +
483             (setup.numRoots * sizeof(xWindowRoot));
484     ConnectionInfo = (char *) xalloc(lenofblock);
485     if (!ConnectionInfo)
486         return FALSE;
487
488     memmove(ConnectionInfo, (char *)&setup, sizeof(xConnSetup));
489     sizesofar = sizeof(xConnSetup);
490     pBuf = ConnectionInfo + sizeof(xConnSetup);
491
492     memmove(pBuf, VENDOR_STRING, (int)setup.nbytesVendor);
493     sizesofar += setup.nbytesVendor;
494     pBuf += setup.nbytesVendor;
495     i = padlength[setup.nbytesVendor & 3];
496     sizesofar += i;
497     while (--i >= 0)
498         *pBuf++ = 0;
499     
500     for (i=0; i<screenInfo.numPixmapFormats; i++)
501     {
502         format.depth = screenInfo.formats[i].depth;
503         format.bitsPerPixel = screenInfo.formats[i].bitsPerPixel;
504 #ifdef INTERNAL_VS_EXTERNAL_PADDING
505         if ( screenInfo.formats[i].scanlinePad > 32 )
506             format.scanLinePad = 32;
507         else
508 #endif
509             format.scanLinePad = screenInfo.formats[i].scanlinePad;
510         memmove(pBuf, (char *)&format, sizeof(xPixmapFormat));
511         pBuf += sizeof(xPixmapFormat);
512         sizesofar += sizeof(xPixmapFormat);
513     }
514
515     connBlockScreenStart = sizesofar;
516     for (i=0; i<screenInfo.numScreens; i++) 
517     {
518         ScreenPtr       pScreen;
519         DepthPtr        pDepth;
520         VisualPtr       pVisual;
521
522         pScreen = screenInfo.screens[i];
523         root.windowId = WindowTable[i]->drawable.id;
524         root.defaultColormap = pScreen->defColormap;
525         root.whitePixel = pScreen->whitePixel;
526         root.blackPixel = pScreen->blackPixel;
527         root.currentInputMask = 0;    /* filled in when sent */
528         root.pixWidth = pScreen->width;
529         root.pixHeight = pScreen->height;
530         root.mmWidth = pScreen->mmWidth;
531         root.mmHeight = pScreen->mmHeight;
532         root.minInstalledMaps = pScreen->minInstalledCmaps;
533         root.maxInstalledMaps = pScreen->maxInstalledCmaps; 
534         root.rootVisualID = pScreen->rootVisual;                
535         root.backingStore = pScreen->backingStoreSupport;
536         root.saveUnders = pScreen->saveUnderSupport != NotUseful;
537         root.rootDepth = pScreen->rootDepth;
538         root.nDepths = pScreen->numDepths;
539         memmove(pBuf, (char *)&root, sizeof(xWindowRoot));
540         sizesofar += sizeof(xWindowRoot);
541         pBuf += sizeof(xWindowRoot);
542
543         pDepth = pScreen->allowedDepths;
544         for(j = 0; j < pScreen->numDepths; j++, pDepth++)
545         {
546             lenofblock += sizeof(xDepth) + 
547                     (pDepth->numVids * sizeof(xVisualType));
548             pBuf = (char *)xrealloc(ConnectionInfo, lenofblock);
549             if (!pBuf)
550             {
551                 xfree(ConnectionInfo);
552                 return FALSE;
553             }
554             ConnectionInfo = pBuf;
555             pBuf += sizesofar;            
556             depth.depth = pDepth->depth;
557             depth.nVisuals = pDepth->numVids;
558             memmove(pBuf, (char *)&depth, sizeof(xDepth));
559             pBuf += sizeof(xDepth);
560             sizesofar += sizeof(xDepth);
561             for(k = 0; k < pDepth->numVids; k++)
562             {
563                 vid = pDepth->vids[k];
564                 for (pVisual = pScreen->visuals;
565                      pVisual->vid != vid;
566                      pVisual++)
567                     ;
568                 visual.visualID = vid;
569                 visual.class = pVisual->class;
570                 visual.bitsPerRGB = pVisual->bitsPerRGBValue;
571                 visual.colormapEntries = pVisual->ColormapEntries;
572                 visual.redMask = pVisual->redMask;
573                 visual.greenMask = pVisual->greenMask;
574                 visual.blueMask = pVisual->blueMask;
575                 memmove(pBuf, (char *)&visual, sizeof(xVisualType));
576                 pBuf += sizeof(xVisualType);
577                 sizesofar += sizeof(xVisualType);
578             }
579         }
580     }
581     connSetupPrefix.success = xTrue;
582     connSetupPrefix.length = lenofblock/4;
583     connSetupPrefix.majorVersion = X_PROTOCOL;
584     connSetupPrefix.minorVersion = X_PROTOCOL_REVISION;
585     return TRUE;
586 }
587
588 /*
589         grow the array of screenRecs if necessary.
590         call the device-supplied initialization procedure 
591 with its screen number, a pointer to its ScreenRec, argc, and argv.
592         return the number of successfully installed screens.
593
594 */
595
596 int
597 #if NeedFunctionPrototypes
598 AddScreen(
599     Bool        (* pfnInit)(
600 #if NeedNestedPrototypes
601         int /*index*/,
602         ScreenPtr /*pScreen*/,
603         int /*argc*/,
604         char ** /*argv*/
605 #endif
606                 ),
607     int argc,
608     char **argv)
609 #else
610 AddScreen(pfnInit, argc, argv)
611     Bool        (* pfnInit)();
612     int argc;
613     char **argv;
614 #endif
615 {
616
617     int i;
618     int scanlinepad, format, depth, bitsPerPixel, j, k;
619     ScreenPtr pScreen;
620 #ifdef DEBUG
621     void        (**jNI) ();
622 #endif /* DEBUG */
623
624     i = screenInfo.numScreens;
625     if (i == MAXSCREENS)
626         return -1;
627
628     pScreen = (ScreenPtr) xalloc(sizeof(ScreenRec));
629     if (!pScreen)
630         return -1;
631
632     pScreen->devPrivates = (DevUnion *)xalloc(screenPrivateCount *
633                                               sizeof(DevUnion));
634     if (!pScreen->devPrivates && screenPrivateCount)
635     {
636         xfree(pScreen);
637         return -1;
638     }
639     pScreen->myNum = i;
640     pScreen->WindowPrivateLen = 0;
641     pScreen->WindowPrivateSizes = (unsigned *)NULL;
642     pScreen->totalWindowSize = sizeof(WindowRec);
643     pScreen->GCPrivateLen = 0;
644     pScreen->GCPrivateSizes = (unsigned *)NULL;
645     pScreen->totalGCSize = sizeof(GC);
646 #ifdef PIXPRIV
647     pScreen->PixmapPrivateLen = 0;
648     pScreen->PixmapPrivateSizes = (unsigned *)NULL;
649     pScreen->totalPixmapSize = BitmapBytePad(sizeof(PixmapRec)*8);
650 #endif
651     pScreen->ClipNotify = 0;    /* for R4 ddx compatibility */
652     pScreen->CreateScreenResources = 0;
653     
654 #ifdef DEBUG
655     for (jNI = &pScreen->QueryBestSize; 
656          jNI < (void (**) ()) &pScreen->SendGraphicsExpose;
657          jNI++)
658         *jNI = NotImplemented;
659 #endif /* DEBUG */
660
661     /*
662      * This loop gets run once for every Screen that gets added,
663      * but thats ok.  If the ddx layer initializes the formats
664      * one at a time calling AddScreen() after each, then each
665      * iteration will make it a little more accurate.  Worst case
666      * we do this loop N * numPixmapFormats where N is # of screens.
667      * Anyway, this must be called after InitOutput and before the
668      * screen init routine is called.
669      */
670     for (format=0; format<screenInfo.numPixmapFormats; format++)
671     {
672         depth = screenInfo.formats[format].depth;
673         bitsPerPixel = screenInfo.formats[format].bitsPerPixel;
674         scanlinepad = screenInfo.formats[format].scanlinePad;
675         j = indexForBitsPerPixel[ bitsPerPixel ];
676         k = indexForScanlinePad[ scanlinepad ];
677         PixmapWidthPaddingInfo[ depth ].padPixelsLog2 = answer[j][k];
678         PixmapWidthPaddingInfo[ depth ].padRoundUp =
679             (scanlinepad/bitsPerPixel) - 1;
680         j = indexForBitsPerPixel[ 8 ]; /* bits per byte */
681         PixmapWidthPaddingInfo[ depth ].padBytesLog2 = answer[j][k];
682         if (answerBytesPerPixel[bitsPerPixel])
683         {
684             PixmapWidthPaddingInfo[ depth ].notPower2 = 1;
685             PixmapWidthPaddingInfo[ depth ].bytesPerPixel =
686                 answerBytesPerPixel[bitsPerPixel];
687         }
688         else
689         {
690             PixmapWidthPaddingInfo[ depth ].notPower2 = 0;
691         }
692
693 #ifdef INTERNAL_VS_EXTERNAL_PADDING
694         /* Fake out protocol interface to make them believe we support
695          * a different padding than the actual internal padding.
696          */
697         j = indexForBitsPerPixel[ bitsPerPixel ];
698         k = indexForScanlinePad[ BITMAP_SCANLINE_PAD_PROTO ];
699         PixmapWidthPaddingInfoProto[ depth ].padPixelsLog2 = answer[j][k];
700         PixmapWidthPaddingInfoProto[ depth ].padRoundUp =
701             (BITMAP_SCANLINE_PAD_PROTO/bitsPerPixel) - 1;
702         j = indexForBitsPerPixel[ 8 ]; /* bits per byte */
703         PixmapWidthPaddingInfoProto[ depth ].padBytesLog2 = answer[j][k];
704         if (answerBytesPerPixel[bitsPerPixel])
705         {
706             PixmapWidthPaddingInfoProto[ depth ].notPower2 = 1;
707             PixmapWidthPaddingInfoProto[ depth ].bytesPerPixel =
708                 answerBytesPerPixel[bitsPerPixel];
709         }
710         else
711         {
712             PixmapWidthPaddingInfoProto[ depth ].notPower2 = 0;
713         }
714 #endif /* INTERNAL_VS_EXTERNAL_PADDING */
715     }
716   
717     /* This is where screen specific stuff gets initialized.  Load the
718        screen structure, call the hardware, whatever.
719        This is also where the default colormap should be allocated and
720        also pixel values for blackPixel, whitePixel, and the cursor
721        Note that InitScreen is NOT allowed to modify argc, argv, or
722        any of the strings pointed to by argv.  They may be passed to
723        multiple screens. 
724     */ 
725     pScreen->rgf = ~0L;  /* there are no scratch GCs yet*/
726     WindowTable[i] = NullWindow;
727     screenInfo.screens[i] = pScreen;
728     screenInfo.numScreens++;
729     if (!(*pfnInit)(i, pScreen, argc, argv))
730     {
731         FreeScreen(pScreen);
732         screenInfo.numScreens--;
733         return -1;
734     }
735     return i;
736 }
737
738 static void
739 FreeScreen(pScreen)
740     ScreenPtr pScreen;
741 {
742     xfree(pScreen->WindowPrivateSizes);
743     xfree(pScreen->GCPrivateSizes);
744 #ifdef PIXPRIV
745     xfree(pScreen->PixmapPrivateSizes);
746 #endif
747     xfree(pScreen->devPrivates);
748     xfree(pScreen);
749 }