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