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.
This commit is contained in:
Alex Villacís Lasso
2009-04-11 19:12:31 -05:00
committed by Alex Deucher
parent 0f4369c95b
commit a5ad3e8f50
3 changed files with 78 additions and 6 deletions

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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 ) {