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