amdgpu_dri2.c revision 35d5b7c7
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 176 if (!amdgpu_get_flink_name(pAMDGPUEnt, pixmap, &buffers->name)) 177 goto error; 178 179 privates = calloc(1, sizeof(struct dri2_buffer_priv)); 180 if (!privates) 181 goto error; 182 183 buffers->attachment = attachment; 184 buffers->pitch = pixmap->devKind; 185 buffers->cpp = cpp; 186 buffers->driverPrivate = privates; 187 buffers->format = format; 188 buffers->flags = 0; /* not tiled */ 189 privates->pixmap = pixmap; 190 privates->attachment = attachment; 191 privates->refcnt = 1; 192 193 return buffers; 194 195error: 196 free(buffers); 197 (*pScreen->DestroyPixmap) (pixmap); 198 return NULL; 199} 200 201static void 202amdgpu_dri2_destroy_buffer2(ScreenPtr pScreen, 203 DrawablePtr drawable, BufferPtr buffers) 204{ 205 if (buffers) { 206 struct dri2_buffer_priv *private = buffers->driverPrivate; 207 208 /* Trying to free an already freed buffer is unlikely to end well */ 209 if (private->refcnt == 0) { 210 ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 211 212 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 213 "Attempted to destroy previously destroyed buffer.\ 214 This is a programming error\n"); 215 return; 216 } 217 218 private->refcnt--; 219 if (private->refcnt == 0) { 220 if (private->pixmap) 221 (*pScreen->DestroyPixmap) (private->pixmap); 222 223 free(buffers->driverPrivate); 224 free(buffers); 225 } 226 } 227} 228 229static inline PixmapPtr GetDrawablePixmap(DrawablePtr drawable) 230{ 231 if (drawable->type == DRAWABLE_PIXMAP) 232 return (PixmapPtr) drawable; 233 else { 234 struct _Window *pWin = (struct _Window *)drawable; 235 return drawable->pScreen->GetWindowPixmap(pWin); 236 } 237} 238 239static void 240amdgpu_dri2_copy_region2(ScreenPtr pScreen, 241 DrawablePtr drawable, 242 RegionPtr region, 243 BufferPtr dest_buffer, BufferPtr src_buffer) 244{ 245 struct dri2_buffer_priv *src_private = src_buffer->driverPrivate; 246 struct dri2_buffer_priv *dst_private = dest_buffer->driverPrivate; 247 DrawablePtr src_drawable; 248 DrawablePtr dst_drawable; 249 RegionPtr copy_clip; 250 GCPtr gc; 251 Bool translate = FALSE; 252 int off_x = 0, off_y = 0; 253 254 src_drawable = &src_private->pixmap->drawable; 255 dst_drawable = &dst_private->pixmap->drawable; 256 257 if (src_private->attachment == DRI2BufferFrontLeft) { 258 if (drawable->pScreen != pScreen) { 259 src_drawable = DRI2UpdatePrime(drawable, src_buffer); 260 if (!src_drawable) 261 return; 262 } else 263 src_drawable = drawable; 264 } 265 if (dst_private->attachment == DRI2BufferFrontLeft) { 266 if (drawable->pScreen != pScreen) { 267 dst_drawable = DRI2UpdatePrime(drawable, dest_buffer); 268 if (!dst_drawable) 269 return; 270 if (dst_drawable != drawable) 271 translate = TRUE; 272 } else 273 dst_drawable = drawable; 274 } 275 276 if (translate && drawable->type == DRAWABLE_WINDOW) { 277 PixmapPtr pPix = GetDrawablePixmap(drawable); 278 279 off_x = drawable->x - pPix->screen_x; 280 off_y = drawable->y - pPix->screen_y; 281 } 282 gc = GetScratchGC(dst_drawable->depth, pScreen); 283 copy_clip = REGION_CREATE(pScreen, NULL, 0); 284 REGION_COPY(pScreen, copy_clip, region); 285 286 if (translate) { 287 REGION_TRANSLATE(pScreen, copy_clip, off_x, off_y); 288 } 289 290 (*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0); 291 ValidateGC(dst_drawable, gc); 292 293 (*gc->ops->CopyArea) (src_drawable, dst_drawable, gc, 294 0, 0, drawable->width, drawable->height, off_x, 295 off_y); 296 297 FreeScratchGC(gc); 298} 299 300enum DRI2FrameEventType { 301 DRI2_SWAP, 302 DRI2_FLIP, 303 DRI2_WAITMSC, 304}; 305 306typedef struct _DRI2FrameEvent { 307 XID drawable_id; 308 ClientPtr client; 309 enum DRI2FrameEventType type; 310 unsigned frame; 311 xf86CrtcPtr crtc; 312 OsTimerPtr timer; 313 uintptr_t drm_queue_seq; 314 315 /* for swaps & flips only */ 316 DRI2SwapEventPtr event_complete; 317 void *event_data; 318 DRI2BufferPtr front; 319 DRI2BufferPtr back; 320} DRI2FrameEventRec, *DRI2FrameEventPtr; 321 322static int DRI2InfoCnt; 323 324static void amdgpu_dri2_ref_buffer(BufferPtr buffer) 325{ 326 struct dri2_buffer_priv *private = buffer->driverPrivate; 327 private->refcnt++; 328} 329 330static void amdgpu_dri2_unref_buffer(BufferPtr buffer) 331{ 332 if (buffer) { 333 struct dri2_buffer_priv *private = buffer->driverPrivate; 334 DrawablePtr draw = &private->pixmap->drawable; 335 336 amdgpu_dri2_destroy_buffer2(draw->pScreen, draw, buffer); 337 } 338} 339 340static void 341amdgpu_dri2_client_state_changed(CallbackListPtr * ClientStateCallback, 342 pointer data, pointer calldata) 343{ 344 NewClientInfoRec *clientinfo = calldata; 345 ClientPtr pClient = clientinfo->client; 346 347 switch (pClient->clientState) { 348 case ClientStateRetained: 349 case ClientStateGone: 350 amdgpu_drm_abort_client(pClient); 351 break; 352 default: 353 break; 354 } 355} 356 357/* 358 * Get current frame count delta for the specified drawable and CRTC 359 */ 360static uint32_t amdgpu_get_msc_delta(DrawablePtr pDraw, xf86CrtcPtr crtc) 361{ 362 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 363 364 if (pDraw && pDraw->type == DRAWABLE_WINDOW) 365 return drmmode_crtc->interpolated_vblanks + 366 get_dri2_window_priv((WindowPtr)pDraw)->vblank_delta; 367 368 return drmmode_crtc->interpolated_vblanks; 369} 370 371/* 372 * Get current frame count and timestamp of the specified CRTC 373 */ 374static Bool amdgpu_dri2_get_crtc_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc) 375{ 376 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 377 378 if (!amdgpu_crtc_is_enabled(crtc) || 379 drmmode_crtc_get_ust_msc(crtc, ust, msc) != Success) { 380 /* CRTC is not running, extrapolate MSC and timestamp */ 381 ScrnInfoPtr scrn = crtc->scrn; 382 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 383 CARD64 now, delta_t, delta_seq; 384 385 if (!drmmode_crtc->dpms_last_ust) 386 return FALSE; 387 388 if (drmmode_get_current_ust(pAMDGPUEnt->fd, &now) != 0) { 389 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 390 "%s cannot get current time\n", __func__); 391 return FALSE; 392 } 393 394 delta_t = now - drmmode_crtc->dpms_last_ust; 395 delta_seq = delta_t * drmmode_crtc->dpms_last_fps; 396 delta_seq /= 1000000; 397 *ust = drmmode_crtc->dpms_last_ust; 398 delta_t = delta_seq * 1000000; 399 delta_t /= drmmode_crtc->dpms_last_fps; 400 *ust += delta_t; 401 *msc = drmmode_crtc->dpms_last_seq; 402 *msc += delta_seq; 403 } 404 405 *msc += drmmode_crtc->interpolated_vblanks; 406 407 return TRUE; 408} 409 410static 411xf86CrtcPtr amdgpu_dri2_drawable_crtc(DrawablePtr pDraw, Bool consider_disabled) 412{ 413 ScreenPtr pScreen = pDraw->pScreen; 414 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 415 xf86CrtcPtr crtc = amdgpu_pick_best_crtc(pScrn, consider_disabled, 416 pDraw->x, pDraw->x + pDraw->width, 417 pDraw->y, pDraw->y + pDraw->height); 418 419 if (crtc && pDraw->type == DRAWABLE_WINDOW) { 420 struct dri2_window_priv *priv = get_dri2_window_priv((WindowPtr)pDraw); 421 422 if (priv->crtc && priv->crtc != crtc) { 423 CARD64 ust, mscold, mscnew; 424 425 if (amdgpu_dri2_get_crtc_msc(priv->crtc, &ust, &mscold) && 426 amdgpu_dri2_get_crtc_msc(crtc, &ust, &mscnew)) 427 priv->vblank_delta += mscold - mscnew; 428 } 429 430 priv->crtc = crtc; 431 } 432 433 return crtc; 434} 435 436static void 437amdgpu_dri2_flip_event_abort(xf86CrtcPtr crtc, void *event_data) 438{ 439 if (crtc) 440 AMDGPUPTR(crtc->scrn)->drmmode.dri2_flipping = FALSE; 441 442 free(event_data); 443} 444 445static void 446amdgpu_dri2_flip_event_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, 447 void *event_data) 448{ 449 DRI2FrameEventPtr flip = event_data; 450 ScrnInfoPtr scrn = crtc->scrn; 451 unsigned tv_sec, tv_usec; 452 DrawablePtr drawable; 453 ScreenPtr screen; 454 int status; 455 PixmapPtr pixmap; 456 457 status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient, 458 M_ANY, DixWriteAccess); 459 if (status != Success) 460 goto abort; 461 462 frame += amdgpu_get_msc_delta(drawable, crtc); 463 464 screen = scrn->pScreen; 465 pixmap = screen->GetScreenPixmap(screen); 466 xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 467 "%s:%d fevent[%p] width %d pitch %d (/4 %d)\n", 468 __func__, __LINE__, flip, pixmap->drawable.width, 469 pixmap->devKind, pixmap->devKind / 4); 470 471 tv_sec = usec / 1000000; 472 tv_usec = usec % 1000000; 473 474 /* We assume our flips arrive in order, so we don't check the frame */ 475 switch (flip->type) { 476 case DRI2_SWAP: 477 /* Check for too small vblank count of pageflip completion, taking wraparound 478 * into account. This usually means some defective kms pageflip completion, 479 * causing wrong (msc, ust) return values and possible visual corruption. 480 */ 481 if ((frame < flip->frame) && (flip->frame - frame < 5)) { 482 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 483 "%s: Pageflip completion event has impossible msc %u < target_msc %u\n", 484 __func__, frame, flip->frame); 485 /* All-Zero values signal failure of (msc, ust) timestamping to client. */ 486 frame = tv_sec = tv_usec = 0; 487 } 488 489 DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec, 490 DRI2_FLIP_COMPLETE, flip->event_complete, 491 flip->event_data); 492 break; 493 default: 494 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 495 "%s: unknown vblank event received\n", __func__); 496 /* Unknown type */ 497 break; 498 } 499 500abort: 501 amdgpu_dri2_flip_event_abort(crtc, event_data); 502} 503 504static Bool 505amdgpu_dri2_schedule_flip(xf86CrtcPtr crtc, ClientPtr client, 506 DrawablePtr draw, DRI2BufferPtr front, 507 DRI2BufferPtr back, DRI2SwapEventPtr func, 508 void *data, unsigned int target_msc) 509{ 510 ScrnInfoPtr scrn = crtc->scrn; 511 AMDGPUInfoPtr info = AMDGPUPTR(scrn); 512 struct dri2_buffer_priv *back_priv; 513 DRI2FrameEventPtr flip_info; 514 515 flip_info = calloc(1, sizeof(DRI2FrameEventRec)); 516 if (!flip_info) 517 return FALSE; 518 519 flip_info->drawable_id = draw->id; 520 flip_info->client = client; 521 flip_info->type = DRI2_SWAP; 522 flip_info->event_complete = func; 523 flip_info->event_data = data; 524 flip_info->frame = target_msc; 525 flip_info->crtc = crtc; 526 527 xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 528 "%s:%d fevent[%p]\n", __func__, __LINE__, flip_info); 529 530 /* Page flip the full screen buffer */ 531 back_priv = back->driverPrivate; 532 if (amdgpu_do_pageflip(scrn, client, back_priv->pixmap, 533 AMDGPU_DRM_QUEUE_ID_DEFAULT, flip_info, crtc, 534 amdgpu_dri2_flip_event_handler, 535 amdgpu_dri2_flip_event_abort, FLIP_VSYNC, 536 target_msc - amdgpu_get_msc_delta(draw, crtc))) { 537 info->drmmode.dri2_flipping = TRUE; 538 return TRUE; 539 } 540 return FALSE; 541} 542 543static Bool update_front(DrawablePtr draw, DRI2BufferPtr front) 544{ 545 ScreenPtr screen = draw->pScreen; 546 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 547 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 548 PixmapPtr pixmap = get_drawable_pixmap(draw); 549 struct dri2_buffer_priv *priv = front->driverPrivate; 550 551 if (!amdgpu_get_flink_name(pAMDGPUEnt, pixmap, &front->name)) 552 return FALSE; 553 554 (*draw->pScreen->DestroyPixmap) (priv->pixmap); 555 front->pitch = pixmap->devKind; 556 front->cpp = pixmap->drawable.bitsPerPixel / 8; 557 priv->pixmap = pixmap; 558 pixmap->refcnt++; 559 560 return TRUE; 561} 562 563static Bool 564can_exchange(ScrnInfoPtr pScrn, DrawablePtr draw, 565 DRI2BufferPtr front, DRI2BufferPtr back) 566{ 567 struct dri2_buffer_priv *front_priv = front->driverPrivate; 568 struct dri2_buffer_priv *back_priv = back->driverPrivate; 569 PixmapPtr front_pixmap; 570 PixmapPtr back_pixmap = back_priv->pixmap; 571 572 if (!update_front(draw, front)) 573 return FALSE; 574 575 front_pixmap = front_priv->pixmap; 576 577 if (front_pixmap->drawable.width != back_pixmap->drawable.width) 578 return FALSE; 579 580 if (front_pixmap->drawable.height != back_pixmap->drawable.height) 581 return FALSE; 582 583 if (front_pixmap->drawable.bitsPerPixel != 584 back_pixmap->drawable.bitsPerPixel) 585 return FALSE; 586 587 if (front_pixmap->devKind != back_pixmap->devKind) 588 return FALSE; 589 590 return TRUE; 591} 592 593static Bool 594can_flip(xf86CrtcPtr crtc, DrawablePtr draw, 595 DRI2BufferPtr front, DRI2BufferPtr back) 596{ 597 ScrnInfoPtr pScrn = crtc->scrn; 598 AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 599 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 600 int num_crtcs_on; 601 int i; 602 603 if (draw->type != DRAWABLE_WINDOW || 604 !info->allowPageFlip || 605 info->sprites_visible > 0 || 606 info->drmmode.present_flipping || 607 !pScrn->vtSema || 608 !DRI2CanFlip(draw)) 609 return FALSE; 610 611 for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) { 612 if (drmmode_crtc_can_flip(config->crtc[i])) 613 num_crtcs_on++; 614 } 615 616 return num_crtcs_on > 0 && can_exchange(pScrn, draw, front, back); 617} 618 619static void 620amdgpu_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front, 621 DRI2BufferPtr back) 622{ 623 struct dri2_buffer_priv *front_priv = front->driverPrivate; 624 struct dri2_buffer_priv *back_priv = back->driverPrivate; 625 struct amdgpu_pixmap *front_pix; 626 struct amdgpu_pixmap *back_pix; 627 ScreenPtr screen; 628 AMDGPUInfoPtr info; 629 RegionRec region; 630 int tmp; 631 632 region.extents.x1 = region.extents.y1 = 0; 633 region.extents.x2 = front_priv->pixmap->drawable.width; 634 region.extents.y2 = front_priv->pixmap->drawable.height; 635 region.data = NULL; 636 DamageRegionAppend(&front_priv->pixmap->drawable, ®ion); 637 638 /* Swap BO names so DRI works */ 639 tmp = front->name; 640 front->name = back->name; 641 back->name = tmp; 642 643 /* Swap pixmap privates */ 644 front_pix = amdgpu_get_pixmap_private(front_priv->pixmap); 645 back_pix = amdgpu_get_pixmap_private(back_priv->pixmap); 646 amdgpu_set_pixmap_private(front_priv->pixmap, back_pix); 647 amdgpu_set_pixmap_private(back_priv->pixmap, front_pix); 648 649 /* Do we need to update the Screen? */ 650 screen = draw->pScreen; 651 info = AMDGPUPTR(xf86ScreenToScrn(screen)); 652 if (front_pix->bo == info->front_buffer) { 653 struct amdgpu_pixmap *screen_priv = 654 amdgpu_get_pixmap_private(screen->GetScreenPixmap(screen)); 655 656 amdgpu_bo_ref(back_pix->bo); 657 amdgpu_bo_unref(&info->front_buffer); 658 info->front_buffer = back_pix->bo; 659 *screen_priv = *back_pix; 660 } 661 662 amdgpu_glamor_exchange_buffers(front_priv->pixmap, back_priv->pixmap); 663 664 DamageRegionProcessPending(&front_priv->pixmap->drawable); 665} 666 667static void amdgpu_dri2_frame_event_abort(xf86CrtcPtr crtc, void *event_data) 668{ 669 DRI2FrameEventPtr event = event_data; 670 671 TimerCancel(event->timer); 672 TimerFree(event->timer); 673 amdgpu_dri2_unref_buffer(event->front); 674 amdgpu_dri2_unref_buffer(event->back); 675 free(event); 676} 677 678static void amdgpu_dri2_frame_event_handler(xf86CrtcPtr crtc, uint32_t seq, 679 uint64_t usec, void *event_data) 680{ 681 DRI2FrameEventPtr event = event_data; 682 ScrnInfoPtr scrn = crtc->scrn; 683 DrawablePtr drawable; 684 int status; 685 int swap_type; 686 BoxRec box; 687 RegionRec region; 688 689 status = dixLookupDrawable(&drawable, event->drawable_id, serverClient, 690 M_ANY, DixWriteAccess); 691 if (status != Success) 692 goto cleanup; 693 694 seq += amdgpu_get_msc_delta(drawable, crtc); 695 696 switch (event->type) { 697 case DRI2_FLIP: 698 if (can_flip(crtc, drawable, event->front, event->back) && 699 amdgpu_dri2_schedule_flip(crtc, 700 event->client, 701 drawable, 702 event->front, 703 event->back, 704 event->event_complete, 705 event->event_data, 706 event->frame)) { 707 amdgpu_dri2_exchange_buffers(drawable, event->front, 708 event->back); 709 break; 710 } 711 /* else fall through to exchange/blit */ 712 case DRI2_SWAP: 713 if (DRI2CanExchange(drawable) && 714 can_exchange(scrn, drawable, event->front, event->back)) { 715 amdgpu_dri2_exchange_buffers(drawable, event->front, 716 event->back); 717 swap_type = DRI2_EXCHANGE_COMPLETE; 718 } else { 719 box.x1 = 0; 720 box.y1 = 0; 721 box.x2 = drawable->width; 722 box.y2 = drawable->height; 723 REGION_INIT(pScreen, ®ion, &box, 0); 724 amdgpu_dri2_copy_region2(drawable->pScreen, drawable, ®ion, 725 event->front, event->back); 726 swap_type = DRI2_BLIT_COMPLETE; 727 } 728 729 DRI2SwapComplete(event->client, drawable, seq, usec / 1000000, 730 usec % 1000000, swap_type, event->event_complete, 731 event->event_data); 732 733 break; 734 case DRI2_WAITMSC: 735 DRI2WaitMSCComplete(event->client, drawable, seq, usec / 1000000, 736 usec % 1000000); 737 break; 738 default: 739 /* Unknown type */ 740 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 741 "%s: unknown vblank event received\n", __func__); 742 break; 743 } 744 745cleanup: 746 amdgpu_dri2_frame_event_abort(crtc, event_data); 747} 748 749/* 750 * This function should be called on a disabled CRTC only (i.e., CRTC 751 * in DPMS-off state). It will calculate the delay necessary to reach 752 * target_msc from present time if the CRTC were running. 753 */ 754static 755CARD32 amdgpu_dri2_extrapolate_msc_delay(xf86CrtcPtr crtc, CARD64 * target_msc, 756 CARD64 divisor, CARD64 remainder) 757{ 758 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 759 ScrnInfoPtr pScrn = crtc->scrn; 760 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 761 int nominal_frame_rate = drmmode_crtc->dpms_last_fps; 762 CARD64 last_vblank_ust = drmmode_crtc->dpms_last_ust; 763 uint32_t last_vblank_seq = drmmode_crtc->dpms_last_seq; 764 CARD64 now, target_time, delta_t; 765 int64_t d, delta_seq; 766 int ret; 767 CARD32 d_ms; 768 769 if (!last_vblank_ust) { 770 *target_msc = 0; 771 return FALLBACK_SWAP_DELAY; 772 } 773 ret = drmmode_get_current_ust(pAMDGPUEnt->fd, &now); 774 if (ret) { 775 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 776 "%s cannot get current time\n", __func__); 777 *target_msc = 0; 778 return FALLBACK_SWAP_DELAY; 779 } 780 delta_seq = *target_msc - last_vblank_seq; 781 delta_seq *= 1000000; 782 target_time = last_vblank_ust; 783 target_time += delta_seq / nominal_frame_rate; 784 d = target_time - now; 785 if (d < 0) { 786 /* we missed the event, adjust target_msc, do the divisor magic */ 787 CARD64 current_msc = last_vblank_seq; 788 789 delta_t = now - last_vblank_ust; 790 delta_seq = delta_t * nominal_frame_rate; 791 current_msc += delta_seq / 1000000; 792 current_msc &= 0xffffffff; 793 if (divisor == 0) { 794 *target_msc = current_msc; 795 d = 0; 796 } else { 797 *target_msc = 798 current_msc - (current_msc % divisor) + remainder; 799 if ((current_msc % divisor) >= remainder) 800 *target_msc += divisor; 801 *target_msc &= 0xffffffff; 802 delta_seq = *target_msc - last_vblank_seq; 803 delta_seq *= 1000000; 804 target_time = last_vblank_ust; 805 target_time += delta_seq / nominal_frame_rate; 806 d = target_time - now; 807 } 808 } 809 /* 810 * convert delay to milliseconds and add margin to prevent the client 811 * from coming back early (due to timer granularity and rounding 812 * errors) and getting the same MSC it just got 813 */ 814 d_ms = (CARD32) d / 1000; 815 if ((CARD32) d - d_ms * 1000 > 0) 816 d_ms += 2; 817 else 818 d_ms++; 819 return d_ms; 820} 821 822/* 823 * Get current interpolated frame count and frame count timestamp, based on 824 * drawable's crtc. 825 */ 826static int amdgpu_dri2_get_msc(DrawablePtr draw, CARD64 * ust, CARD64 * msc) 827{ 828 xf86CrtcPtr crtc = amdgpu_dri2_drawable_crtc(draw, TRUE); 829 830 /* Drawable not displayed, make up a value */ 831 if (!crtc) { 832 *ust = 0; 833 *msc = 0; 834 return TRUE; 835 } 836 837 if (!amdgpu_dri2_get_crtc_msc(crtc, ust, msc)) 838 return FALSE; 839 840 if (draw && draw->type == DRAWABLE_WINDOW) 841 *msc += get_dri2_window_priv((WindowPtr)draw)->vblank_delta; 842 *msc &= 0xffffffff; 843 return TRUE; 844} 845 846static 847CARD32 amdgpu_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data) 848{ 849 DRI2FrameEventPtr event_info = (DRI2FrameEventPtr) data; 850 xf86CrtcPtr crtc = event_info->crtc; 851 ScrnInfoPtr scrn; 852 AMDGPUEntPtr pAMDGPUEnt; 853 CARD64 drm_now; 854 int ret; 855 CARD64 delta_t, delta_seq, frame; 856 drmmode_crtc_private_ptr drmmode_crtc; 857 858 /* 859 * This is emulated event, so its time is current time, which we 860 * have to get in DRM-compatible form (which is a bit messy given 861 * the information that we have at this point). Can't use now argument 862 * because DRM event time may come from monotonic clock, while 863 * DIX timer facility uses real-time clock. 864 */ 865 if (!event_info->crtc) { 866 ErrorF("%s no crtc\n", __func__); 867 if (event_info->drm_queue_seq) 868 amdgpu_drm_abort_entry(event_info->drm_queue_seq); 869 else 870 amdgpu_dri2_frame_event_abort(NULL, data); 871 return 0; 872 } 873 874 scrn = crtc->scrn; 875 pAMDGPUEnt = AMDGPUEntPriv(scrn); 876 drmmode_crtc = event_info->crtc->driver_private; 877 ret = drmmode_get_current_ust(pAMDGPUEnt->fd, &drm_now); 878 if (ret) { 879 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 880 "%s cannot get current time\n", __func__); 881 if (event_info->drm_queue_seq) 882 drmmode_crtc->drmmode->event_context. 883 vblank_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 delta_t = drm_now - (CARD64) drmmode_crtc->dpms_last_ust; 894 delta_seq = delta_t * drmmode_crtc->dpms_last_fps; 895 delta_seq /= 1000000; 896 frame = (CARD64) drmmode_crtc->dpms_last_seq + delta_seq; 897 if (event_info->drm_queue_seq) 898 drmmode_crtc->drmmode->event_context. 899 vblank_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) 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) 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