intel_dri.c revision 13496ba1
1/************************************************************************** 2 3Copyright 2001 VA Linux Systems Inc., Fremont, California. 4Copyright © 2002 by David Dawes 5 6All Rights Reserved. 7 8Permission is hereby granted, free of charge, to any person obtaining a 9copy of this software and associated documentation files (the "Software"), 10to deal in the Software without restriction, including without limitation 11on the rights to use, copy, modify, merge, publish, distribute, sub 12license, and/or sell copies of the Software, and to permit persons to whom 13the Software is furnished to do so, subject to the following conditions: 14 15The above copyright notice and this permission notice (including the next 16paragraph) shall be included in all copies or substantial portions of the 17Software. 18 19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 22ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 23DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 25USE OR OTHER DEALINGS IN THE SOFTWARE. 26 27**************************************************************************/ 28 29/* 30 * Authors: Jeff Hartmann <jhartmann@valinux.com> 31 * David Dawes <dawes@xfree86.org> 32 * Keith Whitwell <keith@tungstengraphics.com> 33 */ 34 35#ifdef HAVE_CONFIG_H 36#include "config.h" 37#endif 38 39#include <stdio.h> 40#include <string.h> 41#include <assert.h> 42#include <sys/types.h> 43#include <sys/stat.h> 44#include <sys/ioctl.h> 45#include <unistd.h> 46#include <fcntl.h> 47#include <sys/time.h> 48#include <time.h> 49#include <errno.h> 50 51#include "xorg-server.h" 52#include "xf86.h" 53#include "xf86_OSproc.h" 54 55#include "xf86Pci.h" 56#include "xf86drm.h" 57 58#include "windowstr.h" 59#include "shadow.h" 60#include "fb.h" 61 62#include "intel.h" 63#include "i830_reg.h" 64 65#include "i915_drm.h" 66 67#include "dri2.h" 68 69#if USE_UXA 70#include "intel_uxa.h" 71#endif 72 73typedef struct { 74 int refcnt; 75 PixmapPtr pixmap; 76} I830DRI2BufferPrivateRec, *I830DRI2BufferPrivatePtr; 77 78#if HAS_DEVPRIVATEKEYREC 79static DevPrivateKeyRec i830_client_key; 80#else 81static int i830_client_key; 82#endif 83 84static uint32_t pixmap_flink(PixmapPtr pixmap) 85{ 86 struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap); 87 uint32_t name; 88 89 if (priv == NULL || priv->bo == NULL) 90 return 0; 91 92 if (dri_bo_flink(priv->bo, &name) != 0) 93 return 0; 94 95 priv->pinned |= PIN_DRI2; 96 return name; 97} 98 99static PixmapPtr get_front_buffer(DrawablePtr drawable) 100{ 101 PixmapPtr pixmap; 102 103 pixmap = get_drawable_pixmap(drawable); 104 if (!intel_get_pixmap_bo(pixmap)) 105 return NULL; 106 107 pixmap->refcnt++; 108 return pixmap; 109} 110 111#if DRI2INFOREC_VERSION < 2 112static DRI2BufferPtr 113I830DRI2CreateBuffers(DrawablePtr drawable, unsigned int *attachments, 114 int count) 115{ 116 ScreenPtr screen = drawable->pScreen; 117 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 118 intel_screen_private *intel = intel_get_screen_private(scrn); 119 DRI2BufferPtr buffers; 120 I830DRI2BufferPrivatePtr privates; 121 PixmapPtr pixmap, pDepthPixmap; 122 int i; 123 124 buffers = calloc(count, sizeof *buffers); 125 if (buffers == NULL) 126 return NULL; 127 privates = calloc(count, sizeof *privates); 128 if (privates == NULL) { 129 free(buffers); 130 return NULL; 131 } 132 133 pDepthPixmap = NULL; 134 for (i = 0; i < count; i++) { 135 pixmap = NULL; 136 if (attachments[i] == DRI2BufferFrontLeft) { 137 pixmap = get_front_buffer(drawable); 138 139 if (pixmap == NULL) 140 drawable = &(get_drawable_pixmap(drawable)->drawable); 141 } else if (attachments[i] == DRI2BufferStencil && pDepthPixmap) { 142 pixmap = pDepthPixmap; 143 pixmap->refcnt++; 144 } 145 146 if (pixmap == NULL) { 147 unsigned int hint = INTEL_CREATE_PIXMAP_DRI2; 148 149 if (intel->tiling & INTEL_TILING_3D) { 150 switch (attachments[i]) { 151 case DRI2BufferDepth: 152 if (SUPPORTS_YTILING(intel)) 153 hint |= INTEL_CREATE_PIXMAP_TILING_Y; 154 else 155 hint |= INTEL_CREATE_PIXMAP_TILING_X; 156 break; 157 case DRI2BufferFakeFrontLeft: 158 case DRI2BufferFakeFrontRight: 159 case DRI2BufferBackLeft: 160 case DRI2BufferBackRight: 161 hint |= INTEL_CREATE_PIXMAP_TILING_X; 162 break; 163 } 164 } 165 166 pixmap = screen->CreatePixmap(screen, 167 drawable->width, 168 drawable->height, 169 drawable->depth, 170 hint); 171 if (pixmap == NULL || 172 intel_get_pixmap_bo(pixmap) == NULL) 173 { 174 if (pixmap) 175 screen->DestroyPixmap(pixmap); 176 goto unwind; 177 } 178 } 179 180 if (attachments[i] == DRI2BufferDepth) 181 pDepthPixmap = pixmap; 182 183 buffers[i].attachment = attachments[i]; 184 buffers[i].pitch = pixmap->devKind; 185 buffers[i].cpp = pixmap->drawable.bitsPerPixel / 8; 186 buffers[i].driverPrivate = &privates[i]; 187 buffers[i].flags = 0; /* not tiled */ 188 privates[i].refcnt = 1; 189 privates[i].pixmap = pixmap; 190 191 if ((buffers[i].name = pixmap_flink(pixmap)) == 0) { 192 /* failed to name buffer */ 193 screen->DestroyPixmap(pixmap); 194 goto unwind; 195 } 196 } 197 198 return buffers; 199 200unwind: 201 while (i--) 202 screen->DestroyPixmap(privates[i].pixmap); 203 free(privates); 204 free(buffers); 205 return NULL; 206} 207 208static void 209I830DRI2DestroyBuffers(DrawablePtr drawable, DRI2BufferPtr buffers, int count) 210{ 211 ScreenPtr screen = drawable->pScreen; 212 I830DRI2BufferPrivatePtr private; 213 int i; 214 215 for (i = 0; i < count; i++) { 216 private = buffers[i].driverPrivate; 217 screen->DestroyPixmap(private->pixmap); 218 } 219 220 if (buffers) { 221 free(buffers[0].driverPrivate); 222 free(buffers); 223 } 224} 225 226#else 227 228static DRI2Buffer2Ptr 229I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment, 230 unsigned int format) 231{ 232 ScreenPtr screen = drawable->pScreen; 233 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 234 intel_screen_private *intel = intel_get_screen_private(scrn); 235 DRI2Buffer2Ptr buffer; 236 I830DRI2BufferPrivatePtr privates; 237 PixmapPtr pixmap; 238 239 buffer = calloc(1, sizeof *buffer); 240 if (buffer == NULL) 241 return NULL; 242 privates = calloc(1, sizeof *privates); 243 if (privates == NULL) { 244 free(buffer); 245 return NULL; 246 } 247 248 pixmap = NULL; 249 if (attachment == DRI2BufferFrontLeft) { 250 pixmap = get_front_buffer(drawable); 251 if (pixmap == NULL) 252 drawable = &(get_drawable_pixmap(drawable)->drawable); 253 } 254 255 if (pixmap == NULL) { 256 unsigned int hint = INTEL_CREATE_PIXMAP_DRI2; 257 int pixmap_width = drawable->width; 258 int pixmap_height = drawable->height; 259 int pixmap_cpp = (format != 0) ? format : drawable->depth; 260 261 if (intel->tiling & INTEL_TILING_3D) { 262 switch (attachment) { 263 case DRI2BufferDepth: 264 case DRI2BufferDepthStencil: 265 case DRI2BufferHiz: 266 if (SUPPORTS_YTILING(intel)) { 267 hint |= INTEL_CREATE_PIXMAP_TILING_Y; 268 break; 269 } 270 case DRI2BufferAccum: 271 case DRI2BufferBackLeft: 272 case DRI2BufferBackRight: 273 case DRI2BufferFakeFrontLeft: 274 case DRI2BufferFakeFrontRight: 275 case DRI2BufferFrontLeft: 276 case DRI2BufferFrontRight: 277 hint |= INTEL_CREATE_PIXMAP_TILING_X; 278 break; 279 case DRI2BufferStencil: 280 /* 281 * The stencil buffer is W tiled. However, we 282 * request from the kernel a non-tiled buffer 283 * because the GTT is incapable of W fencing. 284 */ 285 hint |= INTEL_CREATE_PIXMAP_TILING_NONE; 286 break; 287 default: 288 free(privates); 289 free(buffer); 290 return NULL; 291 } 292 } 293 294 /* 295 * The stencil buffer has quirky pitch requirements. From Vol 296 * 2a, 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface 297 * Pitch": 298 * The pitch must be set to 2x the value computed based on 299 * width, as the stencil buffer is stored with two rows 300 * interleaved. 301 * To accomplish this, we resort to the nasty hack of doubling 302 * the drm region's cpp and halving its height. 303 * 304 * If we neglect to double the pitch, then render corruption 305 * occurs. 306 */ 307 if (attachment == DRI2BufferStencil) { 308 pixmap_width = ALIGN(pixmap_width, 64); 309 pixmap_height = ALIGN((pixmap_height + 1) / 2, 64); 310 pixmap_cpp *= 2; 311 } 312 313 pixmap = screen->CreatePixmap(screen, 314 pixmap_width, 315 pixmap_height, 316 pixmap_cpp, 317 hint); 318 if (pixmap == NULL || intel_get_pixmap_bo(pixmap) == NULL) { 319 if (pixmap) 320 screen->DestroyPixmap(pixmap); 321 free(privates); 322 free(buffer); 323 return NULL; 324 } 325 } 326 327 buffer->attachment = attachment; 328 buffer->pitch = pixmap->devKind; 329 buffer->cpp = pixmap->drawable.bitsPerPixel / 8; 330 buffer->driverPrivate = privates; 331 buffer->format = format; 332 buffer->flags = 0; /* not tiled */ 333 privates->refcnt = 1; 334 privates->pixmap = pixmap; 335 336 if ((buffer->name = pixmap_flink(pixmap)) == 0) { 337 /* failed to name buffer */ 338 screen->DestroyPixmap(pixmap); 339 free(privates); 340 free(buffer); 341 return NULL; 342 } 343 344 return buffer; 345} 346 347static void I830DRI2DestroyBuffer(DrawablePtr drawable, DRI2Buffer2Ptr buffer) 348{ 349 if (buffer && buffer->driverPrivate) { 350 I830DRI2BufferPrivatePtr private = buffer->driverPrivate; 351 if (--private->refcnt == 0) { 352 ScreenPtr screen = private->pixmap->drawable.pScreen; 353 screen->DestroyPixmap(private->pixmap); 354 355 free(private); 356 free(buffer); 357 } 358 } else 359 free(buffer); 360} 361 362#endif 363 364static void 365I830DRI2CopyRegion(DrawablePtr drawable, RegionPtr pRegion, 366 DRI2BufferPtr destBuffer, DRI2BufferPtr sourceBuffer) 367{ 368 I830DRI2BufferPrivatePtr srcPrivate = sourceBuffer->driverPrivate; 369 I830DRI2BufferPrivatePtr dstPrivate = destBuffer->driverPrivate; 370 ScreenPtr screen = drawable->pScreen; 371 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 372 intel_screen_private *intel = intel_get_screen_private(scrn); 373 DrawablePtr src = (sourceBuffer->attachment == DRI2BufferFrontLeft) 374 ? drawable : &srcPrivate->pixmap->drawable; 375 DrawablePtr dst = (destBuffer->attachment == DRI2BufferFrontLeft) 376 ? drawable : &dstPrivate->pixmap->drawable; 377 RegionPtr pCopyClip; 378 GCPtr gc; 379 380 gc = GetScratchGC(dst->depth, screen); 381 if (!gc) 382 return; 383 384 pCopyClip = REGION_CREATE(screen, NULL, 0); 385 REGION_COPY(screen, pCopyClip, pRegion); 386 (*gc->funcs->ChangeClip) (gc, CT_REGION, pCopyClip, 0); 387 ValidateGC(dst, gc); 388 389 /* Wait for the scanline to be outside the region to be copied */ 390 if (scrn->vtSema && 391 pixmap_is_scanout(get_drawable_pixmap(dst)) && 392 intel->swapbuffers_wait && INTEL_INFO(intel)->gen < 060) { 393 BoxPtr box; 394 BoxRec crtcbox; 395 int y1, y2; 396 int event, load_scan_lines_pipe; 397 xf86CrtcPtr crtc; 398 Bool full_height = FALSE; 399 400 box = REGION_EXTENTS(unused, gc->pCompositeClip); 401 crtc = intel_covering_crtc(scrn, box, NULL, &crtcbox); 402 403 /* 404 * Make sure the CRTC is valid and this is the real front 405 * buffer 406 */ 407 if (crtc != NULL && !crtc->rotatedData) { 408 int pipe = intel_crtc_to_pipe(crtc); 409 410 /* 411 * Make sure we don't wait for a scanline that will 412 * never occur 413 */ 414 y1 = (crtcbox.y1 <= box->y1) ? box->y1 - crtcbox.y1 : 0; 415 y2 = (box->y2 <= crtcbox.y2) ? 416 box->y2 - crtcbox.y1 : crtcbox.y2 - crtcbox.y1; 417 418 if (y1 == 0 && y2 == (crtcbox.y2 - crtcbox.y1)) 419 full_height = TRUE; 420 421 /* 422 * Pre-965 doesn't have SVBLANK, so we need a bit 423 * of extra time for the blitter to start up and 424 * do its job for a full height blit 425 */ 426 if (full_height && INTEL_INFO(intel)->gen < 040) 427 y2 -= 2; 428 429 if (pipe == 0) { 430 event = MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW; 431 load_scan_lines_pipe = 432 MI_LOAD_SCAN_LINES_DISPLAY_PIPEA; 433 if (full_height && INTEL_INFO(intel)->gen >= 040) 434 event = MI_WAIT_FOR_PIPEA_SVBLANK; 435 } else { 436 event = MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW; 437 load_scan_lines_pipe = 438 MI_LOAD_SCAN_LINES_DISPLAY_PIPEB; 439 if (full_height && INTEL_INFO(intel)->gen >= 040) 440 event = MI_WAIT_FOR_PIPEB_SVBLANK; 441 } 442 443 if (crtc->mode.Flags & V_INTERLACE) { 444 /* DSL count field lines */ 445 y1 /= 2; 446 y2 /= 2; 447 } 448 449 BEGIN_BATCH(5); 450 /* 451 * The documentation says that the LOAD_SCAN_LINES 452 * command always comes in pairs. Don't ask me why. 453 */ 454 OUT_BATCH(MI_LOAD_SCAN_LINES_INCL | 455 load_scan_lines_pipe); 456 OUT_BATCH((y1 << 16) | (y2-1)); 457 OUT_BATCH(MI_LOAD_SCAN_LINES_INCL | 458 load_scan_lines_pipe); 459 OUT_BATCH((y1 << 16) | (y2-1)); 460 OUT_BATCH(MI_WAIT_FOR_EVENT | event); 461 ADVANCE_BATCH(); 462 } 463 } 464 465 /* It's important that this copy gets submitted before the 466 * direct rendering client submits rendering for the next 467 * frame, but we don't actually need to submit right now. The 468 * client will wait for the DRI2CopyRegion reply or the swap 469 * buffer event before rendering, and we'll hit the flush 470 * callback chain before those messages are sent. We submit 471 * our batch buffers from the flush callback chain so we know 472 * that will happen before the client tries to render 473 * again. */ 474 475 gc->ops->CopyArea(src, dst, gc, 476 0, 0, 477 drawable->width, drawable->height, 478 0, 0); 479 480 FreeScratchGC(gc); 481 482 /* And make sure the WAIT_FOR_EVENT is queued before any 483 * modesetting/dpms operations on the pipe. 484 */ 485 intel_batch_submit(scrn); 486} 487 488static void 489I830DRI2FallbackBlitSwap(DrawablePtr drawable, 490 DRI2BufferPtr dst, 491 DRI2BufferPtr src) 492{ 493 BoxRec box; 494 RegionRec region; 495 496 box.x1 = 0; 497 box.y1 = 0; 498 box.x2 = drawable->width; 499 box.y2 = drawable->height; 500 REGION_INIT(pScreen, ®ion, &box, 0); 501 502 I830DRI2CopyRegion(drawable, ®ion, dst, src); 503} 504 505#if DRI2INFOREC_VERSION >= 4 506 507static void I830DRI2ReferenceBuffer(DRI2Buffer2Ptr buffer) 508{ 509 if (buffer) { 510 I830DRI2BufferPrivatePtr private = buffer->driverPrivate; 511 private->refcnt++; 512 } 513} 514 515static xf86CrtcPtr 516I830DRI2DrawableCrtc(DrawablePtr pDraw) 517{ 518 ScreenPtr pScreen = pDraw->pScreen; 519 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 520 BoxRec box, crtcbox; 521 xf86CrtcPtr crtc = NULL; 522 523 box.x1 = pDraw->x; 524 box.y1 = pDraw->y; 525 box.x2 = box.x1 + pDraw->width; 526 box.y2 = box.y1 + pDraw->height; 527 528 if (pDraw->type != DRAWABLE_PIXMAP) 529 crtc = intel_covering_crtc(pScrn, &box, NULL, &crtcbox); 530 531 /* Make sure the CRTC is valid and this is the real front buffer */ 532 if (crtc != NULL && !crtc->rotatedData) 533 return crtc; 534 535 return NULL; 536} 537 538static RESTYPE frame_event_client_type, frame_event_drawable_type; 539 540struct i830_dri2_resource { 541 XID id; 542 RESTYPE type; 543 struct list list; 544}; 545 546static struct i830_dri2_resource * 547get_resource(XID id, RESTYPE type) 548{ 549 struct i830_dri2_resource *resource; 550 void *ptr; 551 552 ptr = NULL; 553 dixLookupResourceByType(&ptr, id, type, NULL, DixWriteAccess); 554 if (ptr) 555 return ptr; 556 557 resource = malloc(sizeof(*resource)); 558 if (resource == NULL) 559 return NULL; 560 561 if (!AddResource(id, type, resource)) { 562 free(resource); 563 return NULL; 564 } 565 566 resource->id = id; 567 resource->type = type; 568 list_init(&resource->list); 569 return resource; 570} 571 572static int 573i830_dri2_frame_event_client_gone(void *data, XID id) 574{ 575 struct i830_dri2_resource *resource = data; 576 577 while (!list_is_empty(&resource->list)) { 578 DRI2FrameEventPtr info = 579 list_first_entry(&resource->list, 580 DRI2FrameEventRec, 581 client_resource); 582 583 list_del(&info->client_resource); 584 info->client = NULL; 585 } 586 free(resource); 587 588 return Success; 589} 590 591static int 592i830_dri2_frame_event_drawable_gone(void *data, XID id) 593{ 594 struct i830_dri2_resource *resource = data; 595 596 while (!list_is_empty(&resource->list)) { 597 DRI2FrameEventPtr info = 598 list_first_entry(&resource->list, 599 DRI2FrameEventRec, 600 drawable_resource); 601 602 list_del(&info->drawable_resource); 603 info->drawable_id = None; 604 } 605 free(resource); 606 607 return Success; 608} 609 610static Bool 611i830_dri2_register_frame_event_resource_types(void) 612{ 613 frame_event_client_type = CreateNewResourceType(i830_dri2_frame_event_client_gone, "Frame Event Client"); 614 if (!frame_event_client_type) 615 return FALSE; 616 617 frame_event_drawable_type = CreateNewResourceType(i830_dri2_frame_event_drawable_gone, "Frame Event Drawable"); 618 if (!frame_event_drawable_type) 619 return FALSE; 620 621 return TRUE; 622} 623 624static XID 625get_client_id(ClientPtr client) 626{ 627#if HAS_DIXREGISTERPRIVATEKEY 628 XID *ptr = dixGetPrivateAddr(&client->devPrivates, &i830_client_key); 629#else 630 XID *ptr = dixLookupPrivate(&client->devPrivates, &i830_client_key); 631#endif 632 if (*ptr == 0) 633 *ptr = FakeClientID(client->index); 634 return *ptr; 635} 636 637/* 638 * Hook this frame event into the server resource 639 * database so we can clean it up if the drawable or 640 * client exits while the swap is pending 641 */ 642static Bool 643i830_dri2_add_frame_event(DRI2FrameEventPtr info) 644{ 645 struct i830_dri2_resource *resource; 646 647 resource = get_resource(get_client_id(info->client), 648 frame_event_client_type); 649 if (resource == NULL) 650 return FALSE; 651 652 list_add(&info->client_resource, &resource->list); 653 654 resource = get_resource(info->drawable_id, frame_event_drawable_type); 655 if (resource == NULL) { 656 list_del(&info->client_resource); 657 return FALSE; 658 } 659 660 list_add(&info->drawable_resource, &resource->list); 661 662 return TRUE; 663} 664 665static void 666i830_dri2_del_frame_event(DRI2FrameEventPtr info) 667{ 668 list_del(&info->client_resource); 669 list_del(&info->drawable_resource); 670 671 if (info->front) 672 I830DRI2DestroyBuffer(NULL, info->front); 673 if (info->back) 674 I830DRI2DestroyBuffer(NULL, info->back); 675 676 free(info); 677} 678 679static struct intel_uxa_pixmap * 680intel_exchange_pixmap_buffers(struct intel_screen_private *intel, PixmapPtr front, PixmapPtr back) 681{ 682 struct intel_uxa_pixmap *new_front = NULL, *new_back; 683 RegionRec region; 684 685 /* Post damage on the front buffer so that listeners, such 686 * as DisplayLink know take a copy and shove it over the USB. 687 * also for sw cursors. 688 */ 689 region.extents.x1 = region.extents.y1 = 0; 690 region.extents.x2 = front->drawable.width; 691 region.extents.y2 = front->drawable.height; 692 region.data = NULL; 693 DamageRegionAppend(&front->drawable, ®ion); 694 695 new_front = intel_uxa_get_pixmap_private(back); 696 new_back = intel_uxa_get_pixmap_private(front); 697 intel_uxa_set_pixmap_private(front, new_front); 698 intel_uxa_set_pixmap_private(back, new_back); 699 new_front->busy = 1; 700 new_back->busy = -1; 701 702 DamageRegionProcessPending(&front->drawable); 703 704 return new_front; 705} 706 707static void 708I830DRI2ExchangeBuffers(struct intel_screen_private *intel, DRI2BufferPtr front, DRI2BufferPtr back) 709{ 710 I830DRI2BufferPrivatePtr front_priv, back_priv; 711 int tmp; 712 struct intel_uxa_pixmap *new_front; 713 714 front_priv = front->driverPrivate; 715 back_priv = back->driverPrivate; 716 717 /* Swap BO names so DRI works */ 718 tmp = front->name; 719 front->name = back->name; 720 back->name = tmp; 721 722 /* Swap pixmap bos */ 723 new_front = intel_exchange_pixmap_buffers(intel, 724 front_priv->pixmap, 725 back_priv->pixmap); 726 dri_bo_unreference (intel->front_buffer); 727 intel->front_buffer = new_front->bo; 728 dri_bo_reference (intel->front_buffer); 729} 730 731static drm_intel_bo *get_pixmap_bo(I830DRI2BufferPrivatePtr priv) 732{ 733 drm_intel_bo *bo = intel_get_pixmap_bo(priv->pixmap); 734 assert(bo != NULL); /* guaranteed by construction of the DRI2 buffer */ 735 return bo; 736} 737 738static void 739I830DRI2FlipComplete(uint64_t frame, uint64_t usec, void *pageflip_data) 740{ 741 DRI2FrameEventPtr info = pageflip_data; 742 743 I830DRI2FlipEventHandler((uint32_t) frame, usec / 1000000, 744 usec % 1000000, 745 info); 746} 747 748static void 749I830DRI2FlipAbort(void *pageflip_data) 750{ 751 DRI2FrameEventPtr info = pageflip_data; 752 753 i830_dri2_del_frame_event(info); 754} 755 756/* 757 * Our internal swap routine takes care of actually exchanging, blitting, or 758 * flipping buffers as necessary. 759 */ 760static Bool 761I830DRI2ScheduleFlip(struct intel_screen_private *intel, 762 DrawablePtr draw, 763 DRI2FrameEventPtr info) 764{ 765 I830DRI2BufferPrivatePtr priv = info->back->driverPrivate; 766 drm_intel_bo *new_back, *old_back; 767 int tmp_name; 768 769 if (!intel->use_triple_buffer) { 770 info->type = DRI2_SWAP; 771 if (!intel_do_pageflip(intel, 772 get_pixmap_bo(priv), 773 info->pipe, FALSE, info, 774 I830DRI2FlipComplete, 775 I830DRI2FlipAbort)) 776 return FALSE; 777 778 I830DRI2ExchangeBuffers(intel, info->front, info->back); 779 return TRUE; 780 } 781 782 if (intel->pending_flip[info->pipe]) { 783 assert(intel->pending_flip[info->pipe]->chain == NULL); 784 intel->pending_flip[info->pipe]->chain = info; 785 return TRUE; 786 } 787 788 if (intel->back_buffer == NULL) { 789 new_back = drm_intel_bo_alloc(intel->bufmgr, "front buffer", 790 intel->front_buffer->size, 0); 791 if (new_back == NULL) 792 return FALSE; 793 794 if (intel->front_tiling != I915_TILING_NONE) { 795 uint32_t tiling = intel->front_tiling; 796 drm_intel_bo_set_tiling(new_back, &tiling, intel->front_pitch); 797 if (tiling != intel->front_tiling) { 798 drm_intel_bo_unreference(new_back); 799 return FALSE; 800 } 801 } 802 803 drm_intel_bo_disable_reuse(new_back); 804 dri_bo_flink(new_back, &intel->back_name); 805 } else { 806 new_back = intel->back_buffer; 807 intel->back_buffer = NULL; 808 } 809 810 old_back = get_pixmap_bo(priv); 811 if (!intel_do_pageflip(intel, old_back, info->pipe, FALSE, info, I830DRI2FlipComplete, I830DRI2FlipAbort)) { 812 intel->back_buffer = new_back; 813 return FALSE; 814 } 815 info->type = DRI2_SWAP_CHAIN; 816 intel->pending_flip[info->pipe] = info; 817 818 priv = info->front->driverPrivate; 819 820 /* Exchange the current front-buffer with the fresh bo */ 821 822 intel->back_buffer = intel->front_buffer; 823 drm_intel_bo_reference(intel->back_buffer); 824 intel_set_pixmap_bo(priv->pixmap, new_back); 825 drm_intel_bo_unreference(new_back); 826 827 tmp_name = info->front->name; 828 info->front->name = intel->back_name; 829 intel->back_name = tmp_name; 830 831 /* Then flip DRI2 pointers and update the screen pixmap */ 832 I830DRI2ExchangeBuffers(intel, info->front, info->back); 833 DRI2SwapComplete(info->client, draw, 0, 0, 0, 834 DRI2_EXCHANGE_COMPLETE, 835 info->event_complete, 836 info->event_data); 837 return TRUE; 838} 839 840static Bool 841can_exchange(DrawablePtr drawable, DRI2BufferPtr front, DRI2BufferPtr back) 842{ 843 ScrnInfoPtr pScrn = xf86ScreenToScrn(drawable->pScreen); 844 struct intel_screen_private *intel = intel_get_screen_private(pScrn); 845 I830DRI2BufferPrivatePtr front_priv = front->driverPrivate; 846 I830DRI2BufferPrivatePtr back_priv = back->driverPrivate; 847 PixmapPtr front_pixmap = front_priv->pixmap; 848 PixmapPtr back_pixmap = back_priv->pixmap; 849 struct intel_uxa_pixmap *front_intel = intel_uxa_get_pixmap_private(front_pixmap); 850 struct intel_uxa_pixmap *back_intel = intel_uxa_get_pixmap_private(back_pixmap); 851 852 if (!pScrn->vtSema) 853 return FALSE; 854 855 if (I830DRI2DrawableCrtc(drawable) == NULL) 856 return FALSE; 857 858 if (!DRI2CanFlip(drawable)) 859 return FALSE; 860 861 if (intel->shadow_present) 862 return FALSE; 863 864 if (!intel->use_pageflipping) 865 return FALSE; 866 867 if (front_pixmap->drawable.width != back_pixmap->drawable.width) 868 return FALSE; 869 870 if (front_pixmap->drawable.height != back_pixmap->drawable.height) 871 return FALSE; 872 873 /* XXX should we be checking depth instead of bpp? */ 874#if 0 875 if (front_pixmap->drawable.depth != back_pixmap->drawable.depth) 876 return FALSE; 877#else 878 if (front_pixmap->drawable.bitsPerPixel != back_pixmap->drawable.bitsPerPixel) 879 return FALSE; 880#endif 881 882 /* prevent an implicit tiling mode change */ 883 if (front_intel->tiling != back_intel->tiling) 884 return FALSE; 885 886 if (front_intel->pinned & ~(PIN_SCANOUT | PIN_DRI2)) 887 return FALSE; 888 889 return TRUE; 890} 891 892void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec, 893 unsigned int tv_usec, DRI2FrameEventPtr swap_info) 894{ 895 intel_screen_private *intel = swap_info->intel; 896 DrawablePtr drawable; 897 int status; 898 899 if (!swap_info->drawable_id) 900 status = BadDrawable; 901 else 902 status = dixLookupDrawable(&drawable, swap_info->drawable_id, serverClient, 903 M_ANY, DixWriteAccess); 904 if (status != Success) { 905 i830_dri2_del_frame_event(swap_info); 906 return; 907 } 908 909 910 switch (swap_info->type) { 911 case DRI2_FLIP: 912 /* If we can still flip... */ 913 if (can_exchange(drawable, swap_info->front, swap_info->back) && 914 I830DRI2ScheduleFlip(intel, drawable, swap_info)) 915 return; 916 917 /* else fall through to exchange/blit */ 918 case DRI2_SWAP: { 919 I830DRI2FallbackBlitSwap(drawable, 920 swap_info->front, swap_info->back); 921 DRI2SwapComplete(swap_info->client, drawable, frame, tv_sec, tv_usec, 922 DRI2_BLIT_COMPLETE, 923 swap_info->client ? swap_info->event_complete : NULL, 924 swap_info->event_data); 925 break; 926 } 927 case DRI2_WAITMSC: 928 if (swap_info->client) 929 DRI2WaitMSCComplete(swap_info->client, drawable, 930 frame, tv_sec, tv_usec); 931 break; 932 default: 933 xf86DrvMsg(intel->scrn->scrnIndex, X_WARNING, 934 "%s: unknown vblank event received\n", __func__); 935 /* Unknown type */ 936 break; 937 } 938 939 i830_dri2_del_frame_event(swap_info); 940} 941 942void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec, 943 unsigned int tv_usec, DRI2FrameEventPtr flip_info) 944{ 945 struct intel_screen_private *intel = flip_info->intel; 946 DrawablePtr drawable; 947 DRI2FrameEventPtr chain; 948 949 drawable = NULL; 950 if (flip_info->drawable_id) 951 dixLookupDrawable(&drawable, flip_info->drawable_id, serverClient, 952 M_ANY, DixWriteAccess); 953 954 955 /* We assume our flips arrive in order, so we don't check the frame */ 956 switch (flip_info->type) { 957 case DRI2_SWAP: 958 if (!drawable) 959 break; 960 961 /* Check for too small vblank count of pageflip completion, taking wraparound 962 * into account. This usually means some defective kms pageflip completion, 963 * causing wrong (msc, ust) return values and possible visual corruption. 964 */ 965 if ((frame < flip_info->frame) && (flip_info->frame - frame < 5)) { 966 static int limit = 5; 967 968 /* XXX we are currently hitting this path with older 969 * kernels, so make it quieter. 970 */ 971 if (limit) { 972 xf86DrvMsg(intel->scrn->scrnIndex, X_WARNING, 973 "%s: Pageflip completion has impossible msc %d < target_msc %d\n", 974 __func__, frame, flip_info->frame); 975 limit--; 976 } 977 978 /* All-0 values signal timestamping failure. */ 979 frame = tv_sec = tv_usec = 0; 980 } 981 982 DRI2SwapComplete(flip_info->client, drawable, frame, tv_sec, tv_usec, 983 DRI2_FLIP_COMPLETE, flip_info->client ? flip_info->event_complete : NULL, 984 flip_info->event_data); 985 break; 986 987 case DRI2_SWAP_CHAIN: 988 assert(intel->pending_flip[flip_info->pipe] == flip_info); 989 intel->pending_flip[flip_info->pipe] = NULL; 990 991 chain = flip_info->chain; 992 if (chain) { 993 DrawablePtr chain_drawable = NULL; 994 if (chain->drawable_id) 995 dixLookupDrawable(&chain_drawable, 996 chain->drawable_id, 997 serverClient, 998 M_ANY, DixWriteAccess); 999 if (chain_drawable == NULL) { 1000 i830_dri2_del_frame_event(chain); 1001 } else if (!can_exchange(chain_drawable, chain->front, chain->back) || 1002 !I830DRI2ScheduleFlip(intel, chain_drawable, chain)) { 1003 I830DRI2FallbackBlitSwap(chain_drawable, 1004 chain->front, 1005 chain->back); 1006 1007 DRI2SwapComplete(chain->client, chain_drawable, frame, tv_sec, tv_usec, 1008 DRI2_BLIT_COMPLETE, 1009 chain->client ? chain->event_complete : NULL, 1010 chain->event_data); 1011 i830_dri2_del_frame_event(chain); 1012 } 1013 } 1014 break; 1015 1016 default: 1017 xf86DrvMsg(intel->scrn->scrnIndex, X_WARNING, 1018 "%s: unknown vblank event received\n", __func__); 1019 /* Unknown type */ 1020 break; 1021 } 1022 1023 i830_dri2_del_frame_event(flip_info); 1024} 1025 1026static uint32_t pipe_select(int pipe) 1027{ 1028 if (pipe > 1) 1029 return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT; 1030 else if (pipe > 0) 1031 return DRM_VBLANK_SECONDARY; 1032 else 1033 return 0; 1034} 1035 1036static void 1037intel_dri2_vblank_handler(ScrnInfoPtr scrn, 1038 xf86CrtcPtr crtc, 1039 uint64_t msc, 1040 uint64_t usec, 1041 void *data) 1042{ 1043 DRI2FrameEventPtr swap_info = data; 1044 1045 I830DRI2FrameEventHandler((uint32_t) msc, usec / 1000000, usec % 1000000, swap_info); 1046} 1047 1048static void 1049intel_dri2_vblank_abort(ScrnInfoPtr scrn, 1050 xf86CrtcPtr crtc, 1051 void *data) 1052{ 1053 DRI2FrameEventPtr swap_info = data; 1054 1055 i830_dri2_del_frame_event(swap_info); 1056} 1057 1058/* 1059 * ScheduleSwap is responsible for requesting a DRM vblank event for the 1060 * appropriate frame. 1061 * 1062 * In the case of a blit (e.g. for a windowed swap) or buffer exchange, 1063 * the vblank requested can simply be the last queued swap frame + the swap 1064 * interval for the drawable. 1065 * 1066 * In the case of a page flip, we request an event for the last queued swap 1067 * frame + swap interval - 1, since we'll need to queue the flip for the frame 1068 * immediately following the received event. 1069 * 1070 * The client will be blocked if it tries to perform further GL commands 1071 * after queueing a swap, though in the Intel case after queueing a flip, the 1072 * client is free to queue more commands; they'll block in the kernel if 1073 * they access buffers busy with the flip. 1074 * 1075 * When the swap is complete, the driver should call into the server so it 1076 * can send any swap complete events that have been requested. 1077 */ 1078static int 1079I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, 1080 DRI2BufferPtr back, CARD64 *target_msc, CARD64 divisor, 1081 CARD64 remainder, DRI2SwapEventPtr func, void *data) 1082{ 1083 ScreenPtr screen = draw->pScreen; 1084 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1085 intel_screen_private *intel = intel_get_screen_private(scrn); 1086 drmVBlank vbl; 1087 int ret; 1088 xf86CrtcPtr crtc = I830DRI2DrawableCrtc(draw); 1089 int pipe = crtc ? intel_crtc_to_pipe(crtc) : -1; 1090 int flip = 0; 1091 DRI2FrameEventPtr swap_info = NULL; 1092 enum DRI2FrameEventType swap_type = DRI2_SWAP; 1093 uint64_t current_msc, current_ust; 1094 uint64_t request_msc; 1095 uint32_t seq; 1096 1097 /* Drawable not displayed... just complete the swap */ 1098 if (pipe == -1) 1099 goto blit_fallback; 1100 1101 swap_info = calloc(1, sizeof(DRI2FrameEventRec)); 1102 if (!swap_info) 1103 goto blit_fallback; 1104 1105 swap_info->intel = intel; 1106 swap_info->drawable_id = draw->id; 1107 swap_info->client = client; 1108 swap_info->event_complete = func; 1109 swap_info->event_data = data; 1110 swap_info->front = front; 1111 swap_info->back = back; 1112 swap_info->pipe = pipe; 1113 1114 if (!i830_dri2_add_frame_event(swap_info)) { 1115 free(swap_info); 1116 swap_info = NULL; 1117 goto blit_fallback; 1118 } 1119 1120 I830DRI2ReferenceBuffer(front); 1121 I830DRI2ReferenceBuffer(back); 1122 1123 ret = intel_get_crtc_msc_ust(scrn, crtc, ¤t_msc, ¤t_ust); 1124 if (ret) 1125 goto blit_fallback; 1126 1127 /* Flips need to be submitted one frame before */ 1128 if (can_exchange(draw, front, back)) { 1129 swap_type = DRI2_FLIP; 1130 flip = 1; 1131 } 1132 1133 swap_info->type = swap_type; 1134 1135 /* Correct target_msc by 'flip' if swap_type == DRI2_FLIP. 1136 * Do it early, so handling of different timing constraints 1137 * for divisor, remainder and msc vs. target_msc works. 1138 */ 1139 if (*target_msc > 0) 1140 *target_msc -= flip; 1141 1142 /* 1143 * If divisor is zero, or current_msc is smaller than target_msc 1144 * we just need to make sure target_msc passes before initiating 1145 * the swap. 1146 */ 1147 if (divisor == 0 || current_msc < *target_msc) { 1148 /* 1149 * If we can, schedule the flip directly from here rather 1150 * than waiting for an event from the kernel for the current 1151 * (or a past) MSC. 1152 */ 1153 if (flip && divisor == 0 && current_msc >= *target_msc && 1154 I830DRI2ScheduleFlip(intel, draw, swap_info)) 1155 return TRUE; 1156 1157 vbl.request.type = 1158 DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | pipe_select(pipe); 1159 1160 /* If non-pageflipping, but blitting/exchanging, we need to use 1161 * DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later 1162 * on. 1163 */ 1164 if (flip == 0) 1165 vbl.request.type |= DRM_VBLANK_NEXTONMISS; 1166 1167 /* If target_msc already reached or passed, set it to 1168 * current_msc to ensure we return a reasonable value back 1169 * to the caller. This makes swap_interval logic more robust. 1170 */ 1171 if (current_msc >= *target_msc) 1172 *target_msc = current_msc; 1173 1174 seq = intel_drm_queue_alloc(scrn, crtc, swap_info, intel_dri2_vblank_handler, intel_dri2_vblank_abort); 1175 if (!seq) 1176 goto blit_fallback; 1177 1178 vbl.request.sequence = intel_crtc_msc_to_sequence(scrn, crtc, *target_msc); 1179 vbl.request.signal = seq; 1180 1181 ret = drmWaitVBlank(intel->drmSubFD, &vbl); 1182 if (ret) { 1183 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1184 "divisor 0 get vblank counter failed: %s\n", 1185 strerror(errno)); 1186 goto blit_fallback; 1187 } 1188 1189 *target_msc = intel_sequence_to_crtc_msc(crtc, vbl.reply.sequence + flip); 1190 swap_info->frame = *target_msc; 1191 1192 return TRUE; 1193 } 1194 1195 /* 1196 * If we get here, target_msc has already passed or we don't have one, 1197 * and we need to queue an event that will satisfy the divisor/remainder 1198 * equation. 1199 */ 1200 vbl.request.type = 1201 DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | pipe_select(pipe); 1202 if (flip == 0) 1203 vbl.request.type |= DRM_VBLANK_NEXTONMISS; 1204 1205 request_msc = current_msc - (current_msc % divisor) + 1206 remainder; 1207 1208 /* 1209 * If the calculated deadline vbl.request.sequence is smaller than 1210 * or equal to current_msc, it means we've passed the last point 1211 * when effective onset frame seq could satisfy 1212 * seq % divisor == remainder, so we need to wait for the next time 1213 * this will happen. 1214 1215 * This comparison takes the 1 frame swap delay in pageflipping mode 1216 * into account, as well as a potential DRM_VBLANK_NEXTONMISS delay 1217 * if we are blitting/exchanging instead of flipping. 1218 */ 1219 if (request_msc <= current_msc) 1220 request_msc += divisor; 1221 1222 seq = intel_drm_queue_alloc(scrn, crtc, swap_info, intel_dri2_vblank_handler, intel_dri2_vblank_abort); 1223 if (!seq) 1224 goto blit_fallback; 1225 1226 /* Account for 1 frame extra pageflip delay if flip > 0 */ 1227 vbl.request.sequence = intel_crtc_msc_to_sequence(scrn, crtc, request_msc) - flip; 1228 vbl.request.signal = seq; 1229 1230 ret = drmWaitVBlank(intel->drmSubFD, &vbl); 1231 if (ret) { 1232 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1233 "final get vblank counter failed: %s\n", 1234 strerror(errno)); 1235 goto blit_fallback; 1236 } 1237 1238 /* Adjust returned value for 1 fame pageflip offset of flip > 0 */ 1239 *target_msc = intel_sequence_to_crtc_msc(crtc, vbl.reply.sequence + flip); 1240 swap_info->frame = *target_msc; 1241 1242 return TRUE; 1243 1244blit_fallback: 1245 I830DRI2FallbackBlitSwap(draw, front, back); 1246 DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data); 1247 if (swap_info) 1248 i830_dri2_del_frame_event(swap_info); 1249 *target_msc = 0; /* offscreen, so zero out target vblank count */ 1250 return TRUE; 1251} 1252 1253static uint64_t gettime_us(void) 1254{ 1255 struct timespec tv; 1256 1257 if (clock_gettime(CLOCK_MONOTONIC, &tv)) 1258 return 0; 1259 1260 return (uint64_t)tv.tv_sec * 1000000 + tv.tv_nsec / 1000; 1261} 1262 1263/* 1264 * Get current frame count and frame count timestamp, based on drawable's 1265 * crtc. 1266 */ 1267static int 1268I830DRI2GetMSC(DrawablePtr draw, CARD64 *ust, CARD64 *msc) 1269{ 1270 ScreenPtr screen = draw->pScreen; 1271 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1272 int ret; 1273 xf86CrtcPtr crtc = I830DRI2DrawableCrtc(draw); 1274 1275 /* Drawable not displayed, make up a *monotonic* value */ 1276 if (crtc == NULL) { 1277fail: 1278 *ust = gettime_us(); 1279 *msc = 0; 1280 return TRUE; 1281 } 1282 1283 ret = intel_get_crtc_msc_ust(scrn, crtc, msc, ust); 1284 if (ret) { 1285 static int limit = 5; 1286 if (limit) { 1287 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1288 "%s:%d get vblank counter failed: %s\n", 1289 __FUNCTION__, __LINE__, 1290 strerror(errno)); 1291 limit--; 1292 } 1293 goto fail; 1294 } 1295 1296 return TRUE; 1297} 1298 1299/* 1300 * Request a DRM event when the requested conditions will be satisfied. 1301 * 1302 * We need to handle the event and ask the server to wake up the client when 1303 * we receive it. 1304 */ 1305static int 1306I830DRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr draw, CARD64 target_msc, 1307 CARD64 divisor, CARD64 remainder) 1308{ 1309 ScreenPtr screen = draw->pScreen; 1310 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1311 intel_screen_private *intel = intel_get_screen_private(scrn); 1312 DRI2FrameEventPtr wait_info; 1313 drmVBlank vbl; 1314 int ret; 1315 xf86CrtcPtr crtc = I830DRI2DrawableCrtc(draw); 1316 int pipe = crtc ? intel_crtc_to_pipe(crtc) : -1; 1317 CARD64 current_msc, current_ust, request_msc; 1318 uint32_t seq; 1319 1320 /* Drawable not visible, return immediately */ 1321 if (pipe == -1) 1322 goto out_complete; 1323 1324 wait_info = calloc(1, sizeof(DRI2FrameEventRec)); 1325 if (!wait_info) 1326 goto out_complete; 1327 1328 wait_info->intel = intel; 1329 wait_info->drawable_id = draw->id; 1330 wait_info->client = client; 1331 wait_info->type = DRI2_WAITMSC; 1332 1333 if (!i830_dri2_add_frame_event(wait_info)) { 1334 free(wait_info); 1335 wait_info = NULL; 1336 goto out_complete; 1337 } 1338 1339 /* Get current count */ 1340 ret = intel_get_crtc_msc_ust(scrn, crtc, ¤t_msc, ¤t_ust); 1341 if (ret) 1342 goto out_free; 1343 1344 /* 1345 * If divisor is zero, or current_msc is smaller than target_msc, 1346 * we just need to make sure target_msc passes before waking up the 1347 * client. 1348 */ 1349 if (divisor == 0 || current_msc < target_msc) { 1350 /* If target_msc already reached or passed, set it to 1351 * current_msc to ensure we return a reasonable value back 1352 * to the caller. This keeps the client from continually 1353 * sending us MSC targets from the past by forcibly updating 1354 * their count on this call. 1355 */ 1356 seq = intel_drm_queue_alloc(scrn, crtc, wait_info, intel_dri2_vblank_handler, intel_dri2_vblank_abort); 1357 if (!seq) 1358 goto out_free; 1359 1360 if (current_msc >= target_msc) 1361 target_msc = current_msc; 1362 vbl.request.type = 1363 DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | pipe_select(pipe); 1364 vbl.request.sequence = intel_crtc_msc_to_sequence(scrn, crtc, target_msc); 1365 vbl.request.signal = seq; 1366 1367 ret = drmWaitVBlank(intel->drmSubFD, &vbl); 1368 if (ret) { 1369 static int limit = 5; 1370 if (limit) { 1371 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1372 "%s:%d get vblank counter failed: %s\n", 1373 __FUNCTION__, __LINE__, 1374 strerror(errno)); 1375 limit--; 1376 } 1377 goto out_free; 1378 } 1379 1380 wait_info->frame = intel_sequence_to_crtc_msc(crtc, vbl.reply.sequence); 1381 DRI2BlockClient(client, draw); 1382 return TRUE; 1383 } 1384 1385 /* 1386 * If we get here, target_msc has already passed or we don't have one, 1387 * so we queue an event that will satisfy the divisor/remainder equation. 1388 */ 1389 vbl.request.type = 1390 DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | pipe_select(pipe); 1391 1392 request_msc = current_msc - (current_msc % divisor) + 1393 remainder; 1394 /* 1395 * If calculated remainder is larger than requested remainder, 1396 * it means we've passed the last point where 1397 * seq % divisor == remainder, so we need to wait for the next time 1398 * that will happen. 1399 */ 1400 if ((current_msc % divisor) >= remainder) 1401 request_msc += divisor; 1402 1403 seq = intel_drm_queue_alloc(scrn, crtc, wait_info, intel_dri2_vblank_handler, intel_dri2_vblank_abort); 1404 if (!seq) 1405 goto out_free; 1406 1407 vbl.request.sequence = intel_crtc_msc_to_sequence(scrn, crtc, request_msc); 1408 vbl.request.signal = seq; 1409 1410 ret = drmWaitVBlank(intel->drmSubFD, &vbl); 1411 if (ret) { 1412 static int limit = 5; 1413 if (limit) { 1414 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1415 "%s:%d get vblank counter failed: %s\n", 1416 __FUNCTION__, __LINE__, 1417 strerror(errno)); 1418 limit--; 1419 } 1420 goto out_free; 1421 } 1422 1423 wait_info->frame = intel_sequence_to_crtc_msc(crtc, vbl.reply.sequence); 1424 DRI2BlockClient(client, draw); 1425 1426 return TRUE; 1427 1428out_free: 1429 i830_dri2_del_frame_event(wait_info); 1430out_complete: 1431 DRI2WaitMSCComplete(client, draw, target_msc, 0, 0); 1432 return TRUE; 1433} 1434 1435static int dri2_server_generation; 1436#endif 1437 1438static int has_i830_dri(void) 1439{ 1440 return access(DRI_DRIVER_PATH "/i830_dri.so", R_OK) == 0; 1441} 1442 1443static const char *dri_driver_name(intel_screen_private *intel) 1444{ 1445#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0) 1446 const char *s = xf86GetOptValString(intel->Options, OPTION_DRI); 1447 Bool dummy; 1448 1449 if (s == NULL || xf86getBoolValue(&dummy, s)) { 1450 if (INTEL_INFO(intel)->gen < 030) 1451 return has_i830_dri() ? "i830" : "i915"; 1452 else if (INTEL_INFO(intel)->gen < 040) 1453 return "i915"; 1454 else 1455 return "i965"; 1456 } 1457 1458 return s; 1459#else 1460 if (INTEL_INFO(intel)->gen < 030) 1461 return has_i830_dri() ? "i830" : "i915"; 1462 else if (INTEL_INFO(intel)->gen < 040) 1463 return "i915"; 1464 else 1465 return "i965"; 1466#endif 1467} 1468 1469Bool I830DRI2ScreenInit(ScreenPtr screen) 1470{ 1471 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1472 intel_screen_private *intel = intel_get_screen_private(scrn); 1473 DRI2InfoRec info; 1474 int dri2scr_major = 1; 1475 int dri2scr_minor = 0; 1476#if DRI2INFOREC_VERSION >= 4 1477 const char *driverNames[2]; 1478#endif 1479 1480 if (intel->force_fallback) { 1481 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1482 "cannot enable DRI2 whilst forcing software fallbacks\n"); 1483 return FALSE; 1484 } 1485 1486 if (xf86LoaderCheckSymbol("DRI2Version")) 1487 DRI2Version(&dri2scr_major, &dri2scr_minor); 1488 1489 if (dri2scr_minor < 1) { 1490 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1491 "DRI2 requires DRI2 module version 1.1.0 or later\n"); 1492 return FALSE; 1493 } 1494 1495#if HAS_DIXREGISTERPRIVATEKEY 1496 if (!dixRegisterPrivateKey(&i830_client_key, PRIVATE_CLIENT, sizeof(XID))) 1497 return FALSE; 1498#else 1499 if (!dixRequestPrivate(&i830_client_key, sizeof(XID))) 1500 return FALSE; 1501#endif 1502 1503 1504#if DRI2INFOREC_VERSION >= 4 1505 if (serverGeneration != dri2_server_generation) { 1506 dri2_server_generation = serverGeneration; 1507 if (!i830_dri2_register_frame_event_resource_types()) { 1508 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1509 "Cannot register DRI2 frame event resources\n"); 1510 return FALSE; 1511 } 1512 } 1513#endif 1514 1515 intel->deviceName = drmGetDeviceNameFromFd(intel->drmSubFD); 1516 memset(&info, '\0', sizeof(info)); 1517 info.fd = intel->drmSubFD; 1518 info.driverName = dri_driver_name(intel); 1519 info.deviceName = intel->deviceName; 1520 1521#if DRI2INFOREC_VERSION == 1 1522 info.version = 1; 1523 info.CreateBuffers = I830DRI2CreateBuffers; 1524 info.DestroyBuffers = I830DRI2DestroyBuffers; 1525#elif DRI2INFOREC_VERSION == 2 1526 /* The ABI between 2 and 3 was broken so we could get rid of 1527 * the multi-buffer alloc functions. Make sure we indicate the 1528 * right version so DRI2 can reject us if it's version 3 or above. */ 1529 info.version = 2; 1530 info.CreateBuffer = I830DRI2CreateBuffer; 1531 info.DestroyBuffer = I830DRI2DestroyBuffer; 1532#else 1533 info.version = 3; 1534 info.CreateBuffer = I830DRI2CreateBuffer; 1535 info.DestroyBuffer = I830DRI2DestroyBuffer; 1536#endif 1537 1538 info.CopyRegion = I830DRI2CopyRegion; 1539#if DRI2INFOREC_VERSION >= 4 1540 info.version = 4; 1541 info.ScheduleSwap = I830DRI2ScheduleSwap; 1542 info.GetMSC = I830DRI2GetMSC; 1543 info.ScheduleWaitMSC = I830DRI2ScheduleWaitMSC; 1544 info.numDrivers = 2; 1545 info.driverNames = driverNames; 1546 driverNames[0] = info.driverName; 1547 driverNames[1] = info.driverName; 1548#endif 1549 1550 return DRI2ScreenInit(screen, &info); 1551} 1552 1553void I830DRI2CloseScreen(ScreenPtr screen) 1554{ 1555 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1556 intel_screen_private *intel = intel_get_screen_private(scrn); 1557 1558 DRI2CloseScreen(screen); 1559 drmFree(intel->deviceName); 1560} 1561