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