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