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