xf86VidMode.c revision 05b261ec
1/* 2 * Copyright (c) 1999-2003 by The XFree86 Project, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Except as contained in this notice, the name of the copyright holder(s) 23 * and author(s) shall not be used in advertising or otherwise to promote 24 * the sale, use or other dealings in this Software without prior written 25 * authorization from the copyright holder(s) and author(s). 26 */ 27 28/* 29 * This file contains the VidMode functions required by the extension. 30 * These have been added to avoid the need for the higher level extension 31 * code to access the private XFree86 data structures directly. Wherever 32 * possible this code uses the functions in xf86Mode.c to do the work, 33 * so that two version of code that do similar things don't have to be 34 * maintained. 35 */ 36 37#ifdef HAVE_XORG_CONFIG_H 38#include <xorg-config.h> 39#endif 40 41#include <X11/X.h> 42#include "os.h" 43#include "xf86.h" 44#include "xf86Priv.h" 45 46#ifdef XF86VIDMODE 47#include "vidmodeproc.h" 48#include "xf86cmap.h" 49 50static int VidModeGeneration = 0; 51static int VidModeIndex = -1; 52static int VidModeCount = 0; 53static Bool VidModeClose(int i, ScreenPtr pScreen); 54 55#define VMPTR(p) ((VidModePtr)(p)->devPrivates[VidModeIndex].ptr) 56 57#endif 58 59#ifdef DEBUG 60# define DEBUG_P(x) ErrorF(x"\n"); 61#else 62# define DEBUG_P(x) /**/ 63#endif 64 65_X_EXPORT Bool 66VidModeExtensionInit(ScreenPtr pScreen) 67{ 68#ifdef XF86VIDMODE 69 VidModePtr pVidMode; 70 71 if (!xf86GetVidModeEnabled()) { 72 DEBUG_P("!xf86GetVidModeEnabled()"); 73 return FALSE; 74 } 75 76 if (serverGeneration != VidModeGeneration) { 77 if ((VidModeIndex = AllocateScreenPrivateIndex()) < 0) { 78 DEBUG_P("AllocateScreenPrivateIndex() failed"); 79 return FALSE; 80 } 81 VidModeGeneration = serverGeneration; 82 } 83 84 if (!(pScreen->devPrivates[VidModeIndex].ptr = xcalloc(sizeof(VidModeRec), 1))) { 85 DEBUG_P("xcalloc failed"); 86 return FALSE; 87 } 88 89 pVidMode = VMPTR(pScreen); 90 pVidMode->Flags = 0; 91 pVidMode->Next = NULL; 92 pVidMode->CloseScreen = pScreen->CloseScreen; 93 pScreen->CloseScreen = VidModeClose; 94 VidModeCount++; 95 return TRUE; 96#else 97 DEBUG_P("no vidmode extension"); 98 return FALSE; 99#endif 100} 101 102 103#ifdef XF86VIDMODE 104 105static Bool 106VidModeClose(int i, ScreenPtr pScreen) 107{ 108 VidModePtr pVidMode = VMPTR(pScreen); 109 110 /* This shouldn't happen */ 111 if (!pVidMode) 112 return FALSE; 113 114 pScreen->CloseScreen = pVidMode->CloseScreen; 115 116 if (--VidModeCount == 0) { 117 if (pScreen->devPrivates[VidModeIndex].ptr) 118 xfree(pScreen->devPrivates[VidModeIndex].ptr); 119 pScreen->devPrivates[VidModeIndex].ptr = NULL; 120 VidModeIndex = -1; 121 } 122 return pScreen->CloseScreen(i, pScreen); 123} 124 125Bool 126VidModeAvailable(int scrnIndex) 127{ 128 ScrnInfoPtr pScrn; 129 VidModePtr pVidMode; 130 131 if (VidModeIndex < 0) { 132 DEBUG_P("VidModeIndex < 0"); 133 return FALSE; 134 } 135 136 pScrn = xf86Screens[scrnIndex]; 137 if (pScrn == NULL) { 138 DEBUG_P("pScrn == NULL"); 139 return FALSE; 140 } 141 142 pVidMode = VMPTR(pScrn->pScreen); 143 if (pVidMode) 144 return TRUE; 145 else { 146 DEBUG_P("pVidMode == NULL"); 147 return FALSE; 148 } 149} 150 151_X_EXPORT Bool 152VidModeGetCurrentModeline(int scrnIndex, pointer *mode, int *dotClock) 153{ 154 ScrnInfoPtr pScrn; 155 156 if (!VidModeAvailable(scrnIndex)) 157 return FALSE; 158 159 pScrn = xf86Screens[scrnIndex]; 160 *mode = (pointer)(pScrn->currentMode); 161 *dotClock = pScrn->currentMode->Clock; 162 163 return TRUE; 164} 165 166_X_EXPORT int 167VidModeGetDotClock(int scrnIndex, int Clock) 168{ 169 ScrnInfoPtr pScrn; 170 171 if (!VidModeAvailable(scrnIndex)) 172 return 0; 173 174 pScrn = xf86Screens[scrnIndex]; 175 if ((pScrn->progClock) || (Clock >= MAXCLOCKS)) 176 return Clock; 177 else 178 return pScrn->clock[Clock]; 179} 180 181_X_EXPORT int 182VidModeGetNumOfClocks(int scrnIndex, Bool *progClock) 183{ 184 ScrnInfoPtr pScrn; 185 186 if (!VidModeAvailable(scrnIndex)) 187 return 0; 188 189 pScrn = xf86Screens[scrnIndex]; 190 if (pScrn->progClock){ 191 *progClock = TRUE; 192 return 0; 193 } else { 194 *progClock = FALSE; 195 return pScrn->numClocks; 196 } 197} 198 199_X_EXPORT Bool 200VidModeGetClocks(int scrnIndex, int *Clocks) 201{ 202 ScrnInfoPtr pScrn; 203 int i; 204 205 if (!VidModeAvailable(scrnIndex)) 206 return FALSE; 207 208 pScrn = xf86Screens[scrnIndex]; 209 210 if (pScrn->progClock) 211 return FALSE; 212 213 for (i = 0; i < pScrn->numClocks; i++) 214 *Clocks++ = pScrn->clock[i]; 215 216 return TRUE; 217} 218 219 220_X_EXPORT Bool 221VidModeGetFirstModeline(int scrnIndex, pointer *mode, int *dotClock) 222{ 223 ScrnInfoPtr pScrn; 224 VidModePtr pVidMode; 225 226 if (!VidModeAvailable(scrnIndex)) 227 return FALSE; 228 229 pScrn = xf86Screens[scrnIndex]; 230 pVidMode = VMPTR(pScrn->pScreen); 231 pVidMode->First = pScrn->modes; 232 pVidMode->Next = pVidMode->First->next; 233 234 if (pVidMode->First->status == MODE_OK) { 235 *mode = (pointer)(pVidMode->First); 236 *dotClock = VidModeGetDotClock(scrnIndex, pVidMode->First->Clock); 237 return TRUE; 238 } 239 240 return VidModeGetNextModeline(scrnIndex, mode, dotClock); 241} 242 243_X_EXPORT Bool 244VidModeGetNextModeline(int scrnIndex, pointer *mode, int *dotClock) 245{ 246 ScrnInfoPtr pScrn; 247 VidModePtr pVidMode; 248 DisplayModePtr p; 249 250 if (!VidModeAvailable(scrnIndex)) 251 return FALSE; 252 253 pScrn = xf86Screens[scrnIndex]; 254 pVidMode = VMPTR(pScrn->pScreen); 255 256 for (p = pVidMode->Next; p != NULL && p != pVidMode->First; p = p->next) { 257 if (p->status == MODE_OK) { 258 pVidMode->Next = p->next; 259 *mode = (pointer)p; 260 *dotClock = VidModeGetDotClock(scrnIndex, p->Clock); 261 return TRUE; 262 } 263 } 264 265 return FALSE; 266} 267 268_X_EXPORT Bool 269VidModeDeleteModeline(int scrnIndex, pointer mode) 270{ 271 ScrnInfoPtr pScrn; 272 273 if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) 274 return FALSE; 275 276 pScrn = xf86Screens[scrnIndex]; 277 xf86DeleteMode(&(pScrn->modes), (DisplayModePtr)mode); 278 return TRUE; 279} 280 281_X_EXPORT Bool 282VidModeZoomViewport(int scrnIndex, int zoom) 283{ 284 ScrnInfoPtr pScrn; 285 286 if (!VidModeAvailable(scrnIndex)) 287 return FALSE; 288 289 pScrn = xf86Screens[scrnIndex]; 290 xf86ZoomViewport(pScrn->pScreen, zoom); 291 return TRUE; 292} 293 294_X_EXPORT Bool 295VidModeSetViewPort(int scrnIndex, int x, int y) 296{ 297 ScrnInfoPtr pScrn; 298 299 if (!VidModeAvailable(scrnIndex)) 300 return FALSE; 301 302 pScrn = xf86Screens[scrnIndex]; 303 pScrn->frameX0 = min( max(x, 0), 304 pScrn->virtualX - pScrn->currentMode->HDisplay ); 305 pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1; 306 pScrn->frameY0 = min( max(y, 0), 307 pScrn->virtualY - pScrn->currentMode->VDisplay ); 308 pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1; 309 if (pScrn->AdjustFrame != NULL) 310 (pScrn->AdjustFrame)(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 311 312 return TRUE; 313} 314 315_X_EXPORT Bool 316VidModeGetViewPort(int scrnIndex, int *x, int *y) 317{ 318 ScrnInfoPtr pScrn; 319 320 if (!VidModeAvailable(scrnIndex)) 321 return FALSE; 322 323 pScrn = xf86Screens[scrnIndex]; 324 *x = pScrn->frameX0; 325 *y = pScrn->frameY0; 326 return TRUE; 327} 328 329_X_EXPORT Bool 330VidModeSwitchMode(int scrnIndex, pointer mode) 331{ 332 ScrnInfoPtr pScrn; 333 DisplayModePtr pTmpMode; 334 Bool retval; 335 336 if (!VidModeAvailable(scrnIndex)) 337 return FALSE; 338 339 pScrn = xf86Screens[scrnIndex]; 340 /* save in case we fail */ 341 pTmpMode = pScrn->currentMode; 342 /* Force a mode switch */ 343 pScrn->currentMode = NULL; 344 retval = xf86SwitchMode(pScrn->pScreen, mode); 345 /* we failed: restore it */ 346 if (retval == FALSE) 347 pScrn->currentMode = pTmpMode; 348 return retval; 349} 350 351_X_EXPORT Bool 352VidModeLockZoom(int scrnIndex, Bool lock) 353{ 354 ScrnInfoPtr pScrn; 355 356 if (!VidModeAvailable(scrnIndex)) 357 return FALSE; 358 359 pScrn = xf86Screens[scrnIndex]; 360 361 if (xf86Info.dontZoom) 362 return FALSE; 363 364 xf86LockZoom(pScrn->pScreen, lock); 365 return TRUE; 366} 367 368_X_EXPORT Bool 369VidModeGetMonitor(int scrnIndex, pointer *monitor) 370{ 371 ScrnInfoPtr pScrn; 372 373 if (!VidModeAvailable(scrnIndex)) 374 return FALSE; 375 376 pScrn = xf86Screens[scrnIndex]; 377 *monitor = (pointer)(pScrn->monitor); 378 379 return TRUE; 380} 381 382_X_EXPORT ModeStatus 383VidModeCheckModeForMonitor(int scrnIndex, pointer mode) 384{ 385 ScrnInfoPtr pScrn; 386 387 if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) 388 return MODE_ERROR; 389 390 pScrn = xf86Screens[scrnIndex]; 391 392 return xf86CheckModeForMonitor((DisplayModePtr)mode, pScrn->monitor); 393} 394 395_X_EXPORT ModeStatus 396VidModeCheckModeForDriver(int scrnIndex, pointer mode) 397{ 398 ScrnInfoPtr pScrn; 399 400 if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) 401 return MODE_ERROR; 402 403 pScrn = xf86Screens[scrnIndex]; 404 405 return xf86CheckModeForDriver(pScrn, (DisplayModePtr)mode, 0); 406} 407 408_X_EXPORT void 409VidModeSetCrtcForMode(int scrnIndex, pointer mode) 410{ 411 ScrnInfoPtr pScrn; 412 DisplayModePtr ScreenModes; 413 414 if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) 415 return; 416 417 /* Ugly hack so that the xf86Mode.c function can be used without change */ 418 pScrn = xf86Screens[scrnIndex]; 419 ScreenModes = pScrn->modes; 420 pScrn->modes = (DisplayModePtr)mode; 421 422 xf86SetCrtcForModes(pScrn, pScrn->adjustFlags); 423 pScrn->modes = ScreenModes; 424 return; 425} 426 427_X_EXPORT Bool 428VidModeAddModeline(int scrnIndex, pointer mode) 429{ 430 ScrnInfoPtr pScrn; 431 432 if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) 433 return FALSE; 434 435 pScrn = xf86Screens[scrnIndex]; 436 437 ((DisplayModePtr)mode)->name = strdup(""); /* freed by deletemode */ 438 ((DisplayModePtr)mode)->status = MODE_OK; 439 ((DisplayModePtr)mode)->next = pScrn->modes->next; 440 ((DisplayModePtr)mode)->prev = pScrn->modes; 441 pScrn->modes->next = (DisplayModePtr)mode; 442 if( ((DisplayModePtr)mode)->next != NULL ) 443 ((DisplayModePtr)mode)->next->prev = (DisplayModePtr)mode; 444 445 return TRUE; 446} 447 448_X_EXPORT int 449VidModeGetNumOfModes(int scrnIndex) 450{ 451 pointer mode = NULL; 452 int dotClock= 0, nummodes = 0; 453 454 if (!VidModeGetFirstModeline(scrnIndex, &mode, &dotClock)) 455 return nummodes; 456 457 do { 458 nummodes++; 459 if (!VidModeGetNextModeline(scrnIndex, &mode, &dotClock)) 460 return nummodes; 461 } while (TRUE); 462} 463 464_X_EXPORT Bool 465VidModeSetGamma(int scrnIndex, float red, float green, float blue) 466{ 467 ScrnInfoPtr pScrn; 468 Gamma gamma; 469 470 if (!VidModeAvailable(scrnIndex)) 471 return FALSE; 472 473 pScrn = xf86Screens[scrnIndex]; 474 gamma.red = red; 475 gamma.green = green; 476 gamma.blue = blue; 477 if (xf86ChangeGamma(pScrn->pScreen, gamma) != Success) 478 return FALSE; 479 else 480 return TRUE; 481} 482 483_X_EXPORT Bool 484VidModeGetGamma(int scrnIndex, float *red, float *green, float *blue) 485{ 486 ScrnInfoPtr pScrn; 487 488 if (!VidModeAvailable(scrnIndex)) 489 return FALSE; 490 491 pScrn = xf86Screens[scrnIndex]; 492 *red = pScrn->gamma.red; 493 *green = pScrn->gamma.green; 494 *blue = pScrn->gamma.blue; 495 return TRUE; 496} 497 498_X_EXPORT Bool 499VidModeSetGammaRamp(int scrnIndex, int size, CARD16 *r, CARD16 *g, CARD16 *b) 500{ 501 ScrnInfoPtr pScrn; 502 503 if (!VidModeAvailable(scrnIndex)) 504 return FALSE; 505 506 pScrn = xf86Screens[scrnIndex]; 507 xf86ChangeGammaRamp(pScrn->pScreen, size, r, g, b); 508 return TRUE; 509} 510 511_X_EXPORT Bool 512VidModeGetGammaRamp(int scrnIndex, int size, CARD16 *r, CARD16 *g, CARD16 *b) 513{ 514 ScrnInfoPtr pScrn; 515 516 if (!VidModeAvailable(scrnIndex)) 517 return FALSE; 518 519 pScrn = xf86Screens[scrnIndex]; 520 xf86GetGammaRamp(pScrn->pScreen, size, r, g, b); 521 return TRUE; 522} 523 524_X_EXPORT int 525VidModeGetGammaRampSize(int scrnIndex) 526{ 527 if (!VidModeAvailable(scrnIndex)) 528 return 0; 529 530 return xf86GetGammaRampSize(xf86Screens[scrnIndex]->pScreen); 531} 532 533_X_EXPORT pointer 534VidModeCreateMode(void) 535{ 536 DisplayModePtr mode; 537 538 mode = xalloc(sizeof(DisplayModeRec)); 539 if (mode != NULL) { 540 mode->name = ""; 541 mode->VScan = 1; /* divides refresh rate. default = 1 */ 542 mode->Private = NULL; 543 mode->next = mode; 544 mode->prev = mode; 545 } 546 return mode; 547} 548 549_X_EXPORT void 550VidModeCopyMode(pointer modefrom, pointer modeto) 551{ 552 memcpy(modeto, modefrom, sizeof(DisplayModeRec)); 553} 554 555 556_X_EXPORT int 557VidModeGetModeValue(pointer mode, int valtyp) 558{ 559 int ret = 0; 560 561 switch (valtyp) { 562 case VIDMODE_H_DISPLAY: 563 ret = ((DisplayModePtr) mode)->HDisplay; 564 break; 565 case VIDMODE_H_SYNCSTART: 566 ret = ((DisplayModePtr)mode)->HSyncStart; 567 break; 568 case VIDMODE_H_SYNCEND: 569 ret = ((DisplayModePtr)mode)->HSyncEnd; 570 break; 571 case VIDMODE_H_TOTAL: 572 ret = ((DisplayModePtr)mode)->HTotal; 573 break; 574 case VIDMODE_H_SKEW: 575 ret = ((DisplayModePtr)mode)->HSkew; 576 break; 577 case VIDMODE_V_DISPLAY: 578 ret = ((DisplayModePtr)mode)->VDisplay; 579 break; 580 case VIDMODE_V_SYNCSTART: 581 ret = ((DisplayModePtr)mode)->VSyncStart; 582 break; 583 case VIDMODE_V_SYNCEND: 584 ret = ((DisplayModePtr)mode)->VSyncEnd; 585 break; 586 case VIDMODE_V_TOTAL: 587 ret = ((DisplayModePtr)mode)->VTotal; 588 break; 589 case VIDMODE_FLAGS: 590 ret = ((DisplayModePtr)mode)->Flags; 591 break; 592 case VIDMODE_CLOCK: 593 ret = ((DisplayModePtr)mode)->Clock; 594 break; 595 } 596 return ret; 597} 598 599_X_EXPORT void 600VidModeSetModeValue(pointer mode, int valtyp, int val) 601{ 602 switch (valtyp) { 603 case VIDMODE_H_DISPLAY: 604 ((DisplayModePtr)mode)->HDisplay = val; 605 break; 606 case VIDMODE_H_SYNCSTART: 607 ((DisplayModePtr)mode)->HSyncStart = val; 608 break; 609 case VIDMODE_H_SYNCEND: 610 ((DisplayModePtr)mode)->HSyncEnd = val; 611 break; 612 case VIDMODE_H_TOTAL: 613 ((DisplayModePtr)mode)->HTotal = val; 614 break; 615 case VIDMODE_H_SKEW: 616 ((DisplayModePtr)mode)->HSkew = val; 617 break; 618 case VIDMODE_V_DISPLAY: 619 ((DisplayModePtr)mode)->VDisplay = val; 620 break; 621 case VIDMODE_V_SYNCSTART: 622 ((DisplayModePtr)mode)->VSyncStart = val; 623 break; 624 case VIDMODE_V_SYNCEND: 625 ((DisplayModePtr)mode)->VSyncEnd = val; 626 break; 627 case VIDMODE_V_TOTAL: 628 ((DisplayModePtr)mode)->VTotal = val; 629 break; 630 case VIDMODE_FLAGS: 631 ((DisplayModePtr)mode)->Flags = val; 632 break; 633 case VIDMODE_CLOCK: 634 ((DisplayModePtr)mode)->Clock = val; 635 break; 636 } 637 return; 638} 639 640_X_EXPORT vidMonitorValue 641VidModeGetMonitorValue(pointer monitor, int valtyp, int indx) 642{ 643 vidMonitorValue ret; 644 645 switch (valtyp) { 646 case VIDMODE_MON_VENDOR: 647 ret.ptr = (((MonPtr)monitor)->vendor); 648 break; 649 case VIDMODE_MON_MODEL: 650 ret.ptr = (((MonPtr)monitor)->model); 651 break; 652 case VIDMODE_MON_NHSYNC: 653 ret.i = ((MonPtr)monitor)->nHsync; 654 break; 655 case VIDMODE_MON_NVREFRESH: 656 ret.i = ((MonPtr)monitor)->nVrefresh; 657 break; 658 case VIDMODE_MON_HSYNC_LO: 659 ret.f = (100.0 * ((MonPtr)monitor)->hsync[indx].lo); 660 break; 661 case VIDMODE_MON_HSYNC_HI: 662 ret.f = (100.0 * ((MonPtr)monitor)->hsync[indx].hi); 663 break; 664 case VIDMODE_MON_VREFRESH_LO: 665 ret.f = (100.0 * ((MonPtr)monitor)->vrefresh[indx].lo); 666 break; 667 case VIDMODE_MON_VREFRESH_HI: 668 ret.f = (100.0 * ((MonPtr)monitor)->vrefresh[indx].hi); 669 break; 670 } 671 return ret; 672} 673 674 675#endif /* XF86VIDMODE */ 676