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