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 (at) tungstengraphics.com> 29 * Rewrite: Dave Airlie <airlied (at) redhat.com> 30 * Additional contributors: 31 * Aaron Plattner <aplattner (at) 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 void 519 rotate_clip(PixmapPtr pixmap, BoxPtr rect, drmModeClip *clip, Rotation rotation) 520 { 521 int w = pixmap->drawable.width; 522 int h = pixmap->drawable.height; 523 524 if (rotation == RR_Rotate_90) { 525 /* Rotate 90 degrees counter clockwise */ 526 clip->x1 = rect->y1; 527 clip->x2 = rect->y2; 528 clip->y1 = w - rect->x2; 529 clip->y2 = w - rect->x1; 530 } else if (rotation == RR_Rotate_180) { 531 /* Rotate 180 degrees */ 532 clip->x1 = w - rect->x2; 533 clip->x2 = w - rect->x1; 534 clip->y1 = h - rect->y2; 535 clip->y2 = h - rect->y1; 536 } else if (rotation == RR_Rotate_270) { 537 /* Rotate 90 degrees clockwise */ 538 clip->x1 = h - rect->y2; 539 clip->x2 = h - rect->y1; 540 clip->y1 = rect->x1; 541 clip->y2 = rect->x2; 542 } else { 543 clip->x1 = rect->x1; 544 clip->x2 = rect->x2; 545 clip->y1 = rect->y1; 546 clip->y2 = rect->y2; 547 } 548 } 549 550 static int 551 dispatch_dirty_region(ScrnInfoPtr scrn, xf86CrtcPtr crtc, 552 PixmapPtr pixmap, DamagePtr damage, int fb_id) 553 { 554 modesettingPtr ms = modesettingPTR(scrn); 555 RegionPtr dirty = DamageRegion(damage); 556 unsigned num_cliprects = REGION_NUM_RECTS(dirty); 557 int ret = 0; 558 559 if (num_cliprects) { 560 drmModeClip *clip = xallocarray(num_cliprects, sizeof(drmModeClip)); 561 BoxPtr rect = REGION_RECTS(dirty); 562 int i; 563 564 if (!clip) 565 return -ENOMEM; 566 567 /* Rotate and copy rects into clips */ 568 for (i = 0; i < num_cliprects; i++, rect++) 569 rotate_clip(pixmap, rect, &clip[i], crtc->rotation); 570 571 /* TODO query connector property to see if this is needed */ 572 ret = drmModeDirtyFB(ms->fd, fb_id, clip, num_cliprects); 573 574 /* if we're swamping it with work, try one at a time */ 575 if (ret == -EINVAL) { 576 for (i = 0; i < num_cliprects; i++) { 577 if ((ret = drmModeDirtyFB(ms->fd, fb_id, &clip[i], 1)) < 0) 578 break; 579 } 580 } 581 582 free(clip); 583 DamageEmpty(damage); 584 } 585 return ret; 586 } 587 588 static void 589 dispatch_dirty(ScreenPtr pScreen) 590 { 591 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 592 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 593 modesettingPtr ms = modesettingPTR(scrn); 594 PixmapPtr pixmap = pScreen->GetScreenPixmap(pScreen); 595 uint32_t fb_id; 596 int ret, c, x, y ; 597 598 for (c = 0; c < xf86_config->num_crtc; c++) { 599 xf86CrtcPtr crtc = xf86_config->crtc[c]; 600 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 601 602 if (!drmmode_crtc) 603 continue; 604 605 drmmode_crtc_get_fb_id(crtc, &fb_id, &x, &y); 606 607 ret = dispatch_dirty_region(scrn, crtc, pixmap, ms->damage, fb_id); 608 if (ret == -EINVAL || ret == -ENOSYS) { 609 ms->dirty_enabled = FALSE; 610 DamageUnregister(ms->damage); 611 DamageDestroy(ms->damage); 612 ms->damage = NULL; 613 xf86DrvMsg(scrn->scrnIndex, X_INFO, 614 "Disabling kernel dirty updates, not required.\n"); 615 return; 616 } 617 } 618 } 619 620 static void 621 dispatch_dirty_pixmap(ScrnInfoPtr scrn, xf86CrtcPtr crtc, PixmapPtr ppix) 622 { 623 modesettingPtr ms = modesettingPTR(scrn); 624 msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix); 625 DamagePtr damage = ppriv->secondary_damage; 626 int fb_id = ppriv->fb_id; 627 628 dispatch_dirty_region(scrn, crtc, ppix, damage, fb_id); 629 } 630 631 static void 632 dispatch_secondary_dirty(ScreenPtr pScreen) 633 { 634 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 635 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 636 int c; 637 638 for (c = 0; c < xf86_config->num_crtc; c++) { 639 xf86CrtcPtr crtc = xf86_config->crtc[c]; 640 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 641 642 if (!drmmode_crtc) 643 continue; 644 645 if (drmmode_crtc->prime_pixmap) 646 dispatch_dirty_pixmap(scrn, crtc, drmmode_crtc->prime_pixmap); 647 if (drmmode_crtc->prime_pixmap_back) 648 dispatch_dirty_pixmap(scrn, crtc, drmmode_crtc->prime_pixmap_back); 649 } 650 } 651 652 static void 653 redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty, int *timeout) 654 { 655 RegionRec pixregion; 656 657 PixmapRegionInit(&pixregion, dirty->secondary_dst); 658 DamageRegionAppend(&dirty->secondary_dst->drawable, &pixregion); 659 PixmapSyncDirtyHelper(dirty); 660 661 if (!screen->isGPU) { 662 #ifdef GLAMOR_HAS_GBM 663 modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(screen)); 664 /* 665 * When copying from the primary framebuffer to the shared pixmap, 666 * we must ensure the copy is complete before the secondary starts a 667 * copy to its own framebuffer (some secondarys scanout directly from 668 * the shared pixmap, but not all). 669 */ 670 if (ms->drmmode.glamor) 671 ms->glamor.finish(screen); 672 #endif 673 /* Ensure the secondary processes the damage immediately */ 674 if (timeout) 675 *timeout = 0; 676 } 677 678 DamageRegionProcessPending(&dirty->secondary_dst->drawable); 679 RegionUninit(&pixregion); 680 } 681 682 static void 683 ms_dirty_update(ScreenPtr screen, int *timeout) 684 { 685 modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(screen)); 686 687 RegionPtr region; 688 PixmapDirtyUpdatePtr ent; 689 690 if (xorg_list_is_empty(&screen->pixmap_dirty_list)) 691 return; 692 693 xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) { 694 region = DamageRegion(ent->damage); 695 if (RegionNotEmpty(region)) { 696 if (!screen->isGPU) { 697 msPixmapPrivPtr ppriv = 698 msGetPixmapPriv(&ms->drmmode, ent->secondary_dst->primary_pixmap); 699 700 if (ppriv->notify_on_damage) { 701 ppriv->notify_on_damage = FALSE; 702 703 ent->secondary_dst->drawable.pScreen-> 704 SharedPixmapNotifyDamage(ent->secondary_dst); 705 } 706 707 /* Requested manual updating */ 708 if (ppriv->defer_dirty_update) 709 continue; 710 } 711 712 redisplay_dirty(screen, ent, timeout); 713 DamageEmpty(ent->damage); 714 } 715 } 716 } 717 718 static PixmapDirtyUpdatePtr 719 ms_dirty_get_ent(ScreenPtr screen, PixmapPtr secondary_dst) 720 { 721 PixmapDirtyUpdatePtr ent; 722 723 if (xorg_list_is_empty(&screen->pixmap_dirty_list)) 724 return NULL; 725 726 xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) { 727 if (ent->secondary_dst == secondary_dst) 728 return ent; 729 } 730 731 return NULL; 732 } 733 734 static void 735 msBlockHandler(ScreenPtr pScreen, void *timeout) 736 { 737 modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen)); 738 739 pScreen->BlockHandler = ms->BlockHandler; 740 pScreen->BlockHandler(pScreen, timeout); 741 ms->BlockHandler = pScreen->BlockHandler; 742 pScreen->BlockHandler = msBlockHandler; 743 if (pScreen->isGPU && !ms->drmmode.reverse_prime_offload_mode) 744 dispatch_secondary_dirty(pScreen); 745 else if (ms->dirty_enabled) 746 dispatch_dirty(pScreen); 747 748 ms_dirty_update(pScreen, timeout); 749 } 750 751 static void 752 msBlockHandler_oneshot(ScreenPtr pScreen, void *pTimeout) 753 { 754 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 755 modesettingPtr ms = modesettingPTR(pScrn); 756 757 msBlockHandler(pScreen, pTimeout); 758 759 drmmode_set_desired_modes(pScrn, &ms->drmmode, TRUE, FALSE); 760 } 761 762 Bool 763 ms_window_has_variable_refresh(modesettingPtr ms, WindowPtr win) { 764 struct ms_vrr_priv *priv = dixLookupPrivate(&win->devPrivates, &ms->drmmode.vrrPrivateKeyRec); 765 766 return priv->variable_refresh; 767 } 768 769 static void 770 ms_vrr_property_update(WindowPtr window, Bool variable_refresh) 771 { 772 ScrnInfoPtr scrn = xf86ScreenToScrn(window->drawable.pScreen); 773 modesettingPtr ms = modesettingPTR(scrn); 774 775 struct ms_vrr_priv *priv = dixLookupPrivate(&window->devPrivates, 776 &ms->drmmode.vrrPrivateKeyRec); 777 priv->variable_refresh = variable_refresh; 778 779 if (ms->flip_window == window && ms->drmmode.present_flipping) 780 ms_present_set_screen_vrr(scrn, variable_refresh); 781 } 782 783 /* Wrapper for xserver/dix/property.c:ProcChangeProperty */ 784 static int 785 ms_change_property(ClientPtr client) 786 { 787 WindowPtr window = NULL; 788 int ret = 0; 789 790 REQUEST(xChangePropertyReq); 791 792 client->requestVector[X_ChangeProperty] = saved_change_property; 793 ret = saved_change_property(client); 794 795 if (restore_property_vector) 796 return ret; 797 798 client->requestVector[X_ChangeProperty] = ms_change_property; 799 800 if (ret != Success) 801 return ret; 802 803 ret = dixLookupWindow(&window, stuff->window, client, DixSetPropAccess); 804 if (ret != Success) 805 return ret; 806 807 // Checking for the VRR property change on the window 808 if (stuff->property == vrr_atom && 809 xf86ScreenToScrn(window->drawable.pScreen)->PreInit == PreInit && 810 stuff->format == 32 && stuff->nUnits == 1) { 811 uint32_t *value = (uint32_t *)(stuff + 1); 812 ms_vrr_property_update(window, *value != 0); 813 } 814 815 return ret; 816 } 817 818 /* Wrapper for xserver/dix/property.c:ProcDeleteProperty */ 819 static int 820 ms_delete_property(ClientPtr client) 821 { 822 WindowPtr window; 823 int ret; 824 825 REQUEST(xDeletePropertyReq); 826 827 client->requestVector[X_DeleteProperty] = saved_delete_property; 828 ret = saved_delete_property(client); 829 830 if (restore_property_vector) 831 return ret; 832 833 client->requestVector[X_DeleteProperty] = ms_delete_property; 834 835 if (ret != Success) 836 return ret; 837 838 ret = dixLookupWindow(&window, stuff->window, client, DixSetPropAccess); 839 if (ret != Success) 840 return ret; 841 842 if (stuff->property == vrr_atom && 843 xf86ScreenToScrn(window->drawable.pScreen)->PreInit == PreInit) 844 ms_vrr_property_update(window, FALSE); 845 846 return ret; 847 } 848 849 static void 850 ms_unwrap_property_requests(ScrnInfoPtr scrn) 851 { 852 int i; 853 854 if (!property_vectors_wrapped) 855 return; 856 857 if (ProcVector[X_ChangeProperty] == ms_change_property) 858 ProcVector[X_ChangeProperty] = saved_change_property; 859 else 860 restore_property_vector = TRUE; 861 862 if (ProcVector[X_DeleteProperty] == ms_delete_property) 863 ProcVector[X_DeleteProperty] = saved_delete_property; 864 else 865 restore_property_vector = TRUE; 866 867 for (i = 0; i < currentMaxClients; i++) { 868 if (clients[i]->requestVector[X_ChangeProperty] == ms_change_property) { 869 clients[i]->requestVector[X_ChangeProperty] = saved_change_property; 870 } else { 871 restore_property_vector = TRUE; 872 } 873 874 if (clients[i]->requestVector[X_DeleteProperty] == ms_delete_property) { 875 clients[i]->requestVector[X_DeleteProperty] = saved_delete_property; 876 } else { 877 restore_property_vector = TRUE; 878 } 879 } 880 881 if (restore_property_vector) { 882 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 883 "Couldn't unwrap some window property request vectors\n"); 884 } 885 886 property_vectors_wrapped = FALSE; 887 } 888 889 static void 890 FreeRec(ScrnInfoPtr pScrn) 891 { 892 modesettingPtr ms; 893 894 if (!pScrn) 895 return; 896 897 ms = modesettingPTR(pScrn); 898 if (!ms) 899 return; 900 901 if (ms->fd > 0) { 902 modesettingEntPtr ms_ent; 903 int ret; 904 905 ms_ent = ms_ent_priv(pScrn); 906 ms_ent->fd_ref--; 907 if (!ms_ent->fd_ref) { 908 ms_unwrap_property_requests(pScrn); 909 if (ms->pEnt->location.type == BUS_PCI) 910 ret = drmClose(ms->fd); 911 else 912 #ifdef XF86_PDEV_SERVER_FD 913 if (!(ms->pEnt->location.type == BUS_PLATFORM && 914 (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD))) 915 #endif 916 ret = close(ms->fd); 917 (void) ret; 918 ms_ent->fd = 0; 919 } 920 } 921 pScrn->driverPrivate = NULL; 922 free(ms->drmmode.Options); 923 free(ms); 924 925 } 926 927 #ifdef GLAMOR_HAS_GBM 928 929 static Bool 930 load_glamor(ScrnInfoPtr pScrn) 931 { 932 void *mod = xf86LoadSubModule(pScrn, GLAMOR_EGL_MODULE_NAME); 933 modesettingPtr ms = modesettingPTR(pScrn); 934 935 if (!mod) 936 return FALSE; 937 938 ms->glamor.back_pixmap_from_fd = LoaderSymbolFromModule(mod, "glamor_back_pixmap_from_fd"); 939 ms->glamor.block_handler = LoaderSymbolFromModule(mod, "glamor_block_handler"); 940 ms->glamor.clear_pixmap = LoaderSymbolFromModule(mod, "glamor_clear_pixmap"); 941 ms->glamor.egl_create_textured_pixmap = LoaderSymbolFromModule(mod, "glamor_egl_create_textured_pixmap"); 942 ms->glamor.egl_create_textured_pixmap_from_gbm_bo = LoaderSymbolFromModule(mod, "glamor_egl_create_textured_pixmap_from_gbm_bo"); 943 ms->glamor.egl_exchange_buffers = LoaderSymbolFromModule(mod, "glamor_egl_exchange_buffers"); 944 ms->glamor.egl_get_gbm_device = LoaderSymbolFromModule(mod, "glamor_egl_get_gbm_device"); 945 ms->glamor.egl_init = LoaderSymbolFromModule(mod, "glamor_egl_init"); 946 ms->glamor.finish = LoaderSymbolFromModule(mod, "glamor_finish"); 947 ms->glamor.gbm_bo_from_pixmap = LoaderSymbolFromModule(mod, "glamor_gbm_bo_from_pixmap"); 948 ms->glamor.init = LoaderSymbolFromModule(mod, "glamor_init"); 949 ms->glamor.name_from_pixmap = LoaderSymbolFromModule(mod, "glamor_name_from_pixmap"); 950 ms->glamor.set_drawable_modifiers_func = LoaderSymbolFromModule(mod, "glamor_set_drawable_modifiers_func"); 951 ms->glamor.shareable_fd_from_pixmap = LoaderSymbolFromModule(mod, "glamor_shareable_fd_from_pixmap"); 952 ms->glamor.supports_pixmap_import_export = LoaderSymbolFromModule(mod, "glamor_supports_pixmap_import_export"); 953 ms->glamor.xv_init = LoaderSymbolFromModule(mod, "glamor_xv_init"); 954 ms->glamor.egl_get_driver_name = LoaderSymbolFromModule(mod, "glamor_egl_get_driver_name"); 955 956 return TRUE; 957 } 958 959 #endif 960 961 static void 962 try_enable_glamor(ScrnInfoPtr pScrn) 963 { 964 modesettingPtr ms = modesettingPTR(pScrn); 965 const char *accel_method_str = xf86GetOptValString(ms->drmmode.Options, 966 OPTION_ACCEL_METHOD); 967 Bool do_glamor = (!accel_method_str || 968 strcmp(accel_method_str, "glamor") == 0); 969 970 ms->drmmode.glamor = FALSE; 971 972 #ifdef GLAMOR_HAS_GBM 973 if (ms->drmmode.force_24_32) { 974 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Cannot use glamor with 24bpp packed fb\n"); 975 return; 976 } 977 978 if (!do_glamor) { 979 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "glamor disabled\n"); 980 return; 981 } 982 983 if (load_glamor(pScrn)) { 984 if (ms->glamor.egl_init(pScrn, ms->fd)) { 985 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "glamor initialized\n"); 986 ms->drmmode.glamor = TRUE; 987 } else { 988 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 989 "glamor initialization failed\n"); 990 } 991 } else { 992 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 993 "Failed to load glamor module.\n"); 994 } 995 #else 996 if (do_glamor) { 997 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 998 "No glamor support in the X Server\n"); 999 } 1000 #endif 1001 } 1002 1003 static Bool 1004 msShouldDoubleShadow(ScrnInfoPtr pScrn, modesettingPtr ms) 1005 { 1006 Bool ret = FALSE, asked; 1007 int from; 1008 drmVersionPtr v = drmGetVersion(ms->fd); 1009 1010 if (!ms->drmmode.shadow_enable) 1011 return FALSE; 1012 1013 if (!strcmp(v->name, "mgag200") || 1014 !strcmp(v->name, "ast")) /* XXX || rn50 */ 1015 ret = TRUE; 1016 1017 drmFreeVersion(v); 1018 1019 asked = xf86GetOptValBool(ms->drmmode.Options, OPTION_DOUBLE_SHADOW, &ret); 1020 1021 if (asked) 1022 from = X_CONFIG; 1023 else 1024 from = X_INFO; 1025 1026 xf86DrvMsg(pScrn->scrnIndex, from, 1027 "Double-buffered shadow updates: %s\n", ret ? "on" : "off"); 1028 1029 return ret; 1030 } 1031 1032 static Bool 1033 ms_get_drm_master_fd(ScrnInfoPtr pScrn) 1034 { 1035 EntityInfoPtr pEnt; 1036 modesettingPtr ms; 1037 modesettingEntPtr ms_ent; 1038 1039 ms = modesettingPTR(pScrn); 1040 ms_ent = ms_ent_priv(pScrn); 1041 1042 pEnt = ms->pEnt; 1043 1044 if (ms_ent->fd) { 1045 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1046 " reusing fd for second head\n"); 1047 ms->fd = ms_ent->fd; 1048 ms_ent->fd_ref++; 1049 return TRUE; 1050 } 1051 1052 ms->fd_passed = FALSE; 1053 if ((ms->fd = get_passed_fd()) >= 0) { 1054 ms->fd_passed = TRUE; 1055 return TRUE; 1056 } 1057 1058 #ifdef XSERVER_PLATFORM_BUS 1059 if (pEnt->location.type == BUS_PLATFORM) { 1060 #ifdef XF86_PDEV_SERVER_FD 1061 if (pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD) 1062 ms->fd = 1063 xf86_platform_device_odev_attributes(pEnt->location.id.plat)-> 1064 fd; 1065 else 1066 #endif 1067 { 1068 char *path = 1069 xf86_platform_device_odev_attributes(pEnt->location.id.plat)-> 1070 path; 1071 ms->fd = open_hw(path); 1072 } 1073 } 1074 else 1075 #endif 1076 #ifdef XSERVER_LIBPCIACCESS 1077 if (pEnt->location.type == BUS_PCI) { 1078 char *BusID = NULL; 1079 struct pci_device *PciInfo; 1080 1081 PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index); 1082 if (PciInfo) { 1083 if ((BusID = ms_DRICreatePCIBusID(PciInfo)) != NULL) { 1084 ms->fd = drmOpen(NULL, BusID); 1085 free(BusID); 1086 } 1087 } 1088 } 1089 else 1090 #endif 1091 { 1092 const char *devicename; 1093 devicename = xf86FindOptionValue(ms->pEnt->device->options, "kmsdev"); 1094 ms->fd = open_hw(devicename); 1095 } 1096 if (ms->fd < 0) 1097 return FALSE; 1098 1099 ms_ent->fd = ms->fd; 1100 ms_ent->fd_ref = 1; 1101 return TRUE; 1102 } 1103 1104 static Bool 1105 PreInit(ScrnInfoPtr pScrn, int flags) 1106 { 1107 modesettingPtr ms; 1108 rgb defaultWeight = { 0, 0, 0 }; 1109 EntityInfoPtr pEnt; 1110 uint64_t value = 0; 1111 int ret; 1112 int bppflags, connector_count; 1113 int defaultdepth, defaultbpp; 1114 1115 if (pScrn->numEntities != 1) 1116 return FALSE; 1117 1118 if (flags & PROBE_DETECT) { 1119 return FALSE; 1120 } 1121 1122 /* Allocate driverPrivate */ 1123 if (!GetRec(pScrn)) 1124 return FALSE; 1125 1126 pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 1127 1128 ms = modesettingPTR(pScrn); 1129 ms->SaveGeneration = -1; 1130 ms->pEnt = pEnt; 1131 ms->drmmode.is_secondary = FALSE; 1132 pScrn->displayWidth = 640; /* default it */ 1133 1134 if (xf86IsEntityShared(pScrn->entityList[0])) { 1135 if (xf86IsPrimInitDone(pScrn->entityList[0])) 1136 ms->drmmode.is_secondary = TRUE; 1137 else 1138 xf86SetPrimInitDone(pScrn->entityList[0]); 1139 } 1140 1141 pScrn->monitor = pScrn->confScreen->monitor; 1142 pScrn->progClock = TRUE; 1143 pScrn->rgbBits = 8; 1144 1145 if (!ms_get_drm_master_fd(pScrn)) 1146 return FALSE; 1147 ms->drmmode.fd = ms->fd; 1148 1149 if (!check_outputs(ms->fd, &connector_count)) 1150 return FALSE; 1151 1152 drmmode_get_default_bpp(pScrn, &ms->drmmode, &defaultdepth, &defaultbpp); 1153 if (defaultdepth == 24 && defaultbpp == 24) { 1154 ms->drmmode.force_24_32 = TRUE; 1155 ms->drmmode.kbpp = 24; 1156 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1157 "Using 24bpp hw front buffer with 32bpp shadow\n"); 1158 defaultbpp = 32; 1159 } else { 1160 ms->drmmode.kbpp = 0; 1161 } 1162 bppflags = PreferConvert24to32 | SupportConvert24to32 | Support32bppFb; 1163 1164 if (!xf86SetDepthBpp 1165 (pScrn, defaultdepth, defaultdepth, defaultbpp, bppflags)) 1166 return FALSE; 1167 1168 switch (pScrn->depth) { 1169 case 15: 1170 case 16: 1171 case 24: 1172 case 30: 1173 break; 1174 default: 1175 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1176 "Given depth (%d) is not supported by the driver\n", 1177 pScrn->depth); 1178 return FALSE; 1179 } 1180 xf86PrintDepthBpp(pScrn); 1181 if (!ms->drmmode.kbpp) 1182 ms->drmmode.kbpp = pScrn->bitsPerPixel; 1183 1184 /* Process the options */ 1185 xf86CollectOptions(pScrn, NULL); 1186 if (!(ms->drmmode.Options = malloc(sizeof(Options)))) 1187 return FALSE; 1188 memcpy(ms->drmmode.Options, Options, sizeof(Options)); 1189 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->drmmode.Options); 1190 1191 if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) 1192 return FALSE; 1193 if (!xf86SetDefaultVisual(pScrn, -1)) 1194 return FALSE; 1195 1196 if (xf86ReturnOptValBool(ms->drmmode.Options, OPTION_SW_CURSOR, FALSE)) { 1197 ms->drmmode.sw_cursor = TRUE; 1198 } 1199 1200 ms->cursor_width = 64; 1201 ms->cursor_height = 64; 1202 ret = drmGetCap(ms->fd, DRM_CAP_CURSOR_WIDTH, &value); 1203 if (!ret) { 1204 ms->cursor_width = value; 1205 } 1206 ret = drmGetCap(ms->fd, DRM_CAP_CURSOR_HEIGHT, &value); 1207 if (!ret) { 1208 ms->cursor_height = value; 1209 } 1210 1211 try_enable_glamor(pScrn); 1212 1213 if (!ms->drmmode.glamor) { 1214 Bool prefer_shadow = TRUE; 1215 1216 if (ms->drmmode.force_24_32) { 1217 prefer_shadow = TRUE; 1218 ms->drmmode.shadow_enable = TRUE; 1219 } else { 1220 ret = drmGetCap(ms->fd, DRM_CAP_DUMB_PREFER_SHADOW, &value); 1221 if (!ret) { 1222 prefer_shadow = !!value; 1223 } 1224 1225 ms->drmmode.shadow_enable = 1226 xf86ReturnOptValBool(ms->drmmode.Options, OPTION_SHADOW_FB, 1227 prefer_shadow); 1228 } 1229 1230 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1231 "ShadowFB: preferred %s, enabled %s\n", 1232 prefer_shadow ? "YES" : "NO", 1233 ms->drmmode.force_24_32 ? "FORCE" : 1234 ms->drmmode.shadow_enable ? "YES" : "NO"); 1235 1236 ms->drmmode.shadow_enable2 = msShouldDoubleShadow(pScrn, ms); 1237 } else { 1238 if (!pScrn->is_gpu) { 1239 MessageType from = xf86GetOptValBool(ms->drmmode.Options, OPTION_VARIABLE_REFRESH, 1240 &ms->vrr_support) ? X_CONFIG : X_DEFAULT; 1241 xf86DrvMsg(pScrn->scrnIndex, from, "VariableRefresh: %sabled\n", 1242 ms->vrr_support ? "en" : "dis"); 1243 1244 ms->drmmode.async_flip_secondaries = FALSE; 1245 from = xf86GetOptValBool(ms->drmmode.Options, OPTION_ASYNC_FLIP_SECONDARIES, 1246 &ms->drmmode.async_flip_secondaries) ? X_CONFIG : X_DEFAULT; 1247 xf86DrvMsg(pScrn->scrnIndex, from, "AsyncFlipSecondaries: %sabled\n", 1248 ms->drmmode.async_flip_secondaries ? "en" : "dis"); 1249 } 1250 } 1251 1252 ms->drmmode.pageflip = 1253 xf86ReturnOptValBool(ms->drmmode.Options, OPTION_PAGEFLIP, TRUE); 1254 1255 pScrn->capabilities = 0; 1256 ret = drmGetCap(ms->fd, DRM_CAP_PRIME, &value); 1257 if (ret == 0) { 1258 if (connector_count && (value & DRM_PRIME_CAP_IMPORT)) { 1259 pScrn->capabilities |= RR_Capability_SinkOutput; 1260 if (ms->drmmode.glamor) 1261 pScrn->capabilities |= RR_Capability_SinkOffload; 1262 } 1263 #ifdef GLAMOR_HAS_GBM_LINEAR 1264 if (value & DRM_PRIME_CAP_EXPORT && ms->drmmode.glamor) 1265 pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SourceOffload; 1266 #endif 1267 } 1268 1269 /* 1270 * Use "atomic modesetting disable" request to detect if the kms driver is 1271 * atomic capable, regardless if we will actually use atomic modesetting. 1272 * This is effectively a no-op, we only care about the return status code. 1273 */ 1274 ret = drmSetClientCap(ms->fd, DRM_CLIENT_CAP_ATOMIC, 0); 1275 ms->atomic_modeset_capable = (ret == 0); 1276 1277 if (xf86ReturnOptValBool(ms->drmmode.Options, OPTION_ATOMIC, FALSE)) { 1278 ret = drmSetClientCap(ms->fd, DRM_CLIENT_CAP_ATOMIC, 1); 1279 ms->atomic_modeset = (ret == 0); 1280 } else { 1281 ms->atomic_modeset = FALSE; 1282 } 1283 1284 ms->kms_has_modifiers = FALSE; 1285 ret = drmGetCap(ms->fd, DRM_CAP_ADDFB2_MODIFIERS, &value); 1286 if (ret == 0 && value != 0) 1287 ms->kms_has_modifiers = TRUE; 1288 1289 if (drmmode_pre_init(pScrn, &ms->drmmode, pScrn->bitsPerPixel / 8) == FALSE) { 1290 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "KMS setup failed\n"); 1291 goto fail; 1292 } 1293 1294 /* 1295 * If the driver can do gamma correction, it should call xf86SetGamma() here. 1296 */ 1297 { 1298 Gamma zeros = { 0.0, 0.0, 0.0 }; 1299 1300 if (!xf86SetGamma(pScrn, zeros)) { 1301 return FALSE; 1302 } 1303 } 1304 1305 if (!(pScrn->is_gpu && connector_count == 0) && pScrn->modes == NULL) { 1306 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); 1307 return FALSE; 1308 } 1309 1310 pScrn->currentMode = pScrn->modes; 1311 1312 /* Set display resolution */ 1313 xf86SetDpi(pScrn, 0, 0); 1314 1315 /* Load the required sub modules */ 1316 if (!xf86LoadSubModule(pScrn, "fb")) { 1317 return FALSE; 1318 } 1319 1320 if (ms->drmmode.shadow_enable) { 1321 void *mod = xf86LoadSubModule(pScrn, "shadow"); 1322 1323 if (!mod) 1324 return FALSE; 1325 1326 ms->shadow.Setup = LoaderSymbolFromModule(mod, "shadowSetup"); 1327 ms->shadow.Add = LoaderSymbolFromModule(mod, "shadowAdd"); 1328 ms->shadow.Remove = LoaderSymbolFromModule(mod, "shadowRemove"); 1329 ms->shadow.Update32to24 = LoaderSymbolFromModule(mod, "shadowUpdate32to24"); 1330 ms->shadow.UpdatePacked = LoaderSymbolFromModule(mod, "shadowUpdatePacked"); 1331 } 1332 1333 return TRUE; 1334 fail: 1335 return FALSE; 1336 } 1337 1338 static void * 1339 msShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode, 1340 CARD32 *size, void *closure) 1341 { 1342 ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 1343 modesettingPtr ms = modesettingPTR(pScrn); 1344 int stride; 1345 1346 stride = (pScrn->displayWidth * ms->drmmode.kbpp) / 8; 1347 *size = stride; 1348 1349 return ((uint8_t *) ms->drmmode.front_bo.dumb->ptr + row * stride + offset); 1350 } 1351 1352 /* somewhat arbitrary tile size, in pixels */ 1353 #define TILE 16 1354 1355 static int 1356 msUpdateIntersect(modesettingPtr ms, shadowBufPtr pBuf, BoxPtr box, 1357 xRectangle *prect) 1358 { 1359 int i, dirty = 0, stride = pBuf->pPixmap->devKind, cpp = ms->drmmode.cpp; 1360 int width = (box->x2 - box->x1) * cpp; 1361 unsigned char *old, *new; 1362 1363 old = ms->drmmode.shadow_fb2; 1364 old += (box->y1 * stride) + (box->x1 * cpp); 1365 new = ms->drmmode.shadow_fb; 1366 new += (box->y1 * stride) + (box->x1 * cpp); 1367 1368 for (i = box->y2 - box->y1 - 1; i >= 0; i--) { 1369 unsigned char *o = old + i * stride, 1370 *n = new + i * stride; 1371 if (memcmp(o, n, width) != 0) { 1372 dirty = 1; 1373 memcpy(o, n, width); 1374 } 1375 } 1376 1377 if (dirty) { 1378 prect->x = box->x1; 1379 prect->y = box->y1; 1380 prect->width = box->x2 - box->x1; 1381 prect->height = box->y2 - box->y1; 1382 } 1383 1384 return dirty; 1385 } 1386 1387 static void 1388 msUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf) 1389 { 1390 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1391 modesettingPtr ms = modesettingPTR(pScrn); 1392 Bool use_3224 = ms->drmmode.force_24_32 && pScrn->bitsPerPixel == 32; 1393 1394 if (ms->drmmode.shadow_enable2 && ms->drmmode.shadow_fb2) do { 1395 RegionPtr damage = DamageRegion(pBuf->pDamage), tiles; 1396 BoxPtr extents = RegionExtents(damage); 1397 xRectangle *prect; 1398 int nrects; 1399 int i, j, tx1, tx2, ty1, ty2; 1400 1401 tx1 = extents->x1 / TILE; 1402 tx2 = (extents->x2 + TILE - 1) / TILE; 1403 ty1 = extents->y1 / TILE; 1404 ty2 = (extents->y2 + TILE - 1) / TILE; 1405 1406 nrects = (tx2 - tx1) * (ty2 - ty1); 1407 if (!(prect = calloc(nrects, sizeof(xRectangle)))) 1408 break; 1409 1410 nrects = 0; 1411 for (j = ty2 - 1; j >= ty1; j--) { 1412 for (i = tx2 - 1; i >= tx1; i--) { 1413 BoxRec box; 1414 1415 box.x1 = max(i * TILE, extents->x1); 1416 box.y1 = max(j * TILE, extents->y1); 1417 box.x2 = min((i+1) * TILE, extents->x2); 1418 box.y2 = min((j+1) * TILE, extents->y2); 1419 1420 if (RegionContainsRect(damage, &box) != rgnOUT) { 1421 if (msUpdateIntersect(ms, pBuf, &box, prect + nrects)) { 1422 nrects++; 1423 } 1424 } 1425 } 1426 } 1427 1428 tiles = RegionFromRects(nrects, prect, CT_NONE); 1429 RegionIntersect(damage, damage, tiles); 1430 RegionDestroy(tiles); 1431 free(prect); 1432 } while (0); 1433 1434 if (use_3224) 1435 ms->shadow.Update32to24(pScreen, pBuf); 1436 else 1437 ms->shadow.UpdatePacked(pScreen, pBuf); 1438 } 1439 1440 static Bool 1441 msEnableSharedPixmapFlipping(RRCrtcPtr crtc, PixmapPtr front, PixmapPtr back) 1442 { 1443 ScreenPtr screen = crtc->pScreen; 1444 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1445 modesettingPtr ms = modesettingPTR(scrn); 1446 EntityInfoPtr pEnt = ms->pEnt; 1447 xf86CrtcPtr xf86Crtc = crtc->devPrivate; 1448 1449 if (!xf86Crtc) 1450 return FALSE; 1451 1452 /* Not supported if we can't flip */ 1453 if (!ms->drmmode.pageflip) 1454 return FALSE; 1455 1456 /* Not currently supported with reverse PRIME */ 1457 if (ms->drmmode.reverse_prime_offload_mode) 1458 return FALSE; 1459 1460 #ifdef XSERVER_PLATFORM_BUS 1461 if (pEnt->location.type == BUS_PLATFORM) { 1462 char *syspath = 1463 xf86_platform_device_odev_attributes(pEnt->location.id.plat)-> 1464 syspath; 1465 1466 /* Not supported for devices using USB transport due to misbehaved 1467 * vblank events */ 1468 if (syspath && strstr(syspath, "usb")) 1469 return FALSE; 1470 1471 /* EVDI uses USB transport but is platform device, not usb. 1472 * Exclude it explicitly. */ 1473 if (syspath && strstr(syspath, "evdi")) 1474 return FALSE; 1475 } 1476 #endif 1477 1478 return drmmode_EnableSharedPixmapFlipping(xf86Crtc, &ms->drmmode, 1479 front, back); 1480 } 1481 1482 static void 1483 msDisableSharedPixmapFlipping(RRCrtcPtr crtc) 1484 { 1485 ScreenPtr screen = crtc->pScreen; 1486 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1487 modesettingPtr ms = modesettingPTR(scrn); 1488 xf86CrtcPtr xf86Crtc = crtc->devPrivate; 1489 1490 if (xf86Crtc) 1491 drmmode_DisableSharedPixmapFlipping(xf86Crtc, &ms->drmmode); 1492 } 1493 1494 static Bool 1495 msStartFlippingPixmapTracking(RRCrtcPtr crtc, DrawablePtr src, 1496 PixmapPtr secondary_dst1, PixmapPtr secondary_dst2, 1497 int x, int y, int dst_x, int dst_y, 1498 Rotation rotation) 1499 { 1500 ScreenPtr pScreen = src->pScreen; 1501 modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen)); 1502 1503 msPixmapPrivPtr ppriv1 = msGetPixmapPriv(&ms->drmmode, secondary_dst1->primary_pixmap), 1504 ppriv2 = msGetPixmapPriv(&ms->drmmode, secondary_dst2->primary_pixmap); 1505 1506 if (!PixmapStartDirtyTracking(src, secondary_dst1, x, y, 1507 dst_x, dst_y, rotation)) { 1508 return FALSE; 1509 } 1510 1511 if (!PixmapStartDirtyTracking(src, secondary_dst2, x, y, 1512 dst_x, dst_y, rotation)) { 1513 PixmapStopDirtyTracking(src, secondary_dst1); 1514 return FALSE; 1515 } 1516 1517 ppriv1->secondary_src = src; 1518 ppriv2->secondary_src = src; 1519 1520 ppriv1->dirty = ms_dirty_get_ent(pScreen, secondary_dst1); 1521 ppriv2->dirty = ms_dirty_get_ent(pScreen, secondary_dst2); 1522 1523 ppriv1->defer_dirty_update = TRUE; 1524 ppriv2->defer_dirty_update = TRUE; 1525 1526 return TRUE; 1527 } 1528 1529 static Bool 1530 msPresentSharedPixmap(PixmapPtr secondary_dst) 1531 { 1532 ScreenPtr pScreen = secondary_dst->primary_pixmap->drawable.pScreen; 1533 modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen)); 1534 1535 msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, secondary_dst->primary_pixmap); 1536 1537 RegionPtr region = DamageRegion(ppriv->dirty->damage); 1538 1539 if (RegionNotEmpty(region)) { 1540 redisplay_dirty(ppriv->secondary_src->pScreen, ppriv->dirty, NULL); 1541 DamageEmpty(ppriv->dirty->damage); 1542 1543 return TRUE; 1544 } 1545 1546 return FALSE; 1547 } 1548 1549 static Bool 1550 msStopFlippingPixmapTracking(DrawablePtr src, 1551 PixmapPtr secondary_dst1, PixmapPtr secondary_dst2) 1552 { 1553 ScreenPtr pScreen = src->pScreen; 1554 modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen)); 1555 1556 msPixmapPrivPtr ppriv1 = msGetPixmapPriv(&ms->drmmode, secondary_dst1->primary_pixmap), 1557 ppriv2 = msGetPixmapPriv(&ms->drmmode, secondary_dst2->primary_pixmap); 1558 1559 Bool ret = TRUE; 1560 1561 ret &= PixmapStopDirtyTracking(src, secondary_dst1); 1562 ret &= PixmapStopDirtyTracking(src, secondary_dst2); 1563 1564 if (ret) { 1565 ppriv1->secondary_src = NULL; 1566 ppriv2->secondary_src = NULL; 1567 1568 ppriv1->dirty = NULL; 1569 ppriv2->dirty = NULL; 1570 1571 ppriv1->defer_dirty_update = FALSE; 1572 ppriv2->defer_dirty_update = FALSE; 1573 } 1574 1575 return ret; 1576 } 1577 1578 static Bool 1579 CreateScreenResources(ScreenPtr pScreen) 1580 { 1581 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1582 modesettingPtr ms = modesettingPTR(pScrn); 1583 PixmapPtr rootPixmap; 1584 Bool ret; 1585 void *pixels = NULL; 1586 int err; 1587 1588 pScreen->CreateScreenResources = ms->createScreenResources; 1589 ret = pScreen->CreateScreenResources(pScreen); 1590 pScreen->CreateScreenResources = CreateScreenResources; 1591 1592 if (!drmmode_set_desired_modes(pScrn, &ms->drmmode, pScrn->is_gpu, FALSE)) 1593 return FALSE; 1594 1595 if (!drmmode_glamor_handle_new_screen_pixmap(&ms->drmmode)) 1596 return FALSE; 1597 1598 drmmode_uevent_init(pScrn, &ms->drmmode); 1599 1600 if (!ms->drmmode.sw_cursor) 1601 drmmode_map_cursor_bos(pScrn, &ms->drmmode); 1602 1603 if (!ms->drmmode.gbm) { 1604 pixels = drmmode_map_front_bo(&ms->drmmode); 1605 if (!pixels) 1606 return FALSE; 1607 } 1608 1609 rootPixmap = pScreen->GetScreenPixmap(pScreen); 1610 1611 if (ms->drmmode.shadow_enable) 1612 pixels = ms->drmmode.shadow_fb; 1613 1614 if (ms->drmmode.shadow_enable2) { 1615 ms->drmmode.shadow_fb2 = calloc(1, pScrn->displayWidth * pScrn->virtualY * ((pScrn->bitsPerPixel + 7) >> 3)); 1616 if (!ms->drmmode.shadow_fb2) 1617 ms->drmmode.shadow_enable2 = FALSE; 1618 } 1619 1620 if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, pixels)) 1621 FatalError("Couldn't adjust screen pixmap\n"); 1622 1623 if (ms->drmmode.shadow_enable) { 1624 if (!ms->shadow.Add(pScreen, rootPixmap, msUpdatePacked, msShadowWindow, 1625 0, 0)) 1626 return FALSE; 1627 } 1628 1629 err = drmModeDirtyFB(ms->fd, ms->drmmode.fb_id, NULL, 0); 1630 1631 if (err != -EINVAL && err != -ENOSYS) { 1632 ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, 1633 pScreen, rootPixmap); 1634 1635 if (ms->damage) { 1636 DamageRegister(&rootPixmap->drawable, ms->damage); 1637 ms->dirty_enabled = TRUE; 1638 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n"); 1639 } 1640 else { 1641 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1642 "Failed to create screen damage record\n"); 1643 return FALSE; 1644 } 1645 } 1646 1647 if (dixPrivateKeyRegistered(rrPrivKey)) { 1648 rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen); 1649 1650 pScrPriv->rrEnableSharedPixmapFlipping = msEnableSharedPixmapFlipping; 1651 pScrPriv->rrDisableSharedPixmapFlipping = msDisableSharedPixmapFlipping; 1652 1653 pScrPriv->rrStartFlippingPixmapTracking = msStartFlippingPixmapTracking; 1654 } 1655 1656 if (ms->vrr_support && 1657 !dixRegisterPrivateKey(&ms->drmmode.vrrPrivateKeyRec, 1658 PRIVATE_WINDOW, 1659 sizeof(struct ms_vrr_priv))) 1660 return FALSE; 1661 1662 return ret; 1663 } 1664 1665 static Bool 1666 msSharePixmapBacking(PixmapPtr ppix, ScreenPtr secondary, void **handle) 1667 { 1668 #ifdef GLAMOR_HAS_GBM 1669 modesettingPtr ms = 1670 modesettingPTR(xf86ScreenToScrn(ppix->drawable.pScreen)); 1671 int ret; 1672 CARD16 stride; 1673 CARD32 size; 1674 ret = ms->glamor.shareable_fd_from_pixmap(ppix->drawable.pScreen, ppix, 1675 &stride, &size); 1676 if (ret == -1) 1677 return FALSE; 1678 1679 *handle = (void *)(long)(ret); 1680 return TRUE; 1681 #endif 1682 return FALSE; 1683 } 1684 1685 static Bool 1686 msSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle) 1687 { 1688 #ifdef GLAMOR_HAS_GBM 1689 ScreenPtr screen = ppix->drawable.pScreen; 1690 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1691 modesettingPtr ms = modesettingPTR(scrn); 1692 Bool ret; 1693 int ihandle = (int) (long) fd_handle; 1694 1695 if (ihandle == -1) 1696 if (!ms->drmmode.reverse_prime_offload_mode) 1697 return drmmode_SetSlaveBO(ppix, &ms->drmmode, ihandle, 0, 0); 1698 1699 if (ms->drmmode.reverse_prime_offload_mode) { 1700 ret = ms->glamor.back_pixmap_from_fd(ppix, ihandle, 1701 ppix->drawable.width, 1702 ppix->drawable.height, 1703 ppix->devKind, 1704 ppix->drawable.depth, 1705 ppix->drawable.bitsPerPixel); 1706 } else { 1707 int size = ppix->devKind * ppix->drawable.height; 1708 ret = drmmode_SetSlaveBO(ppix, &ms->drmmode, ihandle, ppix->devKind, size); 1709 } 1710 if (ret == FALSE) 1711 return ret; 1712 1713 return TRUE; 1714 #else 1715 return FALSE; 1716 #endif 1717 } 1718 1719 static Bool 1720 msRequestSharedPixmapNotifyDamage(PixmapPtr ppix) 1721 { 1722 ScreenPtr screen = ppix->drawable.pScreen; 1723 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1724 modesettingPtr ms = modesettingPTR(scrn); 1725 1726 msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix->primary_pixmap); 1727 1728 ppriv->notify_on_damage = TRUE; 1729 1730 return TRUE; 1731 } 1732 1733 static Bool 1734 msSharedPixmapNotifyDamage(PixmapPtr ppix) 1735 { 1736 Bool ret = FALSE; 1737 int c; 1738 1739 ScreenPtr screen = ppix->drawable.pScreen; 1740 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1741 modesettingPtr ms = modesettingPTR(scrn); 1742 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1743 1744 msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix); 1745 1746 if (!ppriv->wait_for_damage) 1747 return ret; 1748 ppriv->wait_for_damage = FALSE; 1749 1750 for (c = 0; c < xf86_config->num_crtc; c++) { 1751 xf86CrtcPtr crtc = xf86_config->crtc[c]; 1752 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1753 1754 if (!drmmode_crtc) 1755 continue; 1756 if (!(drmmode_crtc->prime_pixmap && drmmode_crtc->prime_pixmap_back)) 1757 continue; 1758 1759 // Received damage on primary screen pixmap, schedule present on vblank 1760 ret |= drmmode_SharedPixmapPresentOnVBlank(ppix, crtc, &ms->drmmode); 1761 } 1762 1763 return ret; 1764 } 1765 1766 static Bool 1767 SetMaster(ScrnInfoPtr pScrn) 1768 { 1769 modesettingPtr ms = modesettingPTR(pScrn); 1770 int ret; 1771 1772 #ifdef XF86_PDEV_SERVER_FD 1773 if (ms->pEnt->location.type == BUS_PLATFORM && 1774 (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)) 1775 return TRUE; 1776 #endif 1777 1778 if (ms->fd_passed) 1779 return TRUE; 1780 1781 ret = drmSetMaster(ms->fd); 1782 if (ret) 1783 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "drmSetMaster failed: %s\n", 1784 strerror(errno)); 1785 1786 return ret == 0; 1787 } 1788 1789 /* When the root window is created, initialize the screen contents from 1790 * console if -background none was specified on the command line 1791 */ 1792 static Bool 1793 CreateWindow_oneshot(WindowPtr pWin) 1794 { 1795 ScreenPtr pScreen = pWin->drawable.pScreen; 1796 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1797 modesettingPtr ms = modesettingPTR(pScrn); 1798 Bool ret; 1799 1800 pScreen->CreateWindow = ms->CreateWindow; 1801 ret = pScreen->CreateWindow(pWin); 1802 1803 if (ret) 1804 drmmode_copy_fb(pScrn, &ms->drmmode); 1805 return ret; 1806 } 1807 1808 static Bool 1809 ScreenInit(ScreenPtr pScreen, int argc, char **argv) 1810 { 1811 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1812 modesettingPtr ms = modesettingPTR(pScrn); 1813 VisualPtr visual; 1814 1815 pScrn->pScreen = pScreen; 1816 1817 if (!SetMaster(pScrn)) 1818 return FALSE; 1819 1820 #ifdef GLAMOR_HAS_GBM 1821 if (ms->drmmode.glamor) 1822 ms->drmmode.gbm = ms->glamor.egl_get_gbm_device(pScreen); 1823 #endif 1824 1825 /* HW dependent - FIXME */ 1826 pScrn->displayWidth = pScrn->virtualX; 1827 if (!drmmode_create_initial_bos(pScrn, &ms->drmmode)) 1828 return FALSE; 1829 1830 if (ms->drmmode.shadow_enable) { 1831 ms->drmmode.shadow_fb = 1832 calloc(1, 1833 pScrn->displayWidth * pScrn->virtualY * 1834 ((pScrn->bitsPerPixel + 7) >> 3)); 1835 if (!ms->drmmode.shadow_fb) 1836 ms->drmmode.shadow_enable = FALSE; 1837 } 1838 1839 miClearVisualTypes(); 1840 1841 if (!miSetVisualTypes(pScrn->depth, 1842 miGetDefaultVisualMask(pScrn->depth), 1843 pScrn->rgbBits, pScrn->defaultVisual)) 1844 return FALSE; 1845 1846 if (!miSetPixmapDepths()) 1847 return FALSE; 1848 1849 if (!dixRegisterScreenSpecificPrivateKey 1850 (pScreen, &ms->drmmode.pixmapPrivateKeyRec, PRIVATE_PIXMAP, 1851 sizeof(msPixmapPrivRec))) { 1852 return FALSE; 1853 } 1854 1855 pScrn->memPhysBase = 0; 1856 pScrn->fbOffset = 0; 1857 1858 if (!fbScreenInit(pScreen, NULL, 1859 pScrn->virtualX, pScrn->virtualY, 1860 pScrn->xDpi, pScrn->yDpi, 1861 pScrn->displayWidth, pScrn->bitsPerPixel)) 1862 return FALSE; 1863 1864 if (pScrn->bitsPerPixel > 8) { 1865 /* Fixup RGB ordering */ 1866 visual = pScreen->visuals + pScreen->numVisuals; 1867 while (--visual >= pScreen->visuals) { 1868 if ((visual->class | DynamicClass) == DirectColor) { 1869 visual->offsetRed = pScrn->offset.red; 1870 visual->offsetGreen = pScrn->offset.green; 1871 visual->offsetBlue = pScrn->offset.blue; 1872 visual->redMask = pScrn->mask.red; 1873 visual->greenMask = pScrn->mask.green; 1874 visual->blueMask = pScrn->mask.blue; 1875 } 1876 } 1877 } 1878 1879 fbPictureInit(pScreen, NULL, 0); 1880 1881 if (drmmode_init(pScrn, &ms->drmmode) == FALSE) { 1882 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1883 "Failed to initialize glamor at ScreenInit() time.\n"); 1884 return FALSE; 1885 } 1886 1887 if (ms->drmmode.shadow_enable && !ms->shadow.Setup(pScreen)) { 1888 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "shadow fb init failed\n"); 1889 return FALSE; 1890 } 1891 1892 ms->createScreenResources = pScreen->CreateScreenResources; 1893 pScreen->CreateScreenResources = CreateScreenResources; 1894 1895 xf86SetBlackWhitePixels(pScreen); 1896 1897 xf86SetBackingStore(pScreen); 1898 xf86SetSilkenMouse(pScreen); 1899 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1900 1901 /* If pageflip is enabled hook the screen's cursor-sprite (swcursor) funcs. 1902 * So that we can disable page-flipping on fallback to a swcursor. */ 1903 if (ms->drmmode.pageflip) { 1904 miPointerScreenPtr PointPriv = 1905 dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); 1906 1907 if (!dixRegisterScreenPrivateKey(&ms->drmmode.spritePrivateKeyRec, 1908 pScreen, PRIVATE_DEVICE, 1909 sizeof(msSpritePrivRec))) 1910 return FALSE; 1911 1912 ms->SpriteFuncs = PointPriv->spriteFuncs; 1913 PointPriv->spriteFuncs = &drmmode_sprite_funcs; 1914 } 1915 1916 /* Need to extend HWcursor support to handle mask interleave */ 1917 if (!ms->drmmode.sw_cursor) 1918 xf86_cursors_init(pScreen, ms->cursor_width, ms->cursor_height, 1919 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | 1920 HARDWARE_CURSOR_UPDATE_UNHIDDEN | 1921 HARDWARE_CURSOR_ARGB); 1922 1923 /* Must force it before EnterVT, so we are in control of VT and 1924 * later memory should be bound when allocating, e.g rotate_mem */ 1925 pScrn->vtSema = TRUE; 1926 1927 if (serverGeneration == 1 && bgNoneRoot && ms->drmmode.glamor) { 1928 ms->CreateWindow = pScreen->CreateWindow; 1929 pScreen->CreateWindow = CreateWindow_oneshot; 1930 } 1931 1932 pScreen->SaveScreen = xf86SaveScreen; 1933 ms->CloseScreen = pScreen->CloseScreen; 1934 pScreen->CloseScreen = CloseScreen; 1935 1936 ms->BlockHandler = pScreen->BlockHandler; 1937 pScreen->BlockHandler = msBlockHandler_oneshot; 1938 1939 pScreen->SharePixmapBacking = msSharePixmapBacking; 1940 pScreen->SetSharedPixmapBacking = msSetSharedPixmapBacking; 1941 pScreen->StartPixmapTracking = PixmapStartDirtyTracking; 1942 pScreen->StopPixmapTracking = PixmapStopDirtyTracking; 1943 1944 pScreen->SharedPixmapNotifyDamage = msSharedPixmapNotifyDamage; 1945 pScreen->RequestSharedPixmapNotifyDamage = 1946 msRequestSharedPixmapNotifyDamage; 1947 1948 pScreen->PresentSharedPixmap = msPresentSharedPixmap; 1949 pScreen->StopFlippingPixmapTracking = msStopFlippingPixmapTracking; 1950 1951 if (!xf86CrtcScreenInit(pScreen)) 1952 return FALSE; 1953 1954 if (!drmmode_setup_colormap(pScreen, pScrn)) 1955 return FALSE; 1956 1957 if (ms->atomic_modeset) 1958 xf86DPMSInit(pScreen, drmmode_set_dpms, 0); 1959 else 1960 xf86DPMSInit(pScreen, xf86DPMSSet, 0); 1961 1962 #ifdef GLAMOR_HAS_GBM 1963 if (ms->drmmode.glamor) { 1964 XF86VideoAdaptorPtr glamor_adaptor; 1965 1966 glamor_adaptor = ms->glamor.xv_init(pScreen, 16); 1967 if (glamor_adaptor != NULL) 1968 xf86XVScreenInit(pScreen, &glamor_adaptor, 1); 1969 else 1970 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1971 "Failed to initialize XV support.\n"); 1972 } 1973 #endif 1974 1975 if (serverGeneration == 1) 1976 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1977 1978 if (!ms_vblank_screen_init(pScreen)) { 1979 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1980 "Failed to initialize vblank support.\n"); 1981 return FALSE; 1982 } 1983 1984 #ifdef GLAMOR_HAS_GBM 1985 if (ms->drmmode.glamor) { 1986 if (!(ms->drmmode.dri2_enable = ms_dri2_screen_init(pScreen))) { 1987 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1988 "Failed to initialize the DRI2 extension.\n"); 1989 } 1990 1991 /* enable reverse prime if we are a GPU screen, and accelerated, and not 1992 * i915, evdi or udl. i915 is happy scanning out from sysmem. 1993 * evdi and udl are virtual drivers scanning out from sysmem 1994 * backed dumb buffers. 1995 */ 1996 if (pScreen->isGPU) { 1997 drmVersionPtr version; 1998 1999 /* enable if we are an accelerated GPU screen */ 2000 ms->drmmode.reverse_prime_offload_mode = TRUE; 2001 2002 if ((version = drmGetVersion(ms->drmmode.fd))) { 2003 if (!strncmp("i915", version->name, version->name_len)) { 2004 ms->drmmode.reverse_prime_offload_mode = FALSE; 2005 } 2006 if (!strncmp("evdi", version->name, version->name_len)) { 2007 ms->drmmode.reverse_prime_offload_mode = FALSE; 2008 } 2009 if (!strncmp("udl", version->name, version->name_len)) { 2010 ms->drmmode.reverse_prime_offload_mode = FALSE; 2011 } 2012 if (!ms->drmmode.reverse_prime_offload_mode) { 2013 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2014 "Disable reverse prime offload mode for %s.\n", version->name); 2015 } 2016 drmFreeVersion(version); 2017 } 2018 } 2019 } 2020 #endif 2021 if (!(ms->drmmode.present_enable = ms_present_screen_init(pScreen))) { 2022 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2023 "Failed to initialize the Present extension.\n"); 2024 } 2025 2026 2027 pScrn->vtSema = TRUE; 2028 2029 if (ms->vrr_support) { 2030 if (!property_vectors_wrapped) { 2031 saved_change_property = ProcVector[X_ChangeProperty]; 2032 ProcVector[X_ChangeProperty] = ms_change_property; 2033 saved_delete_property = ProcVector[X_DeleteProperty]; 2034 ProcVector[X_DeleteProperty] = ms_delete_property; 2035 property_vectors_wrapped = TRUE; 2036 } 2037 vrr_atom = MakeAtom("_VARIABLE_REFRESH", 2038 strlen("_VARIABLE_REFRESH"), TRUE); 2039 } 2040 2041 return TRUE; 2042 } 2043 2044 static void 2045 AdjustFrame(ScrnInfoPtr pScrn, int x, int y) 2046 { 2047 modesettingPtr ms = modesettingPTR(pScrn); 2048 2049 drmmode_adjust_frame(pScrn, &ms->drmmode, x, y); 2050 } 2051 2052 static void 2053 FreeScreen(ScrnInfoPtr pScrn) 2054 { 2055 FreeRec(pScrn); 2056 } 2057 2058 static void 2059 LeaveVT(ScrnInfoPtr pScrn) 2060 { 2061 modesettingPtr ms = modesettingPTR(pScrn); 2062 2063 xf86_hide_cursors(pScrn); 2064 2065 pScrn->vtSema = FALSE; 2066 2067 #ifdef XF86_PDEV_SERVER_FD 2068 if (ms->pEnt->location.type == BUS_PLATFORM && 2069 (ms->pEnt->location.id.plat->flags & XF86_PDEV_SERVER_FD)) 2070 return; 2071 #endif 2072 2073 if (!ms->fd_passed) 2074 drmDropMaster(ms->fd); 2075 } 2076 2077 /* 2078 * This gets called when gaining control of the VT, and from ScreenInit(). 2079 */ 2080 static Bool 2081 EnterVT(ScrnInfoPtr pScrn) 2082 { 2083 modesettingPtr ms = modesettingPTR(pScrn); 2084 2085 pScrn->vtSema = TRUE; 2086 2087 SetMaster(pScrn); 2088 2089 drmmode_update_kms_state(&ms->drmmode); 2090 2091 /* allow not all modes to be set successfully since some events might have 2092 * happened while not being master that could prevent the previous 2093 * configuration from being re-applied. 2094 */ 2095 if (!drmmode_set_desired_modes(pScrn, &ms->drmmode, TRUE, TRUE)) { 2096 xf86DisableUnusedFunctions(pScrn); 2097 2098 /* TODO: check that at least one screen is on, to allow the user to fix 2099 * their setup if all modeset failed... 2100 */ 2101 2102 /* Tell the desktop environment that something changed, so that they 2103 * can hopefully correct the situation 2104 */ 2105 RRSetChanged(xf86ScrnToScreen(pScrn)); 2106 RRTellChanged(xf86ScrnToScreen(pScrn)); 2107 } 2108 2109 return TRUE; 2110 } 2111 2112 static Bool 2113 SwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode) 2114 { 2115 return xf86SetSingleMode(pScrn, mode, RR_Rotate_0); 2116 } 2117 2118 static Bool 2119 CloseScreen(ScreenPtr pScreen) 2120 { 2121 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2122 modesettingPtr ms = modesettingPTR(pScrn); 2123 modesettingEntPtr ms_ent = ms_ent_priv(pScrn); 2124 2125 /* Clear mask of assigned crtc's in this generation */ 2126 ms_ent->assigned_crtcs = 0; 2127 2128 #ifdef GLAMOR_HAS_GBM 2129 if (ms->drmmode.dri2_enable) { 2130 ms_dri2_close_screen(pScreen); 2131 } 2132 #endif 2133 2134 ms_vblank_close_screen(pScreen); 2135 2136 if (ms->damage) { 2137 DamageUnregister(ms->damage); 2138 DamageDestroy(ms->damage); 2139 ms->damage = NULL; 2140 } 2141 2142 if (ms->drmmode.shadow_enable) { 2143 ms->shadow.Remove(pScreen, pScreen->GetScreenPixmap(pScreen)); 2144 free(ms->drmmode.shadow_fb); 2145 ms->drmmode.shadow_fb = NULL; 2146 free(ms->drmmode.shadow_fb2); 2147 ms->drmmode.shadow_fb2 = NULL; 2148 } 2149 2150 drmmode_uevent_fini(pScrn, &ms->drmmode); 2151 2152 drmmode_free_bos(pScrn, &ms->drmmode); 2153 2154 if (ms->drmmode.pageflip) { 2155 miPointerScreenPtr PointPriv = 2156 dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); 2157 2158 if (PointPriv->spriteFuncs == &drmmode_sprite_funcs) 2159 PointPriv->spriteFuncs = ms->SpriteFuncs; 2160 } 2161 2162 if (pScrn->vtSema) { 2163 LeaveVT(pScrn); 2164 } 2165 2166 pScreen->CreateScreenResources = ms->createScreenResources; 2167 pScreen->BlockHandler = ms->BlockHandler; 2168 2169 pScrn->vtSema = FALSE; 2170 pScreen->CloseScreen = ms->CloseScreen; 2171 return (*pScreen->CloseScreen) (pScreen); 2172 } 2173 2174 static ModeStatus 2175 ValidMode(ScrnInfoPtr arg, DisplayModePtr mode, Bool verbose, int flags) 2176 { 2177 return MODE_OK; 2178 } 2179