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