Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / kdrive / src / kdrive.c
CommitLineData
a09e091a
JB
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_CONFIG_H
24#include <kdrive-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
34#ifdef XV
35#include "kxv.h"
36#endif
37
38#ifdef DPMSExtension
39#include "dpmsproc.h"
40#endif
41
42#ifdef HAVE_EXECINFO_H
43#include <execinfo.h>
44#endif
45
46#include <signal.h>
47
48typedef struct _kdDepths {
49 CARD8 depth;
50 CARD8 bpp;
51} KdDepths;
52
53KdDepths kdDepths[] = {
54 {1, 1},
55 {4, 4},
56 {8, 8},
57 {15, 16},
58 {16, 16},
59 {24, 32},
60 {32, 32}
61};
62
63#define NUM_KD_DEPTHS (sizeof (kdDepths) / sizeof (kdDepths[0]))
64
65#define KD_DEFAULT_BUTTONS 5
66
67DevPrivateKeyRec kdScreenPrivateKeyRec;
68unsigned long kdGeneration;
69
70Bool kdVideoTest;
71unsigned long kdVideoTestTime;
72Bool kdEmulateMiddleButton;
73Bool kdRawPointerCoordinates;
74Bool kdDisableZaphod;
75Bool kdAllowZap;
76Bool kdEnabled;
77int kdSubpixelOrder;
78int kdVirtualTerminal = -1;
79Bool kdSwitchPending;
80char *kdSwitchCmd;
81DDXPointRec kdOrigin;
82Bool kdHasPointer = FALSE;
83Bool kdHasKbd = FALSE;
84
85static Bool kdCaughtSignal = FALSE;
86
87/*
88 * Carry arguments from InitOutput through driver initialization
89 * to KdScreenInit
90 */
91
92KdOsFuncs *kdOsFuncs;
93
94void
95KdDisableScreen(ScreenPtr pScreen)
96{
97 KdScreenPriv(pScreen);
98
99 if (!pScreenPriv->enabled)
100 return;
101 if (!pScreenPriv->closed)
102 SetRootClip(pScreen, FALSE);
103 KdDisableColormap(pScreen);
104 if (!pScreenPriv->screen->dumb && pScreenPriv->card->cfuncs->disableAccel)
105 (*pScreenPriv->card->cfuncs->disableAccel) (pScreen);
106 if (!pScreenPriv->screen->softCursor &&
107 pScreenPriv->card->cfuncs->disableCursor)
108 (*pScreenPriv->card->cfuncs->disableCursor) (pScreen);
109 if (pScreenPriv->card->cfuncs->dpms)
110 (*pScreenPriv->card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL);
111 pScreenPriv->enabled = FALSE;
112 if (pScreenPriv->card->cfuncs->disable)
113 (*pScreenPriv->card->cfuncs->disable) (pScreen);
114}
115
116static void
117KdDoSwitchCmd(const char *reason)
118{
119 if (kdSwitchCmd) {
120 char *command;
121
122 if (asprintf(&command, "%s %s", kdSwitchCmd, reason) == -1)
123 return;
124 system(command);
125 free(command);
126 }
127}
128
129void
130KdSuspend(void)
131{
132 KdCardInfo *card;
133 KdScreenInfo *screen;
134
135 if (kdEnabled) {
136 for (card = kdCardInfo; card; card = card->next) {
137 for (screen = card->screenList; screen; screen = screen->next)
138 if (screen->mynum == card->selected && screen->pScreen)
139 KdDisableScreen(screen->pScreen);
140 if (card->driver && card->cfuncs->restore)
141 (*card->cfuncs->restore) (card);
142 }
143 KdDisableInput();
144 KdDoSwitchCmd("suspend");
145 }
146}
147
148void
149KdDisableScreens(void)
150{
151 KdSuspend();
152 if (kdEnabled) {
153 if (kdOsFuncs->Disable)
154 (*kdOsFuncs->Disable) ();
155 kdEnabled = FALSE;
156 }
157}
158
159Bool
160KdEnableScreen(ScreenPtr pScreen)
161{
162 KdScreenPriv(pScreen);
163
164 if (pScreenPriv->enabled)
165 return TRUE;
166 if (pScreenPriv->card->cfuncs->enable)
167 if (!(*pScreenPriv->card->cfuncs->enable) (pScreen))
168 return FALSE;
169 pScreenPriv->enabled = TRUE;
170 pScreenPriv->dpmsState = KD_DPMS_NORMAL;
171 pScreenPriv->card->selected = pScreenPriv->screen->mynum;
172 if (!pScreenPriv->screen->softCursor &&
173 pScreenPriv->card->cfuncs->enableCursor)
174 (*pScreenPriv->card->cfuncs->enableCursor) (pScreen);
175 if (!pScreenPriv->screen->dumb && pScreenPriv->card->cfuncs->enableAccel)
176 (*pScreenPriv->card->cfuncs->enableAccel) (pScreen);
177 KdEnableColormap(pScreen);
178 SetRootClip(pScreen, TRUE);
179 if (pScreenPriv->card->cfuncs->dpms)
180 (*pScreenPriv->card->cfuncs->dpms) (pScreen, pScreenPriv->dpmsState);
181 return TRUE;
182}
183
184void
185KdResume(void)
186{
187 KdCardInfo *card;
188 KdScreenInfo *screen;
189
190 if (kdEnabled) {
191 KdDoSwitchCmd("resume");
192 for (card = kdCardInfo; card; card = card->next) {
193 if (card->cfuncs->preserve)
194 (*card->cfuncs->preserve) (card);
195 for (screen = card->screenList; screen; screen = screen->next)
196 if (screen->mynum == card->selected && screen->pScreen)
197 KdEnableScreen(screen->pScreen);
198 }
199 KdEnableInput();
200 KdReleaseAllKeys();
201 }
202}
203
204void
205KdEnableScreens(void)
206{
207 if (!kdEnabled) {
208 kdEnabled = TRUE;
209 if (kdOsFuncs->Enable)
210 (*kdOsFuncs->Enable) ();
211 }
212 KdResume();
213}
214
215void
216KdProcessSwitch(void)
217{
218 if (kdEnabled)
219 KdDisableScreens();
220 else
221 KdEnableScreens();
222}
223
224void
225AbortDDX(enum ExitCode error)
226{
227 KdDisableScreens();
228 if (kdOsFuncs) {
229 if (kdEnabled && kdOsFuncs->Disable)
230 (*kdOsFuncs->Disable) ();
231 if (kdOsFuncs->Fini)
232 (*kdOsFuncs->Fini) ();
233 KdDoSwitchCmd("stop");
234 }
235
236 if (kdCaughtSignal)
237 OsAbort();
238}
239
240void
241ddxGiveUp(enum ExitCode error)
242{
243 AbortDDX(error);
244}
245
246Bool kdDumbDriver;
247Bool kdSoftCursor;
248
249const char *
250KdParseFindNext(const char *cur, const char *delim, char *save, char *last)
251{
252 while (*cur && !strchr(delim, *cur)) {
253 *save++ = *cur++;
254 }
255 *save = 0;
256 *last = *cur;
257 if (*cur)
258 cur++;
259 return cur;
260}
261
262Rotation
263KdAddRotation(Rotation a, Rotation b)
264{
265 Rotation rotate = (a & RR_Rotate_All) * (b & RR_Rotate_All);
266 Rotation reflect = (a & RR_Reflect_All) ^ (b & RR_Reflect_All);
267
268 if (rotate > RR_Rotate_270)
269 rotate /= (RR_Rotate_270 * RR_Rotate_90);
270 return reflect | rotate;
271}
272
273Rotation
274KdSubRotation(Rotation a, Rotation b)
275{
276 Rotation rotate = (a & RR_Rotate_All) * 16 / (b & RR_Rotate_All);
277 Rotation reflect = (a & RR_Reflect_All) ^ (b & RR_Reflect_All);
278
279 if (rotate > RR_Rotate_270)
280 rotate /= (RR_Rotate_270 * RR_Rotate_90);
281 return reflect | rotate;
282}
283
284void
285KdParseScreen(KdScreenInfo * screen, const char *arg)
286{
287 char delim;
288 char save[1024];
289 int i;
290 int pixels, mm;
291
292 screen->dumb = kdDumbDriver;
293 screen->softCursor = kdSoftCursor;
294 screen->origin = kdOrigin;
295 screen->randr = RR_Rotate_0;
296 screen->width = 0;
297 screen->height = 0;
298 screen->width_mm = 0;
299 screen->height_mm = 0;
300 screen->subpixel_order = kdSubpixelOrder;
301 screen->rate = 0;
302 screen->fb.depth = 0;
303 if (!arg)
304 return;
305 if (strlen(arg) >= sizeof(save))
306 return;
307
308 for (i = 0; i < 2; i++) {
309 arg = KdParseFindNext(arg, "x/@XY", save, &delim);
310 if (!save[0])
311 return;
312
313 pixels = atoi(save);
314 mm = 0;
315
316 if (delim == '/') {
317 arg = KdParseFindNext(arg, "x@XY", save, &delim);
318 if (!save[0])
319 return;
320 mm = atoi(save);
321 }
322
323 if (i == 0) {
324 screen->width = pixels;
325 screen->width_mm = mm;
326 }
327 else {
328 screen->height = pixels;
329 screen->height_mm = mm;
330 }
331 if (delim != 'x' && delim != '@' && delim != 'X' && delim != 'Y' &&
332 (delim != '\0' || i == 0))
333 return;
334 }
335
336 kdOrigin.x += screen->width;
337 kdOrigin.y = 0;
338 kdDumbDriver = FALSE;
339 kdSoftCursor = FALSE;
340 kdSubpixelOrder = SubPixelUnknown;
341
342 if (delim == '@') {
343 arg = KdParseFindNext(arg, "xXY", save, &delim);
344 if (save[0]) {
345 int rotate = atoi(save);
346
347 if (rotate < 45)
348 screen->randr = RR_Rotate_0;
349 else if (rotate < 135)
350 screen->randr = RR_Rotate_90;
351 else if (rotate < 225)
352 screen->randr = RR_Rotate_180;
353 else if (rotate < 315)
354 screen->randr = RR_Rotate_270;
355 else
356 screen->randr = RR_Rotate_0;
357 }
358 }
359 if (delim == 'X') {
360 arg = KdParseFindNext(arg, "xY", save, &delim);
361 screen->randr |= RR_Reflect_X;
362 }
363
364 if (delim == 'Y') {
365 arg = KdParseFindNext(arg, "xY", save, &delim);
366 screen->randr |= RR_Reflect_Y;
367 }
368
369 arg = KdParseFindNext(arg, "x/,", save, &delim);
370 if (save[0]) {
371 screen->fb.depth = atoi(save);
372 if (delim == '/') {
373 arg = KdParseFindNext(arg, "x,", save, &delim);
374 if (save[0])
375 screen->fb.bitsPerPixel = atoi(save);
376 }
377 else
378 screen->fb.bitsPerPixel = 0;
379 }
380
381 if (delim == 'x') {
382 arg = KdParseFindNext(arg, "x", save, &delim);
383 if (save[0])
384 screen->rate = atoi(save);
385 }
386}
387
388/*
389 * Mouse argument syntax:
390 *
391 * device,protocol,options...
392 *
393 * Options are any of:
394 * 1-5 n button mouse
395 * 2button emulate middle button
396 * {NMO} Reorder buttons
397 */
398
399void
400KdParseRgba(char *rgba)
401{
402 if (!strcmp(rgba, "rgb"))
403 kdSubpixelOrder = SubPixelHorizontalRGB;
404 else if (!strcmp(rgba, "bgr"))
405 kdSubpixelOrder = SubPixelHorizontalBGR;
406 else if (!strcmp(rgba, "vrgb"))
407 kdSubpixelOrder = SubPixelVerticalRGB;
408 else if (!strcmp(rgba, "vbgr"))
409 kdSubpixelOrder = SubPixelVerticalBGR;
410 else if (!strcmp(rgba, "none"))
411 kdSubpixelOrder = SubPixelNone;
412 else
413 kdSubpixelOrder = SubPixelUnknown;
414}
415
416void
417KdUseMsg(void)
418{
419 ErrorF("\nTinyX Device Dependent Usage:\n");
420 ErrorF
421 ("-screen WIDTH[/WIDTHMM]xHEIGHT[/HEIGHTMM][@ROTATION][X][Y][xDEPTH/BPP[xFREQ]] Specify screen characteristics\n");
422 ErrorF
423 ("-rgba rgb/bgr/vrgb/vbgr/none Specify subpixel ordering for LCD panels\n");
424 ErrorF
425 ("-mouse driver [,n,,options] Specify the pointer driver and its options (n is the number of buttons)\n");
426 ErrorF
427 ("-keybd driver [,,options] Specify the keyboard driver and its options\n");
428 ErrorF("-zaphod Disable cursor screen switching\n");
429 ErrorF("-2button Emulate 3 button mouse\n");
430 ErrorF("-3button Disable 3 button mouse emulation\n");
431 ErrorF
432 ("-rawcoord Don't transform pointer coordinates on rotation\n");
433 ErrorF("-dumb Disable hardware acceleration\n");
434 ErrorF("-softCursor Force software cursor\n");
435 ErrorF("-videoTest Start the server, pause momentarily and exit\n");
436 ErrorF
437 ("-origin X,Y Locates the next screen in the the virtual screen (Xinerama)\n");
438 ErrorF("-switchCmd Command to execute on vt switch\n");
439 ErrorF("-zap Terminate server on Ctrl+Alt+Backspace\n");
440 ErrorF
441 ("vtxx Use virtual terminal xx instead of the next available\n");
442}
443
444int
445KdProcessArgument(int argc, char **argv, int i)
446{
447 KdCardInfo *card;
448 KdScreenInfo *screen;
449
450 if (!strcmp(argv[i], "-screen")) {
451 if ((i + 1) < argc) {
452 card = KdCardInfoLast();
453 if (!card) {
454 InitCard(0);
455 card = KdCardInfoLast();
456 }
457 if (card) {
458 screen = KdScreenInfoAdd(card);
459 KdParseScreen(screen, argv[i + 1]);
460 }
461 else
462 ErrorF("No matching card found!\n");
463 }
464 else
465 UseMsg();
466 return 2;
467 }
468 if (!strcmp(argv[i], "-zaphod")) {
469 kdDisableZaphod = TRUE;
470 return 1;
471 }
472 if (!strcmp(argv[i], "-zap")) {
473 kdAllowZap = TRUE;
474 return 1;
475 }
476 if (!strcmp(argv[i], "-3button")) {
477 kdEmulateMiddleButton = FALSE;
478 return 1;
479 }
480 if (!strcmp(argv[i], "-2button")) {
481 kdEmulateMiddleButton = TRUE;
482 return 1;
483 }
484 if (!strcmp(argv[i], "-rawcoord")) {
485 kdRawPointerCoordinates = 1;
486 return 1;
487 }
488 if (!strcmp(argv[i], "-dumb")) {
489 kdDumbDriver = TRUE;
490 return 1;
491 }
492 if (!strcmp(argv[i], "-softCursor")) {
493 kdSoftCursor = TRUE;
494 return 1;
495 }
496 if (!strcmp(argv[i], "-videoTest")) {
497 kdVideoTest = TRUE;
498 return 1;
499 }
500 if (!strcmp(argv[i], "-origin")) {
501 if ((i + 1) < argc) {
502 char *x = argv[i + 1];
503 char *y = strchr(x, ',');
504
505 if (x)
506 kdOrigin.x = atoi(x);
507 else
508 kdOrigin.x = 0;
509 if (y)
510 kdOrigin.y = atoi(y + 1);
511 else
512 kdOrigin.y = 0;
513 }
514 else
515 UseMsg();
516 return 2;
517 }
518 if (!strcmp(argv[i], "-rgba")) {
519 if ((i + 1) < argc)
520 KdParseRgba(argv[i + 1]);
521 else
522 UseMsg();
523 return 2;
524 }
525 if (!strcmp(argv[i], "-switchCmd")) {
526 if ((i + 1) < argc)
527 kdSwitchCmd = argv[i + 1];
528 else
529 UseMsg();
530 return 2;
531 }
532 if (!strncmp(argv[i], "vt", 2) &&
533 sscanf(argv[i], "vt%2d", &kdVirtualTerminal) == 1) {
534 return 1;
535 }
536 if (!strcmp(argv[i], "-mouse") || !strcmp(argv[i], "-pointer")) {
537 if (i + 1 >= argc)
538 UseMsg();
539 KdAddConfigPointer(argv[i + 1]);
540 kdHasPointer = TRUE;
541 return 2;
542 }
543 if (!strcmp(argv[i], "-keybd")) {
544 if (i + 1 >= argc)
545 UseMsg();
546 KdAddConfigKeyboard(argv[i + 1]);
547 kdHasKbd = TRUE;
548 return 2;
549 }
550
551 return 0;
552}
553
554/*
555 * These are getting tossed in here until I can think of where
556 * they really belong
557 */
558
559void
560KdOsInit(KdOsFuncs * pOsFuncs)
561{
562 kdOsFuncs = pOsFuncs;
563 if (pOsFuncs) {
564 if (serverGeneration == 1) {
565 KdDoSwitchCmd("start");
566 if (pOsFuncs->Init)
567 (*pOsFuncs->Init) ();
568 }
569 }
570}
571
572Bool
573KdAllocatePrivates(ScreenPtr pScreen)
574{
575 KdPrivScreenPtr pScreenPriv;
576
577 if (kdGeneration != serverGeneration)
578 kdGeneration = serverGeneration;
579
580 if (!dixRegisterPrivateKey(&kdScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
581 return FALSE;
582
583 pScreenPriv = calloc(1, sizeof(*pScreenPriv));
584 if (!pScreenPriv)
585 return FALSE;
586 KdSetScreenPriv(pScreen, pScreenPriv);
587 return TRUE;
588}
589
590Bool
591KdCreateScreenResources(ScreenPtr pScreen)
592{
593 KdScreenPriv(pScreen);
594 KdCardInfo *card = pScreenPriv->card;
595 Bool ret;
596
597 pScreen->CreateScreenResources = pScreenPriv->CreateScreenResources;
598 if (pScreen->CreateScreenResources)
599 ret = (*pScreen->CreateScreenResources) (pScreen);
600 else
601 ret = -1;
602 pScreenPriv->CreateScreenResources = pScreen->CreateScreenResources;
603 pScreen->CreateScreenResources = KdCreateScreenResources;
604 if (ret && card->cfuncs->createRes)
605 ret = (*card->cfuncs->createRes) (pScreen);
606 return ret;
607}
608
609Bool
610KdCloseScreen(ScreenPtr pScreen)
611{
612 KdScreenPriv(pScreen);
613 KdScreenInfo *screen = pScreenPriv->screen;
614 KdCardInfo *card = pScreenPriv->card;
615 Bool ret;
616
617 pScreenPriv->closed = TRUE;
618 pScreen->CloseScreen = pScreenPriv->CloseScreen;
619 if (pScreen->CloseScreen)
620 ret = (*pScreen->CloseScreen) (pScreen);
621 else
622 ret = TRUE;
623
624 if (pScreenPriv->dpmsState != KD_DPMS_NORMAL)
625 (*card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL);
626
627 if (screen->mynum == card->selected)
628 KdDisableScreen(pScreen);
629
630 /*
631 * Restore video hardware when last screen is closed
632 */
633 if (screen == card->screenList) {
634 if (kdEnabled && card->cfuncs->restore)
635 (*card->cfuncs->restore) (card);
636 }
637
638 if (!pScreenPriv->screen->dumb && card->cfuncs->finiAccel)
639 (*card->cfuncs->finiAccel) (pScreen);
640
641 if (!pScreenPriv->screen->softCursor && card->cfuncs->finiCursor)
642 (*card->cfuncs->finiCursor) (pScreen);
643
644 if (card->cfuncs->scrfini)
645 (*card->cfuncs->scrfini) (screen);
646
647 /*
648 * Clean up card when last screen is closed, DIX closes them in
649 * reverse order, thus we check for when the first in the list is closed
650 */
651 if (screen == card->screenList) {
652 if (card->cfuncs->cardfini)
653 (*card->cfuncs->cardfini) (card);
654 /*
655 * Clean up OS when last card is closed
656 */
657 if (card == kdCardInfo) {
658 if (kdEnabled) {
659 kdEnabled = FALSE;
660 if (kdOsFuncs->Disable)
661 (*kdOsFuncs->Disable) ();
662 }
663 }
664 }
665
666 pScreenPriv->screen->pScreen = 0;
667
668 free((pointer) pScreenPriv);
669 return ret;
670}
671
672Bool
673KdSaveScreen(ScreenPtr pScreen, int on)
674{
675 KdScreenPriv(pScreen);
676 int dpmsState;
677
678 if (!pScreenPriv->card->cfuncs->dpms)
679 return FALSE;
680
681 dpmsState = pScreenPriv->dpmsState;
682 switch (on) {
683 case SCREEN_SAVER_OFF:
684 dpmsState = KD_DPMS_NORMAL;
685 break;
686 case SCREEN_SAVER_ON:
687 if (dpmsState == KD_DPMS_NORMAL)
688 dpmsState = KD_DPMS_NORMAL + 1;
689 break;
690 case SCREEN_SAVER_CYCLE:
691 if (dpmsState < KD_DPMS_MAX)
692 dpmsState++;
693 break;
694 case SCREEN_SAVER_FORCER:
695 break;
696 }
697 if (dpmsState != pScreenPriv->dpmsState) {
698 if (pScreenPriv->enabled)
699 (*pScreenPriv->card->cfuncs->dpms) (pScreen, dpmsState);
700 pScreenPriv->dpmsState = dpmsState;
701 }
702 return TRUE;
703}
704
705static Bool
706KdCreateWindow(WindowPtr pWin)
707{
708#ifndef PHOENIX
709 if (!pWin->parent) {
710 KdScreenPriv(pWin->drawable.pScreen);
711
712 if (!pScreenPriv->enabled) {
713 RegionEmpty(&pWin->borderClip);
714 RegionBreak(&pWin->clipList);
715 }
716 }
717#endif
718 return fbCreateWindow(pWin);
719}
720
721void
722KdSetSubpixelOrder(ScreenPtr pScreen, Rotation randr)
723{
724 KdScreenPriv(pScreen);
725 KdScreenInfo *screen = pScreenPriv->screen;
726 int subpixel_order = screen->subpixel_order;
727 Rotation subpixel_dir;
728 int i;
729
730 static struct {
731 int subpixel_order;
732 Rotation direction;
733 } orders[] = {
734 {SubPixelHorizontalRGB, RR_Rotate_0},
735 {SubPixelHorizontalBGR, RR_Rotate_180},
736 {SubPixelVerticalRGB, RR_Rotate_270},
737 {SubPixelVerticalBGR, RR_Rotate_90},
738 };
739
740 static struct {
741 int bit;
742 int normal;
743 int reflect;
744 } reflects[] = {
745 {RR_Reflect_X, SubPixelHorizontalRGB, SubPixelHorizontalBGR},
746 {RR_Reflect_X, SubPixelHorizontalBGR, SubPixelHorizontalRGB},
747 {RR_Reflect_Y, SubPixelVerticalRGB, SubPixelVerticalBGR},
748 {RR_Reflect_Y, SubPixelVerticalRGB, SubPixelVerticalRGB},
749 };
750
751 /* map subpixel to direction */
752 for (i = 0; i < 4; i++)
753 if (orders[i].subpixel_order == subpixel_order)
754 break;
755 if (i < 4) {
756 subpixel_dir =
757 KdAddRotation(randr & RR_Rotate_All, orders[i].direction);
758
759 /* map back to subpixel order */
760 for (i = 0; i < 4; i++)
761 if (orders[i].direction & subpixel_dir) {
762 subpixel_order = orders[i].subpixel_order;
763 break;
764 }
765 /* reflect */
766 for (i = 0; i < 4; i++)
767 if ((randr & reflects[i].bit) &&
768 reflects[i].normal == subpixel_order) {
769 subpixel_order = reflects[i].reflect;
770 break;
771 }
772 }
773 PictureSetSubpixelOrder(pScreen, subpixel_order);
774}
775
776/* Pass through AddScreen, which doesn't take any closure */
777static KdScreenInfo *kdCurrentScreen;
778
779Bool
780KdScreenInit(ScreenPtr pScreen, int argc, char **argv)
781{
782 KdScreenInfo *screen = kdCurrentScreen;
783 KdCardInfo *card = screen->card;
784 KdPrivScreenPtr pScreenPriv;
785
786 /*
787 * note that screen->fb is set up for the nominal orientation
788 * of the screen; that means if randr is rotated, the values
789 * there should reflect a rotated frame buffer (or shadow).
790 */
791 Bool rotated = (screen->randr & (RR_Rotate_90 | RR_Rotate_270)) != 0;
792 int width, height, *width_mmp, *height_mmp;
793
794 KdAllocatePrivates(pScreen);
795
796 pScreenPriv = KdGetScreenPriv(pScreen);
797
798 if (!rotated) {
799 width = screen->width;
800 height = screen->height;
801 width_mmp = &screen->width_mm;
802 height_mmp = &screen->height_mm;
803 }
804 else {
805 width = screen->height;
806 height = screen->width;
807 width_mmp = &screen->height_mm;
808 height_mmp = &screen->width_mm;
809 }
810 screen->pScreen = pScreen;
811 pScreenPriv->screen = screen;
812 pScreenPriv->card = card;
813 pScreenPriv->bytesPerPixel = screen->fb.bitsPerPixel >> 3;
814 pScreenPriv->dpmsState = KD_DPMS_NORMAL;
815 pScreen->x = screen->origin.x;
816 pScreen->y = screen->origin.y;
817
818 if (!monitorResolution)
819 monitorResolution = 75;
820 /*
821 * This is done in this order so that backing store wraps
822 * our GC functions; fbFinishScreenInit initializes MI
823 * backing store
824 */
825 if (!fbSetupScreen(pScreen,
826 screen->fb.frameBuffer,
827 width, height,
828 monitorResolution, monitorResolution,
829 screen->fb.pixelStride, screen->fb.bitsPerPixel)) {
830 return FALSE;
831 }
832
833 /*
834 * Set colormap functions
835 */
836 pScreen->InstallColormap = KdInstallColormap;
837 pScreen->UninstallColormap = KdUninstallColormap;
838 pScreen->ListInstalledColormaps = KdListInstalledColormaps;
839 pScreen->StoreColors = KdStoreColors;
840
841 pScreen->SaveScreen = KdSaveScreen;
842 pScreen->CreateWindow = KdCreateWindow;
843
844 if (!fbFinishScreenInit(pScreen,
845 screen->fb.frameBuffer,
846 width, height,
847 monitorResolution, monitorResolution,
848 screen->fb.pixelStride, screen->fb.bitsPerPixel)) {
849 return FALSE;
850 }
851
852 /*
853 * Fix screen sizes; for some reason mi takes dpi instead of mm.
854 * Rounding errors are annoying
855 */
856 if (*width_mmp)
857 pScreen->mmWidth = *width_mmp;
858 else
859 *width_mmp = pScreen->mmWidth;
860 if (*height_mmp)
861 pScreen->mmHeight = *height_mmp;
862 else
863 *height_mmp = pScreen->mmHeight;
864
865 /*
866 * Plug in our own block/wakeup handlers.
867 * miScreenInit installs NoopDDA in both places
868 */
869 pScreen->BlockHandler = KdBlockHandler;
870 pScreen->WakeupHandler = KdWakeupHandler;
871
872 if (!fbPictureInit(pScreen, 0, 0))
873 return FALSE;
874 if (card->cfuncs->initScreen)
875 if (!(*card->cfuncs->initScreen) (pScreen))
876 return FALSE;
877
878 if (!screen->dumb && card->cfuncs->initAccel)
879 if (!(*card->cfuncs->initAccel) (pScreen))
880 screen->dumb = TRUE;
881
882 if (card->cfuncs->finishInitScreen)
883 if (!(*card->cfuncs->finishInitScreen) (pScreen))
884 return FALSE;
885
886#if 0
887 fbInitValidateTree(pScreen);
888#endif
889
890 /*
891 * Wrap CloseScreen, the order now is:
892 * KdCloseScreen
893 * miBSCloseScreen
894 * fbCloseScreen
895 */
896 pScreenPriv->CloseScreen = pScreen->CloseScreen;
897 pScreen->CloseScreen = KdCloseScreen;
898
899 pScreenPriv->CreateScreenResources = pScreen->CreateScreenResources;
900 pScreen->CreateScreenResources = KdCreateScreenResources;
901
902 if (screen->softCursor ||
903 !card->cfuncs->initCursor || !(*card->cfuncs->initCursor) (pScreen)) {
904 /* Use MI for cursor display and event queueing. */
905 screen->softCursor = TRUE;
906 miDCInitialize(pScreen, &kdPointerScreenFuncs);
907 }
908
909 if (!fbCreateDefColormap(pScreen)) {
910 return FALSE;
911 }
912
913 KdSetSubpixelOrder(pScreen, screen->randr);
914
915 /*
916 * Enable the hardware
917 */
918 if (!kdEnabled) {
919 kdEnabled = TRUE;
920 if (kdOsFuncs->Enable)
921 (*kdOsFuncs->Enable) ();
922 }
923
924 if (screen->mynum == card->selected) {
925 if (card->cfuncs->preserve)
926 (*card->cfuncs->preserve) (card);
927 if (card->cfuncs->enable)
928 if (!(*card->cfuncs->enable) (pScreen))
929 return FALSE;
930 pScreenPriv->enabled = TRUE;
931 if (!screen->softCursor && card->cfuncs->enableCursor)
932 (*card->cfuncs->enableCursor) (pScreen);
933 KdEnableColormap(pScreen);
934 if (!screen->dumb && card->cfuncs->enableAccel)
935 (*card->cfuncs->enableAccel) (pScreen);
936 }
937
938 return TRUE;
939}
940
941void
942KdInitScreen(ScreenInfo * pScreenInfo,
943 KdScreenInfo * screen, int argc, char **argv)
944{
945 KdCardInfo *card = screen->card;
946
947 if (!(*card->cfuncs->scrinit) (screen))
948 FatalError("Screen initialization failed!\n");
949
950 if (!card->cfuncs->initAccel)
951 screen->dumb = TRUE;
952 if (!card->cfuncs->initCursor)
953 screen->softCursor = TRUE;
954}
955
956static Bool
957KdSetPixmapFormats(ScreenInfo * pScreenInfo)
958{
959 CARD8 depthToBpp[33]; /* depth -> bpp map */
960 KdCardInfo *card;
961 KdScreenInfo *screen;
962 int i;
963 int bpp;
964 PixmapFormatRec *format;
965
966 for (i = 1; i <= 32; i++)
967 depthToBpp[i] = 0;
968
969 /*
970 * Generate mappings between bitsPerPixel and depth,
971 * also ensure that all screens comply with protocol
972 * restrictions on equivalent formats for the same
973 * depth on different screens
974 */
975 for (card = kdCardInfo; card; card = card->next) {
976 for (screen = card->screenList; screen; screen = screen->next) {
977 bpp = screen->fb.bitsPerPixel;
978 if (bpp == 24)
979 bpp = 32;
980 if (!depthToBpp[screen->fb.depth])
981 depthToBpp[screen->fb.depth] = bpp;
982 else if (depthToBpp[screen->fb.depth] != bpp)
983 return FALSE;
984 }
985 }
986
987 /*
988 * Fill in additional formats
989 */
990 for (i = 0; i < NUM_KD_DEPTHS; i++)
991 if (!depthToBpp[kdDepths[i].depth])
992 depthToBpp[kdDepths[i].depth] = kdDepths[i].bpp;
993
994 pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
995 pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
996 pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
997 pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
998
999 pScreenInfo->numPixmapFormats = 0;
1000
1001 for (i = 1; i <= 32; i++) {
1002 if (depthToBpp[i]) {
1003 format = &pScreenInfo->formats[pScreenInfo->numPixmapFormats++];
1004 format->depth = i;
1005 format->bitsPerPixel = depthToBpp[i];
1006 format->scanlinePad = BITMAP_SCANLINE_PAD;
1007 }
1008 }
1009
1010 return TRUE;
1011}
1012
1013static void
1014KdAddScreen(ScreenInfo * pScreenInfo,
1015 KdScreenInfo * screen, int argc, char **argv)
1016{
1017 int i;
1018
1019 /*
1020 * Fill in fb visual type masks for this screen
1021 */
1022 for (i = 0; i < pScreenInfo->numPixmapFormats; i++) {
1023 unsigned long visuals;
1024 Pixel rm, gm, bm;
1025
1026 visuals = 0;
1027 rm = gm = bm = 0;
1028 if (pScreenInfo->formats[i].depth == screen->fb.depth) {
1029 visuals = screen->fb.visuals;
1030 rm = screen->fb.redMask;
1031 gm = screen->fb.greenMask;
1032 bm = screen->fb.blueMask;
1033 }
1034 fbSetVisualTypesAndMasks(pScreenInfo->formats[i].depth,
1035 visuals, 8, rm, gm, bm);
1036 }
1037
1038 kdCurrentScreen = screen;
1039
1040 AddScreen(KdScreenInit, argc, argv);
1041}
1042
1043#if 0 /* This function is not used currently */
1044
1045int
1046KdDepthToFb(ScreenPtr pScreen, int depth)
1047{
1048 KdScreenPriv(pScreen);
1049
1050 for (fb = 0; fb <= KD_MAX_FB && pScreenPriv->screen->fb.frameBuffer; fb++)
1051 if (pScreenPriv->screen->fb.depth == depth)
1052 return fb;
1053}
1054
1055#endif
1056
1057static int
1058KdSignalWrapper(int signum)
1059{
1060 kdCaughtSignal = TRUE;
1061 return 1; /* use generic OS layer cleanup & abort */
1062}
1063
1064void
1065KdInitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
1066{
1067 KdCardInfo *card;
1068 KdScreenInfo *screen;
1069
1070 if (!kdCardInfo) {
1071 InitCard(0);
1072 if (!(card = KdCardInfoLast()))
1073 FatalError("No matching cards found!\n");
1074 screen = KdScreenInfoAdd(card);
1075 KdParseScreen(screen, 0);
1076 }
1077 /*
1078 * Initialize all of the screens for all of the cards
1079 */
1080 for (card = kdCardInfo; card; card = card->next) {
1081 int ret = 1;
1082
1083 if (card->cfuncs->cardinit)
1084 ret = (*card->cfuncs->cardinit) (card);
1085 if (ret) {
1086 for (screen = card->screenList; screen; screen = screen->next)
1087 KdInitScreen(pScreenInfo, screen, argc, argv);
1088 }
1089 }
1090
1091 /*
1092 * Merge the various pixmap formats together, this can fail
1093 * when two screens share depth but not bitsPerPixel
1094 */
1095 if (!KdSetPixmapFormats(pScreenInfo))
1096 return;
1097
1098 /*
1099 * Add all of the screens
1100 */
1101 for (card = kdCardInfo; card; card = card->next)
1102 for (screen = card->screenList; screen; screen = screen->next)
1103 KdAddScreen(pScreenInfo, screen, argc, argv);
1104
1105 OsRegisterSigWrapper(KdSignalWrapper);
1106}
1107
1108void
1109OsVendorFatalError(const char *f, va_list args)
1110{
1111}
1112
1113int
1114DPMSSet(ClientPtr client, int level)
1115{
1116 return Success;
1117}
1118
1119Bool
1120DPMSSupported(void)
1121{
1122 return FALSE;
1123}