📄 radeon_dri.c
字号:
RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *buf = info->FB + info->depthOffset; int xstart, xend, xdir; int ystart, yend, ydir; int x, y, d; if (xa < xb) xdir = -1, xstart = w-1, xend = 0; else xdir = 1, xstart = 0, xend = w-1; if (ya < yb) ydir = -1, ystart = h-1, yend = 0; else ydir = 1, ystart = 0, yend = h-1; switch (pScrn->bitsPerPixel) { case 16: for (x = xstart; x != xend; x += xdir) { for (y = ystart; y != yend; y += ydir) { READ_DEPTH16(d, xa+x, ya+y); WRITE_DEPTH16(xb+x, yb+y, d); } } break; case 32: for (x = xstart; x != xend; x += xdir) { for (y = ystart; y != yend; y += ydir) { READ_DEPTH32(d, xa+x, ya+y); WRITE_DEPTH32(xb+x, yb+y, d); } } break; default: break; }}/* Initialize the state of the back and depth buffers */static void RADEONDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 indx){ /* NOOP. There's no need for the 2d driver to be clearing buffers * for the 3d client. It knows how to do that on its own. */}/* Copy the back and depth buffers when the X server moves a window. * * This routine is a modified form of XAADoBitBlt with the calls to * ScreenToScreenBitBlt built in. My routine has the prgnSrc as source * instead of destination. My origin is upside down so the ydir cases * are reversed. */static void RADEONDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, RegionPtr prgnSrc, CARD32 indx){ ScreenPtr pScreen = pParent->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); BoxPtr pboxTmp, pboxNext, pboxBase; DDXPointPtr pptTmp; int xdir, ydir; int screenwidth = pScrn->virtualX; int screenheight = pScrn->virtualY; BoxPtr pbox = REGION_RECTS(prgnSrc); int nbox = REGION_NUM_RECTS(prgnSrc); BoxPtr pboxNew1 = NULL; BoxPtr pboxNew2 = NULL; DDXPointPtr pptNew1 = NULL; DDXPointPtr pptNew2 = NULL; DDXPointPtr pptSrc = &ptOldOrg; int dx = pParent->drawable.x - ptOldOrg.x; int dy = pParent->drawable.y - ptOldOrg.y; /* If the copy will overlap in Y, reverse the order */ if (dy > 0) { ydir = -1; if (nbox > 1) { /* Keep ordering in each band, reverse order of bands */ pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox); if (!pboxNew1) return; pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox); if (!pptNew1) { DEALLOCATE_LOCAL(pboxNew1); return; } pboxBase = pboxNext = pbox+nbox-1; while (pboxBase >= pbox) { while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1)) pboxNext--; pboxTmp = pboxNext+1; pptTmp = pptSrc + (pboxTmp - pbox); while (pboxTmp <= pboxBase) { *pboxNew1++ = *pboxTmp++; *pptNew1++ = *pptTmp++; } pboxBase = pboxNext; } pboxNew1 -= nbox; pbox = pboxNew1; pptNew1 -= nbox; pptSrc = pptNew1; } } else { /* No changes required */ ydir = 1; } /* If the regions will overlap in X, reverse the order */ if (dx > 0) { xdir = -1; if (nbox > 1) { /* reverse order of rects in each band */ pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox); pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox); if (!pboxNew2 || !pptNew2) { DEALLOCATE_LOCAL(pptNew2); DEALLOCATE_LOCAL(pboxNew2); DEALLOCATE_LOCAL(pptNew1); DEALLOCATE_LOCAL(pboxNew1); return; } pboxBase = pboxNext = pbox; while (pboxBase < pbox+nbox) { while ((pboxNext < pbox+nbox) && (pboxNext->y1 == pboxBase->y1)) pboxNext++; pboxTmp = pboxNext; pptTmp = pptSrc + (pboxTmp - pbox); while (pboxTmp != pboxBase) { *pboxNew2++ = *--pboxTmp; *pptNew2++ = *--pptTmp; } pboxBase = pboxNext; } pboxNew2 -= nbox; pbox = pboxNew2; pptNew2 -= nbox; pptSrc = pptNew2; } } else { /* No changes are needed */ xdir = 1; } (*info->accel->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, GXcopy, (CARD32)(-1), -1); for (; nbox-- ; pbox++) { int xa = pbox->x1; int ya = pbox->y1; int destx = xa + dx; int desty = ya + dy; int w = pbox->x2 - xa + 1; int h = pbox->y2 - ya + 1; if (destx < 0) xa -= destx, w += destx, destx = 0; if (desty < 0) ya -= desty, h += desty, desty = 0; if (destx + w > screenwidth) w = screenwidth - destx; if (desty + h > screenheight) h = screenheight - desty; if (w <= 0) continue; if (h <= 0) continue; RADEONSelectBuffer(pScrn, RADEON_BACK); (*info->accel->SubsequentScreenToScreenCopy)(pScrn, xa, ya, destx, desty, w, h); if (info->depthMoves) { RADEONSelectBuffer(pScrn, RADEON_DEPTH); RADEONScreenToScreenCopyDepth(pScrn, xa, ya, destx, desty, w, h); } } RADEONSelectBuffer(pScrn, RADEON_FRONT); DEALLOCATE_LOCAL(pptNew2); DEALLOCATE_LOCAL(pboxNew2); DEALLOCATE_LOCAL(pptNew1); DEALLOCATE_LOCAL(pboxNew1); info->accel->NeedToSync = TRUE;}static void RADEONDRIInitGARTValues(RADEONInfoPtr info){ int s, l; info->gartOffset = 0; /* Initialize the CP ring buffer data */ info->ringStart = info->gartOffset; info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE; info->ringSizeLog2QW = RADEONMinBits(info->ringSize*1024*1024/8)-1; info->ringReadOffset = info->ringStart + info->ringMapSize; info->ringReadMapSize = DRM_PAGE_SIZE; /* Reserve space for vertex/indirect buffers */ info->bufStart = info->ringReadOffset + info->ringReadMapSize; info->bufMapSize = info->bufSize*1024*1024; /* Reserve the rest for GART textures */ info->gartTexStart = info->bufStart + info->bufMapSize; s = (info->gartSize*1024*1024 - info->gartTexStart); l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS); if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; info->gartTexMapSize = (s >> l) << l; info->log2GARTTexGran = l;}/* Set AGP transfer mode according to requests and constraints */static Bool RADEONSetAgpMode(RADEONInfoPtr info, ScreenPtr pScreen){ unsigned char *RADEONMMIO = info->MMIO; unsigned long mode = drmAgpGetMode(info->drmFD); /* Default mode */ unsigned long vendor = drmAgpVendorId(info->drmFD); unsigned long device = drmAgpDeviceId(info->drmFD); mode &= ~RADEON_AGP_MODE_MASK; switch (info->agpMode) { case 4: mode |= RADEON_AGP_4X_MODE; case 2: mode |= RADEON_AGP_2X_MODE; case 1: default: mode |= RADEON_AGP_1X_MODE; } if (info->agpFastWrite) mode |= RADEON_AGP_FW_MODE; if ((vendor == PCI_VENDOR_AMD) && (device == PCI_CHIP_AMD761)) { /* Disable fast write for AMD 761 chipset, since they cause * lockups when enabled. */ mode &= ~0x10; /* FIXME: Magic number */ } xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n", mode, vendor, device, info->PciInfo->vendor, info->PciInfo->chipType); if (drmAgpEnable(info->drmFD, mode) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n"); drmAgpRelease(info->drmFD); return FALSE; } /* Workaround for some hardware bugs */ if (info->ChipFamily < CHIP_FAMILY_R200) OUTREG(RADEON_AGP_CNTL, INREG(RADEON_AGP_CNTL) | 0x000e0000); /* Modify the mode if the default mode * is not appropriate for this * particular combination of graphics * card and AGP chipset. */ return TRUE;}/* Initialize Radeon's AGP registers */static void RADEONSetAgpBase(RADEONInfoPtr info){ unsigned char *RADEONMMIO = info->MMIO; OUTREG(RADEON_AGP_BASE, drmAgpBase(info->drmFD));}/* Initialize the AGP state. Request memory for use in AGP space, and * initialize the Radeon registers to point to that memory. */static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen){ int ret; if (drmAgpAcquire(info->drmFD) < 0) { xf86DrvMsg(pScreen->myNum, X_WARNING, "[agp] AGP not available\n"); return FALSE; } if (!RADEONSetAgpMode(info, pScreen)) return FALSE; RADEONDRIInitGARTValues(info); if ((ret = drmAgpAlloc(info->drmFD, info->gartSize*1024*1024, 0, NULL, &info->agpMemHandle)) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret); drmAgpRelease(info->drmFD); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] %d kB allocated with handle 0x%08lx\n", info->gartSize*1024, info->agpMemHandle); if (drmAgpBind(info->drmFD, info->agpMemHandle, info->gartOffset) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not bind\n"); drmAgpFree(info->drmFD, info->agpMemHandle); drmAgpRelease(info->drmFD); return FALSE; } if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize, DRM_AGP, DRM_READ_ONLY, &info->ringHandle) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not add ring mapping\n"); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] ring handle = 0x%08lx\n", info->ringHandle); if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize, (drmAddressPtr)&info->ring) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring\n"); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] Ring mapped at 0x%08lx\n", (unsigned long)info->ring); if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize, DRM_AGP, DRM_READ_ONLY, &info->ringReadPtrHandle) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not add ring read ptr mapping\n"); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] ring read ptr handle = 0x%08lx\n", info->ringReadPtrHandle); if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize, (drmAddressPtr)&info->ringReadPtr) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring read ptr\n"); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] Ring read ptr mapped at 0x%08lx\n", (unsigned long)info->ringReadPtr); if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize, DRM_AGP, 0, &info->bufHandle) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not add vertex/indirect buffers mapping\n"); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] vertex/indirect buffers handle = 0x%08lx\n", info->bufHandle); if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize, (drmAddressPtr)&info->buf) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map vertex/indirect buffers\n"); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] Vertex/indirect buffers mapped at 0x%08lx\n", (unsigned long)info->buf); if (drmAddMap(info->drmFD, info->gartTexStart, info->gartTexMapSize, DRM_AGP, 0, &info->gartTexHandle) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not add GART texture map mapping\n"); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] GART texture map handle = 0x%08lx\n", info->gartTexHandle); if (drmMap(info->drmFD, info->gartTexHandle, info->gartTexMapSize, (drmAddressPtr)&info->gartTex) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map GART texture map\n"); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] GART Texture map mapped at 0x%08lx\n", (unsigned long)info->gartTex); RADEONSetAgpBase(info); return TRUE;}/* Initialize the PCI GART state. Request memory for use in PCI space, * and initialize the Radeon registers to point to that memory. */static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen){ int ret; int flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL; ret = drmScatterGatherAlloc(info->drmFD, info->gartSize*1024*1024, &info->pciMemHandle); if (ret < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Out of memory (%d)\n", ret); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[pci] %d kB allocated with handle 0x%08lx\n", info->gartSize*1024, info->pciMemHandle); RADEONDRIInitGARTValues(info); if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize, DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not add ring mapping\n"); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[pci] ring handle = 0x%08lx\n", info->ringHandle); if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize, (drmAddressPtr)&info->ring) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring\n"); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[pci] Ring mapped at 0x%08lx\n", (unsigned long)info->ring); xf86DrvMsg(pScreen->myNum, X_INFO, "[pci] Ring contents 0x%08lx\n", *(unsigned long *)(pointer)info->ring); if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize, DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not add ring read ptr mapping\n"); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[pci] ring read ptr handle = 0x%08lx\n", info->ringReadPtrHandle); if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize, (drmAddressPtr)&info->ringReadPtr) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring read ptr\n"); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[pci] Ring read ptr mapped at 0x%08lx\n", (unsigned long)info->ringReadPtr); xf86DrvMsg(pScreen->myNum, X_INFO, "[pci] Ring read ptr contents 0x%08lx\n", *(unsigned long *)(pointer)info->ringReadPtr); if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize, DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -