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