intel_driver.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 22THE COPYRIGHT HOLDERS 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 * Abraham van der Merwe <abraham@2d3d.co.za> 32 * David Dawes <dawes@xfree86.org> 33 * Alan Hourihane <alanh@tungstengraphics.com> 34 */ 35 36#ifdef HAVE_CONFIG_H 37#include "config.h" 38#endif 39 40#include <assert.h> 41#include <string.h> 42#include <stdio.h> 43#include <unistd.h> 44#include <stdlib.h> 45#include <stdio.h> 46#include <errno.h> 47 48#include "xorg-server.h" 49#include "xf86.h" 50#include "xf86_OSproc.h" 51#include "xf86cmap.h" 52#include "xf86drm.h" 53#include "compiler.h" 54#include "mipointer.h" 55#include "micmap.h" 56#include <X11/extensions/randr.h> 57#include "fb.h" 58#include "miscstruct.h" 59#include "dixstruct.h" 60#include "xf86xv.h" 61#include "shadow.h" 62#include "intel.h" 63#include "intel_video.h" 64#include "uxa_module.h" 65 66#ifdef INTEL_XVMC 67#define _INTEL_XVMC_SERVER_ 68#include "intel_xvmc.h" 69#endif 70 71#if USE_UXA 72#include "intel_uxa.h" 73#endif 74 75#include "intel_options.h" 76#include "i915_drm.h" 77 78static void i830AdjustFrame(ADJUST_FRAME_ARGS_DECL); 79static Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL); 80static Bool I830EnterVT(VT_FUNC_ARGS_DECL); 81 82/* temporary */ 83extern void xf86SetCursor(ScreenPtr screen, CursorPtr pCurs, int x, int y); 84 85/* Export I830 options to i830 driver where necessary */ 86static void 87I830LoadPalette(ScrnInfoPtr scrn, int numColors, int *indices, 88 LOCO * colors, VisualPtr pVisual) 89{ 90 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 91 int i, j, index; 92 int p; 93 uint16_t lut_r[256], lut_g[256], lut_b[256]; 94 95 for (p = 0; p < xf86_config->num_crtc; p++) { 96 xf86CrtcPtr crtc = xf86_config->crtc[p]; 97 98 switch (scrn->depth) { 99 case 15: 100 for (i = 0; i < numColors; i++) { 101 index = indices[i]; 102 for (j = 0; j < 8; j++) { 103 lut_r[index * 8 + j] = 104 colors[index].red << 8; 105 lut_g[index * 8 + j] = 106 colors[index].green << 8; 107 lut_b[index * 8 + j] = 108 colors[index].blue << 8; 109 } 110 } 111 break; 112 case 16: 113 for (i = 0; i < numColors; i++) { 114 index = indices[i]; 115 116 if (index <= 31) { 117 for (j = 0; j < 8; j++) { 118 lut_r[index * 8 + j] = 119 colors[index].red << 8; 120 lut_b[index * 8 + j] = 121 colors[index].blue << 8; 122 } 123 } 124 125 for (j = 0; j < 4; j++) { 126 lut_g[index * 4 + j] = 127 colors[index].green << 8; 128 } 129 } 130 break; 131 default: 132 for (i = 0; i < numColors; i++) { 133 index = indices[i]; 134 lut_r[index] = colors[index].red << 8; 135 lut_g[index] = colors[index].green << 8; 136 lut_b[index] = colors[index].blue << 8; 137 } 138 break; 139 } 140 141 /* Make the change through RandR */ 142#ifdef RANDR_12_INTERFACE 143 RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); 144#else 145 crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); 146#endif 147 } 148} 149 150/** 151 * Adjust the screen pixmap for the current location of the front buffer. 152 * This is done at EnterVT when buffers are bound as long as the resources 153 * have already been created, but the first EnterVT happens before 154 * CreateScreenResources. 155 */ 156static Bool i830CreateScreenResources(ScreenPtr screen) 157{ 158 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 159 intel_screen_private *intel = intel_get_screen_private(scrn); 160 161 screen->CreateScreenResources = intel->CreateScreenResources; 162 if (!(*screen->CreateScreenResources) (screen)) 163 return FALSE; 164 165 if (!intel_uxa_create_screen_resources(screen)) 166 return FALSE; 167 168 intel_copy_fb(scrn); 169 return TRUE; 170} 171 172void 173intel_set_pixmap_bo(PixmapPtr pixmap, dri_bo *bo) 174{ 175 intel_uxa_set_pixmap_bo(pixmap, bo); 176} 177 178dri_bo * 179intel_get_pixmap_bo(PixmapPtr pixmap) 180{ 181 return intel_uxa_get_pixmap_bo(pixmap); 182} 183 184void 185intel_flush(intel_screen_private *intel) 186{ 187 intel_batch_submit(intel->scrn); 188} 189 190static void PreInitCleanup(ScrnInfoPtr scrn) 191{ 192 if (!scrn || !scrn->driverPrivate) 193 return; 194 195 free(scrn->driverPrivate); 196 scrn->driverPrivate = NULL; 197} 198 199static void intel_check_chipset_option(ScrnInfoPtr scrn) 200{ 201 intel_screen_private *intel = intel_get_screen_private(scrn); 202 intel_detect_chipset(scrn, intel->dev); 203} 204 205static Bool I830GetEarlyOptions(ScrnInfoPtr scrn) 206{ 207 intel_screen_private *intel = intel_get_screen_private(scrn); 208 209 /* Process the options */ 210 intel->Options = intel_options_get(scrn); 211 if (!intel->Options) 212 return FALSE; 213 214#if USE_UXA 215 intel->fallback_debug = xf86ReturnOptValBool(intel->Options, 216 OPTION_FALLBACKDEBUG, 217 FALSE); 218 219 intel->debug_flush = 0; 220 221 if (xf86ReturnOptValBool(intel->Options, 222 OPTION_DEBUG_FLUSH_BATCHES, 223 FALSE)) 224 intel->debug_flush |= DEBUG_FLUSH_BATCHES; 225 226 if (xf86ReturnOptValBool(intel->Options, 227 OPTION_DEBUG_FLUSH_CACHES, 228 FALSE)) 229 intel->debug_flush |= DEBUG_FLUSH_CACHES; 230 231 if (xf86ReturnOptValBool(intel->Options, 232 OPTION_DEBUG_WAIT, 233 FALSE)) 234 intel->debug_flush |= DEBUG_FLUSH_WAIT; 235 236#endif 237 return TRUE; 238} 239 240static Bool intel_option_cast_string_to_bool(intel_screen_private *intel, 241 int id, Bool val) 242{ 243#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0) 244 xf86getBoolValue(&val, xf86GetOptValString(intel->Options, id)); 245 return val; 246#else 247 return val; 248#endif 249} 250 251static void intel_check_dri_option(ScrnInfoPtr scrn) 252{ 253 intel_screen_private *intel = intel_get_screen_private(scrn); 254 255 intel->dri2 = intel->dri3 = DRI_NONE; 256 if (!intel_option_cast_string_to_bool(intel, OPTION_DRI, TRUE)) 257 intel->dri2 = intel->dri3 = DRI_DISABLED; 258 259 if (scrn->depth != 16 && scrn->depth != 24 && scrn->depth != 30) { 260 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, 261 "DRI is disabled because it " 262 "runs only at depths 16, 24, and 30.\n"); 263 intel->dri2 = intel->dri3 = DRI_DISABLED; 264 } 265} 266 267static Bool intel_open_drm_master(ScrnInfoPtr scrn) 268{ 269 intel_screen_private *intel = intel_get_screen_private(scrn); 270 intel->dev = intel_get_device(scrn, &intel->drmSubFD); 271 return intel->dev != NULL; 272} 273 274static int intel_init_bufmgr(intel_screen_private *intel) 275{ 276 int batch_size; 277 278 batch_size = 4096 * 4; 279 if (IS_I865G(intel)) 280 /* The 865 has issues with larger-than-page-sized batch buffers. */ 281 batch_size = 4096; 282 283 intel->bufmgr = drm_intel_bufmgr_gem_init(intel->drmSubFD, batch_size); 284 if (!intel->bufmgr) 285 return FALSE; 286 287 if (xf86ReturnOptValBool(intel->Options, OPTION_BUFFER_CACHE, TRUE)) 288 drm_intel_bufmgr_gem_enable_reuse(intel->bufmgr); 289 drm_intel_bufmgr_gem_set_vma_cache_size(intel->bufmgr, 512); 290 drm_intel_bufmgr_gem_enable_fenced_relocs(intel->bufmgr); 291 292 list_init(&intel->batch_pixmaps); 293 294 if ((INTEL_INFO(intel)->gen == 060)) { 295 intel->wa_scratch_bo = 296 drm_intel_bo_alloc(intel->bufmgr, "wa scratch", 297 4096, 4096); 298 } 299 300 return TRUE; 301} 302 303static void intel_bufmgr_fini(intel_screen_private *intel) 304{ 305 if (intel->bufmgr == NULL) 306 return; 307 308 drm_intel_bo_unreference(intel->wa_scratch_bo); 309 drm_intel_bufmgr_destroy(intel->bufmgr); 310} 311 312static void I830XvInit(ScrnInfoPtr scrn) 313{ 314 intel_screen_private *intel = intel_get_screen_private(scrn); 315 MessageType from = X_PROBED; 316 317 intel->XvPreferOverlay = 318 xf86ReturnOptValBool(intel->Options, OPTION_PREFER_OVERLAY, FALSE); 319 320 if (xf86GetOptValInteger(intel->Options, OPTION_VIDEO_KEY, 321 &(intel->colorKey))) { 322 from = X_CONFIG; 323 } else if (xf86GetOptValInteger(intel->Options, OPTION_COLOR_KEY, 324 &(intel->colorKey))) { 325 from = X_CONFIG; 326 } else { 327 intel->colorKey = 328 (1 << scrn->offset.red) | (1 << scrn->offset.green) | 329 (((scrn->mask.blue >> scrn->offset.blue) - 1) << 330 scrn->offset.blue); 331 from = X_DEFAULT; 332 } 333 xf86DrvMsg(scrn->scrnIndex, from, "video overlay key set to 0x%x\n", 334 intel->colorKey); 335} 336 337static Bool drm_has_boolean_param(struct intel_screen_private *intel, 338 int param) 339{ 340 drm_i915_getparam_t gp; 341 int value; 342 343 gp.value = &value; 344 gp.param = param; 345 if (drmIoctl(intel->drmSubFD, DRM_IOCTL_I915_GETPARAM, &gp)) 346 return FALSE; 347 348 return value; 349} 350 351static Bool has_kernel_flush(struct intel_screen_private *intel) 352{ 353 /* The BLT ring was introduced at the same time as the 354 * automatic flush for the busy-ioctl. 355 */ 356 return drm_has_boolean_param(intel, I915_PARAM_HAS_BLT); 357} 358 359static Bool has_relaxed_fencing(struct intel_screen_private *intel) 360{ 361 return drm_has_boolean_param(intel, I915_PARAM_HAS_RELAXED_FENCING); 362} 363 364static Bool has_prime_vmap_flush(struct intel_screen_private *intel) 365{ 366 return drm_has_boolean_param(intel, I915_PARAM_HAS_PRIME_VMAP_FLUSH); 367} 368 369static Bool can_accelerate_blt(struct intel_screen_private *intel) 370{ 371 if (INTEL_INFO(intel)->gen == -1) 372 return FALSE; 373 374 if (xf86ReturnOptValBool(intel->Options, OPTION_ACCEL_DISABLE, FALSE) || 375 !intel_option_cast_string_to_bool(intel, OPTION_ACCEL_METHOD, TRUE)) { 376 xf86DrvMsg(intel->scrn->scrnIndex, X_CONFIG, 377 "Disabling hardware acceleration.\n"); 378 return FALSE; 379 } 380 381 if (INTEL_INFO(intel)->gen == 060) { 382 struct pci_device *const device = xf86GetPciInfoForEntity(intel->pEnt->index); 383 384 /* Sandybridge rev07 locks up easily, even with the 385 * BLT ring workaround in place. 386 * Thus use shadowfb by default. 387 */ 388 if (device->revision < 8) { 389 xf86DrvMsg(intel->scrn->scrnIndex, X_WARNING, 390 "Disabling hardware acceleration on this pre-production hardware.\n"); 391 392 return FALSE; 393 } 394 } 395 396 if (INTEL_INFO(intel)->gen >= 060) { 397 drm_i915_getparam_t gp; 398 int value; 399 400 /* On Sandybridge we need the BLT in order to do anything since 401 * it so frequently used in the acceleration code paths. 402 */ 403 gp.value = &value; 404 gp.param = I915_PARAM_HAS_BLT; 405 if (drmIoctl(intel->drmSubFD, DRM_IOCTL_I915_GETPARAM, &gp)) 406 return FALSE; 407 } 408 409 return TRUE; 410} 411 412static void intel_setup_capabilities(ScrnInfoPtr scrn) 413{ 414#ifdef INTEL_PIXMAP_SHARING 415 intel_screen_private *intel = intel_get_screen_private(scrn); 416 uint64_t value; 417 int ret; 418 419 scrn->capabilities = 0; 420 421 ret = drmGetCap(intel->drmSubFD, DRM_CAP_PRIME, &value); 422 if (ret == 0) { 423 if (value & DRM_PRIME_CAP_EXPORT) 424 scrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SinkOffload; 425 if (value & DRM_PRIME_CAP_IMPORT) 426 scrn->capabilities |= RR_Capability_SinkOutput; 427 } 428#endif 429} 430 431/** 432 * This is called before ScreenInit to do any require probing of screen 433 * configuration. 434 * 435 * This code generally covers probing, module loading, option handling 436 * card mapping, and RandR setup. 437 * 438 * Since xf86InitialConfiguration ends up requiring that we set video modes 439 * in order to detect configuration, we end up having to do a lot of driver 440 * setup (talking to the DRM, mapping the device, etc.) in this function. 441 * As a result, we want to set up that server initialization once rather 442 * that doing it per generation. 443 */ 444static Bool I830PreInit(ScrnInfoPtr scrn, int flags) 445{ 446 intel_screen_private *intel; 447 rgb defaultWeight = { 0, 0, 0 }; 448 EntityInfoPtr pEnt; 449 int flags24; 450 Gamma zeros = { 0.0, 0.0, 0.0 }; 451 452 if (scrn->numEntities != 1) 453 return FALSE; 454 455 pEnt = xf86GetEntityInfo(scrn->entityList[0]); 456 if (pEnt == NULL) 457 return FALSE; 458 459 if (pEnt->location.type != BUS_PCI 460#ifdef XSERVER_PLATFORM_BUS 461 && pEnt->location.type != BUS_PLATFORM 462#endif 463 ) 464 return FALSE; 465 466 if (flags & PROBE_DETECT) 467 return TRUE; 468 469 if (((uintptr_t)scrn->driverPrivate) & 3) { 470 intel = xnfcalloc(sizeof(*intel), 1); 471 if (intel == NULL) 472 return FALSE; 473 474 intel->info = (void *)((uintptr_t)scrn->driverPrivate & ~3); 475 scrn->driverPrivate = intel; 476 } 477 intel = intel_get_screen_private(scrn); 478 intel->scrn = scrn; 479 intel->pEnt = pEnt; 480 481 scrn->displayWidth = 640; /* default it */ 482 483 if (!intel_open_drm_master(scrn)) { 484 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 485 "Failed to become DRM master.\n"); 486 return FALSE; 487 } 488 489 scrn->monitor = scrn->confScreen->monitor; 490 scrn->progClock = TRUE; 491 scrn->rgbBits = 8; 492 493 flags24 = Support32bppFb | PreferConvert24to32 | SupportConvert24to32; 494 495 if (!xf86SetDepthBpp(scrn, 0, 0, 0, flags24)) 496 return FALSE; 497 498 switch (scrn->depth) { 499 case 15: 500 case 16: 501 case 24: 502 case 30: 503 break; 504 case 8: 505 default: 506 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 507 "Given depth (%d) is not supported by intel driver\n", 508 scrn->depth); 509 return FALSE; 510 } 511 xf86PrintDepthBpp(scrn); 512 513 if (!xf86SetWeight(scrn, defaultWeight, defaultWeight)) 514 return FALSE; 515 if (!xf86SetDefaultVisual(scrn, -1)) 516 return FALSE; 517 518 intel->cpp = scrn->bitsPerPixel / 8; 519 520 if (!I830GetEarlyOptions(scrn)) 521 return FALSE; 522 523 intel_setup_capabilities(scrn); 524 intel_check_chipset_option(scrn); 525 intel_check_dri_option(scrn); 526 527 if (!intel_init_bufmgr(intel)) { 528 PreInitCleanup(scrn); 529 return FALSE; 530 } 531 532 intel->force_fallback = 533 drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE) != 0; 534 535 /* Enable tiling by default */ 536 intel->tiling = INTEL_TILING_ALL; 537 538 /* Allow user override if they set a value */ 539 if (!xf86ReturnOptValBool(intel->Options, OPTION_TILING_2D, TRUE)) 540 intel->tiling &= ~INTEL_TILING_2D; 541 if (xf86ReturnOptValBool(intel->Options, OPTION_TILING_FB, FALSE)) 542 intel->tiling &= ~INTEL_TILING_FB; 543 if (!can_accelerate_blt(intel)) { 544 intel->force_fallback = TRUE; 545 intel->tiling &= ~INTEL_TILING_FB; 546 } 547 548 intel->has_kernel_flush = has_kernel_flush(intel); 549 550 intel->has_prime_vmap_flush = has_prime_vmap_flush(intel); 551 552 intel->has_relaxed_fencing = INTEL_INFO(intel)->gen >= 033; 553 /* And override the user if there is no kernel support */ 554 if (intel->has_relaxed_fencing) 555 intel->has_relaxed_fencing = has_relaxed_fencing(intel); 556 557 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, 558 "Relaxed fencing %s\n", 559 intel->has_relaxed_fencing ? "enabled" : "disabled"); 560 561 /* SwapBuffers delays to avoid tearing */ 562 intel->swapbuffers_wait = xf86ReturnOptValBool(intel->Options, 563 OPTION_SWAPBUFFERS_WAIT, 564 TRUE); 565 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Wait on SwapBuffers? %s\n", 566 intel->swapbuffers_wait ? "enabled" : "disabled"); 567 568 intel->use_triple_buffer = 569 xf86ReturnOptValBool(intel->Options, 570 OPTION_TRIPLE_BUFFER, 571 TRUE); 572 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Triple buffering? %s\n", 573 intel->use_triple_buffer ? "enabled" : "disabled"); 574 575 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Framebuffer %s\n", 576 intel->tiling & INTEL_TILING_FB ? "tiled" : "linear"); 577 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "Pixmaps %s\n", 578 intel->tiling & INTEL_TILING_2D ? "tiled" : "linear"); 579 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "3D buffers %s\n", 580 intel->tiling & INTEL_TILING_3D ? "tiled" : "linear"); 581 xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "SwapBuffers wait %sabled\n", 582 intel->swapbuffers_wait ? "en" : "dis"); 583 584 I830XvInit(scrn); 585 586 if (!intel_mode_pre_init(scrn, intel->drmSubFD, intel->cpp)) { 587 PreInitCleanup(scrn); 588 return FALSE; 589 } 590 591 if (!xf86SetGamma(scrn, zeros)) { 592 PreInitCleanup(scrn); 593 return FALSE; 594 } 595 596 if (scrn->modes == NULL) { 597 xf86DrvMsg(scrn->scrnIndex, X_ERROR, "No modes.\n"); 598 PreInitCleanup(scrn); 599 return FALSE; 600 } 601 scrn->currentMode = scrn->modes; 602 603 /* Set display resolution */ 604 xf86SetDpi(scrn, 0, 0); 605 606 /* Load the required sub modules */ 607 if (!xf86LoadSubModule(scrn, "fb")) { 608 PreInitCleanup(scrn); 609 return FALSE; 610 } 611 612 /* Load the dri modules if requested. */ 613#if HAVE_DRI2 614 if (intel->dri2 != DRI_DISABLED && !xf86LoadSubModule(scrn, "dri2")) 615 intel->dri2 = DRI_DISABLED; 616#endif 617#if HAVE_DRI3 618 if (intel->dri3 != DRI_DISABLED && !xf86LoadSubModule(scrn, "dri3")) 619 intel->dri3 = DRI_DISABLED; 620#endif 621 622 return TRUE; 623} 624 625#ifdef INTEL_PIXMAP_SHARING 626static void 627redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty) 628{ 629 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 630 intel_screen_private *intel = intel_get_screen_private(scrn); 631 RegionRec pixregion; 632 int was_blocked; 633 634 PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap); 635 RegionTranslate(&pixregion, dirty->x, dirty->y); 636 RegionIntersect(&pixregion, &pixregion, DamageRegion(dirty->damage)); 637 RegionTranslate(&pixregion, -dirty->x, -dirty->y); 638 was_blocked = RegionNil(&pixregion); 639 DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion); 640 RegionUninit(&pixregion); 641 if (was_blocked) 642 return; 643 644 PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap); 645 PixmapSyncDirtyHelper(dirty, &pixregion); 646 RegionUninit(&pixregion); 647 648 intel_flush(intel); 649 if (!intel->has_prime_vmap_flush) { 650 drm_intel_bo *bo = intel_uxa_get_pixmap_bo(dirty->slave_dst->master_pixmap); 651 was_blocked = xf86BlockSIGIO(); 652 drm_intel_bo_map(bo, FALSE); 653 drm_intel_bo_unmap(bo); 654 xf86UnblockSIGIO(was_blocked); 655 } 656 657 DamageRegionProcessPending(&dirty->slave_dst->drawable); 658 return; 659} 660 661static void 662intel_dirty_update(ScreenPtr screen) 663{ 664 RegionPtr region; 665 PixmapDirtyUpdatePtr ent; 666 667 if (xorg_list_is_empty(&screen->pixmap_dirty_list)) 668 return; 669 670 xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) { 671 region = DamageRegion(ent->damage); 672 if (RegionNotEmpty(region)) { 673 redisplay_dirty(screen, ent); 674 DamageEmpty(ent->damage); 675 } 676 } 677} 678#endif 679 680static void 681I830BlockHandler(BLOCKHANDLER_ARGS_DECL) 682{ 683 SCREEN_PTR(arg); 684 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 685 intel_screen_private *intel = intel_get_screen_private(scrn); 686 687 screen->BlockHandler = intel->BlockHandler; 688 689 (*screen->BlockHandler) (BLOCKHANDLER_ARGS); 690 691 intel->BlockHandler = screen->BlockHandler; 692 screen->BlockHandler = I830BlockHandler; 693 694 intel_uxa_block_handler(intel); 695 intel_video_block_handler(intel); 696#ifdef INTEL_PIXMAP_SHARING 697 intel_dirty_update(screen); 698#endif 699} 700 701static Bool 702intel_init_initial_framebuffer(ScrnInfoPtr scrn) 703{ 704 intel_screen_private *intel = intel_get_screen_private(scrn); 705 int width = scrn->virtualX; 706 int height = scrn->virtualY; 707 int pitch; 708 uint32_t tiling; 709 710 intel->front_buffer = intel_allocate_framebuffer(scrn, 711 width, height, 712 intel->cpp, 713 &pitch, &tiling); 714 715 if (!intel->front_buffer) { 716 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 717 "Couldn't allocate initial framebuffer.\n"); 718 return FALSE; 719 } 720 721 intel->front_pitch = pitch; 722 intel->front_tiling = tiling; 723 scrn->displayWidth = pitch / intel->cpp; 724 725 return TRUE; 726} 727 728static void 729intel_flush_callback(CallbackListPtr *list, 730 pointer user_data, pointer call_data) 731{ 732 ScrnInfoPtr scrn = user_data; 733 if (scrn->vtSema) 734 intel_flush(intel_get_screen_private(scrn)); 735} 736 737#if HAVE_UDEV 738static void 739I830HandleUEvents(int fd, void *closure) 740{ 741 ScrnInfoPtr scrn = closure; 742 intel_screen_private *intel = intel_get_screen_private(scrn); 743 struct udev_device *dev; 744 const char *hotplug; 745 struct stat s; 746 dev_t udev_devnum; 747 748 dev = udev_monitor_receive_device(intel->uevent_monitor); 749 if (!dev) 750 return; 751 752 udev_devnum = udev_device_get_devnum(dev); 753 if (fstat(intel->drmSubFD, &s)) { 754 udev_device_unref(dev); 755 return; 756 } 757 /* 758 * Check to make sure this event is directed at our 759 * device (by comparing dev_t values), then make 760 * sure it's a hotplug event (HOTPLUG=1) 761 */ 762 763 hotplug = udev_device_get_property_value(dev, "HOTPLUG"); 764 765 if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 && 766 hotplug && atoi(hotplug) == 1) 767 { 768 intel_mode_hotplug(intel); 769 } 770 771 udev_device_unref(dev); 772} 773 774static void 775I830UeventInit(ScrnInfoPtr scrn) 776{ 777 intel_screen_private *intel = intel_get_screen_private(scrn); 778 struct udev *u; 779 struct udev_monitor *mon; 780 Bool hotplug; 781 MessageType from = X_CONFIG; 782 783 if (!xf86GetOptValBool(intel->Options, OPTION_HOTPLUG, &hotplug)) { 784 from = X_DEFAULT; 785 hotplug = TRUE; 786 } 787 788 xf86DrvMsg(scrn->scrnIndex, from, "hotplug detection: \"%s\"\n", 789 hotplug ? "enabled" : "disabled"); 790 if (!hotplug) 791 return; 792 793 u = udev_new(); 794 if (!u) 795 return; 796 797 mon = udev_monitor_new_from_netlink(u, "udev"); 798 799 if (!mon) { 800 udev_unref(u); 801 return; 802 } 803 804 if (udev_monitor_filter_add_match_subsystem_devtype(mon, 805 "drm", 806 "drm_minor") < 0 || 807 udev_monitor_enable_receiving(mon) < 0) 808 { 809 udev_monitor_unref(mon); 810 udev_unref(u); 811 return; 812 } 813 814 intel->uevent_handler = xf86AddGeneralHandler(udev_monitor_get_fd(mon), 815 I830HandleUEvents, scrn); 816 if (!intel->uevent_handler) { 817 udev_monitor_unref(mon); 818 udev_unref(u); 819 return; 820 } 821 822 intel->uevent_monitor = mon; 823} 824 825static void 826I830UeventFini(ScrnInfoPtr scrn) 827{ 828 intel_screen_private *intel = intel_get_screen_private(scrn); 829 830 if (intel->uevent_handler) { 831 struct udev *u = udev_monitor_get_udev(intel->uevent_monitor); 832 833 xf86RemoveGeneralHandler(intel->uevent_handler); 834 835 udev_monitor_unref(intel->uevent_monitor); 836 udev_unref(u); 837 intel->uevent_handler = NULL; 838 intel->uevent_monitor = NULL; 839 } 840} 841#endif /* HAVE_UDEV */ 842 843static Bool 844I830ScreenInit(SCREEN_INIT_ARGS_DECL) 845{ 846 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 847 intel_screen_private *intel = intel_get_screen_private(scrn); 848 VisualPtr visual; 849#ifdef INTEL_XVMC 850 MessageType from; 851#endif 852 struct pci_device *const device = xf86GetPciInfoForEntity(intel->pEnt->index); 853 int fb_bar = IS_GEN2(intel) ? 0 : 2; 854 855 scrn->videoRam = device->regions[fb_bar].size / 1024; 856 857 intel->last_3d = LAST_3D_OTHER; 858 intel->overlayOn = FALSE; 859 860 /* 861 * Set this so that the overlay allocation is factored in when 862 * appropriate. 863 */ 864 intel->XvEnabled = TRUE; 865 866 if (!intel_init_initial_framebuffer(scrn)) 867 return FALSE; 868 869 miClearVisualTypes(); 870 if (!miSetVisualTypes(scrn->depth, 871 miGetDefaultVisualMask(scrn->depth), 872 scrn->rgbBits, scrn->defaultVisual)) 873 return FALSE; 874 if (!miSetPixmapDepths()) 875 return FALSE; 876 877 /* Must be first, before anything else installs screen callbacks. */ 878 if (!fbScreenInit(screen, NULL, 879 scrn->virtualX, scrn->virtualY, 880 scrn->xDpi, scrn->yDpi, 881 scrn->displayWidth, scrn->bitsPerPixel)) 882 return FALSE; 883 884 if (scrn->bitsPerPixel > 8) { 885 /* Fixup RGB ordering */ 886 visual = screen->visuals + screen->numVisuals; 887 while (--visual >= screen->visuals) { 888 if ((visual->class | DynamicClass) == DirectColor) { 889 visual->offsetRed = scrn->offset.red; 890 visual->offsetGreen = scrn->offset.green; 891 visual->offsetBlue = scrn->offset.blue; 892 visual->redMask = scrn->mask.red; 893 visual->greenMask = scrn->mask.green; 894 visual->blueMask = scrn->mask.blue; 895 } 896 } 897 } 898 899 fbPictureInit(screen, NULL, 0); 900 901 xf86SetBlackWhitePixels(screen); 902 903 if (!intel_uxa_init(screen)) { 904 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 905 "Hardware acceleration initialization failed\n"); 906 return FALSE; 907 } 908 909#if HAVE_DRI2 910 if (intel->dri2 == DRI_NONE && I830DRI2ScreenInit(screen)) 911 intel->dri2 = DRI_ACTIVE; 912#endif 913 914#if HAVE_DRI3 915 if (!intel_sync_init(screen)) 916 intel->dri3 = DRI_DISABLED; 917 if (intel->dri3 == DRI_NONE && intel_dri3_screen_init(screen)) 918 intel->dri3 = DRI_ACTIVE; 919#endif 920 921 if (xf86ReturnOptValBool(intel->Options, OPTION_PRESENT, TRUE)) 922 intel_present_screen_init(screen); 923 924 xf86SetBackingStore(screen); 925 xf86SetSilkenMouse(screen); 926 miDCInitialize(screen, xf86GetPointerScreenFuncs()); 927 928 xf86DrvMsg(scrn->scrnIndex, X_INFO, "Initializing HW Cursor\n"); 929 if (!xf86_cursors_init(screen, 64, 64, 930 (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 931 HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | 932 HARDWARE_CURSOR_INVERT_MASK | 933 HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | 934 HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | 935 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | 936 HARDWARE_CURSOR_UPDATE_UNHIDDEN | 937 HARDWARE_CURSOR_ARGB))) { 938 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 939 "Hardware cursor initialization failed\n"); 940 } 941 942 intel->BlockHandler = screen->BlockHandler; 943 screen->BlockHandler = I830BlockHandler; 944 945#ifdef INTEL_PIXMAP_SHARING 946 screen->StartPixmapTracking = PixmapStartDirtyTracking; 947 screen->StopPixmapTracking = PixmapStopDirtyTracking; 948#endif 949 950 if (!AddCallback(&FlushCallback, intel_flush_callback, scrn)) 951 return FALSE; 952 953 screen->SaveScreen = xf86SaveScreen; 954 intel->CloseScreen = screen->CloseScreen; 955 screen->CloseScreen = I830CloseScreen; 956 intel->CreateScreenResources = screen->CreateScreenResources; 957 screen->CreateScreenResources = i830CreateScreenResources; 958 959 if (!xf86CrtcScreenInit(screen)) 960 return FALSE; 961 962 if (!miCreateDefColormap(screen)) 963 return FALSE; 964 965 if (!xf86HandleColormaps(screen, 256, 8, I830LoadPalette, NULL, 966 CMAP_RELOAD_ON_MODE_SWITCH | 967 CMAP_PALETTED_TRUECOLOR)) { 968 return FALSE; 969 } 970 971 xf86DPMSInit(screen, xf86DPMSSet, 0); 972 973#ifdef INTEL_XVMC 974 if (INTEL_INFO(intel)->gen >= 040) 975 intel->XvMCEnabled = TRUE; 976 from = (intel->dri2 == DRI_ACTIVE && 977 xf86GetOptValBool(intel->Options, OPTION_XVMC, 978 &intel->XvMCEnabled) ? X_CONFIG : X_DEFAULT); 979 xf86DrvMsg(scrn->scrnIndex, from, "Intel XvMC decoder %sabled\n", 980 intel->XvMCEnabled ? "en" : "dis"); 981#endif 982 /* Init video */ 983 if (intel->XvEnabled) 984 intel_video_init(screen); 985 986#if HAVE_DRI2 987 switch (intel->dri2) { 988 case DRI_ACTIVE: 989 xf86DrvMsg(scrn->scrnIndex, X_INFO, 990 "DRI2: Enabled\n"); 991 break; 992 case DRI_DISABLED: 993 xf86DrvMsg(scrn->scrnIndex, X_INFO, 994 "DRI2: Disabled\n"); 995 break; 996 case DRI_NONE: 997 xf86DrvMsg(scrn->scrnIndex, X_INFO, 998 "DRI2: Failed\n"); 999 break; 1000 } 1001#else 1002 xf86DrvMsg(scrn->scrnIndex, X_INFO, 1003 "DRI2: Not available\n"); 1004#endif 1005 1006#if HAVE_DRI3 1007 switch (intel->dri3) { 1008 case DRI_ACTIVE: 1009 xf86DrvMsg(scrn->scrnIndex, X_INFO, 1010 "DRI3: Enabled\n"); 1011 break; 1012 case DRI_DISABLED: 1013 xf86DrvMsg(scrn->scrnIndex, X_INFO, 1014 "DRI3: Disabled\n"); 1015 break; 1016 case DRI_NONE: 1017 xf86DrvMsg(scrn->scrnIndex, X_INFO, 1018 "DRI3: Failed\n"); 1019 break; 1020 } 1021#else 1022 xf86DrvMsg(scrn->scrnIndex, X_INFO, 1023 "DRI3: Not available\n"); 1024#endif 1025 1026 if (serverGeneration == 1) 1027 xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options); 1028 1029 intel_mode_init(intel); 1030 1031 intel->suspended = FALSE; 1032 1033#if HAVE_UDEV 1034 I830UeventInit(scrn); 1035#endif 1036 1037 /* Must force it before EnterVT, so we are in control of VT and 1038 * later memory should be bound when allocating, e.g rotate_mem */ 1039 scrn->vtSema = TRUE; 1040 1041 return I830EnterVT(VT_FUNC_ARGS(0)); 1042} 1043 1044static void i830AdjustFrame(ADJUST_FRAME_ARGS_DECL) 1045{ 1046} 1047 1048static void I830FreeScreen(FREE_SCREEN_ARGS_DECL) 1049{ 1050 SCRN_INFO_PTR(arg); 1051 intel_screen_private *intel = intel_get_screen_private(scrn); 1052 1053 if (intel && !((uintptr_t)intel & 3)) { 1054 intel_mode_fini(intel); 1055 intel_bufmgr_fini(intel); 1056 intel_put_device(intel->dev); 1057 1058 free(intel); 1059 scrn->driverPrivate = NULL; 1060 } 1061} 1062 1063static void I830LeaveVT(VT_FUNC_ARGS_DECL) 1064{ 1065 SCRN_INFO_PTR(arg); 1066 intel_screen_private *intel = intel_get_screen_private(scrn); 1067 1068 xf86RotateFreeShadow(scrn); 1069 1070 xf86_hide_cursors(scrn); 1071 1072 if (intel_put_master(intel->dev)) 1073 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1074 "drmDropMaster failed: %s\n", strerror(errno)); 1075} 1076 1077/* 1078 * This gets called when gaining control of the VT, and from ScreenInit(). 1079 */ 1080static Bool I830EnterVT(VT_FUNC_ARGS_DECL) 1081{ 1082 SCRN_INFO_PTR(arg); 1083 intel_screen_private *intel = intel_get_screen_private(scrn); 1084 1085 if (intel_get_master(intel->dev)) { 1086 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 1087 "drmSetMaster failed: %s\n", 1088 strerror(errno)); 1089 return FALSE; 1090 } 1091 1092 if (!xf86SetDesiredModes(scrn)) 1093 return FALSE; 1094 1095 intel_mode_disable_unused_functions(scrn); 1096 return TRUE; 1097} 1098 1099static Bool I830SwitchMode(SWITCH_MODE_ARGS_DECL) 1100{ 1101 SCRN_INFO_PTR(arg); 1102 1103 return xf86SetSingleMode(scrn, mode, RR_Rotate_0); 1104} 1105 1106static Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL) 1107{ 1108 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1109 intel_screen_private *intel = intel_get_screen_private(scrn); 1110 1111#if HAVE_UDEV 1112 I830UeventFini(scrn); 1113#endif 1114 1115 intel_mode_close(intel); 1116 1117 DeleteCallback(&FlushCallback, intel_flush_callback, scrn); 1118 1119 TimerFree(intel->cache_expire); 1120 intel->cache_expire = NULL; 1121 1122 if (intel->uxa_driver) { 1123 uxa_driver_fini(screen); 1124 free(intel->uxa_driver); 1125 intel->uxa_driver = NULL; 1126 } 1127 1128 if (intel->back_buffer) { 1129 drm_intel_bo_unreference(intel->back_buffer); 1130 intel->back_buffer = NULL; 1131 } 1132 1133 if (intel->front_buffer) { 1134 intel_mode_remove_fb(intel); 1135 drm_intel_bo_unreference(intel->front_buffer); 1136 intel->front_buffer = NULL; 1137 } 1138 1139 if (scrn->vtSema == TRUE) { 1140 I830LeaveVT(VT_FUNC_ARGS(0)); 1141 } 1142 1143 intel_batch_teardown(scrn); 1144 1145 if (INTEL_INFO(intel)->gen >= 040 && INTEL_INFO(intel)->gen < 0100) 1146 gen4_render_state_cleanup(scrn); 1147 1148 xf86_cursors_fini(screen); 1149 1150 i965_free_video(scrn); 1151 1152 screen->CloseScreen = intel->CloseScreen; 1153 (*screen->CloseScreen) (CLOSE_SCREEN_ARGS); 1154 1155 if (intel->dri2 == DRI_ACTIVE) { 1156 I830DRI2CloseScreen(screen); 1157 intel->dri2 = DRI_NONE; 1158 } 1159 1160 if (intel->dri3 == DRI_ACTIVE) { 1161 /* nothing to do here? */ 1162 intel->dri3 = DRI_NONE; 1163 } 1164 1165 intel_sync_close(screen); 1166 1167 xf86GARTCloseScreen(scrn->scrnIndex); 1168 1169 scrn->vtSema = FALSE; 1170 return TRUE; 1171} 1172 1173static ModeStatus 1174I830ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 1175{ 1176 SCRN_INFO_PTR(arg); 1177 if (mode->Flags & V_INTERLACE) { 1178 if (verbose) { 1179 xf86DrvMsg(scrn->scrnIndex, X_PROBED, 1180 "Removing interlaced mode \"%s\"\n", 1181 mode->name); 1182 } 1183 return MODE_BAD; 1184 } 1185 return MODE_OK; 1186} 1187 1188#ifndef SUSPEND_SLEEP 1189#define SUSPEND_SLEEP 0 1190#endif 1191#ifndef RESUME_SLEEP 1192#define RESUME_SLEEP 0 1193#endif 1194 1195/* 1196 * This function is only required if we need to do anything differently from 1197 * DoApmEvent() in common/xf86PM.c, including if we want to see events other 1198 * than suspend/resume. 1199 */ 1200static Bool I830PMEvent(SCRN_ARG_TYPE arg, pmEvent event, Bool undo) 1201{ 1202 SCRN_INFO_PTR(arg); 1203 intel_screen_private *intel = intel_get_screen_private(scrn); 1204 1205 switch (event) { 1206 case XF86_APM_SYS_SUSPEND: 1207 case XF86_APM_CRITICAL_SUSPEND: /*do we want to delay a critical suspend? */ 1208 case XF86_APM_USER_SUSPEND: 1209 case XF86_APM_SYS_STANDBY: 1210 case XF86_APM_USER_STANDBY: 1211 if (!undo && !intel->suspended) { 1212 scrn->LeaveVT(VT_FUNC_ARGS(0)); 1213 intel->suspended = TRUE; 1214 sleep(SUSPEND_SLEEP); 1215 } else if (undo && intel->suspended) { 1216 sleep(RESUME_SLEEP); 1217 scrn->EnterVT(VT_FUNC_ARGS(0)); 1218 intel->suspended = FALSE; 1219 } 1220 break; 1221 case XF86_APM_STANDBY_RESUME: 1222 case XF86_APM_NORMAL_RESUME: 1223 case XF86_APM_CRITICAL_RESUME: 1224 if (intel->suspended) { 1225 sleep(RESUME_SLEEP); 1226 scrn->EnterVT(VT_FUNC_ARGS(0)); 1227 intel->suspended = FALSE; 1228 /* 1229 * Turn the screen saver off when resuming. This seems to be 1230 * needed to stop xscreensaver kicking in (when used). 1231 * 1232 * XXX DoApmEvent() should probably call this just like 1233 * xf86VTSwitch() does. Maybe do it here only in 4.2 1234 * compatibility mode. 1235 */ 1236 SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); 1237 } 1238 break; 1239 /* This is currently used for ACPI */ 1240 case XF86_APM_CAPABILITY_CHANGED: 1241 ErrorF("I830PMEvent: Capability change\n"); 1242 1243 SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); 1244 1245 break; 1246 default: 1247 ErrorF("I830PMEvent: received APM event %d\n", event); 1248 } 1249 return TRUE; 1250} 1251 1252Bool intel_init_scrn(ScrnInfoPtr scrn) 1253{ 1254 scrn->PreInit = I830PreInit; 1255 scrn->ScreenInit = I830ScreenInit; 1256 scrn->SwitchMode = I830SwitchMode; 1257 scrn->AdjustFrame = i830AdjustFrame; 1258 scrn->EnterVT = I830EnterVT; 1259 scrn->LeaveVT = I830LeaveVT; 1260 scrn->FreeScreen = I830FreeScreen; 1261 scrn->ValidMode = I830ValidMode; 1262 scrn->PMEvent = I830PMEvent; 1263 return TRUE; 1264} 1265