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