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