xorg_driver.c revision def9b0e586e52a0fbdcce15613d96933e9690f38
1/* 2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * 26 * Author: Alan Hourihane <alanh@tungstengraphics.com> 27 * Author: Jakob Bornecrantz <wallbraker@gmail.com> 28 * 29 */ 30 31 32#include "xorg-server.h" 33#include "xf86.h" 34#include "xf86_OSproc.h" 35#include "compiler.h" 36#include "xf86PciInfo.h" 37#include "xf86Pci.h" 38#include "mipointer.h" 39#include "micmap.h" 40#include <X11/extensions/randr.h> 41#include "fb.h" 42#include "edid.h" 43#include "xf86i2c.h" 44#include "xf86Crtc.h" 45#include "miscstruct.h" 46#include "dixstruct.h" 47#include "xf86xv.h" 48#include <X11/extensions/Xv.h> 49#ifndef XSERVER_LIBPCIACCESS 50#error "libpciaccess needed" 51#endif 52 53#include <pciaccess.h> 54 55#include "pipe/p_context.h" 56#include "xorg_tracker.h" 57#include "xorg_winsys.h" 58 59/* 60 * Functions and symbols exported to Xorg via pointers. 61 */ 62 63static Bool drv_pre_init(ScrnInfoPtr pScrn, int flags); 64static Bool drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, 65 char **argv); 66static Bool drv_switch_mode(int scrnIndex, DisplayModePtr mode, int flags); 67static void drv_adjust_frame(int scrnIndex, int x, int y, int flags); 68static Bool drv_enter_vt(int scrnIndex, int flags); 69static void drv_leave_vt(int scrnIndex, int flags); 70static void drv_free_screen(int scrnIndex, int flags); 71static ModeStatus drv_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose, 72 int flags); 73 74typedef enum 75{ 76 OPTION_SW_CURSOR, 77 OPTION_2D_ACCEL, 78} drv_option_enums; 79 80static const OptionInfoRec drv_options[] = { 81 {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, 82 {OPTION_2D_ACCEL, "2DAccel", OPTV_BOOLEAN, {0}, FALSE}, 83 {-1, NULL, OPTV_NONE, {0}, FALSE} 84}; 85 86 87/* 88 * Exported Xorg driver functions to winsys 89 */ 90 91const OptionInfoRec * 92xorg_tracker_available_options(int chipid, int busid) 93{ 94 return drv_options; 95} 96 97void 98xorg_tracker_set_functions(ScrnInfoPtr scrn) 99{ 100 scrn->PreInit = drv_pre_init; 101 scrn->ScreenInit = drv_screen_init; 102 scrn->SwitchMode = drv_switch_mode; 103 scrn->AdjustFrame = drv_adjust_frame; 104 scrn->EnterVT = drv_enter_vt; 105 scrn->LeaveVT = drv_leave_vt; 106 scrn->FreeScreen = drv_free_screen; 107 scrn->ValidMode = drv_valid_mode; 108} 109 110 111/* 112 * Internal function definitions 113 */ 114 115static Bool drv_close_screen(int scrnIndex, ScreenPtr pScreen); 116static Bool drv_save_hw_state(ScrnInfoPtr pScrn); 117static Bool drv_restore_hw_state(ScrnInfoPtr pScrn); 118 119 120/* 121 * Internal functions 122 */ 123 124static Bool 125drv_get_rec(ScrnInfoPtr pScrn) 126{ 127 if (pScrn->driverPrivate) 128 return TRUE; 129 130 pScrn->driverPrivate = xnfcalloc(sizeof(modesettingRec), 1); 131 132 return TRUE; 133} 134 135static void 136drv_free_rec(ScrnInfoPtr pScrn) 137{ 138 if (!pScrn) 139 return; 140 141 if (!pScrn->driverPrivate) 142 return; 143 144 xfree(pScrn->driverPrivate); 145 146 pScrn->driverPrivate = NULL; 147} 148 149static void 150drv_probe_ddc(ScrnInfoPtr pScrn, int index) 151{ 152 ConfiguredMonitor = NULL; 153} 154 155static Bool 156drv_create_front_buffer(ScrnInfoPtr pScrn) 157{ 158 modesettingPtr ms = modesettingPTR(pScrn); 159 unsigned handle, stride; 160 struct pipe_texture *tex; 161 162 ms->noEvict = TRUE; 163 164 tex = xorg_exa_create_root_texture(pScrn, pScrn->virtualX, pScrn->virtualY, 165 pScrn->depth, pScrn->bitsPerPixel); 166 167 if (!tex) 168 return FALSE; 169 170 if (!ms->api->local_handle_from_texture(ms->api, ms->screen, 171 tex, 172 &stride, 173 &handle)) 174 return FALSE; 175 176 drmModeAddFB(ms->fd, 177 pScrn->virtualX, 178 pScrn->virtualY, 179 pScrn->depth, 180 pScrn->bitsPerPixel, 181 stride, 182 handle, 183 &ms->fb_id); 184 185 pScrn->frameX0 = 0; 186 pScrn->frameY0 = 0; 187 drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 188 189 pipe_texture_reference(&ms->root_texture, tex); 190 pipe_texture_reference(&tex, NULL); 191 return TRUE; 192} 193 194static Bool 195drv_bind_texture_to_root(ScrnInfoPtr pScrn) 196{ 197 modesettingPtr ms = modesettingPTR(pScrn); 198 ScreenPtr pScreen = pScrn->pScreen; 199 struct pipe_texture *check; 200 PixmapPtr rootPixmap; 201 202 rootPixmap = pScreen->GetScreenPixmap(pScreen); 203 204 xorg_exa_set_displayed_usage(rootPixmap); 205 xorg_exa_set_shared_usage(rootPixmap); 206 xorg_exa_set_texture(rootPixmap, ms->root_texture); 207 if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, NULL)) 208 FatalError("Couldn't adjust screen pixmap\n"); 209 210 check = xorg_exa_get_texture(rootPixmap); 211 if (ms->root_texture != check) 212 FatalError("Created new root texture\n"); 213 214 pipe_texture_reference(&check, NULL); 215 216 return TRUE; 217} 218 219static Bool 220drv_crtc_resize(ScrnInfoPtr pScrn, int width, int height) 221{ 222 modesettingPtr ms = modesettingPTR(pScrn); 223 unsigned handle, stride; 224 PixmapPtr rootPixmap; 225 ScreenPtr pScreen = pScrn->pScreen; 226 227 if (width == pScrn->virtualX && height == pScrn->virtualY) 228 return TRUE; 229 230 pScrn->virtualX = width; 231 pScrn->virtualY = height; 232 233 /* 234 * Remove the old framebuffer & texture. 235 */ 236 drmModeRmFB(ms->fd, ms->fb_id); 237 pipe_texture_reference(&ms->root_texture, NULL); 238 239 240 rootPixmap = pScreen->GetScreenPixmap(pScreen); 241 if (!pScreen->ModifyPixmapHeader(rootPixmap, width, height, -1, -1, -1, NULL)) 242 return FALSE; 243 244 /* takes one ref */ 245 ms->root_texture = xorg_exa_get_texture(rootPixmap); 246 247 if (!ms->api->local_handle_from_texture(ms->api, ms->screen, 248 ms->root_texture, 249 &stride, 250 &handle)) 251 FatalError("Could not get handle and stride from texture\n"); 252 253 drmModeAddFB(ms->fd, 254 pScrn->virtualX, 255 pScrn->virtualY, 256 pScrn->depth, 257 pScrn->bitsPerPixel, 258 stride, 259 handle, 260 &ms->fb_id); 261 262 /* HW dependent - FIXME */ 263 pScrn->displayWidth = pScrn->virtualX; 264 265 /* now create new frontbuffer */ 266 return drv_create_front_buffer(pScrn) && drv_bind_texture_to_root(pScrn); 267} 268 269static const xf86CrtcConfigFuncsRec crtc_config_funcs = { 270 .resize = drv_crtc_resize 271}; 272 273static Bool 274drv_init_drm(ScrnInfoPtr pScrn) 275{ 276 modesettingPtr ms = modesettingPTR(pScrn); 277 278 /* deal with server regeneration */ 279 if (ms->fd < 0) { 280 char *BusID; 281 282 BusID = xalloc(64); 283 sprintf(BusID, "PCI:%d:%d:%d", 284 ((ms->PciInfo->domain << 8) | ms->PciInfo->bus), 285 ms->PciInfo->dev, ms->PciInfo->func 286 ); 287 288 ms->fd = drmOpen(NULL, BusID); 289 290 if (ms->fd < 0) 291 return FALSE; 292 } 293 294 if (!ms->api) { 295 ms->api = drm_api_create(); 296 297 if (!ms->api) 298 return FALSE; 299 } 300 301 return TRUE; 302} 303 304static Bool 305drv_pre_init(ScrnInfoPtr pScrn, int flags) 306{ 307 xf86CrtcConfigPtr xf86_config; 308 modesettingPtr ms; 309 rgb defaultWeight = { 0, 0, 0 }; 310 EntityInfoPtr pEnt; 311 EntPtr msEnt = NULL; 312 int max_width, max_height; 313 314 if (pScrn->numEntities != 1) 315 return FALSE; 316 317 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 318 319 if (flags & PROBE_DETECT) { 320 drv_probe_ddc(pScrn, pEnt->index); 321 return TRUE; 322 } 323 324 /* Allocate driverPrivate */ 325 if (!drv_get_rec(pScrn)) 326 return FALSE; 327 328 ms = modesettingPTR(pScrn); 329 ms->SaveGeneration = -1; 330 ms->pEnt = pEnt; 331 332 pScrn->displayWidth = 640; /* default it */ 333 334 if (ms->pEnt->location.type != BUS_PCI) 335 return FALSE; 336 337 ms->PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index); 338 339 /* Allocate an entity private if necessary */ 340 if (xf86IsEntityShared(pScrn->entityList[0])) { 341 FatalError("Entity"); 342#if 0 343 msEnt = xf86GetEntityPrivate(pScrn->entityList[0], 344 modesettingEntityIndex)->ptr; 345 ms->entityPrivate = msEnt; 346#else 347 (void)msEnt; 348#endif 349 } else 350 ms->entityPrivate = NULL; 351 352 if (xf86IsEntityShared(pScrn->entityList[0])) { 353 if (xf86IsPrimInitDone(pScrn->entityList[0])) { 354 /* do something */ 355 } else { 356 xf86SetPrimInitDone(pScrn->entityList[0]); 357 } 358 } 359 360 ms->fd = -1; 361 ms->api = NULL; 362 if (!drv_init_drm(pScrn)) 363 return FALSE; 364 365 pScrn->monitor = pScrn->confScreen->monitor; 366 pScrn->progClock = TRUE; 367 pScrn->rgbBits = 8; 368 369 if (!xf86SetDepthBpp 370 (pScrn, 0, 0, 0, 371 PreferConvert24to32 | SupportConvert24to32 | Support32bppFb)) 372 return FALSE; 373 374 switch (pScrn->depth) { 375 case 15: 376 case 16: 377 case 24: 378 break; 379 default: 380 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 381 "Given depth (%d) is not supported by the driver\n", 382 pScrn->depth); 383 return FALSE; 384 } 385 xf86PrintDepthBpp(pScrn); 386 387 if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) 388 return FALSE; 389 if (!xf86SetDefaultVisual(pScrn, -1)) 390 return FALSE; 391 392 /* Process the options */ 393 xf86CollectOptions(pScrn, NULL); 394 if (!(ms->Options = xalloc(sizeof(drv_options)))) 395 return FALSE; 396 memcpy(ms->Options, drv_options, sizeof(drv_options)); 397 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options); 398 399 /* Allocate an xf86CrtcConfig */ 400 xf86CrtcConfigInit(pScrn, &crtc_config_funcs); 401 xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 402 403 max_width = 8192; 404 max_height = 8192; 405 xf86CrtcSetSizeRange(pScrn, 320, 200, max_width, max_height); 406 407 if (xf86ReturnOptValBool(ms->Options, OPTION_SW_CURSOR, FALSE)) { 408 ms->SWCursor = TRUE; 409 } 410 411 drv_save_hw_state(pScrn); 412 413 xorg_crtc_init(pScrn); 414 xorg_output_init(pScrn); 415 416 if (!xf86InitialConfiguration(pScrn, TRUE)) { 417 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); 418 drv_restore_hw_state(pScrn); 419 return FALSE; 420 } 421 422 drv_restore_hw_state(pScrn); 423 424 /* 425 * If the driver can do gamma correction, it should call xf86SetGamma() here. 426 */ 427 { 428 Gamma zeros = { 0.0, 0.0, 0.0 }; 429 430 if (!xf86SetGamma(pScrn, zeros)) { 431 return FALSE; 432 } 433 } 434 435 if (pScrn->modes == NULL) { 436 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); 437 return FALSE; 438 } 439 440 pScrn->currentMode = pScrn->modes; 441 442 /* Set display resolution */ 443 xf86SetDpi(pScrn, 0, 0); 444 445 /* Load the required sub modules */ 446 if (!xf86LoadSubModule(pScrn, "fb")) { 447 return FALSE; 448 } 449 450 xf86LoadSubModule(pScrn, "exa"); 451 452#ifdef DRI2 453 xf86LoadSubModule(pScrn, "dri2"); 454#endif 455 456 return TRUE; 457} 458 459static Bool 460drv_save_hw_state(ScrnInfoPtr pScrn) 461{ 462 /*xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);*/ 463 464 return TRUE; 465} 466 467static Bool 468drv_restore_hw_state(ScrnInfoPtr pScrn) 469{ 470 /*xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);*/ 471 472 return TRUE; 473} 474 475static void drv_block_handler(int i, pointer blockData, pointer pTimeout, 476 pointer pReadmask) 477{ 478 ScreenPtr pScreen = screenInfo.screens[i]; 479 modesettingPtr ms = modesettingPTR(xf86Screens[pScreen->myNum]); 480 481 pScreen->BlockHandler = ms->blockHandler; 482 pScreen->BlockHandler(i, blockData, pTimeout, pReadmask); 483 pScreen->BlockHandler = drv_block_handler; 484 485 ms->ctx->flush(ms->ctx, PIPE_FLUSH_RENDER_CACHE, NULL); 486 487#ifdef DRM_MODE_FEATURE_DIRTYFB 488 { 489 RegionPtr dirty = DamageRegion(ms->damage); 490 unsigned num_cliprects = REGION_NUM_RECTS(dirty); 491 492 if (num_cliprects) { 493 drmModeClip *clip = alloca(num_cliprects * sizeof(drmModeClip)); 494 BoxPtr rect = REGION_RECTS(dirty); 495 int i; 496 497 /* XXX no need for copy? */ 498 for (i = 0; i < num_cliprects; i++, rect++) { 499 clip[i].x1 = rect->x1; 500 clip[i].y1 = rect->y1; 501 clip[i].x2 = rect->x2; 502 clip[i].y2 = rect->y2; 503 } 504 505 /* TODO query connector property to see if this is needed */ 506 drmModeDirtyFB(ms->fd, ms->fb_id, clip, num_cliprects); 507 508 DamageEmpty(ms->damage); 509 } 510 } 511#endif 512} 513 514static Bool 515drv_create_screen_resources(ScreenPtr pScreen) 516{ 517 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 518 modesettingPtr ms = modesettingPTR(pScrn); 519 PixmapPtr rootPixmap; 520 Bool ret; 521 522 ms->noEvict = TRUE; 523 524 pScreen->CreateScreenResources = ms->createScreenResources; 525 ret = pScreen->CreateScreenResources(pScreen); 526 pScreen->CreateScreenResources = drv_create_screen_resources; 527 528 drv_bind_texture_to_root(pScrn); 529 530 ms->noEvict = FALSE; 531 532 drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 533 534#ifdef DRM_MODE_FEATURE_DIRTYFB 535 rootPixmap = pScreen->GetScreenPixmap(pScreen); 536 ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, 537 pScreen, rootPixmap); 538 539 if (ms->damage) { 540 DamageRegister(&rootPixmap->drawable, ms->damage); 541 542 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n"); 543 } else { 544 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 545 "Failed to create screen damage record\n"); 546 return FALSE; 547 } 548#else 549 (void)rootPixmap; 550#endif 551 552 return ret; 553} 554 555static Bool 556drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 557{ 558 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 559 modesettingPtr ms = modesettingPTR(pScrn); 560 VisualPtr visual; 561 562 if (!drv_init_drm(pScrn)) 563 return FALSE; 564 565 if (!ms->screen) { 566 ms->screen = ms->api->create_screen(ms->api, ms->fd, NULL); 567 568 if (!ms->screen) { 569 FatalError("Could not init pipe_screen\n"); 570 return FALSE; 571 } 572 } 573 574 pScrn->pScreen = pScreen; 575 576 /* HW dependent - FIXME */ 577 pScrn->displayWidth = pScrn->virtualX; 578 579 miClearVisualTypes(); 580 581 if (!miSetVisualTypes(pScrn->depth, 582 miGetDefaultVisualMask(pScrn->depth), 583 pScrn->rgbBits, pScrn->defaultVisual)) 584 return FALSE; 585 586 if (!miSetPixmapDepths()) 587 return FALSE; 588 589 pScrn->memPhysBase = 0; 590 pScrn->fbOffset = 0; 591 592 if (!fbScreenInit(pScreen, NULL, 593 pScrn->virtualX, pScrn->virtualY, 594 pScrn->xDpi, pScrn->yDpi, 595 pScrn->displayWidth, pScrn->bitsPerPixel)) 596 return FALSE; 597 598 if (pScrn->bitsPerPixel > 8) { 599 /* Fixup RGB ordering */ 600 visual = pScreen->visuals + pScreen->numVisuals; 601 while (--visual >= pScreen->visuals) { 602 if ((visual->class | DynamicClass) == DirectColor) { 603 visual->offsetRed = pScrn->offset.red; 604 visual->offsetGreen = pScrn->offset.green; 605 visual->offsetBlue = pScrn->offset.blue; 606 visual->redMask = pScrn->mask.red; 607 visual->greenMask = pScrn->mask.green; 608 visual->blueMask = pScrn->mask.blue; 609 } 610 } 611 } 612 613 fbPictureInit(pScreen, NULL, 0); 614 615 ms->blockHandler = pScreen->BlockHandler; 616 pScreen->BlockHandler = drv_block_handler; 617 ms->createScreenResources = pScreen->CreateScreenResources; 618 pScreen->CreateScreenResources = drv_create_screen_resources; 619 620 xf86SetBlackWhitePixels(pScreen); 621 622 ms->exa = xorg_exa_init(pScrn, xf86ReturnOptValBool(ms->Options, 623 OPTION_2D_ACCEL, TRUE)); 624 ms->debug_fallback = debug_get_bool_option("XORG_DEBUG_FALLBACK", TRUE); 625 626 xorg_xv_init(pScreen); 627 628 miInitializeBackingStore(pScreen); 629 xf86SetBackingStore(pScreen); 630 xf86SetSilkenMouse(pScreen); 631 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 632 633 /* Need to extend HWcursor support to handle mask interleave */ 634 if (!ms->SWCursor) 635 xf86_cursors_init(pScreen, 64, 64, 636 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | 637 HARDWARE_CURSOR_ARGB); 638 639 /* Must force it before EnterVT, so we are in control of VT and 640 * later memory should be bound when allocating, e.g rotate_mem */ 641 pScrn->vtSema = TRUE; 642 643 pScreen->SaveScreen = xf86SaveScreen; 644 ms->CloseScreen = pScreen->CloseScreen; 645 pScreen->CloseScreen = drv_close_screen; 646 647 if (!xf86CrtcScreenInit(pScreen)) 648 return FALSE; 649 650 if (!miCreateDefColormap(pScreen)) 651 return FALSE; 652 653 xf86DPMSInit(pScreen, xf86DPMSSet, 0); 654 655 if (serverGeneration == 1) 656 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 657 658#ifdef DRI2 659 xorg_dri2_init(pScreen); 660#endif 661 662 return drv_enter_vt(scrnIndex, 1); 663} 664 665static void 666drv_adjust_frame(int scrnIndex, int x, int y, int flags) 667{ 668 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 669 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 670 xf86OutputPtr output = config->output[config->compat_output]; 671 xf86CrtcPtr crtc = output->crtc; 672 673 if (crtc && crtc->enabled) { 674 crtc->funcs->set_mode_major(crtc, pScrn->currentMode, 675 RR_Rotate_0, x, y); 676 crtc->x = output->initial_x + x; 677 crtc->y = output->initial_y + y; 678 } 679} 680 681static void 682drv_free_screen(int scrnIndex, int flags) 683{ 684 drv_free_rec(xf86Screens[scrnIndex]); 685} 686 687static void 688drv_leave_vt(int scrnIndex, int flags) 689{ 690 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 691 modesettingPtr ms = modesettingPTR(pScrn); 692 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 693 int o; 694 695 for (o = 0; o < config->num_crtc; o++) { 696 xf86CrtcPtr crtc = config->crtc[o]; 697 698 xorg_crtc_cursor_destroy(crtc); 699 700 if (crtc->rotatedPixmap || crtc->rotatedData) { 701 crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap, 702 crtc->rotatedData); 703 crtc->rotatedPixmap = NULL; 704 crtc->rotatedData = NULL; 705 } 706 } 707 708 drmModeRmFB(ms->fd, ms->fb_id); 709 710 drv_restore_hw_state(pScrn); 711 712 if (drmDropMaster(ms->fd)) 713 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 714 "drmDropMaster failed: %s\n", strerror(errno)); 715 716 pScrn->vtSema = FALSE; 717} 718 719/* 720 * This gets called when gaining control of the VT, and from ScreenInit(). 721 */ 722static Bool 723drv_enter_vt(int scrnIndex, int flags) 724{ 725 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 726 modesettingPtr ms = modesettingPTR(pScrn); 727 728 if (drmSetMaster(ms->fd)) { 729 if (errno == EINVAL) { 730 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 731 "drmSetMaster failed: 2.6.29 or newer kernel required for " 732 "multi-server DRI\n"); 733 } else { 734 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 735 "drmSetMaster failed: %s\n", strerror(errno)); 736 } 737 } 738 739 /* 740 * Only save state once per server generation since that's what most 741 * drivers do. Could change this to save state at each VT enter. 742 */ 743 if (ms->SaveGeneration != serverGeneration) { 744 ms->SaveGeneration = serverGeneration; 745 drv_save_hw_state(pScrn); 746 } 747 748 if (!drv_create_front_buffer(pScrn)) 749 return FALSE; 750 751 if (!flags && !drv_bind_texture_to_root(pScrn)) 752 return FALSE; 753 754 if (!xf86SetDesiredModes(pScrn)) 755 return FALSE; 756 757 return TRUE; 758} 759 760static Bool 761drv_switch_mode(int scrnIndex, DisplayModePtr mode, int flags) 762{ 763 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 764 765 return xf86SetSingleMode(pScrn, mode, RR_Rotate_0); 766} 767 768static Bool 769drv_close_screen(int scrnIndex, ScreenPtr pScreen) 770{ 771 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 772 modesettingPtr ms = modesettingPTR(pScrn); 773 774 if (pScrn->vtSema) { 775 drv_leave_vt(scrnIndex, 0); 776 } 777#ifdef DRI2 778 xorg_dri2_close(pScreen); 779#endif 780 781 pScreen->BlockHandler = ms->blockHandler; 782 pScreen->CreateScreenResources = ms->createScreenResources; 783 784#ifdef DRM_MODE_FEATURE_DIRTYFB 785 if (ms->damage) { 786 DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, ms->damage); 787 DamageDestroy(ms->damage); 788 ms->damage = NULL; 789 } 790#endif 791 792 pipe_texture_reference(&ms->root_texture, NULL); 793 794 if (ms->exa) 795 xorg_exa_close(pScrn); 796 797 if (ms->api && ms->api->destroy) 798 ms->api->destroy(ms->api); 799 ms->api = NULL; 800 801 drmClose(ms->fd); 802 ms->fd = -1; 803 804 pScrn->vtSema = FALSE; 805 pScreen->CloseScreen = ms->CloseScreen; 806 return (*pScreen->CloseScreen) (scrnIndex, pScreen); 807} 808 809static ModeStatus 810drv_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) 811{ 812 return MODE_OK; 813} 814 815/* vim: set sw=4 ts=8 sts=4: */ 816