1#ifdef HAVE_CONFIG_H 2#include "config.h" 3#endif 4 5#include <errno.h> 6#include <stdio.h> 7#include <string.h> 8#include <assert.h> 9 10#include "xf86.h" 11#include "xf86_OSproc.h" 12#include "xf86Priv.h" 13 14#include "xf86PciInfo.h" 15#include "xf86Pci.h" 16 17#include "windowstr.h" 18#include "shadow.h" 19#include "shadowfb.h" 20 21#include "GL/glxtokens.h" 22 23#include "i810.h" 24#include "i810_dri.h" 25 26static char I810KernelDriverName[] = "i810"; 27static char I810ClientDriverName[] = "i810"; 28 29static Bool I810InitVisualConfigs(ScreenPtr pScreen); 30static Bool I810CreateContext(ScreenPtr pScreen, VisualPtr visual, 31 drm_context_t hwContext, void *pVisualConfigPriv, 32 DRIContextType contextStore); 33static void I810DestroyContext(ScreenPtr pScreen, drm_context_t hwContext, 34 DRIContextType contextStore); 35static void I810DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, 36 DRIContextType readContextType, 37 void *readContextStore, 38 DRIContextType writeContextType, 39 void *writeContextStore); 40static void I810DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index); 41static void I810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, 42 RegionPtr prgnSrc, CARD32 index); 43 44 45static void I810EnablePageFlip(ScreenPtr pScreen); 46static void I810DisablePageFlip(ScreenPtr pScreen); 47static void I810DRITransitionSingleToMulti3d(ScreenPtr pScreen); 48static void I810DRITransitionMultiToSingle3d(ScreenPtr pScreen); 49static void I810DRITransitionTo3d(ScreenPtr pScreen); 50static void I810DRITransitionTo2d(ScreenPtr pScreen); 51 52static void I810DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox); 53 54extern void GlxSetVisualConfigs(int nconfigs, 55 __GLXvisualConfig * configs, 56 void **configprivs); 57 58static int i810_pitches[] = { 59 512, 60 1024, 61 2048, 62 4096, 63 0 64}; 65 66static int i810_pitch_flags[] = { 67 0x0, 68 0x1, 69 0x2, 70 0x3, 71 0 72}; 73 74static unsigned int i810_drm_version = 0; 75 76Bool 77I810CleanupDma(ScrnInfoPtr pScrn) 78{ 79 I810Ptr pI810 = I810PTR(pScrn); 80 drmI810Init info; 81 82 memset(&info, 0, sizeof(drmI810Init)); 83 info.func = I810_CLEANUP_DMA; 84 85 if (drmCommandWrite(pI810->drmSubFD, DRM_I810_INIT, 86 &info, sizeof(drmI810Init))) { 87 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 88 "[dri] I810 Dma Cleanup Failed\n"); 89 return FALSE; 90 } 91 92 return TRUE; 93} 94 95Bool 96I810InitDma(ScrnInfoPtr pScrn) 97{ 98 I810Ptr pI810 = I810PTR(pScrn); 99 I810RingBuffer *ring = pI810->LpRing; 100 I810DRIPtr pI810DRI = (I810DRIPtr) pI810->pDRIInfo->devPrivate; 101 drmI810Init info; 102 103 memset(&info, 0, sizeof(drmI810Init)); 104 105 info.ring_start = ring->mem.Start; 106 info.ring_end = ring->mem.End; 107 info.ring_size = ring->mem.Size; 108 info.mmio_offset = (unsigned int)pI810DRI->regs; 109 info.buffers_offset = (unsigned int)pI810->buffer_map; 110 info.sarea_priv_offset = sizeof(XF86DRISAREARec); 111 112 info.front_offset = 0; 113 info.back_offset = pI810->BackBuffer.Start; 114 info.depth_offset = pI810->DepthBuffer.Start; 115 info.overlay_offset = pI810->OverlayStart; 116 info.overlay_physical = pI810->OverlayPhysical; 117 info.w = pScrn->virtualX; 118 info.h = pScrn->virtualY; 119 info.pitch = pI810->auxPitch; 120 info.pitch_bits = pI810->auxPitchBits; 121 122 /* We require DRM v1.2 or greater. Since DRM v1.2 broke compatibility 123 * we created a new v1.4 that supports a new init function. Eventually the 124 * old init function will go away. If you change the drm interface, make a 125 * new init type too so that we can detect the new client. 126 */ 127 switch(i810_drm_version) { 128 case ((1<<16) | 0): 129 case ((1<<16) | 1): 130 case ((1<<16) | 2): 131 case ((1<<16) | 3): 132 /* Use OLD drm < 1.4 init */ 133 info.func = I810_INIT_DMA; 134 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Init PRE v1.4 interface.\n"); 135 break; 136 default: 137 case ((1<<16) | 4): 138 /* DRM version 1.3 or greater init */ 139 info.func = I810_INIT_DMA_1_4; 140 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Init v1.4 interface.\n"); 141 break; 142 } 143 144 if (drmCommandWrite(pI810->drmSubFD, DRM_I810_INIT, 145 &info, sizeof(drmI810Init))) { 146 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 147 "[drm] I810 Dma Initialization failed.\n"); 148 return FALSE; 149 } 150 151 return TRUE; 152} 153 154static Bool 155I810InitVisualConfigs(ScreenPtr pScreen) 156{ 157 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 158 I810Ptr pI810 = I810PTR(pScrn); 159 int numConfigs = 0; 160 __GLXvisualConfig *pConfigs = NULL; 161 I810ConfigPrivPtr pI810Configs = NULL; 162 I810ConfigPrivPtr *pI810ConfigPtrs = NULL; 163 int accum, stencil, db, depth; 164 int i; 165 166 switch (pScrn->bitsPerPixel) { 167 case 8: 168 case 24: 169 case 32: 170 break; 171 case 16: 172 numConfigs = 8; 173 174 pConfigs = 175 (__GLXvisualConfig *) xcalloc(sizeof(__GLXvisualConfig), 176 numConfigs); 177 if (!pConfigs) 178 return FALSE; 179 180 pI810Configs = 181 (I810ConfigPrivPtr) xcalloc(sizeof(I810ConfigPrivRec), 182 numConfigs); 183 if (!pI810Configs) { 184 xfree(pConfigs); 185 return FALSE; 186 } 187 188 pI810ConfigPtrs = 189 (I810ConfigPrivPtr *) xcalloc(sizeof(I810ConfigPrivPtr), 190 numConfigs); 191 if (!pI810ConfigPtrs) { 192 xfree(pConfigs); 193 xfree(pI810Configs); 194 return FALSE; 195 } 196 197 for (i = 0; i < numConfigs; i++) 198 pI810ConfigPtrs[i] = &pI810Configs[i]; 199 200 i = 0; 201 depth = 1; 202 for (accum = 0; accum <= 1; accum++) { 203 for (stencil = 0; stencil <= 1; stencil++) { 204 for (db = 1; db >= 0; db--) { 205 pConfigs[i].vid = -1; 206 pConfigs[i].class = -1; 207 pConfigs[i].rgba = TRUE; 208 pConfigs[i].redSize = 5; 209 pConfigs[i].greenSize = 6; 210 pConfigs[i].blueSize = 5; 211 pConfigs[i].alphaSize = 0; 212 pConfigs[i].redMask = 0x0000F800; 213 pConfigs[i].greenMask = 0x000007E0; 214 pConfigs[i].blueMask = 0x0000001F; 215 pConfigs[i].alphaMask = 0; 216 if (accum) { 217 pConfigs[i].accumRedSize = 16; 218 pConfigs[i].accumGreenSize = 16; 219 pConfigs[i].accumBlueSize = 16; 220 pConfigs[i].accumAlphaSize = 0; 221 } else { 222 pConfigs[i].accumRedSize = 0; 223 pConfigs[i].accumGreenSize = 0; 224 pConfigs[i].accumBlueSize = 0; 225 pConfigs[i].accumAlphaSize = 0; 226 } 227 pConfigs[i].doubleBuffer = db ? TRUE : FALSE; 228 pConfigs[i].stereo = FALSE; 229 pConfigs[i].bufferSize = 16; 230 if (depth) 231 pConfigs[i].depthSize = 16; 232 else 233 pConfigs[i].depthSize = 0; 234 if (stencil) 235 pConfigs[i].stencilSize = 8; 236 else 237 pConfigs[i].stencilSize = 0; 238 pConfigs[i].auxBuffers = 0; 239 pConfigs[i].level = 0; 240 if (stencil || accum) 241 pConfigs[i].visualRating = GLX_SLOW_CONFIG; 242 else 243 pConfigs[i].visualRating = GLX_NONE; 244 pConfigs[i].transparentPixel = GLX_NONE; 245 pConfigs[i].transparentRed = 0; 246 pConfigs[i].transparentGreen = 0; 247 pConfigs[i].transparentBlue = 0; 248 pConfigs[i].transparentAlpha = 0; 249 pConfigs[i].transparentIndex = 0; 250 i++; 251 } 252 } 253 } 254 assert(i == numConfigs); 255 break; 256 } 257 pI810->numVisualConfigs = numConfigs; 258 pI810->pVisualConfigs = pConfigs; 259 pI810->pVisualConfigsPriv = pI810Configs; 260 GlxSetVisualConfigs(numConfigs, pConfigs, (void **)pI810ConfigPtrs); 261 return TRUE; 262} 263 264static unsigned int 265mylog2(unsigned int n) 266{ 267 unsigned int log2 = 1; 268 269 while (n > 1) 270 n >>= 1, log2++; 271 return log2; 272} 273 274Bool 275I810DRIScreenInit(ScreenPtr pScreen) 276{ 277 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 278 I810Ptr pI810 = I810PTR(pScrn); 279 DRIInfoPtr pDRIInfo; 280 I810DRIPtr pI810DRI; 281 unsigned long tom; 282 drm_handle_t agpHandle; 283 drm_handle_t dcacheHandle; 284 int sysmem_size = 0; 285 int back_size = 0; 286 unsigned int pitch_idx = 0; 287 int bufs; 288 int width = pScrn->displayWidth * pI810->cpp; 289 int i; 290 291 /* Hardware 3D rendering only implemented for 16bpp */ 292 /* And it only works for 5:6:5 (Mark) */ 293 if (pScrn->depth != 16) 294 return FALSE; 295 296 /* Check that the GLX, DRI, and DRM modules have been loaded by testing 297 * for known symbols in each module. */ 298 if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) 299 return FALSE; 300 if (!xf86LoaderCheckSymbol("drmAvailable")) 301 return FALSE; 302 if (!xf86LoaderCheckSymbol("DRIQueryVersion")) { 303 xf86DrvMsg(pScreen->myNum, X_ERROR, 304 "[dri] I810DRIScreenInit failed (libdri.a too old)\n"); 305 return FALSE; 306 } 307 308 /* Check the DRI version */ 309 { 310 int major, minor, patch; 311 312 DRIQueryVersion(&major, &minor, &patch); 313 if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) { 314 xf86DrvMsg(pScreen->myNum, X_ERROR, 315 "[dri] I810DRIScreenInit failed because of a version mismatch.\n" 316 "[dri] libdri version is %d.%d.%d bug version %d.%d.x is needed.\n" 317 "[dri] Disabling DRI.\n", major, minor, patch, 318 DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION); 319 return FALSE; 320 } 321 } 322 323 pDRIInfo = DRICreateInfoRec(); 324 if (!pDRIInfo) { 325 xf86DrvMsg(pScreen->myNum, X_ERROR, 326 "[dri] DRICreateInfoRec failed. Disabling DRI.\n"); 327 return FALSE; 328 } 329 330/* pDRIInfo->wrap.ValidateTree = 0; */ 331/* pDRIInfo->wrap.PostValidateTree = 0; */ 332 333 pI810->pDRIInfo = pDRIInfo; 334 pI810->LockHeld = 0; 335 336 pDRIInfo->drmDriverName = I810KernelDriverName; 337 pDRIInfo->clientDriverName = I810ClientDriverName; 338 if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { 339 pDRIInfo->busIdString = DRICreatePCIBusID(pI810->PciInfo); 340 } else { 341 pDRIInfo->busIdString = xalloc(64); 342 sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", 343 ((pI810->PciInfo->domain << 8) | pI810->PciInfo->bus), 344 pI810->PciInfo->dev, pI810->PciInfo->func 345 ); 346 } 347 pDRIInfo->ddxDriverMajorVersion = I810_MAJOR_VERSION; 348 pDRIInfo->ddxDriverMinorVersion = I810_MINOR_VERSION; 349 pDRIInfo->ddxDriverPatchVersion = I810_PATCHLEVEL; 350 pDRIInfo->frameBufferPhysicalAddress = (pointer) pI810->LinearAddr; 351 pDRIInfo->frameBufferSize = (((pScrn->displayWidth * 352 pScrn->virtualY * pI810->cpp) + 353 4096 - 1) / 4096) * 4096; 354 355 pDRIInfo->frameBufferStride = pScrn->displayWidth * pI810->cpp; 356 pDRIInfo->ddxDrawableTableEntry = I810_MAX_DRAWABLES; 357 358 if (SAREA_MAX_DRAWABLES < I810_MAX_DRAWABLES) 359 pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES; 360 else 361 pDRIInfo->maxDrawableTableEntry = I810_MAX_DRAWABLES; 362 363 /* For now the mapping works by using a fixed size defined 364 * in the SAREA header 365 */ 366 if (sizeof(XF86DRISAREARec) + sizeof(I810SAREARec) > SAREA_MAX) { 367 xf86DrvMsg(pScreen->myNum, X_ERROR, 368 "[dri] Data does not fit in SAREA\n"); 369 return FALSE; 370 } 371 pDRIInfo->SAREASize = SAREA_MAX; 372 373 if (!(pI810DRI = (I810DRIPtr) xcalloc(sizeof(I810DRIRec), 1))) { 374 DRIDestroyInfoRec(pI810->pDRIInfo); 375 pI810->pDRIInfo = NULL; 376 return FALSE; 377 } 378 pDRIInfo->devPrivate = pI810DRI; 379 pDRIInfo->devPrivateSize = sizeof(I810DRIRec); 380 pDRIInfo->contextSize = sizeof(I810DRIContextRec); 381 382 pDRIInfo->CreateContext = I810CreateContext; 383 pDRIInfo->DestroyContext = I810DestroyContext; 384 pDRIInfo->SwapContext = I810DRISwapContext; 385 pDRIInfo->InitBuffers = I810DRIInitBuffers; 386 pDRIInfo->MoveBuffers = I810DRIMoveBuffers; 387 pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; 388 pDRIInfo->TransitionTo2d = I810DRITransitionTo2d; 389 pDRIInfo->TransitionTo3d = I810DRITransitionTo3d; 390 pDRIInfo->TransitionSingleToMulti3D = I810DRITransitionSingleToMulti3d; 391 pDRIInfo->TransitionMultiToSingle3D = I810DRITransitionMultiToSingle3d; 392 393 pDRIInfo->createDummyCtx = TRUE; 394 pDRIInfo->createDummyCtxPriv = FALSE; 395 396 /* This adds the framebuffer as a drm map *before* we have asked agp 397 * to allocate it. Scary stuff, hold on... 398 */ 399 if (!DRIScreenInit(pScreen, pDRIInfo, &pI810->drmSubFD)) { 400 xf86DrvMsg(pScreen->myNum, X_ERROR, 401 "[dri] DRIScreenInit failed. Disabling DRI.\n"); 402 xfree(pDRIInfo->devPrivate); 403 pDRIInfo->devPrivate = NULL; 404 DRIDestroyInfoRec(pI810->pDRIInfo); 405 pI810->pDRIInfo = NULL; 406 return FALSE; 407 } 408 409 /* Check the i810 DRM versioning */ 410 { 411 drmVersionPtr version; 412 413 /* Check the DRM lib version. 414 * drmGetLibVersion was not supported in version 1.0, so check for 415 * symbol first to avoid possible crash or hang. 416 */ 417 if (xf86LoaderCheckSymbol("drmGetLibVersion")) { 418 version = drmGetLibVersion(pI810->drmSubFD); 419 } else 420 { 421 /* drmlib version 1.0.0 didn't have the drmGetLibVersion 422 * entry point. Fake it by allocating a version record 423 * via drmGetVersion and changing it to version 1.0.0 424 */ 425 version = drmGetVersion(pI810->drmSubFD); 426 version->version_major = 1; 427 version->version_minor = 0; 428 version->version_patchlevel = 0; 429 } 430 431#define REQ_MAJ 1 432#define REQ_MIN 1 433 if (version) { 434 if (version->version_major != REQ_MAJ || 435 version->version_minor < REQ_MIN) { 436 /* incompatible drm library version */ 437 xf86DrvMsg(pScreen->myNum, X_ERROR, 438 "[dri] I810DRIScreenInit failed because of a version mismatch.\n" 439 "[dri] libdrm.a module version is %d.%d.%d but version %d.%d.x is needed.\n" 440 "[dri] Disabling DRI.\n", 441 version->version_major, 442 version->version_minor, version->version_patchlevel, 443 REQ_MAJ, REQ_MIN); 444 drmFreeVersion(version); 445 I810DRICloseScreen(pScreen); 446 return FALSE; 447 } 448 drmFreeVersion(version); 449 } 450 451 /* Check the i810 DRM version */ 452 version = drmGetVersion(pI810->drmSubFD); 453 if (version) { 454 i810_drm_version = (version->version_major<<16) | 455 version->version_minor; 456 if (version->version_major != 1 || version->version_minor < 2) { 457 /* incompatible drm version */ 458 xf86DrvMsg(pScreen->myNum, X_ERROR, 459 "[dri] I810DRIScreenInit failed because of a version mismatch.\n" 460 "[dri] i810.o kernel module version is %d.%d.%d but version 1.2.0 or greater is needed.\n" 461 "[dri] Disabling DRI.\n", 462 version->version_major, 463 version->version_minor, version->version_patchlevel); 464 I810DRICloseScreen(pScreen); 465 drmFreeVersion(version); 466 return FALSE; 467 } 468 pI810->drmMinor = version->version_minor; 469 drmFreeVersion(version); 470 } 471 } 472 473 pI810DRI->regsSize = I810_REG_SIZE; 474 if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->MMIOAddr, 475 pI810DRI->regsSize, DRM_REGISTERS, 0, 476 (drmAddress) &pI810DRI->regs) < 0) { 477 xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(regs) failed\n"); 478 DRICloseScreen(pScreen); 479 return FALSE; 480 } 481 xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n", 482 (int)pI810DRI->regs); 483 484 pI810->backHandle = DRM_AGP_NO_HANDLE; 485 pI810->zHandle = DRM_AGP_NO_HANDLE; 486 pI810->cursorHandle = DRM_AGP_NO_HANDLE; 487 pI810->xvmcHandle = DRM_AGP_NO_HANDLE; 488 pI810->sysmemHandle = DRM_AGP_NO_HANDLE; 489 pI810->agpAcquired = FALSE; 490 pI810->dcacheHandle = DRM_AGP_NO_HANDLE; 491 492 /* Agp Support - Need this just to get the framebuffer. 493 */ 494 if (drmAgpAcquire(pI810->drmSubFD) < 0) { 495 xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpAquire failed\n"); 496 DRICloseScreen(pScreen); 497 return FALSE; 498 } 499 pI810->agpAcquired = TRUE; 500 501 if (drmAgpEnable(pI810->drmSubFD, 0) < 0) { 502 xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpEnable failed\n"); 503 DRICloseScreen(pScreen); 504 return FALSE; 505 } 506 507 memset(&pI810->DcacheMem, 0, sizeof(I810MemRange)); 508 memset(&pI810->BackBuffer, 0, sizeof(I810MemRange)); 509 memset(&pI810->DepthBuffer, 0, sizeof(I810MemRange)); 510 pI810->CursorPhysical = 0; 511 pI810->CursorARGBPhysical = 0; 512 513 /* Dcache - half the speed of normal ram, but has use as a Z buffer 514 * under the DRI. 515 */ 516 517 drmAgpAlloc(pI810->drmSubFD, 4096 * 1024, 1, NULL, 518 (drmAddress) &dcacheHandle); 519 pI810->dcacheHandle = dcacheHandle; 520 521 xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] dcacheHandle : 0x%x\n", 522 (int)dcacheHandle); 523 524#define Elements(x) sizeof(x)/sizeof(*x) 525 for (pitch_idx = 0; pitch_idx < Elements(i810_pitches); pitch_idx++) 526 if (width <= i810_pitches[pitch_idx]) 527 break; 528 529 if (pitch_idx == Elements(i810_pitches)) { 530 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 531 "[dri] Couldn't find depth/back buffer pitch"); 532 DRICloseScreen(pScreen); 533 return FALSE; 534 } else { 535 /* for tiled memory to work, the buffer needs to have the 536 * number of lines as a multiple of 16 (the tile size), 537 * - airlied */ 538 int lines = (pScrn->virtualY + 15) / 16 * 16; 539 back_size = i810_pitches[pitch_idx] * lines; 540 back_size = ((back_size + 4096 - 1) / 4096) * 4096; 541 } 542 543 sysmem_size = pScrn->videoRam * 1024; 544 if (dcacheHandle != DRM_AGP_NO_HANDLE) { 545 if (back_size > 4 * 1024 * 1024) { 546 xf86DrvMsg(pScreen->myNum, X_INFO, 547 "[dri] Backsize is larger then 4 meg\n"); 548 sysmem_size = sysmem_size - 2 * back_size; 549 drmAgpFree(pI810->drmSubFD, dcacheHandle); 550 pI810->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE; 551 } else { 552 sysmem_size = sysmem_size - back_size; 553 } 554 } else { 555 sysmem_size = sysmem_size - 2 * back_size; 556 } 557 558 /* Max size is 48 without XvMC, 41 with 6 surfaces, 40 with 7 surfaces */ 559 if (pI810->numSurfaces && (pI810->numSurfaces == 6)) { 560 if (sysmem_size > (pI810->FbMapSize - 7 * 1024 * 1024)) { 561 sysmem_size = (pI810->FbMapSize - 7 * 1024 * 1024); 562 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 563 "User requested more memory then fits in the agp aperture\n" 564 "Truncating to %d bytes of memory\n", sysmem_size); 565 } 566 } 567 if (pI810->numSurfaces && (pI810->numSurfaces == 7)) { 568 if (sysmem_size > (pI810->FbMapSize - 8 * 1024 * 1024)) { 569 sysmem_size = (pI810->FbMapSize - 8 * 1024 * 1024); 570 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 571 "User requested more memory then fits in the agp aperture\n" 572 "Truncating to %d bytes of memory\n", sysmem_size); 573 } 574 } 575 576 if (sysmem_size > pI810->FbMapSize) { 577 sysmem_size = pI810->FbMapSize; 578 579 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 580 "[dri] User requested more memory then fits in the agp" 581 " aperture\n\tTruncating to %d bytes of memory\n", 582 sysmem_size); 583 } 584 585 sysmem_size -= 4096; /* remove 4k for the hw cursor */ 586 sysmem_size -= 16384; /* remove 16k for the ARGB hw cursor */ 587 588 pI810->SysMem.Start = 0; 589 pI810->SysMem.Size = sysmem_size; 590 pI810->SysMem.End = sysmem_size; 591 tom = sysmem_size; 592 593 pI810->SavedSysMem = pI810->SysMem; 594 595 if (dcacheHandle != DRM_AGP_NO_HANDLE) { 596 if (drmAgpBind(pI810->drmSubFD, dcacheHandle, pI810->DepthOffset) == 0) { 597 memset(&pI810->DcacheMem, 0, sizeof(I810MemRange)); 598 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 599 "[agp] GART: Found 4096K Z buffer memory\n"); 600 pI810->DcacheMem.Start = pI810->DepthOffset; 601 pI810->DcacheMem.Size = 1024 * 4096; 602 pI810->DcacheMem.End = 603 pI810->DcacheMem.Start + pI810->DcacheMem.Size; 604 if (!I810AllocLow 605 (&(pI810->DepthBuffer), &(pI810->DcacheMem), back_size)) { 606 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 607 "[agp] Depth buffer allocation failed\n"); 608 DRICloseScreen(pScreen); 609 return FALSE; 610 } 611 } else { 612 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 613 "[agp] GART: dcache bind failed\n"); 614 drmAgpFree(pI810->drmSubFD, dcacheHandle); 615 pI810->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE; 616 } 617 } else { 618 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 619 "[agp] GART: no dcache memory found\n"); 620 } 621 622 drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL, 623 (drmAddress) &agpHandle); 624 pI810->backHandle = agpHandle; 625 626 if (agpHandle != DRM_AGP_NO_HANDLE) { 627 if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->BackOffset) == 0) { 628 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 629 "[agp] Bound backbuffer memory\n"); 630 631 pI810->BackBuffer.Start = pI810->BackOffset; 632 pI810->BackBuffer.Size = back_size; 633 pI810->BackBuffer.End = (pI810->BackBuffer.Start + 634 pI810->BackBuffer.Size); 635 } else { 636 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 637 "[agp] Unable to bind backbuffer. Disabling DRI.\n"); 638 DRICloseScreen(pScreen); 639 return FALSE; 640 } 641 } else { 642 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 643 "[dri] Unable to allocate backbuffer memory. Disabling DRI.\n"); 644 DRICloseScreen(pScreen); 645 return FALSE; 646 } 647 648 if (dcacheHandle == DRM_AGP_NO_HANDLE) { 649 drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL, 650 (drmAddress) &agpHandle); 651 652 pI810->zHandle = agpHandle; 653 654 if (agpHandle != DRM_AGP_NO_HANDLE) { 655 if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->DepthOffset) == 0) { 656 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 657 "[agp] Bound depthbuffer memory\n"); 658 pI810->DepthBuffer.Start = pI810->DepthOffset; 659 pI810->DepthBuffer.Size = back_size; 660 pI810->DepthBuffer.End = (pI810->DepthBuffer.Start + 661 pI810->DepthBuffer.Size); 662 } else { 663 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 664 "[agp] Unable to bind depthbuffer. Disabling DRI.\n"); 665 DRICloseScreen(pScreen); 666 return FALSE; 667 } 668 } else { 669 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 670 "[agp] Unable to allocate depthbuffer memory. Disabling DRI.\n"); 671 DRICloseScreen(pScreen); 672 return FALSE; 673 } 674 } 675 676 /* Now allocate and bind the agp space. This memory will include the 677 * regular framebuffer as well as texture memory. 678 */ 679 drmAgpAlloc(pI810->drmSubFD, sysmem_size, 0, NULL, 680 (drmAddress)&agpHandle); 681 pI810->sysmemHandle = agpHandle; 682 683 if (agpHandle != DRM_AGP_NO_HANDLE) { 684 if (drmAgpBind(pI810->drmSubFD, agpHandle, 0) == 0) { 685 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 686 "[agp] Bound System Texture Memory\n"); 687 } else { 688 xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Unable to bind system texture memory. Disabling DRI.\n"); 689 DRICloseScreen(pScreen); 690 return FALSE; 691 } 692 } else { 693 xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Unable to allocate system texture memory. Disabling DRI.\n"); 694 DRICloseScreen(pScreen); 695 return FALSE; 696 } 697 698/* Allocate 7 or 8MB for XvMC this is setup as follows to best use tiled 699 regions and required surface pitches. (Numbers are adjusted if the 700 AGP region is only 32MB 701 For numSurfaces == 6 702 44 - 48MB = 4MB Fence, 8 Tiles wide 703 43 - 44MB = 1MB Fence, 8 Tiles wide 704 42 - 43MB = 1MB Fence, 4 Tiles wide 705 41 - 42MB = 1MB Fence, 4 Tiles wide 706 For numSurfaces == 7 707 44 - 48MB = 4MB Fence, 8 Tiles wide 708 43 - 44MB = 1MB Fence, 8 Tiles wide 709 42.5 - 43MB = 0.5MB Fence, 8 Tiles wide 710 42 - 42.5MB = 0.5MB Fence, 4 Tiles wide 711 40 - 42MB = 2MB Fence, 4 Tiles wide 712 */ 713 if (pI810->numSurfaces) { 714 if (pI810->numSurfaces == 6) { 715 pI810->MC.Size = 7 * 1024 * 1024; 716 pI810->MC.Start = pI810->FbMapSize - 7 * 1024 * 1024; 717 718 } 719 if (pI810->numSurfaces == 7) { 720 pI810->MC.Size = 8 * 1024 * 1024; 721 pI810->MC.Start = pI810->FbMapSize - 8 * 1024 * 1024; 722 } 723 drmAgpAlloc(pI810->drmSubFD, pI810->MC.Size, 0, NULL, 724 (drmAddress) &agpHandle); 725 726 pI810->xvmcHandle = agpHandle; 727 728 if (agpHandle != DRM_AGP_NO_HANDLE) { 729 if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->MC.Start) == 0) { 730 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 731 "GART: Allocated 7MB for HWMC\n"); 732 pI810->MC.End = pI810->MC.Start + pI810->MC.Size; 733 } else { 734 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: HWMC bind failed\n"); 735 pI810->MC.Start = 0; 736 pI810->MC.Size = 0; 737 pI810->MC.End = 0; 738 } 739 } else { 740 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: HWMC alloc failed\n"); 741 pI810->MC.Start = 0; 742 pI810->MC.Size = 0; 743 pI810->MC.End = 0; 744 } 745 pI810->xvmcContext = 0; 746 } 747 748 drmAgpAlloc(pI810->drmSubFD, 4096, 2, 749 (unsigned long *)&pI810->CursorPhysical, 750 (drmAddress) &agpHandle); 751 752 pI810->cursorHandle = agpHandle; 753 754 if (agpHandle != DRM_AGP_NO_HANDLE) { 755 tom = sysmem_size; 756 757 if (drmAgpBind(pI810->drmSubFD, agpHandle, tom) == 0) { 758 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 759 "[agp] GART: Allocated 4K for mouse cursor image\n"); 760 pI810->CursorStart = tom; 761 tom += 4096; 762 } else { 763 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 764 "[agp] GART: cursor bind failed\n"); 765 pI810->CursorPhysical = 0; 766 } 767 } else { 768 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 769 "[agp] GART: cursor alloc failed\n"); 770 pI810->CursorPhysical = 0; 771 } 772 773 drmAgpAlloc(pI810->drmSubFD, 16384, 2, 774 (unsigned long *)&pI810->CursorARGBPhysical, 775 (drmAddress) &agpHandle); 776 777 pI810->cursorARGBHandle = agpHandle; 778 779 if (agpHandle != DRM_AGP_NO_HANDLE) { 780 int r; 781 782 if ((r = drmAgpBind(pI810->drmSubFD, agpHandle, tom)) == 0) { 783 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 784 "[agp] GART: Allocated 16K for ARGB mouse cursor image\n"); 785 pI810->CursorARGBStart = tom; 786 tom += 16384; 787 } else { 788 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 789 "[agp] GART: ARGB cursor bind failed\n"); 790 pI810->CursorARGBPhysical = 0; 791 } 792 } else { 793 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 794 "[agp] GART: ARGB cursor alloc failed\n"); 795 pI810->CursorARGBPhysical = 0; 796 } 797 798 /* Steal some of the excess cursor space for the overlay regs. 799 */ 800 pI810->OverlayPhysical = pI810->CursorPhysical + 1024; 801 pI810->OverlayStart = pI810->CursorStart + 1024; 802 803 I810SetTiledMemory(pScrn, 1, 804 pI810->DepthBuffer.Start, 805 i810_pitches[pitch_idx], 8 * 1024 * 1024); 806 807 I810SetTiledMemory(pScrn, 2, 808 pI810->BackBuffer.Start, 809 i810_pitches[pitch_idx], 8 * 1024 * 1024); 810 811 /* These are for HWMC surfaces */ 812 if (pI810->numSurfaces == 6) { 813 I810SetTiledMemory(pScrn, 3, pI810->MC.Start, 512, 1024 * 1024); 814 815 I810SetTiledMemory(pScrn, 4, 816 pI810->MC.Start + 1024 * 1024, 512, 1024 * 1024); 817 818 I810SetTiledMemory(pScrn, 5, 819 pI810->MC.Start + 1024 * 1024 * 2, 820 1024, 1024 * 1024); 821 822 I810SetTiledMemory(pScrn, 6, 823 pI810->MC.Start + 1024 * 1024 * 3, 824 1024, 4 * 1024 * 1024); 825 } 826 if (pI810->numSurfaces == 7) { 827 I810SetTiledMemory(pScrn, 3, pI810->MC.Start, 512, 2 * 1024 * 1024); 828 829 I810SetTiledMemory(pScrn, 4, 830 pI810->MC.Start + 2 * 1024 * 1024, 512, 512 * 1024); 831 832 I810SetTiledMemory(pScrn, 5, 833 pI810->MC.Start + 2 * 1024 * 1024 + 512 * 1024, 834 1024, 512 * 1024); 835 836 I810SetTiledMemory(pScrn, 6, 837 pI810->MC.Start + 3 * 1024 * 1024, 838 1024, 1 * 1024 * 1024); 839 840 I810SetTiledMemory(pScrn, 7, 841 pI810->MC.Start + 4 * 1024 * 1024, 842 1024, 4 * 1024 * 1024); 843 844 } 845 846 pI810->auxPitch = i810_pitches[pitch_idx]; 847 pI810->auxPitchBits = i810_pitch_flags[pitch_idx]; 848 pI810->SavedDcacheMem = pI810->DcacheMem; 849 pI810DRI->backbufferSize = pI810->BackBuffer.Size; 850 851 if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BackBuffer.Start, 852 pI810->BackBuffer.Size, DRM_AGP, 0, 853 (drmAddress) &pI810DRI->backbuffer) < 0) { 854 xf86DrvMsg(pScreen->myNum, X_ERROR, 855 "[drm] drmAddMap(backbuffer) failed. Disabling DRI\n"); 856 DRICloseScreen(pScreen); 857 return FALSE; 858 } 859 860 pI810DRI->depthbufferSize = pI810->DepthBuffer.Size; 861 if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->DepthBuffer.Start, 862 pI810->DepthBuffer.Size, DRM_AGP, 0, 863 (drmAddress) &pI810DRI->depthbuffer) < 0) { 864 xf86DrvMsg(pScreen->myNum, X_ERROR, 865 "[drm] drmAddMap(depthbuffer) failed. Disabling DRI.\n"); 866 DRICloseScreen(pScreen); 867 return FALSE; 868 } 869 870 /* Allocate FrontBuffer etc. */ 871 if (!I810AllocateFront(pScrn)) { 872 DRICloseScreen(pScreen); 873 return FALSE; 874 } 875 876 /* Allocate buffer memory */ 877 I810AllocHigh(&(pI810->BufferMem), &(pI810->SysMem), 878 I810_DMA_BUF_NR * I810_DMA_BUF_SZ); 879 880 xf86DrvMsg(pScreen->myNum, X_INFO, "[dri] Buffer map : %lx\n", 881 pI810->BufferMem.Start); 882 883 if (pI810->BufferMem.Start == 0 || 884 pI810->BufferMem.End - pI810->BufferMem.Start > 885 I810_DMA_BUF_NR * I810_DMA_BUF_SZ) { 886 xf86DrvMsg(pScreen->myNum, X_ERROR, 887 "[dri] Not enough memory for dma buffers. Disabling DRI.\n"); 888 DRICloseScreen(pScreen); 889 return FALSE; 890 } 891 if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BufferMem.Start, 892 pI810->BufferMem.Size, DRM_AGP, 0, 893 (drmAddress) &pI810->buffer_map) < 0) { 894 xf86DrvMsg(pScreen->myNum, X_ERROR, 895 "[drm] drmAddMap(buffer_map) failed. Disabling DRI.\n"); 896 DRICloseScreen(pScreen); 897 return FALSE; 898 } 899 900 pI810DRI->agp_buffers = pI810->buffer_map; 901 pI810DRI->agp_buf_size = pI810->BufferMem.Size; 902 903 if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->LpRing->mem.Start, 904 pI810->LpRing->mem.Size, DRM_AGP, 0, 905 (drmAddress) &pI810->ring_map) < 0) { 906 xf86DrvMsg(pScreen->myNum, X_ERROR, 907 "[drm] drmAddMap(ring_map) failed. Disabling DRI.\n"); 908 DRICloseScreen(pScreen); 909 return FALSE; 910 } 911 912 /* Use the rest of memory for textures. */ 913 pI810DRI->textureSize = pI810->SysMem.Size; 914 915 i = mylog2(pI810DRI->textureSize / I810_NR_TEX_REGIONS); 916 917 if (i < I810_LOG_MIN_TEX_REGION_SIZE) 918 i = I810_LOG_MIN_TEX_REGION_SIZE; 919 920 pI810DRI->logTextureGranularity = i; 921 pI810DRI->textureSize = (pI810DRI->textureSize >> i) << i; /* truncate */ 922 923 if (pI810DRI->textureSize < 512 * 1024) { 924 xf86DrvMsg(pScreen->myNum, X_ERROR, 925 "[drm] Less then 512k memory left for textures. Disabling DRI.\n"); 926 DRICloseScreen(pScreen); 927 return FALSE; 928 } 929 930 I810AllocLow(&(pI810->TexMem), &(pI810->SysMem), pI810DRI->textureSize); 931 932 if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->TexMem.Start, 933 pI810->TexMem.Size, DRM_AGP, 0, 934 (drmAddress) &pI810DRI->textures) < 0) { 935 xf86DrvMsg(pScreen->myNum, X_ERROR, 936 "[drm] drmAddMap(textures) failed. Disabling DRI.\n"); 937 DRICloseScreen(pScreen); 938 return FALSE; 939 } 940 941 if ((bufs = drmAddBufs(pI810->drmSubFD, 942 I810_DMA_BUF_NR, 943 I810_DMA_BUF_SZ, 944 DRM_AGP_BUFFER, pI810->BufferMem.Start)) <= 0) { 945 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 946 "[drm] failure adding %d %d byte DMA buffers. Disabling DRI.\n", 947 I810_DMA_BUF_NR, I810_DMA_BUF_SZ); 948 DRICloseScreen(pScreen); 949 return FALSE; 950 } 951 952 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 953 "[drm] added %d %d byte DMA buffers\n", bufs, I810_DMA_BUF_SZ); 954 955 I810InitDma(pScrn); 956 957 /* Okay now initialize the dma engine */ 958 959 if (!pI810DRI->irq) { 960 pI810DRI->irq = drmGetInterruptFromBusID(pI810->drmSubFD, 961 ((pI810->PciInfo->domain << 8) | 962 pI810->PciInfo->bus), 963 pI810->PciInfo->dev, 964 pI810->PciInfo->func 965 ); 966 if ((drmCtlInstHandler(pI810->drmSubFD, pI810DRI->irq)) != 0) { 967 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 968 "[drm] failure adding irq handler, there is a device " 969 "already using that irq\n Consider rearranging your " 970 "PCI cards. Disabling DRI.\n"); 971 DRICloseScreen(pScreen); 972 return FALSE; 973 } 974 } 975 976 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 977 "[drm] dma control initialized, using IRQ %d\n", pI810DRI->irq); 978 979 pI810DRI->deviceID = DEVICE_ID(pI810->PciInfo); 980 pI810DRI->width = pScrn->virtualX; 981 pI810DRI->height = pScrn->virtualY; 982 pI810DRI->mem = pScrn->videoRam * 1024; 983 pI810DRI->cpp = pI810->cpp; 984 985 pI810DRI->fbOffset = pI810->FrontBuffer.Start; 986 pI810DRI->fbStride = pI810->auxPitch; 987 988 pI810DRI->bitsPerPixel = pScrn->bitsPerPixel; 989 990 pI810DRI->textureOffset = pI810->TexMem.Start; 991 992 pI810DRI->backOffset = pI810->BackBuffer.Start; 993 pI810DRI->depthOffset = pI810->DepthBuffer.Start; 994 995 pI810DRI->ringOffset = pI810->LpRing->mem.Start; 996 pI810DRI->ringSize = pI810->LpRing->mem.Size; 997 998 pI810DRI->auxPitch = pI810->auxPitch; 999 pI810DRI->auxPitchBits = pI810->auxPitchBits; 1000 pI810DRI->sarea_priv_offset = sizeof(XF86DRISAREARec); 1001 1002 if (!(I810InitVisualConfigs(pScreen))) { 1003 xf86DrvMsg(pScreen->myNum, X_ERROR, 1004 "[dri] I810InitVisualConfigs failed. Disabling DRI.\n"); 1005 DRICloseScreen(pScreen); 1006 return FALSE; 1007 } 1008 1009 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1010 "[dri] visual configs initialized.\n"); 1011 pI810->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT; 1012 1013 return TRUE; 1014} 1015 1016void 1017I810DRICloseScreen(ScreenPtr pScreen) 1018{ 1019 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1020 I810Ptr pI810 = I810PTR(pScrn); 1021 I810DRIPtr pI810DRI = (I810DRIPtr) pI810->pDRIInfo->devPrivate; 1022 1023 if (pI810DRI->irq) { 1024 drmCtlUninstHandler(pI810->drmSubFD); 1025 pI810DRI->irq = 0; 1026 } 1027 1028 I810CleanupDma(pScrn); 1029 1030 if (pI810->dcacheHandle!=DRM_AGP_NO_HANDLE) 1031 drmAgpFree(pI810->drmSubFD, pI810->dcacheHandle); 1032 if (pI810->backHandle!=DRM_AGP_NO_HANDLE) 1033 drmAgpFree(pI810->drmSubFD, pI810->backHandle); 1034 if (pI810->zHandle!=DRM_AGP_NO_HANDLE) 1035 drmAgpFree(pI810->drmSubFD, pI810->zHandle); 1036 if (pI810->cursorHandle!=DRM_AGP_NO_HANDLE) 1037 drmAgpFree(pI810->drmSubFD, pI810->cursorHandle); 1038 if (pI810->xvmcHandle!=DRM_AGP_NO_HANDLE) 1039 drmAgpFree(pI810->drmSubFD, pI810->xvmcHandle); 1040 if (pI810->sysmemHandle!=DRM_AGP_NO_HANDLE) 1041 drmAgpFree(pI810->drmSubFD, pI810->sysmemHandle); 1042 1043 if (pI810->agpAcquired == TRUE) 1044 drmAgpRelease(pI810->drmSubFD); 1045 1046 pI810->backHandle = DRM_AGP_NO_HANDLE; 1047 pI810->zHandle = DRM_AGP_NO_HANDLE; 1048 pI810->cursorHandle = DRM_AGP_NO_HANDLE; 1049 pI810->xvmcHandle = DRM_AGP_NO_HANDLE; 1050 pI810->sysmemHandle = DRM_AGP_NO_HANDLE; 1051 pI810->agpAcquired = FALSE; 1052 pI810->dcacheHandle = DRM_AGP_NO_HANDLE; 1053 1054 DRICloseScreen(pScreen); 1055 1056 if (pI810->pDRIInfo) { 1057 if (pI810->pDRIInfo->devPrivate) { 1058 xfree(pI810->pDRIInfo->devPrivate); 1059 pI810->pDRIInfo->devPrivate = NULL; 1060 } 1061 DRIDestroyInfoRec(pI810->pDRIInfo); 1062 pI810->pDRIInfo = NULL; 1063 } 1064 if (pI810->pVisualConfigs) 1065 xfree(pI810->pVisualConfigs); 1066 if (pI810->pVisualConfigsPriv) 1067 xfree(pI810->pVisualConfigsPriv); 1068} 1069 1070static Bool 1071I810CreateContext(ScreenPtr pScreen, VisualPtr visual, 1072 drm_context_t hwContext, void *pVisualConfigPriv, 1073 DRIContextType contextStore) 1074{ 1075 return TRUE; 1076} 1077 1078static void 1079I810DestroyContext(ScreenPtr pScreen, drm_context_t hwContext, 1080 DRIContextType contextStore) 1081{ 1082} 1083 1084Bool 1085I810DRIFinishScreenInit(ScreenPtr pScreen) 1086{ 1087 I810SAREARec *sPriv = (I810SAREARec *) DRIGetSAREAPrivate(pScreen); 1088 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1089 I810Ptr info = I810PTR(pScrn); 1090 1091 memset(sPriv, 0, sizeof(*sPriv)); 1092 1093 /* Have shadow run only while there is 3d active. 1094 */ 1095 if (info->allowPageFlip && info->drmMinor >= 3) { 1096 ShadowFBInit( pScreen, I810DRIRefreshArea ); 1097 } 1098 else 1099 info->allowPageFlip = 0; 1100 return DRIFinishScreenInit(pScreen); 1101} 1102 1103void 1104I810DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, 1105 DRIContextType oldContextType, void *oldContext, 1106 DRIContextType newContextType, void *newContext) 1107{ 1108 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1109 I810Ptr pI810 = I810PTR(pScrn); 1110 1111 if (syncType == DRI_3D_SYNC && 1112 oldContextType == DRI_2D_CONTEXT && newContextType == DRI_2D_CONTEXT) { 1113 if (I810_DEBUG & DEBUG_VERBOSE_DRI) 1114 ErrorF("I810DRISwapContext (in)\n"); 1115 1116 if (!pScrn->vtSema) 1117 return; 1118 pI810->LockHeld = 1; 1119 I810RefreshRing(pScrn); 1120 } else if (syncType == DRI_2D_SYNC && 1121 oldContextType == DRI_NO_CONTEXT && 1122 newContextType == DRI_2D_CONTEXT) { 1123 pI810->LockHeld = 0; 1124 if (I810_DEBUG & DEBUG_VERBOSE_DRI) 1125 ErrorF("I810DRISwapContext (out)\n"); 1126 } else if (I810_DEBUG & DEBUG_VERBOSE_DRI) 1127 ErrorF("I810DRISwapContext (other)\n"); 1128} 1129 1130static void 1131I810DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) 1132{ 1133 ScreenPtr pScreen = pWin->drawable.pScreen; 1134 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1135 I810Ptr pI810 = I810PTR(pScrn); 1136 BoxPtr pbox = REGION_RECTS(prgn); 1137 int nbox = REGION_NUM_RECTS(prgn); 1138 1139 if (I810_DEBUG & DEBUG_VERBOSE_DRI) 1140 ErrorF("I810DRIInitBuffers\n"); 1141 1142 I810SetupForSolidFill(pScrn, 0, GXcopy, -1); 1143 while (nbox--) { 1144 I810SelectBuffer(pScrn, I810_SELECT_BACK); 1145 I810SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, 1146 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); 1147 pbox++; 1148 } 1149 1150 /* Clear the depth buffer - uses 0xffff rather than 0. 1151 */ 1152 pbox = REGION_RECTS(prgn); 1153 nbox = REGION_NUM_RECTS(prgn); 1154 I810SelectBuffer(pScrn, I810_SELECT_DEPTH); 1155 I810SetupForSolidFill(pScrn, 0xffff, GXcopy, -1); 1156 while (nbox--) { 1157 I810SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, 1158 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); 1159 pbox++; 1160 } 1161 I810SelectBuffer(pScrn, I810_SELECT_FRONT); 1162 1163 if (pI810->AccelInfoRec) 1164 pI810->AccelInfoRec->NeedToSync = TRUE; 1165} 1166 1167/* This routine is a modified form of XAADoBitBlt with the calls to 1168 * ScreenToScreenBitBlt built in. My routine has the prgnSrc as source 1169 * instead of destination. My origin is upside down so the ydir cases 1170 * are reversed. 1171 * 1172 * KW: can you believe that this is called even when a 2d window moves? 1173 */ 1174static void 1175I810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, 1176 RegionPtr prgnSrc, CARD32 index) 1177{ 1178 ScreenPtr pScreen = pParent->drawable.pScreen; 1179 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1180 I810Ptr pI810 = I810PTR(pScrn); 1181 BoxPtr pboxTmp, pboxNext, pboxBase; 1182 DDXPointPtr pptTmp, pptNew2 = NULL; 1183 int xdir, ydir; 1184 1185 int screenwidth = pScrn->virtualX; 1186 int screenheight = pScrn->virtualY; 1187 1188 BoxPtr pbox = REGION_RECTS(prgnSrc); 1189 int nbox = REGION_NUM_RECTS(prgnSrc); 1190 1191 BoxPtr pboxNew1 = NULL; 1192 BoxPtr pboxNew2 = NULL; 1193 DDXPointPtr pptNew1 = NULL; 1194 DDXPointPtr pptSrc = &ptOldOrg; 1195 1196 int dx = pParent->drawable.x - ptOldOrg.x; 1197 int dy = pParent->drawable.y - ptOldOrg.y; 1198 1199 /* If the copy will overlap in Y, reverse the order */ 1200 if (dy > 0) { 1201 ydir = -1; 1202 1203 if (nbox > 1) { 1204 /* Keep ordering in each band, reverse order of bands */ 1205 pboxNew1 = (BoxPtr) xalloc(sizeof(BoxRec) * nbox); 1206 if (!pboxNew1) 1207 return; 1208 pptNew1 = (DDXPointPtr) xalloc(sizeof(DDXPointRec) * nbox); 1209 if (!pptNew1) { 1210 xfree(pboxNew1); 1211 return; 1212 } 1213 pboxBase = pboxNext = pbox + nbox - 1; 1214 while (pboxBase >= pbox) { 1215 while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1)) 1216 pboxNext--; 1217 pboxTmp = pboxNext + 1; 1218 pptTmp = pptSrc + (pboxTmp - pbox); 1219 while (pboxTmp <= pboxBase) { 1220 *pboxNew1++ = *pboxTmp++; 1221 *pptNew1++ = *pptTmp++; 1222 } 1223 pboxBase = pboxNext; 1224 } 1225 pboxNew1 -= nbox; 1226 pbox = pboxNew1; 1227 pptNew1 -= nbox; 1228 pptSrc = pptNew1; 1229 } 1230 } else { 1231 /* No changes required */ 1232 ydir = 1; 1233 } 1234 1235 /* If the regions will overlap in X, reverse the order */ 1236 if (dx > 0) { 1237 xdir = -1; 1238 1239 if (nbox > 1) { 1240 /*reverse orderof rects in each band */ 1241 pboxNew2 = (BoxPtr) xalloc(sizeof(BoxRec) * nbox); 1242 pptNew2 = (DDXPointPtr) xalloc(sizeof(DDXPointRec) * nbox); 1243 if (!pboxNew2 || !pptNew2) { 1244 if (pptNew2) 1245 xfree(pptNew2); 1246 if (pboxNew2) 1247 xfree(pboxNew2); 1248 if (pboxNew1) { 1249 xfree(pptNew1); 1250 xfree(pboxNew1); 1251 } 1252 return; 1253 } 1254 pboxBase = pboxNext = pbox; 1255 while (pboxBase < pbox + nbox) { 1256 while ((pboxNext < pbox + nbox) && (pboxNext->y1 == pboxBase->y1)) 1257 pboxNext++; 1258 pboxTmp = pboxNext; 1259 pptTmp = pptSrc + (pboxTmp - pbox); 1260 while (pboxTmp != pboxBase) { 1261 *pboxNew2++ = *--pboxTmp; 1262 *pptNew2++ = *--pptTmp; 1263 } 1264 pboxBase = pboxNext; 1265 } 1266 pboxNew2 -= nbox; 1267 pbox = pboxNew2; 1268 pptNew2 -= nbox; 1269 pptSrc = pptNew2; 1270 } 1271 } else { 1272 /* No changes are needed */ 1273 xdir = 1; 1274 } 1275 1276 /* SelectBuffer isn't really a good concept for the i810. 1277 */ 1278 I810EmitFlush(pScrn); 1279 I810SetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, -1, -1); 1280 for (; nbox--; pbox++) { 1281 1282 int x1 = pbox->x1; 1283 int y1 = pbox->y1; 1284 int destx = x1 + dx; 1285 int desty = y1 + dy; 1286 int w = pbox->x2 - x1 + 1; 1287 int h = pbox->y2 - y1 + 1; 1288 1289 if (destx < 0) 1290 x1 -= destx, w += destx, destx = 0; 1291 if (desty < 0) 1292 y1 -= desty, h += desty, desty = 0; 1293 if (destx + w > screenwidth) 1294 w = screenwidth - destx; 1295 if (desty + h > screenheight) 1296 h = screenheight - desty; 1297 if (w <= 0) 1298 continue; 1299 if (h <= 0) 1300 continue; 1301 1302 if (I810_DEBUG & DEBUG_VERBOSE_DRI) 1303 ErrorF("MoveBuffers %d,%d %dx%d dx: %d dy: %d\n", 1304 x1, y1, w, h, dx, dy); 1305 1306 I810SelectBuffer(pScrn, I810_SELECT_BACK); 1307 I810SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); 1308 I810SelectBuffer(pScrn, I810_SELECT_DEPTH); 1309 I810SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); 1310 } 1311 I810SelectBuffer(pScrn, I810_SELECT_FRONT); 1312 I810EmitFlush(pScrn); 1313 1314 if (pboxNew2) { 1315 xfree(pptNew2); 1316 xfree(pboxNew2); 1317 } 1318 if (pboxNew1) { 1319 xfree(pptNew1); 1320 xfree(pboxNew1); 1321 } 1322 1323 if (pI810->AccelInfoRec) 1324 pI810->AccelInfoRec->NeedToSync = TRUE; 1325} 1326 1327 1328/* Use the miext/shadow module to maintain a list of dirty rectangles. 1329 * These are blitted to the back buffer to keep both buffers clean 1330 * during page-flipping when the 3d application isn't fullscreen. 1331 * 1332 * Unlike most use of the shadow code, both buffers are in video memory. 1333 * 1334 * An alternative to this would be to organize for all on-screen drawing 1335 * operations to be duplicated for the two buffers. That might be 1336 * faster, but seems like a lot more work... 1337 */ 1338 1339 1340/* This should be done *before* XAA syncs or fires its buffer. 1341 * Otherwise will have to fire it again??? 1342 */ 1343static void I810DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) 1344{ 1345 I810Ptr pI810 = I810PTR(pScrn); 1346 int i; 1347 I810SAREAPtr pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); 1348 unsigned int br13; 1349 int cpp=2; 1350 1351 1352 /* Don't want to do this when no 3d is active and pages are 1353 * right-way-round 1354 */ 1355 if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0) 1356 return; 1357 1358 br13 = (pI810->auxPitch) | (0xcc << 16); 1359 1360 for (i = 0 ; i < num ; i++, pbox++) { 1361 unsigned int w = min(pbox->y2, pScrn->virtualY-1) - max(pbox->y1, 0) + 1; 1362 unsigned int h = min(pbox->x2, pScrn->virtualX-1) - max(pbox->x1, 0) + 1; 1363 unsigned int dst = max(pbox->x1, 0)*cpp + (max(pbox->y1, 0)*pI810->auxPitch); 1364 1365 BEGIN_LP_RING(6); 1366 1367 OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4); 1368 OUT_RING(br13); 1369 OUT_RING( (h<<16) | (w*cpp) ); 1370 OUT_RING(pI810->BackBuffer.Start + dst); 1371 OUT_RING(br13 & 0xffff); 1372 OUT_RING(dst); 1373 1374 ADVANCE_LP_RING(); 1375 } 1376 1377} 1378 1379static void I810EnablePageFlip(ScreenPtr pScreen) 1380{ 1381 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1382 I810Ptr pI810 = I810PTR(pScrn); 1383 I810SAREAPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); 1384 int cpp=2; 1385 pSAREAPriv->pf_enabled = pI810->allowPageFlip; 1386 pSAREAPriv->pf_active = 0; 1387 1388 if (pI810->allowPageFlip) { 1389 unsigned int br13 = pI810->auxPitch | (0xcc << 16); 1390 1391 BEGIN_LP_RING(6); 1392 1393 OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4); 1394 OUT_RING(br13); 1395 OUT_RING((pScrn->virtualY << 16) | (pScrn->virtualX*cpp)); 1396 OUT_RING(pI810->BackBuffer.Start); 1397 OUT_RING(br13 & 0xFFFF); 1398 OUT_RING(0); 1399 ADVANCE_LP_RING(); 1400 1401 pSAREAPriv->pf_active = 1; 1402 } 1403 1404} 1405 1406static void I810DisablePageFlip(ScreenPtr pScreen) 1407{ 1408 I810SAREAPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); 1409 1410 pSAREAPriv->pf_active=0; 1411} 1412 1413static void I810DRITransitionSingleToMulti3d(ScreenPtr pScreen) 1414{ 1415 /* Tell the clients not to pageflip. How? 1416 * -- Field in sarea, plus bumping the window counters. 1417 * -- DRM needs to cope with Front-to-Back swapbuffers. 1418 */ 1419 I810DisablePageFlip(pScreen); 1420} 1421 1422static void I810DRITransitionMultiToSingle3d(ScreenPtr pScreen) 1423{ 1424 /* Let the remaining 3d app start page flipping again */ 1425 I810EnablePageFlip(pScreen); 1426} 1427 1428static void I810DRITransitionTo3d(ScreenPtr pScreen) 1429{ 1430 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1431 I810Ptr pI810 = I810PTR(pScrn); 1432 1433 I810EnablePageFlip(pScreen); 1434 pI810->have3DWindows = 1; 1435} 1436 1437static void I810DRITransitionTo2d(ScreenPtr pScreen) 1438{ 1439 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1440 I810Ptr pI810 = I810PTR(pScrn); 1441 I810SAREAPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); 1442 1443 /* Try flipping back to the front page if necessary */ 1444 if (pSAREAPriv->pf_current_page == 1) 1445 drmCommandNone(pI810->drmSubFD, DRM_I810_FLIP); 1446 1447 /* Shut down shadowing if we've made it back to the front page */ 1448 if (pSAREAPriv->pf_current_page == 0) { 1449 I810DisablePageFlip(pScreen); 1450 } 1451 pI810->have3DWindows = 0; 1452} 1453 1454Bool 1455I810DRILeave(ScrnInfoPtr pScrn) 1456{ 1457 I810Ptr pI810 = I810PTR(pScrn); 1458 1459 if (pI810->directRenderingEnabled) { 1460 if (pI810->dcacheHandle != 0) 1461 if (drmAgpUnbind(pI810->drmSubFD, pI810->dcacheHandle) != 0) { 1462 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno)); 1463 return FALSE; 1464 } 1465 if (pI810->backHandle != 0) 1466 if (drmAgpUnbind(pI810->drmSubFD, pI810->backHandle) != 0) { 1467 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno)); 1468 return FALSE; 1469 } 1470 if (pI810->zHandle != 0) 1471 if (drmAgpUnbind(pI810->drmSubFD, pI810->zHandle) != 0) { 1472 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno)); 1473 return FALSE; 1474 } 1475 if (pI810->sysmemHandle != 0) 1476 if (drmAgpUnbind(pI810->drmSubFD, pI810->sysmemHandle) != 0) { 1477 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno)); 1478 return FALSE; 1479 } 1480 if (pI810->xvmcHandle != 0) 1481 if (drmAgpUnbind(pI810->drmSubFD, pI810->xvmcHandle) != 0) { 1482 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno)); 1483 return FALSE; 1484 } 1485 if (pI810->cursorHandle != 0) 1486 if (drmAgpUnbind(pI810->drmSubFD, pI810->cursorHandle) != 0) { 1487 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno)); 1488 return FALSE; 1489 } 1490 if (pI810->cursorARGBHandle != 0) 1491 if (drmAgpUnbind(pI810->drmSubFD, pI810->cursorARGBHandle) != 0) { 1492 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno)); 1493 return FALSE; 1494 } 1495 if (pI810->agpAcquired == TRUE) 1496 drmAgpRelease(pI810->drmSubFD); 1497 pI810->agpAcquired = FALSE; 1498 } 1499 return TRUE; 1500} 1501 1502Bool 1503I810DRIEnter(ScrnInfoPtr pScrn) 1504{ 1505 I810Ptr pI810 = I810PTR(pScrn); 1506 1507 if (pI810->directRenderingEnabled) { 1508 1509 if (pI810->agpAcquired == FALSE) 1510 drmAgpAcquire(pI810->drmSubFD); 1511 pI810->agpAcquired = TRUE; 1512 if (pI810->dcacheHandle != 0) 1513 if (drmAgpBind(pI810->drmSubFD, pI810->dcacheHandle, 1514 pI810->DepthOffset) != 0) 1515 return FALSE; 1516 if (pI810->backHandle != 0) 1517 if (drmAgpBind(pI810->drmSubFD, pI810->backHandle, 1518 pI810->BackOffset) != 0) 1519 return FALSE; 1520 if (pI810->zHandle != 0) 1521 if (drmAgpBind(pI810->drmSubFD, pI810->zHandle, 1522 pI810->DepthOffset) != 0) 1523 return FALSE; 1524 if (pI810->sysmemHandle != 0) 1525 if (drmAgpBind(pI810->drmSubFD, pI810->sysmemHandle, 0) != 0) 1526 return FALSE; 1527 if (pI810->xvmcHandle != 0) 1528 if (drmAgpBind(pI810->drmSubFD, pI810->xvmcHandle, 1529 pI810->MC.Start) != 0) 1530 return FALSE; 1531 if (pI810->cursorHandle != 0) 1532 if (drmAgpBind(pI810->drmSubFD, pI810->cursorHandle, 1533 pI810->CursorStart) != 0) 1534 return FALSE; 1535 if (pI810->cursorARGBHandle != 0) 1536 if (drmAgpBind(pI810->drmSubFD, pI810->cursorARGBHandle, 1537 pI810->CursorARGBStart) != 0) 1538 return FALSE; 1539 } 1540 return TRUE; 1541} 1542