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