xorg_driver.c revision d34fdf149d250275e819ca58554a41a8bff82785
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#ifdef HAVE_LIBKMS 60#include "libkms.h" 61#endif 62 63/* 64 * Functions and symbols exported to Xorg via pointers. 65 */ 66 67static Bool drv_pre_init(ScrnInfoPtr pScrn, int flags); 68static Bool drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, 69 char **argv); 70static Bool drv_switch_mode(int scrnIndex, DisplayModePtr mode, int flags); 71static void drv_adjust_frame(int scrnIndex, int x, int y, int flags); 72static Bool drv_enter_vt(int scrnIndex, int flags); 73static void drv_leave_vt(int scrnIndex, int flags); 74static void drv_free_screen(int scrnIndex, int flags); 75static ModeStatus drv_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose, 76 int flags); 77 78typedef enum 79{ 80 OPTION_SW_CURSOR, 81 OPTION_2D_ACCEL, 82} drv_option_enums; 83 84static const OptionInfoRec drv_options[] = { 85 {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, 86 {OPTION_2D_ACCEL, "2DAccel", OPTV_BOOLEAN, {0}, FALSE}, 87 {-1, NULL, OPTV_NONE, {0}, FALSE} 88}; 89 90 91/* 92 * Exported Xorg driver functions to winsys 93 */ 94 95const OptionInfoRec * 96xorg_tracker_available_options(int chipid, int busid) 97{ 98 return drv_options; 99} 100 101void 102xorg_tracker_set_functions(ScrnInfoPtr scrn) 103{ 104 scrn->PreInit = drv_pre_init; 105 scrn->ScreenInit = drv_screen_init; 106 scrn->SwitchMode = drv_switch_mode; 107 scrn->AdjustFrame = drv_adjust_frame; 108 scrn->EnterVT = drv_enter_vt; 109 scrn->LeaveVT = drv_leave_vt; 110 scrn->FreeScreen = drv_free_screen; 111 scrn->ValidMode = drv_valid_mode; 112} 113 114 115/* 116 * Internal function definitions 117 */ 118 119static Bool drv_init_front_buffer_functions(ScrnInfoPtr pScrn); 120static Bool drv_close_screen(int scrnIndex, ScreenPtr pScreen); 121static Bool drv_save_hw_state(ScrnInfoPtr pScrn); 122static Bool drv_restore_hw_state(ScrnInfoPtr pScrn); 123 124 125/* 126 * Internal functions 127 */ 128 129static Bool 130drv_get_rec(ScrnInfoPtr pScrn) 131{ 132 if (pScrn->driverPrivate) 133 return TRUE; 134 135 pScrn->driverPrivate = xnfcalloc(sizeof(modesettingRec), 1); 136 137 return TRUE; 138} 139 140static void 141drv_free_rec(ScrnInfoPtr pScrn) 142{ 143 if (!pScrn) 144 return; 145 146 if (!pScrn->driverPrivate) 147 return; 148 149 xfree(pScrn->driverPrivate); 150 151 pScrn->driverPrivate = NULL; 152} 153 154static void 155drv_probe_ddc(ScrnInfoPtr pScrn, int index) 156{ 157 ConfiguredMonitor = NULL; 158} 159 160static Bool 161drv_crtc_resize(ScrnInfoPtr pScrn, int width, int height) 162{ 163 modesettingPtr ms = modesettingPTR(pScrn); 164 PixmapPtr rootPixmap; 165 ScreenPtr pScreen = pScrn->pScreen; 166 167 if (width == pScrn->virtualX && height == pScrn->virtualY) 168 return TRUE; 169 170 pScrn->virtualX = width; 171 pScrn->virtualY = height; 172 173 /* 174 * Remove the old framebuffer & texture. 175 */ 176 drmModeRmFB(ms->fd, ms->fb_id); 177 if (!ms->destroy_front_buffer(pScrn)) 178 FatalError("failed to destroy front buffer\n"); 179 180 rootPixmap = pScreen->GetScreenPixmap(pScreen); 181 if (!pScreen->ModifyPixmapHeader(rootPixmap, width, height, -1, -1, -1, NULL)) 182 return FALSE; 183 184 /* HW dependent - FIXME */ 185 pScrn->displayWidth = pScrn->virtualX; 186 187 /* now create new frontbuffer */ 188 return ms->create_front_buffer(pScrn) && ms->bind_front_buffer(pScrn); 189} 190 191static const xf86CrtcConfigFuncsRec crtc_config_funcs = { 192 .resize = drv_crtc_resize 193}; 194 195static Bool 196drv_init_drm(ScrnInfoPtr pScrn) 197{ 198 modesettingPtr ms = modesettingPTR(pScrn); 199 200 /* deal with server regeneration */ 201 if (ms->fd < 0) { 202 char *BusID; 203 204 BusID = xalloc(64); 205 sprintf(BusID, "PCI:%d:%d:%d", 206 ((ms->PciInfo->domain << 8) | ms->PciInfo->bus), 207 ms->PciInfo->dev, ms->PciInfo->func 208 ); 209 210 ms->fd = drmOpen(NULL, BusID); 211 212 if (ms->fd < 0) 213 return FALSE; 214 } 215 216 return TRUE; 217} 218 219static Bool 220drv_init_resource_management(ScrnInfoPtr pScrn) 221{ 222 modesettingPtr ms = modesettingPTR(pScrn); 223 /* 224 ScreenPtr pScreen = pScrn->pScreen; 225 PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen); 226 Bool fbAccessDisabled; 227 CARD8 *fbstart; 228 */ 229 230 if (ms->screen || ms->kms) 231 return TRUE; 232 233 ms->api = drm_api_create(); 234 if (ms->api) { 235 ms->screen = ms->api->create_screen(ms->api, ms->fd, NULL); 236 237 if (ms->screen) 238 return TRUE; 239 240 if (ms->api->destroy) 241 ms->api->destroy(ms->api); 242 243 ms->api = NULL; 244 } 245 246#ifdef HAVE_LIBKMS 247 if (!kms_create(ms->fd, &ms->kms)) 248 return TRUE; 249#endif 250 251 return FALSE; 252} 253 254static Bool 255drv_close_resource_management(ScrnInfoPtr pScrn) 256{ 257 modesettingPtr ms = modesettingPTR(pScrn); 258 int i; 259 260 if (ms->screen) { 261 assert(ms->ctx == NULL); 262 263 for (i = 0; i < XORG_NR_FENCES; i++) { 264 if (ms->fence[i]) { 265 ms->screen->fence_finish(ms->screen, ms->fence[i], 0); 266 ms->screen->fence_reference(ms->screen, &ms->fence[i], NULL); 267 } 268 } 269 ms->screen->destroy(ms->screen); 270 } 271 ms->screen = NULL; 272 273 if (ms->api && ms->api->destroy) 274 ms->api->destroy(ms->api); 275 ms->api = NULL; 276 277#ifdef HAVE_LIBKMS 278 if (ms->kms) 279 kms_destroy(&ms->kms); 280#endif 281 282 return TRUE; 283} 284 285static Bool 286drv_pre_init(ScrnInfoPtr pScrn, int flags) 287{ 288 xf86CrtcConfigPtr xf86_config; 289 modesettingPtr ms; 290 rgb defaultWeight = { 0, 0, 0 }; 291 EntityInfoPtr pEnt; 292 EntPtr msEnt = NULL; 293 int max_width, max_height; 294 295 if (pScrn->numEntities != 1) 296 return FALSE; 297 298 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 299 300 if (flags & PROBE_DETECT) { 301 drv_probe_ddc(pScrn, pEnt->index); 302 return TRUE; 303 } 304 305 /* Allocate driverPrivate */ 306 if (!drv_get_rec(pScrn)) 307 return FALSE; 308 309 ms = modesettingPTR(pScrn); 310 ms->SaveGeneration = -1; 311 ms->pEnt = pEnt; 312 313 pScrn->displayWidth = 640; /* default it */ 314 315 if (ms->pEnt->location.type != BUS_PCI) 316 return FALSE; 317 318 ms->PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index); 319 320 /* Allocate an entity private if necessary */ 321 if (xf86IsEntityShared(pScrn->entityList[0])) { 322 FatalError("Entity"); 323#if 0 324 msEnt = xf86GetEntityPrivate(pScrn->entityList[0], 325 modesettingEntityIndex)->ptr; 326 ms->entityPrivate = msEnt; 327#else 328 (void)msEnt; 329#endif 330 } else 331 ms->entityPrivate = NULL; 332 333 if (xf86IsEntityShared(pScrn->entityList[0])) { 334 if (xf86IsPrimInitDone(pScrn->entityList[0])) { 335 /* do something */ 336 } else { 337 xf86SetPrimInitDone(pScrn->entityList[0]); 338 } 339 } 340 341 ms->fd = -1; 342 ms->api = NULL; 343 if (!drv_init_drm(pScrn)) 344 return FALSE; 345 346 pScrn->monitor = pScrn->confScreen->monitor; 347 pScrn->progClock = TRUE; 348 pScrn->rgbBits = 8; 349 350 if (!xf86SetDepthBpp 351 (pScrn, 0, 0, 0, 352 PreferConvert24to32 | SupportConvert24to32 | Support32bppFb)) 353 return FALSE; 354 355 switch (pScrn->depth) { 356 case 15: 357 case 16: 358 case 24: 359 break; 360 default: 361 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 362 "Given depth (%d) is not supported by the driver\n", 363 pScrn->depth); 364 return FALSE; 365 } 366 xf86PrintDepthBpp(pScrn); 367 368 if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) 369 return FALSE; 370 if (!xf86SetDefaultVisual(pScrn, -1)) 371 return FALSE; 372 373 /* Process the options */ 374 xf86CollectOptions(pScrn, NULL); 375 if (!(ms->Options = xalloc(sizeof(drv_options)))) 376 return FALSE; 377 memcpy(ms->Options, drv_options, sizeof(drv_options)); 378 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options); 379 380 /* Allocate an xf86CrtcConfig */ 381 xf86CrtcConfigInit(pScrn, &crtc_config_funcs); 382 xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 383 384 max_width = 8192; 385 max_height = 8192; 386 xf86CrtcSetSizeRange(pScrn, 320, 200, max_width, max_height); 387 388 if (xf86ReturnOptValBool(ms->Options, OPTION_SW_CURSOR, FALSE)) { 389 ms->SWCursor = TRUE; 390 } 391 392 drv_save_hw_state(pScrn); 393 394 xorg_crtc_init(pScrn); 395 xorg_output_init(pScrn); 396 397 if (!xf86InitialConfiguration(pScrn, TRUE)) { 398 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); 399 drv_restore_hw_state(pScrn); 400 return FALSE; 401 } 402 403 drv_restore_hw_state(pScrn); 404 405 /* 406 * If the driver can do gamma correction, it should call xf86SetGamma() here. 407 */ 408 { 409 Gamma zeros = { 0.0, 0.0, 0.0 }; 410 411 if (!xf86SetGamma(pScrn, zeros)) { 412 return FALSE; 413 } 414 } 415 416 if (pScrn->modes == NULL) { 417 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); 418 return FALSE; 419 } 420 421 pScrn->currentMode = pScrn->modes; 422 423 /* Set display resolution */ 424 xf86SetDpi(pScrn, 0, 0); 425 426 /* Load the required sub modules */ 427 if (!xf86LoadSubModule(pScrn, "fb")) 428 return FALSE; 429 430 /* XXX: these aren't needed when we are using libkms */ 431 if (!xf86LoadSubModule(pScrn, "exa")) 432 return FALSE; 433 434#ifdef DRI2 435 if (!xf86LoadSubModule(pScrn, "dri2")) 436 return FALSE; 437#endif 438 439 return TRUE; 440} 441 442static Bool 443drv_save_hw_state(ScrnInfoPtr pScrn) 444{ 445 /*xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);*/ 446 447 return TRUE; 448} 449 450static Bool 451drv_restore_hw_state(ScrnInfoPtr pScrn) 452{ 453 /*xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);*/ 454 455 return TRUE; 456} 457 458static void drv_block_handler(int i, pointer blockData, pointer pTimeout, 459 pointer pReadmask) 460{ 461 ScreenPtr pScreen = screenInfo.screens[i]; 462 modesettingPtr ms = modesettingPTR(xf86Screens[pScreen->myNum]); 463 464 pScreen->BlockHandler = ms->blockHandler; 465 pScreen->BlockHandler(i, blockData, pTimeout, pReadmask); 466 pScreen->BlockHandler = drv_block_handler; 467 468 if (ms->ctx) { 469 int j; 470 471 ms->ctx->flush(ms->ctx, PIPE_FLUSH_RENDER_CACHE, &ms->fence[XORG_NR_FENCES-1]); 472 473 if (ms->fence[0]) 474 ms->ctx->screen->fence_finish(ms->ctx->screen, ms->fence[0], 0); 475 476 /* The amount of rendering generated by a block handler can be 477 * quite small. Let us get a fair way ahead of hardware before 478 * throttling. 479 */ 480 for (j = 0; j < XORG_NR_FENCES - 1; j++) 481 ms->screen->fence_reference(ms->screen, 482 &ms->fence[j], 483 ms->fence[j+1]); 484 485 ms->screen->fence_reference(ms->screen, 486 &ms->fence[XORG_NR_FENCES-1], 487 NULL); 488 } 489 490 491#ifdef DRM_MODE_FEATURE_DIRTYFB 492 { 493 RegionPtr dirty = DamageRegion(ms->damage); 494 unsigned num_cliprects = REGION_NUM_RECTS(dirty); 495 496 if (num_cliprects) { 497 drmModeClip *clip = alloca(num_cliprects * sizeof(drmModeClip)); 498 BoxPtr rect = REGION_RECTS(dirty); 499 int i, ret; 500 501 /* XXX no need for copy? */ 502 for (i = 0; i < num_cliprects; i++, rect++) { 503 clip[i].x1 = rect->x1; 504 clip[i].y1 = rect->y1; 505 clip[i].x2 = rect->x2; 506 clip[i].y2 = rect->y2; 507 } 508 509 /* TODO query connector property to see if this is needed */ 510 ret = drmModeDirtyFB(ms->fd, ms->fb_id, clip, num_cliprects); 511 if (ret) { 512 debug_printf("%s: failed to send dirty (%i, %s)\n", 513 __func__, ret, strerror(-ret)); 514 } 515 516 DamageEmpty(ms->damage); 517 } 518 } 519#endif 520} 521 522static Bool 523drv_create_screen_resources(ScreenPtr pScreen) 524{ 525 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 526 modesettingPtr ms = modesettingPTR(pScrn); 527 PixmapPtr rootPixmap; 528 Bool ret; 529 530 ms->noEvict = TRUE; 531 532 pScreen->CreateScreenResources = ms->createScreenResources; 533 ret = pScreen->CreateScreenResources(pScreen); 534 pScreen->CreateScreenResources = drv_create_screen_resources; 535 536 ms->bind_front_buffer(pScrn); 537 538 ms->noEvict = FALSE; 539 540 drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 541 542#ifdef DRM_MODE_FEATURE_DIRTYFB 543 rootPixmap = pScreen->GetScreenPixmap(pScreen); 544 ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, 545 pScreen, rootPixmap); 546 547 if (ms->damage) { 548 DamageRegister(&rootPixmap->drawable, ms->damage); 549 550 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n"); 551 } else { 552 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 553 "Failed to create screen damage record\n"); 554 return FALSE; 555 } 556#else 557 (void)rootPixmap; 558#endif 559 560 return ret; 561} 562 563static Bool 564drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 565{ 566 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 567 modesettingPtr ms = modesettingPTR(pScrn); 568 VisualPtr visual; 569 570 if (!drv_init_drm(pScrn)) { 571 FatalError("Could not init DRM"); 572 return FALSE; 573 } 574 575 if (!drv_init_resource_management(pScrn)) { 576 FatalError("Could not init resource management (!pipe_screen && !libkms)"); 577 return FALSE; 578 } 579 580 if (!drv_init_front_buffer_functions(pScrn)) { 581 FatalError("Could not init front buffer manager"); 582 return FALSE; 583 } 584 585 pScrn->pScreen = pScreen; 586 587 /* HW dependent - FIXME */ 588 pScrn->displayWidth = pScrn->virtualX; 589 590 miClearVisualTypes(); 591 592 if (!miSetVisualTypes(pScrn->depth, 593 miGetDefaultVisualMask(pScrn->depth), 594 pScrn->rgbBits, pScrn->defaultVisual)) 595 return FALSE; 596 597 if (!miSetPixmapDepths()) 598 return FALSE; 599 600 pScrn->memPhysBase = 0; 601 pScrn->fbOffset = 0; 602 603 if (!fbScreenInit(pScreen, NULL, 604 pScrn->virtualX, pScrn->virtualY, 605 pScrn->xDpi, pScrn->yDpi, 606 pScrn->displayWidth, pScrn->bitsPerPixel)) 607 return FALSE; 608 609 if (pScrn->bitsPerPixel > 8) { 610 /* Fixup RGB ordering */ 611 visual = pScreen->visuals + pScreen->numVisuals; 612 while (--visual >= pScreen->visuals) { 613 if ((visual->class | DynamicClass) == DirectColor) { 614 visual->offsetRed = pScrn->offset.red; 615 visual->offsetGreen = pScrn->offset.green; 616 visual->offsetBlue = pScrn->offset.blue; 617 visual->redMask = pScrn->mask.red; 618 visual->greenMask = pScrn->mask.green; 619 visual->blueMask = pScrn->mask.blue; 620 } 621 } 622 } 623 624 fbPictureInit(pScreen, NULL, 0); 625 626 ms->blockHandler = pScreen->BlockHandler; 627 pScreen->BlockHandler = drv_block_handler; 628 ms->createScreenResources = pScreen->CreateScreenResources; 629 pScreen->CreateScreenResources = drv_create_screen_resources; 630 631 xf86SetBlackWhitePixels(pScreen); 632 633 if (ms->screen) { 634 ms->exa = xorg_exa_init(pScrn, xf86ReturnOptValBool(ms->Options, 635 OPTION_2D_ACCEL, TRUE)); 636 ms->debug_fallback = debug_get_bool_option("XORG_DEBUG_FALLBACK", TRUE); 637 638 xorg_xv_init(pScreen); 639#ifdef DRI2 640 xorg_dri2_init(pScreen); 641#endif 642 } 643 644 miInitializeBackingStore(pScreen); 645 xf86SetBackingStore(pScreen); 646 xf86SetSilkenMouse(pScreen); 647 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 648 649 /* Need to extend HWcursor support to handle mask interleave */ 650 if (!ms->SWCursor) 651 xf86_cursors_init(pScreen, 64, 64, 652 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | 653 HARDWARE_CURSOR_ARGB); 654 655 /* Must force it before EnterVT, so we are in control of VT and 656 * later memory should be bound when allocating, e.g rotate_mem */ 657 pScrn->vtSema = TRUE; 658 659 pScreen->SaveScreen = xf86SaveScreen; 660 ms->CloseScreen = pScreen->CloseScreen; 661 pScreen->CloseScreen = drv_close_screen; 662 663 if (!xf86CrtcScreenInit(pScreen)) 664 return FALSE; 665 666 if (!miCreateDefColormap(pScreen)) 667 return FALSE; 668 669 xf86DPMSInit(pScreen, xf86DPMSSet, 0); 670 671 if (serverGeneration == 1) 672 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 673 674 if (ms->winsys_screen_init) 675 ms->winsys_screen_init(pScrn); 676 677 return drv_enter_vt(scrnIndex, 1); 678} 679 680static void 681drv_adjust_frame(int scrnIndex, int x, int y, int flags) 682{ 683 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 684 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 685 xf86OutputPtr output = config->output[config->compat_output]; 686 xf86CrtcPtr crtc = output->crtc; 687 688 if (crtc && crtc->enabled) { 689 crtc->funcs->set_mode_major(crtc, pScrn->currentMode, 690 RR_Rotate_0, x, y); 691 crtc->x = output->initial_x + x; 692 crtc->y = output->initial_y + y; 693 } 694} 695 696static void 697drv_free_screen(int scrnIndex, int flags) 698{ 699 drv_free_rec(xf86Screens[scrnIndex]); 700} 701 702static void 703drv_leave_vt(int scrnIndex, int flags) 704{ 705 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 706 modesettingPtr ms = modesettingPTR(pScrn); 707 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 708 int o; 709 710 if (ms->winsys_leave_vt) 711 ms->winsys_leave_vt(pScrn); 712 713 for (o = 0; o < config->num_crtc; o++) { 714 xf86CrtcPtr crtc = config->crtc[o]; 715 716 xorg_crtc_cursor_destroy(crtc); 717 718 if (crtc->rotatedPixmap || crtc->rotatedData) { 719 crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap, 720 crtc->rotatedData); 721 crtc->rotatedPixmap = NULL; 722 crtc->rotatedData = NULL; 723 } 724 } 725 726 drmModeRmFB(ms->fd, ms->fb_id); 727 728 drv_restore_hw_state(pScrn); 729 730 if (drmDropMaster(ms->fd)) 731 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 732 "drmDropMaster failed: %s\n", strerror(errno)); 733 734 pScrn->vtSema = FALSE; 735} 736 737/* 738 * This gets called when gaining control of the VT, and from ScreenInit(). 739 */ 740static Bool 741drv_enter_vt(int scrnIndex, int flags) 742{ 743 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 744 modesettingPtr ms = modesettingPTR(pScrn); 745 746 if (drmSetMaster(ms->fd)) { 747 if (errno == EINVAL) { 748 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 749 "drmSetMaster failed: 2.6.29 or newer kernel required for " 750 "multi-server DRI\n"); 751 } else { 752 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 753 "drmSetMaster failed: %s\n", strerror(errno)); 754 } 755 } 756 757 /* 758 * Only save state once per server generation since that's what most 759 * drivers do. Could change this to save state at each VT enter. 760 */ 761 if (ms->SaveGeneration != serverGeneration) { 762 ms->SaveGeneration = serverGeneration; 763 drv_save_hw_state(pScrn); 764 } 765 766 if (!ms->create_front_buffer(pScrn)) 767 return FALSE; 768 769 if (!flags && !ms->bind_front_buffer(pScrn)) 770 return FALSE; 771 772 if (!xf86SetDesiredModes(pScrn)) 773 return FALSE; 774 775 if (ms->winsys_enter_vt) 776 ms->winsys_enter_vt(pScrn); 777 778 return TRUE; 779} 780 781static Bool 782drv_switch_mode(int scrnIndex, DisplayModePtr mode, int flags) 783{ 784 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 785 786 return xf86SetSingleMode(pScrn, mode, RR_Rotate_0); 787} 788 789static Bool 790drv_close_screen(int scrnIndex, ScreenPtr pScreen) 791{ 792 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 793 modesettingPtr ms = modesettingPTR(pScrn); 794 795 if (pScrn->vtSema) { 796 drv_leave_vt(scrnIndex, 0); 797 } 798 799 if (ms->winsys_screen_close) 800 ms->winsys_screen_close(pScrn); 801 802#ifdef DRI2 803 if (ms->screen) 804 xorg_dri2_close(pScreen); 805#endif 806 807 pScreen->BlockHandler = ms->blockHandler; 808 pScreen->CreateScreenResources = ms->createScreenResources; 809 810#ifdef DRM_MODE_FEATURE_DIRTYFB 811 if (ms->damage) { 812 DamageUnregister(&pScreen->GetScreenPixmap(pScreen)->drawable, ms->damage); 813 DamageDestroy(ms->damage); 814 ms->damage = NULL; 815 } 816#endif 817 818 drmModeRmFB(ms->fd, ms->fb_id); 819 ms->destroy_front_buffer(pScrn); 820 821 if (ms->exa) 822 xorg_exa_close(pScrn); 823 ms->exa = NULL; 824 825 drv_close_resource_management(pScrn); 826 827 drmClose(ms->fd); 828 ms->fd = -1; 829 830 pScrn->vtSema = FALSE; 831 pScreen->CloseScreen = ms->CloseScreen; 832 return (*pScreen->CloseScreen) (scrnIndex, pScreen); 833} 834 835static ModeStatus 836drv_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) 837{ 838 return MODE_OK; 839} 840 841 842/* 843 * Front buffer backing store functions. 844 */ 845 846static Bool 847drv_destroy_front_buffer_ga3d(ScrnInfoPtr pScrn) 848{ 849 modesettingPtr ms = modesettingPTR(pScrn); 850 pipe_texture_reference(&ms->root_texture, NULL); 851 return TRUE; 852} 853 854static Bool 855drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn) 856{ 857 modesettingPtr ms = modesettingPTR(pScrn); 858 unsigned handle, stride; 859 struct pipe_texture *tex; 860 int ret; 861 862 ms->noEvict = TRUE; 863 864 tex = xorg_exa_create_root_texture(pScrn, pScrn->virtualX, pScrn->virtualY, 865 pScrn->depth, pScrn->bitsPerPixel); 866 867 if (!tex) 868 return FALSE; 869 870 if (!ms->api->local_handle_from_texture(ms->api, ms->screen, 871 tex, 872 &stride, 873 &handle)) 874 goto err_destroy; 875 876 ret = drmModeAddFB(ms->fd, 877 pScrn->virtualX, 878 pScrn->virtualY, 879 pScrn->depth, 880 pScrn->bitsPerPixel, 881 stride, 882 handle, 883 &ms->fb_id); 884 if (ret) { 885 debug_printf("%s: failed to create framebuffer (%i, %s)", 886 __func__, ret, strerror(-ret)); 887 goto err_destroy; 888 } 889 890 pScrn->frameX0 = 0; 891 pScrn->frameY0 = 0; 892 drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 893 894 pipe_texture_reference(&ms->root_texture, tex); 895 pipe_texture_reference(&tex, NULL); 896 897 return TRUE; 898 899err_destroy: 900 pipe_texture_reference(&tex, NULL); 901 return FALSE; 902} 903 904static Bool 905drv_bind_front_buffer_ga3d(ScrnInfoPtr pScrn) 906{ 907 modesettingPtr ms = modesettingPTR(pScrn); 908 ScreenPtr pScreen = pScrn->pScreen; 909 PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen); 910 struct pipe_texture *check; 911 912 xorg_exa_set_displayed_usage(rootPixmap); 913 xorg_exa_set_shared_usage(rootPixmap); 914 xorg_exa_set_texture(rootPixmap, ms->root_texture); 915 if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, NULL)) 916 FatalError("Couldn't adjust screen pixmap\n"); 917 918 check = xorg_exa_get_texture(rootPixmap); 919 if (ms->root_texture != check) 920 FatalError("Created new root texture\n"); 921 922 pipe_texture_reference(&check, NULL); 923 return TRUE; 924} 925 926#ifdef HAVE_LIBKMS 927static Bool 928drv_destroy_front_buffer_kms(ScrnInfoPtr pScrn) 929{ 930 modesettingPtr ms = modesettingPTR(pScrn); 931 ScreenPtr pScreen = pScrn->pScreen; 932 PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen); 933 934 if (!ms->root_bo) 935 return TRUE; 936 937 kms_bo_unmap(ms->root_bo); 938 kms_bo_destroy(&ms->root_bo); 939 return TRUE; 940} 941 942static Bool 943drv_create_front_buffer_kms(ScrnInfoPtr pScrn) 944{ 945 modesettingPtr ms = modesettingPTR(pScrn); 946 unsigned handle, stride; 947 struct kms_bo *bo; 948 unsigned attr[8]; 949 int ret; 950 951 attr[0] = KMS_BO_TYPE; 952 attr[1] = KMS_BO_TYPE_SCANOUT; 953 attr[2] = KMS_WIDTH; 954 attr[3] = pScrn->virtualX; 955 attr[4] = KMS_HEIGHT; 956 attr[5] = pScrn->virtualY; 957 attr[6] = 0; 958 959 if (kms_bo_create(ms->kms, attr, &bo)) 960 return FALSE; 961 962 if (kms_bo_get_prop(bo, KMS_PITCH, &stride)) 963 goto err_destroy; 964 965 if (kms_bo_get_prop(bo, KMS_HANDLE, &handle)) 966 goto err_destroy; 967 968 ret = drmModeAddFB(ms->fd, 969 pScrn->virtualX, 970 pScrn->virtualY, 971 pScrn->depth, 972 pScrn->bitsPerPixel, 973 stride, 974 handle, 975 &ms->fb_id); 976 if (ret) { 977 debug_printf("%s: failed to create framebuffer (%i, %s)", 978 __func__, ret, strerror(-ret)); 979 goto err_destroy; 980 } 981 982 pScrn->frameX0 = 0; 983 pScrn->frameY0 = 0; 984 drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 985 ms->root_bo = bo; 986 987 return TRUE; 988 989err_destroy: 990 kms_bo_destroy(&bo); 991 return FALSE; 992} 993 994static Bool 995drv_bind_front_buffer_kms(ScrnInfoPtr pScrn) 996{ 997 modesettingPtr ms = modesettingPTR(pScrn); 998 ScreenPtr pScreen = pScrn->pScreen; 999 PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen); 1000 unsigned stride; 1001 void *ptr; 1002 1003 if (kms_bo_get_prop(ms->root_bo, KMS_PITCH, &stride)) 1004 return FALSE; 1005 1006 if (kms_bo_map(ms->root_bo, &ptr)) 1007 goto err_destroy; 1008 1009 pScreen->ModifyPixmapHeader(rootPixmap, 1010 pScreen->width, 1011 pScreen->height, 1012 pScreen->rootDepth, 1013 pScrn->bitsPerPixel, 1014 stride, 1015 ptr); 1016 return TRUE; 1017 1018err_destroy: 1019 kms_bo_destroy(&ms->root_bo); 1020 return FALSE; 1021} 1022#endif /* HAVE_LIBKMS */ 1023 1024static Bool drv_init_front_buffer_functions(ScrnInfoPtr pScrn) 1025{ 1026 modesettingPtr ms = modesettingPTR(pScrn); 1027 if (ms->screen) { 1028 ms->destroy_front_buffer = drv_destroy_front_buffer_ga3d; 1029 ms->create_front_buffer = drv_create_front_buffer_ga3d; 1030 ms->bind_front_buffer = drv_bind_front_buffer_ga3d; 1031#ifdef HAVE_LIBKMS 1032 } else if (ms->kms) { 1033 ms->destroy_front_buffer = drv_destroy_front_buffer_kms; 1034 ms->create_front_buffer = drv_create_front_buffer_kms; 1035 ms->bind_front_buffer = drv_bind_front_buffer_kms; 1036#endif 1037 } else 1038 return FALSE; 1039 1040 return TRUE; 1041} 1042 1043/* vim: set sw=4 ts=8 sts=4: */ 1044