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