105b261ecSmrg/*
205b261ecSmrg * Copyright © 1999 Keith Packard
305b261ecSmrg *
405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
605b261ecSmrg * the above copyright notice appear in all copies and that both that
705b261ecSmrg * copyright notice and this permission notice appear in supporting
805b261ecSmrg * documentation, and that the name of Keith Packard not be used in
905b261ecSmrg * advertising or publicity pertaining to distribution of the software without
1005b261ecSmrg * specific, written prior permission.  Keith Packard makes no
1105b261ecSmrg * representations about the suitability of this software for any purpose.  It
1205b261ecSmrg * is provided "as is" without express or implied warranty.
1305b261ecSmrg *
1405b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1605b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2005b261ecSmrg * PERFORMANCE OF THIS SOFTWARE.
2105b261ecSmrg */
2205b261ecSmrg
231b5d61b8Smrg#ifdef HAVE_DIX_CONFIG_H
241b5d61b8Smrg#include <dix-config.h>
2505b261ecSmrg#endif
2605b261ecSmrg#include "kdrive.h"
2705b261ecSmrg#include <mivalidate.h>
2805b261ecSmrg#include <dixstruct.h>
294642e01fSmrg#include "privates.h"
3005b261ecSmrg#ifdef RANDR
3105b261ecSmrg#include <randrstr.h>
3205b261ecSmrg#endif
331b5d61b8Smrg#include "glx_extinit.h"
3405b261ecSmrg
3505b261ecSmrg#ifdef XV
3605b261ecSmrg#include "kxv.h"
3705b261ecSmrg#endif
3805b261ecSmrg
3905b261ecSmrg#ifdef DPMSExtension
4005b261ecSmrg#include "dpmsproc.h"
4105b261ecSmrg#endif
4205b261ecSmrg
4305b261ecSmrg#ifdef HAVE_EXECINFO_H
4405b261ecSmrg#include <execinfo.h>
4505b261ecSmrg#endif
4605b261ecSmrg
471b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
481b5d61b8Smrg#include <hotplug.h>
491b5d61b8Smrg#endif
501b5d61b8Smrg
511b5d61b8Smrg/* This stub can be safely removed once we can
521b5d61b8Smrg * split input and GPU parts in hotplug.h et al. */
531b5d61b8Smrg#include <systemd-logind.h>
5405b261ecSmrg
5505b261ecSmrgtypedef struct _kdDepths {
5635c4bbdfSmrg    CARD8 depth;
5735c4bbdfSmrg    CARD8 bpp;
5805b261ecSmrg} KdDepths;
5905b261ecSmrg
6035c4bbdfSmrgKdDepths kdDepths[] = {
6135c4bbdfSmrg    {1, 1},
6235c4bbdfSmrg    {4, 4},
6335c4bbdfSmrg    {8, 8},
6435c4bbdfSmrg    {15, 16},
6535c4bbdfSmrg    {16, 16},
6635c4bbdfSmrg    {24, 32},
6735c4bbdfSmrg    {32, 32}
6805b261ecSmrg};
6905b261ecSmrg
7005b261ecSmrg#define KD_DEFAULT_BUTTONS 5
7105b261ecSmrg
7235c4bbdfSmrgDevPrivateKeyRec kdScreenPrivateKeyRec;
731b5d61b8Smrgstatic unsigned long kdGeneration;
7435c4bbdfSmrg
7535c4bbdfSmrgBool kdEmulateMiddleButton;
7635c4bbdfSmrgBool kdRawPointerCoordinates;
7735c4bbdfSmrgBool kdDisableZaphod;
781b5d61b8Smrgstatic Bool kdEnabled;
791b5d61b8Smrgstatic int kdSubpixelOrder;
801b5d61b8Smrgstatic char *kdSwitchCmd;
811b5d61b8Smrgstatic DDXPointRec kdOrigin;
8235c4bbdfSmrgBool kdHasPointer = FALSE;
8335c4bbdfSmrgBool kdHasKbd = FALSE;
841b5d61b8Smrgconst char *kdGlobalXkbRules = NULL;
851b5d61b8Smrgconst char *kdGlobalXkbModel = NULL;
861b5d61b8Smrgconst char *kdGlobalXkbLayout = NULL;
871b5d61b8Smrgconst char *kdGlobalXkbVariant = NULL;
881b5d61b8Smrgconst char *kdGlobalXkbOptions = NULL;
8905b261ecSmrg
9005b261ecSmrgvoid
9135c4bbdfSmrgKdDisableScreen(ScreenPtr pScreen)
9205b261ecSmrg{
9305b261ecSmrg    KdScreenPriv(pScreen);
946747b715Smrg
9505b261ecSmrg    if (!pScreenPriv->enabled)
9635c4bbdfSmrg        return;
9705b261ecSmrg    if (!pScreenPriv->closed)
9835c4bbdfSmrg        SetRootClip(pScreen, ROOT_CLIP_NONE);
9935c4bbdfSmrg    KdDisableColormap(pScreen);
10005b261ecSmrg    if (!pScreenPriv->screen->dumb && pScreenPriv->card->cfuncs->disableAccel)
10135c4bbdfSmrg        (*pScreenPriv->card->cfuncs->disableAccel) (pScreen);
10205b261ecSmrg    pScreenPriv->enabled = FALSE;
10305b261ecSmrg}
10405b261ecSmrg
10505b261ecSmrgstatic void
10635c4bbdfSmrgKdDoSwitchCmd(const char *reason)
10705b261ecSmrg{
10835c4bbdfSmrg    if (kdSwitchCmd) {
10935c4bbdfSmrg        char *command;
11035c4bbdfSmrg        int ret;
11135c4bbdfSmrg
11235c4bbdfSmrg        if (asprintf(&command, "%s %s", kdSwitchCmd, reason) == -1)
11335c4bbdfSmrg            return;
11435c4bbdfSmrg
11535c4bbdfSmrg        /* Ignore the return value from system; I'm not sure
11635c4bbdfSmrg         * there's anything more useful to be done when
11735c4bbdfSmrg         * it fails
11835c4bbdfSmrg         */
11935c4bbdfSmrg        ret = system(command);
12035c4bbdfSmrg        (void) ret;
12135c4bbdfSmrg        free(command);
12205b261ecSmrg    }
12305b261ecSmrg}
12405b261ecSmrg
1251b5d61b8Smrgstatic void
12635c4bbdfSmrgKdSuspend(void)
12705b261ecSmrg{
12835c4bbdfSmrg    KdCardInfo *card;
12935c4bbdfSmrg    KdScreenInfo *screen;
13035c4bbdfSmrg
13135c4bbdfSmrg    if (kdEnabled) {
13235c4bbdfSmrg        for (card = kdCardInfo; card; card = card->next) {
13335c4bbdfSmrg            for (screen = card->screenList; screen; screen = screen->next)
13435c4bbdfSmrg                if (screen->mynum == card->selected && screen->pScreen)
13535c4bbdfSmrg                    KdDisableScreen(screen->pScreen);
13635c4bbdfSmrg        }
13735c4bbdfSmrg        KdDisableInput();
13835c4bbdfSmrg        KdDoSwitchCmd("suspend");
13905b261ecSmrg    }
14005b261ecSmrg}
14105b261ecSmrg
1421b5d61b8Smrgstatic void
14335c4bbdfSmrgKdDisableScreens(void)
14405b261ecSmrg{
14535c4bbdfSmrg    KdSuspend();
1461b5d61b8Smrg    kdEnabled = FALSE;
14705b261ecSmrg}
14805b261ecSmrg
14905b261ecSmrgBool
15035c4bbdfSmrgKdEnableScreen(ScreenPtr pScreen)
15105b261ecSmrg{
15235c4bbdfSmrg    KdScreenPriv(pScreen);
15305b261ecSmrg
15405b261ecSmrg    if (pScreenPriv->enabled)
15535c4bbdfSmrg        return TRUE;
15605b261ecSmrg    pScreenPriv->enabled = TRUE;
15705b261ecSmrg    pScreenPriv->dpmsState = KD_DPMS_NORMAL;
15805b261ecSmrg    pScreenPriv->card->selected = pScreenPriv->screen->mynum;
15905b261ecSmrg    if (!pScreenPriv->screen->dumb && pScreenPriv->card->cfuncs->enableAccel)
16035c4bbdfSmrg        (*pScreenPriv->card->cfuncs->enableAccel) (pScreen);
16135c4bbdfSmrg    KdEnableColormap(pScreen);
16235c4bbdfSmrg    SetRootClip(pScreen, ROOT_CLIP_FULL);
16305b261ecSmrg    return TRUE;
16405b261ecSmrg}
16505b261ecSmrg
16605b261ecSmrgvoid
16735c4bbdfSmrgddxGiveUp(enum ExitCode error)
16805b261ecSmrg{
169ed6184dfSmrg    KdDisableScreens();
17005b261ecSmrg}
17105b261ecSmrg
1721b5d61b8Smrgstatic Bool kdDumbDriver;
1731b5d61b8Smrgstatic Bool kdSoftCursor;
17405b261ecSmrg
17535c4bbdfSmrgconst char *
17635c4bbdfSmrgKdParseFindNext(const char *cur, const char *delim, char *save, char *last)
17705b261ecSmrg{
17835c4bbdfSmrg    while (*cur && !strchr(delim, *cur)) {
17935c4bbdfSmrg        *save++ = *cur++;
18005b261ecSmrg    }
18105b261ecSmrg    *save = 0;
18205b261ecSmrg    *last = *cur;
18305b261ecSmrg    if (*cur)
18435c4bbdfSmrg        cur++;
18505b261ecSmrg    return cur;
18605b261ecSmrg}
18705b261ecSmrg
18805b261ecSmrgRotation
18935c4bbdfSmrgKdAddRotation(Rotation a, Rotation b)
19005b261ecSmrg{
19135c4bbdfSmrg    Rotation rotate = (a & RR_Rotate_All) * (b & RR_Rotate_All);
19235c4bbdfSmrg    Rotation reflect = (a & RR_Reflect_All) ^ (b & RR_Reflect_All);
19305b261ecSmrg
19405b261ecSmrg    if (rotate > RR_Rotate_270)
19535c4bbdfSmrg        rotate /= (RR_Rotate_270 * RR_Rotate_90);
19605b261ecSmrg    return reflect | rotate;
19705b261ecSmrg}
19805b261ecSmrg
19905b261ecSmrgRotation
20035c4bbdfSmrgKdSubRotation(Rotation a, Rotation b)
20105b261ecSmrg{
20235c4bbdfSmrg    Rotation rotate = (a & RR_Rotate_All) * 16 / (b & RR_Rotate_All);
20335c4bbdfSmrg    Rotation reflect = (a & RR_Reflect_All) ^ (b & RR_Reflect_All);
20405b261ecSmrg
20505b261ecSmrg    if (rotate > RR_Rotate_270)
20635c4bbdfSmrg        rotate /= (RR_Rotate_270 * RR_Rotate_90);
20705b261ecSmrg    return reflect | rotate;
20805b261ecSmrg}
20905b261ecSmrg
21005b261ecSmrgvoid
21135c4bbdfSmrgKdParseScreen(KdScreenInfo * screen, const char *arg)
21205b261ecSmrg{
21335c4bbdfSmrg    char delim;
21435c4bbdfSmrg    char save[1024];
21535c4bbdfSmrg    int i;
21635c4bbdfSmrg    int pixels, mm;
2176747b715Smrg
21805b261ecSmrg    screen->dumb = kdDumbDriver;
21905b261ecSmrg    screen->softCursor = kdSoftCursor;
22005b261ecSmrg    screen->origin = kdOrigin;
22105b261ecSmrg    screen->randr = RR_Rotate_0;
22235c4bbdfSmrg    screen->x = 0;
22335c4bbdfSmrg    screen->y = 0;
22405b261ecSmrg    screen->width = 0;
22505b261ecSmrg    screen->height = 0;
22605b261ecSmrg    screen->width_mm = 0;
22705b261ecSmrg    screen->height_mm = 0;
22805b261ecSmrg    screen->subpixel_order = kdSubpixelOrder;
22905b261ecSmrg    screen->rate = 0;
2306747b715Smrg    screen->fb.depth = 0;
23105b261ecSmrg    if (!arg)
23235c4bbdfSmrg        return;
23335c4bbdfSmrg    if (strlen(arg) >= sizeof(save))
23435c4bbdfSmrg        return;
23535c4bbdfSmrg
23635c4bbdfSmrg    for (i = 0; i < 2; i++) {
23735c4bbdfSmrg        arg = KdParseFindNext(arg, "x/+@XY", save, &delim);
23835c4bbdfSmrg        if (!save[0])
23935c4bbdfSmrg            return;
24035c4bbdfSmrg
24135c4bbdfSmrg        pixels = atoi(save);
24235c4bbdfSmrg        mm = 0;
24335c4bbdfSmrg
24435c4bbdfSmrg        if (delim == '/') {
24535c4bbdfSmrg            arg = KdParseFindNext(arg, "x+@XY", save, &delim);
24635c4bbdfSmrg            if (!save[0])
24735c4bbdfSmrg                return;
24835c4bbdfSmrg            mm = atoi(save);
24935c4bbdfSmrg        }
25035c4bbdfSmrg
25135c4bbdfSmrg        if (i == 0) {
25235c4bbdfSmrg            screen->width = pixels;
25335c4bbdfSmrg            screen->width_mm = mm;
25435c4bbdfSmrg        }
25535c4bbdfSmrg        else {
25635c4bbdfSmrg            screen->height = pixels;
25735c4bbdfSmrg            screen->height_mm = mm;
25835c4bbdfSmrg        }
25935c4bbdfSmrg        if (delim != 'x' && delim != '+' && delim != '@' &&
26035c4bbdfSmrg            delim != 'X' && delim != 'Y' &&
26135c4bbdfSmrg            (delim != '\0' || i == 0))
26235c4bbdfSmrg            return;
26305b261ecSmrg    }
26405b261ecSmrg
26505b261ecSmrg    kdOrigin.x += screen->width;
26605b261ecSmrg    kdOrigin.y = 0;
26705b261ecSmrg    kdDumbDriver = FALSE;
26805b261ecSmrg    kdSoftCursor = FALSE;
26905b261ecSmrg    kdSubpixelOrder = SubPixelUnknown;
27005b261ecSmrg
27135c4bbdfSmrg    if (delim == '+') {
27235c4bbdfSmrg        arg = KdParseFindNext(arg, "+@xXY", save, &delim);
27335c4bbdfSmrg        if (save[0])
27435c4bbdfSmrg            screen->x = atoi(save);
27535c4bbdfSmrg    }
27635c4bbdfSmrg
27735c4bbdfSmrg    if (delim == '+') {
27835c4bbdfSmrg        arg = KdParseFindNext(arg, "@xXY", save, &delim);
27935c4bbdfSmrg        if (save[0])
28035c4bbdfSmrg            screen->y = atoi(save);
28105b261ecSmrg    }
28235c4bbdfSmrg
28335c4bbdfSmrg    if (delim == '@') {
28435c4bbdfSmrg        arg = KdParseFindNext(arg, "xXY", save, &delim);
28535c4bbdfSmrg        if (save[0]) {
28635c4bbdfSmrg            int rotate = atoi(save);
28735c4bbdfSmrg
28835c4bbdfSmrg            if (rotate < 45)
28935c4bbdfSmrg                screen->randr = RR_Rotate_0;
29035c4bbdfSmrg            else if (rotate < 135)
29135c4bbdfSmrg                screen->randr = RR_Rotate_90;
29235c4bbdfSmrg            else if (rotate < 225)
29335c4bbdfSmrg                screen->randr = RR_Rotate_180;
29435c4bbdfSmrg            else if (rotate < 315)
29535c4bbdfSmrg                screen->randr = RR_Rotate_270;
29635c4bbdfSmrg            else
29735c4bbdfSmrg                screen->randr = RR_Rotate_0;
29835c4bbdfSmrg        }
29935c4bbdfSmrg    }
30035c4bbdfSmrg    if (delim == 'X') {
30135c4bbdfSmrg        arg = KdParseFindNext(arg, "xY", save, &delim);
30235c4bbdfSmrg        screen->randr |= RR_Reflect_X;
30305b261ecSmrg    }
30405b261ecSmrg
30535c4bbdfSmrg    if (delim == 'Y') {
30635c4bbdfSmrg        arg = KdParseFindNext(arg, "xY", save, &delim);
30735c4bbdfSmrg        screen->randr |= RR_Reflect_Y;
30805b261ecSmrg    }
3096747b715Smrg
31035c4bbdfSmrg    arg = KdParseFindNext(arg, "x/,", save, &delim);
31135c4bbdfSmrg    if (save[0]) {
31235c4bbdfSmrg        screen->fb.depth = atoi(save);
31335c4bbdfSmrg        if (delim == '/') {
31435c4bbdfSmrg            arg = KdParseFindNext(arg, "x,", save, &delim);
31535c4bbdfSmrg            if (save[0])
31635c4bbdfSmrg                screen->fb.bitsPerPixel = atoi(save);
31735c4bbdfSmrg        }
31835c4bbdfSmrg        else
31935c4bbdfSmrg            screen->fb.bitsPerPixel = 0;
32005b261ecSmrg    }
32105b261ecSmrg
32235c4bbdfSmrg    if (delim == 'x') {
32335c4bbdfSmrg        arg = KdParseFindNext(arg, "x", save, &delim);
32435c4bbdfSmrg        if (save[0])
32535c4bbdfSmrg            screen->rate = atoi(save);
32605b261ecSmrg    }
32705b261ecSmrg}
32805b261ecSmrg
3291b5d61b8Smrgstatic void
33035c4bbdfSmrgKdParseRgba(char *rgba)
33105b261ecSmrg{
33235c4bbdfSmrg    if (!strcmp(rgba, "rgb"))
33335c4bbdfSmrg        kdSubpixelOrder = SubPixelHorizontalRGB;
33435c4bbdfSmrg    else if (!strcmp(rgba, "bgr"))
33535c4bbdfSmrg        kdSubpixelOrder = SubPixelHorizontalBGR;
33635c4bbdfSmrg    else if (!strcmp(rgba, "vrgb"))
33735c4bbdfSmrg        kdSubpixelOrder = SubPixelVerticalRGB;
33835c4bbdfSmrg    else if (!strcmp(rgba, "vbgr"))
33935c4bbdfSmrg        kdSubpixelOrder = SubPixelVerticalBGR;
34035c4bbdfSmrg    else if (!strcmp(rgba, "none"))
34135c4bbdfSmrg        kdSubpixelOrder = SubPixelNone;
34205b261ecSmrg    else
34335c4bbdfSmrg        kdSubpixelOrder = SubPixelUnknown;
34405b261ecSmrg}
34505b261ecSmrg
34605b261ecSmrgvoid
34735c4bbdfSmrgKdUseMsg(void)
34805b261ecSmrg{
34905b261ecSmrg    ErrorF("\nTinyX Device Dependent Usage:\n");
35035c4bbdfSmrg    ErrorF
35135c4bbdfSmrg        ("-screen WIDTH[/WIDTHMM]xHEIGHT[/HEIGHTMM][+[-]XOFFSET][+[-]YOFFSET][@ROTATION][X][Y][xDEPTH/BPP[xFREQ]]  Specify screen characteristics\n");
35235c4bbdfSmrg    ErrorF
35335c4bbdfSmrg        ("-rgba rgb/bgr/vrgb/vbgr/none   Specify subpixel ordering for LCD panels\n");
35435c4bbdfSmrg    ErrorF
35535c4bbdfSmrg        ("-mouse driver [,n,,options]    Specify the pointer driver and its options (n is the number of buttons)\n");
35635c4bbdfSmrg    ErrorF
35735c4bbdfSmrg        ("-keybd driver [,,options]      Specify the keyboard driver and its options\n");
358ed6184dfSmrg    ErrorF("-xkb-rules       Set default XkbRules value (can be overridden by -keybd options)\n");
359ed6184dfSmrg    ErrorF("-xkb-model       Set default XkbModel value (can be overridden by -keybd options)\n");
360ed6184dfSmrg    ErrorF("-xkb-layout      Set default XkbLayout value (can be overridden by -keybd options)\n");
361ed6184dfSmrg    ErrorF("-xkb-variant     Set default XkbVariant value (can be overridden by -keybd options)\n");
362ed6184dfSmrg    ErrorF("-xkb-options     Set default XkbOptions value (can be overridden by -keybd options)\n");
36305b261ecSmrg    ErrorF("-zaphod          Disable cursor screen switching\n");
36405b261ecSmrg    ErrorF("-2button         Emulate 3 button mouse\n");
36505b261ecSmrg    ErrorF("-3button         Disable 3 button mouse emulation\n");
36635c4bbdfSmrg    ErrorF
36735c4bbdfSmrg        ("-rawcoord        Don't transform pointer coordinates on rotation\n");
36805b261ecSmrg    ErrorF("-dumb            Disable hardware acceleration\n");
36905b261ecSmrg    ErrorF("-softCursor      Force software cursor\n");
37005b261ecSmrg    ErrorF("-videoTest       Start the server, pause momentarily and exit\n");
37135c4bbdfSmrg    ErrorF
37235c4bbdfSmrg        ("-origin X,Y      Locates the next screen in the the virtual screen (Xinerama)\n");
37305b261ecSmrg    ErrorF("-switchCmd       Command to execute on vt switch\n");
37435c4bbdfSmrg    ErrorF
37535c4bbdfSmrg        ("vtxx             Use virtual terminal xx instead of the next available\n");
37605b261ecSmrg}
37705b261ecSmrg
37805b261ecSmrgint
37935c4bbdfSmrgKdProcessArgument(int argc, char **argv, int i)
38005b261ecSmrg{
38135c4bbdfSmrg    KdCardInfo *card;
38235c4bbdfSmrg    KdScreenInfo *screen;
38335c4bbdfSmrg
38435c4bbdfSmrg    if (!strcmp(argv[i], "-screen")) {
38535c4bbdfSmrg        if ((i + 1) < argc) {
38635c4bbdfSmrg            card = KdCardInfoLast();
38735c4bbdfSmrg            if (!card) {
38835c4bbdfSmrg                InitCard(0);
38935c4bbdfSmrg                card = KdCardInfoLast();
39035c4bbdfSmrg            }
39135c4bbdfSmrg            if (card) {
39235c4bbdfSmrg                screen = KdScreenInfoAdd(card);
39335c4bbdfSmrg                KdParseScreen(screen, argv[i + 1]);
39435c4bbdfSmrg            }
39535c4bbdfSmrg            else
39635c4bbdfSmrg                ErrorF("No matching card found!\n");
39735c4bbdfSmrg        }
39835c4bbdfSmrg        else
39935c4bbdfSmrg            UseMsg();
40035c4bbdfSmrg        return 2;
40105b261ecSmrg    }
40235c4bbdfSmrg    if (!strcmp(argv[i], "-zaphod")) {
40335c4bbdfSmrg        kdDisableZaphod = TRUE;
40435c4bbdfSmrg        return 1;
40505b261ecSmrg    }
40635c4bbdfSmrg    if (!strcmp(argv[i], "-3button")) {
40735c4bbdfSmrg        kdEmulateMiddleButton = FALSE;
40835c4bbdfSmrg        return 1;
40905b261ecSmrg    }
41035c4bbdfSmrg    if (!strcmp(argv[i], "-2button")) {
41135c4bbdfSmrg        kdEmulateMiddleButton = TRUE;
41235c4bbdfSmrg        return 1;
41305b261ecSmrg    }
41435c4bbdfSmrg    if (!strcmp(argv[i], "-rawcoord")) {
41535c4bbdfSmrg        kdRawPointerCoordinates = 1;
41635c4bbdfSmrg        return 1;
41705b261ecSmrg    }
41835c4bbdfSmrg    if (!strcmp(argv[i], "-dumb")) {
41935c4bbdfSmrg        kdDumbDriver = TRUE;
42035c4bbdfSmrg        return 1;
42105b261ecSmrg    }
42235c4bbdfSmrg    if (!strcmp(argv[i], "-softCursor")) {
42335c4bbdfSmrg        kdSoftCursor = TRUE;
42435c4bbdfSmrg        return 1;
42505b261ecSmrg    }
42635c4bbdfSmrg    if (!strcmp(argv[i], "-origin")) {
42735c4bbdfSmrg        if ((i + 1) < argc) {
42835c4bbdfSmrg            char *x = argv[i + 1];
42935c4bbdfSmrg            char *y = strchr(x, ',');
43035c4bbdfSmrg
43135c4bbdfSmrg            if (x)
43235c4bbdfSmrg                kdOrigin.x = atoi(x);
43335c4bbdfSmrg            else
43435c4bbdfSmrg                kdOrigin.x = 0;
43535c4bbdfSmrg            if (y)
43635c4bbdfSmrg                kdOrigin.y = atoi(y + 1);
43735c4bbdfSmrg            else
43835c4bbdfSmrg                kdOrigin.y = 0;
43935c4bbdfSmrg        }
44035c4bbdfSmrg        else
44135c4bbdfSmrg            UseMsg();
44235c4bbdfSmrg        return 2;
44305b261ecSmrg    }
44435c4bbdfSmrg    if (!strcmp(argv[i], "-rgba")) {
44535c4bbdfSmrg        if ((i + 1) < argc)
44635c4bbdfSmrg            KdParseRgba(argv[i + 1]);
44735c4bbdfSmrg        else
44835c4bbdfSmrg            UseMsg();
44935c4bbdfSmrg        return 2;
45005b261ecSmrg    }
45135c4bbdfSmrg    if (!strcmp(argv[i], "-switchCmd")) {
45235c4bbdfSmrg        if ((i + 1) < argc)
45335c4bbdfSmrg            kdSwitchCmd = argv[i + 1];
45435c4bbdfSmrg        else
45535c4bbdfSmrg            UseMsg();
45635c4bbdfSmrg        return 2;
45705b261ecSmrg    }
4581b5d61b8Smrg    if (!strcmp(argv[i], "-xkb-rules")) {
4591b5d61b8Smrg        if (i + 1 >= argc) {
4601b5d61b8Smrg            UseMsg();
4611b5d61b8Smrg            FatalError("Missing argument for option -xkb-rules.\n");
4621b5d61b8Smrg        }
4631b5d61b8Smrg        kdGlobalXkbRules = argv[i + 1];
4641b5d61b8Smrg        return 2;
4651b5d61b8Smrg    }
4661b5d61b8Smrg    if (!strcmp(argv[i], "-xkb-model")) {
4671b5d61b8Smrg        if (i + 1 >= argc) {
4681b5d61b8Smrg            UseMsg();
4691b5d61b8Smrg            FatalError("Missing argument for option -xkb-model.\n");
4701b5d61b8Smrg        }
4711b5d61b8Smrg        kdGlobalXkbModel = argv[i + 1];
4721b5d61b8Smrg        return 2;
4731b5d61b8Smrg    }
4741b5d61b8Smrg    if (!strcmp(argv[i], "-xkb-layout")) {
4751b5d61b8Smrg        if (i + 1 >= argc) {
4761b5d61b8Smrg            UseMsg();
4771b5d61b8Smrg            FatalError("Missing argument for option -xkb-layout.\n");
4781b5d61b8Smrg        }
4791b5d61b8Smrg        kdGlobalXkbLayout = argv[i + 1];
4801b5d61b8Smrg        return 2;
4811b5d61b8Smrg    }
4821b5d61b8Smrg    if (!strcmp(argv[i], "-xkb-variant")) {
4831b5d61b8Smrg        if (i + 1 >= argc) {
4841b5d61b8Smrg            UseMsg();
4851b5d61b8Smrg            FatalError("Missing argument for option -xkb-variant.\n");
4861b5d61b8Smrg        }
4871b5d61b8Smrg        kdGlobalXkbVariant = argv[i + 1];
4881b5d61b8Smrg        return 2;
4891b5d61b8Smrg    }
4901b5d61b8Smrg    if (!strcmp(argv[i], "-xkb-options")) {
4911b5d61b8Smrg        if (i + 1 >= argc) {
4921b5d61b8Smrg            UseMsg();
4931b5d61b8Smrg            FatalError("Missing argument for option -xkb-options.\n");
4941b5d61b8Smrg        }
4951b5d61b8Smrg        kdGlobalXkbOptions = argv[i + 1];
4961b5d61b8Smrg        return 2;
49705b261ecSmrg    }
49835c4bbdfSmrg    if (!strcmp(argv[i], "-mouse") || !strcmp(argv[i], "-pointer")) {
49905b261ecSmrg        if (i + 1 >= argc)
50005b261ecSmrg            UseMsg();
50105b261ecSmrg        KdAddConfigPointer(argv[i + 1]);
50235c4bbdfSmrg        kdHasPointer = TRUE;
50305b261ecSmrg        return 2;
50405b261ecSmrg    }
50535c4bbdfSmrg    if (!strcmp(argv[i], "-keybd")) {
50605b261ecSmrg        if (i + 1 >= argc)
50705b261ecSmrg            UseMsg();
50805b261ecSmrg        KdAddConfigKeyboard(argv[i + 1]);
50935c4bbdfSmrg        kdHasKbd = TRUE;
51005b261ecSmrg        return 2;
51105b261ecSmrg    }
51205b261ecSmrg
51305b261ecSmrg    return 0;
51405b261ecSmrg}
51505b261ecSmrg
5161b5d61b8Smrgstatic Bool
51735c4bbdfSmrgKdAllocatePrivates(ScreenPtr pScreen)
51805b261ecSmrg{
51935c4bbdfSmrg    KdPrivScreenPtr pScreenPriv;
5206747b715Smrg
52105b261ecSmrg    if (kdGeneration != serverGeneration)
52235c4bbdfSmrg        kdGeneration = serverGeneration;
5234642e01fSmrg
5246747b715Smrg    if (!dixRegisterPrivateKey(&kdScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
52535c4bbdfSmrg        return FALSE;
5266747b715Smrg
52735c4bbdfSmrg    pScreenPriv = calloc(1, sizeof(*pScreenPriv));
52805b261ecSmrg    if (!pScreenPriv)
52935c4bbdfSmrg        return FALSE;
53035c4bbdfSmrg    KdSetScreenPriv(pScreen, pScreenPriv);
53105b261ecSmrg    return TRUE;
53205b261ecSmrg}
53305b261ecSmrg
5341b5d61b8Smrgstatic Bool
53535c4bbdfSmrgKdCreateScreenResources(ScreenPtr pScreen)
53605b261ecSmrg{
53705b261ecSmrg    KdScreenPriv(pScreen);
53835c4bbdfSmrg    KdCardInfo *card = pScreenPriv->card;
53905b261ecSmrg    Bool ret;
54005b261ecSmrg
54105b261ecSmrg    pScreen->CreateScreenResources = pScreenPriv->CreateScreenResources;
54235c4bbdfSmrg    if (pScreen->CreateScreenResources)
54335c4bbdfSmrg        ret = (*pScreen->CreateScreenResources) (pScreen);
54405b261ecSmrg    else
54535c4bbdfSmrg        ret = -1;
54605b261ecSmrg    pScreenPriv->CreateScreenResources = pScreen->CreateScreenResources;
54705b261ecSmrg    pScreen->CreateScreenResources = KdCreateScreenResources;
54805b261ecSmrg    if (ret && card->cfuncs->createRes)
54935c4bbdfSmrg        ret = (*card->cfuncs->createRes) (pScreen);
55005b261ecSmrg    return ret;
55105b261ecSmrg}
55205b261ecSmrg
5531b5d61b8Smrgstatic Bool
55435c4bbdfSmrgKdCloseScreen(ScreenPtr pScreen)
55505b261ecSmrg{
55605b261ecSmrg    KdScreenPriv(pScreen);
55735c4bbdfSmrg    KdScreenInfo *screen = pScreenPriv->screen;
55835c4bbdfSmrg    KdCardInfo *card = pScreenPriv->card;
55935c4bbdfSmrg    Bool ret;
56035c4bbdfSmrg
56135c4bbdfSmrg    if (card->cfuncs->closeScreen)
56235c4bbdfSmrg        (*card->cfuncs->closeScreen)(pScreen);
5636747b715Smrg
56405b261ecSmrg    pScreenPriv->closed = TRUE;
56505b261ecSmrg    pScreen->CloseScreen = pScreenPriv->CloseScreen;
56635c4bbdfSmrg
56735c4bbdfSmrg    if (pScreen->CloseScreen)
56835c4bbdfSmrg        ret = (*pScreen->CloseScreen) (pScreen);
56905b261ecSmrg    else
57035c4bbdfSmrg        ret = TRUE;
5716747b715Smrg
57205b261ecSmrg    if (screen->mynum == card->selected)
57335c4bbdfSmrg        KdDisableScreen(pScreen);
5746747b715Smrg
57505b261ecSmrg    if (!pScreenPriv->screen->dumb && card->cfuncs->finiAccel)
57635c4bbdfSmrg        (*card->cfuncs->finiAccel) (pScreen);
57705b261ecSmrg
57835c4bbdfSmrg    if (card->cfuncs->scrfini)
57905b261ecSmrg        (*card->cfuncs->scrfini) (screen);
58005b261ecSmrg
58105b261ecSmrg    /*
58205b261ecSmrg     * Clean up card when last screen is closed, DIX closes them in
58305b261ecSmrg     * reverse order, thus we check for when the first in the list is closed
58405b261ecSmrg     */
58535c4bbdfSmrg    if (screen == card->screenList) {
58635c4bbdfSmrg        if (card->cfuncs->cardfini)
58735c4bbdfSmrg            (*card->cfuncs->cardfini) (card);
58835c4bbdfSmrg        /*
58935c4bbdfSmrg         * Clean up OS when last card is closed
59035c4bbdfSmrg         */
59135c4bbdfSmrg        if (card == kdCardInfo) {
5921b5d61b8Smrg            kdEnabled = FALSE;
59335c4bbdfSmrg        }
59405b261ecSmrg    }
5956747b715Smrg
59605b261ecSmrg    pScreenPriv->screen->pScreen = 0;
5976747b715Smrg
59835c4bbdfSmrg    free((void *) pScreenPriv);
59905b261ecSmrg    return ret;
60005b261ecSmrg}
60105b261ecSmrg
6021b5d61b8Smrgstatic Bool
60335c4bbdfSmrgKdSaveScreen(ScreenPtr pScreen, int on)
60405b261ecSmrg{
6051b5d61b8Smrg    return FALSE;
60605b261ecSmrg}
60705b261ecSmrg
60805b261ecSmrgstatic Bool
60935c4bbdfSmrgKdCreateWindow(WindowPtr pWin)
61005b261ecSmrg{
61105b261ecSmrg#ifndef PHOENIX
61235c4bbdfSmrg    if (!pWin->parent) {
61335c4bbdfSmrg        KdScreenPriv(pWin->drawable.pScreen);
61435c4bbdfSmrg
61535c4bbdfSmrg        if (!pScreenPriv->enabled) {
61635c4bbdfSmrg            RegionEmpty(&pWin->borderClip);
61735c4bbdfSmrg            RegionBreak(&pWin->clipList);
61835c4bbdfSmrg        }
61905b261ecSmrg    }
62005b261ecSmrg#endif
62135c4bbdfSmrg    return fbCreateWindow(pWin);
62205b261ecSmrg}
62305b261ecSmrg
62405b261ecSmrgvoid
62535c4bbdfSmrgKdSetSubpixelOrder(ScreenPtr pScreen, Rotation randr)
62605b261ecSmrg{
62705b261ecSmrg    KdScreenPriv(pScreen);
62835c4bbdfSmrg    KdScreenInfo *screen = pScreenPriv->screen;
62935c4bbdfSmrg    int subpixel_order = screen->subpixel_order;
63035c4bbdfSmrg    Rotation subpixel_dir;
63135c4bbdfSmrg    int i;
6326747b715Smrg
63305b261ecSmrg    static struct {
63435c4bbdfSmrg        int subpixel_order;
63535c4bbdfSmrg        Rotation direction;
63605b261ecSmrg    } orders[] = {
63735c4bbdfSmrg        {SubPixelHorizontalRGB, RR_Rotate_0},
63835c4bbdfSmrg        {SubPixelHorizontalBGR, RR_Rotate_180},
63935c4bbdfSmrg        {SubPixelVerticalRGB, RR_Rotate_270},
64035c4bbdfSmrg        {SubPixelVerticalBGR, RR_Rotate_90},
64105b261ecSmrg    };
64205b261ecSmrg
64305b261ecSmrg    static struct {
64435c4bbdfSmrg        int bit;
64535c4bbdfSmrg        int normal;
64635c4bbdfSmrg        int reflect;
64705b261ecSmrg    } reflects[] = {
64835c4bbdfSmrg        {RR_Reflect_X, SubPixelHorizontalRGB, SubPixelHorizontalBGR},
64935c4bbdfSmrg        {RR_Reflect_X, SubPixelHorizontalBGR, SubPixelHorizontalRGB},
65035c4bbdfSmrg        {RR_Reflect_Y, SubPixelVerticalRGB, SubPixelVerticalBGR},
65135c4bbdfSmrg        {RR_Reflect_Y, SubPixelVerticalRGB, SubPixelVerticalRGB},
65205b261ecSmrg    };
6536747b715Smrg
65405b261ecSmrg    /* map subpixel to direction */
65505b261ecSmrg    for (i = 0; i < 4; i++)
65635c4bbdfSmrg        if (orders[i].subpixel_order == subpixel_order)
65735c4bbdfSmrg            break;
65835c4bbdfSmrg    if (i < 4) {
65935c4bbdfSmrg        subpixel_dir =
66035c4bbdfSmrg            KdAddRotation(randr & RR_Rotate_All, orders[i].direction);
66135c4bbdfSmrg
66235c4bbdfSmrg        /* map back to subpixel order */
66335c4bbdfSmrg        for (i = 0; i < 4; i++)
66435c4bbdfSmrg            if (orders[i].direction & subpixel_dir) {
66535c4bbdfSmrg                subpixel_order = orders[i].subpixel_order;
66635c4bbdfSmrg                break;
66735c4bbdfSmrg            }
66835c4bbdfSmrg        /* reflect */
66935c4bbdfSmrg        for (i = 0; i < 4; i++)
67035c4bbdfSmrg            if ((randr & reflects[i].bit) &&
67135c4bbdfSmrg                reflects[i].normal == subpixel_order) {
67235c4bbdfSmrg                subpixel_order = reflects[i].reflect;
67335c4bbdfSmrg                break;
67435c4bbdfSmrg            }
67505b261ecSmrg    }
67635c4bbdfSmrg    PictureSetSubpixelOrder(pScreen, subpixel_order);
67705b261ecSmrg}
67805b261ecSmrg
67905b261ecSmrg/* Pass through AddScreen, which doesn't take any closure */
68005b261ecSmrgstatic KdScreenInfo *kdCurrentScreen;
68105b261ecSmrg
6821b5d61b8Smrgstatic Bool
68335c4bbdfSmrgKdScreenInit(ScreenPtr pScreen, int argc, char **argv)
68405b261ecSmrg{
68535c4bbdfSmrg    KdScreenInfo *screen = kdCurrentScreen;
68635c4bbdfSmrg    KdCardInfo *card = screen->card;
68735c4bbdfSmrg    KdPrivScreenPtr pScreenPriv;
68835c4bbdfSmrg
68905b261ecSmrg    /*
69005b261ecSmrg     * note that screen->fb is set up for the nominal orientation
69105b261ecSmrg     * of the screen; that means if randr is rotated, the values
69205b261ecSmrg     * there should reflect a rotated frame buffer (or shadow).
69305b261ecSmrg     */
69435c4bbdfSmrg    Bool rotated = (screen->randr & (RR_Rotate_90 | RR_Rotate_270)) != 0;
69535c4bbdfSmrg    int width, height, *width_mmp, *height_mmp;
69605b261ecSmrg
69735c4bbdfSmrg    KdAllocatePrivates(pScreen);
69805b261ecSmrg
69905b261ecSmrg    pScreenPriv = KdGetScreenPriv(pScreen);
7006747b715Smrg
70135c4bbdfSmrg    if (!rotated) {
70235c4bbdfSmrg        width = screen->width;
70335c4bbdfSmrg        height = screen->height;
70435c4bbdfSmrg        width_mmp = &screen->width_mm;
70535c4bbdfSmrg        height_mmp = &screen->height_mm;
70605b261ecSmrg    }
70735c4bbdfSmrg    else {
70835c4bbdfSmrg        width = screen->height;
70935c4bbdfSmrg        height = screen->width;
71035c4bbdfSmrg        width_mmp = &screen->height_mm;
71135c4bbdfSmrg        height_mmp = &screen->width_mm;
71205b261ecSmrg    }
71305b261ecSmrg    screen->pScreen = pScreen;
71405b261ecSmrg    pScreenPriv->screen = screen;
71505b261ecSmrg    pScreenPriv->card = card;
7166747b715Smrg    pScreenPriv->bytesPerPixel = screen->fb.bitsPerPixel >> 3;
71705b261ecSmrg    pScreenPriv->dpmsState = KD_DPMS_NORMAL;
7186747b715Smrg    pScreen->x = screen->origin.x;
7196747b715Smrg    pScreen->y = screen->origin.y;
72005b261ecSmrg
72105b261ecSmrg    if (!monitorResolution)
72235c4bbdfSmrg        monitorResolution = 75;
72305b261ecSmrg    /*
72405b261ecSmrg     * This is done in this order so that backing store wraps
72505b261ecSmrg     * our GC functions; fbFinishScreenInit initializes MI
72605b261ecSmrg     * backing store
72705b261ecSmrg     */
72835c4bbdfSmrg    if (!fbSetupScreen(pScreen,
72935c4bbdfSmrg                       screen->fb.frameBuffer,
73035c4bbdfSmrg                       width, height,
73135c4bbdfSmrg                       monitorResolution, monitorResolution,
73235c4bbdfSmrg                       screen->fb.pixelStride, screen->fb.bitsPerPixel)) {
73335c4bbdfSmrg        return FALSE;
73405b261ecSmrg    }
73505b261ecSmrg
73605b261ecSmrg    /*
73705b261ecSmrg     * Set colormap functions
73805b261ecSmrg     */
73935c4bbdfSmrg    pScreen->InstallColormap = KdInstallColormap;
74035c4bbdfSmrg    pScreen->UninstallColormap = KdUninstallColormap;
74105b261ecSmrg    pScreen->ListInstalledColormaps = KdListInstalledColormaps;
74235c4bbdfSmrg    pScreen->StoreColors = KdStoreColors;
74335c4bbdfSmrg
74435c4bbdfSmrg    pScreen->SaveScreen = KdSaveScreen;
74535c4bbdfSmrg    pScreen->CreateWindow = KdCreateWindow;
74635c4bbdfSmrg
74735c4bbdfSmrg    if (!fbFinishScreenInit(pScreen,
74835c4bbdfSmrg                            screen->fb.frameBuffer,
74935c4bbdfSmrg                            width, height,
75035c4bbdfSmrg                            monitorResolution, monitorResolution,
75135c4bbdfSmrg                            screen->fb.pixelStride, screen->fb.bitsPerPixel)) {
75235c4bbdfSmrg        return FALSE;
75305b261ecSmrg    }
7546747b715Smrg
75505b261ecSmrg    /*
75605b261ecSmrg     * Fix screen sizes; for some reason mi takes dpi instead of mm.
75705b261ecSmrg     * Rounding errors are annoying
75805b261ecSmrg     */
75905b261ecSmrg    if (*width_mmp)
76035c4bbdfSmrg        pScreen->mmWidth = *width_mmp;
76105b261ecSmrg    else
76235c4bbdfSmrg        *width_mmp = pScreen->mmWidth;
76305b261ecSmrg    if (*height_mmp)
76435c4bbdfSmrg        pScreen->mmHeight = *height_mmp;
76505b261ecSmrg    else
76635c4bbdfSmrg        *height_mmp = pScreen->mmHeight;
7676747b715Smrg
76805b261ecSmrg    /*
76905b261ecSmrg     * Plug in our own block/wakeup handlers.
77005b261ecSmrg     * miScreenInit installs NoopDDA in both places
77105b261ecSmrg     */
77235c4bbdfSmrg    pScreen->BlockHandler = KdBlockHandler;
77335c4bbdfSmrg    pScreen->WakeupHandler = KdWakeupHandler;
7746747b715Smrg
77535c4bbdfSmrg    if (!fbPictureInit(pScreen, 0, 0))
77635c4bbdfSmrg        return FALSE;
77705b261ecSmrg    if (card->cfuncs->initScreen)
77835c4bbdfSmrg        if (!(*card->cfuncs->initScreen) (pScreen))
77935c4bbdfSmrg            return FALSE;
7806747b715Smrg
78105b261ecSmrg    if (!screen->dumb && card->cfuncs->initAccel)
78235c4bbdfSmrg        if (!(*card->cfuncs->initAccel) (pScreen))
78335c4bbdfSmrg            screen->dumb = TRUE;
7846747b715Smrg
78505b261ecSmrg    if (card->cfuncs->finishInitScreen)
78635c4bbdfSmrg        if (!(*card->cfuncs->finishInitScreen) (pScreen))
78735c4bbdfSmrg            return FALSE;
7886747b715Smrg
7896747b715Smrg    /*
79005b261ecSmrg     * Wrap CloseScreen, the order now is:
79135c4bbdfSmrg     *  KdCloseScreen
79235c4bbdfSmrg     *  fbCloseScreen
79305b261ecSmrg     */
79405b261ecSmrg    pScreenPriv->CloseScreen = pScreen->CloseScreen;
79505b261ecSmrg    pScreen->CloseScreen = KdCloseScreen;
79605b261ecSmrg
79705b261ecSmrg    pScreenPriv->CreateScreenResources = pScreen->CreateScreenResources;
79805b261ecSmrg    pScreen->CreateScreenResources = KdCreateScreenResources;
7996747b715Smrg
80005b261ecSmrg    if (screen->softCursor ||
80135c4bbdfSmrg        !card->cfuncs->initCursor || !(*card->cfuncs->initCursor) (pScreen)) {
80235c4bbdfSmrg        /* Use MI for cursor display and event queueing. */
80335c4bbdfSmrg        screen->softCursor = TRUE;
80435c4bbdfSmrg        miDCInitialize(pScreen, &kdPointerScreenFuncs);
80505b261ecSmrg    }
80605b261ecSmrg
80735c4bbdfSmrg    if (!fbCreateDefColormap(pScreen)) {
80835c4bbdfSmrg        return FALSE;
80905b261ecSmrg    }
81005b261ecSmrg
81135c4bbdfSmrg    KdSetSubpixelOrder(pScreen, screen->randr);
81205b261ecSmrg
81305b261ecSmrg    /*
81405b261ecSmrg     * Enable the hardware
81505b261ecSmrg     */
8161b5d61b8Smrg    kdEnabled = TRUE;
8176747b715Smrg
81835c4bbdfSmrg    if (screen->mynum == card->selected) {
81935c4bbdfSmrg        pScreenPriv->enabled = TRUE;
82035c4bbdfSmrg        KdEnableColormap(pScreen);
82135c4bbdfSmrg        if (!screen->dumb && card->cfuncs->enableAccel)
82235c4bbdfSmrg            (*card->cfuncs->enableAccel) (pScreen);
82305b261ecSmrg    }
8246747b715Smrg
82505b261ecSmrg    return TRUE;
82605b261ecSmrg}
82705b261ecSmrg
8281b5d61b8Smrgstatic void
82935c4bbdfSmrgKdInitScreen(ScreenInfo * pScreenInfo,
83035c4bbdfSmrg             KdScreenInfo * screen, int argc, char **argv)
83105b261ecSmrg{
83235c4bbdfSmrg    KdCardInfo *card = screen->card;
8336747b715Smrg
83435c4bbdfSmrg    if (!(*card->cfuncs->scrinit) (screen))
83535c4bbdfSmrg        FatalError("Screen initialization failed!\n");
8366747b715Smrg
83705b261ecSmrg    if (!card->cfuncs->initAccel)
83835c4bbdfSmrg        screen->dumb = TRUE;
83905b261ecSmrg    if (!card->cfuncs->initCursor)
84035c4bbdfSmrg        screen->softCursor = TRUE;
84105b261ecSmrg}
84205b261ecSmrg
84305b261ecSmrgstatic Bool
84435c4bbdfSmrgKdSetPixmapFormats(ScreenInfo * pScreenInfo)
84505b261ecSmrg{
84635c4bbdfSmrg    CARD8 depthToBpp[33];       /* depth -> bpp map */
84735c4bbdfSmrg    KdCardInfo *card;
84835c4bbdfSmrg    KdScreenInfo *screen;
84935c4bbdfSmrg    int i;
85035c4bbdfSmrg    int bpp;
85105b261ecSmrg    PixmapFormatRec *format;
85205b261ecSmrg
85305b261ecSmrg    for (i = 1; i <= 32; i++)
85435c4bbdfSmrg        depthToBpp[i] = 0;
85505b261ecSmrg
85605b261ecSmrg    /*
85705b261ecSmrg     * Generate mappings between bitsPerPixel and depth,
85805b261ecSmrg     * also ensure that all screens comply with protocol
85905b261ecSmrg     * restrictions on equivalent formats for the same
86005b261ecSmrg     * depth on different screens
86105b261ecSmrg     */
86235c4bbdfSmrg    for (card = kdCardInfo; card; card = card->next) {
86335c4bbdfSmrg        for (screen = card->screenList; screen; screen = screen->next) {
86435c4bbdfSmrg            bpp = screen->fb.bitsPerPixel;
86535c4bbdfSmrg            if (bpp == 24)
86635c4bbdfSmrg                bpp = 32;
86735c4bbdfSmrg            if (!depthToBpp[screen->fb.depth])
86835c4bbdfSmrg                depthToBpp[screen->fb.depth] = bpp;
86935c4bbdfSmrg            else if (depthToBpp[screen->fb.depth] != bpp)
87035c4bbdfSmrg                return FALSE;
87135c4bbdfSmrg        }
87205b261ecSmrg    }
8736747b715Smrg
87405b261ecSmrg    /*
87505b261ecSmrg     * Fill in additional formats
87605b261ecSmrg     */
8771b5d61b8Smrg    for (i = 0; i < ARRAY_SIZE(kdDepths); i++)
87835c4bbdfSmrg        if (!depthToBpp[kdDepths[i].depth])
87935c4bbdfSmrg            depthToBpp[kdDepths[i].depth] = kdDepths[i].bpp;
8806747b715Smrg
88135c4bbdfSmrg    pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
88205b261ecSmrg    pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
88335c4bbdfSmrg    pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
88435c4bbdfSmrg    pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
8856747b715Smrg
88605b261ecSmrg    pScreenInfo->numPixmapFormats = 0;
8876747b715Smrg
88835c4bbdfSmrg    for (i = 1; i <= 32; i++) {
88935c4bbdfSmrg        if (depthToBpp[i]) {
89035c4bbdfSmrg            format = &pScreenInfo->formats[pScreenInfo->numPixmapFormats++];
89135c4bbdfSmrg            format->depth = i;
89235c4bbdfSmrg            format->bitsPerPixel = depthToBpp[i];
89335c4bbdfSmrg            format->scanlinePad = BITMAP_SCANLINE_PAD;
89435c4bbdfSmrg        }
89505b261ecSmrg    }
8966747b715Smrg
89705b261ecSmrg    return TRUE;
89805b261ecSmrg}
89905b261ecSmrg
90005b261ecSmrgstatic void
90135c4bbdfSmrgKdAddScreen(ScreenInfo * pScreenInfo,
90235c4bbdfSmrg            KdScreenInfo * screen, int argc, char **argv)
90305b261ecSmrg{
90435c4bbdfSmrg    int i;
90535c4bbdfSmrg
90605b261ecSmrg    /*
90705b261ecSmrg     * Fill in fb visual type masks for this screen
90805b261ecSmrg     */
90935c4bbdfSmrg    for (i = 0; i < pScreenInfo->numPixmapFormats; i++) {
91035c4bbdfSmrg        unsigned long visuals;
91135c4bbdfSmrg        Pixel rm, gm, bm;
91235c4bbdfSmrg
91335c4bbdfSmrg        visuals = 0;
91435c4bbdfSmrg        rm = gm = bm = 0;
91535c4bbdfSmrg        if (pScreenInfo->formats[i].depth == screen->fb.depth) {
91635c4bbdfSmrg            visuals = screen->fb.visuals;
91735c4bbdfSmrg            rm = screen->fb.redMask;
91835c4bbdfSmrg            gm = screen->fb.greenMask;
91935c4bbdfSmrg            bm = screen->fb.blueMask;
92035c4bbdfSmrg        }
92135c4bbdfSmrg        fbSetVisualTypesAndMasks(pScreenInfo->formats[i].depth,
92235c4bbdfSmrg                                 visuals, 8, rm, gm, bm);
92305b261ecSmrg    }
92405b261ecSmrg
92505b261ecSmrg    kdCurrentScreen = screen;
9266747b715Smrg
92735c4bbdfSmrg    AddScreen(KdScreenInit, argc, argv);
92805b261ecSmrg}
92905b261ecSmrg
93005b261ecSmrgvoid
93135c4bbdfSmrgKdInitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
93205b261ecSmrg{
93335c4bbdfSmrg    KdCardInfo *card;
93435c4bbdfSmrg    KdScreenInfo *screen;
93535c4bbdfSmrg
93635c4bbdfSmrg    if (!kdCardInfo) {
93735c4bbdfSmrg        InitCard(0);
93835c4bbdfSmrg        if (!(card = KdCardInfoLast()))
93935c4bbdfSmrg            FatalError("No matching cards found!\n");
94035c4bbdfSmrg        screen = KdScreenInfoAdd(card);
94135c4bbdfSmrg        KdParseScreen(screen, 0);
94205b261ecSmrg    }
94305b261ecSmrg    /*
94405b261ecSmrg     * Initialize all of the screens for all of the cards
94505b261ecSmrg     */
94635c4bbdfSmrg    for (card = kdCardInfo; card; card = card->next) {
94735c4bbdfSmrg        int ret = 1;
94835c4bbdfSmrg
94935c4bbdfSmrg        if (card->cfuncs->cardinit)
95035c4bbdfSmrg            ret = (*card->cfuncs->cardinit) (card);
95135c4bbdfSmrg        if (ret) {
95235c4bbdfSmrg            for (screen = card->screenList; screen; screen = screen->next)
95335c4bbdfSmrg                KdInitScreen(pScreenInfo, screen, argc, argv);
95435c4bbdfSmrg        }
95505b261ecSmrg    }
9566747b715Smrg
95705b261ecSmrg    /*
95805b261ecSmrg     * Merge the various pixmap formats together, this can fail
95905b261ecSmrg     * when two screens share depth but not bitsPerPixel
96005b261ecSmrg     */
96135c4bbdfSmrg    if (!KdSetPixmapFormats(pScreenInfo))
96235c4bbdfSmrg        return;
9636747b715Smrg
96405b261ecSmrg    /*
96505b261ecSmrg     * Add all of the screens
96605b261ecSmrg     */
96705b261ecSmrg    for (card = kdCardInfo; card; card = card->next)
96835c4bbdfSmrg        for (screen = card->screenList; screen; screen = screen->next)
96935c4bbdfSmrg            KdAddScreen(pScreenInfo, screen, argc, argv);
97005b261ecSmrg
9711b5d61b8Smrg    xorgGlxCreateVendor();
9721b5d61b8Smrg
9731b5d61b8Smrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
9741b5d61b8Smrg    if (SeatId) /* Enable input hot-plugging */
9751b5d61b8Smrg        config_pre_init();
9761b5d61b8Smrg#endif
97705b261ecSmrg}
97805b261ecSmrg
97905b261ecSmrgvoid
98035c4bbdfSmrgOsVendorFatalError(const char *f, va_list args)
9814642e01fSmrg{
9824642e01fSmrg}
9834642e01fSmrg
9841b5d61b8Smrg/* These stubs can be safely removed once we can
9851b5d61b8Smrg * split input and GPU parts in hotplug.h et al. */
9861b5d61b8Smrg#ifdef CONFIG_UDEV_KMS
9871b5d61b8Smrgvoid
9881b5d61b8SmrgNewGPUDeviceRequest(struct OdevAttributes *attribs)
98905b261ecSmrg{
99005b261ecSmrg}
99105b261ecSmrg
9921b5d61b8Smrgvoid
9931b5d61b8SmrgDeleteGPUDeviceRequest(struct OdevAttributes *attribs)
99405b261ecSmrg{
99505b261ecSmrg}
9961b5d61b8Smrg#endif
9971b5d61b8Smrg
998ed6184dfSmrg#if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
9991b5d61b8Smrgstruct xf86_platform_device *
10001b5d61b8Smrgxf86_find_platform_device_by_devnum(int major, int minor)
10011b5d61b8Smrg{
10021b5d61b8Smrg    return NULL;
10031b5d61b8Smrg}
1004ed6184dfSmrg#endif
10051b5d61b8Smrg
10061b5d61b8Smrg#ifdef SYSTEMD_LOGIND
10071b5d61b8Smrgvoid
10081b5d61b8Smrgsystemd_logind_vtenter(void)
10091b5d61b8Smrg{
10101b5d61b8Smrg}
10111b5d61b8Smrg
10121b5d61b8Smrgvoid
10131b5d61b8Smrgsystemd_logind_release_fd(int major, int minor, int fd)
10141b5d61b8Smrg{
10151b5d61b8Smrg    close(fd);
10161b5d61b8Smrg}
10171b5d61b8Smrg#endif
1018