amdgpu_dri2.c revision 504d986f
1/* 2 * Copyright 2008 Kristian Høgsberg 3 * Copyright 2008 Jérôme Glisse 4 * 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining 8 * a copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation on the rights to use, copy, modify, merge, 11 * publish, distribute, sublicense, and/or sell copies of the Software, 12 * and to permit persons to whom the Software is furnished to do so, 13 * subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial 17 * portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR 23 * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 * DEALINGS IN THE SOFTWARE. 27 */ 28#ifdef HAVE_CONFIG_H 29#include "config.h" 30#endif 31 32#include "amdgpu_drv.h" 33#include "amdgpu_dri2.h" 34#include "amdgpu_glamor.h" 35#include "amdgpu_video.h" 36#include "amdgpu_pixmap.h" 37 38#ifdef DRI2 39 40#include <sys/ioctl.h> 41#include <sys/types.h> 42#include <sys/stat.h> 43#include <fcntl.h> 44#include <errno.h> 45 46#include <gbm.h> 47 48#include "amdgpu_bo_helper.h" 49#include "amdgpu_version.h" 50 51#include "amdgpu_list.h" 52 53#include <xf86Priv.h> 54 55#if DRI2INFOREC_VERSION >= 9 56#define USE_DRI2_PRIME 57#endif 58 59#define FALLBACK_SWAP_DELAY 16 60 61typedef DRI2BufferPtr BufferPtr; 62 63struct dri2_buffer_priv { 64 PixmapPtr pixmap; 65 unsigned int attachment; 66 unsigned int refcnt; 67}; 68 69struct dri2_window_priv { 70 xf86CrtcPtr crtc; 71 int vblank_delta; 72}; 73 74static DevPrivateKeyRec dri2_window_private_key_rec; 75#define dri2_window_private_key (&dri2_window_private_key_rec) 76 77#define get_dri2_window_priv(window) \ 78 ((struct dri2_window_priv*) \ 79 dixLookupPrivate(&(window)->devPrivates, dri2_window_private_key)) 80 81/* Get GEM flink name for a pixmap */ 82static Bool 83amdgpu_get_flink_name(AMDGPUEntPtr pAMDGPUEnt, PixmapPtr pixmap, uint32_t *name) 84{ 85 struct amdgpu_buffer *bo = amdgpu_get_pixmap_bo(pixmap); 86 struct drm_gem_flink flink; 87 88 if (bo && !(bo->flags & AMDGPU_BO_FLAGS_GBM) && 89 amdgpu_bo_export(bo->bo.amdgpu, 90 amdgpu_bo_handle_type_gem_flink_name, 91 name) == 0) 92 return TRUE; 93 94 if (!amdgpu_pixmap_get_handle(pixmap, &flink.handle) || 95 ioctl(pAMDGPUEnt->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) 96 return FALSE; 97 *name = flink.name; 98 return TRUE; 99} 100 101static BufferPtr 102amdgpu_dri2_create_buffer2(ScreenPtr pScreen, 103 DrawablePtr drawable, 104 unsigned int attachment, unsigned int format) 105{ 106 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 107 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 108 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 109 BufferPtr buffers; 110 struct dri2_buffer_priv *privates; 111 PixmapPtr pixmap; 112 unsigned front_width; 113 unsigned aligned_width = drawable->width; 114 unsigned height = drawable->height; 115 Bool is_glamor_pixmap = FALSE; 116 int depth; 117 int cpp; 118 119 if (format) { 120 depth = format; 121 122 switch (depth) { 123 case 15: 124 cpp = 2; 125 break; 126 case 24: 127 cpp = 4; 128 break; 129 default: 130 cpp = depth / 8; 131 } 132 } else { 133 depth = drawable->depth; 134 cpp = drawable->bitsPerPixel / 8; 135 } 136 137 front_width = pScreen->GetScreenPixmap(pScreen)->drawable.width; 138 139 pixmap = NULL; 140 141 if (attachment == DRI2BufferFrontLeft) { 142 uint32_t handle; 143 144 pixmap = get_drawable_pixmap(drawable); 145 if (pScreen != pixmap->drawable.pScreen) 146 pixmap = NULL; 147 else if (info->use_glamor && !amdgpu_pixmap_get_handle(pixmap, &handle)) { 148 is_glamor_pixmap = TRUE; 149 aligned_width = pixmap->drawable.width; 150 height = pixmap->drawable.height; 151 pixmap = NULL; 152 } else 153 pixmap->refcnt++; 154 } 155 156 if (!pixmap && (is_glamor_pixmap || attachment != DRI2BufferFrontLeft)) { 157 if (aligned_width == front_width) 158 aligned_width = pScrn->virtualX; 159 160 pixmap = (*pScreen->CreatePixmap) (pScreen, 161 aligned_width, 162 height, 163 depth, 164 AMDGPU_CREATE_PIXMAP_DRI2); 165 } 166 167 buffers = calloc(1, sizeof *buffers); 168 if (buffers == NULL) 169 goto error; 170 171 if (pixmap) { 172 if (is_glamor_pixmap) { 173 pixmap = amdgpu_glamor_set_pixmap_bo(drawable, pixmap); 174 pixmap->refcnt++; 175 } 176 177 if (!amdgpu_get_flink_name(pAMDGPUEnt, pixmap, &buffers->name)) 178 goto error; 179 } 180 181 privates = calloc(1, sizeof(struct dri2_buffer_priv)); 182 if (privates == NULL) 183 goto error; 184 185 buffers->attachment = attachment; 186 if (pixmap) { 187 buffers->pitch = pixmap->devKind; 188 buffers->cpp = cpp; 189 } 190 buffers->driverPrivate = privates; 191 buffers->format = format; 192 buffers->flags = 0; /* not tiled */ 193 privates->pixmap = pixmap; 194 privates->attachment = attachment; 195 privates->refcnt = 1; 196 197 return buffers; 198 199error: 200 free(buffers); 201 if (pixmap) 202 (*pScreen->DestroyPixmap) (pixmap); 203 return NULL; 204} 205 206DRI2BufferPtr 207amdgpu_dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment, 208 unsigned int format) 209{ 210 return amdgpu_dri2_create_buffer2(pDraw->pScreen, pDraw, 211 attachment, format); 212} 213 214static void 215amdgpu_dri2_destroy_buffer2(ScreenPtr pScreen, 216 DrawablePtr drawable, BufferPtr buffers) 217{ 218 if (buffers) { 219 struct dri2_buffer_priv *private = buffers->driverPrivate; 220 221 /* Trying to free an already freed buffer is unlikely to end well */ 222 if (private->refcnt == 0) { 223 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 224 225 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 226 "Attempted to destroy previously destroyed buffer.\ 227 This is a programming error\n"); 228 return; 229 } 230 231 private->refcnt--; 232 if (private->refcnt == 0) { 233 if (private->pixmap) 234 (*pScreen->DestroyPixmap) (private->pixmap); 235 236 free(buffers->driverPrivate); 237 free(buffers); 238 } 239 } 240} 241 242void amdgpu_dri2_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buf) 243{ 244 amdgpu_dri2_destroy_buffer2(pDraw->pScreen, pDraw, buf); 245} 246 247static inline PixmapPtr GetDrawablePixmap(DrawablePtr drawable) 248{ 249 if (drawable->type == DRAWABLE_PIXMAP) 250 return (PixmapPtr) drawable; 251 else { 252 struct _Window *pWin = (struct _Window *)drawable; 253 return drawable->pScreen->GetWindowPixmap(pWin); 254 } 255} 256 257static void 258amdgpu_dri2_copy_region2(ScreenPtr pScreen, 259 DrawablePtr drawable, 260 RegionPtr region, 261 BufferPtr dest_buffer, BufferPtr src_buffer) 262{ 263 struct dri2_buffer_priv *src_private = src_buffer->driverPrivate; 264 struct dri2_buffer_priv *dst_private = dest_buffer->driverPrivate; 265 DrawablePtr src_drawable; 266 DrawablePtr dst_drawable; 267 RegionPtr copy_clip; 268 GCPtr gc; 269 Bool translate = FALSE; 270 int off_x = 0, off_y = 0; 271 272 src_drawable = &src_private->pixmap->drawable; 273 dst_drawable = &dst_private->pixmap->drawable; 274 275 if (src_private->attachment == DRI2BufferFrontLeft) { 276#ifdef USE_DRI2_PRIME 277 if (drawable->pScreen != pScreen) { 278 src_drawable = DRI2UpdatePrime(drawable, src_buffer); 279 if (!src_drawable) 280 return; 281 } else 282#endif 283 src_drawable = drawable; 284 } 285 if (dst_private->attachment == DRI2BufferFrontLeft) { 286#ifdef USE_DRI2_PRIME 287 if (drawable->pScreen != pScreen) { 288 dst_drawable = DRI2UpdatePrime(drawable, dest_buffer); 289 if (!dst_drawable) 290 return; 291 if (dst_drawable != drawable) 292 translate = TRUE; 293 } else 294#endif 295 dst_drawable = drawable; 296 } 297 298 if (translate && drawable->type == DRAWABLE_WINDOW) { 299 PixmapPtr pPix = GetDrawablePixmap(drawable); 300 301 off_x = drawable->x - pPix->screen_x; 302 off_y = drawable->y - pPix->screen_y; 303 } 304 gc = GetScratchGC(dst_drawable->depth, pScreen); 305 copy_clip = REGION_CREATE(pScreen, NULL, 0); 306 REGION_COPY(pScreen, copy_clip, region); 307 308 if (translate) { 309 REGION_TRANSLATE(pScreen, copy_clip, off_x, off_y); 310 } 311 312 (*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0); 313 ValidateGC(dst_drawable, gc); 314 315 (*gc->ops->CopyArea) (src_drawable, dst_drawable, gc, 316 0, 0, drawable->width, drawable->height, off_x, 317 off_y); 318 319 FreeScratchGC(gc); 320} 321 322void 323amdgpu_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, 324 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer) 325{ 326 return amdgpu_dri2_copy_region2(pDraw->pScreen, pDraw, pRegion, 327 pDstBuffer, pSrcBuffer); 328} 329 330enum DRI2FrameEventType { 331 DRI2_SWAP, 332 DRI2_FLIP, 333 DRI2_WAITMSC, 334}; 335 336typedef struct _DRI2FrameEvent { 337 XID drawable_id; 338 ClientPtr client; 339 enum DRI2FrameEventType type; 340 unsigned frame; 341 xf86CrtcPtr crtc; 342 OsTimerPtr timer; 343 uintptr_t drm_queue_seq; 344 345 /* for swaps & flips only */ 346 DRI2SwapEventPtr event_complete; 347 void *event_data; 348 DRI2BufferPtr front; 349 DRI2BufferPtr back; 350} DRI2FrameEventRec, *DRI2FrameEventPtr; 351 352static int DRI2InfoCnt; 353 354static void amdgpu_dri2_ref_buffer(BufferPtr buffer) 355{ 356 struct dri2_buffer_priv *private = buffer->driverPrivate; 357 private->refcnt++; 358} 359 360static void amdgpu_dri2_unref_buffer(BufferPtr buffer) 361{ 362 if (buffer) { 363 struct dri2_buffer_priv *private = buffer->driverPrivate; 364 amdgpu_dri2_destroy_buffer(&(private->pixmap->drawable), 365 buffer); 366 } 367} 368 369static void 370amdgpu_dri2_client_state_changed(CallbackListPtr * ClientStateCallback, 371 pointer data, pointer calldata) 372{ 373 NewClientInfoRec *clientinfo = calldata; 374 ClientPtr pClient = clientinfo->client; 375 376 switch (pClient->clientState) { 377 case ClientStateRetained: 378 case ClientStateGone: 379 amdgpu_drm_abort_client(pClient); 380 break; 381 default: 382 break; 383 } 384} 385 386/* 387 * Get current frame count delta for the specified drawable and CRTC 388 */ 389static uint32_t amdgpu_get_msc_delta(DrawablePtr pDraw, xf86CrtcPtr crtc) 390{ 391 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 392 393 if (pDraw && pDraw->type == DRAWABLE_WINDOW) 394 return drmmode_crtc->interpolated_vblanks + 395 get_dri2_window_priv((WindowPtr)pDraw)->vblank_delta; 396 397 return drmmode_crtc->interpolated_vblanks; 398} 399 400/* 401 * Get current frame count and timestamp of the specified CRTC 402 */ 403static Bool amdgpu_dri2_get_crtc_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc) 404{ 405 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 406 407 if (!amdgpu_crtc_is_enabled(crtc) || 408 drmmode_crtc_get_ust_msc(crtc, ust, msc) != Success) { 409 /* CRTC is not running, extrapolate MSC and timestamp */ 410 ScrnInfoPtr scrn = crtc->scrn; 411 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 412 CARD64 now, delta_t, delta_seq; 413 414 if (!drmmode_crtc->dpms_last_ust) 415 return FALSE; 416 417 if (drmmode_get_current_ust(pAMDGPUEnt->fd, &now) != 0) { 418 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 419 "%s cannot get current time\n", __func__); 420 return FALSE; 421 } 422 423 delta_t = now - drmmode_crtc->dpms_last_ust; 424 delta_seq = delta_t * drmmode_crtc->dpms_last_fps; 425 delta_seq /= 1000000; 426 *ust = drmmode_crtc->dpms_last_ust; 427 delta_t = delta_seq * 1000000; 428 delta_t /= drmmode_crtc->dpms_last_fps; 429 *ust += delta_t; 430 *msc = drmmode_crtc->dpms_last_seq; 431 *msc += delta_seq; 432 } 433 434 *msc += drmmode_crtc->interpolated_vblanks; 435 436 return TRUE; 437} 438 439static 440xf86CrtcPtr amdgpu_dri2_drawable_crtc(DrawablePtr pDraw, Bool consider_disabled) 441{ 442 ScreenPtr pScreen = pDraw->pScreen; 443 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 444 xf86CrtcPtr crtc = amdgpu_pick_best_crtc(pScrn, consider_disabled, 445 pDraw->x, pDraw->x + pDraw->width, 446 pDraw->y, pDraw->y + pDraw->height); 447 448 if (crtc && pDraw->type == DRAWABLE_WINDOW) { 449 struct dri2_window_priv *priv = get_dri2_window_priv((WindowPtr)pDraw); 450 451 if (priv->crtc && priv->crtc != crtc) { 452 CARD64 ust, mscold, mscnew; 453 454 if (amdgpu_dri2_get_crtc_msc(priv->crtc, &ust, &mscold) && 455 amdgpu_dri2_get_crtc_msc(crtc, &ust, &mscnew)) 456 priv->vblank_delta += mscold - mscnew; 457 } 458 459 priv->crtc = crtc; 460 } 461 462 return crtc; 463} 464 465static void 466amdgpu_dri2_flip_event_abort(xf86CrtcPtr crtc, void *event_data) 467{ 468 AMDGPUInfoPtr info = AMDGPUPTR(crtc->scrn); 469 470 info->drmmode.dri2_flipping = FALSE; 471 free(event_data); 472} 473 474static void 475amdgpu_dri2_flip_event_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, 476 void *event_data) 477{ 478 DRI2FrameEventPtr flip = event_data; 479 ScrnInfoPtr scrn = crtc->scrn; 480 unsigned tv_sec, tv_usec; 481 DrawablePtr drawable; 482 ScreenPtr screen; 483 int status; 484 PixmapPtr pixmap; 485 486 status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient, 487 M_ANY, DixWriteAccess); 488 if (status != Success) 489 goto abort; 490 491 frame += amdgpu_get_msc_delta(drawable, crtc); 492 493 screen = scrn->pScreen; 494 pixmap = screen->GetScreenPixmap(screen); 495 xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 496 "%s:%d fevent[%p] width %d pitch %d (/4 %d)\n", 497 __func__, __LINE__, flip, pixmap->drawable.width, 498 pixmap->devKind, pixmap->devKind / 4); 499 500 tv_sec = usec / 1000000; 501 tv_usec = usec % 1000000; 502 503 /* We assume our flips arrive in order, so we don't check the frame */ 504 switch (flip->type) { 505 case DRI2_SWAP: 506 /* Check for too small vblank count of pageflip completion, taking wraparound 507 * into account. This usually means some defective kms pageflip completion, 508 * causing wrong (msc, ust) return values and possible visual corruption. 509 */ 510 if ((frame < flip->frame) && (flip->frame - frame < 5)) { 511 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 512 "%s: Pageflip completion event has impossible msc %u < target_msc %u\n", 513 __func__, frame, flip->frame); 514 /* All-Zero values signal failure of (msc, ust) timestamping to client. */ 515 frame = tv_sec = tv_usec = 0; 516 } 517 518 DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec, 519 DRI2_FLIP_COMPLETE, flip->event_complete, 520 flip->event_data); 521 break; 522 default: 523 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 524 "%s: unknown vblank event received\n", __func__); 525 /* Unknown type */ 526 break; 527 } 528 529abort: 530 amdgpu_dri2_flip_event_abort(crtc, event_data); 531} 532 533static Bool 534amdgpu_dri2_schedule_flip(xf86CrtcPtr crtc, ClientPtr client, 535 DrawablePtr draw, DRI2BufferPtr front, 536 DRI2BufferPtr back, DRI2SwapEventPtr func, 537 void *data, unsigned int target_msc) 538{ 539 ScrnInfoPtr scrn = crtc->scrn; 540 AMDGPUInfoPtr info = AMDGPUPTR(scrn); 541 struct dri2_buffer_priv *back_priv; 542 DRI2FrameEventPtr flip_info; 543 int ref_crtc_hw_id = drmmode_get_crtc_id(crtc); 544 545 flip_info = calloc(1, sizeof(DRI2FrameEventRec)); 546 if (!flip_info) 547 return FALSE; 548 549 flip_info->drawable_id = draw->id; 550 flip_info->client = client; 551 flip_info->type = DRI2_SWAP; 552 flip_info->event_complete = func; 553 flip_info->event_data = data; 554 flip_info->frame = target_msc; 555 flip_info->crtc = crtc; 556 557 xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 558 "%s:%d fevent[%p]\n", __func__, __LINE__, flip_info); 559 560 /* Page flip the full screen buffer */ 561 back_priv = back->driverPrivate; 562 if (amdgpu_do_pageflip(scrn, client, back_priv->pixmap, 563 AMDGPU_DRM_QUEUE_ID_DEFAULT, flip_info, 564 ref_crtc_hw_id, 565 amdgpu_dri2_flip_event_handler, 566 amdgpu_dri2_flip_event_abort, FLIP_VSYNC)) { 567 info->drmmode.dri2_flipping = TRUE; 568 return TRUE; 569 } 570 return FALSE; 571} 572 573static Bool update_front(DrawablePtr draw, DRI2BufferPtr front) 574{ 575 ScreenPtr screen = draw->pScreen; 576 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 577 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 578 PixmapPtr pixmap = get_drawable_pixmap(draw); 579 struct dri2_buffer_priv *priv = front->driverPrivate; 580 581 if (!amdgpu_get_flink_name(pAMDGPUEnt, pixmap, &front->name)) 582 return FALSE; 583 584 (*draw->pScreen->DestroyPixmap) (priv->pixmap); 585 front->pitch = pixmap->devKind; 586 front->cpp = pixmap->drawable.bitsPerPixel / 8; 587 priv->pixmap = pixmap; 588 pixmap->refcnt++; 589 590 return TRUE; 591} 592 593static Bool 594can_exchange(ScrnInfoPtr pScrn, DrawablePtr draw, 595 DRI2BufferPtr front, DRI2BufferPtr back) 596{ 597 struct dri2_buffer_priv *front_priv = front->driverPrivate; 598 struct dri2_buffer_priv *back_priv = back->driverPrivate; 599 PixmapPtr front_pixmap; 600 PixmapPtr back_pixmap = back_priv->pixmap; 601 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 602 int i; 603 604 for (i = 0; i < xf86_config->num_crtc; i++) { 605 xf86CrtcPtr crtc = xf86_config->crtc[i]; 606 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 607 608 if (crtc->enabled && 609 (crtc->rotatedData || drmmode_crtc->scanout[0].bo)) 610 return FALSE; 611 } 612 613 if (!update_front(draw, front)) 614 return FALSE; 615 616 front_pixmap = front_priv->pixmap; 617 618 if (front_pixmap->drawable.width != back_pixmap->drawable.width) 619 return FALSE; 620 621 if (front_pixmap->drawable.height != back_pixmap->drawable.height) 622 return FALSE; 623 624 if (front_pixmap->drawable.bitsPerPixel != 625 back_pixmap->drawable.bitsPerPixel) 626 return FALSE; 627 628 if (front_pixmap->devKind != back_pixmap->devKind) 629 return FALSE; 630 631 return TRUE; 632} 633 634static Bool 635can_flip(ScrnInfoPtr pScrn, DrawablePtr draw, 636 DRI2BufferPtr front, DRI2BufferPtr back) 637{ 638 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 639 640 return draw->type == DRAWABLE_WINDOW && 641 info->allowPageFlip && 642 !info->hwcursor_disabled && 643 !info->drmmode.present_flipping && 644 pScrn->vtSema && 645 DRI2CanFlip(draw) && can_exchange(pScrn, draw, front, back); 646} 647 648static void 649amdgpu_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front, 650 DRI2BufferPtr back) 651{ 652 struct dri2_buffer_priv *front_priv = front->driverPrivate; 653 struct dri2_buffer_priv *back_priv = back->driverPrivate; 654 struct amdgpu_pixmap *front_pix; 655 struct amdgpu_pixmap *back_pix; 656 ScreenPtr screen; 657 AMDGPUInfoPtr info; 658 RegionRec region; 659 int tmp; 660 661 region.extents.x1 = region.extents.y1 = 0; 662 region.extents.x2 = front_priv->pixmap->drawable.width; 663 region.extents.y2 = front_priv->pixmap->drawable.height; 664 region.data = NULL; 665 DamageRegionAppend(&front_priv->pixmap->drawable, ®ion); 666 667 /* Swap BO names so DRI works */ 668 tmp = front->name; 669 front->name = back->name; 670 back->name = tmp; 671 672 /* Swap pixmap privates */ 673 front_pix = amdgpu_get_pixmap_private(front_priv->pixmap); 674 back_pix = amdgpu_get_pixmap_private(back_priv->pixmap); 675 amdgpu_set_pixmap_private(front_priv->pixmap, back_pix); 676 amdgpu_set_pixmap_private(back_priv->pixmap, front_pix); 677 678 /* Do we need to update the Screen? */ 679 screen = draw->pScreen; 680 info = AMDGPUPTR(xf86ScreenToScrn(screen)); 681 if (front_pix->bo == info->front_buffer) { 682 struct amdgpu_pixmap *screen_priv = 683 amdgpu_get_pixmap_private(screen->GetScreenPixmap(screen)); 684 685 amdgpu_bo_ref(back_pix->bo); 686 amdgpu_bo_unref(&info->front_buffer); 687 info->front_buffer = back_pix->bo; 688 *screen_priv = *back_pix; 689 } 690 691 amdgpu_glamor_exchange_buffers(front_priv->pixmap, back_priv->pixmap); 692 693 DamageRegionProcessPending(&front_priv->pixmap->drawable); 694} 695 696static void amdgpu_dri2_frame_event_abort(xf86CrtcPtr crtc, void *event_data) 697{ 698 DRI2FrameEventPtr event = event_data; 699 700 TimerCancel(event->timer); 701 TimerFree(event->timer); 702 amdgpu_dri2_unref_buffer(event->front); 703 amdgpu_dri2_unref_buffer(event->back); 704 free(event); 705} 706 707static void amdgpu_dri2_frame_event_handler(xf86CrtcPtr crtc, uint32_t seq, 708 uint64_t usec, void *event_data) 709{ 710 DRI2FrameEventPtr event = event_data; 711 ScrnInfoPtr scrn = crtc->scrn; 712 DrawablePtr drawable; 713 int status; 714 int swap_type; 715 BoxRec box; 716 RegionRec region; 717 718 status = dixLookupDrawable(&drawable, event->drawable_id, serverClient, 719 M_ANY, DixWriteAccess); 720 if (status != Success) 721 goto cleanup; 722 723 seq += amdgpu_get_msc_delta(drawable, crtc); 724 725 switch (event->type) { 726 case DRI2_FLIP: 727 if (can_flip(scrn, drawable, event->front, event->back) && 728 amdgpu_dri2_schedule_flip(crtc, 729 event->client, 730 drawable, 731 event->front, 732 event->back, 733 event->event_complete, 734 event->event_data, 735 event->frame)) { 736 amdgpu_dri2_exchange_buffers(drawable, event->front, 737 event->back); 738 break; 739 } 740 /* else fall through to exchange/blit */ 741 case DRI2_SWAP: 742 if (DRI2CanExchange(drawable) && 743 can_exchange(scrn, drawable, event->front, event->back)) { 744 amdgpu_dri2_exchange_buffers(drawable, event->front, 745 event->back); 746 swap_type = DRI2_EXCHANGE_COMPLETE; 747 } else { 748 box.x1 = 0; 749 box.y1 = 0; 750 box.x2 = drawable->width; 751 box.y2 = drawable->height; 752 REGION_INIT(pScreen, ®ion, &box, 0); 753 amdgpu_dri2_copy_region(drawable, ®ion, event->front, 754 event->back); 755 swap_type = DRI2_BLIT_COMPLETE; 756 } 757 758 DRI2SwapComplete(event->client, drawable, seq, usec / 1000000, 759 usec % 1000000, swap_type, event->event_complete, 760 event->event_data); 761 762 break; 763 case DRI2_WAITMSC: 764 DRI2WaitMSCComplete(event->client, drawable, seq, usec / 1000000, 765 usec % 1000000); 766 break; 767 default: 768 /* Unknown type */ 769 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 770 "%s: unknown vblank event received\n", __func__); 771 break; 772 } 773 774cleanup: 775 amdgpu_dri2_frame_event_abort(crtc, event_data); 776} 777 778drmVBlankSeqType amdgpu_populate_vbl_request_type(xf86CrtcPtr crtc) 779{ 780 drmVBlankSeqType type = 0; 781 int crtc_id = drmmode_get_crtc_id(crtc); 782 783 if (crtc_id == 1) 784 type |= DRM_VBLANK_SECONDARY; 785 else if (crtc_id > 1) 786#ifdef DRM_VBLANK_HIGH_CRTC_SHIFT 787 type |= (crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT) & 788 DRM_VBLANK_HIGH_CRTC_MASK; 789#else 790 ErrorF("amdgpu driver bug: %s called for CRTC %d > 1, but " 791 "DRM_VBLANK_HIGH_CRTC_MASK not defined at build time\n", 792 __func__, crtc_id); 793#endif 794 795 return type; 796} 797 798/* 799 * This function should be called on a disabled CRTC only (i.e., CRTC 800 * in DPMS-off state). It will calculate the delay necessary to reach 801 * target_msc from present time if the CRTC were running. 802 */ 803static 804CARD32 amdgpu_dri2_extrapolate_msc_delay(xf86CrtcPtr crtc, CARD64 * target_msc, 805 CARD64 divisor, CARD64 remainder) 806{ 807 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 808 ScrnInfoPtr pScrn = crtc->scrn; 809 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 810 int nominal_frame_rate = drmmode_crtc->dpms_last_fps; 811 CARD64 last_vblank_ust = drmmode_crtc->dpms_last_ust; 812 uint32_t last_vblank_seq = drmmode_crtc->dpms_last_seq; 813 CARD64 now, target_time, delta_t; 814 int64_t d, delta_seq; 815 int ret; 816 CARD32 d_ms; 817 818 if (!last_vblank_ust) { 819 *target_msc = 0; 820 return FALLBACK_SWAP_DELAY; 821 } 822 ret = drmmode_get_current_ust(pAMDGPUEnt->fd, &now); 823 if (ret) { 824 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 825 "%s cannot get current time\n", __func__); 826 *target_msc = 0; 827 return FALLBACK_SWAP_DELAY; 828 } 829 delta_seq = *target_msc - last_vblank_seq; 830 delta_seq *= 1000000; 831 target_time = last_vblank_ust; 832 target_time += delta_seq / nominal_frame_rate; 833 d = target_time - now; 834 if (d < 0) { 835 /* we missed the event, adjust target_msc, do the divisor magic */ 836 CARD64 current_msc = last_vblank_seq; 837 838 delta_t = now - last_vblank_ust; 839 delta_seq = delta_t * nominal_frame_rate; 840 current_msc += delta_seq / 1000000; 841 current_msc &= 0xffffffff; 842 if (divisor == 0) { 843 *target_msc = current_msc; 844 d = 0; 845 } else { 846 *target_msc = 847 current_msc - (current_msc % divisor) + remainder; 848 if ((current_msc % divisor) >= remainder) 849 *target_msc += divisor; 850 *target_msc &= 0xffffffff; 851 delta_seq = *target_msc - last_vblank_seq; 852 delta_seq *= 1000000; 853 target_time = last_vblank_ust; 854 target_time += delta_seq / nominal_frame_rate; 855 d = target_time - now; 856 } 857 } 858 /* 859 * convert delay to milliseconds and add margin to prevent the client 860 * from coming back early (due to timer granularity and rounding 861 * errors) and getting the same MSC it just got 862 */ 863 d_ms = (CARD32) d / 1000; 864 if ((CARD32) d - d_ms * 1000 > 0) 865 d_ms += 2; 866 else 867 d_ms++; 868 return d_ms; 869} 870 871/* 872 * Get current interpolated frame count and frame count timestamp, based on 873 * drawable's crtc. 874 */ 875static int amdgpu_dri2_get_msc(DrawablePtr draw, CARD64 * ust, CARD64 * msc) 876{ 877 xf86CrtcPtr crtc = amdgpu_dri2_drawable_crtc(draw, TRUE); 878 879 /* Drawable not displayed, make up a value */ 880 if (crtc == NULL) { 881 *ust = 0; 882 *msc = 0; 883 return TRUE; 884 } 885 886 if (!amdgpu_dri2_get_crtc_msc(crtc, ust, msc)) 887 return FALSE; 888 889 if (draw && draw->type == DRAWABLE_WINDOW) 890 *msc += get_dri2_window_priv((WindowPtr)draw)->vblank_delta; 891 *msc &= 0xffffffff; 892 return TRUE; 893} 894 895static 896CARD32 amdgpu_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data) 897{ 898 DRI2FrameEventPtr event_info = (DRI2FrameEventPtr) data; 899 xf86CrtcPtr crtc = event_info->crtc; 900 ScrnInfoPtr scrn; 901 AMDGPUEntPtr pAMDGPUEnt; 902 CARD64 drm_now; 903 int ret; 904 CARD64 delta_t, delta_seq, frame; 905 drmmode_crtc_private_ptr drmmode_crtc; 906 907 /* 908 * This is emulated event, so its time is current time, which we 909 * have to get in DRM-compatible form (which is a bit messy given 910 * the information that we have at this point). Can't use now argument 911 * because DRM event time may come from monotonic clock, while 912 * DIX timer facility uses real-time clock. 913 */ 914 if (!event_info->crtc) { 915 ErrorF("%s no crtc\n", __func__); 916 if (event_info->drm_queue_seq) 917 amdgpu_drm_abort_entry(event_info->drm_queue_seq); 918 else 919 amdgpu_dri2_frame_event_abort(NULL, data); 920 return 0; 921 } 922 923 scrn = crtc->scrn; 924 pAMDGPUEnt = AMDGPUEntPriv(scrn); 925 ret = drmmode_get_current_ust(pAMDGPUEnt->fd, &drm_now); 926 if (ret) { 927 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 928 "%s cannot get current time\n", __func__); 929 if (event_info->drm_queue_seq) 930 amdgpu_drm_queue_handler(pAMDGPUEnt->fd, 0, 0, 0, 931 (void*)event_info->drm_queue_seq); 932 else 933 amdgpu_dri2_frame_event_handler(crtc, 0, 0, data); 934 return 0; 935 } 936 /* 937 * calculate the frame number from current time 938 * that would come from CRTC if it were running 939 */ 940 drmmode_crtc = event_info->crtc->driver_private; 941 delta_t = drm_now - (CARD64) drmmode_crtc->dpms_last_ust; 942 delta_seq = delta_t * drmmode_crtc->dpms_last_fps; 943 delta_seq /= 1000000; 944 frame = (CARD64) drmmode_crtc->dpms_last_seq + delta_seq; 945 if (event_info->drm_queue_seq) 946 amdgpu_drm_queue_handler(pAMDGPUEnt->fd, frame, drm_now / 1000000, 947 drm_now % 1000000, 948 (void*)event_info->drm_queue_seq); 949 else 950 amdgpu_dri2_frame_event_handler(crtc, frame, drm_now, data); 951 return 0; 952} 953 954static 955void amdgpu_dri2_schedule_event(CARD32 delay, DRI2FrameEventPtr event_info) 956{ 957 event_info->timer = TimerSet(NULL, 0, delay, amdgpu_dri2_deferred_event, 958 event_info); 959 if (delay == 0) { 960 CARD32 now = GetTimeInMillis(); 961 amdgpu_dri2_deferred_event(event_info->timer, now, event_info); 962 } 963} 964 965/* 966 * Request a DRM event when the requested conditions will be satisfied. 967 * 968 * We need to handle the event and ask the server to wake up the client when 969 * we receive it. 970 */ 971static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, 972 CARD64 target_msc, CARD64 divisor, 973 CARD64 remainder) 974{ 975 ScreenPtr screen = draw->pScreen; 976 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 977 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 978 DRI2FrameEventPtr wait_info = NULL; 979 uintptr_t drm_queue_seq = 0; 980 xf86CrtcPtr crtc = amdgpu_dri2_drawable_crtc(draw, TRUE); 981 uint32_t msc_delta; 982 drmVBlank vbl; 983 int ret; 984 CARD64 current_msc; 985 986 /* Truncate to match kernel interfaces; means occasional overflow 987 * misses, but that's generally not a big deal */ 988 target_msc &= 0xffffffff; 989 divisor &= 0xffffffff; 990 remainder &= 0xffffffff; 991 992 /* Drawable not visible, return immediately */ 993 if (crtc == NULL) 994 goto out_complete; 995 996 msc_delta = amdgpu_get_msc_delta(draw, crtc); 997 998 wait_info = calloc(1, sizeof(DRI2FrameEventRec)); 999 if (!wait_info) 1000 goto out_complete; 1001 1002 wait_info->drawable_id = draw->id; 1003 wait_info->client = client; 1004 wait_info->type = DRI2_WAITMSC; 1005 wait_info->crtc = crtc; 1006 1007 /* 1008 * CRTC is in DPMS off state, calculate wait time from current time, 1009 * target_msc and last vblank time/sequence when CRTC was turned off 1010 */ 1011 if (!amdgpu_crtc_is_enabled(crtc)) { 1012 CARD32 delay; 1013 target_msc -= msc_delta; 1014 delay = amdgpu_dri2_extrapolate_msc_delay(crtc, &target_msc, 1015 divisor, remainder); 1016 amdgpu_dri2_schedule_event(delay, wait_info); 1017 DRI2BlockClient(client, draw); 1018 return TRUE; 1019 } 1020 1021 /* Get current count */ 1022 vbl.request.type = DRM_VBLANK_RELATIVE; 1023 vbl.request.type |= amdgpu_populate_vbl_request_type(crtc); 1024 vbl.request.sequence = 0; 1025 ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl); 1026 if (ret) { 1027 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1028 "get vblank counter failed: %s\n", strerror(errno)); 1029 goto out_complete; 1030 } 1031 1032 current_msc = vbl.reply.sequence + msc_delta; 1033 current_msc &= 0xffffffff; 1034 1035 drm_queue_seq = amdgpu_drm_queue_alloc(crtc, client, AMDGPU_DRM_QUEUE_ID_DEFAULT, 1036 wait_info, amdgpu_dri2_frame_event_handler, 1037 amdgpu_dri2_frame_event_abort); 1038 if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) { 1039 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1040 "Allocating DRM queue event entry failed.\n"); 1041 goto out_complete; 1042 } 1043 wait_info->drm_queue_seq = drm_queue_seq; 1044 1045 /* 1046 * If divisor is zero, or current_msc is smaller than target_msc, 1047 * we just need to make sure target_msc passes before waking up the 1048 * client. 1049 */ 1050 if (divisor == 0 || current_msc < target_msc) { 1051 /* If target_msc already reached or passed, set it to 1052 * current_msc to ensure we return a reasonable value back 1053 * to the caller. This keeps the client from continually 1054 * sending us MSC targets from the past by forcibly updating 1055 * their count on this call. 1056 */ 1057 if (current_msc >= target_msc) 1058 target_msc = current_msc; 1059 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; 1060 vbl.request.type |= amdgpu_populate_vbl_request_type(crtc); 1061 vbl.request.sequence = target_msc - msc_delta; 1062 vbl.request.signal = drm_queue_seq; 1063 ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl); 1064 if (ret) { 1065 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1066 "get vblank counter failed: %s\n", 1067 strerror(errno)); 1068 goto out_complete; 1069 } 1070 1071 DRI2BlockClient(client, draw); 1072 return TRUE; 1073 } 1074 1075 /* 1076 * If we get here, target_msc has already passed or we don't have one, 1077 * so we queue an event that will satisfy the divisor/remainder equation. 1078 */ 1079 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; 1080 vbl.request.type |= amdgpu_populate_vbl_request_type(crtc); 1081 1082 vbl.request.sequence = current_msc - (current_msc % divisor) + 1083 remainder - msc_delta; 1084 1085 /* 1086 * If calculated remainder is larger than requested remainder, 1087 * it means we've passed the last point where 1088 * seq % divisor == remainder, so we need to wait for the next time 1089 * that will happen. 1090 */ 1091 if ((current_msc % divisor) >= remainder) 1092 vbl.request.sequence += divisor; 1093 1094 vbl.request.signal = drm_queue_seq; 1095 ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl); 1096 if (ret) { 1097 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1098 "get vblank counter failed: %s\n", strerror(errno)); 1099 goto out_complete; 1100 } 1101 1102 DRI2BlockClient(client, draw); 1103 1104 return TRUE; 1105 1106out_complete: 1107 if (wait_info) 1108 amdgpu_dri2_deferred_event(NULL, 0, wait_info); 1109 return TRUE; 1110} 1111 1112/* 1113 * ScheduleSwap is responsible for requesting a DRM vblank event for the 1114 * appropriate frame. 1115 * 1116 * In the case of a blit (e.g. for a windowed swap) or buffer exchange, 1117 * the vblank requested can simply be the last queued swap frame + the swap 1118 * interval for the drawable. 1119 * 1120 * In the case of a page flip, we request an event for the last queued swap 1121 * frame + swap interval - 1, since we'll need to queue the flip for the frame 1122 * immediately following the received event. 1123 * 1124 * The client will be blocked if it tries to perform further GL commands 1125 * after queueing a swap, though in the Intel case after queueing a flip, the 1126 * client is free to queue more commands; they'll block in the kernel if 1127 * they access buffers busy with the flip. 1128 * 1129 * When the swap is complete, the driver should call into the server so it 1130 * can send any swap complete events that have been requested. 1131 */ 1132static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, 1133 DRI2BufferPtr front, DRI2BufferPtr back, 1134 CARD64 * target_msc, CARD64 divisor, 1135 CARD64 remainder, DRI2SwapEventPtr func, 1136 void *data) 1137{ 1138 ScreenPtr screen = draw->pScreen; 1139 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1140 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 1141 xf86CrtcPtr crtc = amdgpu_dri2_drawable_crtc(draw, TRUE); 1142 uint32_t msc_delta; 1143 drmVBlank vbl; 1144 int ret, flip = 0; 1145 DRI2FrameEventPtr swap_info = NULL; 1146 uintptr_t drm_queue_seq; 1147 CARD64 current_msc; 1148 BoxRec box; 1149 RegionRec region; 1150 1151 /* Truncate to match kernel interfaces; means occasional overflow 1152 * misses, but that's generally not a big deal */ 1153 *target_msc &= 0xffffffff; 1154 divisor &= 0xffffffff; 1155 remainder &= 0xffffffff; 1156 1157 /* amdgpu_dri2_frame_event_handler will get called some unknown time in the 1158 * future with these buffers. Take a reference to ensure that they won't 1159 * get destroyed before then. 1160 */ 1161 amdgpu_dri2_ref_buffer(front); 1162 amdgpu_dri2_ref_buffer(back); 1163 1164 /* either off-screen or CRTC not usable... just complete the swap */ 1165 if (crtc == NULL) 1166 goto blit_fallback; 1167 1168 msc_delta = amdgpu_get_msc_delta(draw, crtc); 1169 1170 swap_info = calloc(1, sizeof(DRI2FrameEventRec)); 1171 if (!swap_info) 1172 goto blit_fallback; 1173 1174 swap_info->type = DRI2_SWAP; 1175 swap_info->drawable_id = draw->id; 1176 swap_info->client = client; 1177 swap_info->event_complete = func; 1178 swap_info->event_data = data; 1179 swap_info->front = front; 1180 swap_info->back = back; 1181 swap_info->crtc = crtc; 1182 1183 drm_queue_seq = amdgpu_drm_queue_alloc(crtc, client, AMDGPU_DRM_QUEUE_ID_DEFAULT, 1184 swap_info, amdgpu_dri2_frame_event_handler, 1185 amdgpu_dri2_frame_event_abort); 1186 if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) { 1187 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1188 "Allocating DRM queue entry failed.\n"); 1189 goto blit_fallback; 1190 } 1191 swap_info->drm_queue_seq = drm_queue_seq; 1192 1193 /* 1194 * CRTC is in DPMS off state, fallback to blit, but calculate 1195 * wait time from current time, target_msc and last vblank 1196 * time/sequence when CRTC was turned off 1197 */ 1198 if (!amdgpu_crtc_is_enabled(crtc)) { 1199 CARD32 delay; 1200 *target_msc -= msc_delta; 1201 delay = amdgpu_dri2_extrapolate_msc_delay(crtc, target_msc, 1202 divisor, remainder); 1203 *target_msc += msc_delta; 1204 *target_msc &= 0xffffffff; 1205 amdgpu_dri2_schedule_event(delay, swap_info); 1206 return TRUE; 1207 } 1208 1209 /* Get current count */ 1210 vbl.request.type = DRM_VBLANK_RELATIVE; 1211 vbl.request.type |= amdgpu_populate_vbl_request_type(crtc); 1212 vbl.request.sequence = 0; 1213 ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl); 1214 if (ret) { 1215 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1216 "first get vblank counter failed: %s\n", 1217 strerror(errno)); 1218 goto blit_fallback; 1219 } 1220 1221 current_msc = vbl.reply.sequence + msc_delta; 1222 current_msc &= 0xffffffff; 1223 1224 /* Flips need to be submitted one frame before */ 1225 if (can_flip(scrn, draw, front, back)) { 1226 swap_info->type = DRI2_FLIP; 1227 flip = 1; 1228 } 1229 1230 /* Correct target_msc by 'flip' if swap_info->type == DRI2_FLIP. 1231 * Do it early, so handling of different timing constraints 1232 * for divisor, remainder and msc vs. target_msc works. 1233 */ 1234 if (*target_msc > 0) 1235 *target_msc -= flip; 1236 1237 /* 1238 * If divisor is zero, or current_msc is smaller than target_msc 1239 * we just need to make sure target_msc passes before initiating 1240 * the swap. 1241 */ 1242 if (divisor == 0 || current_msc < *target_msc) { 1243 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; 1244 /* If non-pageflipping, but blitting/exchanging, we need to use 1245 * DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later 1246 * on. 1247 */ 1248 if (flip == 0) 1249 vbl.request.type |= DRM_VBLANK_NEXTONMISS; 1250 vbl.request.type |= amdgpu_populate_vbl_request_type(crtc); 1251 1252 /* If target_msc already reached or passed, set it to 1253 * current_msc to ensure we return a reasonable value back 1254 * to the caller. This makes swap_interval logic more robust. 1255 */ 1256 if (current_msc >= *target_msc) 1257 *target_msc = current_msc; 1258 1259 vbl.request.sequence = *target_msc - msc_delta; 1260 vbl.request.signal = drm_queue_seq; 1261 ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl); 1262 if (ret) { 1263 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1264 "divisor 0 get vblank counter failed: %s\n", 1265 strerror(errno)); 1266 goto blit_fallback; 1267 } 1268 1269 *target_msc = vbl.reply.sequence + flip + msc_delta; 1270 *target_msc &= 0xffffffff; 1271 swap_info->frame = *target_msc; 1272 1273 return TRUE; 1274 } 1275 1276 /* 1277 * If we get here, target_msc has already passed or we don't have one, 1278 * and we need to queue an event that will satisfy the divisor/remainder 1279 * equation. 1280 */ 1281 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; 1282 if (flip == 0) 1283 vbl.request.type |= DRM_VBLANK_NEXTONMISS; 1284 vbl.request.type |= amdgpu_populate_vbl_request_type(crtc); 1285 1286 vbl.request.sequence = current_msc - (current_msc % divisor) + 1287 remainder - msc_delta; 1288 1289 /* 1290 * If the calculated deadline vbl.request.sequence is smaller than 1291 * or equal to current_msc, it means we've passed the last point 1292 * when effective onset frame seq could satisfy 1293 * seq % divisor == remainder, so we need to wait for the next time 1294 * this will happen. 1295 1296 * This comparison takes the 1 frame swap delay in pageflipping mode 1297 * into account, as well as a potential DRM_VBLANK_NEXTONMISS delay 1298 * if we are blitting/exchanging instead of flipping. 1299 */ 1300 if (vbl.request.sequence <= current_msc) 1301 vbl.request.sequence += divisor; 1302 1303 /* Account for 1 frame extra pageflip delay if flip > 0 */ 1304 vbl.request.sequence -= flip; 1305 1306 vbl.request.signal = drm_queue_seq; 1307 ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl); 1308 if (ret) { 1309 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1310 "final get vblank counter failed: %s\n", 1311 strerror(errno)); 1312 goto blit_fallback; 1313 } 1314 1315 /* Adjust returned value for 1 fame pageflip offset of flip > 0 */ 1316 *target_msc = vbl.reply.sequence + flip + msc_delta; 1317 *target_msc &= 0xffffffff; 1318 swap_info->frame = *target_msc; 1319 1320 return TRUE; 1321 1322blit_fallback: 1323 if (swap_info) { 1324 swap_info->type = DRI2_SWAP; 1325 amdgpu_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info); 1326 } else { 1327 box.x1 = 0; 1328 box.y1 = 0; 1329 box.x2 = draw->width; 1330 box.y2 = draw->height; 1331 REGION_INIT(pScreen, ®ion, &box, 0); 1332 1333 amdgpu_dri2_copy_region(draw, ®ion, front, back); 1334 1335 DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data); 1336 1337 amdgpu_dri2_unref_buffer(front); 1338 amdgpu_dri2_unref_buffer(back); 1339 } 1340 1341 *target_msc = 0; /* offscreen, so zero out target vblank count */ 1342 return TRUE; 1343} 1344 1345Bool amdgpu_dri2_screen_init(ScreenPtr pScreen) 1346{ 1347 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1348 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1349 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1350 DRI2InfoRec dri2_info = { 0 }; 1351 const char *driverNames[2]; 1352 Bool scheduling_works = TRUE; 1353 1354 if (!info->dri2.available) 1355 return FALSE; 1356 1357 info->dri2.device_name = drmGetDeviceNameFromFd(pAMDGPUEnt->fd); 1358 1359 dri2_info.driverName = SI_DRIVER_NAME; 1360 dri2_info.fd = pAMDGPUEnt->fd; 1361 dri2_info.deviceName = info->dri2.device_name; 1362 dri2_info.version = DRI2INFOREC_VERSION; 1363 dri2_info.CreateBuffer = amdgpu_dri2_create_buffer; 1364 dri2_info.DestroyBuffer = amdgpu_dri2_destroy_buffer; 1365 dri2_info.CopyRegion = amdgpu_dri2_copy_region; 1366 1367 if (info->drmmode.count_crtcs > 2) { 1368#ifdef DRM_CAP_VBLANK_HIGH_CRTC 1369 uint64_t cap_value; 1370 1371 if (drmGetCap 1372 (pAMDGPUEnt->fd, DRM_CAP_VBLANK_HIGH_CRTC, &cap_value)) { 1373 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1374 "You need a newer kernel " 1375 "for VBLANKs on CRTC > 1\n"); 1376 scheduling_works = FALSE; 1377 } else if (!cap_value) { 1378 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1379 "Your kernel does not " 1380 "handle VBLANKs on CRTC > 1\n"); 1381 scheduling_works = FALSE; 1382 } 1383#else 1384 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1385 "You need to rebuild against a " 1386 "newer libdrm to handle VBLANKs on CRTC > 1\n"); 1387 scheduling_works = FALSE; 1388#endif 1389 } 1390 1391 if (scheduling_works) { 1392 dri2_info.version = 4; 1393 dri2_info.ScheduleSwap = amdgpu_dri2_schedule_swap; 1394 dri2_info.GetMSC = amdgpu_dri2_get_msc; 1395 dri2_info.ScheduleWaitMSC = amdgpu_dri2_schedule_wait_msc; 1396 dri2_info.numDrivers = AMDGPU_ARRAY_SIZE(driverNames); 1397 dri2_info.driverNames = driverNames; 1398 driverNames[0] = driverNames[1] = dri2_info.driverName; 1399 1400 if (DRI2InfoCnt == 0) { 1401 if (!dixRegisterPrivateKey(dri2_window_private_key, 1402 PRIVATE_WINDOW, 1403 sizeof(struct dri2_window_priv))) { 1404 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1405 "Failed to get DRI2 window private\n"); 1406 return FALSE; 1407 } 1408 1409 AddCallback(&ClientStateCallback, 1410 amdgpu_dri2_client_state_changed, 0); 1411 } 1412 1413 DRI2InfoCnt++; 1414 } 1415 1416#if DRI2INFOREC_VERSION >= 9 1417 dri2_info.version = 9; 1418 dri2_info.CreateBuffer2 = amdgpu_dri2_create_buffer2; 1419 dri2_info.DestroyBuffer2 = amdgpu_dri2_destroy_buffer2; 1420 dri2_info.CopyRegion2 = amdgpu_dri2_copy_region2; 1421#endif 1422 1423 info->dri2.enabled = DRI2ScreenInit(pScreen, &dri2_info); 1424 return info->dri2.enabled; 1425} 1426 1427void amdgpu_dri2_close_screen(ScreenPtr pScreen) 1428{ 1429 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1430 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1431 1432 if (--DRI2InfoCnt == 0) 1433 DeleteCallback(&ClientStateCallback, 1434 amdgpu_dri2_client_state_changed, 0); 1435 1436 DRI2CloseScreen(pScreen); 1437 drmFree(info->dri2.device_name); 1438} 1439 1440#endif /* DRI2 */ 1441