diff options
author | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2009-11-22 17:48:11 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2009-11-22 17:48:11 +0000 |
commit | ef1822cea93f7497da13487910e25d1977d2d9c2 (patch) | |
tree | da25a9cfd55be568bf4b90e52552c07453ff824c /driver/xf86-video-savage/src/savage_video.c | |
parent | 3658335d05c05cca47a13948a009d212f63dee13 (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.c | 196 |
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); } |