summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex VillacĂ­s Lasso <alex@karlalex.palosanto.com>2009-04-11 19:12:31 -0500
committerAlex Deucher <alexdeucher@gmail.com>2009-05-27 17:59:48 -0400
commita5ad3e8f509ca07c429a43810cc3e2f80e70a1dc (patch)
tree8e500d0ae230c6ccf034a3f5735b77850550dcd8
parent0f4369c95b6ef948743c9b244709e454b8b8ef7f (diff)
Implement use of Mastered Image Transfer through AGP for UploadToScreen EXA acceleration.
Under some conditions (documented in this patch), the UploadToScreen implementation can make use of the AGP scratch buffer used for XVideo as a convenient source for Mastered Image Transfer. The previous implementation is still available as a fallback for when AGP acceleration is not possible. This requires the AGP scratch buffer to be persistent, so the XVideo code is also made aware of an existing DRM mapping for the scratch buffer.
-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 ) {