amdgpu_kms.c revision 46845023
1/* 2 * Copyright © 2009 Red Hat, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * Authors: 24 * Dave Airlie <airlied@redhat.com> 25 * 26 */ 27#ifdef HAVE_CONFIG_H 28#include "config.h" 29#endif 30 31#include <errno.h> 32#include <sys/ioctl.h> 33/* Driver data structures */ 34#include "amdgpu_drv.h" 35#include "amdgpu_bo_helper.h" 36#include "amdgpu_drm_queue.h" 37#include "amdgpu_glamor.h" 38#include "amdgpu_probe.h" 39#include "micmap.h" 40#include "mipointrst.h" 41 42#include "amdgpu_version.h" 43#include "shadow.h" 44#include <xf86Priv.h> 45 46#if HAVE_PRESENT_H 47#include <present.h> 48#endif 49 50/* DPMS */ 51#ifdef HAVE_XEXTPROTO_71 52#include <X11/extensions/dpmsconst.h> 53#else 54#define DPMS_SERVER 55#include <X11/extensions/dpms.h> 56#endif 57 58#include <X11/extensions/damageproto.h> 59 60#include "amdgpu_bo_helper.h" 61#include "amdgpu_pixmap.h" 62 63#include <gbm.h> 64 65static DevPrivateKeyRec amdgpu_window_private_key; 66static DevScreenPrivateKeyRec amdgpu_client_private_key; 67DevScreenPrivateKeyRec amdgpu_device_private_key; 68 69static Atom amdgpu_vrr_atom; 70static Bool amdgpu_property_vectors_wrapped; 71static Bool restore_property_vector; 72static int (*saved_change_property) (ClientPtr client); 73static int (*saved_delete_property) (ClientPtr client); 74 75static Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen); 76 77const OptionInfoRec AMDGPUOptions_KMS[] = { 78 {OPTION_ACCEL, "Accel", OPTV_BOOLEAN, {0}, FALSE}, 79 {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, 80 {OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE}, 81 {OPTION_SUBPIXEL_ORDER, "SubPixelOrder", OPTV_ANYSTR, {0}, FALSE}, 82 {OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE}, 83 {OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE}, 84 {OPTION_DRI3, "DRI3", OPTV_BOOLEAN, {0}, FALSE}, 85 {OPTION_DRI, "DRI", OPTV_INTEGER, {0}, FALSE}, 86 {OPTION_SHADOW_PRIMARY, "ShadowPrimary", OPTV_BOOLEAN, {0}, FALSE}, 87 {OPTION_TEAR_FREE, "TearFree", OPTV_BOOLEAN, {0}, FALSE}, 88 {OPTION_DELETE_DP12, "DeleteUnusedDP12Displays", OPTV_BOOLEAN, {0}, FALSE}, 89 {OPTION_VARIABLE_REFRESH, "VariableRefresh", OPTV_BOOLEAN, {0}, FALSE }, 90 {-1, NULL, OPTV_NONE, {0}, FALSE} 91}; 92 93const OptionInfoRec *AMDGPUOptionsWeak(void) 94{ 95 return AMDGPUOptions_KMS; 96} 97 98static inline struct amdgpu_window_priv *get_window_priv(WindowPtr win) { 99 return dixLookupPrivate(&win->devPrivates, &amdgpu_window_private_key); 100} 101 102static void 103amdgpu_vrr_property_update(WindowPtr window, Bool variable_refresh) 104{ 105 ScrnInfoPtr scrn = xf86ScreenToScrn(window->drawable.pScreen); 106 AMDGPUInfoPtr info = AMDGPUPTR(scrn); 107 108 get_window_priv(window)->variable_refresh = variable_refresh; 109 110 if (info->flip_window == window && 111 info->drmmode.present_flipping) 112 amdgpu_present_set_screen_vrr(scrn, variable_refresh); 113} 114 115/* Wrapper for xserver/dix/property.c:ProcChangeProperty */ 116static int 117amdgpu_change_property(ClientPtr client) 118{ 119 WindowPtr window; 120 int ret; 121 122 REQUEST(xChangePropertyReq); 123 124 client->requestVector[X_ChangeProperty] = saved_change_property; 125 ret = saved_change_property(client); 126 127 if (restore_property_vector) 128 return ret; 129 130 client->requestVector[X_ChangeProperty] = amdgpu_change_property; 131 132 if (ret != Success) 133 return ret; 134 135 ret = dixLookupWindow(&window, stuff->window, client, DixSetPropAccess); 136 if (ret != Success) 137 return ret; 138 139 if (stuff->property == amdgpu_vrr_atom && 140 xf86ScreenToScrn(window->drawable.pScreen)->PreInit == 141 AMDGPUPreInit_KMS && stuff->format == 32 && stuff->nUnits == 1) { 142 uint32_t *value = (uint32_t*)(stuff + 1); 143 144 amdgpu_vrr_property_update(window, *value != 0); 145 } 146 147 return ret; 148} 149 150/* Wrapper for xserver/dix/property.c:ProcDeleteProperty */ 151static int 152amdgpu_delete_property(ClientPtr client) 153{ 154 WindowPtr window; 155 int ret; 156 157 REQUEST(xDeletePropertyReq); 158 159 client->requestVector[X_DeleteProperty] = saved_delete_property; 160 ret = saved_delete_property(client); 161 162 if (restore_property_vector) 163 return ret; 164 165 client->requestVector[X_DeleteProperty] = amdgpu_delete_property; 166 167 if (ret != Success) 168 return ret; 169 170 ret = dixLookupWindow(&window, stuff->window, client, DixSetPropAccess); 171 if (ret != Success) 172 return ret; 173 174 if (stuff->property == amdgpu_vrr_atom && 175 xf86ScreenToScrn(window->drawable.pScreen)->PreInit == 176 AMDGPUPreInit_KMS) 177 amdgpu_vrr_property_update(window, FALSE); 178 179 return ret; 180} 181 182static void 183amdgpu_unwrap_property_requests(ScrnInfoPtr scrn) 184{ 185 int i; 186 187 if (!amdgpu_property_vectors_wrapped) 188 return; 189 190 if (ProcVector[X_ChangeProperty] == amdgpu_change_property) 191 ProcVector[X_ChangeProperty] = saved_change_property; 192 else 193 restore_property_vector = TRUE; 194 195 if (ProcVector[X_DeleteProperty] == amdgpu_delete_property) 196 ProcVector[X_DeleteProperty] = saved_delete_property; 197 else 198 restore_property_vector = TRUE; 199 200 for (i = 0; i < currentMaxClients; i++) { 201 if (clients[i]->requestVector[X_ChangeProperty] == 202 amdgpu_change_property) { 203 clients[i]->requestVector[X_ChangeProperty] = 204 saved_change_property; 205 } else { 206 restore_property_vector = TRUE; 207 } 208 209 if (clients[i]->requestVector[X_DeleteProperty] == 210 amdgpu_delete_property) { 211 clients[i]->requestVector[X_DeleteProperty] = 212 saved_delete_property; 213 } else { 214 restore_property_vector = TRUE; 215 } 216 } 217 218 if (restore_property_vector) { 219 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 220 "Couldn't unwrap some window property request vectors\n"); 221 } 222 223 amdgpu_property_vectors_wrapped = FALSE; 224} 225 226extern _X_EXPORT int gAMDGPUEntityIndex; 227 228static int getAMDGPUEntityIndex(void) 229{ 230 return gAMDGPUEntityIndex; 231} 232 233AMDGPUEntPtr AMDGPUEntPriv(ScrnInfoPtr pScrn) 234{ 235 DevUnion *pPriv; 236 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 237 pPriv = xf86GetEntityPrivate(info->pEnt->index, getAMDGPUEntityIndex()); 238 return pPriv->ptr; 239} 240 241/* Allocate our private AMDGPUInfoRec */ 242static Bool AMDGPUGetRec(ScrnInfoPtr pScrn) 243{ 244 if (pScrn->driverPrivate) 245 return TRUE; 246 247 pScrn->driverPrivate = xnfcalloc(sizeof(AMDGPUInfoRec), 1); 248 return TRUE; 249} 250 251/* Free our private AMDGPUInfoRec */ 252static void AMDGPUFreeRec(ScrnInfoPtr pScrn) 253{ 254 DevUnion *pPriv; 255 AMDGPUEntPtr pAMDGPUEnt; 256 AMDGPUInfoPtr info; 257 EntityInfoPtr pEnt; 258 259 if (!pScrn) 260 return; 261 262 pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); 263 pPriv = xf86GetEntityPrivate(pEnt->index, gAMDGPUEntityIndex); 264 pAMDGPUEnt = pPriv->ptr; 265 266 info = AMDGPUPTR(pScrn); 267 if (info) { 268 pAMDGPUEnt->scrn[info->instance_id] = NULL; 269 pAMDGPUEnt->num_scrns--; 270 free(pScrn->driverPrivate); 271 pScrn->driverPrivate = NULL; 272 } 273 274 if (pAMDGPUEnt->fd > 0) { 275 DevUnion *pPriv; 276 AMDGPUEntPtr pAMDGPUEnt; 277 pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 278 getAMDGPUEntityIndex()); 279 280 pAMDGPUEnt = pPriv->ptr; 281 pAMDGPUEnt->fd_ref--; 282 if (!pAMDGPUEnt->fd_ref) { 283 amdgpu_unwrap_property_requests(pScrn); 284 amdgpu_device_deinitialize(pAMDGPUEnt->pDev); 285 amdgpu_kernel_close_fd(pAMDGPUEnt); 286 free(pAMDGPUEnt->busid); 287 free(pPriv->ptr); 288 pPriv->ptr = NULL; 289 } 290 } 291 292 free(pEnt); 293} 294 295Bool amdgpu_window_has_variable_refresh(WindowPtr win) { 296 struct amdgpu_window_priv *priv = get_window_priv(win); 297 298 return priv->variable_refresh; 299} 300 301static void *amdgpuShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, 302 int mode, CARD32 * size, void *closure) 303{ 304 ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 305 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 306 int stride; 307 308 stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8; 309 *size = stride; 310 311 return ((uint8_t *) info->front_buffer->cpu_ptr + row * stride + offset); 312} 313 314static void 315amdgpuUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf) 316{ 317 shadowUpdatePacked(pScreen, pBuf); 318} 319 320static Bool 321callback_needs_flush(AMDGPUInfoPtr info, struct amdgpu_client_priv *client_priv) 322{ 323 return (int)(client_priv->needs_flush - info->gpu_flushed) > 0; 324} 325 326static void 327amdgpu_event_callback(CallbackListPtr *list, 328 pointer user_data, pointer call_data) 329{ 330 EventInfoRec *eventinfo = call_data; 331 ScrnInfoPtr pScrn = user_data; 332 ScreenPtr pScreen = pScrn->pScreen; 333 struct amdgpu_client_priv *client_priv = 334 dixLookupScreenPrivate(&eventinfo->client->devPrivates, 335 &amdgpu_client_private_key, pScreen); 336 struct amdgpu_client_priv *server_priv = 337 dixLookupScreenPrivate(&serverClient->devPrivates, 338 &amdgpu_client_private_key, pScreen); 339 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 340 int i; 341 342 if (callback_needs_flush(info, client_priv) || 343 callback_needs_flush(info, server_priv)) 344 return; 345 346 /* Don't let gpu_flushed get too far ahead of needs_flush, in order 347 * to prevent false positives in callback_needs_flush() 348 */ 349 client_priv->needs_flush = info->gpu_flushed; 350 server_priv->needs_flush = info->gpu_flushed; 351 352 for (i = 0; i < eventinfo->count; i++) { 353 if (eventinfo->events[i].u.u.type == info->callback_event_type) { 354 client_priv->needs_flush++; 355 server_priv->needs_flush++; 356 return; 357 } 358 } 359} 360 361static void 362amdgpu_flush_callback(CallbackListPtr *list, 363 pointer user_data, pointer call_data) 364{ 365 ScrnInfoPtr pScrn = user_data; 366 ScreenPtr pScreen = pScrn->pScreen; 367 ClientPtr client = call_data ? call_data : serverClient; 368 struct amdgpu_client_priv *client_priv = 369 dixLookupScreenPrivate(&client->devPrivates, 370 &amdgpu_client_private_key, pScreen); 371 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 372 373 if (pScrn->vtSema && callback_needs_flush(info, client_priv)) 374 amdgpu_glamor_flush(pScrn); 375} 376 377static Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen) 378{ 379 ExtensionEntry *damage_ext; 380 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 381 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 382 PixmapPtr pixmap; 383 384 pScreen->CreateScreenResources = info->CreateScreenResources; 385 if (!(*pScreen->CreateScreenResources) (pScreen)) 386 return FALSE; 387 pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS; 388 389 /* Set the RandR primary output if Xorg hasn't */ 390 if (dixPrivateKeyRegistered(rrPrivKey)) { 391 rrScrPrivPtr rrScrPriv = rrGetScrPriv(pScreen); 392 393 if (!pScreen->isGPU && !rrScrPriv->primaryOutput) { 394 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 395 396 rrScrPriv->primaryOutput = xf86_config->output[0]->randr_output; 397 RROutputChanged(rrScrPriv->primaryOutput, FALSE); 398 rrScrPriv->layoutChanged = TRUE; 399 } 400 401 drmmode_uevent_init(pScrn, &info->drmmode); 402 } 403 404 if (!drmmode_set_desired_modes(pScrn, &info->drmmode, pScreen->isGPU)) 405 return FALSE; 406 407 if (info->shadow_fb) { 408 pixmap = pScreen->GetScreenPixmap(pScreen); 409 410 if (!shadowAdd(pScreen, pixmap, amdgpuUpdatePacked, 411 amdgpuShadowWindow, 0, NULL)) 412 return FALSE; 413 } 414 415 if (info->dri2.enabled || info->use_glamor) { 416 if (info->front_buffer) { 417 PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); 418 419 if (!amdgpu_set_pixmap_bo(pPix, info->front_buffer)) 420 return FALSE; 421 } 422 } 423 424 if (info->use_glamor) 425 amdgpu_glamor_create_screen_resources(pScreen); 426 427 info->callback_event_type = -1; 428 if (!pScreen->isGPU && (damage_ext = CheckExtension("DAMAGE"))) { 429 info->callback_event_type = damage_ext->eventBase + XDamageNotify; 430 431 if (!AddCallback(&FlushCallback, amdgpu_flush_callback, pScrn)) 432 return FALSE; 433 434 if (!AddCallback(&EventCallback, amdgpu_event_callback, pScrn)) { 435 DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn); 436 return FALSE; 437 } 438 439 if (!dixRegisterScreenPrivateKey(&amdgpu_client_private_key, pScreen, 440 PRIVATE_CLIENT, sizeof(struct amdgpu_client_priv))) { 441 DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn); 442 DeleteCallback(&EventCallback, amdgpu_event_callback, pScrn); 443 return FALSE; 444 } 445 } 446 447 if (info->vrr_support && 448 !dixRegisterPrivateKey(&amdgpu_window_private_key, 449 PRIVATE_WINDOW, 450 sizeof(struct amdgpu_window_priv))) 451 return FALSE; 452 453 return TRUE; 454} 455 456static Bool 457amdgpu_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents) 458{ 459 if (xf86_crtc->scrn->is_gpu) { 460 extents->x1 -= xf86_crtc->x; 461 extents->y1 -= xf86_crtc->y; 462 extents->x2 -= xf86_crtc->x; 463 extents->y2 -= xf86_crtc->y; 464 } else { 465 extents->x1 -= xf86_crtc->filter_width >> 1; 466 extents->x2 += xf86_crtc->filter_width >> 1; 467 extents->y1 -= xf86_crtc->filter_height >> 1; 468 extents->y2 += xf86_crtc->filter_height >> 1; 469 pixman_f_transform_bounds(&xf86_crtc->f_framebuffer_to_crtc, extents); 470 } 471 472 extents->x1 = max(extents->x1, 0); 473 extents->y1 = max(extents->y1, 0); 474 extents->x2 = min(extents->x2, xf86_crtc->mode.HDisplay); 475 extents->y2 = min(extents->y2, xf86_crtc->mode.VDisplay); 476 477 return (extents->x1 < extents->x2 && extents->y1 < extents->y2); 478} 479 480static RegionPtr 481transform_region(RegionPtr region, struct pict_f_transform *transform, 482 int w, int h) 483{ 484 BoxPtr boxes = RegionRects(region); 485 int nboxes = RegionNumRects(region); 486 xRectanglePtr rects = malloc(nboxes * sizeof(*rects)); 487 RegionPtr transformed; 488 int nrects = 0; 489 BoxRec box; 490 int i; 491 492 for (i = 0; i < nboxes; i++) { 493 box.x1 = boxes[i].x1; 494 box.x2 = boxes[i].x2; 495 box.y1 = boxes[i].y1; 496 box.y2 = boxes[i].y2; 497 pixman_f_transform_bounds(transform, &box); 498 499 box.x1 = max(box.x1, 0); 500 box.y1 = max(box.y1, 0); 501 box.x2 = min(box.x2, w); 502 box.y2 = min(box.y2, h); 503 if (box.x1 >= box.x2 || box.y1 >= box.y2) 504 continue; 505 506 rects[nrects].x = box.x1; 507 rects[nrects].y = box.y1; 508 rects[nrects].width = box.x2 - box.x1; 509 rects[nrects].height = box.y2 - box.y1; 510 nrects++; 511 } 512 513 transformed = RegionFromRects(nrects, rects, CT_UNSORTED); 514 free(rects); 515 return transformed; 516} 517 518static void 519amdgpu_sync_scanout_pixmaps(xf86CrtcPtr xf86_crtc, RegionPtr new_region, 520 int scanout_id) 521{ 522 drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 523 DrawablePtr dst = &drmmode_crtc->scanout[scanout_id]->drawable; 524 DrawablePtr src = &drmmode_crtc->scanout[scanout_id ^ 1]->drawable; 525 RegionPtr last_region = &drmmode_crtc->scanout_last_region; 526 ScrnInfoPtr scrn = xf86_crtc->scrn; 527 ScreenPtr pScreen = scrn->pScreen; 528 RegionRec remaining; 529 RegionPtr sync_region = NULL; 530 BoxRec extents; 531 GCPtr gc; 532 533 if (RegionNil(last_region)) 534 return; 535 536 RegionNull(&remaining); 537 RegionSubtract(&remaining, last_region, new_region); 538 if (RegionNil(&remaining)) 539 goto uninit; 540 541 extents = *RegionExtents(&remaining); 542 if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents)) 543 goto uninit; 544 545 if (xf86_crtc->driverIsPerformingTransform) { 546 sync_region = transform_region(&remaining, 547 &xf86_crtc->f_framebuffer_to_crtc, 548 dst->width, dst->height); 549 } else { 550 sync_region = RegionDuplicate(&remaining); 551 RegionTranslate(sync_region, -xf86_crtc->x, -xf86_crtc->y); 552 } 553 554 gc = GetScratchGC(dst->depth, pScreen); 555 if (gc) { 556 gc->funcs->ChangeClip(gc, CT_REGION, sync_region, 0); 557 ValidateGC(dst, gc); 558 sync_region = NULL; 559 gc->ops->CopyArea(src, dst, gc, 0, 0, dst->width, dst->height, 0, 0); 560 FreeScratchGC(gc); 561 } 562 563 uninit: 564 if (sync_region) 565 RegionDestroy(sync_region); 566 RegionUninit(&remaining); 567} 568 569static void 570amdgpu_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data) 571{ 572 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn); 573 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 574 struct drmmode_fb *fb = event_data; 575 576 drmmode_crtc->scanout_update_pending = 0; 577 578 if (drmmode_crtc->flip_pending == fb) { 579 drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending, 580 NULL); 581 } 582} 583 584static void 585amdgpu_scanout_flip_handler(xf86CrtcPtr crtc, uint32_t msc, uint64_t usec, 586 void *event_data) 587{ 588 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn); 589 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 590 struct drmmode_fb *fb = event_data; 591 592 drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb, fb); 593 amdgpu_scanout_flip_abort(crtc, event_data); 594} 595 596 597static RegionPtr 598dirty_region(PixmapDirtyUpdatePtr dirty) 599{ 600 RegionPtr damageregion = DamageRegion(dirty->damage); 601 RegionPtr dstregion; 602 603#ifdef HAS_DIRTYTRACKING_ROTATION 604 if (dirty->rotation != RR_Rotate_0) { 605 dstregion = transform_region(damageregion, 606 &dirty->f_inverse, 607 dirty->secondary_dst->drawable.width, 608 dirty->secondary_dst->drawable.height); 609 } else 610#endif 611 { 612 RegionRec pixregion; 613 614 dstregion = RegionDuplicate(damageregion); 615 RegionTranslate(dstregion, -dirty->x, -dirty->y); 616 PixmapRegionInit(&pixregion, dirty->secondary_dst); 617 RegionIntersect(dstregion, dstregion, &pixregion); 618 RegionUninit(&pixregion); 619 } 620 621 return dstregion; 622} 623 624static void 625redisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region) 626{ 627 ScrnInfoPtr src_scrn = 628 xf86ScreenToScrn(amdgpu_dirty_src_drawable(dirty)->pScreen); 629 630 if (RegionNil(region)) 631 goto out; 632 633 if (dirty->secondary_dst->primary_pixmap) 634 DamageRegionAppend(&dirty->secondary_dst->drawable, region); 635 636#ifdef HAS_DIRTYTRACKING_ROTATION 637 PixmapSyncDirtyHelper(dirty); 638#else 639 PixmapSyncDirtyHelper(dirty, region); 640#endif 641 642 amdgpu_glamor_flush(src_scrn); 643 if (dirty->secondary_dst->primary_pixmap) 644 DamageRegionProcessPending(&dirty->secondary_dst->drawable); 645 646out: 647 DamageEmpty(dirty->damage); 648} 649 650static void 651amdgpu_prime_scanout_update_abort(xf86CrtcPtr crtc, void *event_data) 652{ 653 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 654 655 drmmode_crtc->scanout_update_pending = 0; 656} 657 658void 659amdgpu_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) 660{ 661 ScreenPtr primary_screen = amdgpu_dirty_primary(dirty); 662 PixmapDirtyUpdatePtr ent; 663 RegionPtr region; 664 665 xorg_list_for_each_entry(ent, &primary_screen->pixmap_dirty_list, ent) { 666 if (!amdgpu_dirty_src_equals(dirty, ent->secondary_dst)) 667 continue; 668 669 region = dirty_region(ent); 670 redisplay_dirty(ent, region); 671 RegionDestroy(region); 672 } 673} 674 675 676#if HAS_SYNC_SHARED_PIXMAP 677 678static Bool 679primary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) 680{ 681 ScreenPtr primary_screen = amdgpu_dirty_primary(dirty); 682 683 return primary_screen->SyncSharedPixmap != NULL; 684} 685 686static Bool 687secondary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) 688{ 689 ScreenPtr secondary_screen = dirty->secondary_dst->drawable.pScreen; 690 691 return secondary_screen->SyncSharedPixmap != NULL; 692} 693 694static void 695call_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) 696{ 697 ScreenPtr primary_screen = amdgpu_dirty_primary(dirty); 698 699 primary_screen->SyncSharedPixmap(dirty); 700} 701 702#else /* !HAS_SYNC_SHARED_PIXMAP */ 703 704static Bool 705primary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) 706{ 707 ScrnInfoPtr primary_scrn = xf86ScreenToScrn(amdgpu_dirty_primary(dirty)); 708 709 return primary_scrn->driverName == scrn->driverName; 710} 711 712static Bool 713secondary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) 714{ 715 ScrnInfoPtr secondary_scrn = xf86ScreenToScrn(dirty->secondary_dst->drawable.pScreen); 716 717 return secondary_scrn->driverName == scrn->driverName; 718} 719 720static void 721call_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) 722{ 723 amdgpu_sync_shared_pixmap(dirty); 724} 725 726#endif /* HAS_SYNC_SHARED_PIXMAPS */ 727 728 729static xf86CrtcPtr 730amdgpu_prime_dirty_to_crtc(PixmapDirtyUpdatePtr dirty) 731{ 732 ScreenPtr screen = dirty->secondary_dst->drawable.pScreen; 733 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 734 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 735 int c; 736 737 /* Find the CRTC which is scanning out from this secondary pixmap */ 738 for (c = 0; c < xf86_config->num_crtc; c++) { 739 xf86CrtcPtr xf86_crtc = xf86_config->crtc[c]; 740 drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 741 742 if (amdgpu_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) 743 return xf86_crtc; 744 } 745 746 return NULL; 747} 748 749static Bool 750amdgpu_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id) 751{ 752 ScrnInfoPtr scrn = crtc->scrn; 753 ScreenPtr screen = scrn->pScreen; 754 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 755 PixmapDirtyUpdatePtr dirty; 756 Bool ret = FALSE; 757 758 xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) { 759 if (amdgpu_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) { 760 RegionPtr region; 761 762 if (primary_has_sync_shared_pixmap(scrn, dirty)) 763 call_sync_shared_pixmap(dirty); 764 765 region = dirty_region(dirty); 766 if (RegionNil(region)) 767 goto destroy; 768 769 if (drmmode_crtc->tear_free) { 770 RegionTranslate(region, crtc->x, crtc->y); 771 amdgpu_sync_scanout_pixmaps(crtc, region, scanout_id); 772 amdgpu_glamor_flush(scrn); 773 RegionCopy(&drmmode_crtc->scanout_last_region, region); 774 RegionTranslate(region, -crtc->x, -crtc->y); 775 dirty->secondary_dst = drmmode_crtc->scanout[scanout_id]; 776 } 777 778 redisplay_dirty(dirty, region); 779 ret = TRUE; 780 destroy: 781 RegionDestroy(region); 782 break; 783 } 784 } 785 786 return ret; 787} 788 789static void 790amdgpu_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, 791 void *event_data) 792{ 793 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 794 795 amdgpu_prime_scanout_do_update(crtc, 0); 796 drmmode_crtc->scanout_update_pending = 0; 797} 798 799static void 800amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty) 801{ 802 ScreenPtr screen = dirty->secondary_dst->drawable.pScreen; 803 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 804 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 805 xf86CrtcPtr xf86_crtc = amdgpu_prime_dirty_to_crtc(dirty); 806 drmmode_crtc_private_ptr drmmode_crtc; 807 uintptr_t drm_queue_seq; 808 809 if (!xf86_crtc || !xf86_crtc->enabled) 810 return; 811 812 drmmode_crtc = xf86_crtc->driver_private; 813 if (drmmode_crtc->scanout_update_pending || 814 !drmmode_crtc->scanout[drmmode_crtc->scanout_id] || 815 drmmode_crtc->dpms_mode != DPMSModeOn) 816 return; 817 818 drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc, 819 AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, 820 AMDGPU_DRM_QUEUE_ID_DEFAULT, NULL, 821 amdgpu_prime_scanout_update_handler, 822 amdgpu_prime_scanout_update_abort, 823 FALSE); 824 if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) { 825 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 826 "amdgpu_drm_queue_alloc failed for PRIME update\n"); 827 amdgpu_prime_scanout_update_handler(xf86_crtc, 0, 0, NULL); 828 return; 829 } 830 831 drmmode_crtc->scanout_update_pending = drm_queue_seq; 832 833 if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, 834 1, drm_queue_seq, NULL, NULL)) { 835 if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_VBLANK_FAILED)) { 836 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 837 "drmmode_wait_vblank failed for PRIME update: %s\n", 838 strerror(errno)); 839 drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_VBLANK_FAILED; 840 } 841 842 drmmode_crtc->drmmode->event_context.vblank_handler(pAMDGPUEnt->fd, 843 0, 0, 0, 844 (void*)drm_queue_seq); 845 drmmode_crtc->wait_flip_nesting_level++; 846 amdgpu_drm_queue_handle_deferred(xf86_crtc); 847 return; 848 } 849 850 if (drmmode_crtc->scanout_status == 851 (DRMMODE_SCANOUT_FLIP_FAILED | DRMMODE_SCANOUT_VBLANK_FAILED)) { 852 /* The page flip and vblank ioctls failed before, but the vblank 853 * ioctl is working again, so we can try re-enabling TearFree 854 */ 855 xf86_crtc->funcs->set_mode_major(xf86_crtc, &xf86_crtc->mode, 856 xf86_crtc->rotation, 857 xf86_crtc->x, xf86_crtc->y); 858 } 859 860 drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_VBLANK_FAILED; 861} 862 863static void 864amdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent) 865{ 866 ScreenPtr screen = ent->secondary_dst->drawable.pScreen; 867 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 868 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 869 xf86CrtcPtr crtc = amdgpu_prime_dirty_to_crtc(ent); 870 drmmode_crtc_private_ptr drmmode_crtc; 871 uintptr_t drm_queue_seq; 872 unsigned scanout_id; 873 struct drmmode_fb *fb; 874 875 if (!crtc || !crtc->enabled) 876 return; 877 878 drmmode_crtc = crtc->driver_private; 879 scanout_id = drmmode_crtc->scanout_id ^ 1; 880 if (drmmode_crtc->scanout_update_pending || 881 !drmmode_crtc->scanout[scanout_id] || 882 drmmode_crtc->dpms_mode != DPMSModeOn) 883 return; 884 885 if (!amdgpu_prime_scanout_do_update(crtc, scanout_id)) 886 return; 887 888 fb = amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id]); 889 if (!fb) { 890 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 891 "Failed to get FB for PRIME flip.\n"); 892 return; 893 } 894 895 drm_queue_seq = amdgpu_drm_queue_alloc(crtc, 896 AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, 897 AMDGPU_DRM_QUEUE_ID_DEFAULT, fb, 898 amdgpu_scanout_flip_handler, 899 amdgpu_scanout_flip_abort, TRUE); 900 if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) { 901 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 902 "Allocating DRM event queue entry failed for PRIME flip.\n"); 903 return; 904 } 905 906 if (drmmode_page_flip_target_relative(pAMDGPUEnt, drmmode_crtc, 907 fb->handle, 0, drm_queue_seq, 1) 908 != 0) { 909 if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED)) { 910 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 911 "flip queue failed in %s: %s, TearFree inactive\n", 912 __func__, strerror(errno)); 913 drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_FLIP_FAILED; 914 } 915 916 amdgpu_drm_abort_entry(drm_queue_seq); 917 return; 918 } 919 920 if (drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED) { 921 xf86DrvMsg(scrn->scrnIndex, X_INFO, "TearFree active again\n"); 922 drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_FLIP_FAILED; 923 } 924 925 drmmode_crtc->scanout_id = scanout_id; 926 drmmode_crtc->scanout_update_pending = drm_queue_seq; 927 drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending, fb); 928} 929 930static void 931amdgpu_dirty_update(ScrnInfoPtr scrn) 932{ 933 ScreenPtr screen = scrn->pScreen; 934 PixmapDirtyUpdatePtr ent; 935 RegionPtr region; 936 937 xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) { 938 if (screen->isGPU) { 939 PixmapDirtyUpdatePtr region_ent = ent; 940 941 if (primary_has_sync_shared_pixmap(scrn, ent)) { 942 ScreenPtr primary_screen = amdgpu_dirty_primary(ent); 943 944 xorg_list_for_each_entry(region_ent, &primary_screen->pixmap_dirty_list, ent) { 945 if (amdgpu_dirty_src_equals(ent, region_ent->secondary_dst)) 946 break; 947 } 948 } 949 950 region = dirty_region(region_ent); 951 952 if (RegionNotEmpty(region)) { 953 xf86CrtcPtr crtc = amdgpu_prime_dirty_to_crtc(ent); 954 drmmode_crtc_private_ptr drmmode_crtc = NULL; 955 956 if (crtc) 957 drmmode_crtc = crtc->driver_private; 958 959 if (drmmode_crtc && drmmode_crtc->tear_free) 960 amdgpu_prime_scanout_flip(ent); 961 else 962 amdgpu_prime_scanout_update(ent); 963 } else { 964 DamageEmpty(region_ent->damage); 965 } 966 967 RegionDestroy(region); 968 } else { 969 if (secondary_has_sync_shared_pixmap(scrn, ent)) 970 continue; 971 972 region = dirty_region(ent); 973 redisplay_dirty(ent, region); 974 RegionDestroy(region); 975 } 976 } 977} 978 979static void 980amdgpuSourceValidate(DrawablePtr draw, int x, int y, int w, int h, 981 unsigned int subWindowMode) 982{ 983} 984 985Bool 986amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id, 987 PixmapPtr src_pix, BoxRec extents) 988{ 989 drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 990 RegionRec region = { .extents = extents, .data = NULL }; 991 ScrnInfoPtr scrn = xf86_crtc->scrn; 992 ScreenPtr pScreen = scrn->pScreen; 993 DrawablePtr pDraw; 994 995 if (!xf86_crtc->enabled || 996 !drmmode_crtc->scanout[scanout_id] || 997 extents.x1 >= extents.x2 || extents.y1 >= extents.y2) 998 return FALSE; 999 1000 pDraw = &drmmode_crtc->scanout[scanout_id]->drawable; 1001 if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents)) 1002 return FALSE; 1003 1004 if (drmmode_crtc->tear_free) { 1005 amdgpu_sync_scanout_pixmaps(xf86_crtc, ®ion, scanout_id); 1006 RegionCopy(&drmmode_crtc->scanout_last_region, ®ion); 1007 } 1008 1009 if (xf86_crtc->driverIsPerformingTransform) { 1010 SourceValidateProcPtr SourceValidate = pScreen->SourceValidate; 1011 PictFormatPtr format = PictureWindowFormat(pScreen->root); 1012 int error; 1013 PicturePtr src, dst; 1014 1015 src = CreatePicture(None, &src_pix->drawable, format, 0L, NULL, 1016 serverClient, &error); 1017 if (!src) { 1018 ErrorF("Failed to create source picture for transformed scanout " 1019 "update\n"); 1020 goto out; 1021 } 1022 1023 dst = CreatePicture(None, pDraw, format, 0L, NULL, serverClient, &error); 1024 if (!dst) { 1025 ErrorF("Failed to create destination picture for transformed scanout " 1026 "update\n"); 1027 goto free_src; 1028 } 1029 error = SetPictureTransform(src, &xf86_crtc->crtc_to_framebuffer); 1030 if (error) { 1031 ErrorF("SetPictureTransform failed for transformed scanout " 1032 "update\n"); 1033 goto free_dst; 1034 } 1035 1036 if (xf86_crtc->filter) 1037 SetPicturePictFilter(src, xf86_crtc->filter, xf86_crtc->params, 1038 xf86_crtc->nparams); 1039 1040 pScreen->SourceValidate = amdgpuSourceValidate; 1041 CompositePicture(PictOpSrc, 1042 src, NULL, dst, 1043 extents.x1, extents.y1, 0, 0, extents.x1, 1044 extents.y1, extents.x2 - extents.x1, 1045 extents.y2 - extents.y1); 1046 pScreen->SourceValidate = SourceValidate; 1047 1048 free_dst: 1049 FreePicture(dst, None); 1050 free_src: 1051 FreePicture(src, None); 1052 } else 1053 out: 1054 { 1055 GCPtr gc = GetScratchGC(pDraw->depth, pScreen); 1056 1057 ValidateGC(pDraw, gc); 1058 (*gc->ops->CopyArea)(&src_pix->drawable, pDraw, gc, 1059 xf86_crtc->x + extents.x1, xf86_crtc->y + extents.y1, 1060 extents.x2 - extents.x1, extents.y2 - extents.y1, 1061 extents.x1, extents.y1); 1062 FreeScratchGC(gc); 1063 } 1064 1065 return TRUE; 1066} 1067 1068static void 1069amdgpu_scanout_update_abort(xf86CrtcPtr crtc, void *event_data) 1070{ 1071 drmmode_crtc_private_ptr drmmode_crtc = event_data; 1072 1073 drmmode_crtc->scanout_update_pending = 0; 1074} 1075 1076static void 1077amdgpu_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, 1078 void *event_data) 1079{ 1080 drmmode_crtc_private_ptr drmmode_crtc = event_data; 1081 ScreenPtr screen = crtc->scrn->pScreen; 1082 RegionPtr region = DamageRegion(drmmode_crtc->scanout_damage); 1083 1084 if (crtc->enabled && 1085 !drmmode_crtc->flip_pending && 1086 drmmode_crtc->dpms_mode == DPMSModeOn) { 1087 if (amdgpu_scanout_do_update(crtc, drmmode_crtc->scanout_id, 1088 screen->GetWindowPixmap(screen->root), 1089 region->extents)) { 1090 amdgpu_glamor_flush(crtc->scrn); 1091 RegionEmpty(region); 1092 } 1093 } 1094 1095 amdgpu_scanout_update_abort(crtc, event_data); 1096} 1097 1098static void 1099amdgpu_scanout_update(xf86CrtcPtr xf86_crtc) 1100{ 1101 drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 1102 ScrnInfoPtr scrn = xf86_crtc->scrn; 1103 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 1104 uintptr_t drm_queue_seq; 1105 DamagePtr pDamage; 1106 RegionPtr pRegion; 1107 BoxRec extents; 1108 1109 if (!xf86_crtc->enabled || 1110 drmmode_crtc->scanout_update_pending || 1111 drmmode_crtc->flip_pending || 1112 drmmode_crtc->dpms_mode != DPMSModeOn) 1113 return; 1114 1115 pDamage = drmmode_crtc->scanout_damage; 1116 if (!pDamage) 1117 return; 1118 1119 pRegion = DamageRegion(pDamage); 1120 if (!RegionNotEmpty(pRegion)) 1121 return; 1122 1123 extents = *RegionExtents(pRegion); 1124 if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents)) { 1125 RegionEmpty(pRegion); 1126 return; 1127 } 1128 1129 drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc, 1130 AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, 1131 AMDGPU_DRM_QUEUE_ID_DEFAULT, 1132 drmmode_crtc, 1133 amdgpu_scanout_update_handler, 1134 amdgpu_scanout_update_abort, 1135 FALSE); 1136 if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) { 1137 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1138 "amdgpu_drm_queue_alloc failed for scanout update\n"); 1139 amdgpu_scanout_update_handler(xf86_crtc, 0, 0, drmmode_crtc); 1140 return; 1141 } 1142 1143 drmmode_crtc->scanout_update_pending = drm_queue_seq; 1144 1145 if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, 1146 1, drm_queue_seq, NULL, NULL)) { 1147 if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_VBLANK_FAILED)) { 1148 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1149 "drmmode_wait_vblank failed for scanout update: %s\n", 1150 strerror(errno)); 1151 drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_VBLANK_FAILED; 1152 } 1153 1154 drmmode_crtc->drmmode->event_context.vblank_handler(pAMDGPUEnt->fd, 1155 0, 0, 0, 1156 (void*)drm_queue_seq); 1157 drmmode_crtc->wait_flip_nesting_level++; 1158 amdgpu_drm_queue_handle_deferred(xf86_crtc); 1159 return; 1160 } 1161 1162 if (drmmode_crtc->scanout_status == 1163 (DRMMODE_SCANOUT_FLIP_FAILED | DRMMODE_SCANOUT_VBLANK_FAILED)) { 1164 /* The page flip and vblank ioctls failed before, but the vblank 1165 * ioctl is working again, so we can try re-enabling TearFree 1166 */ 1167 xf86_crtc->funcs->set_mode_major(xf86_crtc, &xf86_crtc->mode, 1168 xf86_crtc->rotation, 1169 xf86_crtc->x, xf86_crtc->y); 1170 } 1171 1172 drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_VBLANK_FAILED; 1173} 1174 1175static void 1176amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info, 1177 xf86CrtcPtr xf86_crtc) 1178{ 1179 drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 1180 RegionPtr region = DamageRegion(drmmode_crtc->scanout_damage); 1181 ScrnInfoPtr scrn = xf86_crtc->scrn; 1182 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 1183 uintptr_t drm_queue_seq; 1184 unsigned scanout_id; 1185 struct drmmode_fb *fb; 1186 1187 if (drmmode_crtc->scanout_update_pending || 1188 drmmode_crtc->flip_pending || 1189 drmmode_crtc->dpms_mode != DPMSModeOn) 1190 return; 1191 1192 scanout_id = drmmode_crtc->scanout_id ^ 1; 1193 if (!amdgpu_scanout_do_update(xf86_crtc, scanout_id, 1194 pScreen->GetWindowPixmap(pScreen->root), 1195 region->extents)) 1196 return; 1197 1198 amdgpu_glamor_flush(scrn); 1199 RegionEmpty(region); 1200 1201 fb = amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id]); 1202 if (!fb) { 1203 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1204 "Failed to get FB for scanout flip.\n"); 1205 return; 1206 } 1207 1208 drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc, 1209 AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, 1210 AMDGPU_DRM_QUEUE_ID_DEFAULT, fb, 1211 amdgpu_scanout_flip_handler, 1212 amdgpu_scanout_flip_abort, TRUE); 1213 if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) { 1214 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1215 "Allocating DRM event queue entry failed.\n"); 1216 return; 1217 } 1218 1219 if (drmmode_page_flip_target_relative(pAMDGPUEnt, drmmode_crtc, 1220 fb->handle, 0, drm_queue_seq, 1) 1221 != 0) { 1222 if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED)) { 1223 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1224 "flip queue failed in %s: %s, TearFree inactive\n", 1225 __func__, strerror(errno)); 1226 drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_FLIP_FAILED; 1227 } 1228 1229 amdgpu_drm_abort_entry(drm_queue_seq); 1230 RegionCopy(DamageRegion(drmmode_crtc->scanout_damage), 1231 &drmmode_crtc->scanout_last_region); 1232 RegionEmpty(&drmmode_crtc->scanout_last_region); 1233 amdgpu_scanout_update(xf86_crtc); 1234 drmmode_crtc_scanout_destroy(&drmmode_crtc->scanout[scanout_id]); 1235 drmmode_crtc->tear_free = FALSE; 1236 return; 1237 } 1238 1239 if (drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED) { 1240 xf86DrvMsg(scrn->scrnIndex, X_INFO, "TearFree active again\n"); 1241 drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_FLIP_FAILED; 1242 } 1243 1244 drmmode_crtc->scanout_id = scanout_id; 1245 drmmode_crtc->scanout_update_pending = drm_queue_seq; 1246 drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending, fb); 1247} 1248 1249static void AMDGPUBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL) 1250{ 1251 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1252 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1253 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1254 int c; 1255 1256 pScreen->BlockHandler = info->BlockHandler; 1257 (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); 1258 pScreen->BlockHandler = AMDGPUBlockHandler_KMS; 1259 1260 if (!xf86ScreenToScrn(amdgpu_primary_screen(pScreen))->vtSema) 1261 return; 1262 1263 if (!pScreen->isGPU) 1264 { 1265 for (c = 0; c < xf86_config->num_crtc; c++) { 1266 xf86CrtcPtr crtc = xf86_config->crtc[c]; 1267 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1268 1269 if (drmmode_crtc->rotate) 1270 continue; 1271 1272 if (drmmode_crtc->tear_free) 1273 amdgpu_scanout_flip(pScreen, info, crtc); 1274 else if (drmmode_crtc->scanout[drmmode_crtc->scanout_id]) 1275 amdgpu_scanout_update(crtc); 1276 } 1277 } 1278 1279#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,19,0,0,0) 1280 if (info->use_glamor) 1281 amdgpu_glamor_flush(pScrn); 1282#endif 1283 1284 amdgpu_dirty_update(pScrn); 1285} 1286 1287/* This is called by AMDGPUPreInit to set up the default visual */ 1288static Bool AMDGPUPreInitVisual(ScrnInfoPtr pScrn) 1289{ 1290 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1291 1292 if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) 1293 return FALSE; 1294 1295 switch (pScrn->depth) { 1296 case 8: 1297 case 15: 1298 case 16: 1299 case 24: 1300 case 30: 1301 break; 1302 1303 default: 1304 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1305 "Given depth (%d) is not supported by %s driver\n", 1306 pScrn->depth, AMDGPU_DRIVER_NAME); 1307 return FALSE; 1308 } 1309 1310 xf86PrintDepthBpp(pScrn); 1311 1312 info->pix24bpp = xf86GetBppFromDepth(pScrn, pScrn->depth); 1313 info->pixel_bytes = pScrn->bitsPerPixel / 8; 1314 1315 if (info->pix24bpp == 24) { 1316 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1317 "Amdgpu does NOT support 24bpp\n"); 1318 return FALSE; 1319 } 1320 1321 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1322 "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n", 1323 pScrn->depth, 1324 info->pixel_bytes, 1325 info->pixel_bytes > 1 ? "s" : "", info->pix24bpp); 1326 1327 if (!xf86SetDefaultVisual(pScrn, -1)) 1328 return FALSE; 1329 1330 if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 1331 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1332 "Default visual (%s) is not supported at depth %d\n", 1333 xf86GetVisualName(pScrn->defaultVisual), 1334 pScrn->depth); 1335 return FALSE; 1336 } 1337 return TRUE; 1338} 1339 1340/* This is called by AMDGPUPreInit to handle all color weight issues */ 1341static Bool AMDGPUPreInitWeight(ScrnInfoPtr pScrn) 1342{ 1343 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1344 1345 /* Save flag for 6 bit DAC to use for 1346 setting CRTC registers. Otherwise use 1347 an 8 bit DAC, even if xf86SetWeight sets 1348 pScrn->rgbBits to some value other than 1349 8. */ 1350 info->dac6bits = FALSE; 1351 1352 if (pScrn->depth > 8) { 1353 rgb defaultWeight = { 0, 0, 0 }; 1354 1355 if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) 1356 return FALSE; 1357 } else { 1358 pScrn->rgbBits = 8; 1359 } 1360 1361 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1362 "Using %d bits per RGB (%d bit DAC)\n", 1363 pScrn->rgbBits, info->dac6bits ? 6 : 8); 1364 1365 return TRUE; 1366} 1367 1368static Bool AMDGPUPreInitAccel_KMS(ScrnInfoPtr pScrn) 1369{ 1370 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1371 1372 if (xf86ReturnOptValBool(info->Options, OPTION_ACCEL, TRUE)) { 1373 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1374 Bool use_glamor = TRUE; 1375#ifdef HAVE_GBM_BO_USE_LINEAR 1376 const char *accel_method; 1377 1378 accel_method = xf86GetOptValString(info->Options, OPTION_ACCEL_METHOD); 1379 if ((accel_method && !strcmp(accel_method, "none"))) 1380 use_glamor = FALSE; 1381#endif 1382 1383#ifdef DRI2 1384 info->dri2.available = ! !xf86LoadSubModule(pScrn, "dri2"); 1385#endif 1386 1387 if (info->dri2.available) 1388 info->gbm = gbm_create_device(pAMDGPUEnt->fd); 1389 1390 if (info->gbm) { 1391 if (use_glamor) { 1392 if (amdgpu_glamor_pre_init(pScrn)) 1393 return TRUE; 1394 1395 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1396 "amdgpu_glamor_pre_init returned " 1397 "FALSE, using ShadowFB\n"); 1398 } 1399 } else { 1400 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1401 "gbm_create_device returned NULL, using " 1402 "ShadowFB\n"); 1403 } 1404 } else { 1405 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1406 "GPU acceleration disabled, using ShadowFB\n"); 1407 } 1408 1409 if (!xf86LoadSubModule(pScrn, "shadow")) 1410 return FALSE; 1411 1412 info->dri2.available = FALSE; 1413 info->shadow_fb = TRUE; 1414 return TRUE; 1415} 1416 1417static Bool AMDGPUPreInitChipType_KMS(ScrnInfoPtr pScrn, 1418 struct amdgpu_gpu_info *gpu_info) 1419{ 1420 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1421 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1422 1423 pScrn->chipset = (char*)amdgpu_get_marketing_name(pAMDGPUEnt->pDev); 1424 if (!pScrn->chipset) 1425 pScrn->chipset = "Unknown AMD Radeon GPU"; 1426 1427 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1428 "Chipset: \"%s\" (ChipID = 0x%04x)\n", 1429 pScrn->chipset, gpu_info->asic_id); 1430 1431 info->family = gpu_info->family_id; 1432 1433 return TRUE; 1434} 1435 1436static Bool amdgpu_get_tile_config(AMDGPUInfoPtr info, 1437 struct amdgpu_gpu_info *gpu_info) 1438{ 1439 switch ((gpu_info->gb_addr_cfg & 0x70) >> 4) { 1440 case 0: 1441 info->group_bytes = 256; 1442 break; 1443 case 1: 1444 info->group_bytes = 512; 1445 break; 1446 default: 1447 return FALSE; 1448 } 1449 1450 info->have_tiling_info = TRUE; 1451 return TRUE; 1452} 1453 1454static void AMDGPUSetupCapabilities(ScrnInfoPtr pScrn) 1455{ 1456 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1457 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1458 uint64_t value; 1459 int ret; 1460 1461 pScrn->capabilities = 0; 1462 1463 /* PRIME offloading requires acceleration */ 1464 if (!info->use_glamor) 1465 return; 1466 1467 ret = drmGetCap(pAMDGPUEnt->fd, DRM_CAP_PRIME, &value); 1468 if (ret == 0) { 1469 if (value & DRM_PRIME_CAP_EXPORT) 1470 pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SourceOffload; 1471 if (value & DRM_PRIME_CAP_IMPORT) { 1472 pScrn->capabilities |= RR_Capability_SinkOffload; 1473 if (info->drmmode.count_crtcs) 1474 pScrn->capabilities |= RR_Capability_SinkOutput; 1475 } 1476 } 1477} 1478 1479/* When the root window is created, initialize the screen contents from 1480 * console if -background none was specified on the command line 1481 */ 1482static Bool AMDGPUCreateWindow_oneshot(WindowPtr pWin) 1483{ 1484 ScreenPtr pScreen = pWin->drawable.pScreen; 1485 ScrnInfoPtr pScrn; 1486 AMDGPUInfoPtr info; 1487 Bool ret; 1488 1489 if (pWin != pScreen->root) 1490 ErrorF("%s called for non-root window %p\n", __func__, pWin); 1491 1492 pScrn = xf86ScreenToScrn(pScreen); 1493 info = AMDGPUPTR(pScrn); 1494 pScreen->CreateWindow = info->CreateWindow; 1495 ret = pScreen->CreateWindow(pWin); 1496 1497 if (ret) 1498 drmmode_copy_fb(pScrn, &info->drmmode); 1499 1500 return ret; 1501} 1502 1503/* When the root window is mapped, set the initial modes */ 1504void AMDGPUWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion 1505#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0) 1506 , RegionPtr pBSRegion 1507#endif 1508 ) 1509{ 1510 ScreenPtr pScreen = pWin->drawable.pScreen; 1511 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1512 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1513 1514 if (pWin != pScreen->root) 1515 ErrorF("%s called for non-root window %p\n", __func__, pWin); 1516 1517 pScreen->WindowExposures = info->WindowExposures; 1518#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0) 1519 pScreen->WindowExposures(pWin, pRegion, pBSRegion); 1520#else 1521 pScreen->WindowExposures(pWin, pRegion); 1522#endif 1523 1524 amdgpu_glamor_finish(pScrn); 1525 drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE); 1526} 1527 1528Bool AMDGPUPreInit_KMS(ScrnInfoPtr pScrn, int flags) 1529{ 1530 AMDGPUInfoPtr info; 1531 AMDGPUEntPtr pAMDGPUEnt; 1532 struct amdgpu_gpu_info gpu_info; 1533 MessageType from; 1534 Gamma zeros = { 0.0, 0.0, 0.0 }; 1535 int cpp; 1536 uint64_t heap_size = 0; 1537 uint64_t max_allocation = 0; 1538 1539 if (flags & PROBE_DETECT) 1540 return TRUE; 1541 1542 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1543 "AMDGPUPreInit_KMS\n"); 1544 if (pScrn->numEntities != 1) 1545 return FALSE; 1546 1547 pAMDGPUEnt = xf86GetEntityPrivate(pScrn->entityList[0], 1548 getAMDGPUEntityIndex())->ptr; 1549 1550 if (!AMDGPUGetRec(pScrn)) 1551 return FALSE; 1552 1553 info = AMDGPUPTR(pScrn); 1554 info->instance_id = pAMDGPUEnt->num_scrns++; 1555 pAMDGPUEnt->scrn[info->instance_id] = pScrn; 1556 1557 info->pEnt = 1558 xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); 1559 if (info->pEnt->location.type != BUS_PCI 1560#ifdef XSERVER_PLATFORM_BUS 1561 && info->pEnt->location.type != BUS_PLATFORM 1562#endif 1563 ) 1564 return FALSE; 1565 1566 if (xf86IsEntityShared(pScrn->entityList[0]) && 1567 info->instance_id == 0) { 1568 xf86SetPrimInitDone(pScrn->entityList[0]); 1569 } 1570 1571 pScrn->monitor = pScrn->confScreen->monitor; 1572 1573 if (!AMDGPUPreInitVisual(pScrn)) 1574 return FALSE; 1575 1576 xf86CollectOptions(pScrn, NULL); 1577 if (!(info->Options = malloc(sizeof(AMDGPUOptions_KMS)))) 1578 return FALSE; 1579 1580 memcpy(info->Options, AMDGPUOptions_KMS, sizeof(AMDGPUOptions_KMS)); 1581 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options); 1582 1583 if (!AMDGPUPreInitWeight(pScrn)) 1584 return FALSE; 1585 1586 memset(&gpu_info, 0, sizeof(gpu_info)); 1587 amdgpu_query_gpu_info(pAMDGPUEnt->pDev, &gpu_info); 1588 1589 if (!AMDGPUPreInitChipType_KMS(pScrn, &gpu_info)) 1590 return FALSE; 1591 1592 info->dri2.available = FALSE; 1593 info->dri2.enabled = FALSE; 1594 info->dri2.pKernelDRMVersion = drmGetVersion(pAMDGPUEnt->fd); 1595 if (info->dri2.pKernelDRMVersion == NULL) { 1596 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1597 "AMDGPUDRIGetVersion failed to get the DRM version\n"); 1598 return FALSE; 1599 } 1600 1601 /* Get ScreenInit function */ 1602 if (!xf86LoadSubModule(pScrn, "fb")) 1603 return FALSE; 1604 1605 if (!AMDGPUPreInitAccel_KMS(pScrn)) 1606 return FALSE; 1607 1608 amdgpu_drm_queue_init(pScrn); 1609 1610 /* don't enable tiling if accel is not enabled */ 1611 if (info->use_glamor) { 1612 /* set default group bytes, overridden by kernel info below */ 1613 info->group_bytes = 256; 1614 info->have_tiling_info = FALSE; 1615 amdgpu_get_tile_config(info, &gpu_info); 1616 } 1617 1618 if (info->use_glamor) { 1619 from = X_DEFAULT; 1620 1621 info->tear_free = 2; 1622 if (xf86GetOptValBool(info->Options, OPTION_TEAR_FREE, 1623 &info->tear_free)) 1624 from = X_CONFIG; 1625 xf86DrvMsg(pScrn->scrnIndex, from, "TearFree property default: %s\n", 1626 info->tear_free == 2 ? "auto" : (info->tear_free ? "on" : "off")); 1627 1628 info->shadow_primary = 1629 xf86ReturnOptValBool(info->Options, OPTION_SHADOW_PRIMARY, FALSE); 1630 1631 if (info->shadow_primary) 1632 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowPrimary enabled\n"); 1633 1634 if (!pScrn->is_gpu) { 1635 from = xf86GetOptValBool(info->Options, OPTION_VARIABLE_REFRESH, 1636 &info->vrr_support) ? X_CONFIG : X_DEFAULT; 1637 1638 xf86DrvMsg(pScrn->scrnIndex, from, "VariableRefresh: %sabled\n", 1639 info->vrr_support ? "en" : "dis"); 1640 } 1641 } 1642 1643 if (!pScrn->is_gpu) { 1644 info->allowPageFlip = xf86ReturnOptValBool(info->Options, 1645 OPTION_PAGE_FLIP, 1646 TRUE); 1647 if (info->shadow_primary) { 1648 xf86DrvMsg(pScrn->scrnIndex, 1649 info->allowPageFlip ? X_WARNING : X_DEFAULT, 1650 "KMS Pageflipping: disabled%s\n", 1651 info->allowPageFlip ? 1652 " because of ShadowPrimary" : ""); 1653 info->allowPageFlip = FALSE; 1654 } else { 1655 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1656 "KMS Pageflipping: %sabled\n", 1657 info->allowPageFlip ? "en" : "dis"); 1658 } 1659 } 1660 1661 if (xf86ReturnOptValBool(info->Options, OPTION_DELETE_DP12, FALSE)) { 1662 info->drmmode.delete_dp_12_displays = TRUE; 1663 } 1664 1665 if (drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8) == 1666 FALSE) { 1667 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1668 "Kernel modesetting setup failed\n"); 1669 return FALSE; 1670 } 1671 1672 AMDGPUSetupCapabilities(pScrn); 1673 1674 if (info->drmmode.count_crtcs == 1) 1675 pAMDGPUEnt->HasCRTC2 = FALSE; 1676 else 1677 pAMDGPUEnt->HasCRTC2 = TRUE; 1678 1679 if (info->family < AMDGPU_FAMILY_CI) { 1680 info->cursor_w = CURSOR_WIDTH; 1681 info->cursor_h = CURSOR_HEIGHT; 1682 } else { 1683 info->cursor_w = CURSOR_WIDTH_CIK; 1684 info->cursor_h = CURSOR_HEIGHT_CIK; 1685 } 1686 1687 amdgpu_query_heap_size(pAMDGPUEnt->pDev, AMDGPU_GEM_DOMAIN_GTT, 1688 &heap_size, &max_allocation); 1689 info->gart_size = heap_size; 1690 amdgpu_query_heap_size(pAMDGPUEnt->pDev, AMDGPU_GEM_DOMAIN_VRAM, 1691 &heap_size, &max_allocation); 1692 info->vram_size = max_allocation; 1693 1694 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1695 "mem size init: gart size :%llx vram size: s:%llx visible:%llx\n", 1696 (unsigned long long)info->gart_size, 1697 (unsigned long long)heap_size, 1698 (unsigned long long)max_allocation); 1699 1700 cpp = pScrn->bitsPerPixel / 8; 1701 pScrn->displayWidth = 1702 AMDGPU_ALIGN(pScrn->virtualX, drmmode_get_pitch_align(pScrn, cpp)); 1703 1704 /* Set display resolution */ 1705 xf86SetDpi(pScrn, 0, 0); 1706 1707 if (!xf86SetGamma(pScrn, zeros)) 1708 return FALSE; 1709 1710 if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { 1711 if (!xf86LoadSubModule(pScrn, "ramdac")) 1712 return FALSE; 1713 } 1714 1715 if (!pScrn->modes 1716#ifdef XSERVER_PLATFORM_BUS 1717 && !pScrn->is_gpu 1718#endif 1719 ) { 1720 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); 1721 return FALSE; 1722 } 1723 1724 return TRUE; 1725} 1726 1727static Bool AMDGPUCursorInit_KMS(ScreenPtr pScreen) 1728{ 1729 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1730 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1731 1732 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1733 "Initializing Cursor\n"); 1734 1735 /* Set Silken Mouse */ 1736 xf86SetSilkenMouse(pScreen); 1737 1738 /* Cursor setup */ 1739 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1740 1741 if (info->allowPageFlip) { 1742 miPointerScreenPtr PointPriv = 1743 dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); 1744 1745 if (!dixRegisterScreenPrivateKey(&amdgpu_device_private_key, pScreen, 1746 PRIVATE_DEVICE, 1747 sizeof(struct amdgpu_device_priv))) { 1748 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "dixRegisterScreenPrivateKey failed\n"); 1749 return FALSE; 1750 } 1751 1752 info->SpriteFuncs = PointPriv->spriteFuncs; 1753 PointPriv->spriteFuncs = &drmmode_sprite_funcs; 1754 } 1755 1756 if (xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) 1757 return TRUE; 1758 1759 if (!xf86_cursors_init(pScreen, info->cursor_w, info->cursor_h, 1760 HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 1761 HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | 1762 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | 1763 HARDWARE_CURSOR_UPDATE_UNHIDDEN | 1764 HARDWARE_CURSOR_ARGB)) { 1765 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86_cursors_init failed\n"); 1766 return FALSE; 1767 } 1768 1769 return TRUE; 1770} 1771 1772void AMDGPUBlank(ScrnInfoPtr pScrn) 1773{ 1774 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1775 xf86OutputPtr output; 1776 xf86CrtcPtr crtc; 1777 int o, c; 1778 1779 for (c = 0; c < xf86_config->num_crtc; c++) { 1780 crtc = xf86_config->crtc[c]; 1781 for (o = 0; o < xf86_config->num_output; o++) { 1782 output = xf86_config->output[o]; 1783 if (output->crtc != crtc) 1784 continue; 1785 1786 output->funcs->dpms(output, DPMSModeOff); 1787 } 1788 crtc->funcs->dpms(crtc, DPMSModeOff); 1789 } 1790} 1791 1792void AMDGPUUnblank(ScrnInfoPtr pScrn) 1793{ 1794 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1795 xf86OutputPtr output; 1796 xf86CrtcPtr crtc; 1797 int o, c; 1798 for (c = 0; c < xf86_config->num_crtc; c++) { 1799 crtc = xf86_config->crtc[c]; 1800 if (!crtc->enabled) 1801 continue; 1802 crtc->funcs->dpms(crtc, DPMSModeOn); 1803 for (o = 0; o < xf86_config->num_output; o++) { 1804 output = xf86_config->output[o]; 1805 if (output->crtc != crtc) 1806 continue; 1807 output->funcs->dpms(output, DPMSModeOn); 1808 } 1809 } 1810} 1811 1812static Bool amdgpu_set_drm_master(ScrnInfoPtr pScrn) 1813{ 1814 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1815 int err; 1816 1817#ifdef XF86_PDEV_SERVER_FD 1818 if (pAMDGPUEnt->platform_dev && 1819 (pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD)) 1820 return TRUE; 1821#endif 1822 1823 err = drmSetMaster(pAMDGPUEnt->fd); 1824 if (err) 1825 ErrorF("Unable to retrieve master\n"); 1826 1827 return err == 0; 1828} 1829 1830static void amdgpu_drop_drm_master(ScrnInfoPtr pScrn) 1831{ 1832 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1833 1834#ifdef XF86_PDEV_SERVER_FD 1835 if (pAMDGPUEnt->platform_dev && 1836 (pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD)) 1837 return; 1838#endif 1839 1840 drmDropMaster(pAMDGPUEnt->fd); 1841} 1842 1843 1844static 1845CARD32 cleanup_black_fb(OsTimerPtr timer, CARD32 now, pointer data) 1846{ 1847 ScreenPtr screen = data; 1848 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1849 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 1850 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1851 int c; 1852 1853 if (xf86ScreenToScrn(amdgpu_primary_screen(screen))->vtSema) 1854 return 0; 1855 1856 /* Unreference the all-black FB created by AMDGPULeaveVT_KMS. After 1857 * this, there should be no FB left created by this driver. 1858 */ 1859 for (c = 0; c < xf86_config->num_crtc; c++) { 1860 drmmode_crtc_private_ptr drmmode_crtc = 1861 xf86_config->crtc[c]->driver_private; 1862 1863 drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb, NULL); 1864 } 1865 1866 TimerFree(timer); 1867 return 0; 1868} 1869 1870static Bool AMDGPUSaveScreen_KMS(ScreenPtr pScreen, int mode) 1871{ 1872 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1873 Bool unblank; 1874 1875 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1876 "AMDGPUSaveScreen(%d)\n", mode); 1877 1878 unblank = xf86IsUnblank(mode); 1879 if (unblank) 1880 SetTimeSinceLastInputEvent(); 1881 1882 if ((pScrn != NULL) && pScrn->vtSema) { 1883 if (unblank) 1884 AMDGPUUnblank(pScrn); 1885 else 1886 AMDGPUBlank(pScrn); 1887 } 1888 return TRUE; 1889} 1890 1891/* Called at the end of each server generation. Restore the original 1892 * text mode, unmap video memory, and unwrap and call the saved 1893 * CloseScreen function. 1894 */ 1895static Bool AMDGPUCloseScreen_KMS(ScreenPtr pScreen) 1896{ 1897 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1898 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1899 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1900 1901 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1902 "AMDGPUCloseScreen\n"); 1903 1904 /* Clear mask of assigned crtc's in this generation */ 1905 pAMDGPUEnt->assigned_crtcs = 0; 1906 1907 drmmode_uevent_fini(pScrn, &info->drmmode); 1908 amdgpu_drm_queue_close(pScrn); 1909 1910 if (info->callback_event_type != -1) { 1911 DeleteCallback(&EventCallback, amdgpu_event_callback, pScrn); 1912 DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn); 1913 } 1914 1915 amdgpu_sync_close(pScreen); 1916 amdgpu_drop_drm_master(pScrn); 1917 1918 drmmode_fini(pScrn, &info->drmmode); 1919 if (info->dri2.enabled) { 1920 amdgpu_dri2_close_screen(pScreen); 1921 } 1922 amdgpu_glamor_fini(pScreen); 1923 pScrn->vtSema = FALSE; 1924 xf86ClearPrimInitDone(info->pEnt->index); 1925 1926 if (info->allowPageFlip) { 1927 miPointerScreenPtr PointPriv = 1928 dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); 1929 1930 if (PointPriv->spriteFuncs == &drmmode_sprite_funcs) 1931 PointPriv->spriteFuncs = info->SpriteFuncs; 1932 } 1933 1934 pScreen->BlockHandler = info->BlockHandler; 1935 pScreen->CloseScreen = info->CloseScreen; 1936 return pScreen->CloseScreen(pScreen); 1937} 1938 1939void AMDGPUFreeScreen_KMS(ScrnInfoPtr pScrn) 1940{ 1941 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1942 "AMDGPUFreeScreen\n"); 1943 1944 AMDGPUFreeRec(pScrn); 1945} 1946 1947Bool AMDGPUScreenInit_KMS(ScreenPtr pScreen, int argc, char **argv) 1948{ 1949 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1950 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1951 int subPixelOrder = SubPixelUnknown; 1952 MessageType from; 1953 Bool value; 1954 int driLevel; 1955 const char *s; 1956 void *front_ptr; 1957 1958 pScrn->fbOffset = 0; 1959 1960 miClearVisualTypes(); 1961 if (!miSetVisualTypes(pScrn->depth, 1962 miGetDefaultVisualMask(pScrn->depth), 1963 pScrn->rgbBits, pScrn->defaultVisual)) 1964 return FALSE; 1965 miSetPixmapDepths(); 1966 1967 if (!amdgpu_set_drm_master(pScrn)) 1968 return FALSE; 1969 1970 info->directRenderingEnabled = FALSE; 1971 if (info->shadow_fb == FALSE) 1972 info->directRenderingEnabled = amdgpu_dri2_screen_init(pScreen); 1973 1974 if (!amdgpu_setup_kernel_mem(pScreen)) { 1975 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1976 "amdgpu_setup_kernel_mem failed\n"); 1977 return FALSE; 1978 } 1979 front_ptr = info->front_buffer->cpu_ptr; 1980 1981 if (info->shadow_fb) { 1982 info->fb_shadow = calloc(1, 1983 pScrn->displayWidth * pScrn->virtualY * 1984 ((pScrn->bitsPerPixel + 7) >> 3)); 1985 if (!info->fb_shadow) { 1986 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1987 "Failed to allocate shadow framebuffer\n"); 1988 return FALSE; 1989 } else { 1990 if (!fbScreenInit(pScreen, info->fb_shadow, 1991 pScrn->virtualX, pScrn->virtualY, 1992 pScrn->xDpi, pScrn->yDpi, 1993 pScrn->displayWidth, 1994 pScrn->bitsPerPixel)) 1995 return FALSE; 1996 } 1997 } 1998 1999 if (info->shadow_fb == FALSE) { 2000 /* Init fb layer */ 2001 if (!fbScreenInit(pScreen, front_ptr, 2002 pScrn->virtualX, pScrn->virtualY, 2003 pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, 2004 pScrn->bitsPerPixel)) 2005 return FALSE; 2006 } 2007 2008 xf86SetBlackWhitePixels(pScreen); 2009 2010 if (pScrn->bitsPerPixel > 8) { 2011 VisualPtr visual; 2012 2013 visual = pScreen->visuals + pScreen->numVisuals; 2014 while (--visual >= pScreen->visuals) { 2015 if ((visual->class | DynamicClass) == DirectColor) { 2016 visual->offsetRed = pScrn->offset.red; 2017 visual->offsetGreen = pScrn->offset.green; 2018 visual->offsetBlue = pScrn->offset.blue; 2019 visual->redMask = pScrn->mask.red; 2020 visual->greenMask = pScrn->mask.green; 2021 visual->blueMask = pScrn->mask.blue; 2022 } 2023 } 2024 } 2025 2026 /* Must be after RGB order fixed */ 2027 fbPictureInit(pScreen, 0, 0); 2028 2029#ifdef RENDER 2030 if ((s = xf86GetOptValString(info->Options, OPTION_SUBPIXEL_ORDER))) { 2031 if (strcmp(s, "RGB") == 0) 2032 subPixelOrder = SubPixelHorizontalRGB; 2033 else if (strcmp(s, "BGR") == 0) 2034 subPixelOrder = SubPixelHorizontalBGR; 2035 else if (strcmp(s, "NONE") == 0) 2036 subPixelOrder = SubPixelNone; 2037 PictureSetSubpixelOrder(pScreen, subPixelOrder); 2038 } 2039#endif 2040 2041 if (!pScreen->isGPU) { 2042 if (xorgGetVersion() >= XORG_VERSION_NUMERIC(1,18,3,0,0)) 2043 value = info->use_glamor; 2044 else 2045 value = FALSE; 2046 from = X_DEFAULT; 2047 2048 if (info->use_glamor) { 2049 if (xf86GetOptValBool(info->Options, OPTION_DRI3, &value)) 2050 from = X_CONFIG; 2051 2052 if (xf86GetOptValInteger(info->Options, OPTION_DRI, &driLevel) && 2053 (driLevel == 2 || driLevel == 3)) { 2054 from = X_CONFIG; 2055 value = driLevel == 3; 2056 } 2057 } 2058 2059 if (value) { 2060 value = amdgpu_sync_init(pScreen) && 2061 amdgpu_present_screen_init(pScreen) && 2062 amdgpu_dri3_screen_init(pScreen); 2063 2064 if (!value) 2065 from = X_WARNING; 2066 } 2067 2068 xf86DrvMsg(pScrn->scrnIndex, from, "DRI3 %sabled\n", value ? "en" : "dis"); 2069 } 2070 2071 pScrn->vtSema = TRUE; 2072 xf86SetBackingStore(pScreen); 2073 2074 if (info->directRenderingEnabled) { 2075 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2076 "Direct rendering enabled\n"); 2077 } else { 2078 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2079 "Direct rendering disabled\n"); 2080 } 2081 2082 if (info->use_glamor && info->directRenderingEnabled) { 2083 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 2084 "Initializing Acceleration\n"); 2085 if (amdgpu_glamor_init(pScreen)) { 2086 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2087 "Acceleration enabled\n"); 2088 } else { 2089 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2090 "Acceleration initialization failed\n"); 2091 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2092 "2D and 3D acceleration disabled\n"); 2093 info->use_glamor = FALSE; 2094 } 2095 } else if (info->directRenderingEnabled) { 2096 if (!amdgpu_pixmap_init(pScreen)) 2097 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D acceleration disabled\n"); 2098 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D acceleration disabled\n"); 2099 } else { 2100 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D and 3D acceleration disabled\n"); 2101 } 2102 2103 /* Init DPMS */ 2104 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 2105 "Initializing DPMS\n"); 2106 xf86DPMSInit(pScreen, xf86DPMSSet, 0); 2107 2108 if (!AMDGPUCursorInit_KMS(pScreen)) 2109 return FALSE; 2110 2111 /* DGA setup */ 2112#ifdef XFreeXDGA 2113 /* DGA is dangerous on kms as the base and framebuffer location may change: 2114 * http://lists.freedesktop.org/archives/xorg-devel/2009-September/002113.html 2115 */ 2116 /* xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset); */ 2117#endif 2118 if (info->shadow_fb == FALSE && !pScreen->isGPU) { 2119 /* Init Xv */ 2120 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 2121 "Initializing Xv\n"); 2122 AMDGPUInitVideo(pScreen); 2123 } 2124 2125 if (info->shadow_fb == TRUE) { 2126 if (!shadowSetup(pScreen)) { 2127 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2128 "Shadowfb initialization failed\n"); 2129 return FALSE; 2130 } 2131 } 2132 pScrn->pScreen = pScreen; 2133 2134 if (!pScreen->isGPU) { 2135 if (serverGeneration == 1 && bgNoneRoot && info->use_glamor) { 2136 info->CreateWindow = pScreen->CreateWindow; 2137 pScreen->CreateWindow = AMDGPUCreateWindow_oneshot; 2138 } 2139 info->WindowExposures = pScreen->WindowExposures; 2140 pScreen->WindowExposures = AMDGPUWindowExposures_oneshot; 2141 } 2142 2143 /* Provide SaveScreen & wrap BlockHandler and CloseScreen */ 2144 /* Wrap CloseScreen */ 2145 info->CloseScreen = pScreen->CloseScreen; 2146 pScreen->CloseScreen = AMDGPUCloseScreen_KMS; 2147 pScreen->SaveScreen = AMDGPUSaveScreen_KMS; 2148 info->BlockHandler = pScreen->BlockHandler; 2149 pScreen->BlockHandler = AMDGPUBlockHandler_KMS; 2150 2151 info->CreateScreenResources = pScreen->CreateScreenResources; 2152 pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS; 2153 2154 pScreen->StartPixmapTracking = PixmapStartDirtyTracking; 2155 pScreen->StopPixmapTracking = PixmapStopDirtyTracking; 2156#if HAS_SYNC_SHARED_PIXMAP 2157 pScreen->SyncSharedPixmap = amdgpu_sync_shared_pixmap; 2158#endif 2159 2160 if (!xf86CrtcScreenInit(pScreen)) 2161 return FALSE; 2162 2163 /* Wrap pointer motion to flip touch screen around */ 2164// info->PointerMoved = pScrn->PointerMoved; 2165// pScrn->PointerMoved = AMDGPUPointerMoved; 2166 2167 if (!drmmode_setup_colormap(pScreen, pScrn)) 2168 return FALSE; 2169 2170 /* Note unused options */ 2171 if (serverGeneration == 1) 2172 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 2173 2174 if (info->vrr_support) { 2175 if (!amdgpu_property_vectors_wrapped) { 2176 saved_change_property = ProcVector[X_ChangeProperty]; 2177 ProcVector[X_ChangeProperty] = amdgpu_change_property; 2178 saved_delete_property = ProcVector[X_DeleteProperty]; 2179 ProcVector[X_DeleteProperty] = amdgpu_delete_property; 2180 amdgpu_property_vectors_wrapped = TRUE; 2181 } 2182 2183 amdgpu_vrr_atom = MakeAtom("_VARIABLE_REFRESH", 2184 strlen("_VARIABLE_REFRESH"), TRUE); 2185 } 2186 2187 drmmode_init(pScrn, &info->drmmode); 2188 2189 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 2190 "AMDGPUScreenInit finished\n"); 2191 2192 return TRUE; 2193} 2194 2195Bool AMDGPUEnterVT_KMS(ScrnInfoPtr pScrn) 2196{ 2197 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 2198 2199 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 2200 "AMDGPUEnterVT_KMS\n"); 2201 2202 amdgpu_set_drm_master(pScrn); 2203 2204 if (info->shadow_fb) { 2205 int pitch; 2206 struct amdgpu_buffer *front_buffer = 2207 amdgpu_alloc_pixmap_bo(pScrn, pScrn->virtualX, 2208 pScrn->virtualY, pScrn->depth, 2209 AMDGPU_CREATE_PIXMAP_SCANOUT | 2210 AMDGPU_CREATE_PIXMAP_LINEAR, 2211 pScrn->bitsPerPixel, 2212 &pitch); 2213 2214 if (front_buffer) { 2215 if (amdgpu_bo_map(pScrn, front_buffer) == 0) { 2216 memset(front_buffer->cpu_ptr, 0, pitch * pScrn->virtualY); 2217 amdgpu_bo_unref(&info->front_buffer); 2218 info->front_buffer = front_buffer; 2219 } else { 2220 amdgpu_bo_unref(&front_buffer); 2221 front_buffer = NULL; 2222 } 2223 } 2224 2225 if (!front_buffer) { 2226 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2227 "Failed to allocate new scanout BO after VT switch, " 2228 "other DRM masters may see screen contents\n"); 2229 } 2230 } 2231 2232 pScrn->vtSema = TRUE; 2233 2234 if (!drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE)) 2235 return FALSE; 2236 2237 return TRUE; 2238} 2239 2240static void 2241pixmap_unref_fb(PixmapPtr pixmap) 2242{ 2243 ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); 2244 struct drmmode_fb **fb_ptr = amdgpu_pixmap_get_fb_ptr(pixmap); 2245 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 2246 2247 if (fb_ptr) 2248 drmmode_fb_reference(pAMDGPUEnt->fd, fb_ptr, NULL); 2249} 2250 2251static void 2252client_pixmap_unref_fb(void *value, XID id, void *pScreen) 2253{ 2254 PixmapPtr pixmap = value; 2255 2256 if (pixmap->drawable.pScreen == pScreen) 2257 pixmap_unref_fb(pixmap); 2258} 2259 2260void AMDGPULeaveVT_KMS(ScrnInfoPtr pScrn) 2261{ 2262 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 2263 ScreenPtr pScreen = pScrn->pScreen; 2264 2265 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 2266 "AMDGPULeaveVT_KMS\n"); 2267 2268 if (!info->shadow_fb) { 2269 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 2270 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 2271 xf86CrtcPtr crtc; 2272 drmmode_crtc_private_ptr drmmode_crtc; 2273 unsigned w = 0, h = 0; 2274 int i; 2275 2276 /* If we're called from CloseScreen, trying to clear the black 2277 * scanout BO will likely crash and burn 2278 */ 2279 if (!pScreen->GCperDepth[0]) 2280 goto hide_cursors; 2281 2282 /* Compute maximum scanout dimensions of active CRTCs */ 2283 for (i = 0; i < xf86_config->num_crtc; i++) { 2284 crtc = xf86_config->crtc[i]; 2285 drmmode_crtc = crtc->driver_private; 2286 2287 if (!drmmode_crtc->fb) 2288 continue; 2289 2290 w = max(w, crtc->mode.HDisplay); 2291 h = max(h, crtc->mode.VDisplay); 2292 } 2293 2294 /* Make all active CRTCs scan out from an all-black framebuffer */ 2295 if (w > 0 && h > 0) { 2296 PixmapPtr black_scanout = 2297 pScreen->CreatePixmap(pScreen, w, h, pScrn->depth, 2298 AMDGPU_CREATE_PIXMAP_SCANOUT); 2299 2300 if (black_scanout) { 2301 struct drmmode_fb *black_fb = 2302 amdgpu_pixmap_get_fb(black_scanout); 2303 2304 amdgpu_pixmap_clear(black_scanout); 2305 amdgpu_glamor_finish(pScrn); 2306 2307 for (i = 0; i < xf86_config->num_crtc; i++) { 2308 crtc = xf86_config->crtc[i]; 2309 drmmode_crtc = crtc->driver_private; 2310 2311 if (drmmode_crtc->fb) { 2312 if (black_fb) { 2313 drmmode_set_mode(crtc, black_fb, &crtc->mode, 0, 0); 2314 } else { 2315 drmModeSetCrtc(pAMDGPUEnt->fd, 2316 drmmode_crtc->mode_crtc->crtc_id, 0, 2317 0, 0, NULL, 0, NULL); 2318 drmmode_fb_reference(pAMDGPUEnt->fd, 2319 &drmmode_crtc->fb, NULL); 2320 } 2321 2322 if (pScrn->is_gpu) { 2323 if (drmmode_crtc->scanout[0]) 2324 pixmap_unref_fb(drmmode_crtc->scanout[0]); 2325 if (drmmode_crtc->scanout[1]) 2326 pixmap_unref_fb(drmmode_crtc->scanout[1]); 2327 } else { 2328 drmmode_crtc_scanout_free(crtc); 2329 } 2330 } 2331 } 2332 2333 pScreen->DestroyPixmap(black_scanout); 2334 } 2335 } 2336 2337 xf86RotateFreeShadow(pScrn); 2338 2339 /* Unreference FBs of all pixmaps. After this, the only FB remaining 2340 * should be the all-black one being scanned out by active CRTCs 2341 */ 2342 for (i = 0; i < currentMaxClients; i++) { 2343 if (i > 0 && 2344 (!clients[i] || clients[i]->clientState != ClientStateRunning)) 2345 continue; 2346 2347 FindClientResourcesByType(clients[i], RT_PIXMAP, 2348 client_pixmap_unref_fb, pScreen); 2349 } 2350 2351 pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen)); 2352 } else { 2353 memset(info->front_buffer->cpu_ptr, 0, pScrn->virtualX * 2354 info->pixel_bytes * pScrn->virtualY); 2355 } 2356 2357 if (pScreen->GCperDepth[0]) 2358 TimerSet(NULL, 0, 1000, cleanup_black_fb, pScreen); 2359 2360 hide_cursors: 2361 xf86_hide_cursors(pScrn); 2362 2363 amdgpu_drop_drm_master(pScrn); 2364 2365 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 2366 "Ok, leaving now...\n"); 2367} 2368 2369Bool AMDGPUSwitchMode_KMS(ScrnInfoPtr pScrn, DisplayModePtr mode) 2370{ 2371 Bool ret; 2372 ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0); 2373 return ret; 2374 2375} 2376 2377void AMDGPUAdjustFrame_KMS(ScrnInfoPtr pScrn, int x, int y) 2378{ 2379 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 2380 drmmode_adjust_frame(pScrn, &info->drmmode, x, y); 2381 return; 2382} 2383 2384static Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen) 2385{ 2386 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2387 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 2388 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 2389 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 2390 int cpp = info->pixel_bytes; 2391 int cursor_size; 2392 int c, i; 2393 2394 cursor_size = info->cursor_w * info->cursor_h * 4; 2395 cursor_size = AMDGPU_ALIGN(cursor_size, AMDGPU_GPU_PAGE_SIZE); 2396 for (c = 0; c < xf86_config->num_crtc; c++) { 2397 drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[c]->driver_private; 2398 2399 for (i = 0; i < 2; i++) { 2400 if (!drmmode_crtc->cursor_buffer[i]) { 2401 drmmode_crtc->cursor_buffer[i] = 2402 amdgpu_bo_open(pAMDGPUEnt->pDev, 2403 cursor_size, 0, 2404 AMDGPU_GEM_DOMAIN_VRAM); 2405 2406 if (!(drmmode_crtc->cursor_buffer[i])) { 2407 ErrorF("Failed to allocate cursor buffer memory\n"); 2408 return FALSE; 2409 } 2410 2411 if (amdgpu_bo_cpu_map(drmmode_crtc->cursor_buffer[i]->bo.amdgpu, 2412 &drmmode_crtc->cursor_buffer[i]->cpu_ptr)) 2413 ErrorF("Failed to map cursor buffer memory\n"); 2414 } 2415 } 2416 } 2417 2418 if (!info->front_buffer) { 2419 int pitch; 2420 int hint = AMDGPU_CREATE_PIXMAP_SCANOUT; 2421 2422 if (info->shadow_primary) 2423 hint |= AMDGPU_CREATE_PIXMAP_LINEAR | AMDGPU_CREATE_PIXMAP_GTT; 2424 else if (!info->use_glamor) 2425 hint |= AMDGPU_CREATE_PIXMAP_LINEAR; 2426 2427 info->front_buffer = 2428 amdgpu_alloc_pixmap_bo(pScrn, pScrn->virtualX, 2429 pScrn->virtualY, pScrn->depth, 2430 hint, pScrn->bitsPerPixel, 2431 &pitch); 2432 if (!(info->front_buffer)) { 2433 ErrorF("Failed to allocate front buffer memory\n"); 2434 return FALSE; 2435 } 2436 2437 if (!info->use_glamor && 2438 amdgpu_bo_map(pScrn, info->front_buffer) != 0) { 2439 ErrorF("Failed to map front buffer memory\n"); 2440 return FALSE; 2441 } 2442 2443 pScrn->displayWidth = pitch / cpp; 2444 } 2445 2446 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer pitch: %d bytes\n", 2447 pScrn->displayWidth * cpp); 2448 return TRUE; 2449} 2450 2451/* Used to disallow modes that are not supported by the hardware */ 2452ModeStatus AMDGPUValidMode(ScrnInfoPtr pScrn, DisplayModePtr mode, 2453 Bool verbose, int flag) 2454{ 2455 /* There are problems with double scan mode at high clocks 2456 * They're likely related PLL and display buffer settings. 2457 * Disable these modes for now. 2458 */ 2459 if (mode->Flags & V_DBLSCAN) { 2460 if ((mode->CrtcHDisplay >= 1024) || (mode->CrtcVDisplay >= 768)) 2461 return MODE_CLOCK_RANGE; 2462 } 2463 return MODE_OK; 2464} 2465