diff options
author | Luc Verhaegen <libv@skynet.be> | 2005-12-22 21:11:44 +0000 |
---|---|---|
committer | Luc Verhaegen <libv@skynet.be> | 2005-12-22 21:11:44 +0000 |
commit | 1472c8f242adf5da236b3e401c7afcdbc94b58a7 (patch) | |
tree | 91abf041360f18e11b999e39eda4b53d74499661 | |
parent | b6eb2568a1ed12472acd17fbc8a90fcf5a11dae4 (diff) |
[devel-Add_DMACopy]
- Move DRMVersion to a CARD32. Makes a world of difference when comparing
versions. CARD32 will suffice for at least the next 2 years.
- Add a routine to SwovCopy implementing Thomas Hellstroms DMA blit. This
very dramatically reduces Xv overhead.
-rw-r--r-- | src/via_dri.c | 67 | ||||
-rw-r--r-- | src/via_driver.c | 16 | ||||
-rw-r--r-- | src/via_driver.h | 3 | ||||
-rw-r--r-- | src/via_video.c | 103 |
4 files changed, 172 insertions, 17 deletions
diff --git a/src/via_dri.c b/src/via_dri.c index 58a0b6e..eed6355 100644 --- a/src/via_dri.c +++ b/src/via_dri.c @@ -151,9 +151,8 @@ VIADRIRingBufferInit(ScrnInfoPtr pScrn) if (pVia->agpEnable) { drm_via_dma_init_t ringBufInit; - if (!pVia->drmVersion || ((pVia->drmVersion->version_major <= 1) && - (pVia->drmVersion->version_minor <= 3))) - return FALSE; + if (pVia->drmVersion < 0x010400) + return FALSE; /* * Info frome code-snippet on DRI-DEVEL list; Erdi Chen. @@ -532,6 +531,57 @@ VIAInitVisualConfigs(ScrnInfoPtr pScrn) } /* + * Get DRM version, and do some checks. + */ +static void +ViaDRMGetVersion(ScrnInfoPtr pScrn) +{ + VIAPtr pVia = VIAPTR(pScrn); + drmVersionPtr drmVersion = drmGetVersion(pVia->drmFD); + + VIAFUNC(pScrn->scrnIndex); + + if (!drmVersion) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] unable to retrieve DRM" + " version.\n"); + pVia->drmVersion = 0; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[drm] using DRM driver version %d.%d.%d (%s)\n", + drmVersion->version_major, drmVersion->version_minor, + drmVersion->version_patchlevel, drmVersion->date); + + pVia->drmVersion = (drmVersion->version_major << 16) | + (drmVersion->version_minor << 8) | drmVersion->version_patchlevel; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "drm: 0x%lX\n", pVia->drmVersion); + } + + /* Check wether we can use DMA for copying */ + if (pVia->UseDMACopy) { +#ifdef __linux__ +#ifdef DRM_VIA_DMA_BLIT + if (pVia->drmVersion >= 0x020703) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Using DMA for " + "copying to FB\n"); + else { + pVia->UseDMACopy = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "[drm] Not using DMA for " + "copying to FB (requires at least drm driver < 2.7.3).\n"); + } +#else + pVia->UseDMACopy = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Not using DMA for " + "copying to FB (via_drm.h is too old).\n"); +#endif /* DRM_VIA_DMA_BLIT */ +#else + pVia->UseDMACopy = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Not using DMA for " + "copying to FB (only present in linux drm).\n"); +#endif /* __linux__ */ + } +} + +/* * These only came into existence in xorg in may 2005, so provide * a fallback. See dri.h for more information. */ @@ -679,16 +729,7 @@ VIADRIScreenInit(ScrnInfoPtr pScrn, ScreenPtr pScreen) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] mmio mapped.\n" ); - /* Get DRM version */ - pVia->drmVersion = drmGetVersion(pVia->drmFD); - if (pVia->drmVersion) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "[drm] using DRM driver version %d.%d.%d (%s)\n", - pVia->drmVersion->version_major, pVia->drmVersion->version_minor, - pVia->drmVersion->version_patchlevel, pVia->drmVersion->date); - } else - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] unable to retrieve DRM version.\n"); + ViaDRMGetVersion(pScrn); return TRUE; } diff --git a/src/via_driver.c b/src/via_driver.c index 0d2897f..5319151 100644 --- a/src/via_driver.c +++ b/src/via_driver.c @@ -138,7 +138,8 @@ typedef enum { OPTION_DISABLEIRQ, OPTION_INSECUREDRI, OPTION_AGP_DMA, - OPTION_2D_DMA + OPTION_2D_DMA, + OPTION_USEDMACOPY } VIAOpts; @@ -163,6 +164,7 @@ static OptionInfoRec VIAOptions[] = {OPTION_DISABLEIRQ, "DisableIRQ", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_AGP_DMA, "EnableAGPDMA", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_2D_DMA, "NoAGPFor2D", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_USEDMACOPY, "UseDMACopy", OPTV_BOOLEAN, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; @@ -1022,6 +1024,13 @@ VIAPreInit(ScrnInfoPtr pScrn, int flags) pVia->dma2d = TRUE; } +#ifdef XF86DRI + if (xf86ReturnOptValBool(VIAOptions, OPTION_USEDMACOPY, TRUE)) + pVia->UseDMACopy = TRUE; /* properly checked from DRIScreenInit */ + else +#endif + pVia->UseDMACopy = FALSE; + /* ActiveDevice Option for device selection */ pVia->ActiveDevice = 0x00; if ((s = xf86GetOptValString(VIAOptions, OPTION_ACTIVEDEVICE))) { @@ -1871,6 +1880,11 @@ VIAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) #ifdef XF86DRI pVia->directRenderingEnabled = VIADRIScreenInit(pScrn, pScreen); + if (!pVia->directRenderingEnabled) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Not using DMA for " + "copying to FB (no DRI)\n."); + pVia->UseDMACopy = FALSE; + } #endif ViaDebug(scrnIndex, "- Visuals set up\n"); diff --git a/src/via_driver.h b/src/via_driver.h index 30e4645..b52bc19 100644 --- a/src/via_driver.h +++ b/src/via_driver.h @@ -226,7 +226,7 @@ typedef struct _VIA { Bool directRenderingEnabled; DRIInfoPtr pDRIInfo; int drmFD; - drmVersionPtr drmVersion; + CARD32 drmVersion; /* major << 16 | minor << 8 | patch */ int numVisualConfigs; __GLXvisualConfig* pVisualConfigs; VIAConfigPrivPtr pVisualConfigsPriv; @@ -242,6 +242,7 @@ typedef struct _VIA { Bool DRIIrqEnable; Bool agpEnable; Bool dma2d; + Bool UseDMACopy; CARD8 ActiveDevice; /* Option */ diff --git a/src/via_video.c b/src/via_video.c index 94c579b..d879ecf 100644 --- a/src/via_video.c +++ b/src/via_video.c @@ -1655,12 +1655,111 @@ RegionsEqual(ScreenPtr pScreen, RegionPtr A, RegionPtr B) #endif /* !REGION_EQUAL */ /* + * There is no via_drm.h versioning so we need to revert to using defines + * directly.. + */ +#ifdef DRM_VIA_DMA_BLIT +/* + * Clean Xv code has the client align data for the driver and thus the hardware. + * This means that a block needs to be dmaed over, pitch alignment has already + * been taken care of. The DRM side will be adapted to do this more efficiently. + */ +static Bool +ViaSwovCopyDMA(VIAPtr pVia, struct ViaMem *Mem, unsigned char *buf) +{ + struct ViaXvPort *Port = pVia->Swov->Port; + unsigned char *aligned_buf, *new_buf = NULL; + drm_via_dmablit_t blit; + drm_via_blitsync_t *sync = &(blit.sync); + short width, height; + int error, i; + + height = Port->Height; + width = Mem->Size / Port->Height; + + /* reduce the amount of copies needed - work around unneccessary + * restrictions as best as possible*/ + i = 4096 / width; + while (i > 1) { + if (!(height % i)) { + width *= i; + height /= i; + break; + } + i--; + } + + /* Everything VIA requires 16byte alignment -- idiots */ + if (((int) buf & 0x0F)) { + ViaDebug(pVia->scrnIndex, "%s: Buffer Misalignment!\n", __FUNCTION__); + new_buf = malloc(Mem->Size + 0x0F); + aligned_buf = (unsigned char *) (((int) new_buf + 0x0F) & ~0x0F); + xf86memcpy(aligned_buf, buf, Mem->Size); + } else + aligned_buf = buf; + + /* hrm */ + blit.num_lines = height; + blit.line_length = width; + blit.fb_addr = Mem->Base; + blit.fb_stride = width; + blit.mem_addr = aligned_buf; + blit.mem_stride = width; + blit.bounce_buffer = 0; /* not implemented anyway */ + blit.to_fb = 1; + + /* shedule this copy */ + error = -EAGAIN; + while (error == -EAGAIN) + error = drmCommandWriteRead(pVia->drmFD, DRM_VIA_DMA_BLIT, &blit, + sizeof(drm_via_dmablit_t)); + + if (error) { + xf86DrvMsg(pVia->scrnIndex, X_ERROR, "%s: DMA copy sheduling failed.\n", + __FUNCTION__); + if (new_buf) + xfree(new_buf); + + return FALSE; + } + + /* wait for this copy to complete */ + error = -EAGAIN; + while (error == -EAGAIN) + error = drmCommandWrite(pVia->drmFD, DRM_VIA_BLIT_SYNC, sync, + sizeof(drm_via_blitsync_t)); + + if (new_buf) + xfree(new_buf); + + if (error) { + xf86DrvMsg(pVia->scrnIndex, X_ERROR, "%s: DMA copy sync failed.\n", + __FUNCTION__); + return FALSE; + } + return TRUE; +} +#endif /* DRM_VIA_DMA_BLIT */ + +/* * */ -__inline__ static void +static Bool ViaSwovCopy(VIAPtr pVia, struct ViaMem *Mem, unsigned char *buf) { - xf86memcpy(pVia->FBBase + Mem->Base, buf, Mem->Size); +#ifdef DRM_VIA_DMA_BLIT + if (pVia->UseDMACopy) { + if (!ViaSwovCopyDMA(pVia, Mem, buf)) { + xf86DrvMsg(pVia->scrnIndex, X_ERROR, "%s: DMA Copy failed. " + "Disabling.\n", __FUNCTION__); + pVia->UseDMACopy = FALSE; + return FALSE; + } + } else +#endif + xf86memcpy(pVia->FBBase + Mem->Base, buf, Mem->Size); + + return TRUE; } /* |