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