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 95KdSetRootClip (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 183void 184KdDisableScreen (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 204static void 205KdDoSwitchCmd (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 223void 224KdSuspend (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 244void 245KdDisableScreens (void) 246{ 247 KdSuspend (); 248 if (kdEnabled) 249 { 250 if (kdOsFuncs->Disable) 251 (*kdOsFuncs->Disable) (); 252 kdEnabled = FALSE; 253 } 254} 255 256Bool 257KdEnableScreen (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 280void 281KdResume (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 302void 303KdEnableScreens (void) 304{ 305 if (!kdEnabled) 306 { 307 kdEnabled = TRUE; 308 if (kdOsFuncs->Enable) 309 (*kdOsFuncs->Enable) (); 310 } 311 KdResume (); 312} 313 314void 315KdProcessSwitch (void) 316{ 317 if (kdEnabled) 318 KdDisableScreens (); 319 else 320 KdEnableScreens (); 321} 322 323void 324AbortDDX(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 340void 341ddxGiveUp (void) 342{ 343 AbortDDX (); 344} 345 346Bool kdDumbDriver; 347Bool kdSoftCursor; 348 349char * 350KdParseFindNext (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 363Rotation 364KdAddRotation (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 374Rotation 375KdSubRotation (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 385void 386KdParseScreen (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 510void 511KdParseRgba (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 527void 528KdUseMsg (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 548int 549KdProcessArgument (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 678void 679KdOsInit (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 693Bool 694KdAllocatePrivates (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 711Bool 712KdCreateScreenResources (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 730Bool 731KdCloseScreen (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 797Bool 798KdSaveScreen (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 831static Bool 832KdCreateWindow (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 849void 850KdSetSubpixelOrder (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 */ 907static KdScreenInfo *kdCurrentScreen; 908 909Bool 910KdScreenInit(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 1082void 1083KdInitScreen (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 1098static Bool 1099KdSetPixmapFormats (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 1159static void 1160KdAddScreen (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 1196int 1197KdDepthToFb (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 1208static int 1209KdSignalWrapper (int signum) 1210{ 1211 kdCaughtSignal = TRUE; 1212 return 1; /* use generic OS layer cleanup & abort */ 1213} 1214 1215void 1216KdInitOutput (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 1263void 1264OsVendorFatalError(void) 1265{ 1266} 1267 1268int 1269DPMSSet(ClientPtr client, int level) 1270{ 1271 return Success; 1272} 1273 1274Bool 1275DPMSSupported (void) 1276{ 1277 return FALSE; 1278} 1279