📄 radeon_dri.c
字号:
* registers to start and stop the CP are privileged, only the X server * can start/stop the engine. */static void RADEONLeaveServer(ScreenPtr pScreen){ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); RING_LOCALS; /* The CP is always running, but if we've generated any CP commands * we must flush them to the kernel module now. */ if (info->CPInUse) { RADEON_FLUSH_CACHE(); RADEON_WAIT_UNTIL_IDLE(); RADEONCPReleaseIndirect(pScrn); info->CPInUse = FALSE; }#ifdef USE_EXA info->engineMode = EXA_ENGINEMODE_UNKNOWN;#endif}/* Contexts can be swapped by the X server if necessary. This callback * is currently only used to perform any functions necessary when * entering or leaving the X server, and in the future might not be * necessary. */static void RADEONDRISwapContext(ScreenPtr pScreen, DRISyncType syncType, DRIContextType oldContextType, void *oldContext, DRIContextType newContextType, void *newContext){ if ((syncType==DRI_3D_SYNC) && (oldContextType==DRI_2D_CONTEXT) && (newContextType==DRI_2D_CONTEXT)) { /* Entering from Wakeup */ RADEONEnterServer(pScreen); } if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) && (newContextType==DRI_2D_CONTEXT)) { /* Exiting from Block Handler */ RADEONLeaveServer(pScreen); }}#ifdef USE_XAA/* The Radeon has depth tiling on all the time. Rely on surface regs to * translate the addresses (only works if allowColorTiling is true). *//* 16-bit depth buffer functions */#define WRITE_DEPTH16(_x, _y, d) \ *(CARD16 *)(pointer)(buf + 2*(_x + _y*info->frontPitch)) = (d)#define READ_DEPTH16(d, _x, _y) \ (d) = *(CARD16 *)(pointer)(buf + 2*(_x + _y*info->frontPitch))/* 32-bit depth buffer (stencil and depth simultaneously) functions */#define WRITE_DEPTHSTENCIL32(_x, _y, d) \ *(CARD32 *)(pointer)(buf + 4*(_x + _y*info->frontPitch)) = (d)#define READ_DEPTHSTENCIL32(d, _x, _y) \ (d) = *(CARD32 *)(pointer)(buf + 4*(_x + _y*info->frontPitch))/* Screen to screen copy of data in the depth buffer */static void RADEONScreenToScreenCopyDepth(ScrnInfoPtr pScrn, int xa, int ya, int xb, int yb, int w, int h){ 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_DEPTHSTENCIL32(d, xa+x, ya+y); WRITE_DEPTHSTENCIL32(xb+x, yb+y, d); } } break; default: break; }}#endif /* USE_XAA *//* 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){#ifdef USE_XAA 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; /* XXX: Fix in EXA case. */ if (info->useEXA) return; /* 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; } /* pretty much a hack. */ info->dst_pitch_offset = info->backPitchOffset; if (info->tilingEnabled) info->dst_pitch_offset |= RADEON_DST_TILE_MACRO; (*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; (*info->accel->SubsequentScreenToScreenCopy)(pScrn, xa, ya, destx, desty, w, h); if (info->depthMoves) { RADEONScreenToScreenCopyDepth(pScrn, xa, ya, destx, desty, w, h); } } info->dst_pitch_offset = info->frontPitchOffset;; DEALLOCATE_LOCAL(pptNew2); DEALLOCATE_LOCAL(pboxNew2); DEALLOCATE_LOCAL(pptNew1); DEALLOCATE_LOCAL(pboxNew1); info->accel->NeedToSync = TRUE;#endif /* USE_XAA */}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 + radeon_drm_page_size; info->ringSizeLog2QW = RADEONMinBits(info->ringSize*1024*1024/8)-1; info->ringReadOffset = info->ringStart + info->ringMapSize; info->ringReadMapSize = radeon_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 int vendor = drmAgpVendorId(info->drmFD); unsigned int device = drmAgpDeviceId(info->drmFD); mode &= ~RADEON_AGP_MODE_MASK; if ((mode & RADEON_AGPv3_MODE) && (INREG(RADEON_AGP_STATUS) & RADEON_AGPv3_MODE)) { /* only set one mode bit for AGPv3 */ switch (info->agpMode) { case 8: mode |= RADEON_AGPv3_8X_MODE; break; case 4: default: mode |= RADEON_AGPv3_4X_MODE; } /*TODO: need to take care of other bits valid for v3 mode * currently these bits are not used in all tested cards. */ } else { 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 && (vendor == PCI_VENDOR_AMD) && (device == PCI_CHIP_AMD761)) { /* Disable fast write for AMD 761 chipset, since they cause * lockups when enabled. */ info->agpFastWrite = FALSE; xf86DrvMsg(pScreen->myNum, X_WARNING, "[agp] Not enabling Fast Writes on AMD 761 chipset to avoid " "lockups"); } if (info->agpFastWrite) mode |= RADEON_AGP_FW_MODE; 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -