summaryrefslogtreecommitdiff
path: root/driver/xf86-video-savage/src/savage_video.c
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2009-11-22 17:48:11 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2009-11-22 17:48:11 +0000
commitef1822cea93f7497da13487910e25d1977d2d9c2 (patch)
treeda25a9cfd55be568bf4b90e52552c07453ff824c /driver/xf86-video-savage/src/savage_video.c
parent3658335d05c05cca47a13948a009d212f63dee13 (diff)
Update to xf86-video-savage 2.3.1
Diffstat (limited to 'driver/xf86-video-savage/src/savage_video.c')
-rw-r--r--driver/xf86-video-savage/src/savage_video.c196
1 files changed, 155 insertions, 41 deletions
diff --git a/driver/xf86-video-savage/src/savage_video.c b/driver/xf86-video-savage/src/savage_video.c
index a68c19103..cf51ba06b 100644
--- a/driver/xf86-video-savage/src/savage_video.c
+++ b/driver/xf86-video-savage/src/savage_video.c
@@ -241,9 +241,16 @@ typedef struct {
Time freeTime;
int lastKnownPitch;
- int size;
- void *video_memory;
- int video_offset;
+ void *video_memory; /* opaque memory management information structure */
+ CARD32 video_offset; /* offset in video memory of packed YUV buffer */
+
+ void *video_planarmem; /* opaque memory management information structure */
+ CARD32 video_planarbuf; /* offset in video memory of planar YV12 buffer */
+
+ Bool tried_agp; /* TRUE if AGP allocation has been tried */
+ CARD32 agpBase; /* Physical address of aperture base */
+ CARD32 agpBufferOffset; /* Offset of buffer in AGP memory, or 0 if unavailable */
+ drmAddress agpBufferMap; /* Mapping of AGP buffer in process memory, or NULL */
} SavagePortPrivRec, *SavagePortPrivPtr;
@@ -1028,7 +1035,8 @@ static void
SavageStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
{
SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
- /*SavagePtr psav = SAVPTR(pScrn); */
+ SavagePtr psav = SAVPTR(pScrn);
+ ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
xf86ErrorFVerb(XVTRACE,"SavageStopVideo\n");
@@ -1037,11 +1045,29 @@ SavageStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
if(shutdown) {
/*SavageClipVWindow(pScrn);*/
SavageStreamsOff( pScrn );
+
+ if (pPriv->agpBufferMap != NULL) {
+ SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
+
+ /* 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;
+ }
+
if (pPriv->video_memory != NULL) {
SavageFreeMemory(pScrn, pPriv->video_memory);
pPriv->video_memory = NULL;
}
+ if (pPriv->video_planarmem != NULL) {
+ SavageFreeMemory(pScrn, pPriv->video_planarmem);
+ pPriv->video_planarmem = NULL;
+ }
pPriv->videoStatus = 0;
+ pPriv->tried_agp = FALSE;
} else {
if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
pPriv->videoStatus |= OFF_TIMER;
@@ -1170,34 +1196,37 @@ SavageCopyPlanarDataBCI(
unsigned char *srcV, /* V */
unsigned char *srcU, /* U */
unsigned char *dst,
+ unsigned char * planarPtr,
+ unsigned long planarOffset,
int srcPitch, int srcPitch2,
int dstPitch,
- int h,int w)
+ int h,int w,
+ Bool isAGP)
{
SavagePtr psav = SAVPTR(pScrn);
- /* half of the dest buffer for copying the YVU data to it ??? */
- unsigned char *dstCopy = (unsigned char *)(((unsigned long)dst
- + dstPitch * h
- + 0x0f) & ~0x0f);
+
/* for pixel transfer */
- unsigned long offsetY = (unsigned long)dstCopy - (unsigned long)psav->FBBase;
+ unsigned long offsetY = planarOffset;
unsigned long offsetV = offsetY + srcPitch * h;
unsigned long offsetU = offsetV + srcPitch2 * (h>>1);
unsigned long dstOffset = (unsigned long)dst - (unsigned long)psav->FBBase;
int i;
+ unsigned char memType;
BCI_GET_PTR;
/* copy Y planar */
- memcpy(dstCopy, srcY, srcPitch * h);
+ memcpy(planarPtr, srcY, srcPitch * h);
/* copy V planar */
- dstCopy = dstCopy + srcPitch * h;
- memcpy(dstCopy, srcV, srcPitch2 * (h>>1));
+ planarPtr = planarPtr + srcPitch * h;
+ memcpy(planarPtr, srcV, srcPitch2 * (h>>1));
/* copy U planar */
- dstCopy = dstCopy + srcPitch2 * (h>>1);
- memcpy(dstCopy, srcU, srcPitch2 * (h>>1));
+ planarPtr = planarPtr + srcPitch2 * (h>>1);
+ memcpy(planarPtr, srcU, srcPitch2 * (h>>1));
+
+ memType = isAGP ? 3 : 0;
/*
* Transfer pixel data from one memory location to another location
@@ -1217,23 +1246,18 @@ SavageCopyPlanarDataBCI(
w = (w+0xf)&0xff0;
psav->WaitQueue(psav,11);
- BCI_SEND(0x96070051);
- BCI_SEND(offsetY);
-
+ BCI_SEND(BCI_SET_REGISTER | BCI_SET_REGISTER_COUNT(7) | 0x51);
+ BCI_SEND(offsetY | memType);
BCI_SEND(dstOffset);
-
BCI_SEND(((h-1)<<16)|((w-1)>>3));
-
BCI_SEND(dstPitch >> 3);
-
-
- BCI_SEND(offsetU);
- BCI_SEND(offsetV);
-
+ BCI_SEND(offsetU | memType);
+ BCI_SEND(offsetV | memType);
BCI_SEND((srcPitch2 << 16)| srcPitch2);
- BCI_SEND(0x96010050);
+ BCI_SEND(BCI_SET_REGISTER | BCI_SET_REGISTER_COUNT(1) | 0x50);
BCI_SEND(0x00200003 | srcPitch);
+
BCI_SEND(0xC0170000);
}
@@ -1304,6 +1328,8 @@ SavageVideoSave(ScreenPtr pScreen, ExaOffscreenArea *area)
if (pPriv->video_memory == area)
pPriv->video_memory = NULL;
+ if (pPriv->video_planarmem == area)
+ pPriv->video_planarmem = NULL;
}
static CARD32
@@ -1840,6 +1866,16 @@ SavageDisplayVideo2000(
#endif
}
+static void
+SavageFillKeyHelper(DrawablePtr pDraw, uint32_t colorKey, RegionPtr clipBoxes)
+{
+#if HAVE_XV_DRAWABLE_HELPER
+ xf86XVFillKeyHelperDrawable(pDraw, colorKey, clipBoxes);
+#else
+ xf86XVFillKeyHelper(pDraw->pScreen, colorKey, clipBoxes);
+#endif
+}
+
static int
SavagePutImage(
ScrnInfoPtr pScrn,
@@ -1860,6 +1896,7 @@ SavagePutImage(
unsigned char *dst_start;
int pitch, new_size, offset, offsetV=0, offsetU=0;
int srcPitch, srcPitch2=0, dstPitch;
+ int planarFrameSize;
int top, left, npixels, nlines;
BoxRec dstBox;
CARD32 tmp;
@@ -1895,8 +1932,8 @@ SavagePutImage(
pitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3;
+ /* All formats directly displayable by Savage are packed and 2 bytes per pixel */
dstPitch = ((width << 1) + 15) & ~15;
- /*new_h = ((dstPitch * height) + pitch - 1) / pitch;*/
new_size = dstPitch * height;
switch(id) {
@@ -1923,17 +1960,78 @@ SavagePutImage(
break;
}
+ /* Calculate required memory for all planar frames */
+ planarFrameSize = 0;
if (srcPitch2 != 0 && S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv) {
- new_size = ((new_size + 0xF) & ~0xF) + srcPitch * height + srcPitch2 * height;
+ new_size = ((new_size + 0xF) & ~0xF);
+ planarFrameSize = srcPitch * height + srcPitch2 * height;
+ }
+
+ /* Check whether AGP buffers can be allocated. If not, fall back to ordinary
+ upload to framebuffer (slower) */
+ if (!pPriv->tried_agp && !psav->IsPCI && psav->drmFD > 0 && psav->DRIServerInfo != NULL) {
+ int ret;
+ SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
+
+ pPriv->tried_agp = TRUE;
+ if (pSAVAGEDRIServer->agpXVideo.size >= max(new_size, planarFrameSize)) {
+ if (pSAVAGEDRIServer->agpXVideo.map == NULL &&
+ drmMap( psav->drmFD,
+ pSAVAGEDRIServer->agpXVideo.handle,
+ pSAVAGEDRIServer->agpXVideo.size,
+ &pSAVAGEDRIServer->agpXVideo.map ) < 0 ) {
+
+ xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] XVideo: Could not map agpXVideo \n" );
+ pPriv->agpBufferOffset = 0;
+ pPriv->agpBufferMap = NULL;
+ } else {
+ pPriv->agpBufferMap = pSAVAGEDRIServer->agpXVideo.map;
+ pPriv->agpBufferOffset = pSAVAGEDRIServer->agpXVideo.offset;
+ pPriv->agpBase = drmAgpBase(psav->drmFD);
+#if 0
+ xf86DrvMsg( pScreen->myNum, X_INFO,
+ "[agp] agpXVideo mapped at 0x%08lx aperture=0x%08x offset=0x%08lx\n",
+ (unsigned long)pPriv->agpBufferMap, pPriv->agpBase, pPriv->agpBufferOffset);
+#endif
+ }
+ } else {
+ /* This situation is expected if AGPforXv is disabled, otherwise report. */
+ if (pSAVAGEDRIServer->agpXVideo.size > 0) {
+ xf86DrvMsg( pScreen->myNum, X_ERROR,
+ "[agp] XVideo: not enough space in buffer (got %ld bytes, required %ld bytes).\n",
+ pSAVAGEDRIServer->agpXVideo.size, max(new_size, planarFrameSize));
+ }
+ pPriv->agpBufferMap = NULL;
+ pPriv->agpBufferOffset = 0;
+ }
}
-/* if(!(pPriv->area = SavageAllocateMemory(pScrn, pPriv->area, new_h)))
- return BadAlloc;*/
- pPriv->video_offset = SavageAllocateMemory(pScrn, &pPriv->video_memory,
- new_size);
+
+ /* Buffer for final packed frame */
+ pPriv->video_offset = SavageAllocateMemory(
+ pScrn, &pPriv->video_memory,
+ new_size);
if (pPriv->video_offset == 0)
return BadAlloc;
+ /* Packed format cases */
+ if (planarFrameSize == 0) {
+ pPriv->video_planarbuf = 0;
+
+ /* Planar format cases */
+ } else {
+ /* Hardware-assisted planar conversion only works on 16-byte aligned addresses */
+ pPriv->video_planarbuf = SavageAllocateMemory(
+ pScrn, &pPriv->video_planarmem,
+ ((planarFrameSize + 0xF) & ~0xF));
+ if (pPriv->video_planarbuf != 0) {
+ /* TODO: stop any pending conversions when buffers change... */
+ pPriv->video_planarbuf = ((pPriv->video_planarbuf + 0xF) & ~0xF);
+ } else {
+ /* Fallback using software conversion */
+ }
+ }
+
/* copy data */
top = y1 >> 16;
left = (x1 >> 16) & ~1;
@@ -1941,7 +2039,6 @@ SavagePutImage(
left <<= 1;
offset = (pPriv->video_offset) + (top * dstPitch);
- /*offset = pPriv->area->box.y1 * psav->lDelta;*/
dst_start = (psav->FBBase + ((offset + left) & ~BASE_PAD));
switch(id) {
@@ -1952,13 +2049,30 @@ SavagePutImage(
offsetU += tmp;
offsetV += tmp;
nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
- if (S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv && (npixels & 0xF) == 0) {
- SavageCopyPlanarDataBCI(
- pScrn,
- buf + (top * srcPitch) + (left >> 1),
- buf + offsetV,
- buf + offsetU,
- dst_start, srcPitch, srcPitch2, dstPitch, nlines, npixels);
+ if (S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv && (npixels & 0xF) == 0 && pPriv->video_planarbuf != 0) {
+ if (pPriv->agpBufferMap != NULL) {
+ /* Using copy to AGP memory */
+ SavageCopyPlanarDataBCI(
+ pScrn,
+ buf + (top * srcPitch) + (left >> 1),
+ buf + offsetV,
+ buf + offsetU,
+ dst_start,
+ pPriv->agpBufferMap,
+ pPriv->agpBase + pPriv->agpBufferOffset,
+ srcPitch, srcPitch2, dstPitch, nlines, npixels, TRUE);
+ } else {
+ /* Using ordinary copy to framebuffer */
+ SavageCopyPlanarDataBCI(
+ pScrn,
+ buf + (top * srcPitch) + (left >> 1),
+ buf + offsetV,
+ buf + offsetU,
+ dst_start,
+ (unsigned char *)psav->FBBase + pPriv->video_planarbuf,
+ pPriv->video_planarbuf,
+ srcPitch, srcPitch2, dstPitch, nlines, npixels, FALSE);
+ }
} else {
SavageCopyPlanarData(
buf + (top * srcPitch) + (left >> 1),
@@ -1988,7 +2102,7 @@ SavagePutImage(
if(!REGION_EQUAL(pScreen, &pPriv->clip, clipBoxes)) {
REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
/* draw these */
- xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
+ SavageFillKeyHelper(pDraw, pPriv->colorKey, clipBoxes);
}