nouveau_dri2.c revision fda9279d
1#include <sys/types.h> 2#include <sys/stat.h> 3#include <fcntl.h> 4#include <errno.h> 5 6#include "xorg-server.h" 7#include "nv_include.h" 8#ifdef DRI2 9#include "dri2.h" 10#else 11#error "This driver requires a DRI2-enabled X server" 12#endif 13 14#include "xf86drmMode.h" 15 16struct nouveau_dri2_buffer { 17 DRI2BufferRec base; 18 PixmapPtr ppix; 19}; 20 21static inline struct nouveau_dri2_buffer * 22nouveau_dri2_buffer(DRI2BufferPtr buf) 23{ 24 return (struct nouveau_dri2_buffer *)buf; 25} 26 27static PixmapPtr get_drawable_pixmap(DrawablePtr drawable) 28{ 29 if (drawable->type == DRAWABLE_PIXMAP) 30 return (PixmapPtr)drawable; 31 else 32 return (*drawable->pScreen->GetWindowPixmap)((WindowPtr)drawable); 33} 34 35DRI2BufferPtr 36nouveau_dri2_create_buffer2(ScreenPtr pScreen, DrawablePtr pDraw, unsigned int attachment, 37 unsigned int format) 38{ 39 NVPtr pNv = NVPTR(xf86ScreenToScrn(pScreen)); 40 struct nouveau_dri2_buffer *nvbuf; 41 struct nouveau_pixmap *nvpix; 42 PixmapPtr ppix = NULL; 43 44 nvbuf = calloc(1, sizeof(*nvbuf)); 45 if (!nvbuf) 46 return NULL; 47 48 if (attachment == DRI2BufferFrontLeft) { 49 ppix = get_drawable_pixmap(pDraw); 50 if (pScreen != ppix->drawable.pScreen) 51 ppix = NULL; 52 53 if (pDraw->type == DRAWABLE_WINDOW) { 54#if DRI2INFOREC_VERSION >= 6 55 /* Set initial swap limit on drawable. */ 56 DRI2SwapLimit(pDraw, pNv->swap_limit); 57#endif 58 } 59 if (ppix) 60 ppix->refcnt++; 61 } else { 62 int bpp; 63 unsigned int usage_hint = NOUVEAU_CREATE_PIXMAP_TILED; 64 65 /* 'format' is just depth (or 0, or maybe it depends on the caller) */ 66 bpp = round_up_pow2(format ? format : pDraw->depth); 67 68 if (attachment == DRI2BufferDepth || 69 attachment == DRI2BufferDepthStencil) 70 usage_hint |= NOUVEAU_CREATE_PIXMAP_ZETA; 71 else 72 usage_hint |= NOUVEAU_CREATE_PIXMAP_SCANOUT; 73 74 ppix = pScreen->CreatePixmap(pScreen, pDraw->width, 75 pDraw->height, bpp, 76 usage_hint); 77 } 78 79 if (ppix) { 80 pNv->exa_force_cp = TRUE; 81 exaMoveInPixmap(ppix); 82 pNv->exa_force_cp = FALSE; 83 84 nvbuf->base.pitch = ppix->devKind; 85 nvbuf->base.cpp = ppix->drawable.bitsPerPixel / 8; 86 } 87 88 nvbuf->base.attachment = attachment; 89 nvbuf->base.driverPrivate = nvbuf; 90 nvbuf->base.format = format; 91 nvbuf->base.flags = 0; 92 nvbuf->ppix = ppix; 93 94 if (ppix) { 95 nvpix = nouveau_pixmap(ppix); 96 if (!nvpix || !nvpix->bo || 97 nouveau_bo_name_get(nvpix->bo, &nvbuf->base.name)) { 98 pScreen->DestroyPixmap(nvbuf->ppix); 99 free(nvbuf); 100 return NULL; 101 } 102 } 103 return &nvbuf->base; 104} 105 106DRI2BufferPtr 107nouveau_dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment, 108 unsigned int format) 109{ 110 return nouveau_dri2_create_buffer2(pDraw->pScreen, pDraw, 111 attachment, format); 112} 113 114void 115nouveau_dri2_destroy_buffer2(ScreenPtr pScreen, DrawablePtr pDraw, DRI2BufferPtr buf) 116{ 117 struct nouveau_dri2_buffer *nvbuf; 118 119 nvbuf = nouveau_dri2_buffer(buf); 120 if (!nvbuf) 121 return; 122 123 if (nvbuf->ppix) 124 pScreen->DestroyPixmap(nvbuf->ppix); 125 free(nvbuf); 126} 127 128void 129nouveau_dri2_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buf) 130{ 131 nouveau_dri2_destroy_buffer2(pDraw->pScreen, pDraw, buf); 132} 133 134void 135nouveau_dri2_copy_region2(ScreenPtr pScreen, DrawablePtr pDraw, RegionPtr pRegion, 136 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer) 137{ 138 struct nouveau_dri2_buffer *src = nouveau_dri2_buffer(pSrcBuffer); 139 struct nouveau_dri2_buffer *dst = nouveau_dri2_buffer(pDstBuffer); 140 NVPtr pNv = NVPTR(xf86ScreenToScrn(pScreen)); 141 RegionPtr pCopyClip; 142 GCPtr pGC; 143 DrawablePtr src_draw, dst_draw; 144 Bool translate = FALSE; 145 int off_x = 0, off_y = 0; 146 147 src_draw = &src->ppix->drawable; 148 dst_draw = &dst->ppix->drawable; 149#if 0 150 ErrorF("attachments src %d, dst %d, drawable %p %p pDraw %p\n", 151 src->base.attachment, dst->base.attachment, 152 src_draw, dst_draw, pDraw); 153#endif 154 if (src->base.attachment == DRI2BufferFrontLeft) 155 src_draw = pDraw; 156 if (dst->base.attachment == DRI2BufferFrontLeft) { 157#ifdef NOUVEAU_PIXMAP_SHARING 158 if (pDraw->pScreen != pScreen) { 159 dst_draw = DRI2UpdatePrime(pDraw, pDstBuffer); 160 if (!dst_draw) 161 return; 162 } 163 else 164#endif 165 dst_draw = pDraw; 166 if (dst_draw != pDraw) 167 translate = TRUE; 168 } 169 170 if (translate && pDraw->type == DRAWABLE_WINDOW) { 171 PixmapPtr pPix = get_drawable_pixmap(pDraw); 172 off_x = pDraw->x - pPix->screen_x; 173 off_y = pDraw->y - pPix->screen_y; 174 } 175 176 pGC = GetScratchGC(pDraw->depth, pScreen); 177 pCopyClip = REGION_CREATE(pScreen, NULL, 0); 178 REGION_COPY(pScreen, pCopyClip, pRegion); 179 180 if (translate) { 181 REGION_TRANSLATE(pScreen, pCopyClip, off_x, off_y); 182 } 183 pGC->funcs->ChangeClip(pGC, CT_REGION, pCopyClip, 0); 184 ValidateGC(dst_draw, pGC); 185 186 /* If this is a full buffer swap or frontbuffer flush, throttle on 187 * the previous one. 188 */ 189 if (dst->base.attachment == DRI2BufferFrontLeft && 190 REGION_NUM_RECTS(pRegion) == 1) { 191 BoxPtr extents = REGION_EXTENTS(pScreen, pRegion); 192 if (extents->x1 == 0 && extents->y1 == 0 && 193 extents->x2 == pDraw->width && 194 extents->y2 == pDraw->height) { 195 PixmapPtr fpix = get_drawable_pixmap(dst_draw); 196 struct nouveau_bo *bo = nouveau_pixmap_bo(fpix); 197 if (bo) 198 nouveau_bo_wait(bo, NOUVEAU_BO_RD, pNv->client); 199 } 200 } 201 202 pGC->ops->CopyArea(src_draw, dst_draw, pGC, 0, 0, 203 pDraw->width, pDraw->height, off_x, off_y); 204 205 FreeScratchGC(pGC); 206} 207 208void 209nouveau_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, 210 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer) 211{ 212 return nouveau_dri2_copy_region2(pDraw->pScreen, pDraw, pRegion, 213 pDstBuffer, pSrcBuffer); 214} 215 216struct nouveau_dri2_vblank_state { 217 enum { 218 SWAP, 219 BLIT, 220 WAIT 221 } action; 222 223 ClientPtr client; 224 XID draw; 225 226 DRI2BufferPtr dst; 227 DRI2BufferPtr src; 228 DRI2SwapEventPtr func; 229 void *data; 230 unsigned int frame; 231}; 232 233struct dri2_vblank { 234 struct nouveau_dri2_vblank_state *s; 235}; 236 237static uint64_t dri2_sequence; 238 239static Bool 240update_front(DrawablePtr draw, DRI2BufferPtr front) 241{ 242 int r; 243 PixmapPtr pixmap; 244 struct nouveau_dri2_buffer *nvbuf = nouveau_dri2_buffer(front); 245 246 if (draw->type == DRAWABLE_PIXMAP) 247 pixmap = (PixmapPtr)draw; 248 else 249 pixmap = (*draw->pScreen->GetWindowPixmap)((WindowPtr)draw); 250 251 pixmap->refcnt++; 252 253 exaMoveInPixmap(pixmap); 254 r = nouveau_bo_name_get(nouveau_pixmap_bo(pixmap), &front->name); 255 if (r) { 256 (*draw->pScreen->DestroyPixmap)(pixmap); 257 return FALSE; 258 } 259 260 if (nvbuf->ppix) 261 (*draw->pScreen->DestroyPixmap)(nvbuf->ppix); 262 263 front->pitch = pixmap->devKind; 264 front->cpp = pixmap->drawable.bitsPerPixel / 8; 265 nvbuf->ppix = pixmap; 266 267 return TRUE; 268} 269 270static Bool 271can_exchange(DrawablePtr draw, PixmapPtr dst_pix, PixmapPtr src_pix) 272{ 273 ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen); 274 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 275 NVPtr pNv = NVPTR(scrn); 276 int i; 277 278 if (!xf86_config->num_crtc) 279 return FALSE; 280 281 for (i = 0; i < xf86_config->num_crtc; i++) { 282 xf86CrtcPtr crtc = xf86_config->crtc[i]; 283 if (crtc->enabled && crtc->rotatedData) 284 return FALSE; 285 286 } 287 288 return ((DRI2CanFlip(draw) && pNv->has_pageflip)) && 289 dst_pix->drawable.width == src_pix->drawable.width && 290 dst_pix->drawable.height == src_pix->drawable.height && 291 dst_pix->drawable.bitsPerPixel == src_pix->drawable.bitsPerPixel && 292 dst_pix->devKind == src_pix->devKind; 293} 294 295static Bool 296can_sync_to_vblank(DrawablePtr draw) 297{ 298 ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen); 299 NVPtr pNv = NVPTR(scrn); 300 301 return pNv->glx_vblank && 302 nv_window_belongs_to_crtc(scrn, draw->x, draw->y, 303 draw->width, draw->height); 304} 305 306#if DRI2INFOREC_VERSION >= 6 307static Bool 308nouveau_dri2_swap_limit_validate(DrawablePtr draw, int swap_limit) 309{ 310 ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen); 311 NVPtr pNv = NVPTR(scrn); 312 313 if ((swap_limit < 1 ) || (swap_limit > pNv->max_swap_limit)) 314 return FALSE; 315 316 return TRUE; 317} 318#endif 319 320/* Shall we intentionally violate the OML_sync_control spec to 321 * get some sort of triple-buffering behaviour on a pre 1.12.0 322 * x-server? 323 */ 324static Bool violate_oml(DrawablePtr draw) 325{ 326 ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen); 327 NVPtr pNv = NVPTR(scrn); 328 329 return (DRI2INFOREC_VERSION < 6) && (pNv->swap_limit > 1); 330} 331 332typedef struct { 333 int fd; 334 unsigned old_fb_id; 335 int flip_count; 336 void *event_data; 337 unsigned int fe_msc; 338 uint64_t fe_ust; 339} dri2_flipdata_rec, *dri2_flipdata_ptr; 340 341typedef struct { 342 dri2_flipdata_ptr flipdata; 343 Bool dispatch_me; 344} dri2_flipevtcarrier_rec, *dri2_flipevtcarrier_ptr; 345 346static void 347nouveau_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec, 348 unsigned int tv_usec, void *event_data) 349{ 350 struct nouveau_dri2_vblank_state *flip = event_data; 351 DrawablePtr draw; 352 ScreenPtr screen; 353 ScrnInfoPtr scrn; 354 int status; 355 356 status = dixLookupDrawable(&draw, flip->draw, serverClient, 357 M_ANY, DixWriteAccess); 358 if (status != Success) { 359 free(flip); 360 return; 361 } 362 363 screen = draw->pScreen; 364 scrn = xf86ScreenToScrn(screen); 365 366 /* We assume our flips arrive in order, so we don't check the frame */ 367 switch (flip->action) { 368 case SWAP: 369 /* Check for too small vblank count of pageflip completion, 370 * taking wraparound into account. This usually means some 371 * defective kms pageflip completion, causing wrong (msc, ust) 372 * return values and possible visual corruption. 373 * Skip test for frame == 0, as this is a valid constant value 374 * reported by all Linux kernels at least up to Linux 3.0. 375 */ 376 if ((frame != 0) && 377 (frame < flip->frame) && (flip->frame - frame < 5)) { 378 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 379 "%s: Pageflip has impossible msc %d < target_msc %d\n", 380 __func__, frame, flip->frame); 381 /* All-Zero values signal failure of (msc, ust) 382 * timestamping to client. 383 */ 384 frame = tv_sec = tv_usec = 0; 385 } 386 387 DRI2SwapComplete(flip->client, draw, frame, tv_sec, tv_usec, 388 DRI2_FLIP_COMPLETE, flip->func, 389 flip->data); 390 break; 391 default: 392 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 393 "%s: unknown vblank event received\n", __func__); 394 /* Unknown type */ 395 break; 396 } 397 398 free(flip); 399} 400 401static void 402nouveau_dri2_flip_handler(void *priv, uint64_t name, uint64_t ust, uint32_t msc) 403{ 404 dri2_flipevtcarrier_ptr flipcarrier = priv; 405 dri2_flipdata_ptr flipdata = flipcarrier->flipdata; 406 407 /* Is this the event whose info shall be delivered to higher level? */ 408 if (flipcarrier->dispatch_me) { 409 /* Yes: Cache msc, ust for later delivery. */ 410 flipdata->fe_msc = msc; 411 flipdata->fe_ust = ust; 412 } 413 414 /* Last crtc completed flip? */ 415 flipdata->flip_count--; 416 if (flipdata->flip_count > 0) 417 return; 418 419 /* Release framebuffer */ 420 drmModeRmFB(flipdata->fd, flipdata->old_fb_id); 421 422 if (flipdata->event_data == NULL) { 423 free(flipdata); 424 return; 425 } 426 427 /* Deliver cached msc, ust from reference crtc to flip event handler */ 428 nouveau_dri2_flip_event_handler(flipdata->fe_msc, 429 flipdata->fe_ust / 1000000, 430 flipdata->fe_ust % 1000000, 431 flipdata->event_data); 432 free(flipdata); 433} 434 435static Bool 436dri2_page_flip(DrawablePtr draw, PixmapPtr back, void *priv, 437 xf86CrtcPtr ref_crtc) 438{ 439 ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen); 440 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 441 NVPtr pNv = NVPTR(scrn); 442 uint32_t next_fb; 443 int emitted = 0; 444 int ret, i; 445 dri2_flipdata_ptr flipdata; 446 dri2_flipevtcarrier_ptr flipcarrier; 447 448 ret = drmModeAddFB(pNv->dev->fd, scrn->virtualX, scrn->virtualY, 449 scrn->depth, scrn->bitsPerPixel, 450 scrn->displayWidth * scrn->bitsPerPixel / 8, 451 nouveau_pixmap(back)->bo->handle, &next_fb); 452 if (ret) { 453 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 454 "add fb failed: %s\n", strerror(errno)); 455 return FALSE; 456 } 457 458 flipdata = calloc(1, sizeof(dri2_flipdata_rec)); 459 if (!flipdata) { 460 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 461 "flip queue: data alloc failed.\n"); 462 goto error_undo; 463 } 464 465 flipdata->event_data = priv; 466 flipdata->fd = pNv->dev->fd; 467 468 for (i = 0; i < config->num_crtc; i++) { 469 int head = drmmode_crtc(config->crtc[i]); 470 void *token; 471 472 if (!config->crtc[i]->enabled) 473 continue; 474 475 flipdata->flip_count++; 476 477 flipcarrier = drmmode_event_queue(scrn, ++dri2_sequence, 478 sizeof(*flipcarrier), 479 nouveau_dri2_flip_handler, 480 &token); 481 if (!flipcarrier) { 482 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 483 "flip queue: carrier alloc failed.\n"); 484 if (emitted == 0) 485 free(flipdata); 486 goto error_undo; 487 } 488 489 /* Only the reference crtc will finally deliver its page flip 490 * completion event. All other crtc's events will be discarded. 491 */ 492 flipcarrier->dispatch_me = (config->crtc[i] == ref_crtc); 493 flipcarrier->flipdata = flipdata; 494 495 ret = drmModePageFlip(pNv->dev->fd, head, next_fb, 496 DRM_MODE_PAGE_FLIP_EVENT, token); 497 if (ret) { 498 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 499 "flip queue failed: %s\n", strerror(errno)); 500 drmmode_event_abort(scrn, dri2_sequence--, false); 501 if (emitted == 0) 502 free(flipdata); 503 goto error_undo; 504 } 505 506 emitted++; 507 } 508 509 /* Will release old fb after all crtc's completed flip. */ 510 drmmode_swap(scrn, next_fb, &flipdata->old_fb_id); 511 return TRUE; 512 513error_undo: 514 drmModeRmFB(pNv->dev->fd, next_fb); 515 return FALSE; 516} 517 518static void 519nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, 520 unsigned int tv_sec, unsigned int tv_usec, 521 struct nouveau_dri2_vblank_state *s); 522 523static void 524nouveau_dri2_vblank_handler(void *priv, uint64_t name, uint64_t ust, uint32_t frame) 525{ 526 struct dri2_vblank *event = priv; 527 struct nouveau_dri2_vblank_state *s = event->s; 528 uint32_t tv_sec = ust / 1000000; 529 uint32_t tv_usec = ust % 1000000; 530 DrawablePtr draw; 531 int ret; 532 533 ret = dixLookupDrawable(&draw, s->draw, serverClient, 534 M_ANY, DixWriteAccess); 535 if (ret) { 536 free(s); 537 return; 538 } 539 540 switch (s->action) { 541 case SWAP: 542 nouveau_dri2_finish_swap(draw, frame, tv_sec, tv_usec, s); 543#if DRI2INFOREC_VERSION >= 6 544 /* Restore real swap limit on drawable, now that it is safe. */ 545 ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen); 546 DRI2SwapLimit(draw, NVPTR(scrn)->swap_limit); 547#endif 548 break; 549 550 case WAIT: 551 DRI2WaitMSCComplete(s->client, draw, frame, tv_sec, tv_usec); 552 free(s); 553 break; 554 555 case BLIT: 556 DRI2SwapComplete(s->client, draw, frame, tv_sec, tv_usec, 557 DRI2_BLIT_COMPLETE, s->func, s->data); 558 free(s); 559 break; 560 } 561} 562 563static int 564nouveau_wait_vblank(DrawablePtr draw, int type, CARD64 msc, 565 CARD64 *pmsc, CARD64 *pust, void *data) 566{ 567 ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen); 568 NVPtr pNv = NVPTR(scrn); 569 xf86CrtcPtr crtc; 570 drmVBlank vbl; 571 struct dri2_vblank *event = NULL; 572 void *token = NULL; 573 int ret; 574 int head; 575 576 /* Select crtc which shows the largest part of the drawable */ 577 crtc = nouveau_pick_best_crtc(scrn, FALSE, 578 draw->x, draw->y, draw->width, draw->height); 579 580 if (!crtc) { 581 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 582 "Wait for VBlank failed: No valid crtc for drawable.\n"); 583 return -EINVAL; 584 } 585 586 if (type & DRM_VBLANK_EVENT) { 587 event = drmmode_event_queue(scrn, ++dri2_sequence, 588 sizeof(*event), 589 nouveau_dri2_vblank_handler, 590 &token); 591 if (!event) 592 return -ENOMEM; 593 594 event->s = data; 595 } 596 597 /* Map xf86CrtcPtr to drmWaitVBlank compatible display head index. */ 598 head = drmmode_head(crtc); 599 600 if (head == 1) 601 type |= DRM_VBLANK_SECONDARY; 602 else if (head > 1) 603#ifdef DRM_VBLANK_HIGH_CRTC_SHIFT 604 type |= (head << DRM_VBLANK_HIGH_CRTC_SHIFT) & 605 DRM_VBLANK_HIGH_CRTC_MASK; 606#else 607 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 608 "Wait for VBlank failed: Called for CRTC %d > 1, but " 609 "DRM_VBLANK_HIGH_CRTC_SHIFT not defined at build time.\n", 610 head); 611#endif 612 613 vbl.request.type = type; 614 vbl.request.sequence = msc; 615 vbl.request.signal = (unsigned long)token; 616 617 ret = drmWaitVBlank(pNv->dev->fd, &vbl); 618 if (ret) { 619 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 620 "Wait for VBlank failed: %s\n", strerror(errno)); 621 if (event) 622 drmmode_event_abort(scrn, dri2_sequence--, false); 623 return ret; 624 } 625 626 if (pmsc) 627 *pmsc = vbl.reply.sequence; 628 if (pust) 629 *pust = (CARD64)vbl.reply.tval_sec * 1000000 + 630 vbl.reply.tval_usec; 631 return 0; 632} 633 634static void 635nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, 636 unsigned int tv_sec, unsigned int tv_usec, 637 struct nouveau_dri2_vblank_state *s) 638{ 639 ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen); 640 NVPtr pNv = NVPTR(scrn); 641 PixmapPtr dst_pix; 642 PixmapPtr src_pix = nouveau_dri2_buffer(s->src)->ppix; 643 struct nouveau_bo *dst_bo; 644 struct nouveau_bo *src_bo = nouveau_pixmap_bo(src_pix); 645 struct nouveau_pushbuf *push = pNv->pushbuf; 646 RegionRec reg; 647 int type, ret; 648 Bool front_updated, will_exchange; 649 xf86CrtcPtr ref_crtc; 650 651 REGION_INIT(0, ®, (&(BoxRec){ 0, 0, draw->width, draw->height }), 0); 652 REGION_TRANSLATE(0, ®, draw->x, draw->y); 653 654 /* Main crtc for this drawable shall finally deliver pageflip event. */ 655 ref_crtc = nouveau_pick_best_crtc(scrn, FALSE, draw->x, draw->y, 656 draw->width, draw->height); 657 658 /* Update frontbuffer pixmap and name: Could have changed due to 659 * window (un)redirection as part of compositing. 660 */ 661 front_updated = update_front(draw, s->dst); 662 663 /* Assign frontbuffer pixmap, after update in update_front() */ 664 dst_pix = nouveau_dri2_buffer(s->dst)->ppix; 665 dst_bo = nouveau_pixmap_bo(dst_pix); 666 667 /* Throttle on the previous frame before swapping */ 668 nouveau_bo_wait(dst_bo, NOUVEAU_BO_RD, push->client); 669 670 /* Swap by buffer exchange possible? */ 671 will_exchange = front_updated && can_exchange(draw, dst_pix, src_pix); 672 673 /* Only emit a wait for vblank pushbuf here if this is a copy-swap, or 674 * if it is a kms pageflip-swap on an old kernel. Pure exchange swaps 675 * don't need sync to vblank. kms pageflip-swaps on Linux 3.13+ are 676 * synced to vblank in the kms driver, so we must not sync here, or 677 * framerate will be cut in half! 678 */ 679 if (can_sync_to_vblank(draw) && 680 (!will_exchange || 681 (!pNv->has_async_pageflip && nouveau_exa_pixmap_is_onscreen(dst_pix)))) { 682 /* Reference the back buffer to sync it to vblank */ 683 nouveau_pushbuf_refn(push, &(struct nouveau_pushbuf_refn) { 684 src_bo, 685 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD 686 }, 1); 687 688 if (pNv->Architecture >= NV_FERMI) 689 NVC0SyncToVBlank(dst_pix, REGION_EXTENTS(0, ®)); 690 else 691 if (pNv->Architecture >= NV_TESLA) 692 NV50SyncToVBlank(dst_pix, REGION_EXTENTS(0, ®)); 693 else 694 NV11SyncToVBlank(dst_pix, REGION_EXTENTS(0, ®)); 695 696 nouveau_pushbuf_kick(push, push->channel); 697 } 698 699 if (will_exchange) { 700 type = DRI2_EXCHANGE_COMPLETE; 701 DamageRegionAppend(draw, ®); 702 703 if (nouveau_exa_pixmap_is_onscreen(dst_pix)) { 704 type = DRI2_FLIP_COMPLETE; 705 ret = dri2_page_flip(draw, src_pix, violate_oml(draw) ? 706 NULL : s, ref_crtc); 707 if (!ret) 708 goto out; 709 } 710 711 SWAP(s->dst->name, s->src->name); 712 SWAP(nouveau_pixmap(dst_pix)->bo, nouveau_pixmap(src_pix)->bo); 713 714 DamageRegionProcessPending(draw); 715 716 /* If it is a page flip, finish it in the flip event handler. */ 717 if ((type == DRI2_FLIP_COMPLETE) && !violate_oml(draw)) 718 return; 719 } else { 720 type = DRI2_BLIT_COMPLETE; 721 722 /* Reference the front buffer to let throttling work 723 * on occluded drawables. */ 724 nouveau_pushbuf_refn(push, &(struct nouveau_pushbuf_refn) { 725 dst_bo, 726 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD 727 }, 1); 728 729 REGION_TRANSLATE(0, ®, -draw->x, -draw->y); 730 nouveau_dri2_copy_region(draw, ®, s->dst, s->src); 731 732 if (can_sync_to_vblank(draw) && !violate_oml(draw)) { 733 /* Request a vblank event one vblank from now, the most 734 * likely (optimistic?) time a direct framebuffer blit 735 * will complete or a desktop compositor will update its 736 * screen. This defers DRI2SwapComplete() to the earliest 737 * likely time of real swap completion. 738 */ 739 s->action = BLIT; 740 ret = nouveau_wait_vblank(draw, DRM_VBLANK_EVENT | 741 DRM_VBLANK_RELATIVE, 1, 742 NULL, NULL, s); 743 /* Done, if success. Otherwise use fallback below. */ 744 if (!ret) 745 return; 746 } 747 } 748 749 /* Special triple-buffering hack for old pre 1.12.0 x-servers used? */ 750 if (violate_oml(draw)) { 751 /* Signal to client that swap completion timestamps and counts 752 * are invalid - they violate the specification. 753 */ 754 frame = tv_sec = tv_usec = 0; 755 } 756 757 /* 758 * Tell the X server buffers are already swapped even if they're 759 * not, to prevent it from blocking the client on the next 760 * GetBuffers request (and let the client do triple-buffering). 761 * 762 * XXX - The DRI2SwapLimit() API allowed us to move this to 763 * the flip handler with no FPS hit for page flipped swaps. 764 * It is still needed as a fallback for some copy swaps as 765 * we lack a method to detect true swap completion for 766 * DRI2_BLIT_COMPLETE. 767 * 768 * It is also used if triple-buffering is requested on 769 * old x-servers which don't support the DRI2SwapLimit() 770 * function. 771 */ 772 DRI2SwapComplete(s->client, draw, frame, tv_sec, tv_usec, 773 type, s->func, s->data); 774out: 775 free(s); 776} 777 778static Bool 779nouveau_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, 780 DRI2BufferPtr dst, DRI2BufferPtr src, 781 CARD64 *target_msc, CARD64 divisor, CARD64 remainder, 782 DRI2SwapEventPtr func, void *data) 783{ 784 struct nouveau_dri2_vblank_state *s; 785 CARD64 current_msc, expect_msc; 786 CARD64 current_ust; 787 int ret; 788 789 /* Initialize a swap structure */ 790 s = malloc(sizeof(*s)); 791 if (!s) 792 return FALSE; 793 794 *s = (struct nouveau_dri2_vblank_state) 795 { SWAP, client, draw->id, dst, src, func, data, 0 }; 796 797 if (can_sync_to_vblank(draw)) { 798 /* Get current sequence and vblank time*/ 799 ret = nouveau_wait_vblank(draw, DRM_VBLANK_RELATIVE, 0, 800 ¤t_msc, ¤t_ust, NULL); 801 if (ret) 802 goto fail; 803 804 /* Truncate to match kernel interfaces; means occasional overflow 805 * misses, but that's generally not a big deal. 806 */ 807 *target_msc &= 0xffffffff; 808 divisor &= 0xffffffff; 809 remainder &= 0xffffffff; 810 811 /* Calculate a swap target if we don't have one */ 812 if (current_msc >= *target_msc && divisor) 813 *target_msc = current_msc + divisor 814 - (current_msc - remainder) % divisor; 815 816 /* Avoid underflow of unsigned value below */ 817 if (*target_msc == 0) 818 *target_msc = 1; 819 820 /* Swap at next possible vblank requested? */ 821 if (current_msc >= *target_msc - 1) { 822 /* Special case: Need to swap at next vblank. 823 * Schedule swap immediately, bypassing the kernel 824 * vblank event mechanism to avoid a dangerous race 825 * between the client and the x-server vblank event 826 * dispatch in the main x-server dispatch loop when 827 * the swap_limit is set to 2 for triple-buffering. 828 * 829 * This also optimizes for the common case of swap 830 * at next vblank, avoiding vblank dispatch delay. 831 */ 832 s->frame = 1 + ((unsigned int) current_msc & 0xffffffff); 833 *target_msc = 1 + current_msc; 834 nouveau_dri2_finish_swap(draw, current_msc, 835 (unsigned int) (current_ust / 1000000), 836 (unsigned int) (current_ust % 1000000), 837 s); 838 return TRUE; 839 } 840 841 /* This is a swap in the future, ie. the vblank event will 842 * only get dispatched at least 2 vblanks into the future. 843 */ 844 845#if DRI2INFOREC_VERSION >= 6 846 /* On XOrg 1.12+ we need to temporarily lower the swaplimit to 1, 847 * so that DRI2GetBuffersWithFormat() requests from the client get 848 * deferred in the x-server until the vblank event has been 849 * dispatched to us and nouveau_dri2_finish_swap() is done. If 850 * we wouldn't do this, DRI2GetBuffersWithFormat() would operate 851 * on wrong (pre-swap) buffers, and cause a segfault later on in 852 * nouveau_dri2_finish_swap(). Our vblank event handler will restore 853 * the old swaplimit immediately after nouveau_dri2_finish_swap() 854 * is done, so we still get 1 video refresh cycle worth of triple- 855 * buffering, because the client can start rendering again 1 cycle 856 * before the pending swap is completed. 857 * 858 * The same race would happen for the "swap at next vblank" case, 859 * but the special case "swap immediately" code above prevents this. 860 */ 861 DRI2SwapLimit(draw, 1); 862#endif 863 864 /* Request a vblank event one frame before the target */ 865 ret = nouveau_wait_vblank(draw, DRM_VBLANK_ABSOLUTE | 866 DRM_VBLANK_EVENT, 867 max(current_msc, *target_msc - 1), 868 &expect_msc, NULL, s); 869 if (ret) 870 goto fail; 871 s->frame = 1 + ((unsigned int) expect_msc & 0xffffffff); 872 *target_msc = 1 + expect_msc; 873 } else { 874 /* We can't/don't want to sync to vblank, just swap. */ 875 nouveau_dri2_finish_swap(draw, 0, 0, 0, s); 876 } 877 878 return TRUE; 879 880fail: 881 free(s); 882 return FALSE; 883} 884 885static Bool 886nouveau_dri2_schedule_wait(ClientPtr client, DrawablePtr draw, 887 CARD64 target_msc, CARD64 divisor, CARD64 remainder) 888{ 889 struct nouveau_dri2_vblank_state *s; 890 CARD64 current_msc; 891 int ret; 892 893 /* Truncate to match kernel interfaces; means occasional overflow 894 * misses, but that's generally not a big deal. 895 */ 896 target_msc &= 0xffffffff; 897 divisor &= 0xffffffff; 898 remainder &= 0xffffffff; 899 900 if (!can_sync_to_vblank(draw)) { 901 DRI2WaitMSCComplete(client, draw, target_msc, 0, 0); 902 return TRUE; 903 } 904 905 /* Initialize a vblank structure */ 906 s = malloc(sizeof(*s)); 907 if (!s) 908 return FALSE; 909 910 *s = (struct nouveau_dri2_vblank_state) { WAIT, client, draw->id }; 911 912 /* Get current sequence */ 913 ret = nouveau_wait_vblank(draw, DRM_VBLANK_RELATIVE, 0, 914 ¤t_msc, NULL, NULL); 915 if (ret) 916 goto fail; 917 918 /* Calculate a wait target if we don't have one */ 919 if (current_msc >= target_msc && divisor) 920 target_msc = current_msc + divisor 921 - (current_msc - remainder) % divisor; 922 923 /* Request a vblank event */ 924 ret = nouveau_wait_vblank(draw, DRM_VBLANK_ABSOLUTE | 925 DRM_VBLANK_EVENT, 926 max(current_msc, target_msc), 927 NULL, NULL, s); 928 if (ret) 929 goto fail; 930 931 DRI2BlockClient(client, draw); 932 return TRUE; 933fail: 934 free(s); 935 return FALSE; 936} 937 938static Bool 939nouveau_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc) 940{ 941 int ret; 942 943 if (!can_sync_to_vblank(draw)) { 944 *ust = 0; 945 *msc = 0; 946 return TRUE; 947 } 948 949 /* Get current sequence */ 950 ret = nouveau_wait_vblank(draw, DRM_VBLANK_RELATIVE, 0, msc, ust, NULL); 951 if (ret) 952 return FALSE; 953 954 return TRUE; 955} 956 957Bool 958nouveau_dri2_init(ScreenPtr pScreen) 959{ 960 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 961 NVPtr pNv = NVPTR(pScrn); 962 DRI2InfoRec dri2 = { 0 }; 963 const char *drivernames[2][2] = { 964 { "nouveau", "nouveau" }, 965 { "nouveau_vieux", "nouveau_vieux" } 966 }; 967 968 if (pNv->AccelMethod != EXA) 969 return FALSE; 970 971 if (pNv->Architecture >= NV_ARCH_30) 972 dri2.driverNames = drivernames[0]; 973 else 974 dri2.driverNames = drivernames[1]; 975 dri2.numDrivers = 2; 976 dri2.driverName = dri2.driverNames[0]; 977 978 dri2.fd = pNv->dev->fd; 979 dri2.deviceName = pNv->drm_device_name; 980 981 dri2.version = DRI2INFOREC_VERSION; 982 dri2.CreateBuffer = nouveau_dri2_create_buffer; 983 dri2.DestroyBuffer = nouveau_dri2_destroy_buffer; 984 dri2.CopyRegion = nouveau_dri2_copy_region; 985 dri2.ScheduleSwap = nouveau_dri2_schedule_swap; 986 dri2.ScheduleWaitMSC = nouveau_dri2_schedule_wait; 987 dri2.GetMSC = nouveau_dri2_get_msc; 988 989#if DRI2INFOREC_VERSION >= 6 990 dri2.SwapLimitValidate = nouveau_dri2_swap_limit_validate; 991#endif 992 993#if DRI2INFOREC_VERSION >= 7 994 dri2.version = 7; 995 dri2.GetParam = NULL; 996#endif 997 998#if DRI2INFOREC_VERSION >= 9 999 dri2.version = 9; 1000 dri2.CreateBuffer2 = nouveau_dri2_create_buffer2; 1001 dri2.DestroyBuffer2 = nouveau_dri2_destroy_buffer2; 1002 dri2.CopyRegion2 = nouveau_dri2_copy_region2; 1003#endif 1004 return DRI2ScreenInit(pScreen, &dri2); 1005} 1006 1007void 1008nouveau_dri2_fini(ScreenPtr pScreen) 1009{ 1010 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1011 NVPtr pNv = NVPTR(pScrn); 1012 if (pNv->AccelMethod == EXA) 1013 DRI2CloseScreen(pScreen); 1014} 1015