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