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 = xf86ScreenToScrn(pScreen); 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 = xf86ScreenToScrn(pScreen); 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 = xf86ScreenToScrn(pScreen); 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 = xf86ScreenToScrn(pScreen); 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 = NULL; 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 = xf86ScreenToScrn(pScreen); 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 pScrn->vtSema && 748 DRI2CanFlip(draw) && 749 can_exchange(pScrn, draw, front, back); 750} 751 752static void 753radeon_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back) 754{ 755 struct dri2_buffer_priv *front_priv = front->driverPrivate; 756 struct dri2_buffer_priv *back_priv = back->driverPrivate; 757 struct radeon_exa_pixmap_priv *front_radeon, *back_radeon; 758 ScreenPtr screen; 759 RADEONInfoPtr info; 760 struct radeon_bo *bo; 761 int tmp; 762 763 /* Swap BO names so DRI works */ 764 tmp = front->name; 765 front->name = back->name; 766 back->name = tmp; 767 768 /* Swap pixmap bos */ 769 front_radeon = exaGetPixmapDriverPrivate(front_priv->pixmap); 770 back_radeon = exaGetPixmapDriverPrivate(back_priv->pixmap); 771 bo = back_radeon->bo; 772 back_radeon->bo = front_radeon->bo; 773 front_radeon->bo = bo; 774 775 /* Do we need to update the Screen? */ 776 screen = draw->pScreen; 777 info = RADEONPTR(xf86ScreenToScrn(screen)); 778 if (front_radeon->bo == info->front_bo) { 779 radeon_bo_unref(info->front_bo); 780 info->front_bo = back_radeon->bo; 781 radeon_bo_ref(info->front_bo); 782 front_radeon = exaGetPixmapDriverPrivate(screen->GetScreenPixmap(screen)); 783 front_radeon->bo = bo; 784 } 785} 786 787void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec, 788 unsigned int tv_usec, void *event_data) 789{ 790 DRI2FrameEventPtr event = event_data; 791 DrawablePtr drawable; 792 ScreenPtr screen; 793 ScrnInfoPtr scrn; 794 int status; 795 int swap_type; 796 BoxRec box; 797 RegionRec region; 798 799 if (!event->valid) 800 goto cleanup; 801 802 status = dixLookupDrawable(&drawable, event->drawable_id, serverClient, 803 M_ANY, DixWriteAccess); 804 if (status != Success) 805 goto cleanup; 806 807 screen = drawable->pScreen; 808 scrn = xf86ScreenToScrn(screen); 809 810 switch (event->type) { 811 case DRI2_FLIP: 812 if (can_flip(scrn, drawable, event->front, event->back) && 813 radeon_dri2_schedule_flip(scrn, 814 event->client, 815 drawable, 816 event->front, 817 event->back, 818 event->event_complete, 819 event->event_data, 820 event->frame)) { 821 radeon_dri2_exchange_buffers(drawable, event->front, event->back); 822 break; 823 } 824 /* else fall through to exchange/blit */ 825 case DRI2_SWAP: 826 if (DRI2CanExchange(drawable) && 827 can_exchange(scrn, drawable, event->front, event->back)) { 828 radeon_dri2_exchange_buffers(drawable, event->front, event->back); 829 swap_type = DRI2_EXCHANGE_COMPLETE; 830 } else { 831 box.x1 = 0; 832 box.y1 = 0; 833 box.x2 = drawable->width; 834 box.y2 = drawable->height; 835 REGION_INIT(pScreen, ®ion, &box, 0); 836 radeon_dri2_copy_region(drawable, ®ion, event->front, event->back); 837 swap_type = DRI2_BLIT_COMPLETE; 838 } 839 840 DRI2SwapComplete(event->client, drawable, frame, tv_sec, tv_usec, 841 swap_type, event->event_complete, event->event_data); 842 843 break; 844 case DRI2_WAITMSC: 845 DRI2WaitMSCComplete(event->client, drawable, frame, tv_sec, tv_usec); 846 break; 847 default: 848 /* Unknown type */ 849 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 850 "%s: unknown vblank event received\n", __func__); 851 break; 852 } 853 854cleanup: 855 if (event->valid) { 856 radeon_dri2_unref_buffer(event->front); 857 radeon_dri2_unref_buffer(event->back); 858 ListDelDRI2ClientEvents(event->client, &event->link); 859 } 860 free(event); 861} 862 863static drmVBlankSeqType populate_vbl_request_type(RADEONInfoPtr info, int crtc) 864{ 865 drmVBlankSeqType type = 0; 866 867 if (crtc == 1) 868 type |= DRM_VBLANK_SECONDARY; 869 else if (crtc > 1) 870#ifdef DRM_VBLANK_HIGH_CRTC_SHIFT 871 type |= (crtc << DRM_VBLANK_HIGH_CRTC_SHIFT) & 872 DRM_VBLANK_HIGH_CRTC_MASK; 873#else 874 ErrorF("radeon driver bug: %s called for CRTC %d > 1, but " 875 "DRM_VBLANK_HIGH_CRTC_MASK not defined at build time\n", 876 __func__, crtc); 877#endif 878 879 return type; 880} 881 882/* 883 * Get current frame count and frame count timestamp, based on drawable's 884 * crtc. 885 */ 886static int radeon_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc) 887{ 888 ScreenPtr screen = draw->pScreen; 889 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 890 RADEONInfoPtr info = RADEONPTR(scrn); 891 drmVBlank vbl; 892 int ret; 893 int crtc = radeon_dri2_drawable_crtc(draw); 894 895 /* Drawable not displayed, make up a value */ 896 if (crtc == -1) { 897 *ust = 0; 898 *msc = 0; 899 return TRUE; 900 } 901 vbl.request.type = DRM_VBLANK_RELATIVE; 902 vbl.request.type |= populate_vbl_request_type(info, crtc); 903 vbl.request.sequence = 0; 904 905 ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); 906 if (ret) { 907 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 908 "get vblank counter failed: %s\n", strerror(errno)); 909 return FALSE; 910 } 911 912 *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec; 913 *msc = vbl.reply.sequence; 914 915 return TRUE; 916} 917 918/* 919 * Request a DRM event when the requested conditions will be satisfied. 920 * 921 * We need to handle the event and ask the server to wake up the client when 922 * we receive it. 923 */ 924static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, 925 CARD64 target_msc, CARD64 divisor, 926 CARD64 remainder) 927{ 928 ScreenPtr screen = draw->pScreen; 929 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 930 RADEONInfoPtr info = RADEONPTR(scrn); 931 DRI2FrameEventPtr wait_info = NULL; 932 drmVBlank vbl; 933 int ret, crtc = radeon_dri2_drawable_crtc(draw); 934 CARD64 current_msc; 935 936 /* Truncate to match kernel interfaces; means occasional overflow 937 * misses, but that's generally not a big deal */ 938 target_msc &= 0xffffffff; 939 divisor &= 0xffffffff; 940 remainder &= 0xffffffff; 941 942 /* Drawable not visible, return immediately */ 943 if (crtc == -1) 944 goto out_complete; 945 946 wait_info = calloc(1, sizeof(DRI2FrameEventRec)); 947 if (!wait_info) 948 goto out_complete; 949 950 wait_info->drawable_id = draw->id; 951 wait_info->client = client; 952 wait_info->type = DRI2_WAITMSC; 953 wait_info->valid = TRUE; 954 955 if (ListAddDRI2ClientEvents(client, &wait_info->link)) { 956 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 957 "add events to client private failed.\n"); 958 free(wait_info); 959 wait_info = NULL; 960 goto out_complete; 961 } 962 963 /* Get current count */ 964 vbl.request.type = DRM_VBLANK_RELATIVE; 965 vbl.request.type |= populate_vbl_request_type(info, crtc); 966 vbl.request.sequence = 0; 967 ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); 968 if (ret) { 969 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 970 "get vblank counter failed: %s\n", strerror(errno)); 971 goto out_complete; 972 } 973 974 current_msc = vbl.reply.sequence; 975 976 /* 977 * If divisor is zero, or current_msc is smaller than target_msc, 978 * we just need to make sure target_msc passes before waking up the 979 * client. 980 */ 981 if (divisor == 0 || current_msc < target_msc) { 982 /* If target_msc already reached or passed, set it to 983 * current_msc to ensure we return a reasonable value back 984 * to the caller. This keeps the client from continually 985 * sending us MSC targets from the past by forcibly updating 986 * their count on this call. 987 */ 988 if (current_msc >= target_msc) 989 target_msc = current_msc; 990 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; 991 vbl.request.type |= populate_vbl_request_type(info, crtc); 992 vbl.request.sequence = target_msc; 993 vbl.request.signal = (unsigned long)wait_info; 994 ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); 995 if (ret) { 996 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 997 "get vblank counter failed: %s\n", strerror(errno)); 998 goto out_complete; 999 } 1000 1001 wait_info->frame = vbl.reply.sequence; 1002 DRI2BlockClient(client, draw); 1003 return TRUE; 1004 } 1005 1006 /* 1007 * If we get here, target_msc has already passed or we don't have one, 1008 * so we queue an event that will satisfy the divisor/remainder equation. 1009 */ 1010 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; 1011 vbl.request.type |= populate_vbl_request_type(info, crtc); 1012 1013 vbl.request.sequence = current_msc - (current_msc % divisor) + 1014 remainder; 1015 1016 /* 1017 * If calculated remainder is larger than requested remainder, 1018 * it means we've passed the last point where 1019 * seq % divisor == remainder, so we need to wait for the next time 1020 * that will happen. 1021 */ 1022 if ((current_msc % divisor) >= remainder) 1023 vbl.request.sequence += divisor; 1024 1025 vbl.request.signal = (unsigned long)wait_info; 1026 ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); 1027 if (ret) { 1028 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1029 "get vblank counter failed: %s\n", strerror(errno)); 1030 goto out_complete; 1031 } 1032 1033 wait_info->frame = vbl.reply.sequence; 1034 DRI2BlockClient(client, draw); 1035 1036 return TRUE; 1037 1038out_complete: 1039 if (wait_info) { 1040 ListDelDRI2ClientEvents(wait_info->client, &wait_info->link); 1041 free(wait_info); 1042 } 1043 DRI2WaitMSCComplete(client, draw, target_msc, 0, 0); 1044 return TRUE; 1045} 1046 1047void radeon_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec, 1048 unsigned int tv_usec, void *event_data) 1049{ 1050 DRI2FrameEventPtr flip = event_data; 1051 DrawablePtr drawable; 1052 ScreenPtr screen; 1053 ScrnInfoPtr scrn; 1054 int status; 1055 PixmapPtr pixmap; 1056 1057 status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient, 1058 M_ANY, DixWriteAccess); 1059 if (status != Success) { 1060 free(flip); 1061 return; 1062 } 1063 1064 screen = drawable->pScreen; 1065 scrn = xf86ScreenToScrn(screen); 1066 1067 pixmap = screen->GetScreenPixmap(screen); 1068 xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 1069 "%s:%d fevent[%p] width %d pitch %d (/4 %d)\n", 1070 __func__, __LINE__, flip, pixmap->drawable.width, pixmap->devKind, pixmap->devKind/4); 1071 1072 /* We assume our flips arrive in order, so we don't check the frame */ 1073 switch (flip->type) { 1074 case DRI2_SWAP: 1075 /* Check for too small vblank count of pageflip completion, taking wraparound 1076 * into account. This usually means some defective kms pageflip completion, 1077 * causing wrong (msc, ust) return values and possible visual corruption. 1078 */ 1079 if ((frame < flip->frame) && (flip->frame - frame < 5)) { 1080 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1081 "%s: Pageflip completion event has impossible msc %d < target_msc %d\n", 1082 __func__, frame, flip->frame); 1083 /* All-Zero values signal failure of (msc, ust) timestamping to client. */ 1084 frame = tv_sec = tv_usec = 0; 1085 } 1086 1087 DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec, 1088 DRI2_FLIP_COMPLETE, flip->event_complete, 1089 flip->event_data); 1090 break; 1091 default: 1092 xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: unknown vblank event received\n", __func__); 1093 /* Unknown type */ 1094 break; 1095 } 1096 1097 free(flip); 1098} 1099 1100/* 1101 * ScheduleSwap is responsible for requesting a DRM vblank event for the 1102 * appropriate frame. 1103 * 1104 * In the case of a blit (e.g. for a windowed swap) or buffer exchange, 1105 * the vblank requested can simply be the last queued swap frame + the swap 1106 * interval for the drawable. 1107 * 1108 * In the case of a page flip, we request an event for the last queued swap 1109 * frame + swap interval - 1, since we'll need to queue the flip for the frame 1110 * immediately following the received event. 1111 * 1112 * The client will be blocked if it tries to perform further GL commands 1113 * after queueing a swap, though in the Intel case after queueing a flip, the 1114 * client is free to queue more commands; they'll block in the kernel if 1115 * they access buffers busy with the flip. 1116 * 1117 * When the swap is complete, the driver should call into the server so it 1118 * can send any swap complete events that have been requested. 1119 */ 1120static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, 1121 DRI2BufferPtr front, DRI2BufferPtr back, 1122 CARD64 *target_msc, CARD64 divisor, 1123 CARD64 remainder, DRI2SwapEventPtr func, 1124 void *data) 1125{ 1126 ScreenPtr screen = draw->pScreen; 1127 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1128 RADEONInfoPtr info = RADEONPTR(scrn); 1129 drmVBlank vbl; 1130 int ret, crtc= radeon_dri2_drawable_crtc(draw), flip = 0; 1131 DRI2FrameEventPtr swap_info = NULL; 1132 enum DRI2FrameEventType swap_type = DRI2_SWAP; 1133 CARD64 current_msc; 1134 BoxRec box; 1135 RegionRec region; 1136 1137 /* Truncate to match kernel interfaces; means occasional overflow 1138 * misses, but that's generally not a big deal */ 1139 *target_msc &= 0xffffffff; 1140 divisor &= 0xffffffff; 1141 remainder &= 0xffffffff; 1142 1143 /* radeon_dri2_frame_event_handler will get called some unknown time in the 1144 * future with these buffers. Take a reference to ensure that they won't 1145 * get destroyed before then. 1146 */ 1147 radeon_dri2_ref_buffer(front); 1148 radeon_dri2_ref_buffer(back); 1149 1150 /* Drawable not displayed... just complete the swap */ 1151 if (crtc == -1) 1152 goto blit_fallback; 1153 1154 swap_info = calloc(1, sizeof(DRI2FrameEventRec)); 1155 if (!swap_info) 1156 goto blit_fallback; 1157 1158 swap_info->drawable_id = draw->id; 1159 swap_info->client = client; 1160 swap_info->event_complete = func; 1161 swap_info->event_data = data; 1162 swap_info->front = front; 1163 swap_info->back = back; 1164 swap_info->valid = TRUE; 1165 if (ListAddDRI2ClientEvents(client, &swap_info->link)) { 1166 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1167 "add events to client private failed.\n"); 1168 free(swap_info); 1169 swap_info = NULL; 1170 goto blit_fallback; 1171 } 1172 1173 /* Get current count */ 1174 vbl.request.type = DRM_VBLANK_RELATIVE; 1175 vbl.request.type |= populate_vbl_request_type(info, crtc); 1176 vbl.request.sequence = 0; 1177 ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); 1178 if (ret) { 1179 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1180 "first get vblank counter failed: %s\n", 1181 strerror(errno)); 1182 goto blit_fallback; 1183 } 1184 1185 current_msc = vbl.reply.sequence; 1186 1187 /* Flips need to be submitted one frame before */ 1188 if (can_flip(scrn, draw, front, back)) { 1189 swap_type = DRI2_FLIP; 1190 flip = 1; 1191 } 1192 1193 swap_info->type = swap_type; 1194 1195 /* Correct target_msc by 'flip' if swap_type == DRI2_FLIP. 1196 * Do it early, so handling of different timing constraints 1197 * for divisor, remainder and msc vs. target_msc works. 1198 */ 1199 if (*target_msc > 0) 1200 *target_msc -= flip; 1201 1202 /* 1203 * If divisor is zero, or current_msc is smaller than target_msc 1204 * we just need to make sure target_msc passes before initiating 1205 * the swap. 1206 */ 1207 if (divisor == 0 || current_msc < *target_msc) { 1208 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; 1209 /* If non-pageflipping, but blitting/exchanging, we need to use 1210 * DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later 1211 * on. 1212 */ 1213 if (flip == 0) 1214 vbl.request.type |= DRM_VBLANK_NEXTONMISS; 1215 vbl.request.type |= populate_vbl_request_type(info, crtc); 1216 1217 /* If target_msc already reached or passed, set it to 1218 * current_msc to ensure we return a reasonable value back 1219 * to the caller. This makes swap_interval logic more robust. 1220 */ 1221 if (current_msc >= *target_msc) 1222 *target_msc = current_msc; 1223 1224 vbl.request.sequence = *target_msc; 1225 vbl.request.signal = (unsigned long)swap_info; 1226 ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); 1227 if (ret) { 1228 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1229 "divisor 0 get vblank counter failed: %s\n", 1230 strerror(errno)); 1231 goto blit_fallback; 1232 } 1233 1234 *target_msc = vbl.reply.sequence + flip; 1235 swap_info->frame = *target_msc; 1236 1237 return TRUE; 1238 } 1239 1240 /* 1241 * If we get here, target_msc has already passed or we don't have one, 1242 * and we need to queue an event that will satisfy the divisor/remainder 1243 * equation. 1244 */ 1245 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; 1246 if (flip == 0) 1247 vbl.request.type |= DRM_VBLANK_NEXTONMISS; 1248 vbl.request.type |= populate_vbl_request_type(info, crtc); 1249 1250 vbl.request.sequence = current_msc - (current_msc % divisor) + 1251 remainder; 1252 1253 /* 1254 * If the calculated deadline vbl.request.sequence is smaller than 1255 * or equal to current_msc, it means we've passed the last point 1256 * when effective onset frame seq could satisfy 1257 * seq % divisor == remainder, so we need to wait for the next time 1258 * this will happen. 1259 1260 * This comparison takes the 1 frame swap delay in pageflipping mode 1261 * into account, as well as a potential DRM_VBLANK_NEXTONMISS delay 1262 * if we are blitting/exchanging instead of flipping. 1263 */ 1264 if (vbl.request.sequence <= current_msc) 1265 vbl.request.sequence += divisor; 1266 1267 /* Account for 1 frame extra pageflip delay if flip > 0 */ 1268 vbl.request.sequence -= flip; 1269 1270 vbl.request.signal = (unsigned long)swap_info; 1271 ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); 1272 if (ret) { 1273 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1274 "final get vblank counter failed: %s\n", 1275 strerror(errno)); 1276 goto blit_fallback; 1277 } 1278 1279 /* Adjust returned value for 1 fame pageflip offset of flip > 0 */ 1280 *target_msc = vbl.reply.sequence + flip; 1281 swap_info->frame = *target_msc; 1282 1283 return TRUE; 1284 1285blit_fallback: 1286 box.x1 = 0; 1287 box.y1 = 0; 1288 box.x2 = draw->width; 1289 box.y2 = draw->height; 1290 REGION_INIT(pScreen, ®ion, &box, 0); 1291 1292 radeon_dri2_copy_region(draw, ®ion, front, back); 1293 1294 DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data); 1295 if (swap_info) { 1296 ListDelDRI2ClientEvents(swap_info->client, &swap_info->link); 1297 free(swap_info); 1298 } 1299 1300 radeon_dri2_unref_buffer(front); 1301 radeon_dri2_unref_buffer(back); 1302 1303 *target_msc = 0; /* offscreen, so zero out target vblank count */ 1304 return TRUE; 1305} 1306 1307#endif /* USE_DRI2_SCHEDULING */ 1308 1309 1310Bool 1311radeon_dri2_screen_init(ScreenPtr pScreen) 1312{ 1313 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1314 RADEONInfoPtr info = RADEONPTR(pScrn); 1315 DRI2InfoRec dri2_info = { 0 }; 1316#ifdef USE_DRI2_SCHEDULING 1317 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 1318 const char *driverNames[2]; 1319 Bool scheduling_works = TRUE; 1320#endif 1321 1322 if (!info->useEXA) { 1323 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI2 requires EXA\n"); 1324 return FALSE; 1325 } 1326 1327 info->dri2.device_name = drmGetDeviceNameFromFd(info->dri2.drm_fd); 1328 1329 if ( (info->ChipFamily >= CHIP_FAMILY_R600) ) { 1330 dri2_info.driverName = R600_DRIVER_NAME; 1331 } else if ( (info->ChipFamily >= CHIP_FAMILY_R300) ) { 1332 dri2_info.driverName = R300_DRIVER_NAME; 1333 } else if ( info->ChipFamily >= CHIP_FAMILY_R200 ) { 1334 dri2_info.driverName = R200_DRIVER_NAME; 1335 } else { 1336 dri2_info.driverName = RADEON_DRIVER_NAME; 1337 } 1338 dri2_info.fd = info->dri2.drm_fd; 1339 dri2_info.deviceName = info->dri2.device_name; 1340#ifndef USE_DRI2_1_1_0 1341 dri2_info.version = 1; 1342 dri2_info.CreateBuffers = radeon_dri2_create_buffers; 1343 dri2_info.DestroyBuffers = radeon_dri2_destroy_buffers; 1344#else 1345 dri2_info.version = DRI2INFOREC_VERSION; 1346 dri2_info.CreateBuffer = radeon_dri2_create_buffer; 1347 dri2_info.DestroyBuffer = radeon_dri2_destroy_buffer; 1348#endif 1349 dri2_info.CopyRegion = radeon_dri2_copy_region; 1350 1351#ifdef USE_DRI2_SCHEDULING 1352 if (info->dri->pKernelDRMVersion->version_minor < 4) { 1353 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "You need a newer kernel for " 1354 "sync extension\n"); 1355 scheduling_works = FALSE; 1356 } 1357 1358 if (scheduling_works && info->drmmode.mode_res->count_crtcs > 2) { 1359#ifdef DRM_CAP_VBLANK_HIGH_CRTC 1360 uint64_t cap_value; 1361 1362 if (drmGetCap(info->dri2.drm_fd, DRM_CAP_VBLANK_HIGH_CRTC, &cap_value)) { 1363 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "You need a newer kernel " 1364 "for VBLANKs on CRTC > 1\n"); 1365 scheduling_works = FALSE; 1366 } else if (!cap_value) { 1367 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Your kernel does not " 1368 "handle VBLANKs on CRTC > 1\n"); 1369 scheduling_works = FALSE; 1370 } 1371#else 1372 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "You need to rebuild against a " 1373 "newer libdrm to handle VBLANKs on CRTC > 1\n"); 1374 scheduling_works = FALSE; 1375#endif 1376 } 1377 1378 if (scheduling_works) { 1379 dri2_info.version = 4; 1380 dri2_info.ScheduleSwap = radeon_dri2_schedule_swap; 1381 dri2_info.GetMSC = radeon_dri2_get_msc; 1382 dri2_info.ScheduleWaitMSC = radeon_dri2_schedule_wait_msc; 1383 dri2_info.numDrivers = RADEON_ARRAY_SIZE(driverNames); 1384 dri2_info.driverNames = driverNames; 1385 driverNames[0] = driverNames[1] = dri2_info.driverName; 1386 1387 if (pRADEONEnt->dri2_info_cnt == 0) { 1388#if HAS_DIXREGISTERPRIVATEKEY 1389 if (!dixRegisterPrivateKey(DRI2ClientEventsPrivateKey, 1390 PRIVATE_CLIENT, sizeof(DRI2ClientEventsRec))) { 1391 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI2 registering " 1392 "private key to client failed\n"); 1393 return FALSE; 1394 } 1395#else 1396 if (!dixRequestPrivate(DRI2ClientEventsPrivateKey, 1397 sizeof(DRI2ClientEventsRec))) { 1398 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI2 requesting " 1399 "private key to client failed\n"); 1400 return FALSE; 1401 } 1402#endif 1403 1404 AddCallback(&ClientStateCallback, radeon_dri2_client_state_changed, 0); 1405 } 1406 1407 pRADEONEnt->dri2_info_cnt++; 1408 } 1409#endif 1410 1411 info->dri2.enabled = DRI2ScreenInit(pScreen, &dri2_info); 1412 return info->dri2.enabled; 1413} 1414 1415void radeon_dri2_close_screen(ScreenPtr pScreen) 1416{ 1417 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1418 RADEONInfoPtr info = RADEONPTR(pScrn); 1419#ifdef USE_DRI2_SCHEDULING 1420 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 1421 1422 if (--pRADEONEnt->dri2_info_cnt == 0) 1423 DeleteCallback(&ClientStateCallback, radeon_dri2_client_state_changed, 0); 1424#endif 1425 DRI2CloseScreen(pScreen); 1426 drmFree(info->dri2.device_name); 1427} 1428 1429#endif 1430