driver.c (62763B)
1 /* 2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 3 * Copyright 2011 Dave Airlie 4 * Copyright 2019 NVIDIA CORPORATION 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 * 28 * Original Author: Alan Hourihane <alanh@tungstengraphics.com> 29 * Rewrite: Dave Airlie <airlied@redhat.com> 30 * Additional contributors: 31 * Aaron Plattner <aplattner@nvidia.com> 32 * 33 */ 34 35 #ifdef HAVE_DIX_CONFIG_H 36 #include "dix-config.h" 37 #endif 38 39 #include <unistd.h> 40 #include <fcntl.h> 41 #include "xf86.h" 42 #include "xf86Priv.h" 43 #include "xf86_OSproc.h" 44 #include "compiler.h" 45 #include "xf86Pci.h" 46 #include "mipointer.h" 47 #include "mipointrst.h" 48 #include "micmap.h" 49 #include <X11/extensions/randr.h> 50 #include "fb.h" 51 #include "edid.h" 52 #include "xf86i2c.h" 53 #include "xf86Crtc.h" 54 #include "miscstruct.h" 55 #include "dixstruct.h" 56 #include "xf86xv.h" 57 #include <X11/extensions/Xv.h> 58 #include <xorg-config.h> 59 #ifdef XSERVER_PLATFORM_BUS 60 #include "xf86platformBus.h" 61 #endif 62 #ifdef XSERVER_LIBPCIACCESS 63 #include <pciaccess.h> 64 #endif 65 #include "driver.h" 66 67 static void AdjustFrame(ScrnInfoPtr pScrn, int x, int y); 68 static Bool CloseScreen(ScreenPtr pScreen); 69 static Bool EnterVT(ScrnInfoPtr pScrn); 70 static void Identify(int flags); 71 static const OptionInfoRec *AvailableOptions(int chipid, int busid); 72 static ModeStatus ValidMode(ScrnInfoPtr pScrn, DisplayModePtr mode, 73 Bool verbose, int flags); 74 static void FreeScreen(ScrnInfoPtr pScrn); 75 static void LeaveVT(ScrnInfoPtr pScrn); 76 static Bool SwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode); 77 static Bool ScreenInit(ScreenPtr pScreen, int argc, char **argv); 78 static Bool PreInit(ScrnInfoPtr pScrn, int flags); 79 80 static Bool Probe(DriverPtr drv, int flags); 81 static Bool ms_pci_probe(DriverPtr driver, 82 int entity_num, struct pci_device *device, 83 intptr_t match_data); 84 static Bool ms_driver_func(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data); 85 86 /* window wrapper functions used to get the notification when 87 * the window property changes */ 88 static Atom vrr_atom; 89 static Bool property_vectors_wrapped; 90 static Bool restore_property_vector; 91 static int (*saved_change_property) (ClientPtr client); 92 static int (*saved_delete_property) (ClientPtr client); 93 94 #ifdef XSERVER_LIBPCIACCESS 95 static const struct pci_id_match ms_device_match[] = { 96 { 97 PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 98 0x00030000, 0x00ff0000, 0}, 99 100 {0, 0, 0}, 101 }; 102 #endif 103 104 #ifndef XSERVER_PLATFORM_BUS 105 struct xf86_platform_device; 106 #endif 107 108 #ifdef XSERVER_PLATFORM_BUS 109 static Bool ms_platform_probe(DriverPtr driver, 110 int entity_num, int flags, 111 struct xf86_platform_device *device, 112 intptr_t match_data); 113 #endif 114 115 _X_EXPORT DriverRec modesetting = { 116 1, 117 "modesetting", 118 Identify, 119 Probe, 120 AvailableOptions, 121 NULL, 122 0, 123 ms_driver_func, 124 ms_device_match, 125 ms_pci_probe, 126 #ifdef XSERVER_PLATFORM_BUS 127 ms_platform_probe, 128 #endif 129 }; 130 131 static SymTabRec Chipsets[] = { 132 {0, "kms"}, 133 {-1, NULL} 134 }; 135 136 static const OptionInfoRec Options[] = { 137 {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, 138 {OPTION_DEVICE_PATH, "kmsdev", OPTV_STRING, {0}, FALSE}, 139 {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE}, 140 {OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE}, 141 {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE}, 142 {OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE}, 143 {OPTION_DOUBLE_SHADOW, "DoubleShadow", OPTV_BOOLEAN, {0}, FALSE}, 144 {OPTION_ATOMIC, "Atomic", OPTV_BOOLEAN, {0}, FALSE}, 145 {OPTION_VARIABLE_REFRESH, "VariableRefresh", OPTV_BOOLEAN, {0}, FALSE}, 146 {OPTION_USE_GAMMA_LUT, "UseGammaLUT", OPTV_BOOLEAN, {0}, FALSE}, 147 {OPTION_ASYNC_FLIP_SECONDARIES, "AsyncFlipSecondaries", OPTV_BOOLEAN, {0}, FALSE}, 148 {-1, NULL, OPTV_NONE, {0}, FALSE} 149 }; 150 151 int ms_entity_index = -1; 152 153 static MODULESETUPPROTO(Setup); 154 155 static XF86ModuleVersionInfo VersRec = { 156 "modesetting", 157 MODULEVENDORSTRING, 158 MODINFOSTRING1, 159 MODINFOSTRING2, 160 XORG_VERSION_CURRENT, 161 XORG_VERSION_MAJOR, 162 XORG_VERSION_MINOR, 163 XORG_VERSION_PATCH, 164 ABI_CLASS_VIDEODRV, 165 ABI_VIDEODRV_VERSION, 166 MOD_CLASS_VIDEODRV, 167 {0, 0, 0, 0} 168 }; 169 170 _X_EXPORT XF86ModuleData modesettingModuleData = { &VersRec, Setup, NULL }; 171 172 static void * 173 Setup(void *module, void *opts, int *errmaj, int *errmin) 174 { 175 static Bool setupDone = 0; 176 177 /* This module should be loaded only once, but check to be sure. 178 */ 179 if (!setupDone) { 180 setupDone = 1; 181 xf86AddDriver(&modesetting, module, HaveDriverFuncs); 182 183 /* 184 * The return value must be non-NULL on success even though there 185 * is no TearDownProc. 186 */ 187 return (void *) 1; 188 } 189 else { 190 if (errmaj) 191 *errmaj = LDR_ONCEONLY; 192 return NULL; 193 } 194 } 195 196 static void 197 Identify(int flags) 198 { 199 xf86PrintChipsets("modesetting", "Driver for Modesetting Kernel Drivers", 200 Chipsets); 201 } 202 203 modesettingEntPtr ms_ent_priv(ScrnInfoPtr scrn) 204 { 205 DevUnion *pPriv; 206 modesettingPtr ms = modesettingPTR(scrn); 207 pPriv = xf86GetEntityPrivate(ms->pEnt->index, 208 ms_entity_index); 209 return pPriv->ptr; 210 } 211 212 static int 213 get_passed_fd(void) 214 { 215 if (xf86DRMMasterFd >= 0) { 216 xf86DrvMsg(-1, X_INFO, "Using passed DRM master file descriptor %d\n", xf86DRMMasterFd); 217 return dup(xf86DRMMasterFd); 218 } 219 return -1; 220 } 221 222 static int 223 open_hw(const char *dev) 224 { 225 int fd; 226 227 if ((fd = get_passed_fd()) != -1) 228 return fd; 229 230 if (dev) 231 fd = open(dev, O_RDWR | O_CLOEXEC, 0); 232 else { 233 dev = getenv("KMSDEVICE"); 234 if ((NULL == dev) || ((fd = open(dev, O_RDWR | O_CLOEXEC, 0)) == -1)) { 235 dev = "/dev/dri/card0"; 236 fd = open(dev, O_RDWR | O_CLOEXEC, 0); 237 } 238 } 239 if (fd == -1) 240 xf86DrvMsg(-1, X_ERROR, "open %s: %s\n", dev, strerror(errno)); 241 242 return fd; 243 } 244 245 static int 246 check_outputs(int fd, int *count) 247 { 248 drmModeResPtr res = drmModeGetResources(fd); 249 int ret; 250 251 if (!res) 252 return FALSE; 253 254 if (count) 255 *count = res->count_connectors; 256 257 ret = res->count_connectors > 0; 258 #if defined(GLAMOR_HAS_GBM_LINEAR) 259 if (ret == FALSE) { 260 uint64_t value = 0; 261 if (drmGetCap(fd, DRM_CAP_PRIME, &value) == 0 && 262 (value & DRM_PRIME_CAP_EXPORT)) 263 ret = TRUE; 264 } 265 #endif 266 drmModeFreeResources(res); 267 return ret; 268 } 269 270 static Bool 271 probe_hw(const char *dev, struct xf86_platform_device *platform_dev) 272 { 273 int fd; 274 275 #ifdef XF86_PDEV_SERVER_FD 276 if (platform_dev && (platform_dev->flags & XF86_PDEV_SERVER_FD)) { 277 fd = xf86_platform_device_odev_attributes(platform_dev)->fd; 278 if (fd == -1) 279 return FALSE; 280 return check_outputs(fd, NULL); 281 } 282 #endif 283 284 fd = open_hw(dev); 285 if (fd != -1) { 286 int ret = check_outputs(fd, NULL); 287 288 close(fd); 289 return ret; 290 } 291 return FALSE; 292 } 293 294 static char * 295 ms_DRICreatePCIBusID(const struct pci_device *dev) 296 { 297 char *busID; 298 299 if (asprintf(&busID, "pci:%04x:%02x:%02x.%d", 300 dev->domain, dev->bus, dev->dev, dev->func) == -1) 301 return NULL; 302 303 return busID; 304 } 305 306 static Bool 307 probe_hw_pci(const char *dev, struct pci_device *pdev) 308 { 309 int ret = FALSE, fd = open_hw(dev); 310 char *id, *devid; 311 drmSetVersion sv; 312 313 if (fd == -1) 314 return FALSE; 315 316 sv.drm_di_major = 1; 317 sv.drm_di_minor = 4; 318 sv.drm_dd_major = -1; 319 sv.drm_dd_minor = -1; 320 if (drmSetInterfaceVersion(fd, &sv)) { 321 close(fd); 322 return FALSE; 323 } 324 325 id = drmGetBusid(fd); 326 devid = ms_DRICreatePCIBusID(pdev); 327 328 if (id && devid && !strcmp(id, devid)) 329 ret = check_outputs(fd, NULL); 330 331 close(fd); 332 free(id); 333 free(devid); 334 return ret; 335 } 336 337 static const OptionInfoRec * 338 AvailableOptions(int chipid, int busid) 339 { 340 return Options; 341 } 342 343 static Bool 344 ms_driver_func(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data) 345 { 346 xorgHWFlags *flag; 347 348 switch (op) { 349 case GET_REQUIRED_HW_INTERFACES: 350 flag = (CARD32 *) data; 351 (*flag) = 0; 352 return TRUE; 353 case SUPPORTS_SERVER_FDS: 354 return TRUE; 355 default: 356 return FALSE; 357 } 358 } 359 360 static void 361 ms_setup_scrn_hooks(ScrnInfoPtr scrn) 362 { 363 scrn->driverVersion = 1; 364 scrn->driverName = "modesetting"; 365 scrn->name = "modeset"; 366 367 scrn->Probe = NULL; 368 scrn->PreInit = PreInit; 369 scrn->ScreenInit = ScreenInit; 370 scrn->SwitchMode = SwitchMode; 371 scrn->AdjustFrame = AdjustFrame; 372 scrn->EnterVT = EnterVT; 373 scrn->LeaveVT = LeaveVT; 374 scrn->FreeScreen = FreeScreen; 375 scrn->ValidMode = ValidMode; 376 } 377 378 static void 379 ms_setup_entity(ScrnInfoPtr scrn, int entity_num) 380 { 381 DevUnion *pPriv; 382 383 xf86SetEntitySharable(entity_num); 384 385 if (ms_entity_index == -1) 386 ms_entity_index = xf86AllocateEntityPrivateIndex(); 387 388 pPriv = xf86GetEntityPrivate(entity_num, 389 ms_entity_index); 390 391 xf86SetEntityInstanceForScreen(scrn, entity_num, xf86GetNumEntityInstances(entity_num) - 1); 392 393 if (!pPriv->ptr) 394 pPriv->ptr = xnfcalloc(sizeof(modesettingEntRec), 1); 395 } 396 397 #ifdef XSERVER_LIBPCIACCESS 398 static Bool 399 ms_pci_probe(DriverPtr driver, 400 int entity_num, struct pci_device *dev, intptr_t match_data) 401 { 402 ScrnInfoPtr scrn = NULL; 403 404 scrn = xf86ConfigPciEntity(scrn, 0, entity_num, NULL, 405 NULL, NULL, NULL, NULL, NULL); 406 if (scrn) { 407 const char *devpath; 408 GDevPtr devSection = xf86GetDevFromEntity(scrn->entityList[0], 409 scrn->entityInstanceList[0]); 410 411 devpath = xf86FindOptionValue(devSection->options, "kmsdev"); 412 if (probe_hw_pci(devpath, dev)) { 413 ms_setup_scrn_hooks(scrn); 414 415 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, 416 "claimed PCI slot %d@%d:%d:%d\n", 417 dev->bus, dev->domain, dev->dev, dev->func); 418 xf86DrvMsg(scrn->scrnIndex, X_INFO, 419 "using %s\n", devpath ? devpath : "default device"); 420 421 ms_setup_entity(scrn, entity_num); 422 } 423 else 424 scrn = NULL; 425 } 426 return scrn != NULL; 427 } 428 #endif 429 430 #ifdef XSERVER_PLATFORM_BUS 431 static Bool 432 ms_platform_probe(DriverPtr driver, 433 int entity_num, int flags, struct xf86_platform_device *dev, 434 intptr_t match_data) 435 { 436 ScrnInfoPtr scrn = NULL; 437 const char *path = xf86_platform_device_odev_attributes(dev)->path; 438 int scr_flags = 0; 439 440 if (flags & PLATFORM_PROBE_GPU_SCREEN) 441 scr_flags = XF86_ALLOCATE_GPU_SCREEN; 442 443 if (probe_hw(path, dev)) { 444 scrn = xf86AllocateScreen(driver, scr_flags); 445 if (xf86IsEntitySharable(entity_num)) 446 xf86SetEntityShared(entity_num); 447 xf86AddEntityToScreen(scrn, entity_num); 448 449 ms_setup_scrn_hooks(scrn); 450 451 xf86DrvMsg(scrn->scrnIndex, X_INFO, 452 "using drv %s\n", path ? path : "default device"); 453 454 ms_setup_entity(scrn, entity_num); 455 } 456 457 return scrn != NULL; 458 } 459 #endif 460 461 static Bool 462 Probe(DriverPtr drv, int flags) 463 { 464 int i, numDevSections; 465 GDevPtr *devSections; 466 Bool foundScreen = FALSE; 467 const char *dev; 468 ScrnInfoPtr scrn = NULL; 469 470 /* For now, just bail out for PROBE_DETECT. */ 471 if (flags & PROBE_DETECT) 472 return FALSE; 473 474 /* 475 * Find the config file Device sections that match this 476 * driver, and return if there are none. 477 */ 478 if ((numDevSections = xf86MatchDevice("modesetting", &devSections)) <= 0) { 479 return FALSE; 480 } 481 482 for (i = 0; i < numDevSections; i++) { 483 int entity_num; 484 dev = xf86FindOptionValue(devSections[i]->options, "kmsdev"); 485 if (probe_hw(dev, NULL)) { 486 487 entity_num = xf86ClaimFbSlot(drv, 0, devSections[i], TRUE); 488 scrn = xf86ConfigFbEntity(scrn, 0, entity_num, NULL, NULL, NULL, NULL); 489 } 490 491 if (scrn) { 492 foundScreen = TRUE; 493 ms_setup_scrn_hooks(scrn); 494 scrn->Probe = Probe; 495 496 xf86DrvMsg(scrn->scrnIndex, X_INFO, 497 "using %s\n", dev ? dev : "default device"); 498 ms_setup_entity(scrn, entity_num); 499 } 500 } 501 502 free(devSections); 503 504 return foundScreen; 505 } 506 507 static Bool 508 GetRec(ScrnInfoPtr pScrn) 509 { 510 if (pScrn->driverPrivate) 511 return TRUE; 512 513 pScrn->driverPrivate = xnfcalloc(sizeof(modesettingRec), 1); 514 515 return TRUE; 516 } 517 518 static int 519 dispatch_dirty_region(ScrnInfoPtr scrn, 520 PixmapPtr pixmap, DamagePtr damage, int fb_id) 521 { 522 modesettingPtr ms = modesettingPTR(scrn); 523 RegionPtr dirty = DamageRegion(damage); 524 unsigned num_cliprects = REGION_NUM_RECTS(dirty); 525 int ret = 0; 526 527 if (num_cliprects) { 528 drmModeClip *clip = xallocarray(num_cliprects, sizeof(drmModeClip)); 529 BoxPtr rect = REGION_RECTS(dirty); 530 int i; 531 532 if (!clip) 533 return -ENOMEM; 534 535 /* XXX no need for copy? */ 536 for (i = 0; i < num_cliprects; i++, rect++) { 537 clip[i].x1 = rect->x1; 538 clip[i].y1 = rect->y1; 539 clip[i].x2 = rect->x2; 540 clip[i].y2 = rect->y2; 541 } 542 543 /* TODO query connector property to see if this is needed */ 544 ret = drmModeDirtyFB(ms->fd, fb_id, clip, num_cliprects); 545 546 /* if we're swamping it with work, try one at a time */ 547 if (ret == -EINVAL) { 548 for (i = 0; i < num_cliprects; i++) { 549 if ((ret = drmModeDirtyFB(ms->fd, fb_id, &clip[i], 1)) < 0) 550 break; 551 } 552 } 553 554 free(clip); 555 DamageEmpty(damage); 556 } 557 return ret; 558 } 559 560 static void 561 dispatch_dirty(ScreenPtr pScreen) 562 { 563 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 564 modesettingPtr ms = modesettingPTR(scrn); 565 PixmapPtr pixmap = pScreen->GetScreenPixmap(pScreen); 566 int fb_id = ms->drmmode.fb_id; 567 int ret; 568 569 ret = dispatch_dirty_region(scrn, pixmap, ms->damage, fb_id); 570 if (ret == -EINVAL || ret == -ENOSYS) { 571 ms->dirty_enabled = FALSE; 572 DamageUnregister(ms->damage); 573 DamageDestroy(ms->damage); 574 ms->damage = NULL; 575 xf86DrvMsg(scrn->scrnIndex, X_INFO, 576 "Disabling kernel dirty updates, not required.\n"); 577 return; 578 } 579 } 580 581 static void 582 dispatch_dirty_pixmap(ScrnInfoPtr scrn, xf86CrtcPtr crtc, PixmapPtr ppix) 583 { 584 modesettingPtr ms = modesettingPTR(scrn); 585 msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix); 586 DamagePtr damage = ppriv->secondary_damage; 587 int fb_id = ppriv->fb_id; 588 589 dispatch_dirty_region(scrn, ppix, damage, fb_id); 590 } 591 592 static void 593 dispatch_secondary_dirty(ScreenPtr pScreen) 594 { 595 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 596 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 597 int c; 598 599 for (c = 0; c < xf86_config->num_crtc; c++) { 600 xf86CrtcPtr crtc = xf86_config->crtc[c]; 601 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 602 603 if (!drmmode_crtc) 604 continue; 605 606 if (drmmode_crtc->prime_pixmap) 607 dispatch_dirty_pixmap(scrn, crtc, drmmode_crtc->prime_pixmap); 608 if (drmmode_crtc->prime_pixmap_back) 609 dispatch_dirty_pixmap(scrn, crtc, drmmode_crtc->prime_pixmap_back); 610 } 611 } 612 613 static void 614 redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty, int *timeout) 615 { 616 RegionRec pixregion; 617 618 PixmapRegionInit(&pixregion, dirty->secondary_dst); 619 DamageRegionAppend(&dirty->secondary_dst->drawable, &pixregion); 620 PixmapSyncDirtyHelper(dirty); 621 622 if (!screen->isGPU) { 623 #ifdef GLAMOR_HAS_GBM 624 modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(screen)); 625 /* 626 * When copying from the primary framebuffer to the shared pixmap, 627 * we must ensure the copy is complete before the secondary starts a 628 * copy to its own framebuffer (some secondarys scanout directly from 629 * the shared pixmap, but not all). 630 */ 631 if (ms->drmmode.glamor) 632 ms->glamor.finish(screen); 633 #endif 634 /* Ensure the secondary processes the damage immediately */ 635 if (timeout) 636 *timeout = 0; 637 } 638 639 DamageRegionProcessPending(&dirty->secondary_dst->drawable); 640 RegionUninit(&pixregion); 641 } 642 643 static void 644 ms_dirty_update(ScreenPtr screen, int *timeout) 645 { 646 modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(screen)); 647 648 RegionPtr region; 649 PixmapDirtyUpdatePtr ent; 650 651 if (xorg_list_is_empty(&screen->pixmap_dirty_list)) 652 return; 653 654 xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) { 655 region = DamageRegion(ent->damage); 656 if (RegionNotEmpty(region)) { 657 if (!screen->isGPU) { 658 msPixmapPrivPtr ppriv = 659 msGetPixmapPriv(&ms->drmmode, ent->secondary_dst->primary_pixmap); 660 661 if (ppriv->notify_on_damage) { 662 ppriv->notify_on_damage = FALSE; 663 664 ent->secondary_dst->drawable.pScreen-> 665 SharedPixmapNotifyDamage(ent->secondary_dst); 666 } 667 668 /* Requested manual updating */ 669 if (ppriv->defer_dirty_update) 670 continue; 671 } 672 673 redisplay_dirty(screen, ent, timeout); 674 DamageEmpty(ent->damage); 675 } 676 } 677 } 678 679 static PixmapDirtyUpdatePtr 680 ms_dirty_get_ent(ScreenPtr screen, PixmapPtr secondary_dst) 681 { 682 PixmapDirtyUpdatePtr ent; 683 684 if (xorg_list_is_empty(&screen->pixmap_dirty_list)) 685 return NULL; 686 687 xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) { 688 if (ent->secondary_dst == secondary_dst) 689 return ent; 690 } 691 692 return NULL; 693 } 694 695 static void 696 msBlockHandler(ScreenPtr pScreen, void *timeout) 697 { 698 modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen)); 699 700 pScreen->BlockHandler = ms->BlockHandler; 701 pScreen->BlockHandler(pScreen, timeout); 702 ms->BlockHandler = pScreen->BlockHandler; 703 pScreen->BlockHandler = msBlockHandler; 704 if (pScreen->isGPU && !ms->drmmode.reverse_prime_offload_mode) 705 dispatch_secondary_dirty(pScreen); 706 else if (ms->dirty_enabled) 707 dispatch_dirty(pScreen); 708 709 ms_dirty_update(pScreen, timeout); 710 } 711 712 static void 713 msBlockHandler_oneshot(ScreenPtr pScreen, void *pTimeout) 714 { 715 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 716 modesettingPtr ms = modesettingPTR(pScrn); 717 718 msBlockHandler(pScreen, pTimeout); 719 720 drmmode_set_desired_modes(pScrn, &ms->drmmode, TRUE, FALSE); 721 } 722 723 Bool 724 ms_window_has_variable_refresh(modesettingPtr ms, WindowPtr win) { 725 struct ms_vrr_priv *priv = dixLookupPrivate(&win->devPrivates, &ms->drmmode.vrrPrivateKeyRec); 726 727 return priv->variable_refresh; 728 } 729 730 static void 731 ms_vrr_property_update(WindowPtr window, Bool variable_refresh) 732 { 733 ScrnInfoPtr scrn = xf86ScreenToScrn(window->drawable.pScreen); 734 modesettingPtr ms = modesettingPTR(scrn); 735 736 struct ms_vrr_priv *priv = dixLookupPrivate(&window->devPrivates, 737 &ms->drmmode.vrrPrivateKeyRec); 738 priv->variable_refresh = variable_refresh; 739 740 if (ms->flip_window == window && ms->drmmode.present_flipping) 741 ms_present_set_screen_vrr(scrn, variable_refresh); 742 } 743 744 /* Wrapper for xserver/dix/property.c:ProcChangeProperty */ 745 static int 746 ms_change_property(ClientPtr client) 747 { 748 WindowPtr window = NULL; 749 int ret = 0; 750 751 REQUEST(xChangePropertyReq); 752 753 client->requestVector[X_ChangeProperty] = saved_change_property; 754 ret = saved_change_property(client); 755 756 if (restore_property_vector) 757 return ret; 758 759 client->requestVector[X_ChangeProperty] = ms_change_property; 760 761 if (ret != Success) 762 return ret; 763 764 ret = dixLookupWindow(&window, stuff->window, client, DixSetPropAccess); 765 if (ret != Success) 766 return ret; 767 768 // Checking for the VRR property change on the window 769 if (stuff->property == vrr_atom && 770 xf86ScreenToScrn(window->drawable.pScreen)->PreInit == PreInit && 771 stuff->format == 32 && stuff->nUnits == 1) { 772 uint32_t *value = (uint32_t *)(stuff + 1); 773 ms_vrr_property_update(window, *value != 0); 774 } 775 776 return ret; 777 } 778 779 /* Wrapper for xserver/dix/property.c:ProcDeleteProperty */ 780 static int 781 ms_delete_property(ClientPtr client) 782 { 783 WindowPtr window; 784 int ret; 785 786 REQUEST(xDeletePropertyReq); 787 788 client->requestVector[X_DeleteProperty] = saved_delete_property; 789 ret = saved_delete_property(client); 790 791 if (restore_property_vector) 792 return ret; 793 794 client->requestVector[X_DeleteProperty] = ms_delete_property; 795 796 if (ret != Success) 797 return ret; 798 799 ret = dixLookupWindow(&window, stuff->window, client, DixSetPropAccess); 800 if (ret != Success) 801 return ret; 802 803 if (stuff->property == vrr_atom && 804 xf86ScreenToScrn(window->drawable.pScreen)->PreInit == PreInit) 805 ms_vrr_property_update(window, FALSE); 806 807 return ret; 808 } 809 810 static void 811 ms_unwrap_property_requests(ScrnInfoPtr scrn) 812 { 813 int i; 814 815 if (!property_vectors_wrapped) 816 return; 817 818 if (ProcVector[X_ChangeProperty] == ms_change_property) 819 ProcVector[X_ChangeProperty] = saved_change_property; 820 else 821 restore_property_vector = TRUE; 822 823 if (ProcVector[X_DeleteProperty] == ms_delete_property) 824 ProcVector[X_DeleteProperty] = saved_delete_property; 825 else 826 restore_property_vector = TRUE; 827 828 for (i = 0; i < currentMaxClients; i++) { 829 if (clients[i]->requestVector[X_ChangeProperty] == ms_change_property) { 830 clients[i]->requestVector[X_ChangeProperty] = saved_change_property; 831 } else { 832 restore_property_vector = TRUE; 833 } 834 835 if (clients[i]->requestVector[X_DeleteProperty] == ms_delete_property) { 836 clients[i]->requestVector[X_DeleteProperty] = saved_delete_property; 837 } else { 838 restore_property_vector = TRUE; 839 } 840 } 841 842 if (restore_property_vector) { 843 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 844 "Couldn't unwrap some window property request vectors\n"); 845 } 846 847 property_vectors_wrapped = FALSE; 848 } 849 850 static void 851 FreeRec(ScrnInfoPtr pScrn) 852 { 853 modesettingPtr ms; 854 855 if (!pScrn) 856 return; 857 858 ms = modesettingPTR(pScrn); 859 if (!ms) 860 return; 861 862 if (ms->fd > 0) { 863 modesettingEntPtr ms_ent; 864 int ret; 865 866 ms_ent = ms_ent_priv(pScrn); 867 ms_ent->fd_ref--; 868 if (!ms_ent->fd_ref) { 869 ms_unwrap_property_requests(pScrn); 870 if (ms->pEnt->location.type == BUS_PCI) 871 ret = drmClose(ms->fd); 872 else 873 #ifdef XF86_PDEV_SERVER_FD 874 if (!(ms->pEnt->location.type == BUS_PLATFORM && 875 (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD))) 876 #endif 877 ret = close(ms->fd); 878 (void) ret; 879 ms_ent->fd = 0; 880 } 881 } 882 pScrn->driverPrivate = NULL; 883 free(ms->drmmode.Options); 884 free(ms); 885 886 } 887 888 #ifdef GLAMOR_HAS_GBM 889 890 static Bool 891 load_glamor(ScrnInfoPtr pScrn) 892 { 893 void *mod = xf86LoadSubModule(pScrn, GLAMOR_EGL_MODULE_NAME); 894 modesettingPtr ms = modesettingPTR(pScrn); 895 896 if (!mod) 897 return FALSE; 898 899 ms->glamor.back_pixmap_from_fd = LoaderSymbolFromModule(mod, "glamor_back_pixmap_from_fd"); 900 ms->glamor.block_handler = LoaderSymbolFromModule(mod, "glamor_block_handler"); 901 ms->glamor.clear_pixmap = LoaderSymbolFromModule(mod, "glamor_clear_pixmap"); 902 ms->glamor.egl_create_textured_pixmap = LoaderSymbolFromModule(mod, "glamor_egl_create_textured_pixmap"); 903 ms->glamor.egl_create_textured_pixmap_from_gbm_bo = LoaderSymbolFromModule(mod, "glamor_egl_create_textured_pixmap_from_gbm_bo"); 904 ms->glamor.egl_exchange_buffers = LoaderSymbolFromModule(mod, "glamor_egl_exchange_buffers"); 905 ms->glamor.egl_get_gbm_device = LoaderSymbolFromModule(mod, "glamor_egl_get_gbm_device"); 906 ms->glamor.egl_init = LoaderSymbolFromModule(mod, "glamor_egl_init"); 907 ms->glamor.finish = LoaderSymbolFromModule(mod, "glamor_finish"); 908 ms->glamor.gbm_bo_from_pixmap = LoaderSymbolFromModule(mod, "glamor_gbm_bo_from_pixmap"); 909 ms->glamor.init = LoaderSymbolFromModule(mod, "glamor_init"); 910 ms->glamor.name_from_pixmap = LoaderSymbolFromModule(mod, "glamor_name_from_pixmap"); 911 ms->glamor.set_drawable_modifiers_func = LoaderSymbolFromModule(mod, "glamor_set_drawable_modifiers_func"); 912 ms->glamor.shareable_fd_from_pixmap = LoaderSymbolFromModule(mod, "glamor_shareable_fd_from_pixmap"); 913 ms->glamor.supports_pixmap_import_export = LoaderSymbolFromModule(mod, "glamor_supports_pixmap_import_export"); 914 ms->glamor.xv_init = LoaderSymbolFromModule(mod, "glamor_xv_init"); 915 ms->glamor.egl_get_driver_name = LoaderSymbolFromModule(mod, "glamor_egl_get_driver_name"); 916 917 return TRUE; 918 } 919 920 #endif 921 922 static void 923 try_enable_glamor(ScrnInfoPtr pScrn) 924 { 925 modesettingPtr ms = modesettingPTR(pScrn); 926 const char *accel_method_str = xf86GetOptValString(ms->drmmode.Options, 927 OPTION_ACCEL_METHOD); 928 Bool do_glamor = (!accel_method_str || 929 strcmp(accel_method_str, "glamor") == 0); 930 931 ms->drmmode.glamor = FALSE; 932 933 #ifdef GLAMOR_HAS_GBM 934 if (ms->drmmode.force_24_32) { 935 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Cannot use glamor with 24bpp packed fb\n"); 936 return; 937 } 938 939 if (!do_glamor) { 940 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "glamor disabled\n"); 941 return; 942 } 943 944 if (load_glamor(pScrn)) { 945 if (ms->glamor.egl_init(pScrn, ms->fd)) { 946 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "glamor initialized\n"); 947 ms->drmmode.glamor = TRUE; 948 } else { 949 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 950 "glamor initialization failed\n"); 951 } 952 } else { 953 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 954 "Failed to load glamor module.\n"); 955 } 956 #else 957 if (do_glamor) { 958 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 959 "No glamor support in the X Server\n"); 960 } 961 #endif 962 } 963 964 static Bool 965 msShouldDoubleShadow(ScrnInfoPtr pScrn, modesettingPtr ms) 966 { 967 Bool ret = FALSE, asked; 968 int from; 969 drmVersionPtr v = drmGetVersion(ms->fd); 970 971 if (!ms->drmmode.shadow_enable) 972 return FALSE; 973 974 if (!strcmp(v->name, "mgag200") || 975 !strcmp(v->name, "ast")) /* XXX || rn50 */ 976 ret = TRUE; 977 978 drmFreeVersion(v); 979 980 asked = xf86GetOptValBool(ms->drmmode.Options, OPTION_DOUBLE_SHADOW, &ret); 981 982 if (asked) 983 from = X_CONFIG; 984 else 985 from = X_INFO; 986 987 xf86DrvMsg(pScrn->scrnIndex, from, 988 "Double-buffered shadow updates: %s\n", ret ? "on" : "off"); 989 990 return ret; 991 } 992 993 static Bool 994 ms_get_drm_master_fd(ScrnInfoPtr pScrn) 995 { 996 EntityInfoPtr pEnt; 997 modesettingPtr ms; 998 modesettingEntPtr ms_ent; 999 1000 ms = modesettingPTR(pScrn); 1001 ms_ent = ms_ent_priv(pScrn); 1002 1003 pEnt = ms->pEnt; 1004 1005 if (ms_ent->fd) { 1006 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1007 " reusing fd for second head\n"); 1008 ms->fd = ms_ent->fd; 1009 ms_ent->fd_ref++; 1010 return TRUE; 1011 } 1012 1013 ms->fd_passed = FALSE; 1014 if ((ms->fd = get_passed_fd()) >= 0) { 1015 ms->fd_passed = TRUE; 1016 return TRUE; 1017 } 1018 1019 #ifdef XSERVER_PLATFORM_BUS 1020 if (pEnt->location.type == BUS_PLATFORM) { 1021 #ifdef XF86_PDEV_SERVER_FD 1022 if (pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD) 1023 ms->fd = 1024 xf86_platform_device_odev_attributes(pEnt->location.id.plat)-> 1025 fd; 1026 else 1027 #endif 1028 { 1029 char *path = 1030 xf86_platform_device_odev_attributes(pEnt->location.id.plat)-> 1031 path; 1032 ms->fd = open_hw(path); 1033 } 1034 } 1035 else 1036 #endif 1037 #ifdef XSERVER_LIBPCIACCESS 1038 if (pEnt->location.type == BUS_PCI) { 1039 char *BusID = NULL; 1040 struct pci_device *PciInfo; 1041 1042 PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index); 1043 if (PciInfo) { 1044 if ((BusID = ms_DRICreatePCIBusID(PciInfo)) != NULL) { 1045 ms->fd = drmOpen(NULL, BusID); 1046 free(BusID); 1047 } 1048 } 1049 } 1050 else 1051 #endif 1052 { 1053 const char *devicename; 1054 devicename = xf86FindOptionValue(ms->pEnt->device->options, "kmsdev"); 1055 ms->fd = open_hw(devicename); 1056 } 1057 if (ms->fd < 0) 1058 return FALSE; 1059 1060 ms_ent->fd = ms->fd; 1061 ms_ent->fd_ref = 1; 1062 return TRUE; 1063 } 1064 1065 static Bool 1066 PreInit(ScrnInfoPtr pScrn, int flags) 1067 { 1068 modesettingPtr ms; 1069 rgb defaultWeight = { 0, 0, 0 }; 1070 EntityInfoPtr pEnt; 1071 uint64_t value = 0; 1072 int ret; 1073 int bppflags, connector_count; 1074 int defaultdepth, defaultbpp; 1075 1076 if (pScrn->numEntities != 1) 1077 return FALSE; 1078 1079 if (flags & PROBE_DETECT) { 1080 return FALSE; 1081 } 1082 1083 /* Allocate driverPrivate */ 1084 if (!GetRec(pScrn)) 1085 return FALSE; 1086 1087 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 1088 1089 ms = modesettingPTR(pScrn); 1090 ms->SaveGeneration = -1; 1091 ms->pEnt = pEnt; 1092 ms->drmmode.is_secondary = FALSE; 1093 pScrn->displayWidth = 640; /* default it */ 1094 1095 if (xf86IsEntityShared(pScrn->entityList[0])) { 1096 if (xf86IsPrimInitDone(pScrn->entityList[0])) 1097 ms->drmmode.is_secondary = TRUE; 1098 else 1099 xf86SetPrimInitDone(pScrn->entityList[0]); 1100 } 1101 1102 pScrn->monitor = pScrn->confScreen->monitor; 1103 pScrn->progClock = TRUE; 1104 pScrn->rgbBits = 8; 1105 1106 if (!ms_get_drm_master_fd(pScrn)) 1107 return FALSE; 1108 ms->drmmode.fd = ms->fd; 1109 1110 if (!check_outputs(ms->fd, &connector_count)) 1111 return FALSE; 1112 1113 drmmode_get_default_bpp(pScrn, &ms->drmmode, &defaultdepth, &defaultbpp); 1114 if (defaultdepth == 24 && defaultbpp == 24) { 1115 ms->drmmode.force_24_32 = TRUE; 1116 ms->drmmode.kbpp = 24; 1117 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1118 "Using 24bpp hw front buffer with 32bpp shadow\n"); 1119 defaultbpp = 32; 1120 } else { 1121 ms->drmmode.kbpp = 0; 1122 } 1123 bppflags = PreferConvert24to32 | SupportConvert24to32 | Support32bppFb; 1124 1125 if (!xf86SetDepthBpp 1126 (pScrn, defaultdepth, defaultdepth, defaultbpp, bppflags)) 1127 return FALSE; 1128 1129 switch (pScrn->depth) { 1130 case 15: 1131 case 16: 1132 case 24: 1133 case 30: 1134 break; 1135 default: 1136 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1137 "Given depth (%d) is not supported by the driver\n", 1138 pScrn->depth); 1139 return FALSE; 1140 } 1141 xf86PrintDepthBpp(pScrn); 1142 if (!ms->drmmode.kbpp) 1143 ms->drmmode.kbpp = pScrn->bitsPerPixel; 1144 1145 /* Process the options */ 1146 xf86CollectOptions(pScrn, NULL); 1147 if (!(ms->drmmode.Options = malloc(sizeof(Options)))) 1148 return FALSE; 1149 memcpy(ms->drmmode.Options, Options, sizeof(Options)); 1150 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->drmmode.Options); 1151 1152 if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) 1153 return FALSE; 1154 if (!xf86SetDefaultVisual(pScrn, -1)) 1155 return FALSE; 1156 1157 if (xf86ReturnOptValBool(ms->drmmode.Options, OPTION_SW_CURSOR, FALSE)) { 1158 ms->drmmode.sw_cursor = TRUE; 1159 } 1160 1161 ms->cursor_width = 64; 1162 ms->cursor_height = 64; 1163 ret = drmGetCap(ms->fd, DRM_CAP_CURSOR_WIDTH, &value); 1164 if (!ret) { 1165 ms->cursor_width = value; 1166 } 1167 ret = drmGetCap(ms->fd, DRM_CAP_CURSOR_HEIGHT, &value); 1168 if (!ret) { 1169 ms->cursor_height = value; 1170 } 1171 1172 try_enable_glamor(pScrn); 1173 1174 if (!ms->drmmode.glamor) { 1175 Bool prefer_shadow = TRUE; 1176 1177 if (ms->drmmode.force_24_32) { 1178 prefer_shadow = TRUE; 1179 ms->drmmode.shadow_enable = TRUE; 1180 } else { 1181 ret = drmGetCap(ms->fd, DRM_CAP_DUMB_PREFER_SHADOW, &value); 1182 if (!ret) { 1183 prefer_shadow = !!value; 1184 } 1185 1186 ms->drmmode.shadow_enable = 1187 xf86ReturnOptValBool(ms->drmmode.Options, OPTION_SHADOW_FB, 1188 prefer_shadow); 1189 } 1190 1191 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1192 "ShadowFB: preferred %s, enabled %s\n", 1193 prefer_shadow ? "YES" : "NO", 1194 ms->drmmode.force_24_32 ? "FORCE" : 1195 ms->drmmode.shadow_enable ? "YES" : "NO"); 1196 1197 ms->drmmode.shadow_enable2 = msShouldDoubleShadow(pScrn, ms); 1198 } else { 1199 if (!pScrn->is_gpu) { 1200 MessageType from = xf86GetOptValBool(ms->drmmode.Options, OPTION_VARIABLE_REFRESH, 1201 &ms->vrr_support) ? X_CONFIG : X_DEFAULT; 1202 xf86DrvMsg(pScrn->scrnIndex, from, "VariableRefresh: %sabled\n", 1203 ms->vrr_support ? "en" : "dis"); 1204 1205 ms->drmmode.async_flip_secondaries = FALSE; 1206 from = xf86GetOptValBool(ms->drmmode.Options, OPTION_ASYNC_FLIP_SECONDARIES, 1207 &ms->drmmode.async_flip_secondaries) ? X_CONFIG : X_DEFAULT; 1208 xf86DrvMsg(pScrn->scrnIndex, from, "AsyncFlipSecondaries: %sabled\n", 1209 ms->drmmode.async_flip_secondaries ? "en" : "dis"); 1210 } 1211 } 1212 1213 ms->drmmode.pageflip = 1214 xf86ReturnOptValBool(ms->drmmode.Options, OPTION_PAGEFLIP, TRUE); 1215 1216 pScrn->capabilities = 0; 1217 ret = drmGetCap(ms->fd, DRM_CAP_PRIME, &value); 1218 if (ret == 0) { 1219 if (connector_count && (value & DRM_PRIME_CAP_IMPORT)) { 1220 pScrn->capabilities |= RR_Capability_SinkOutput; 1221 if (ms->drmmode.glamor) 1222 pScrn->capabilities |= RR_Capability_SinkOffload; 1223 } 1224 #ifdef GLAMOR_HAS_GBM_LINEAR 1225 if (value & DRM_PRIME_CAP_EXPORT && ms->drmmode.glamor) 1226 pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SourceOffload; 1227 #endif 1228 } 1229 1230 /* 1231 * Use "atomic modesetting disable" request to detect if the kms driver is 1232 * atomic capable, regardless if we will actually use atomic modesetting. 1233 * This is effectively a no-op, we only care about the return status code. 1234 */ 1235 ret = drmSetClientCap(ms->fd, DRM_CLIENT_CAP_ATOMIC, 0); 1236 ms->atomic_modeset_capable = (ret == 0); 1237 1238 if (xf86ReturnOptValBool(ms->drmmode.Options, OPTION_ATOMIC, FALSE)) { 1239 ret = drmSetClientCap(ms->fd, DRM_CLIENT_CAP_ATOMIC, 1); 1240 ms->atomic_modeset = (ret == 0); 1241 } else { 1242 ms->atomic_modeset = FALSE; 1243 } 1244 1245 ms->kms_has_modifiers = FALSE; 1246 ret = drmGetCap(ms->fd, DRM_CAP_ADDFB2_MODIFIERS, &value); 1247 if (ret == 0 && value != 0) 1248 ms->kms_has_modifiers = TRUE; 1249 1250 if (drmmode_pre_init(pScrn, &ms->drmmode, pScrn->bitsPerPixel / 8) == FALSE) { 1251 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "KMS setup failed\n"); 1252 goto fail; 1253 } 1254 1255 /* 1256 * If the driver can do gamma correction, it should call xf86SetGamma() here. 1257 */ 1258 { 1259 Gamma zeros = { 0.0, 0.0, 0.0 }; 1260 1261 if (!xf86SetGamma(pScrn, zeros)) { 1262 return FALSE; 1263 } 1264 } 1265 1266 if (!(pScrn->is_gpu && connector_count == 0) && pScrn->modes == NULL) { 1267 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); 1268 return FALSE; 1269 } 1270 1271 pScrn->currentMode = pScrn->modes; 1272 1273 /* Set display resolution */ 1274 xf86SetDpi(pScrn, 0, 0); 1275 1276 /* Load the required sub modules */ 1277 if (!xf86LoadSubModule(pScrn, "fb")) { 1278 return FALSE; 1279 } 1280 1281 if (ms->drmmode.shadow_enable) { 1282 void *mod = xf86LoadSubModule(pScrn, "shadow"); 1283 1284 if (!mod) 1285 return FALSE; 1286 1287 ms->shadow.Setup = LoaderSymbolFromModule(mod, "shadowSetup"); 1288 ms->shadow.Add = LoaderSymbolFromModule(mod, "shadowAdd"); 1289 ms->shadow.Remove = LoaderSymbolFromModule(mod, "shadowRemove"); 1290 ms->shadow.Update32to24 = LoaderSymbolFromModule(mod, "shadowUpdate32to24"); 1291 ms->shadow.UpdatePacked = LoaderSymbolFromModule(mod, "shadowUpdatePacked"); 1292 } 1293 1294 return TRUE; 1295 fail: 1296 return FALSE; 1297 } 1298 1299 static void * 1300 msShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode, 1301 CARD32 *size, void *closure) 1302 { 1303 ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 1304 modesettingPtr ms = modesettingPTR(pScrn); 1305 int stride; 1306 1307 stride = (pScrn->displayWidth * ms->drmmode.kbpp) / 8; 1308 *size = stride; 1309 1310 return ((uint8_t *) ms->drmmode.front_bo.dumb->ptr + row * stride + offset); 1311 } 1312 1313 /* somewhat arbitrary tile size, in pixels */ 1314 #define TILE 16 1315 1316 static int 1317 msUpdateIntersect(modesettingPtr ms, shadowBufPtr pBuf, BoxPtr box, 1318 xRectangle *prect) 1319 { 1320 int i, dirty = 0, stride = pBuf->pPixmap->devKind, cpp = ms->drmmode.cpp; 1321 int width = (box->x2 - box->x1) * cpp; 1322 unsigned char *old, *new; 1323 1324 old = ms->drmmode.shadow_fb2; 1325 old += (box->y1 * stride) + (box->x1 * cpp); 1326 new = ms->drmmode.shadow_fb; 1327 new += (box->y1 * stride) + (box->x1 * cpp); 1328 1329 for (i = box->y2 - box->y1 - 1; i >= 0; i--) { 1330 unsigned char *o = old + i * stride, 1331 *n = new + i * stride; 1332 if (memcmp(o, n, width) != 0) { 1333 dirty = 1; 1334 memcpy(o, n, width); 1335 } 1336 } 1337 1338 if (dirty) { 1339 prect->x = box->x1; 1340 prect->y = box->y1; 1341 prect->width = box->x2 - box->x1; 1342 prect->height = box->y2 - box->y1; 1343 } 1344 1345 return dirty; 1346 } 1347 1348 static void 1349 msUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf) 1350 { 1351 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1352 modesettingPtr ms = modesettingPTR(pScrn); 1353 Bool use_3224 = ms->drmmode.force_24_32 && pScrn->bitsPerPixel == 32; 1354 1355 if (ms->drmmode.shadow_enable2 && ms->drmmode.shadow_fb2) do { 1356 RegionPtr damage = DamageRegion(pBuf->pDamage), tiles; 1357 BoxPtr extents = RegionExtents(damage); 1358 xRectangle *prect; 1359 int nrects; 1360 int i, j, tx1, tx2, ty1, ty2; 1361 1362 tx1 = extents->x1 / TILE; 1363 tx2 = (extents->x2 + TILE - 1) / TILE; 1364 ty1 = extents->y1 / TILE; 1365 ty2 = (extents->y2 + TILE - 1) / TILE; 1366 1367 nrects = (tx2 - tx1) * (ty2 - ty1); 1368 if (!(prect = calloc(nrects, sizeof(xRectangle)))) 1369 break; 1370 1371 nrects = 0; 1372 for (j = ty2 - 1; j >= ty1; j--) { 1373 for (i = tx2 - 1; i >= tx1; i--) { 1374 BoxRec box; 1375 1376 box.x1 = max(i * TILE, extents->x1); 1377 box.y1 = max(j * TILE, extents->y1); 1378 box.x2 = min((i+1) * TILE, extents->x2); 1379 box.y2 = min((j+1) * TILE, extents->y2); 1380 1381 if (RegionContainsRect(damage, &box) != rgnOUT) { 1382 if (msUpdateIntersect(ms, pBuf, &box, prect + nrects)) { 1383 nrects++; 1384 } 1385 } 1386 } 1387 } 1388 1389 tiles = RegionFromRects(nrects, prect, CT_NONE); 1390 RegionIntersect(damage, damage, tiles); 1391 RegionDestroy(tiles); 1392 free(prect); 1393 } while (0); 1394 1395 if (use_3224) 1396 ms->shadow.Update32to24(pScreen, pBuf); 1397 else 1398 ms->shadow.UpdatePacked(pScreen, pBuf); 1399 } 1400 1401 static Bool 1402 msEnableSharedPixmapFlipping(RRCrtcPtr crtc, PixmapPtr front, PixmapPtr back) 1403 { 1404 ScreenPtr screen = crtc->pScreen; 1405 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1406 modesettingPtr ms = modesettingPTR(scrn); 1407 EntityInfoPtr pEnt = ms->pEnt; 1408 xf86CrtcPtr xf86Crtc = crtc->devPrivate; 1409 1410 if (!xf86Crtc) 1411 return FALSE; 1412 1413 /* Not supported if we can't flip */ 1414 if (!ms->drmmode.pageflip) 1415 return FALSE; 1416 1417 /* Not currently supported with reverse PRIME */ 1418 if (ms->drmmode.reverse_prime_offload_mode) 1419 return FALSE; 1420 1421 #ifdef XSERVER_PLATFORM_BUS 1422 if (pEnt->location.type == BUS_PLATFORM) { 1423 char *syspath = 1424 xf86_platform_device_odev_attributes(pEnt->location.id.plat)-> 1425 syspath; 1426 1427 /* Not supported for devices using USB transport due to misbehaved 1428 * vblank events */ 1429 if (syspath && strstr(syspath, "usb")) 1430 return FALSE; 1431 1432 /* EVDI uses USB transport but is platform device, not usb. 1433 * Exclude it explicitly. */ 1434 if (syspath && strstr(syspath, "evdi")) 1435 return FALSE; 1436 } 1437 #endif 1438 1439 return drmmode_EnableSharedPixmapFlipping(xf86Crtc, &ms->drmmode, 1440 front, back); 1441 } 1442 1443 static void 1444 msDisableSharedPixmapFlipping(RRCrtcPtr crtc) 1445 { 1446 ScreenPtr screen = crtc->pScreen; 1447 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1448 modesettingPtr ms = modesettingPTR(scrn); 1449 xf86CrtcPtr xf86Crtc = crtc->devPrivate; 1450 1451 if (xf86Crtc) 1452 drmmode_DisableSharedPixmapFlipping(xf86Crtc, &ms->drmmode); 1453 } 1454 1455 static Bool 1456 msStartFlippingPixmapTracking(RRCrtcPtr crtc, DrawablePtr src, 1457 PixmapPtr secondary_dst1, PixmapPtr secondary_dst2, 1458 int x, int y, int dst_x, int dst_y, 1459 Rotation rotation) 1460 { 1461 ScreenPtr pScreen = src->pScreen; 1462 modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen)); 1463 1464 msPixmapPrivPtr ppriv1 = msGetPixmapPriv(&ms->drmmode, secondary_dst1->primary_pixmap), 1465 ppriv2 = msGetPixmapPriv(&ms->drmmode, secondary_dst2->primary_pixmap); 1466 1467 if (!PixmapStartDirtyTracking(src, secondary_dst1, x, y, 1468 dst_x, dst_y, rotation)) { 1469 return FALSE; 1470 } 1471 1472 if (!PixmapStartDirtyTracking(src, secondary_dst2, x, y, 1473 dst_x, dst_y, rotation)) { 1474 PixmapStopDirtyTracking(src, secondary_dst1); 1475 return FALSE; 1476 } 1477 1478 ppriv1->secondary_src = src; 1479 ppriv2->secondary_src = src; 1480 1481 ppriv1->dirty = ms_dirty_get_ent(pScreen, secondary_dst1); 1482 ppriv2->dirty = ms_dirty_get_ent(pScreen, secondary_dst2); 1483 1484 ppriv1->defer_dirty_update = TRUE; 1485 ppriv2->defer_dirty_update = TRUE; 1486 1487 return TRUE; 1488 } 1489 1490 static Bool 1491 msPresentSharedPixmap(PixmapPtr secondary_dst) 1492 { 1493 ScreenPtr pScreen = secondary_dst->primary_pixmap->drawable.pScreen; 1494 modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen)); 1495 1496 msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, secondary_dst->primary_pixmap); 1497 1498 RegionPtr region = DamageRegion(ppriv->dirty->damage); 1499 1500 if (RegionNotEmpty(region)) { 1501 redisplay_dirty(ppriv->secondary_src->pScreen, ppriv->dirty, NULL); 1502 DamageEmpty(ppriv->dirty->damage); 1503 1504 return TRUE; 1505 } 1506 1507 return FALSE; 1508 } 1509 1510 static Bool 1511 msStopFlippingPixmapTracking(DrawablePtr src, 1512 PixmapPtr secondary_dst1, PixmapPtr secondary_dst2) 1513 { 1514 ScreenPtr pScreen = src->pScreen; 1515 modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen)); 1516 1517 msPixmapPrivPtr ppriv1 = msGetPixmapPriv(&ms->drmmode, secondary_dst1->primary_pixmap), 1518 ppriv2 = msGetPixmapPriv(&ms->drmmode, secondary_dst2->primary_pixmap); 1519 1520 Bool ret = TRUE; 1521 1522 ret &= PixmapStopDirtyTracking(src, secondary_dst1); 1523 ret &= PixmapStopDirtyTracking(src, secondary_dst2); 1524 1525 if (ret) { 1526 ppriv1->secondary_src = NULL; 1527 ppriv2->secondary_src = NULL; 1528 1529 ppriv1->dirty = NULL; 1530 ppriv2->dirty = NULL; 1531 1532 ppriv1->defer_dirty_update = FALSE; 1533 ppriv2->defer_dirty_update = FALSE; 1534 } 1535 1536 return ret; 1537 } 1538 1539 static Bool 1540 CreateScreenResources(ScreenPtr pScreen) 1541 { 1542 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1543 modesettingPtr ms = modesettingPTR(pScrn); 1544 PixmapPtr rootPixmap; 1545 Bool ret; 1546 void *pixels = NULL; 1547 int err; 1548 1549 pScreen->CreateScreenResources = ms->createScreenResources; 1550 ret = pScreen->CreateScreenResources(pScreen); 1551 pScreen->CreateScreenResources = CreateScreenResources; 1552 1553 if (!drmmode_set_desired_modes(pScrn, &ms->drmmode, pScrn->is_gpu, FALSE)) 1554 return FALSE; 1555 1556 if (!drmmode_glamor_handle_new_screen_pixmap(&ms->drmmode)) 1557 return FALSE; 1558 1559 drmmode_uevent_init(pScrn, &ms->drmmode); 1560 1561 if (!ms->drmmode.sw_cursor) 1562 drmmode_map_cursor_bos(pScrn, &ms->drmmode); 1563 1564 if (!ms->drmmode.gbm) { 1565 pixels = drmmode_map_front_bo(&ms->drmmode); 1566 if (!pixels) 1567 return FALSE; 1568 } 1569 1570 rootPixmap = pScreen->GetScreenPixmap(pScreen); 1571 1572 if (ms->drmmode.shadow_enable) 1573 pixels = ms->drmmode.shadow_fb; 1574 1575 if (ms->drmmode.shadow_enable2) { 1576 ms->drmmode.shadow_fb2 = calloc(1, pScrn->displayWidth * pScrn->virtualY * ((pScrn->bitsPerPixel + 7) >> 3)); 1577 if (!ms->drmmode.shadow_fb2) 1578 ms->drmmode.shadow_enable2 = FALSE; 1579 } 1580 1581 if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, pixels)) 1582 FatalError("Couldn't adjust screen pixmap\n"); 1583 1584 if (ms->drmmode.shadow_enable) { 1585 if (!ms->shadow.Add(pScreen, rootPixmap, msUpdatePacked, msShadowWindow, 1586 0, 0)) 1587 return FALSE; 1588 } 1589 1590 err = drmModeDirtyFB(ms->fd, ms->drmmode.fb_id, NULL, 0); 1591 1592 if (err != -EINVAL && err != -ENOSYS) { 1593 ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, 1594 pScreen, rootPixmap); 1595 1596 if (ms->damage) { 1597 DamageRegister(&rootPixmap->drawable, ms->damage); 1598 ms->dirty_enabled = TRUE; 1599 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n"); 1600 } 1601 else { 1602 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1603 "Failed to create screen damage record\n"); 1604 return FALSE; 1605 } 1606 } 1607 1608 if (dixPrivateKeyRegistered(rrPrivKey)) { 1609 rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen); 1610 1611 pScrPriv->rrEnableSharedPixmapFlipping = msEnableSharedPixmapFlipping; 1612 pScrPriv->rrDisableSharedPixmapFlipping = msDisableSharedPixmapFlipping; 1613 1614 pScrPriv->rrStartFlippingPixmapTracking = msStartFlippingPixmapTracking; 1615 } 1616 1617 if (ms->vrr_support && 1618 !dixRegisterPrivateKey(&ms->drmmode.vrrPrivateKeyRec, 1619 PRIVATE_WINDOW, 1620 sizeof(struct ms_vrr_priv))) 1621 return FALSE; 1622 1623 return ret; 1624 } 1625 1626 static Bool 1627 msSharePixmapBacking(PixmapPtr ppix, ScreenPtr secondary, void **handle) 1628 { 1629 #ifdef GLAMOR_HAS_GBM 1630 modesettingPtr ms = 1631 modesettingPTR(xf86ScreenToScrn(ppix->drawable.pScreen)); 1632 int ret; 1633 CARD16 stride; 1634 CARD32 size; 1635 ret = ms->glamor.shareable_fd_from_pixmap(ppix->drawable.pScreen, ppix, 1636 &stride, &size); 1637 if (ret == -1) 1638 return FALSE; 1639 1640 *handle = (void *)(long)(ret); 1641 return TRUE; 1642 #endif 1643 return FALSE; 1644 } 1645 1646 static Bool 1647 msSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle) 1648 { 1649 #ifdef GLAMOR_HAS_GBM 1650 ScreenPtr screen = ppix->drawable.pScreen; 1651 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1652 modesettingPtr ms = modesettingPTR(scrn); 1653 Bool ret; 1654 int ihandle = (int) (long) fd_handle; 1655 1656 if (ihandle == -1) 1657 if (!ms->drmmode.reverse_prime_offload_mode) 1658 return drmmode_SetSlaveBO(ppix, &ms->drmmode, ihandle, 0, 0); 1659 1660 if (ms->drmmode.reverse_prime_offload_mode) { 1661 ret = ms->glamor.back_pixmap_from_fd(ppix, ihandle, 1662 ppix->drawable.width, 1663 ppix->drawable.height, 1664 ppix->devKind, 1665 ppix->drawable.depth, 1666 ppix->drawable.bitsPerPixel); 1667 } else { 1668 int size = ppix->devKind * ppix->drawable.height; 1669 ret = drmmode_SetSlaveBO(ppix, &ms->drmmode, ihandle, ppix->devKind, size); 1670 } 1671 if (ret == FALSE) 1672 return ret; 1673 1674 return TRUE; 1675 #else 1676 return FALSE; 1677 #endif 1678 } 1679 1680 static Bool 1681 msRequestSharedPixmapNotifyDamage(PixmapPtr ppix) 1682 { 1683 ScreenPtr screen = ppix->drawable.pScreen; 1684 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1685 modesettingPtr ms = modesettingPTR(scrn); 1686 1687 msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix->primary_pixmap); 1688 1689 ppriv->notify_on_damage = TRUE; 1690 1691 return TRUE; 1692 } 1693 1694 static Bool 1695 msSharedPixmapNotifyDamage(PixmapPtr ppix) 1696 { 1697 Bool ret = FALSE; 1698 int c; 1699 1700 ScreenPtr screen = ppix->drawable.pScreen; 1701 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1702 modesettingPtr ms = modesettingPTR(scrn); 1703 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1704 1705 msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix); 1706 1707 if (!ppriv->wait_for_damage) 1708 return ret; 1709 ppriv->wait_for_damage = FALSE; 1710 1711 for (c = 0; c < xf86_config->num_crtc; c++) { 1712 xf86CrtcPtr crtc = xf86_config->crtc[c]; 1713 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1714 1715 if (!drmmode_crtc) 1716 continue; 1717 if (!(drmmode_crtc->prime_pixmap && drmmode_crtc->prime_pixmap_back)) 1718 continue; 1719 1720 // Received damage on primary screen pixmap, schedule present on vblank 1721 ret |= drmmode_SharedPixmapPresentOnVBlank(ppix, crtc, &ms->drmmode); 1722 } 1723 1724 return ret; 1725 } 1726 1727 static Bool 1728 SetMaster(ScrnInfoPtr pScrn) 1729 { 1730 modesettingPtr ms = modesettingPTR(pScrn); 1731 int ret; 1732 1733 #ifdef XF86_PDEV_SERVER_FD 1734 if (ms->pEnt->location.type == BUS_PLATFORM && 1735 (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)) 1736 return TRUE; 1737 #endif 1738 1739 if (ms->fd_passed) 1740 return TRUE; 1741 1742 ret = drmSetMaster(ms->fd); 1743 if (ret) 1744 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "drmSetMaster failed: %s\n", 1745 strerror(errno)); 1746 1747 return ret == 0; 1748 } 1749 1750 /* When the root window is created, initialize the screen contents from 1751 * console if -background none was specified on the command line 1752 */ 1753 static Bool 1754 CreateWindow_oneshot(WindowPtr pWin) 1755 { 1756 ScreenPtr pScreen = pWin->drawable.pScreen; 1757 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1758 modesettingPtr ms = modesettingPTR(pScrn); 1759 Bool ret; 1760 1761 pScreen->CreateWindow = ms->CreateWindow; 1762 ret = pScreen->CreateWindow(pWin); 1763 1764 if (ret) 1765 drmmode_copy_fb(pScrn, &ms->drmmode); 1766 return ret; 1767 } 1768 1769 static Bool 1770 ScreenInit(ScreenPtr pScreen, int argc, char **argv) 1771 { 1772 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1773 modesettingPtr ms = modesettingPTR(pScrn); 1774 VisualPtr visual; 1775 1776 pScrn->pScreen = pScreen; 1777 1778 if (!SetMaster(pScrn)) 1779 return FALSE; 1780 1781 #ifdef GLAMOR_HAS_GBM 1782 if (ms->drmmode.glamor) 1783 ms->drmmode.gbm = ms->glamor.egl_get_gbm_device(pScreen); 1784 #endif 1785 1786 /* HW dependent - FIXME */ 1787 pScrn->displayWidth = pScrn->virtualX; 1788 if (!drmmode_create_initial_bos(pScrn, &ms->drmmode)) 1789 return FALSE; 1790 1791 if (ms->drmmode.shadow_enable) { 1792 ms->drmmode.shadow_fb = 1793 calloc(1, 1794 pScrn->displayWidth * pScrn->virtualY * 1795 ((pScrn->bitsPerPixel + 7) >> 3)); 1796 if (!ms->drmmode.shadow_fb) 1797 ms->drmmode.shadow_enable = FALSE; 1798 } 1799 1800 miClearVisualTypes(); 1801 1802 if (!miSetVisualTypes(pScrn->depth, 1803 miGetDefaultVisualMask(pScrn->depth), 1804 pScrn->rgbBits, pScrn->defaultVisual)) 1805 return FALSE; 1806 1807 if (!miSetPixmapDepths()) 1808 return FALSE; 1809 1810 if (!dixRegisterScreenSpecificPrivateKey 1811 (pScreen, &ms->drmmode.pixmapPrivateKeyRec, PRIVATE_PIXMAP, 1812 sizeof(msPixmapPrivRec))) { 1813 return FALSE; 1814 } 1815 1816 pScrn->memPhysBase = 0; 1817 pScrn->fbOffset = 0; 1818 1819 if (!fbScreenInit(pScreen, NULL, 1820 pScrn->virtualX, pScrn->virtualY, 1821 pScrn->xDpi, pScrn->yDpi, 1822 pScrn->displayWidth, pScrn->bitsPerPixel)) 1823 return FALSE; 1824 1825 if (pScrn->bitsPerPixel > 8) { 1826 /* Fixup RGB ordering */ 1827 visual = pScreen->visuals + pScreen->numVisuals; 1828 while (--visual >= pScreen->visuals) { 1829 if ((visual->class | DynamicClass) == DirectColor) { 1830 visual->offsetRed = pScrn->offset.red; 1831 visual->offsetGreen = pScrn->offset.green; 1832 visual->offsetBlue = pScrn->offset.blue; 1833 visual->redMask = pScrn->mask.red; 1834 visual->greenMask = pScrn->mask.green; 1835 visual->blueMask = pScrn->mask.blue; 1836 } 1837 } 1838 } 1839 1840 fbPictureInit(pScreen, NULL, 0); 1841 1842 if (drmmode_init(pScrn, &ms->drmmode) == FALSE) { 1843 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1844 "Failed to initialize glamor at ScreenInit() time.\n"); 1845 return FALSE; 1846 } 1847 1848 if (ms->drmmode.shadow_enable && !ms->shadow.Setup(pScreen)) { 1849 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "shadow fb init failed\n"); 1850 return FALSE; 1851 } 1852 1853 ms->createScreenResources = pScreen->CreateScreenResources; 1854 pScreen->CreateScreenResources = CreateScreenResources; 1855 1856 xf86SetBlackWhitePixels(pScreen); 1857 1858 xf86SetBackingStore(pScreen); 1859 xf86SetSilkenMouse(pScreen); 1860 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1861 1862 /* If pageflip is enabled hook the screen's cursor-sprite (swcursor) funcs. 1863 * So that we can disable page-flipping on fallback to a swcursor. */ 1864 if (ms->drmmode.pageflip) { 1865 miPointerScreenPtr PointPriv = 1866 dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); 1867 1868 if (!dixRegisterScreenPrivateKey(&ms->drmmode.spritePrivateKeyRec, 1869 pScreen, PRIVATE_DEVICE, 1870 sizeof(msSpritePrivRec))) 1871 return FALSE; 1872 1873 ms->SpriteFuncs = PointPriv->spriteFuncs; 1874 PointPriv->spriteFuncs = &drmmode_sprite_funcs; 1875 } 1876 1877 /* Need to extend HWcursor support to handle mask interleave */ 1878 if (!ms->drmmode.sw_cursor) 1879 xf86_cursors_init(pScreen, ms->cursor_width, ms->cursor_height, 1880 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | 1881 HARDWARE_CURSOR_UPDATE_UNHIDDEN | 1882 HARDWARE_CURSOR_ARGB); 1883 1884 /* Must force it before EnterVT, so we are in control of VT and 1885 * later memory should be bound when allocating, e.g rotate_mem */ 1886 pScrn->vtSema = TRUE; 1887 1888 if (serverGeneration == 1 && bgNoneRoot && ms->drmmode.glamor) { 1889 ms->CreateWindow = pScreen->CreateWindow; 1890 pScreen->CreateWindow = CreateWindow_oneshot; 1891 } 1892 1893 pScreen->SaveScreen = xf86SaveScreen; 1894 ms->CloseScreen = pScreen->CloseScreen; 1895 pScreen->CloseScreen = CloseScreen; 1896 1897 ms->BlockHandler = pScreen->BlockHandler; 1898 pScreen->BlockHandler = msBlockHandler_oneshot; 1899 1900 pScreen->SharePixmapBacking = msSharePixmapBacking; 1901 pScreen->SetSharedPixmapBacking = msSetSharedPixmapBacking; 1902 pScreen->StartPixmapTracking = PixmapStartDirtyTracking; 1903 pScreen->StopPixmapTracking = PixmapStopDirtyTracking; 1904 1905 pScreen->SharedPixmapNotifyDamage = msSharedPixmapNotifyDamage; 1906 pScreen->RequestSharedPixmapNotifyDamage = 1907 msRequestSharedPixmapNotifyDamage; 1908 1909 pScreen->PresentSharedPixmap = msPresentSharedPixmap; 1910 pScreen->StopFlippingPixmapTracking = msStopFlippingPixmapTracking; 1911 1912 if (!xf86CrtcScreenInit(pScreen)) 1913 return FALSE; 1914 1915 if (!drmmode_setup_colormap(pScreen, pScrn)) 1916 return FALSE; 1917 1918 if (ms->atomic_modeset) 1919 xf86DPMSInit(pScreen, drmmode_set_dpms, 0); 1920 else 1921 xf86DPMSInit(pScreen, xf86DPMSSet, 0); 1922 1923 #ifdef GLAMOR_HAS_GBM 1924 if (ms->drmmode.glamor) { 1925 XF86VideoAdaptorPtr glamor_adaptor; 1926 1927 glamor_adaptor = ms->glamor.xv_init(pScreen, 16); 1928 if (glamor_adaptor != NULL) 1929 xf86XVScreenInit(pScreen, &glamor_adaptor, 1); 1930 else 1931 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1932 "Failed to initialize XV support.\n"); 1933 } 1934 #endif 1935 1936 if (serverGeneration == 1) 1937 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1938 1939 if (!ms_vblank_screen_init(pScreen)) { 1940 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1941 "Failed to initialize vblank support.\n"); 1942 return FALSE; 1943 } 1944 1945 #ifdef GLAMOR_HAS_GBM 1946 if (ms->drmmode.glamor) { 1947 if (!(ms->drmmode.dri2_enable = ms_dri2_screen_init(pScreen))) { 1948 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1949 "Failed to initialize the DRI2 extension.\n"); 1950 } 1951 1952 /* enable reverse prime if we are a GPU screen, and accelerated, and not 1953 * i915, evdi or udl. i915 is happy scanning out from sysmem. 1954 * evdi and udl are virtual drivers scanning out from sysmem 1955 * backed dumb buffers. 1956 */ 1957 if (pScreen->isGPU) { 1958 drmVersionPtr version; 1959 1960 /* enable if we are an accelerated GPU screen */ 1961 ms->drmmode.reverse_prime_offload_mode = TRUE; 1962 1963 if ((version = drmGetVersion(ms->drmmode.fd))) { 1964 if (!strncmp("i915", version->name, version->name_len)) { 1965 ms->drmmode.reverse_prime_offload_mode = FALSE; 1966 } 1967 if (!strncmp("evdi", version->name, version->name_len)) { 1968 ms->drmmode.reverse_prime_offload_mode = FALSE; 1969 } 1970 if (!strncmp("udl", version->name, version->name_len)) { 1971 ms->drmmode.reverse_prime_offload_mode = FALSE; 1972 } 1973 if (!ms->drmmode.reverse_prime_offload_mode) { 1974 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1975 "Disable reverse prime offload mode for %s.\n", version->name); 1976 } 1977 drmFreeVersion(version); 1978 } 1979 } 1980 } 1981 #endif 1982 if (!(ms->drmmode.present_enable = ms_present_screen_init(pScreen))) { 1983 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1984 "Failed to initialize the Present extension.\n"); 1985 } 1986 1987 1988 pScrn->vtSema = TRUE; 1989 1990 if (ms->vrr_support) { 1991 if (!property_vectors_wrapped) { 1992 saved_change_property = ProcVector[X_ChangeProperty]; 1993 ProcVector[X_ChangeProperty] = ms_change_property; 1994 saved_delete_property = ProcVector[X_DeleteProperty]; 1995 ProcVector[X_DeleteProperty] = ms_delete_property; 1996 property_vectors_wrapped = TRUE; 1997 } 1998 vrr_atom = MakeAtom("_VARIABLE_REFRESH", 1999 strlen("_VARIABLE_REFRESH"), TRUE); 2000 } 2001 2002 return TRUE; 2003 } 2004 2005 static void 2006 AdjustFrame(ScrnInfoPtr pScrn, int x, int y) 2007 { 2008 modesettingPtr ms = modesettingPTR(pScrn); 2009 2010 drmmode_adjust_frame(pScrn, &ms->drmmode, x, y); 2011 } 2012 2013 static void 2014 FreeScreen(ScrnInfoPtr pScrn) 2015 { 2016 FreeRec(pScrn); 2017 } 2018 2019 static void 2020 LeaveVT(ScrnInfoPtr pScrn) 2021 { 2022 modesettingPtr ms = modesettingPTR(pScrn); 2023 2024 xf86_hide_cursors(pScrn); 2025 2026 pScrn->vtSema = FALSE; 2027 2028 #ifdef XF86_PDEV_SERVER_FD 2029 if (ms->pEnt->location.type == BUS_PLATFORM && 2030 (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)) 2031 return; 2032 #endif 2033 2034 if (!ms->fd_passed) 2035 drmDropMaster(ms->fd); 2036 } 2037 2038 /* 2039 * This gets called when gaining control of the VT, and from ScreenInit(). 2040 */ 2041 static Bool 2042 EnterVT(ScrnInfoPtr pScrn) 2043 { 2044 modesettingPtr ms = modesettingPTR(pScrn); 2045 2046 pScrn->vtSema = TRUE; 2047 2048 SetMaster(pScrn); 2049 2050 drmmode_update_kms_state(&ms->drmmode); 2051 2052 /* allow not all modes to be set successfully since some events might have 2053 * happened while not being master that could prevent the previous 2054 * configuration from being re-applied. 2055 */ 2056 if (!drmmode_set_desired_modes(pScrn, &ms->drmmode, TRUE, TRUE)) { 2057 xf86DisableUnusedFunctions(pScrn); 2058 2059 /* TODO: check that at least one screen is on, to allow the user to fix 2060 * their setup if all modeset failed... 2061 */ 2062 2063 /* Tell the desktop environment that something changed, so that they 2064 * can hopefully correct the situation 2065 */ 2066 RRSetChanged(xf86ScrnToScreen(pScrn)); 2067 RRTellChanged(xf86ScrnToScreen(pScrn)); 2068 } 2069 2070 return TRUE; 2071 } 2072 2073 static Bool 2074 SwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode) 2075 { 2076 return xf86SetSingleMode(pScrn, mode, RR_Rotate_0); 2077 } 2078 2079 static Bool 2080 CloseScreen(ScreenPtr pScreen) 2081 { 2082 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2083 modesettingPtr ms = modesettingPTR(pScrn); 2084 modesettingEntPtr ms_ent = ms_ent_priv(pScrn); 2085 2086 /* Clear mask of assigned crtc's in this generation */ 2087 ms_ent->assigned_crtcs = 0; 2088 2089 #ifdef GLAMOR_HAS_GBM 2090 if (ms->drmmode.dri2_enable) { 2091 ms_dri2_close_screen(pScreen); 2092 } 2093 #endif 2094 2095 ms_vblank_close_screen(pScreen); 2096 2097 if (ms->damage) { 2098 DamageUnregister(ms->damage); 2099 DamageDestroy(ms->damage); 2100 ms->damage = NULL; 2101 } 2102 2103 if (ms->drmmode.shadow_enable) { 2104 ms->shadow.Remove(pScreen, pScreen->GetScreenPixmap(pScreen)); 2105 free(ms->drmmode.shadow_fb); 2106 ms->drmmode.shadow_fb = NULL; 2107 free(ms->drmmode.shadow_fb2); 2108 ms->drmmode.shadow_fb2 = NULL; 2109 } 2110 2111 drmmode_uevent_fini(pScrn, &ms->drmmode); 2112 2113 drmmode_free_bos(pScrn, &ms->drmmode); 2114 2115 if (ms->drmmode.pageflip) { 2116 miPointerScreenPtr PointPriv = 2117 dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); 2118 2119 if (PointPriv->spriteFuncs == &drmmode_sprite_funcs) 2120 PointPriv->spriteFuncs = ms->SpriteFuncs; 2121 } 2122 2123 if (pScrn->vtSema) { 2124 LeaveVT(pScrn); 2125 } 2126 2127 pScreen->CreateScreenResources = ms->createScreenResources; 2128 pScreen->BlockHandler = ms->BlockHandler; 2129 2130 pScrn->vtSema = FALSE; 2131 pScreen->CloseScreen = ms->CloseScreen; 2132 return (*pScreen->CloseScreen) (pScreen); 2133 } 2134 2135 static ModeStatus 2136 ValidMode(ScrnInfoPtr arg, DisplayModePtr mode, Bool verbose, int flags) 2137 { 2138 return MODE_OK; 2139 }