summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/savage.man6
-rw-r--r--src/savage_exa.c67
-rw-r--r--src/savage_video.c11
3 files changed, 78 insertions, 6 deletions
diff --git a/man/savage.man b/man/savage.man
index 822a233..a1cbb1e 100644
--- a/man/savage.man
+++ b/man/savage.man
@@ -180,7 +180,7 @@ and twister (use BCI for Xv); off for savage4 (do not use the BCI for Xv).
Instructs the BCI Xv pixel formatter to use AGP memory as a scratch buffer.
Ordinarily the BCI formatter uses a an area in framebuffer memory to hold
YV12 planar data to be converted for display. This requires a somewhat expensive
-upload of YV12 data to framebuffer memory. The \*qAGPforXv\*q causes the BCI
+upload of YV12 data to framebuffer memory. The \*qAGPforXv\*q option causes the BCI
formatter to place the YV12 data in AGP memory instead, which can be uploaded
faster than the framebuffer. Use of this option cuts upload overhead by 25%
according to benchmarks. This option also smooths out most of the shearing
@@ -189,6 +189,10 @@ present when using BCI for pixel conversion. Currently this option is
and is disabled by default. Video width restrictions that apply to \*qBCIforXv\*q
also apply here. Only valid when \*qDRI\*q and \*qBCIforXv\*q are both active,
and only on AGP chipsets. Default: \*qoff\*q.
+.br
+If \*qAccelMethod\*q is set to \*qEXA\*q and \*qAGPforXv\*q is enabled, then the
+driver will also attempt to reuse the AGP scratch buffer for UploadToScreen
+acceleration.
.TP
.BI "Option \*qAGPMode\*q \*q" integer \*q
Set AGP data transfer rate.
diff --git a/src/savage_exa.c b/src/savage_exa.c
index 538e000..08524f0 100644
--- a/src/savage_exa.c
+++ b/src/savage_exa.c
@@ -463,10 +463,73 @@ SavageUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, int
BCI_GET_PTR;
int i, j, dwords, queue, Bpp;
unsigned int cmd;
- CARD32 * srcp;
+ CARD32 * srcp;
+ unsigned int dst_pitch;
+ unsigned int dst_yoffset;
+ int agp_possible;
+ exaWaitSync(pDst->drawable.pScreen);
+
Bpp = pDst->drawable.bitsPerPixel / 8;
+ /* Test for conditions for AGP Mastered Image Transfer (MIT). AGP memory
+ needs to be available, the XVideo AGP needs to be enabled, the
+ framebuffer destination must be a multiple of 32 bytes, and the source
+ pitch must span the entirety of the destination pitch. This last
+ condition allows the code to consider this upload as equivalent to a
+ plain memcpy() call. */
+ dst_pitch = exaGetPixmapPitch(pDst);
+ dst_yoffset = exaGetPixmapOffset(pDst) + y * dst_pitch;
+ agp_possible =
+ (!psav->IsPCI && psav->drmFD > 0 && psav->DRIServerInfo != NULL &&
+ psav->DRIServerInfo->agpXVideo.size > 0 &&
+ x == 0 && src_pitch == dst_pitch && w * Bpp == dst_pitch &&
+ (dst_yoffset & 0x1f) == 0);
+
+ if (agp_possible) {
+ SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
+ if (pSAVAGEDRIServer->agpXVideo.map != NULL ||
+ 0 <= drmMap( psav->drmFD,
+ pSAVAGEDRIServer->agpXVideo.handle,
+ pSAVAGEDRIServer->agpXVideo.size,
+ &pSAVAGEDRIServer->agpXVideo.map)) {
+
+ unsigned char * agpMap = pSAVAGEDRIServer->agpXVideo.map;
+ unsigned int agpOffset = drmAgpBase(psav->drmFD) + pSAVAGEDRIServer->agpXVideo.offset;
+ unsigned int bytesTotal = dst_pitch * h;
+
+ while (bytesTotal > 0) {
+ unsigned int bytesTransfer =
+ (bytesTotal > pSAVAGEDRIServer->agpXVideo.size)
+ ? pSAVAGEDRIServer->agpXVideo.size
+ : bytesTotal;
+ unsigned int qwordsTransfer = bytesTransfer >> 3;
+
+ /* Copy source into AGP buffer */
+ memcpy(agpMap, src, bytesTransfer);
+
+ psav->WaitQueue(psav,6);
+ BCI_SEND(BCI_SET_REGISTER | BCI_SET_REGISTER_COUNT(2) | 0x51);
+ BCI_SEND(agpOffset | 3); /* Source buffer in AGP memory */
+ BCI_SEND(dst_yoffset); /* Destination buffer in framebuffer */
+
+ BCI_SEND(BCI_SET_REGISTER | BCI_SET_REGISTER_COUNT(1) | 0x50);
+ BCI_SEND(0x00000002 | ((qwordsTransfer - 1) << 3)); /* Select MIT, sysmem to framebuffer */
+
+ /* I want to wait here for any reads from AGP memory and any
+ framebuffer writes performed by the MIT to stop. */
+ BCI_SEND(0xC0000000 | ((0x08 | 0x01) << 16));
+
+ bytesTotal -= bytesTransfer;
+ src += bytesTransfer;
+ dst_yoffset += bytesTransfer;
+ }
+ exaMarkSync(pDst->drawable.pScreen);
+ return TRUE;
+ }
+ }
+
+ /* If we reach here, AGP transfer is not possible, or failed to drmMap() */
psav->sbd_offset = exaGetPixmapOffset(pDst);
psav->sbd_high = SavageSetBD(psav, pDst);
@@ -515,7 +578,7 @@ SavageUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, int
}
/*exaWaitSync(pDst->drawable.pScreen);*/
-
+ exaMarkSync(pDst->drawable.pScreen);
return TRUE;
}
diff --git a/src/savage_video.c b/src/savage_video.c
index bccb801..cf51ba0 100644
--- a/src/savage_video.c
+++ b/src/savage_video.c
@@ -1048,8 +1048,12 @@ SavageStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
if (pPriv->agpBufferMap != NULL) {
SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
- drmUnmap(pPriv->agpBufferMap, pSAVAGEDRIServer->agpXVideo.size);
- pSAVAGEDRIServer->agpXVideo.map = NULL;
+
+ /* agpXVideo is reused to implement UploadToScreen in EXA */
+ if (!psav->useEXA) {
+ drmUnmap(pPriv->agpBufferMap, pSAVAGEDRIServer->agpXVideo.size);
+ pSAVAGEDRIServer->agpXVideo.map = NULL;
+ }
pPriv->agpBufferMap = NULL;
pPriv->agpBufferOffset = 0;
}
@@ -1971,7 +1975,8 @@ SavagePutImage(
pPriv->tried_agp = TRUE;
if (pSAVAGEDRIServer->agpXVideo.size >= max(new_size, planarFrameSize)) {
- if ( drmMap( psav->drmFD,
+ if (pSAVAGEDRIServer->agpXVideo.map == NULL &&
+ drmMap( psav->drmFD,
pSAVAGEDRIServer->agpXVideo.handle,
pSAVAGEDRIServer->agpXVideo.size,
&pSAVAGEDRIServer->agpXVideo.map ) < 0 ) {