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.
--
perl -e '$x=2.3;printf("%.0f + %.0f = %.0f\n",$x,$x,$x+$x);'
>From f4929b64da2ebc2adaabce7a5da716026449b9d9 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Alex=20Villac=C3=ADs=20Lasso?= <[email protected]>
Date: Sat, 11 Apr 2009 19:12:31 -0500
Subject: [PATCH] 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.
---
man/savage.man | 6 ++++-
src/savage_exa.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++-
src/savage_video.c | 11 ++++++--
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 ) {
--
1.6.0.6
_______________________________________________
xorg mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/xorg