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