summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuc Verhaegen <libv@skynet.be>2005-12-22 21:11:44 +0000
committerLuc Verhaegen <libv@skynet.be>2005-12-22 21:11:44 +0000
commit1472c8f242adf5da236b3e401c7afcdbc94b58a7 (patch)
tree91abf041360f18e11b999e39eda4b53d74499661
parentb6eb2568a1ed12472acd17fbc8a90fcf5a11dae4 (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.c67
-rw-r--r--src/via_driver.c16
-rw-r--r--src/via_driver.h3
-rw-r--r--src/via_video.c103
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;
}
/*