1 /*
2  * Copyright © 1999 Keith Packard
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of Keith Packard not be used in
9  * advertising or publicity pertaining to distribution of the software without
10  * specific, written prior permission.  Keith Packard makes no
11  * representations about the suitability of this software for any purpose.  It
12  * is provided "as is" without express or implied warranty.
13  *
14  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20  * PERFORMANCE OF THIS SOFTWARE.
21  */
22 
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
25 #endif
26 #include "kdrive.h"
27 #include <mivalidate.h>
28 #include <dixstruct.h>
29 #include "privates.h"
30 #ifdef RANDR
31 #include <randrstr.h>
32 #endif
33 #include "glx_extinit.h"
34 
35 #ifdef XV
36 #include "kxv.h"
37 #endif
38 
39 #ifdef DPMSExtension
40 #include "dpmsproc.h"
41 #endif
42 
43 #ifdef HAVE_EXECINFO_H
44 #include <execinfo.h>
45 #endif
46 
47 #if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
48 #include <hotplug.h>
49 #endif
50 
51 /* This stub can be safely removed once we can
52  * split input and GPU parts in hotplug.h et al. */
53 #include <systemd-logind.h>
54 
55 typedef struct _kdDepths {
56     CARD8 depth;
57     CARD8 bpp;
58 } KdDepths;
59 
60 KdDepths kdDepths[] = {
61     {1, 1},
62     {4, 4},
63     {8, 8},
64     {15, 16},
65     {16, 16},
66     {24, 32},
67     {32, 32}
68 };
69 
70 #define KD_DEFAULT_BUTTONS 5
71 
72 DevPrivateKeyRec kdScreenPrivateKeyRec;
73 static unsigned long kdGeneration;
74 
75 Bool kdEmulateMiddleButton;
76 Bool kdRawPointerCoordinates;
77 Bool kdDisableZaphod;
78 static Bool kdEnabled;
79 static int kdSubpixelOrder;
80 static char *kdSwitchCmd;
81 static DDXPointRec kdOrigin;
82 Bool kdHasPointer = FALSE;
83 Bool kdHasKbd = FALSE;
84 const char *kdGlobalXkbRules = NULL;
85 const char *kdGlobalXkbModel = NULL;
86 const char *kdGlobalXkbLayout = NULL;
87 const char *kdGlobalXkbVariant = NULL;
88 const char *kdGlobalXkbOptions = NULL;
89 
90 void
KdDisableScreen(ScreenPtr pScreen)91 KdDisableScreen(ScreenPtr pScreen)
92 {
93     KdScreenPriv(pScreen);
94 
95     if (!pScreenPriv->enabled)
96         return;
97     if (!pScreenPriv->closed)
98         SetRootClip(pScreen, ROOT_CLIP_NONE);
99     KdDisableColormap(pScreen);
100     if (!pScreenPriv->screen->dumb && pScreenPriv->card->cfuncs->disableAccel)
101         (*pScreenPriv->card->cfuncs->disableAccel) (pScreen);
102     pScreenPriv->enabled = FALSE;
103 }
104 
105 static void
KdDoSwitchCmd(const char * reason)106 KdDoSwitchCmd(const char *reason)
107 {
108     if (kdSwitchCmd) {
109         char *command;
110         int ret;
111 
112         if (asprintf(&command, "%s %s", kdSwitchCmd, reason) == -1)
113             return;
114 
115         /* Ignore the return value from system; I'm not sure
116          * there's anything more useful to be done when
117          * it fails
118          */
119         ret = system(command);
120         (void) ret;
121         free(command);
122     }
123 }
124 
125 static void
KdSuspend(void)126 KdSuspend(void)
127 {
128     KdCardInfo *card;
129     KdScreenInfo *screen;
130 
131     if (kdEnabled) {
132         for (card = kdCardInfo; card; card = card->next) {
133             for (screen = card->screenList; screen; screen = screen->next)
134                 if (screen->mynum == card->selected && screen->pScreen)
135                     KdDisableScreen(screen->pScreen);
136         }
137         KdDisableInput();
138         KdDoSwitchCmd("suspend");
139     }
140 }
141 
142 static void
KdDisableScreens(void)143 KdDisableScreens(void)
144 {
145     KdSuspend();
146     kdEnabled = FALSE;
147 }
148 
149 Bool
KdEnableScreen(ScreenPtr pScreen)150 KdEnableScreen(ScreenPtr pScreen)
151 {
152     KdScreenPriv(pScreen);
153 
154     if (pScreenPriv->enabled)
155         return TRUE;
156     pScreenPriv->enabled = TRUE;
157     pScreenPriv->dpmsState = KD_DPMS_NORMAL;
158     pScreenPriv->card->selected = pScreenPriv->screen->mynum;
159     if (!pScreenPriv->screen->dumb && pScreenPriv->card->cfuncs->enableAccel)
160         (*pScreenPriv->card->cfuncs->enableAccel) (pScreen);
161     KdEnableColormap(pScreen);
162     SetRootClip(pScreen, ROOT_CLIP_FULL);
163     return TRUE;
164 }
165 
166 void
ddxGiveUp(enum ExitCode error)167 ddxGiveUp(enum ExitCode error)
168 {
169     KdDisableScreens();
170 }
171 
172 static Bool kdDumbDriver;
173 static Bool kdSoftCursor;
174 
175 const char *
KdParseFindNext(const char * cur,const char * delim,char * save,char * last)176 KdParseFindNext(const char *cur, const char *delim, char *save, char *last)
177 {
178     while (*cur && !strchr(delim, *cur)) {
179         *save++ = *cur++;
180     }
181     *save = 0;
182     *last = *cur;
183     if (*cur)
184         cur++;
185     return cur;
186 }
187 
188 Rotation
KdAddRotation(Rotation a,Rotation b)189 KdAddRotation(Rotation a, Rotation b)
190 {
191     Rotation rotate = (a & RR_Rotate_All) * (b & RR_Rotate_All);
192     Rotation reflect = (a & RR_Reflect_All) ^ (b & RR_Reflect_All);
193 
194     if (rotate > RR_Rotate_270)
195         rotate /= (RR_Rotate_270 * RR_Rotate_90);
196     return reflect | rotate;
197 }
198 
199 Rotation
KdSubRotation(Rotation a,Rotation b)200 KdSubRotation(Rotation a, Rotation b)
201 {
202     Rotation rotate = (a & RR_Rotate_All) * 16 / (b & RR_Rotate_All);
203     Rotation reflect = (a & RR_Reflect_All) ^ (b & RR_Reflect_All);
204 
205     if (rotate > RR_Rotate_270)
206         rotate /= (RR_Rotate_270 * RR_Rotate_90);
207     return reflect | rotate;
208 }
209 
210 void
KdParseScreen(KdScreenInfo * screen,const char * arg)211 KdParseScreen(KdScreenInfo * screen, const char *arg)
212 {
213     char delim;
214     char save[1024];
215     int i;
216     int pixels, mm;
217 
218     screen->dumb = kdDumbDriver;
219     screen->softCursor = kdSoftCursor;
220     screen->origin = kdOrigin;
221     screen->randr = RR_Rotate_0;
222     screen->x = 0;
223     screen->y = 0;
224     screen->width = 0;
225     screen->height = 0;
226     screen->width_mm = 0;
227     screen->height_mm = 0;
228     screen->subpixel_order = kdSubpixelOrder;
229     screen->rate = 0;
230     screen->fb.depth = 0;
231     if (!arg)
232         return;
233     if (strlen(arg) >= sizeof(save))
234         return;
235 
236     for (i = 0; i < 2; i++) {
237         arg = KdParseFindNext(arg, "x/+@XY", save, &delim);
238         if (!save[0])
239             return;
240 
241         pixels = atoi(save);
242         mm = 0;
243 
244         if (delim == '/') {
245             arg = KdParseFindNext(arg, "x+@XY", save, &delim);
246             if (!save[0])
247                 return;
248             mm = atoi(save);
249         }
250 
251         if (i == 0) {
252             screen->width = pixels;
253             screen->width_mm = mm;
254         }
255         else {
256             screen->height = pixels;
257             screen->height_mm = mm;
258         }
259         if (delim != 'x' && delim != '+' && delim != '@' &&
260             delim != 'X' && delim != 'Y' &&
261             (delim != '\0' || i == 0))
262             return;
263     }
264 
265     kdOrigin.x += screen->width;
266     kdOrigin.y = 0;
267     kdDumbDriver = FALSE;
268     kdSoftCursor = FALSE;
269     kdSubpixelOrder = SubPixelUnknown;
270 
271     if (delim == '+') {
272         arg = KdParseFindNext(arg, "+@xXY", save, &delim);
273         if (save[0])
274             screen->x = atoi(save);
275     }
276 
277     if (delim == '+') {
278         arg = KdParseFindNext(arg, "@xXY", save, &delim);
279         if (save[0])
280             screen->y = atoi(save);
281     }
282 
283     if (delim == '@') {
284         arg = KdParseFindNext(arg, "xXY", save, &delim);
285         if (save[0]) {
286             int rotate = atoi(save);
287 
288             if (rotate < 45)
289                 screen->randr = RR_Rotate_0;
290             else if (rotate < 135)
291                 screen->randr = RR_Rotate_90;
292             else if (rotate < 225)
293                 screen->randr = RR_Rotate_180;
294             else if (rotate < 315)
295                 screen->randr = RR_Rotate_270;
296             else
297                 screen->randr = RR_Rotate_0;
298         }
299     }
300     if (delim == 'X') {
301         arg = KdParseFindNext(arg, "xY", save, &delim);
302         screen->randr |= RR_Reflect_X;
303     }
304 
305     if (delim == 'Y') {
306         arg = KdParseFindNext(arg, "xY", save, &delim);
307         screen->randr |= RR_Reflect_Y;
308     }
309 
310     arg = KdParseFindNext(arg, "x/,", save, &delim);
311     if (save[0]) {
312         screen->fb.depth = atoi(save);
313         if (delim == '/') {
314             arg = KdParseFindNext(arg, "x,", save, &delim);
315             if (save[0])
316                 screen->fb.bitsPerPixel = atoi(save);
317         }
318         else
319             screen->fb.bitsPerPixel = 0;
320     }
321 
322     if (delim == 'x') {
323         arg = KdParseFindNext(arg, "x", save, &delim);
324         if (save[0])
325             screen->rate = atoi(save);
326     }
327 }
328 
329 static void
KdParseRgba(char * rgba)330 KdParseRgba(char *rgba)
331 {
332     if (!strcmp(rgba, "rgb"))
333         kdSubpixelOrder = SubPixelHorizontalRGB;
334     else if (!strcmp(rgba, "bgr"))
335         kdSubpixelOrder = SubPixelHorizontalBGR;
336     else if (!strcmp(rgba, "vrgb"))
337         kdSubpixelOrder = SubPixelVerticalRGB;
338     else if (!strcmp(rgba, "vbgr"))
339         kdSubpixelOrder = SubPixelVerticalBGR;
340     else if (!strcmp(rgba, "none"))
341         kdSubpixelOrder = SubPixelNone;
342     else
343         kdSubpixelOrder = SubPixelUnknown;
344 }
345 
346 void
KdUseMsg(void)347 KdUseMsg(void)
348 {
349     ErrorF("\nTinyX Device Dependent Usage:\n");
350     ErrorF
351         ("-screen WIDTH[/WIDTHMM]xHEIGHT[/HEIGHTMM][+[-]XOFFSET][+[-]YOFFSET][@ROTATION][X][Y][xDEPTH/BPP[xFREQ]]  Specify screen characteristics\n");
352     ErrorF
353         ("-rgba rgb/bgr/vrgb/vbgr/none   Specify subpixel ordering for LCD panels\n");
354     ErrorF
355         ("-mouse driver [,n,,options]    Specify the pointer driver and its options (n is the number of buttons)\n");
356     ErrorF
357         ("-keybd driver [,,options]      Specify the keyboard driver and its options\n");
358     ErrorF("-xkb-rules       Set default XkbRules value (can be overridden by -keybd options)\n");
359     ErrorF("-xkb-model       Set default XkbModel value (can be overridden by -keybd options)\n");
360     ErrorF("-xkb-layout      Set default XkbLayout value (can be overridden by -keybd options)\n");
361     ErrorF("-xkb-variant     Set default XkbVariant value (can be overridden by -keybd options)\n");
362     ErrorF("-xkb-options     Set default XkbOptions value (can be overridden by -keybd options)\n");
363     ErrorF("-zaphod          Disable cursor screen switching\n");
364     ErrorF("-2button         Emulate 3 button mouse\n");
365     ErrorF("-3button         Disable 3 button mouse emulation\n");
366     ErrorF
367         ("-rawcoord        Don't transform pointer coordinates on rotation\n");
368     ErrorF("-dumb            Disable hardware acceleration\n");
369     ErrorF("-softCursor      Force software cursor\n");
370     ErrorF("-videoTest       Start the server, pause momentarily and exit\n");
371     ErrorF
372         ("-origin X,Y      Locates the next screen in the the virtual screen (Xinerama)\n");
373     ErrorF("-switchCmd       Command to execute on vt switch\n");
374     ErrorF
375         ("vtxx             Use virtual terminal xx instead of the next available\n");
376 }
377 
378 int
KdProcessArgument(int argc,char ** argv,int i)379 KdProcessArgument(int argc, char **argv, int i)
380 {
381     KdCardInfo *card;
382     KdScreenInfo *screen;
383 
384     if (!strcmp(argv[i], "-screen")) {
385         if ((i + 1) < argc) {
386             card = KdCardInfoLast();
387             if (!card) {
388                 InitCard(0);
389                 card = KdCardInfoLast();
390             }
391             if (card) {
392                 screen = KdScreenInfoAdd(card);
393                 KdParseScreen(screen, argv[i + 1]);
394             }
395             else
396                 ErrorF("No matching card found!\n");
397         }
398         else
399             UseMsg();
400         return 2;
401     }
402     if (!strcmp(argv[i], "-zaphod")) {
403         kdDisableZaphod = TRUE;
404         return 1;
405     }
406     if (!strcmp(argv[i], "-3button")) {
407         kdEmulateMiddleButton = FALSE;
408         return 1;
409     }
410     if (!strcmp(argv[i], "-2button")) {
411         kdEmulateMiddleButton = TRUE;
412         return 1;
413     }
414     if (!strcmp(argv[i], "-rawcoord")) {
415         kdRawPointerCoordinates = 1;
416         return 1;
417     }
418     if (!strcmp(argv[i], "-dumb")) {
419         kdDumbDriver = TRUE;
420         return 1;
421     }
422     if (!strcmp(argv[i], "-softCursor")) {
423         kdSoftCursor = TRUE;
424         return 1;
425     }
426     if (!strcmp(argv[i], "-origin")) {
427         if ((i + 1) < argc) {
428             char *x = argv[i + 1];
429             char *y = strchr(x, ',');
430 
431             if (x)
432                 kdOrigin.x = atoi(x);
433             else
434                 kdOrigin.x = 0;
435             if (y)
436                 kdOrigin.y = atoi(y + 1);
437             else
438                 kdOrigin.y = 0;
439         }
440         else
441             UseMsg();
442         return 2;
443     }
444     if (!strcmp(argv[i], "-rgba")) {
445         if ((i + 1) < argc)
446             KdParseRgba(argv[i + 1]);
447         else
448             UseMsg();
449         return 2;
450     }
451     if (!strcmp(argv[i], "-switchCmd")) {
452         if ((i + 1) < argc)
453             kdSwitchCmd = argv[i + 1];
454         else
455             UseMsg();
456         return 2;
457     }
458     if (!strcmp(argv[i], "-xkb-rules")) {
459         if (i + 1 >= argc) {
460             UseMsg();
461             FatalError("Missing argument for option -xkb-rules.\n");
462         }
463         kdGlobalXkbRules = argv[i + 1];
464         return 2;
465     }
466     if (!strcmp(argv[i], "-xkb-model")) {
467         if (i + 1 >= argc) {
468             UseMsg();
469             FatalError("Missing argument for option -xkb-model.\n");
470         }
471         kdGlobalXkbModel = argv[i + 1];
472         return 2;
473     }
474     if (!strcmp(argv[i], "-xkb-layout")) {
475         if (i + 1 >= argc) {
476             UseMsg();
477             FatalError("Missing argument for option -xkb-layout.\n");
478         }
479         kdGlobalXkbLayout = argv[i + 1];
480         return 2;
481     }
482     if (!strcmp(argv[i], "-xkb-variant")) {
483         if (i + 1 >= argc) {
484             UseMsg();
485             FatalError("Missing argument for option -xkb-variant.\n");
486         }
487         kdGlobalXkbVariant = argv[i + 1];
488         return 2;
489     }
490     if (!strcmp(argv[i], "-xkb-options")) {
491         if (i + 1 >= argc) {
492             UseMsg();
493             FatalError("Missing argument for option -xkb-options.\n");
494         }
495         kdGlobalXkbOptions = argv[i + 1];
496         return 2;
497     }
498     if (!strcmp(argv[i], "-mouse") || !strcmp(argv[i], "-pointer")) {
499         if (i + 1 >= argc)
500             UseMsg();
501         KdAddConfigPointer(argv[i + 1]);
502         kdHasPointer = TRUE;
503         return 2;
504     }
505     if (!strcmp(argv[i], "-keybd")) {
506         if (i + 1 >= argc)
507             UseMsg();
508         KdAddConfigKeyboard(argv[i + 1]);
509         kdHasKbd = TRUE;
510         return 2;
511     }
512 
513     return 0;
514 }
515 
516 static Bool
KdAllocatePrivates(ScreenPtr pScreen)517 KdAllocatePrivates(ScreenPtr pScreen)
518 {
519     KdPrivScreenPtr pScreenPriv;
520 
521     if (kdGeneration != serverGeneration)
522         kdGeneration = serverGeneration;
523 
524     if (!dixRegisterPrivateKey(&kdScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
525         return FALSE;
526 
527     pScreenPriv = calloc(1, sizeof(*pScreenPriv));
528     if (!pScreenPriv)
529         return FALSE;
530     KdSetScreenPriv(pScreen, pScreenPriv);
531     return TRUE;
532 }
533 
534 static Bool
KdCreateScreenResources(ScreenPtr pScreen)535 KdCreateScreenResources(ScreenPtr pScreen)
536 {
537     KdScreenPriv(pScreen);
538     KdCardInfo *card = pScreenPriv->card;
539     Bool ret;
540 
541     pScreen->CreateScreenResources = pScreenPriv->CreateScreenResources;
542     if (pScreen->CreateScreenResources)
543         ret = (*pScreen->CreateScreenResources) (pScreen);
544     else
545         ret = -1;
546     pScreenPriv->CreateScreenResources = pScreen->CreateScreenResources;
547     pScreen->CreateScreenResources = KdCreateScreenResources;
548     if (ret && card->cfuncs->createRes)
549         ret = (*card->cfuncs->createRes) (pScreen);
550     return ret;
551 }
552 
553 static Bool
KdCloseScreen(ScreenPtr pScreen)554 KdCloseScreen(ScreenPtr pScreen)
555 {
556     KdScreenPriv(pScreen);
557     KdScreenInfo *screen = pScreenPriv->screen;
558     KdCardInfo *card = pScreenPriv->card;
559     Bool ret;
560 
561     if (card->cfuncs->closeScreen)
562         (*card->cfuncs->closeScreen)(pScreen);
563 
564     pScreenPriv->closed = TRUE;
565     pScreen->CloseScreen = pScreenPriv->CloseScreen;
566 
567     if (pScreen->CloseScreen)
568         ret = (*pScreen->CloseScreen) (pScreen);
569     else
570         ret = TRUE;
571 
572     if (screen->mynum == card->selected)
573         KdDisableScreen(pScreen);
574 
575     if (!pScreenPriv->screen->dumb && card->cfuncs->finiAccel)
576         (*card->cfuncs->finiAccel) (pScreen);
577 
578     if (card->cfuncs->scrfini)
579         (*card->cfuncs->scrfini) (screen);
580 
581     /*
582      * Clean up card when last screen is closed, DIX closes them in
583      * reverse order, thus we check for when the first in the list is closed
584      */
585     if (screen == card->screenList) {
586         if (card->cfuncs->cardfini)
587             (*card->cfuncs->cardfini) (card);
588         /*
589          * Clean up OS when last card is closed
590          */
591         if (card == kdCardInfo) {
592             kdEnabled = FALSE;
593         }
594     }
595 
596     pScreenPriv->screen->pScreen = 0;
597 
598     free((void *) pScreenPriv);
599     return ret;
600 }
601 
602 static Bool
KdSaveScreen(ScreenPtr pScreen,int on)603 KdSaveScreen(ScreenPtr pScreen, int on)
604 {
605     return FALSE;
606 }
607 
608 static Bool
KdCreateWindow(WindowPtr pWin)609 KdCreateWindow(WindowPtr pWin)
610 {
611 #ifndef PHOENIX
612     if (!pWin->parent) {
613         KdScreenPriv(pWin->drawable.pScreen);
614 
615         if (!pScreenPriv->enabled) {
616             RegionEmpty(&pWin->borderClip);
617             RegionBreak(&pWin->clipList);
618         }
619     }
620 #endif
621     return fbCreateWindow(pWin);
622 }
623 
624 void
KdSetSubpixelOrder(ScreenPtr pScreen,Rotation randr)625 KdSetSubpixelOrder(ScreenPtr pScreen, Rotation randr)
626 {
627     KdScreenPriv(pScreen);
628     KdScreenInfo *screen = pScreenPriv->screen;
629     int subpixel_order = screen->subpixel_order;
630     Rotation subpixel_dir;
631     int i;
632 
633     static struct {
634         int subpixel_order;
635         Rotation direction;
636     } orders[] = {
637         {SubPixelHorizontalRGB, RR_Rotate_0},
638         {SubPixelHorizontalBGR, RR_Rotate_180},
639         {SubPixelVerticalRGB, RR_Rotate_270},
640         {SubPixelVerticalBGR, RR_Rotate_90},
641     };
642 
643     static struct {
644         int bit;
645         int normal;
646         int reflect;
647     } reflects[] = {
648         {RR_Reflect_X, SubPixelHorizontalRGB, SubPixelHorizontalBGR},
649         {RR_Reflect_X, SubPixelHorizontalBGR, SubPixelHorizontalRGB},
650         {RR_Reflect_Y, SubPixelVerticalRGB, SubPixelVerticalBGR},
651         {RR_Reflect_Y, SubPixelVerticalRGB, SubPixelVerticalRGB},
652     };
653 
654     /* map subpixel to direction */
655     for (i = 0; i < 4; i++)
656         if (orders[i].subpixel_order == subpixel_order)
657             break;
658     if (i < 4) {
659         subpixel_dir =
660             KdAddRotation(randr & RR_Rotate_All, orders[i].direction);
661 
662         /* map back to subpixel order */
663         for (i = 0; i < 4; i++)
664             if (orders[i].direction & subpixel_dir) {
665                 subpixel_order = orders[i].subpixel_order;
666                 break;
667             }
668         /* reflect */
669         for (i = 0; i < 4; i++)
670             if ((randr & reflects[i].bit) &&
671                 reflects[i].normal == subpixel_order) {
672                 subpixel_order = reflects[i].reflect;
673                 break;
674             }
675     }
676     PictureSetSubpixelOrder(pScreen, subpixel_order);
677 }
678 
679 /* Pass through AddScreen, which doesn't take any closure */
680 static KdScreenInfo *kdCurrentScreen;
681 
682 static Bool
KdScreenInit(ScreenPtr pScreen,int argc,char ** argv)683 KdScreenInit(ScreenPtr pScreen, int argc, char **argv)
684 {
685     KdScreenInfo *screen = kdCurrentScreen;
686     KdCardInfo *card = screen->card;
687     KdPrivScreenPtr pScreenPriv;
688 
689     /*
690      * note that screen->fb is set up for the nominal orientation
691      * of the screen; that means if randr is rotated, the values
692      * there should reflect a rotated frame buffer (or shadow).
693      */
694     Bool rotated = (screen->randr & (RR_Rotate_90 | RR_Rotate_270)) != 0;
695     int width, height, *width_mmp, *height_mmp;
696 
697     KdAllocatePrivates(pScreen);
698 
699     pScreenPriv = KdGetScreenPriv(pScreen);
700 
701     if (!rotated) {
702         width = screen->width;
703         height = screen->height;
704         width_mmp = &screen->width_mm;
705         height_mmp = &screen->height_mm;
706     }
707     else {
708         width = screen->height;
709         height = screen->width;
710         width_mmp = &screen->height_mm;
711         height_mmp = &screen->width_mm;
712     }
713     screen->pScreen = pScreen;
714     pScreenPriv->screen = screen;
715     pScreenPriv->card = card;
716     pScreenPriv->bytesPerPixel = screen->fb.bitsPerPixel >> 3;
717     pScreenPriv->dpmsState = KD_DPMS_NORMAL;
718     pScreen->x = screen->origin.x;
719     pScreen->y = screen->origin.y;
720 
721     if (!monitorResolution)
722         monitorResolution = 75;
723     /*
724      * This is done in this order so that backing store wraps
725      * our GC functions; fbFinishScreenInit initializes MI
726      * backing store
727      */
728     if (!fbSetupScreen(pScreen,
729                        screen->fb.frameBuffer,
730                        width, height,
731                        monitorResolution, monitorResolution,
732                        screen->fb.pixelStride, screen->fb.bitsPerPixel)) {
733         return FALSE;
734     }
735 
736     /*
737      * Set colormap functions
738      */
739     pScreen->InstallColormap = KdInstallColormap;
740     pScreen->UninstallColormap = KdUninstallColormap;
741     pScreen->ListInstalledColormaps = KdListInstalledColormaps;
742     pScreen->StoreColors = KdStoreColors;
743 
744     pScreen->SaveScreen = KdSaveScreen;
745     pScreen->CreateWindow = KdCreateWindow;
746 
747     if (!fbFinishScreenInit(pScreen,
748                             screen->fb.frameBuffer,
749                             width, height,
750                             monitorResolution, monitorResolution,
751                             screen->fb.pixelStride, screen->fb.bitsPerPixel)) {
752         return FALSE;
753     }
754 
755     /*
756      * Fix screen sizes; for some reason mi takes dpi instead of mm.
757      * Rounding errors are annoying
758      */
759     if (*width_mmp)
760         pScreen->mmWidth = *width_mmp;
761     else
762         *width_mmp = pScreen->mmWidth;
763     if (*height_mmp)
764         pScreen->mmHeight = *height_mmp;
765     else
766         *height_mmp = pScreen->mmHeight;
767 
768     /*
769      * Plug in our own block/wakeup handlers.
770      * miScreenInit installs NoopDDA in both places
771      */
772     pScreen->BlockHandler = KdBlockHandler;
773     pScreen->WakeupHandler = KdWakeupHandler;
774 
775     if (!fbPictureInit(pScreen, 0, 0))
776         return FALSE;
777     if (card->cfuncs->initScreen)
778         if (!(*card->cfuncs->initScreen) (pScreen))
779             return FALSE;
780 
781     if (!screen->dumb && card->cfuncs->initAccel)
782         if (!(*card->cfuncs->initAccel) (pScreen))
783             screen->dumb = TRUE;
784 
785     if (card->cfuncs->finishInitScreen)
786         if (!(*card->cfuncs->finishInitScreen) (pScreen))
787             return FALSE;
788 
789     /*
790      * Wrap CloseScreen, the order now is:
791      *  KdCloseScreen
792      *  fbCloseScreen
793      */
794     pScreenPriv->CloseScreen = pScreen->CloseScreen;
795     pScreen->CloseScreen = KdCloseScreen;
796 
797     pScreenPriv->CreateScreenResources = pScreen->CreateScreenResources;
798     pScreen->CreateScreenResources = KdCreateScreenResources;
799 
800     if (screen->softCursor ||
801         !card->cfuncs->initCursor || !(*card->cfuncs->initCursor) (pScreen)) {
802         /* Use MI for cursor display and event queueing. */
803         screen->softCursor = TRUE;
804         miDCInitialize(pScreen, &kdPointerScreenFuncs);
805     }
806 
807     if (!fbCreateDefColormap(pScreen)) {
808         return FALSE;
809     }
810 
811     KdSetSubpixelOrder(pScreen, screen->randr);
812 
813     /*
814      * Enable the hardware
815      */
816     kdEnabled = TRUE;
817 
818     if (screen->mynum == card->selected) {
819         pScreenPriv->enabled = TRUE;
820         KdEnableColormap(pScreen);
821         if (!screen->dumb && card->cfuncs->enableAccel)
822             (*card->cfuncs->enableAccel) (pScreen);
823     }
824 
825     return TRUE;
826 }
827 
828 static void
KdInitScreen(ScreenInfo * pScreenInfo,KdScreenInfo * screen,int argc,char ** argv)829 KdInitScreen(ScreenInfo * pScreenInfo,
830              KdScreenInfo * screen, int argc, char **argv)
831 {
832     KdCardInfo *card = screen->card;
833 
834     if (!(*card->cfuncs->scrinit) (screen))
835         FatalError("Screen initialization failed!\n");
836 
837     if (!card->cfuncs->initAccel)
838         screen->dumb = TRUE;
839     if (!card->cfuncs->initCursor)
840         screen->softCursor = TRUE;
841 }
842 
843 static Bool
KdSetPixmapFormats(ScreenInfo * pScreenInfo)844 KdSetPixmapFormats(ScreenInfo * pScreenInfo)
845 {
846     CARD8 depthToBpp[33];       /* depth -> bpp map */
847     KdCardInfo *card;
848     KdScreenInfo *screen;
849     int i;
850     int bpp;
851     PixmapFormatRec *format;
852 
853     for (i = 1; i <= 32; i++)
854         depthToBpp[i] = 0;
855 
856     /*
857      * Generate mappings between bitsPerPixel and depth,
858      * also ensure that all screens comply with protocol
859      * restrictions on equivalent formats for the same
860      * depth on different screens
861      */
862     for (card = kdCardInfo; card; card = card->next) {
863         for (screen = card->screenList; screen; screen = screen->next) {
864             bpp = screen->fb.bitsPerPixel;
865             if (bpp == 24)
866                 bpp = 32;
867             if (!depthToBpp[screen->fb.depth])
868                 depthToBpp[screen->fb.depth] = bpp;
869             else if (depthToBpp[screen->fb.depth] != bpp)
870                 return FALSE;
871         }
872     }
873 
874     /*
875      * Fill in additional formats
876      */
877     for (i = 0; i < ARRAY_SIZE(kdDepths); i++)
878         if (!depthToBpp[kdDepths[i].depth])
879             depthToBpp[kdDepths[i].depth] = kdDepths[i].bpp;
880 
881     pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
882     pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
883     pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
884     pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
885 
886     pScreenInfo->numPixmapFormats = 0;
887 
888     for (i = 1; i <= 32; i++) {
889         if (depthToBpp[i]) {
890             format = &pScreenInfo->formats[pScreenInfo->numPixmapFormats++];
891             format->depth = i;
892             format->bitsPerPixel = depthToBpp[i];
893             format->scanlinePad = BITMAP_SCANLINE_PAD;
894         }
895     }
896 
897     return TRUE;
898 }
899 
900 static void
KdAddScreen(ScreenInfo * pScreenInfo,KdScreenInfo * screen,int argc,char ** argv)901 KdAddScreen(ScreenInfo * pScreenInfo,
902             KdScreenInfo * screen, int argc, char **argv)
903 {
904     int i;
905 
906     /*
907      * Fill in fb visual type masks for this screen
908      */
909     for (i = 0; i < pScreenInfo->numPixmapFormats; i++) {
910         unsigned long visuals;
911         Pixel rm, gm, bm;
912 
913         visuals = 0;
914         rm = gm = bm = 0;
915         if (pScreenInfo->formats[i].depth == screen->fb.depth) {
916             visuals = screen->fb.visuals;
917             rm = screen->fb.redMask;
918             gm = screen->fb.greenMask;
919             bm = screen->fb.blueMask;
920         }
921         fbSetVisualTypesAndMasks(pScreenInfo->formats[i].depth,
922                                  visuals, 8, rm, gm, bm);
923     }
924 
925     kdCurrentScreen = screen;
926 
927     AddScreen(KdScreenInit, argc, argv);
928 }
929 
930 void
KdInitOutput(ScreenInfo * pScreenInfo,int argc,char ** argv)931 KdInitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
932 {
933     KdCardInfo *card;
934     KdScreenInfo *screen;
935 
936     if (!kdCardInfo) {
937         InitCard(0);
938         if (!(card = KdCardInfoLast()))
939             FatalError("No matching cards found!\n");
940         screen = KdScreenInfoAdd(card);
941         KdParseScreen(screen, 0);
942     }
943     /*
944      * Initialize all of the screens for all of the cards
945      */
946     for (card = kdCardInfo; card; card = card->next) {
947         int ret = 1;
948 
949         if (card->cfuncs->cardinit)
950             ret = (*card->cfuncs->cardinit) (card);
951         if (ret) {
952             for (screen = card->screenList; screen; screen = screen->next)
953                 KdInitScreen(pScreenInfo, screen, argc, argv);
954         }
955     }
956 
957     /*
958      * Merge the various pixmap formats together, this can fail
959      * when two screens share depth but not bitsPerPixel
960      */
961     if (!KdSetPixmapFormats(pScreenInfo))
962         return;
963 
964     /*
965      * Add all of the screens
966      */
967     for (card = kdCardInfo; card; card = card->next)
968         for (screen = card->screenList; screen; screen = screen->next)
969             KdAddScreen(pScreenInfo, screen, argc, argv);
970 
971     xorgGlxCreateVendor();
972 
973 #if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
974     if (SeatId) /* Enable input hot-plugging */
975         config_pre_init();
976 #endif
977 }
978 
979 void
OsVendorFatalError(const char * f,va_list args)980 OsVendorFatalError(const char *f, va_list args)
981 {
982 }
983 
984 /* These stubs can be safely removed once we can
985  * split input and GPU parts in hotplug.h et al. */
986 #ifdef CONFIG_UDEV_KMS
987 void
NewGPUDeviceRequest(struct OdevAttributes * attribs)988 NewGPUDeviceRequest(struct OdevAttributes *attribs)
989 {
990 }
991 
992 void
DeleteGPUDeviceRequest(struct OdevAttributes * attribs)993 DeleteGPUDeviceRequest(struct OdevAttributes *attribs)
994 {
995 }
996 #endif
997 
998 #if defined(CONFIG_UDEV) || defined(CONFIG_HAL)
999 struct xf86_platform_device *
xf86_find_platform_device_by_devnum(int major,int minor)1000 xf86_find_platform_device_by_devnum(int major, int minor)
1001 {
1002     return NULL;
1003 }
1004 #endif
1005 
1006 #ifdef SYSTEMD_LOGIND
1007 void
systemd_logind_vtenter(void)1008 systemd_logind_vtenter(void)
1009 {
1010 }
1011 
1012 void
systemd_logind_release_fd(int major,int minor,int fd)1013 systemd_logind_release_fd(int major, int minor, int fd)
1014 {
1015     close(fd);
1016 }
1017 #endif
1018