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