e2b32a0748a01d210e19a54da2d62c2bc6f44766
[framework/uifw/xorg/server/xorg-server.git] / hw / xfree86 / common / xf86Helper.c
1 /*
2  * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Except as contained in this notice, the name of the copyright holder(s)
23  * and author(s) shall not be used in advertising or otherwise to promote
24  * the sale, use or other dealings in this Software without prior written
25  * authorization from the copyright holder(s) and author(s).
26  */
27
28 /*
29  * Authors: Dirk Hohndel <hohndel@XFree86.Org>
30  *          David Dawes <dawes@XFree86.Org>
31  *          ... and others
32  *
33  * This file includes the helper functions that the server provides for
34  * different drivers.
35  */
36
37 #ifdef HAVE_XORG_CONFIG_H
38 #include <xorg-config.h>
39 #endif
40
41 #include <X11/X.h>
42 #include "os.h"
43 #include "servermd.h"
44 #include "pixmapstr.h"
45 #include "windowstr.h"
46 #include "propertyst.h"
47 #include "gcstruct.h"
48 #include "loaderProcs.h"
49 #include "xf86.h"
50 #include "xf86Priv.h"
51 #include "xf86_OSlib.h"
52 #include "micmap.h"
53 #include "xf86DDC.h"
54 #include "xf86Xinput.h"
55 #include "xf86InPriv.h"
56 #include "mivalidate.h"
57 #include "xf86Crtc.h"
58
59 /* For xf86GetClocks */
60 #if defined(CSRG_BASED) || defined(__GNU__)
61 #define HAS_SETPRIORITY
62 #include <sys/resource.h>
63 #endif
64
65 static int xf86ScrnInfoPrivateCount = 0;
66
67 /* Add a pointer to a new DriverRec to xf86DriverList */
68
69 void
70 xf86AddDriver(DriverPtr driver, void *module, int flags)
71 {
72     /* Don't add null entries */
73     if (!driver)
74         return;
75
76     if (xf86DriverList == NULL)
77         xf86NumDrivers = 0;
78
79     xf86NumDrivers++;
80     xf86DriverList = xnfrealloc(xf86DriverList,
81                                 xf86NumDrivers * sizeof(DriverPtr));
82     xf86DriverList[xf86NumDrivers - 1] = xnfalloc(sizeof(DriverRec));
83     if (flags & HaveDriverFuncs)
84         *xf86DriverList[xf86NumDrivers - 1] = *driver;
85     else {
86         (void) memset(xf86DriverList[xf86NumDrivers - 1], 0, sizeof(DriverRec));
87         (void) memcpy(xf86DriverList[xf86NumDrivers - 1], driver,
88                       sizeof(DriverRec1));
89
90     }
91     xf86DriverList[xf86NumDrivers - 1]->module = module;
92     xf86DriverList[xf86NumDrivers - 1]->refCount = 0;
93 }
94
95 void
96 xf86DeleteDriver(int drvIndex)
97 {
98     if (xf86DriverList[drvIndex]
99         && (!xf86DriverHasEntities(xf86DriverList[drvIndex]))) {
100         if (xf86DriverList[drvIndex]->module)
101             UnloadModule(xf86DriverList[drvIndex]->module);
102         free(xf86DriverList[drvIndex]);
103         xf86DriverList[drvIndex] = NULL;
104     }
105 }
106
107 /* Add a pointer to a new InputDriverRec to xf86InputDriverList */
108
109 void
110 xf86AddInputDriver(InputDriverPtr driver, void *module, int flags)
111 {
112     /* Don't add null entries */
113     if (!driver)
114         return;
115
116     if (xf86InputDriverList == NULL)
117         xf86NumInputDrivers = 0;
118
119     xf86NumInputDrivers++;
120     xf86InputDriverList = xnfrealloc(xf86InputDriverList,
121                                      xf86NumInputDrivers *
122                                      sizeof(InputDriverPtr));
123     xf86InputDriverList[xf86NumInputDrivers - 1] =
124         xnfalloc(sizeof(InputDriverRec));
125     *xf86InputDriverList[xf86NumInputDrivers - 1] = *driver;
126     xf86InputDriverList[xf86NumInputDrivers - 1]->module = module;
127 }
128
129 void
130 xf86DeleteInputDriver(int drvIndex)
131 {
132     if (xf86InputDriverList[drvIndex] && xf86InputDriverList[drvIndex]->module)
133         UnloadModule(xf86InputDriverList[drvIndex]->module);
134     free(xf86InputDriverList[drvIndex]);
135     xf86InputDriverList[drvIndex] = NULL;
136 }
137
138 InputDriverPtr
139 xf86LookupInputDriver(const char *name)
140 {
141     int i;
142
143     for (i = 0; i < xf86NumInputDrivers; i++) {
144         if (xf86InputDriverList[i] && xf86InputDriverList[i]->driverName &&
145             xf86NameCmp(name, xf86InputDriverList[i]->driverName) == 0)
146             return xf86InputDriverList[i];
147     }
148     return NULL;
149 }
150
151 InputInfoPtr
152 xf86LookupInput(const char *name)
153 {
154     InputInfoPtr p;
155
156     for (p = xf86InputDevs; p != NULL; p = p->next) {
157         if (strcmp(name, p->name) == 0)
158             return p;
159     }
160
161     return NULL;
162 }
163
164 /* Allocate a new ScrnInfoRec in xf86Screens */
165
166 ScrnInfoPtr
167 xf86AllocateScreen(DriverPtr drv, int flags)
168 {
169     int i;
170     ScrnInfoPtr pScrn;
171
172     if (flags & XF86_ALLOCATE_GPU_SCREEN) {
173         if (xf86GPUScreens == NULL)
174             xf86NumGPUScreens = 0;
175         i = xf86NumGPUScreens++;
176         xf86GPUScreens = xnfrealloc(xf86GPUScreens, xf86NumGPUScreens * sizeof(ScrnInfoPtr));
177         xf86GPUScreens[i] = xnfcalloc(sizeof(ScrnInfoRec), 1);
178         pScrn = xf86GPUScreens[i];
179         pScrn->scrnIndex = i + GPU_SCREEN_OFFSET;      /* Changes when a screen is removed */
180         pScrn->is_gpu = TRUE;
181     } else {
182         if (xf86Screens == NULL)
183             xf86NumScreens = 0;
184
185         i = xf86NumScreens++;
186         xf86Screens = xnfrealloc(xf86Screens, xf86NumScreens * sizeof(ScrnInfoPtr));
187         xf86Screens[i] = xnfcalloc(sizeof(ScrnInfoRec), 1);
188         pScrn = xf86Screens[i];
189
190         pScrn->scrnIndex = i;      /* Changes when a screen is removed */
191     }
192
193     pScrn->origIndex = pScrn->scrnIndex;      /* This never changes */
194     pScrn->privates = xnfcalloc(sizeof(DevUnion), xf86ScrnInfoPrivateCount);
195     /*
196      * EnableDisableFBAccess now gets initialized in InitOutput()
197      * pScrn->EnableDisableFBAccess = xf86EnableDisableFBAccess;
198      */
199
200     pScrn->drv = drv;
201     drv->refCount++;
202     pScrn->module = DuplicateModule(drv->module, NULL);
203
204     pScrn->DriverFunc = drv->driverFunc;
205
206     return pScrn;
207 }
208
209 /*
210  * Remove an entry from xf86Screens.  Ideally it should free all allocated
211  * data.  To do this properly may require a driver hook.
212  */
213
214 void
215 xf86DeleteScreen(ScrnInfoPtr pScrn)
216 {
217     int i;
218     int scrnIndex;
219     Bool is_gpu = FALSE;
220
221     if (!pScrn)
222         return;
223
224     if (pScrn->is_gpu) {
225         /* First check if the screen is valid */
226         if (xf86NumGPUScreens == 0 || xf86GPUScreens == NULL)
227             return;
228         is_gpu = TRUE;
229     } else {
230         /* First check if the screen is valid */
231         if (xf86NumScreens == 0 || xf86Screens == NULL)
232             return;
233     }
234
235     scrnIndex = pScrn->scrnIndex;
236     /* If a FreeScreen function is defined, call it here */
237     if (pScrn->FreeScreen != NULL)
238         pScrn->FreeScreen(pScrn);
239
240     while (pScrn->modes)
241         xf86DeleteMode(&pScrn->modes, pScrn->modes);
242
243     while (pScrn->modePool)
244         xf86DeleteMode(&pScrn->modePool, pScrn->modePool);
245
246     xf86OptionListFree(pScrn->options);
247
248     if (pScrn->module)
249         UnloadModule(pScrn->module);
250
251     if (pScrn->drv)
252         pScrn->drv->refCount--;
253
254     free(pScrn->privates);
255
256     xf86ClearEntityListForScreen(pScrn);
257
258     free(pScrn);
259
260     /* Move the other entries down, updating their scrnIndex fields */
261
262     if (is_gpu) {
263         xf86NumGPUScreens--;
264         scrnIndex -= GPU_SCREEN_OFFSET;
265         for (i = scrnIndex; i < xf86NumGPUScreens; i++) {
266             xf86GPUScreens[i] = xf86GPUScreens[i + 1];
267             xf86GPUScreens[i]->scrnIndex = i + GPU_SCREEN_OFFSET;
268             /* Also need to take care of the screen layout settings */
269         }
270     }
271     else {
272         xf86NumScreens--;
273
274         for (i = scrnIndex; i < xf86NumScreens; i++) {
275             xf86Screens[i] = xf86Screens[i + 1];
276             xf86Screens[i]->scrnIndex = i;
277             /* Also need to take care of the screen layout settings */
278         }
279     }
280 }
281
282 /*
283  * Allocate a private in ScrnInfoRec.
284  */
285
286 int
287 xf86AllocateScrnInfoPrivateIndex(void)
288 {
289     int idx, i;
290     ScrnInfoPtr pScr;
291     DevUnion *nprivs;
292
293     idx = xf86ScrnInfoPrivateCount++;
294     for (i = 0; i < xf86NumScreens; i++) {
295         pScr = xf86Screens[i];
296         nprivs = xnfrealloc(pScr->privates,
297                             xf86ScrnInfoPrivateCount * sizeof(DevUnion));
298         /* Zero the new private */
299         memset(&nprivs[idx], 0, sizeof(DevUnion));
300         pScr->privates = nprivs;
301     }
302     for (i = 0; i < xf86NumGPUScreens; i++) {
303         pScr = xf86GPUScreens[i];
304         nprivs = xnfrealloc(pScr->privates,
305                             xf86ScrnInfoPrivateCount * sizeof(DevUnion));
306         /* Zero the new private */
307         memset(&nprivs[idx], 0, sizeof(DevUnion));
308         pScr->privates = nprivs;
309     }
310     return idx;
311 }
312
313 Bool
314 xf86AddPixFormat(ScrnInfoPtr pScrn, int depth, int bpp, int pad)
315 {
316     int i;
317
318     if (pScrn->numFormats >= MAXFORMATS)
319         return FALSE;
320
321     if (bpp <= 0) {
322         if (depth == 1)
323             bpp = 1;
324         else if (depth <= 8)
325             bpp = 8;
326         else if (depth <= 16)
327             bpp = 16;
328         else if (depth <= 32)
329             bpp = 32;
330         else
331             return FALSE;
332     }
333     if (pad <= 0)
334         pad = BITMAP_SCANLINE_PAD;
335
336     i = pScrn->numFormats++;
337     pScrn->formats[i].depth = depth;
338     pScrn->formats[i].bitsPerPixel = bpp;
339     pScrn->formats[i].scanlinePad = pad;
340     return TRUE;
341 }
342
343 /*
344  * Set the depth we are using based on (in the following order of preference):
345  *  - values given on the command line
346  *  - values given in the config file
347  *  - values provided by the driver
348  *  - an overall default when nothing else is given
349  *
350  * Also find a Display subsection matching the depth/bpp found.
351  *
352  * Sets the following ScrnInfoRec fields:
353  *     bitsPerPixel, pixmap24, depth, display, imageByteOrder,
354  *     bitmapScanlinePad, bitmapScanlineUnit, bitmapBitOrder, numFormats,
355  *     formats, fbFormat.
356  */
357
358 /* Can the screen handle 24 bpp pixmaps */
359 #define DO_PIX24(f) ((f & Support24bppFb) || \
360                      ((f & Support32bppFb) && (f & SupportConvert24to32)))
361
362 /* Can the screen handle 32 bpp pixmaps */
363 #define DO_PIX32(f) ((f & Support32bppFb) || \
364                      ((f & Support24bppFb) && (f & SupportConvert32to24)))
365
366 /* Does the screen prefer 32bpp fb for 24bpp pixmaps */
367 #define CHOOSE32FOR24(f) ((f & Support32bppFb) && (f & SupportConvert24to32) \
368                           && (f & PreferConvert24to32))
369
370 /* Does the screen prefer 24bpp fb for 32bpp pixmaps */
371 #define CHOOSE24FOR32(f) ((f & Support24bppFb) && (f & SupportConvert32to24) \
372                           && (f & PreferConvert32to24))
373
374 /* Can the screen handle 32bpp pixmaps for 24bpp fb */
375 #define DO_PIX32FOR24(f) ((f & Support24bppFb) && (f & SupportConvert32to24))
376
377 /* Can the screen handle 24bpp pixmaps for 32bpp fb */
378 #define DO_PIX24FOR32(f) ((f & Support32bppFb) && (f & SupportConvert24to32))
379
380 #ifndef GLOBAL_DEFAULT_DEPTH
381 #define GLOBAL_DEFAULT_DEPTH 24
382 #endif
383
384 Bool
385 xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int dummy, int fbbpp,
386                 int depth24flags)
387 {
388     int i;
389     DispPtr disp;
390     Pix24Flags pix24 = xf86Info.pixmap24;
391     Bool nomatch = FALSE;
392
393     scrp->bitsPerPixel = -1;
394     scrp->depth = -1;
395     scrp->pixmap24 = Pix24DontCare;
396     scrp->bitsPerPixelFrom = X_DEFAULT;
397     scrp->depthFrom = X_DEFAULT;
398
399     if (xf86FbBpp > 0) {
400         scrp->bitsPerPixel = xf86FbBpp;
401         scrp->bitsPerPixelFrom = X_CMDLINE;
402     }
403
404     if (xf86Depth > 0) {
405         scrp->depth = xf86Depth;
406         scrp->depthFrom = X_CMDLINE;
407     }
408
409     if (xf86FbBpp < 0 && xf86Depth < 0) {
410         if (scrp->confScreen->defaultfbbpp > 0) {
411             scrp->bitsPerPixel = scrp->confScreen->defaultfbbpp;
412             scrp->bitsPerPixelFrom = X_CONFIG;
413         }
414         if (scrp->confScreen->defaultdepth > 0) {
415             scrp->depth = scrp->confScreen->defaultdepth;
416             scrp->depthFrom = X_CONFIG;
417         }
418
419         if (scrp->confScreen->defaultfbbpp <= 0 &&
420             scrp->confScreen->defaultdepth <= 0) {
421             /*
422              * Check for DefaultDepth and DefaultFbBpp options in the
423              * Device sections.
424              */
425             GDevPtr device;
426             Bool found = FALSE;
427
428             for (i = 0; i < scrp->numEntities; i++) {
429                 device = xf86GetDevFromEntity(scrp->entityList[i],
430                                               scrp->entityInstanceList[i]);
431                 if (device && device->options) {
432                     if (xf86FindOption(device->options, "DefaultDepth")) {
433                         scrp->depth = xf86SetIntOption(device->options,
434                                                        "DefaultDepth", -1);
435                         scrp->depthFrom = X_CONFIG;
436                         found = TRUE;
437                     }
438                     if (xf86FindOption(device->options, "DefaultFbBpp")) {
439                         scrp->bitsPerPixel = xf86SetIntOption(device->options,
440                                                               "DefaultFbBpp",
441                                                               -1);
442                         scrp->bitsPerPixelFrom = X_CONFIG;
443                         found = TRUE;
444                     }
445                 }
446                 if (found)
447                     break;
448             }
449         }
450     }
451
452     /* If none of these is set, pick a default */
453     if (scrp->bitsPerPixel < 0 && scrp->depth < 0) {
454         if (fbbpp > 0 || depth > 0) {
455             if (fbbpp > 0)
456                 scrp->bitsPerPixel = fbbpp;
457             if (depth > 0)
458                 scrp->depth = depth;
459         }
460         else {
461             scrp->depth = GLOBAL_DEFAULT_DEPTH;
462         }
463     }
464
465     /* If any are not given, determine a default for the others */
466
467     if (scrp->bitsPerPixel < 0) {
468         /* The depth must be set */
469         if (scrp->depth > -1) {
470             if (scrp->depth == 1)
471                 scrp->bitsPerPixel = 1;
472             else if (scrp->depth <= 4)
473                 scrp->bitsPerPixel = 4;
474             else if (scrp->depth <= 8)
475                 scrp->bitsPerPixel = 8;
476             else if (scrp->depth <= 16)
477                 scrp->bitsPerPixel = 16;
478             else if (scrp->depth <= 24) {
479                 /*
480                  * Figure out if a choice is possible based on the depth24
481                  * and pix24 flags.
482                  */
483                 /* Check pix24 first */
484                 if (pix24 != Pix24DontCare) {
485                     if (pix24 == Pix24Use32) {
486                         if (DO_PIX32(depth24flags)) {
487                             if (CHOOSE24FOR32(depth24flags))
488                                 scrp->bitsPerPixel = 24;
489                             else
490                                 scrp->bitsPerPixel = 32;
491                         }
492                         else {
493                             nomatch = TRUE;
494                         }
495                     }
496                     else if (pix24 == Pix24Use24) {
497                         if (DO_PIX24(depth24flags)) {
498                             if (CHOOSE32FOR24(depth24flags))
499                                 scrp->bitsPerPixel = 32;
500                             else
501                                 scrp->bitsPerPixel = 24;
502                         }
503                         else {
504                             nomatch = TRUE;
505                         }
506                     }
507                 }
508                 else {
509                     if (DO_PIX32(depth24flags)) {
510                         if (CHOOSE24FOR32(depth24flags))
511                             scrp->bitsPerPixel = 24;
512                         else
513                             scrp->bitsPerPixel = 32;
514                     }
515                     else if (DO_PIX24(depth24flags)) {
516                         if (CHOOSE32FOR24(depth24flags))
517                             scrp->bitsPerPixel = 32;
518                         else
519                             scrp->bitsPerPixel = 24;
520                     }
521                 }
522             }
523             else if (scrp->depth <= 32)
524                 scrp->bitsPerPixel = 32;
525             else {
526                 xf86DrvMsg(scrp->scrnIndex, X_ERROR,
527                            "Specified depth (%d) is greater than 32\n",
528                            scrp->depth);
529                 return FALSE;
530             }
531         }
532         else {
533             xf86DrvMsg(scrp->scrnIndex, X_ERROR,
534                        "xf86SetDepthBpp: internal error: depth and fbbpp"
535                        " are both not set\n");
536             return FALSE;
537         }
538         if (scrp->bitsPerPixel < 0) {
539             if (nomatch)
540                 xf86DrvMsg(scrp->scrnIndex, X_ERROR,
541                            "Driver can't support depth 24 pixmap format (%d)\n",
542                            PIX24TOBPP(pix24));
543             else if ((depth24flags & (Support24bppFb | Support32bppFb)) ==
544                      NoDepth24Support)
545                 xf86DrvMsg(scrp->scrnIndex, X_ERROR,
546                            "Driver can't support depth 24\n");
547             else
548                 xf86DrvMsg(scrp->scrnIndex, X_ERROR,
549                            "Can't find fbbpp for depth 24\n");
550             return FALSE;
551         }
552         scrp->bitsPerPixelFrom = X_PROBED;
553     }
554
555     if (scrp->depth <= 0) {
556         /* bitsPerPixel is already set */
557         switch (scrp->bitsPerPixel) {
558         case 32:
559             scrp->depth = 24;
560             break;
561         default:
562             /* 1, 4, 8, 16 and 24 */
563             scrp->depth = scrp->bitsPerPixel;
564             break;
565         }
566         scrp->depthFrom = X_PROBED;
567     }
568
569     /* Sanity checks */
570     if (scrp->depth < 1 || scrp->depth > 32) {
571         xf86DrvMsg(scrp->scrnIndex, X_ERROR,
572                    "Specified depth (%d) is not in the range 1-32\n",
573                    scrp->depth);
574         return FALSE;
575     }
576     switch (scrp->bitsPerPixel) {
577     case 1:
578     case 4:
579     case 8:
580     case 16:
581     case 24:
582     case 32:
583         break;
584     default:
585         xf86DrvMsg(scrp->scrnIndex, X_ERROR,
586                    "Specified fbbpp (%d) is not a permitted value\n",
587                    scrp->bitsPerPixel);
588         return FALSE;
589     }
590     if (scrp->depth > scrp->bitsPerPixel) {
591         xf86DrvMsg(scrp->scrnIndex, X_ERROR,
592                    "Specified depth (%d) is greater than the fbbpp (%d)\n",
593                    scrp->depth, scrp->bitsPerPixel);
594         return FALSE;
595     }
596
597     /* set scrp->pixmap24 if the driver isn't flexible */
598     if (scrp->bitsPerPixel == 24 && !DO_PIX32FOR24(depth24flags)) {
599         scrp->pixmap24 = Pix24Use24;
600     }
601     if (scrp->bitsPerPixel == 32 && !DO_PIX24FOR32(depth24flags)) {
602         scrp->pixmap24 = Pix24Use32;
603     }
604
605     /*
606      * Find the Display subsection matching the depth/fbbpp and initialise
607      * scrp->display with it.
608      */
609     for (i = 0, disp = scrp->confScreen->displays;
610          i < scrp->confScreen->numdisplays; i++, disp++) {
611         if ((disp->depth == scrp->depth && disp->fbbpp == scrp->bitsPerPixel)
612             || (disp->depth == scrp->depth && disp->fbbpp <= 0)
613             || (disp->fbbpp == scrp->bitsPerPixel && disp->depth <= 0)) {
614             scrp->display = disp;
615             break;
616         }
617     }
618
619     /*
620      * If an exact match can't be found, see if there is one with no
621      * depth or fbbpp specified.
622      */
623     if (i == scrp->confScreen->numdisplays) {
624         for (i = 0, disp = scrp->confScreen->displays;
625              i < scrp->confScreen->numdisplays; i++, disp++) {
626             if (disp->depth <= 0 && disp->fbbpp <= 0) {
627                 scrp->display = disp;
628                 break;
629             }
630         }
631     }
632
633     /*
634      * If all else fails, create a default one.
635      */
636     if (i == scrp->confScreen->numdisplays) {
637         scrp->confScreen->numdisplays++;
638         scrp->confScreen->displays =
639             xnfrealloc(scrp->confScreen->displays,
640                        scrp->confScreen->numdisplays * sizeof(DispRec));
641         xf86DrvMsg(scrp->scrnIndex, X_INFO,
642                    "Creating default Display subsection in Screen section\n"
643                    "\t\"%s\" for depth/fbbpp %d/%d\n",
644                    scrp->confScreen->id, scrp->depth, scrp->bitsPerPixel);
645         memset(&scrp->confScreen->displays[i], 0, sizeof(DispRec));
646         scrp->confScreen->displays[i].blackColour.red = -1;
647         scrp->confScreen->displays[i].blackColour.green = -1;
648         scrp->confScreen->displays[i].blackColour.blue = -1;
649         scrp->confScreen->displays[i].whiteColour.red = -1;
650         scrp->confScreen->displays[i].whiteColour.green = -1;
651         scrp->confScreen->displays[i].whiteColour.blue = -1;
652         scrp->confScreen->displays[i].defaultVisual = -1;
653         scrp->confScreen->displays[i].modes = xnfalloc(sizeof(char *));
654         scrp->confScreen->displays[i].modes[0] = NULL;
655         scrp->confScreen->displays[i].depth = depth;
656         scrp->confScreen->displays[i].fbbpp = fbbpp;
657         scrp->display = &scrp->confScreen->displays[i];
658     }
659
660     /*
661      * Setup defaults for the display-wide attributes the framebuffer will
662      * need.  These defaults should eventually be set globally, and not
663      * dependent on the screens.
664      */
665     scrp->imageByteOrder = IMAGE_BYTE_ORDER;
666     scrp->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
667     if (scrp->depth < 8) {
668         /* Planar modes need these settings */
669         scrp->bitmapScanlineUnit = 8;
670         scrp->bitmapBitOrder = MSBFirst;
671     }
672     else {
673         scrp->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
674         scrp->bitmapBitOrder = BITMAP_BIT_ORDER;
675     }
676
677     /*
678      * If an unusual depth is required, add it to scrp->formats.  The formats
679      * for the common depths are handled globally in InitOutput
680      */
681     switch (scrp->depth) {
682     case 1:
683     case 4:
684     case 8:
685     case 15:
686     case 16:
687     case 24:
688         /* Common depths.  Nothing to do for them */
689         break;
690     default:
691         if (!xf86AddPixFormat(scrp, scrp->depth, 0, 0)) {
692             xf86DrvMsg(scrp->scrnIndex, X_ERROR,
693                        "Can't add pixmap format for depth %d\n", scrp->depth);
694             return FALSE;
695         }
696     }
697
698     /* Initialise the framebuffer format for this screen */
699     scrp->fbFormat.depth = scrp->depth;
700     scrp->fbFormat.bitsPerPixel = scrp->bitsPerPixel;
701     scrp->fbFormat.scanlinePad = BITMAP_SCANLINE_PAD;
702
703     return TRUE;
704 }
705
706 /*
707  * Print out the selected depth and bpp.
708  */
709 void
710 xf86PrintDepthBpp(ScrnInfoPtr scrp)
711 {
712     xf86DrvMsg(scrp->scrnIndex, scrp->depthFrom, "Depth %d, ", scrp->depth);
713     xf86Msg(scrp->bitsPerPixelFrom, "framebuffer bpp %d\n", scrp->bitsPerPixel);
714 }
715
716 /*
717  * xf86SetWeight sets scrp->weight, scrp->mask, scrp->offset, and for depths
718  * greater than MAX_PSEUDO_DEPTH also scrp->rgbBits.
719  */
720 Bool
721 xf86SetWeight(ScrnInfoPtr scrp, rgb weight, rgb mask)
722 {
723     MessageType weightFrom = X_DEFAULT;
724
725     scrp->weight.red = 0;
726     scrp->weight.green = 0;
727     scrp->weight.blue = 0;
728
729     if (xf86Weight.red > 0 && xf86Weight.green > 0 && xf86Weight.blue > 0) {
730         scrp->weight = xf86Weight;
731         weightFrom = X_CMDLINE;
732     }
733     else if (scrp->display->weight.red > 0 && scrp->display->weight.green > 0
734              && scrp->display->weight.blue > 0) {
735         scrp->weight = scrp->display->weight;
736         weightFrom = X_CONFIG;
737     }
738     else if (weight.red > 0 && weight.green > 0 && weight.blue > 0) {
739         scrp->weight = weight;
740     }
741     else {
742         switch (scrp->depth) {
743         case 1:
744         case 4:
745         case 8:
746             scrp->weight.red = scrp->weight.green =
747                 scrp->weight.blue = scrp->rgbBits;
748             break;
749         case 15:
750             scrp->weight.red = scrp->weight.green = scrp->weight.blue = 5;
751             break;
752         case 16:
753             scrp->weight.red = scrp->weight.blue = 5;
754             scrp->weight.green = 6;
755             break;
756         case 18:
757             scrp->weight.red = scrp->weight.green = scrp->weight.blue = 6;
758             break;
759         case 24:
760             scrp->weight.red = scrp->weight.green = scrp->weight.blue = 8;
761             break;
762         case 30:
763             scrp->weight.red = scrp->weight.green = scrp->weight.blue = 10;
764             break;
765         }
766     }
767
768     if (scrp->weight.red)
769         xf86DrvMsg(scrp->scrnIndex, weightFrom, "RGB weight %d%d%d\n",
770                    (int) scrp->weight.red, (int) scrp->weight.green,
771                    (int) scrp->weight.blue);
772
773     if (scrp->depth > MAX_PSEUDO_DEPTH &&
774         (scrp->depth != scrp->weight.red + scrp->weight.green +
775          scrp->weight.blue)) {
776         xf86DrvMsg(scrp->scrnIndex, X_ERROR,
777                    "Weight given (%d%d%d) is inconsistent with the "
778                    "depth (%d)\n",
779                    (int) scrp->weight.red, (int) scrp->weight.green,
780                    (int) scrp->weight.blue, scrp->depth);
781         return FALSE;
782     }
783     if (scrp->depth > MAX_PSEUDO_DEPTH && scrp->weight.red) {
784         /*
785          * XXX Does this even mean anything for TrueColor visuals?
786          * If not, we shouldn't even be setting it here.  However, this
787          * matches the behaviour of 3.x versions of XFree86.
788          */
789         scrp->rgbBits = scrp->weight.red;
790         if (scrp->weight.green > scrp->rgbBits)
791             scrp->rgbBits = scrp->weight.green;
792         if (scrp->weight.blue > scrp->rgbBits)
793             scrp->rgbBits = scrp->weight.blue;
794     }
795
796     /* Set the mask and offsets */
797     if (mask.red == 0 || mask.green == 0 || mask.blue == 0) {
798         /* Default to a setting common to PC hardware */
799         scrp->offset.red = scrp->weight.green + scrp->weight.blue;
800         scrp->offset.green = scrp->weight.blue;
801         scrp->offset.blue = 0;
802         scrp->mask.red = ((1 << scrp->weight.red) - 1) << scrp->offset.red;
803         scrp->mask.green = ((1 << scrp->weight.green) - 1)
804             << scrp->offset.green;
805         scrp->mask.blue = (1 << scrp->weight.blue) - 1;
806     }
807     else {
808         /* Initialise to the values passed */
809         scrp->mask.red = mask.red;
810         scrp->mask.green = mask.green;
811         scrp->mask.blue = mask.blue;
812         scrp->offset.red = ffs(mask.red);
813         scrp->offset.green = ffs(mask.green);
814         scrp->offset.blue = ffs(mask.blue);
815     }
816     return TRUE;
817 }
818
819 Bool
820 xf86SetDefaultVisual(ScrnInfoPtr scrp, int visual)
821 {
822     MessageType visualFrom = X_DEFAULT;
823
824     if (defaultColorVisualClass >= 0) {
825         scrp->defaultVisual = defaultColorVisualClass;
826         visualFrom = X_CMDLINE;
827     }
828     else if (scrp->display->defaultVisual >= 0) {
829         scrp->defaultVisual = scrp->display->defaultVisual;
830         visualFrom = X_CONFIG;
831     }
832     else if (visual >= 0) {
833         scrp->defaultVisual = visual;
834     }
835     else {
836         if (scrp->depth == 1)
837             scrp->defaultVisual = StaticGray;
838         else if (scrp->depth == 4)
839             scrp->defaultVisual = StaticColor;
840         else if (scrp->depth <= MAX_PSEUDO_DEPTH)
841             scrp->defaultVisual = PseudoColor;
842         else
843             scrp->defaultVisual = TrueColor;
844     }
845     switch (scrp->defaultVisual) {
846     case StaticGray:
847     case GrayScale:
848     case StaticColor:
849     case PseudoColor:
850     case TrueColor:
851     case DirectColor:
852         xf86DrvMsg(scrp->scrnIndex, visualFrom, "Default visual is %s\n",
853                    xf86VisualNames[scrp->defaultVisual]);
854         return TRUE;
855     default:
856
857         xf86DrvMsg(scrp->scrnIndex, X_ERROR,
858                    "Invalid default visual class (%d)\n", scrp->defaultVisual);
859         return FALSE;
860     }
861 }
862
863 #define TEST_GAMMA(g) \
864         (g).red > GAMMA_ZERO || (g).green > GAMMA_ZERO || (g).blue > GAMMA_ZERO
865
866 #define SET_GAMMA(g) \
867         (g) > GAMMA_ZERO ? (g) : 1.0
868
869 Bool
870 xf86SetGamma(ScrnInfoPtr scrp, Gamma gamma)
871 {
872     MessageType from = X_DEFAULT;
873
874 #if 0
875     xf86MonPtr DDC = (xf86MonPtr) (scrp->monitor->DDC);
876 #endif
877     if (TEST_GAMMA(xf86Gamma)) {
878         from = X_CMDLINE;
879         scrp->gamma.red = SET_GAMMA(xf86Gamma.red);
880         scrp->gamma.green = SET_GAMMA(xf86Gamma.green);
881         scrp->gamma.blue = SET_GAMMA(xf86Gamma.blue);
882     }
883     else if (TEST_GAMMA(scrp->monitor->gamma)) {
884         from = X_CONFIG;
885         scrp->gamma.red = SET_GAMMA(scrp->monitor->gamma.red);
886         scrp->gamma.green = SET_GAMMA(scrp->monitor->gamma.green);
887         scrp->gamma.blue = SET_GAMMA(scrp->monitor->gamma.blue);
888 #if 0
889     }
890     else if (DDC && DDC->features.gamma > GAMMA_ZERO) {
891         from = X_PROBED;
892         scrp->gamma.red = SET_GAMMA(DDC->features.gamma);
893         scrp->gamma.green = SET_GAMMA(DDC->features.gamma);
894         scrp->gamma.blue = SET_GAMMA(DDC->features.gamma);
895         /* EDID structure version 2 gives optional seperate red, green & blue gamma values
896          * in bytes 0x57-0x59 */
897 #endif
898     }
899     else if (TEST_GAMMA(gamma)) {
900         scrp->gamma.red = SET_GAMMA(gamma.red);
901         scrp->gamma.green = SET_GAMMA(gamma.green);
902         scrp->gamma.blue = SET_GAMMA(gamma.blue);
903     }
904     else {
905         scrp->gamma.red = 1.0;
906         scrp->gamma.green = 1.0;
907         scrp->gamma.blue = 1.0;
908     }
909     /* Pretend we succeeded if we support better a gamma system.
910      * This avoids a confusing message.
911      */
912     if (xf86_crtc_supports_gamma(scrp))
913         return TRUE;
914     xf86DrvMsg(scrp->scrnIndex, from,
915                "Using gamma correction (%.1f, %.1f, %.1f)\n",
916                scrp->gamma.red, scrp->gamma.green, scrp->gamma.blue);
917
918     return TRUE;
919 }
920
921 #undef TEST_GAMMA
922 #undef SET_GAMMA
923
924 /*
925  * Set the DPI from the command line option.  XXX should allow it to be
926  * calculated from the widthmm/heightmm values.
927  */
928
929 #undef MMPERINCH
930 #define MMPERINCH 25.4
931
932 void
933 xf86SetDpi(ScrnInfoPtr pScrn, int x, int y)
934 {
935     MessageType from = X_DEFAULT;
936     xf86MonPtr DDC = (xf86MonPtr) (pScrn->monitor->DDC);
937     int ddcWidthmm, ddcHeightmm;
938     int widthErr, heightErr;
939
940     /* XXX Maybe there is no need for widthmm/heightmm in ScrnInfoRec */
941     pScrn->widthmm = pScrn->monitor->widthmm;
942     pScrn->heightmm = pScrn->monitor->heightmm;
943
944     if (DDC && (DDC->features.hsize > 0 && DDC->features.vsize > 0)) {
945         /* DDC gives display size in mm for individual modes,
946          * but cm for monitor
947          */
948         ddcWidthmm = DDC->features.hsize * 10;  /* 10mm in 1cm */
949         ddcHeightmm = DDC->features.vsize * 10; /* 10mm in 1cm */
950     }
951     else {
952         ddcWidthmm = ddcHeightmm = 0;
953     }
954
955     if (monitorResolution > 0) {
956         pScrn->xDpi = monitorResolution;
957         pScrn->yDpi = monitorResolution;
958         from = X_CMDLINE;
959     }
960     else if (pScrn->widthmm > 0 || pScrn->heightmm > 0) {
961         from = X_CONFIG;
962         if (pScrn->widthmm > 0) {
963             pScrn->xDpi =
964                 (int) ((double) pScrn->virtualX * MMPERINCH / pScrn->widthmm);
965         }
966         if (pScrn->heightmm > 0) {
967             pScrn->yDpi =
968                 (int) ((double) pScrn->virtualY * MMPERINCH / pScrn->heightmm);
969         }
970         if (pScrn->xDpi > 0 && pScrn->yDpi <= 0)
971             pScrn->yDpi = pScrn->xDpi;
972         if (pScrn->yDpi > 0 && pScrn->xDpi <= 0)
973             pScrn->xDpi = pScrn->yDpi;
974         xf86DrvMsg(pScrn->scrnIndex, from, "Display dimensions: (%d, %d) mm\n",
975                    pScrn->widthmm, pScrn->heightmm);
976
977         /* Warn if config and probe disagree about display size */
978         if (ddcWidthmm && ddcHeightmm) {
979             if (pScrn->widthmm > 0) {
980                 widthErr = abs(ddcWidthmm - pScrn->widthmm);
981             }
982             else {
983                 widthErr = 0;
984             }
985             if (pScrn->heightmm > 0) {
986                 heightErr = abs(ddcHeightmm - pScrn->heightmm);
987             }
988             else {
989                 heightErr = 0;
990             }
991             if (widthErr > 10 || heightErr > 10) {
992                 /* Should include config file name for monitor here */
993                 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
994                            "Probed monitor is %dx%d mm, using Displaysize %dx%d mm\n",
995                            ddcWidthmm, ddcHeightmm, pScrn->widthmm,
996                            pScrn->heightmm);
997             }
998         }
999     }
1000     else if (ddcWidthmm && ddcHeightmm) {
1001         from = X_PROBED;
1002         xf86DrvMsg(pScrn->scrnIndex, from, "Display dimensions: (%d, %d) mm\n",
1003                    ddcWidthmm, ddcHeightmm);
1004         pScrn->widthmm = ddcWidthmm;
1005         pScrn->heightmm = ddcHeightmm;
1006         if (pScrn->widthmm > 0) {
1007             pScrn->xDpi =
1008                 (int) ((double) pScrn->virtualX * MMPERINCH / pScrn->widthmm);
1009         }
1010         if (pScrn->heightmm > 0) {
1011             pScrn->yDpi =
1012                 (int) ((double) pScrn->virtualY * MMPERINCH / pScrn->heightmm);
1013         }
1014         if (pScrn->xDpi > 0 && pScrn->yDpi <= 0)
1015             pScrn->yDpi = pScrn->xDpi;
1016         if (pScrn->yDpi > 0 && pScrn->xDpi <= 0)
1017             pScrn->xDpi = pScrn->yDpi;
1018     }
1019     else {
1020         if (x > 0)
1021             pScrn->xDpi = x;
1022         else
1023             pScrn->xDpi = DEFAULT_DPI;
1024         if (y > 0)
1025             pScrn->yDpi = y;
1026         else
1027             pScrn->yDpi = DEFAULT_DPI;
1028     }
1029     xf86DrvMsg(pScrn->scrnIndex, from, "DPI set to (%d, %d)\n",
1030                pScrn->xDpi, pScrn->yDpi);
1031 }
1032
1033 #undef MMPERINCH
1034
1035 void
1036 xf86SetBlackWhitePixels(ScreenPtr pScreen)
1037 {
1038     if (xf86FlipPixels) {
1039         pScreen->whitePixel = 0;
1040         pScreen->blackPixel = 1;
1041     }
1042     else {
1043         pScreen->whitePixel = 1;
1044         pScreen->blackPixel = 0;
1045     }
1046 }
1047
1048 /*
1049  * Function to enable/disable access to the frame buffer
1050  *
1051  * This is used when VT switching and when entering/leaving DGA direct mode.
1052  *
1053  * This has been rewritten again to eliminate the saved pixmap.  The
1054  * devPrivate field in the screen pixmap is set to NULL to catch code
1055  * accidentally referencing the frame buffer while the X server is not
1056  * supposed to touch it.
1057  *
1058  * Here, we exchange the pixmap private data, rather than the pixmaps
1059  * themselves to avoid having to find and change any references to the screen
1060  * pixmap such as GC's, window privates etc.  This also means that this code
1061  * does not need to know exactly how the pixmap pixels are accessed.  Further,
1062  * this exchange is >not< done through the screen's ModifyPixmapHeader()
1063  * vector.  This means the called frame buffer code layers can determine
1064  * whether they are switched in or out by keeping track of the root pixmap's
1065  * private data, and therefore don't need to access pScrnInfo->vtSema.
1066  */
1067 void
1068 xf86EnableDisableFBAccess(ScrnInfoPtr pScrnInfo, Bool enable)
1069 {
1070     ScreenPtr pScreen = pScrnInfo->pScreen;
1071
1072     if (enable) {
1073         /*
1074          * Restore all of the clip lists on the screen
1075          */
1076         if (!xf86Resetting)
1077             SetRootClip(pScreen, TRUE);
1078
1079     }
1080     else {
1081         /*
1082          * Empty all of the clip lists on the screen
1083          */
1084         SetRootClip(pScreen, FALSE);
1085     }
1086 }
1087
1088 /* Print driver messages in the standard format of
1089    (<type>) <screen name>(<screen index>): <message> */
1090 void
1091 xf86VDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
1092                 va_list args)
1093 {
1094     /* Prefix the scrnIndex name to the format string. */
1095     if (scrnIndex >= 0 && scrnIndex < xf86NumScreens &&
1096         xf86Screens[scrnIndex]->name)
1097         LogHdrMessageVerb(type, verb, format, args, "%s(%d): ",
1098                           xf86Screens[scrnIndex]->name, scrnIndex);
1099     else if (scrnIndex >= GPU_SCREEN_OFFSET &&
1100              scrnIndex < GPU_SCREEN_OFFSET + xf86NumGPUScreens &&
1101              xf86GPUScreens[scrnIndex - GPU_SCREEN_OFFSET]->name)
1102         LogHdrMessageVerb(type, verb, format, args, "%s(G%d): ",
1103                           xf86GPUScreens[scrnIndex - GPU_SCREEN_OFFSET]->name, scrnIndex - GPU_SCREEN_OFFSET);
1104     else
1105         LogVMessageVerb(type, verb, format, args);
1106 }
1107
1108 /* Print driver messages, with verbose level specified directly */
1109 void
1110 xf86DrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
1111                ...)
1112 {
1113     va_list ap;
1114
1115     va_start(ap, format);
1116     xf86VDrvMsgVerb(scrnIndex, type, verb, format, ap);
1117     va_end(ap);
1118 }
1119
1120 /* Print driver messages, with verbose level of 1 (default) */
1121 void
1122 xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...)
1123 {
1124     va_list ap;
1125
1126     va_start(ap, format);
1127     xf86VDrvMsgVerb(scrnIndex, type, 1, format, ap);
1128     va_end(ap);
1129 }
1130
1131 /* Print input driver messages in the standard format of
1132    (<type>) <driver>: <device name>: <message> */
1133 void
1134 xf86VIDrvMsgVerb(InputInfoPtr dev, MessageType type, int verb,
1135                  const char *format, va_list args)
1136 {
1137     const char *driverName = NULL;
1138     const char *deviceName = NULL;
1139
1140     /* Prefix driver and device names to formatted message. */
1141     if (dev) {
1142         deviceName = dev->name;
1143         if (dev->drv)
1144             driverName = dev->drv->driverName;
1145     }
1146
1147     LogHdrMessageVerb(type, verb, format, args, "%s: %s: ", driverName,
1148                       deviceName);
1149 }
1150
1151 /* Print input driver message, with verbose level specified directly */
1152 void
1153 xf86IDrvMsgVerb(InputInfoPtr dev, MessageType type, int verb,
1154                 const char *format, ...)
1155 {
1156     va_list ap;
1157
1158     va_start(ap, format);
1159     xf86VIDrvMsgVerb(dev, type, verb, format, ap);
1160     va_end(ap);
1161 }
1162
1163 /* Print input driver messages, with verbose level of 1 (default) */
1164 void
1165 xf86IDrvMsg(InputInfoPtr dev, MessageType type, const char *format, ...)
1166 {
1167     va_list ap;
1168
1169     va_start(ap, format);
1170     xf86VIDrvMsgVerb(dev, type, 1, format, ap);
1171     va_end(ap);
1172 }
1173
1174 /* Print non-driver messages with verbose level specified directly */
1175 void
1176 xf86MsgVerb(MessageType type, int verb, const char *format, ...)
1177 {
1178     va_list ap;
1179
1180     va_start(ap, format);
1181     LogVMessageVerb(type, verb, format, ap);
1182     va_end(ap);
1183 }
1184
1185 /* Print non-driver messages with verbose level of 1 (default) */
1186 void
1187 xf86Msg(MessageType type, const char *format, ...)
1188 {
1189     va_list ap;
1190
1191     va_start(ap, format);
1192     LogVMessageVerb(type, 1, format, ap);
1193     va_end(ap);
1194 }
1195
1196 /* Just like ErrorF, but with the verbose level checked */
1197 void
1198 xf86ErrorFVerb(int verb, const char *format, ...)
1199 {
1200     va_list ap;
1201
1202     va_start(ap, format);
1203     if (xf86Verbose >= verb || xf86LogVerbose >= verb)
1204         LogVWrite(verb, format, ap);
1205     va_end(ap);
1206 }
1207
1208 /* Like xf86ErrorFVerb, but with an implied verbose level of 1 */
1209 void
1210 xf86ErrorF(const char *format, ...)
1211 {
1212     va_list ap;
1213
1214     va_start(ap, format);
1215     if (xf86Verbose >= 1 || xf86LogVerbose >= 1)
1216         LogVWrite(1, format, ap);
1217     va_end(ap);
1218 }
1219
1220 /* Note temporarily modifies the passed in buffer! */
1221 static void xf86_mkdir_p(char *path)
1222 {
1223     char *sep = path;
1224
1225     while ((sep = strchr(sep + 1, '/'))) {
1226         *sep = 0;
1227         (void)mkdir(path, 0777);
1228         *sep = '/';
1229     }
1230     (void)mkdir(path, 0777);
1231 }
1232
1233 void
1234 xf86LogInit(void)
1235 {
1236     char *env, *lf = NULL;
1237     char buf[PATH_MAX];
1238
1239 #define LOGSUFFIX ".log"
1240 #define LOGOLDSUFFIX ".old"
1241
1242     /* Get the log file name */
1243     if (xf86LogFileFrom == X_DEFAULT) {
1244         /* When not running as root, we won't be able to write to /var/log */
1245         if (geteuid() != 0) {
1246             if ((env = getenv("XDG_DATA_HOME")))
1247                 snprintf(buf, sizeof(buf), "%s/%s", env,
1248                          DEFAULT_XDG_DATA_HOME_LOGDIR);
1249             else if ((env = getenv("HOME")))
1250                 snprintf(buf, sizeof(buf), "%s/%s/%s", env,
1251                          DEFAULT_XDG_DATA_HOME, DEFAULT_XDG_DATA_HOME_LOGDIR);
1252
1253             if (env) {
1254                 xf86_mkdir_p(buf);
1255                 strlcat(buf, "/" DEFAULT_LOGPREFIX, sizeof(buf));
1256                 xf86LogFile = buf;
1257             }
1258         }
1259         /* Append the display number and ".log" */
1260         if (asprintf(&lf, "%s%%s" LOGSUFFIX, xf86LogFile) == -1)
1261             FatalError("Cannot allocate space for the log file name\n");
1262         xf86LogFile = lf;
1263     }
1264
1265     xf86LogFile = LogInit(xf86LogFile, LOGOLDSUFFIX);
1266     xf86LogFileWasOpened = TRUE;
1267
1268     xf86SetVerbosity(xf86Verbose);
1269     xf86SetLogVerbosity(xf86LogVerbose);
1270
1271 #undef LOGSUFFIX
1272 #undef LOGOLDSUFFIX
1273
1274     free(lf);
1275 }
1276
1277 void
1278 xf86CloseLog(enum ExitCode error)
1279 {
1280     LogClose(error);
1281 }
1282
1283 /*
1284  * Drivers can use these for using their own SymTabRecs.
1285  */
1286
1287 const char *
1288 xf86TokenToString(SymTabPtr table, int token)
1289 {
1290     int i;
1291
1292     for (i = 0; table[i].token >= 0 && table[i].token != token; i++);
1293
1294     if (table[i].token < 0)
1295         return NULL;
1296     else
1297         return table[i].name;
1298 }
1299
1300 int
1301 xf86StringToToken(SymTabPtr table, const char *string)
1302 {
1303     int i;
1304
1305     if (string == NULL)
1306         return -1;
1307
1308     for (i = 0; table[i].token >= 0 && xf86NameCmp(string, table[i].name); i++);
1309
1310     return table[i].token;
1311 }
1312
1313 /*
1314  * helper to display the clocks found on a card
1315  */
1316 void
1317 xf86ShowClocks(ScrnInfoPtr scrp, MessageType from)
1318 {
1319     int j;
1320
1321     xf86DrvMsg(scrp->scrnIndex, from, "Pixel clocks available:");
1322     for (j = 0; j < scrp->numClocks; j++) {
1323         if ((j % 4) == 0) {
1324             xf86ErrorF("\n");
1325             xf86DrvMsg(scrp->scrnIndex, from, "pixel clocks:");
1326         }
1327         xf86ErrorF(" %7.3f", (double) scrp->clock[j] / 1000.0);
1328     }
1329     xf86ErrorF("\n");
1330 }
1331
1332 /*
1333  * This prints out the driver identify message, including the names of
1334  * the supported chipsets.
1335  *
1336  * XXX This makes assumptions about the line width, etc.  Maybe we could
1337  * use a more general "pretty print" function for messages.
1338  */
1339 void
1340 xf86PrintChipsets(const char *drvname, const char *drvmsg, SymTabPtr chips)
1341 {
1342     int len, i;
1343
1344     len = 6 + strlen(drvname) + 2 + strlen(drvmsg) + 2;
1345     xf86Msg(X_INFO, "%s: %s:", drvname, drvmsg);
1346     for (i = 0; chips[i].name != NULL; i++) {
1347         if (i != 0) {
1348             xf86ErrorF(",");
1349             len++;
1350         }
1351         if (len + 2 + strlen(chips[i].name) < 78) {
1352             xf86ErrorF(" ");
1353             len++;
1354         }
1355         else {
1356             xf86ErrorF("\n\t");
1357             len = 8;
1358         }
1359         xf86ErrorF("%s", chips[i].name);
1360         len += strlen(chips[i].name);
1361     }
1362     xf86ErrorF("\n");
1363 }
1364
1365 int
1366 xf86MatchDevice(const char *drivername, GDevPtr ** sectlist)
1367 {
1368     GDevPtr gdp, *pgdp = NULL;
1369     confScreenPtr screensecptr;
1370     int i, j;
1371
1372     if (sectlist)
1373         *sectlist = NULL;
1374
1375     /*
1376      * This can happen when running Xorg -showopts and a module like ati
1377      * or vmware tries to load its submodules when xf86ConfigLayout is empty
1378      */
1379     if (!xf86ConfigLayout.screens)
1380         return 0;
1381
1382     /*
1383      * This is a very important function that matches the device sections
1384      * as they show up in the config file with the drivers that the server
1385      * loads at run time.
1386      *
1387      * ChipProbe can call
1388      * int xf86MatchDevice(char * drivername, GDevPtr ** sectlist)
1389      * with its driver name. The function allocates an array of GDevPtr and
1390      * returns this via sectlist and returns the number of elements in
1391      * this list as return value. 0 means none found, -1 means fatal error.
1392      *
1393      * It can figure out which of the Device sections to use for which card
1394      * (using things like the Card statement, etc). For single headed servers
1395      * there will of course be just one such Device section.
1396      */
1397     i = 0;
1398
1399     /*
1400      * first we need to loop over all the Screens sections to get to all
1401      * 'active' device sections
1402      */
1403     for (j = 0; xf86ConfigLayout.screens[j].screen != NULL; j++) {
1404         screensecptr = xf86ConfigLayout.screens[j].screen;
1405         if ((screensecptr->device->driver != NULL)
1406             && (xf86NameCmp(screensecptr->device->driver, drivername) == 0)
1407             && (!screensecptr->device->claimed)) {
1408             /*
1409              * we have a matching driver that wasn't claimed, yet
1410              */
1411             pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr));
1412             pgdp[i++] = screensecptr->device;
1413         }
1414     }
1415
1416     /* Then handle the inactive devices */
1417     j = 0;
1418     while (xf86ConfigLayout.inactives[j].identifier) {
1419         gdp = &xf86ConfigLayout.inactives[j];
1420         if (gdp->driver && !gdp->claimed &&
1421             !xf86NameCmp(gdp->driver, drivername)) {
1422             /* we have a matching driver that wasn't claimed yet */
1423             pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr));
1424             pgdp[i++] = gdp;
1425         }
1426         j++;
1427     }
1428
1429     /*
1430      * make the array NULL terminated and return its address
1431      */
1432     if (i)
1433         pgdp[i] = NULL;
1434
1435     if (sectlist)
1436         *sectlist = pgdp;
1437     else
1438         free(pgdp);
1439     return i;
1440 }
1441
1442 const char *
1443 xf86GetVisualName(int visual)
1444 {
1445     if (visual < 0 || visual > DirectColor)
1446         return NULL;
1447
1448     return xf86VisualNames[visual];
1449 }
1450
1451 int
1452 xf86GetVerbosity(void)
1453 {
1454     return max(xf86Verbose, xf86LogVerbose);
1455 }
1456
1457 Pix24Flags
1458 xf86GetPix24(void)
1459 {
1460     return xf86Info.pixmap24;
1461 }
1462
1463 int
1464 xf86GetDepth(void)
1465 {
1466     return xf86Depth;
1467 }
1468
1469 rgb
1470 xf86GetWeight(void)
1471 {
1472     return xf86Weight;
1473 }
1474
1475 Gamma
1476 xf86GetGamma(void)
1477 {
1478     return xf86Gamma;
1479 }
1480
1481 Bool
1482 xf86GetFlipPixels(void)
1483 {
1484     return xf86FlipPixels;
1485 }
1486
1487 const char *
1488 xf86GetServerName(void)
1489 {
1490     return xf86ServerName;
1491 }
1492
1493 Bool
1494 xf86ServerIsExiting(void)
1495 {
1496     return (dispatchException & DE_TERMINATE) == DE_TERMINATE;
1497 }
1498
1499 Bool
1500 xf86ServerIsResetting(void)
1501 {
1502     return xf86Resetting;
1503 }
1504
1505 Bool
1506 xf86ServerIsInitialising(void)
1507 {
1508     return xf86Initialising;
1509 }
1510
1511 Bool
1512 xf86ServerIsOnlyDetecting(void)
1513 {
1514     return xf86DoConfigure;
1515 }
1516
1517 Bool
1518 xf86CaughtSignal(void)
1519 {
1520     return xf86Info.caughtSignal;
1521 }
1522
1523 Bool
1524 xf86GetVidModeAllowNonLocal(void)
1525 {
1526     return xf86Info.vidModeAllowNonLocal;
1527 }
1528
1529 Bool
1530 xf86GetVidModeEnabled(void)
1531 {
1532     return xf86Info.vidModeEnabled;
1533 }
1534
1535 Bool
1536 xf86GetModInDevAllowNonLocal(void)
1537 {
1538     return xf86Info.miscModInDevAllowNonLocal;
1539 }
1540
1541 Bool
1542 xf86GetModInDevEnabled(void)
1543 {
1544     return xf86Info.miscModInDevEnabled;
1545 }
1546
1547 Bool
1548 xf86GetAllowMouseOpenFail(void)
1549 {
1550     return xf86Info.allowMouseOpenFail;
1551 }
1552
1553 void
1554 xf86DisableRandR(void)
1555 {
1556     xf86Info.disableRandR = TRUE;
1557     xf86Info.randRFrom = X_PROBED;
1558 }
1559
1560 CARD32
1561 xf86GetModuleVersion(void *module)
1562 {
1563     return (CARD32) LoaderGetModuleVersion(module);
1564 }
1565
1566 void *
1567 xf86LoadDrvSubModule(DriverPtr drv, const char *name)
1568 {
1569     void *ret;
1570     int errmaj = 0, errmin = 0;
1571
1572     ret = LoadSubModule(drv->module, name, NULL, NULL, NULL, NULL,
1573                         &errmaj, &errmin);
1574     if (!ret)
1575         LoaderErrorMsg(NULL, name, errmaj, errmin);
1576     return ret;
1577 }
1578
1579 void *
1580 xf86LoadSubModule(ScrnInfoPtr pScrn, const char *name)
1581 {
1582     void *ret;
1583     int errmaj = 0, errmin = 0;
1584
1585     ret = LoadSubModule(pScrn->module, name, NULL, NULL, NULL, NULL,
1586                         &errmaj, &errmin);
1587     if (!ret)
1588         LoaderErrorMsg(pScrn->name, name, errmaj, errmin);
1589     return ret;
1590 }
1591
1592 /*
1593  * xf86LoadOneModule loads a single module.
1594  */
1595 void *
1596 xf86LoadOneModule(const char *name, void *opt)
1597 {
1598     int errmaj, errmin;
1599     char *Name;
1600     void *mod;
1601
1602     if (!name)
1603         return NULL;
1604
1605     /* Normalise the module name */
1606     Name = xf86NormalizeName(name);
1607
1608     /* Skip empty names */
1609     if (Name == NULL)
1610         return NULL;
1611     if (*Name == '\0') {
1612         free(Name);
1613         return NULL;
1614     }
1615
1616     mod = LoadModule(Name, NULL, NULL, NULL, opt, NULL, &errmaj, &errmin);
1617     if (!mod)
1618         LoaderErrorMsg(NULL, Name, errmaj, errmin);
1619     free(Name);
1620     return mod;
1621 }
1622
1623 void
1624 xf86UnloadSubModule(void *mod)
1625 {
1626     UnloadSubModule(mod);
1627 }
1628
1629 Bool
1630 xf86LoaderCheckSymbol(const char *name)
1631 {
1632     return LoaderSymbol(name) != NULL;
1633 }
1634
1635 typedef enum {
1636     OPTION_BACKING_STORE
1637 } BSOpts;
1638
1639 static const OptionInfoRec BSOptions[] = {
1640     {OPTION_BACKING_STORE, "BackingStore", OPTV_BOOLEAN, {0}, FALSE},
1641     {-1, NULL, OPTV_NONE, {0}, FALSE}
1642 };
1643
1644 void
1645 xf86SetBackingStore(ScreenPtr pScreen)
1646 {
1647     Bool useBS = FALSE;
1648     MessageType from = X_DEFAULT;
1649     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1650     OptionInfoPtr options;
1651
1652     options = xnfalloc(sizeof(BSOptions));
1653     (void) memcpy(options, BSOptions, sizeof(BSOptions));
1654     xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
1655
1656     /* check for commandline option here */
1657     if (xf86bsEnableFlag) {
1658         from = X_CMDLINE;
1659         useBS = TRUE;
1660     }
1661     else if (xf86bsDisableFlag) {
1662         from = X_CMDLINE;
1663         useBS = FALSE;
1664     }
1665     else {
1666         if (xf86GetOptValBool(options, OPTION_BACKING_STORE, &useBS))
1667             from = X_CONFIG;
1668 #ifdef COMPOSITE
1669         if (from != X_CONFIG)
1670             useBS = xf86ReturnOptValBool(options, OPTION_BACKING_STORE,
1671                                          !noCompositeExtension);
1672 #endif
1673     }
1674     free(options);
1675     pScreen->backingStoreSupport = useBS ? WhenMapped : NotUseful;
1676     if (serverGeneration == 1)
1677         xf86DrvMsg(pScreen->myNum, from, "Backing store %s\n",
1678                    useBS ? "enabled" : "disabled");
1679 }
1680
1681 typedef enum {
1682     OPTION_SILKEN_MOUSE
1683 } SMOpts;
1684
1685 static const OptionInfoRec SMOptions[] = {
1686     {OPTION_SILKEN_MOUSE, "SilkenMouse", OPTV_BOOLEAN, {0}, FALSE},
1687     {-1, NULL, OPTV_NONE, {0}, FALSE}
1688 };
1689
1690 void
1691 xf86SetSilkenMouse(ScreenPtr pScreen)
1692 {
1693     Bool useSM = TRUE;
1694     MessageType from = X_DEFAULT;
1695     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1696     OptionInfoPtr options;
1697
1698     options = xnfalloc(sizeof(SMOptions));
1699     (void) memcpy(options, SMOptions, sizeof(SMOptions));
1700     xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
1701
1702     /* check for commandline option here */
1703     /* disable if screen shares resources */
1704     /* TODO VGA arb disable silken mouse */
1705     if (xf86silkenMouseDisableFlag) {
1706         from = X_CMDLINE;
1707         useSM = FALSE;
1708     }
1709     else {
1710         if (xf86GetOptValBool(options, OPTION_SILKEN_MOUSE, &useSM))
1711             from = X_CONFIG;
1712     }
1713     free(options);
1714     /*
1715      * XXX quick hack to report correctly for OSs that can't do SilkenMouse
1716      * yet.  Should handle this differently so that alternate async methods
1717      * work correctly with this too.
1718      */
1719     pScrn->silkenMouse = useSM && xf86Info.useSIGIO && xf86SIGIOSupported();
1720     if (serverGeneration == 1)
1721         xf86DrvMsg(pScreen->myNum, from, "Silken mouse %s\n",
1722                    pScrn->silkenMouse ? "enabled" : "disabled");
1723 }
1724
1725 /* Wrote this function for the PM2 Xv driver, preliminary. */
1726
1727 void *
1728 xf86FindXvOptions(ScrnInfoPtr pScrn, int adaptor_index, const char *port_name,
1729                   const char **adaptor_name, void **adaptor_options)
1730 {
1731     confXvAdaptorPtr adaptor;
1732     int i;
1733
1734     if (adaptor_index >= pScrn->confScreen->numxvadaptors) {
1735         if (adaptor_name)
1736             *adaptor_name = NULL;
1737         if (adaptor_options)
1738             *adaptor_options = NULL;
1739         return NULL;
1740     }
1741
1742     adaptor = &pScrn->confScreen->xvadaptors[adaptor_index];
1743     if (adaptor_name)
1744         *adaptor_name = adaptor->identifier;
1745     if (adaptor_options)
1746         *adaptor_options = adaptor->options;
1747
1748     for (i = 0; i < adaptor->numports; i++)
1749         if (!xf86NameCmp(adaptor->ports[i].identifier, port_name))
1750             return adaptor->ports[i].options;
1751
1752     return NULL;
1753 }
1754
1755 /* Rather than duplicate loader's get OS function, just include it directly */
1756 #define LoaderGetOS xf86GetOS
1757 #include "loader/os.c"
1758
1759 static void
1760 xf86ConfigFbEntityInactive(EntityInfoPtr pEnt, EntityProc init,
1761                            EntityProc enter, EntityProc leave, void *private)
1762 {
1763     ScrnInfoPtr pScrn;
1764
1765     if ((pScrn = xf86FindScreenForEntity(pEnt->index)))
1766         xf86RemoveEntityFromScreen(pScrn, pEnt->index);
1767     xf86SetEntityFuncs(pEnt->index, init, enter, leave, private);
1768 }
1769
1770 ScrnInfoPtr
1771 xf86ConfigFbEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex,
1772                    EntityProc init, EntityProc enter, EntityProc leave,
1773                    void *private)
1774 {
1775     EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
1776
1777     if (!pEnt)
1778         return pScrn;
1779
1780     if (!(pEnt->location.type == BUS_NONE)) {
1781         free(pEnt);
1782         return pScrn;
1783     }
1784
1785     if (!pEnt->active) {
1786         xf86ConfigFbEntityInactive(pEnt, init, enter, leave, private);
1787         free(pEnt);
1788         return pScrn;
1789     }
1790
1791     if (!pScrn)
1792         pScrn = xf86AllocateScreen(pEnt->driver, scrnFlag);
1793     xf86AddEntityToScreen(pScrn, entityIndex);
1794
1795     xf86SetEntityFuncs(entityIndex, init, enter, leave, private);
1796
1797     free(pEnt);
1798     return pScrn;
1799 }
1800
1801 Bool
1802 xf86IsScreenPrimary(ScrnInfoPtr pScrn)
1803 {
1804     int i;
1805
1806     for (i = 0; i < pScrn->numEntities; i++) {
1807         if (xf86IsEntityPrimary(i))
1808             return TRUE;
1809     }
1810     return FALSE;
1811 }
1812
1813 int
1814 xf86RegisterRootWindowProperty(int ScrnIndex, Atom property, Atom type,
1815                                int format, unsigned long len, void *value)
1816 {
1817     RootWinPropPtr pNewProp = NULL, pRegProp;
1818     Bool existing = FALSE;
1819
1820     DebugF("xf86RegisterRootWindowProperty(%d, %ld, %ld, %d, %ld, %p)\n",
1821            ScrnIndex, property, type, format, len, value);
1822
1823     if (ScrnIndex < 0 || ScrnIndex >= xf86NumScreens) {
1824         return BadMatch;
1825     }
1826
1827     if (xf86RegisteredPropertiesTable &&
1828         xf86RegisteredPropertiesTable[ScrnIndex]) {
1829         for (pNewProp = xf86RegisteredPropertiesTable[ScrnIndex];
1830              pNewProp; pNewProp = pNewProp->next) {
1831             if (strcmp(pNewProp->name, NameForAtom(property)) == 0)
1832                 break;
1833         }
1834     }
1835
1836     if (!pNewProp) {
1837         if ((pNewProp = (RootWinPropPtr) malloc(sizeof(RootWinProp))) == NULL) {
1838             return BadAlloc;
1839         }
1840         /*
1841          * We will put this property at the end of the list so that
1842          * the changes are made in the order they were requested.
1843          */
1844         pNewProp->next = NULL;
1845     }
1846     else {
1847         free((void *) pNewProp->name);
1848         existing = TRUE;
1849     }
1850
1851     pNewProp->name = xnfstrdup(NameForAtom(property));
1852     pNewProp->type = type;
1853     pNewProp->format = format;
1854     pNewProp->size = len;
1855     pNewProp->data = value;
1856
1857     DebugF("new property filled\n");
1858
1859     if (xf86RegisteredPropertiesTable == NULL) {
1860         DebugF("creating xf86RegisteredPropertiesTable[] size %d\n",
1861                xf86NumScreens);
1862         xf86RegisteredPropertiesTable =
1863             xnfcalloc(sizeof(RootWinProp), xf86NumScreens);
1864     }
1865
1866     DebugF("xf86RegisteredPropertiesTable %p\n",
1867            (void *) xf86RegisteredPropertiesTable);
1868     DebugF("xf86RegisteredPropertiesTable[%d] %p\n",
1869            ScrnIndex, (void *) xf86RegisteredPropertiesTable[ScrnIndex]);
1870
1871     if (!existing) {
1872         if (xf86RegisteredPropertiesTable[ScrnIndex] == NULL) {
1873             xf86RegisteredPropertiesTable[ScrnIndex] = pNewProp;
1874         }
1875         else {
1876             pRegProp = xf86RegisteredPropertiesTable[ScrnIndex];
1877             while (pRegProp->next != NULL) {
1878                 DebugF("- next %p\n", (void *) pRegProp);
1879                 pRegProp = pRegProp->next;
1880             }
1881             pRegProp->next = pNewProp;
1882         }
1883     }
1884     DebugF("xf86RegisterRootWindowProperty succeeded\n");
1885     return Success;
1886 }
1887
1888 Bool
1889 xf86IsUnblank(int mode)
1890 {
1891     switch (mode) {
1892     case SCREEN_SAVER_OFF:
1893     case SCREEN_SAVER_FORCER:
1894         return TRUE;
1895     case SCREEN_SAVER_ON:
1896     case SCREEN_SAVER_CYCLE:
1897         return FALSE;
1898     default:
1899         xf86MsgVerb(X_WARNING, 0, "Unexpected save screen mode: %d\n", mode);
1900         return TRUE;
1901     }
1902 }
1903
1904 void
1905 xf86MotionHistoryAllocate(InputInfoPtr pInfo)
1906 {
1907     AllocateMotionHistory(pInfo->dev);
1908 }
1909
1910 ScrnInfoPtr
1911 xf86ScreenToScrn(ScreenPtr pScreen)
1912 {
1913     if (pScreen->isGPU) {
1914         assert(pScreen->myNum - GPU_SCREEN_OFFSET < xf86NumGPUScreens);
1915         return xf86GPUScreens[pScreen->myNum - GPU_SCREEN_OFFSET];
1916     } else {
1917         assert(pScreen->myNum < xf86NumScreens);
1918         return xf86Screens[pScreen->myNum];
1919     }
1920 }
1921
1922 ScreenPtr
1923 xf86ScrnToScreen(ScrnInfoPtr pScrn)
1924 {
1925     if (pScrn->is_gpu) {
1926         assert(pScrn->scrnIndex - GPU_SCREEN_OFFSET < screenInfo.numGPUScreens);
1927         return screenInfo.gpuscreens[pScrn->scrnIndex - GPU_SCREEN_OFFSET];
1928     } else {
1929         assert(pScrn->scrnIndex < screenInfo.numScreens);
1930         return screenInfo.screens[pScrn->scrnIndex];
1931     }
1932 }
1933
1934 void
1935 xf86UpdateDesktopDimensions(void)
1936 {
1937     update_desktop_dimensions();
1938 }