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