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