Little success: I took the neo_video.c from Ralph and added my card into the two case structures (see neo_video.c below).
mpeg2play and xine shows me the video in mpeg format. But when i move another window over wideo output, the video is plitted into stripes. When i try xine with a dvd stream, it craches. ff -- SYNTAGS GmbH, Märkische Str. 237, D-44141 Dortmund, Germany Security, Cryptography, Networks, Software Development http://www.syntags.de mailto:[EMAIL PROTECTED]
#include "neo.h" #include "neo_video.h" #define nElems(x) (sizeof(x) / sizeof(x[0])) #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) #if defined(XvExtension) #include "dixstruct.h" #include "xaa.h" #include "xaalocal.h" static XF86VideoAdaptorPtr NEOSetupVideo(ScreenPtr); static void NEOResetVideo(ScrnInfoPtr); static int NEOPutVideo(ScrnInfoPtr, short, short, short, short, short, short, short, short, RegionPtr, pointer); static void NEOStopVideo(ScrnInfoPtr, pointer, Bool); static int NEOSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); static int NEOGetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer); static void NEOQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, unsigned int *, unsigned int *, pointer); static int NEOPutImage(ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char *, short, short, Bool, RegionPtr, pointer); static int NEOQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *, int *, int *); static Bool RegionsEqual(RegionPtr, RegionPtr); static Bool NEOClipVideo(ScrnInfoPtr, BoxPtr, INT32 *, INT32 *, INT32 *, INT32 *, RegionPtr, INT32, INT32); static void NEODisplayVideo(ScrnInfoPtr, int, int, short, short, int, int, int, int, int, BoxPtr, short, short, short, short); static void NEOInitOffscreenImages(ScreenPtr); static FBLinearPtr NEOAllocateMemory(ScrnInfoPtr, FBLinearPtr, int); static void NEOCopyData(unsigned char *, unsigned char *, int, int, int, int); static void NEOCopyYV12Data(unsigned char *, unsigned char *, unsigned char *, unsigned char *, int, int, int, int, int); static int NEOAllocSurface(ScrnInfoPtr, int, unsigned short, unsigned short, XF86SurfacePtr); static int NEOFreeSurface(XF86SurfacePtr); static int NEODisplaySurface(XF86SurfacePtr, short, short, short, short, short, short, short, short, RegionPtr clipBoxes); static int NEOStopSurface(XF86SurfacePtr); static int NEOGetSurfaceAttribute(ScrnInfoPtr, Atom, INT32 *); static int NEOSetSurfaceAttribute(ScrnInfoPtr, Atom, INT32); static Atom xvColorKey, xvBrightness; void NEOInitVideo(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; NEOPtr nPtr = NEOPTR(pScrn); XF86VideoAdaptorPtr *overlayAdaptors, *newAdaptors = NULL; XF86VideoAdaptorPtr newAdaptor = NULL; int numAdaptors; numAdaptors = xf86XVListGenericAdaptors(pScrn, &overlayAdaptors); if (nPtr->NeoMMIOBase2 != NULL && !nPtr->noAccel){ newAdaptor = NEOSetupVideo(pScreen); NEOInitOffscreenImages(pScreen); } if (newAdaptor){ if (!numAdaptors){ numAdaptors = 1; overlayAdaptors = &newAdaptor; } else { newAdaptors = xalloc((numAdaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); if (newAdaptors){ memcpy(newAdaptors, overlayAdaptors, numAdaptors * sizeof(XF86VideoAdaptorPtr)); newAdaptors[numAdaptors++] = newAdaptor; overlayAdaptors = newAdaptors; } } } if (numAdaptors) xf86XVScreenInit(pScreen, overlayAdaptors, numAdaptors); if (newAdaptors) xfree(newAdaptors); } static XF86VideoEncodingRec NEOVideoEncodings[] = { { NEO_VIDEO_VIDEO, "XV_VIDEO", 1024, 1024, {1, 1} }, { NEO_VIDEO_IMAGE, "XV_IMAGE", 1024, 1024, {1, 1} } }; static XF86VideoFormatRec NEOVideoFormats[] = { { 15, TrueColor }, { 16, TrueColor }, }; static XF86AttributeRec NEOVideoAttributes[] = { { XvSettable | XvGettable, 0x000000, 0xFFFFFF, "XV_COLORKEY" }, { XvSettable | XvGettable, -128, 127, "XV1_BRIGHTNESS" }, }; static XF86ImageRec NEOVideoImages[] = { XVIMAGE_YUY2, XVIMAGE_YV12, XVIMAGE_I420, { FOURCC_RV15, XvRGB, LSBFirst, { 'R', 'V' ,'1', '5', 0x00,'5',0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 16, XvPacked, 1, 15, 0x001F, 0x03E0, 0x7C00, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 'R', 'V', 'B' }, XvTopToBottom }, { FOURCC_RV16, XvRGB, LSBFirst, { 'R', 'V' ,'1', '6', 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 16, XvPacked, 1, 16, 0x001F, 0x07E0, 0xF800, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 'R', 'V', 'B' }, XvTopToBottom } }; static XF86VideoAdaptorPtr NEOSetupVideo(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; NEOPtr nPtr = NEOPTR(pScrn); NEOPortPtr pPriv; XF86VideoAdaptorPtr overlayAdaptor; int i; #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOSetupVideo\n"); #endif if ((overlayAdaptor = xcalloc(1, sizeof(XF86VideoAdaptorRec) + sizeof(DevUnion) + sizeof(NEOPortRec))) == NULL){ return (NULL); } overlayAdaptor->type = XvInputMask | XvImageMask | XvWindowMask | XvOutputMask | XvVideoMask; overlayAdaptor->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; overlayAdaptor->name = "NeoMagic Video Engine"; overlayAdaptor->nEncodings = nElems(NEOVideoEncodings); overlayAdaptor->pEncodings = NEOVideoEncodings; for (i = 0; i < nElems(NEOVideoEncodings); i++){ NEOVideoEncodings[i].width = 1024; NEOVideoEncodings[i].height = 1024; } overlayAdaptor->nFormats = nElems(NEOVideoFormats); overlayAdaptor->pFormats = NEOVideoFormats; overlayAdaptor->nPorts = 1; overlayAdaptor->pPortPrivates = (DevUnion*) &overlayAdaptor[1]; overlayAdaptor->pPortPrivates[0].ptr = (pointer) &overlayAdaptor->pPortPrivates[1]; overlayAdaptor->nAttributes = nElems(NEOVideoAttributes); overlayAdaptor->pAttributes = NEOVideoAttributes; overlayAdaptor->nImages = nElems(NEOVideoImages); overlayAdaptor->pImages = NEOVideoImages; overlayAdaptor->PutVideo = NEOPutVideo; overlayAdaptor->PutStill = NULL; overlayAdaptor->GetVideo = NULL; overlayAdaptor->GetStill = NULL; overlayAdaptor->StopVideo = NEOStopVideo; overlayAdaptor->SetPortAttribute = NEOSetPortAttribute; overlayAdaptor->GetPortAttribute = NEOGetPortAttribute; overlayAdaptor->QueryBestSize = NEOQueryBestSize; overlayAdaptor->PutImage = NEOPutImage; overlayAdaptor->QueryImageAttributes = NEOQueryImageAttributes; pPriv = (NEOPortPtr)overlayAdaptor->pPortPrivates[0].ptr; pPriv->colorKey = nPtr->videoKey; pPriv->videoStatus = 0; pPriv->brightness = 0; REGION_INIT(pScreen, &pPriv->clip, NullBox, 0); nPtr->overlayAdaptor = overlayAdaptor; xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); xvColorKey = MAKE_ATOM("XV_COLORKEY"); NEOResetVideo(pScrn); return (overlayAdaptor); } static void NEOResetVideo(ScrnInfoPtr pScrn) { NEOPtr nPtr = NEOPTR(pScrn); NEOPortPtr pPriv = (NEOPortPtr)nPtr->overlayAdaptor->pPortPrivates[0].ptr; int r, g, b; #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOResetVideo\n"); #endif switch (pScrn->depth){ case 8: OUTGR(0xc6, pPriv->colorKey & 0xff); OUTGR(0xc5, 0x00); OUTGR(0xc7, 0x00); break; default: r = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; g = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; b = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; OUTGR(0xc5, r); OUTGR(0xc6, g); OUTGR(0xc7, b); break; } OUTGR(0xc4, pPriv->brightness); } static int NEOPutVideo(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, short drw_y, short src_w, short src_h, short drw_w, short drw_h, RegionPtr clipBoxes, pointer data) { NEOPortPtr pPriv = (NEOPortPtr)data; NEOPtr nPtr = NEOPTR(pScrn); CARD32 src_pitch, offset; int xscale, yscale; BoxRec dstBox; INT32 x1, y1, x2, y2; int size, bpp; #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: src: %d %d %d %d\n", src_x, src_y, src_w, src_h); xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: drw: %d %d %d %d\n", drw_x, drw_y, drw_w, drw_h); #endif if (src_w > 720) src_w = 720; if (src_h > 576) src_h = 576; x1 = src_x; y1 = src_y; x2 = src_x + src_w; y2 = src_y + src_h; dstBox.x1 = drw_x; dstBox.y1 = drw_y; dstBox.x2 = drw_x + drw_w; dstBox.y2 = drw_y + drw_h; if (!NEOClipVideo(pScrn, &dstBox, &x1, &y1, &x2, &y2, clipBoxes, src_w, src_h)){ return(Success); } #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: %d %d %d %d\n", x1, y1, x2, y2); #endif dstBox.x1 -= pScrn->frameX0; dstBox.y1 -= pScrn->frameY0; dstBox.x2 -= pScrn->frameX0; dstBox.y2 -= pScrn->frameY0; #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: dstBox %d %d %d %d\n", dstBox.x1, dstBox.y1, dstBox.x2, dstBox.y2); #endif bpp = pScrn->bitsPerPixel >> 3; src_pitch = (src_w + 7) & ~7; xscale = 0x1000; if (src_w <= drw_w){ xscale = (src_w * 0x1000 / drw_w) & 0xffff; } yscale = 0x1000; if (src_h <= drw_h){ yscale = (src_h * 0x1000 / drw_h) & 0xffff; } size = src_h * src_pitch * 2; if ((pPriv->linear = NEOAllocateMemory(pScrn, pPriv->linear, size)) == NULL){ return (BadAlloc); } offset = pPriv->linear->offset * bpp; #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: offset=0x%x\n", offset); #endif memset(nPtr->NeoFbBase + offset, 0, size); if (!RegionsEqual(&pPriv->clip, clipBoxes)){ REGION_COPY(pScreen, &pPriv->clip, clipBoxes); XAAFillSolidRects(pScrn, pPriv->colorKey, GXcopy, ~0, REGION_NUM_RECTS(clipBoxes), REGION_RECTS(clipBoxes)); } x1 >>= 16; y1 >>= 16; x2 >>= 16; y2 >>= 16; switch (nPtr->NeoChipset) { default: case NM2160: offset/=2; OUTGR(0xbc, 0x4f); break; case NM2230: OUTGR(0xbc, 0x2e); break; case NM2360: OUTGR(0xbc, 0x2e); break; } OUTGR(0xb1, (((dstBox.x2-1)>>4)&0xf0)|((dstBox.x1>>8)&0x0f)); OUTGR(0xb2, dstBox.x1); OUTGR(0xb3, dstBox.x2-1); OUTGR(0xb4, (((dstBox.y2-1)>>4)&0xf0)|((dstBox.y1>>8)&0x0f)); OUTGR(0xb5, dstBox.y1); OUTGR(0xb6, dstBox.y2-1); OUTGR(0xb7, offset >> 16); OUTGR(0xb8, offset >> 8); OUTGR(0xb9, offset ); OUTGR(0xba, src_pitch >> 8); OUTGR(0xbb, src_pitch); OUTGR(0xc0, xscale >> 8); OUTGR(0xc1, xscale); OUTGR(0xc2, yscale >> 8); OUTGR(0xc3, yscale); OUTGR(0xbf, 0x02); OUTGR(0x0a, 0x21); OUTSR(0x0c, offset ); OUTSR(0x0d, offset >> 8); OUTSR(0x0e, offset >> 16); OUTSR(0x1a, src_pitch); OUTSR(0x1b, src_pitch>>8); OUTSR(0x17, 0+x1); OUTSR(0x18, 0+x2-1); OUTSR(0x19, (((0+x2-1)>>4)&0xf0)|(((0+x1)>>8)&0x0f)); OUTSR(0x14, 14 + y1); OUTSR(0x15, 14 + y2 - 2); OUTSR(0x16, 0); OUTSR(0x1c, 0xfb); OUTSR(0x1d, 0x00); OUTSR(0x1e, 0xe2); OUTSR(0x1f, 0x02); OUTSR(0x09, 0x11); OUTSR(0x0a, 0x00); OUTSR(0x08, 0xa1); #if 0 OUTGR(0x0a, 0x01); #endif OUTGR(0xb0, 0x03); pPriv->videoStatus = CLIENT_VIDEO_ON; return (Success); } static void NEOStopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit) { NEOPortPtr pPriv = (NEOPortPtr)data; NEOPtr nPtr = NEOPTR(pScrn); #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOStopVideo\n"); #endif REGION_EMPTY(pScrn->pScreen, &pPriv->clip); if (exit){ if (pPriv->videoStatus & CLIENT_VIDEO_ON){ #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOStopVideo: stop capture\n"); #endif OUTGR(0xb0, 0x02); OUTGR(0x0a, 0x21); OUTSR(0x08, 0xa0); #if 0 OUTGR(0x0a, 0x01); #endif } if (pPriv->linear != NULL){ xf86FreeOffscreenLinear(pPriv->linear); pPriv->linear = NULL; } pPriv->videoStatus = 0; } else { if (pPriv->videoStatus & CLIENT_VIDEO_ON){ OUTGR(0xb0, 0x02); OUTGR(0x0a, 0x21); OUTSR(0x08, 0xa0); #if 0 OUTGR(0x0a, 0x01); #endif pPriv->videoStatus |= OFF_TIMER; pPriv->offTime = currentTime.milliseconds + OFF_DELAY; } } } static int NEOSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, pointer data) { NEOPortPtr pPriv = (NEOPortPtr)data; NEOPtr nPtr = NEOPTR(pScrn); #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOSetPortAttribute\n"); #endif if (attribute == xvColorKey){ int r, g, b; pPriv->colorKey = value; switch (pScrn->depth){ case 8: OUTGR(0xc6, pPriv->colorKey & 0xff); OUTGR(0xc5, 0x00); OUTGR(0xc7, 0x00); break; default: r = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; g = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; b = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; OUTGR(0xc5, r); OUTGR(0xc6, g); OUTGR(0xc7, b); } } else if (attribute == xvBrightness){ if ((value < -128) || (value > 127)){ return (BadValue); } pPriv->brightness = value; OUTGR(0xc4, value); } else { return (BadMatch); } return (Success); } static int NEOGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value, pointer data) { NEOPortPtr pPriv = (NEOPortPtr)data; #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOGetPortAttribute\n"); #endif if (attribute == xvColorKey){ *value = pPriv->colorKey; } else if (attribute == xvBrightness){ *value = pPriv->brightness; } else { return (BadMatch); } return (Success); } static void NEOQueryBestSize(ScrnInfoPtr pScrn, Bool motion, short vid_w, short vid_h, short drw_w, short drw_h, unsigned int *p_w, unsigned int *p_h, pointer data) { #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOQueryBestSize\n"); #endif *p_w = min(drw_w, 1024); *p_h = min(drw_h, 1024); } static int NEOPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, short drw_y, short src_w, short src_h, short drw_w, short drw_h, int id, unsigned char *buf, short width, short height, Bool sync, RegionPtr clipBoxes, pointer data) { NEOPtr nPtr = NEOPTR(pScrn); NEOPortPtr pPriv = (NEOPortPtr)nPtr->overlayAdaptor->pPortPrivates[0].ptr; INT32 x1, y1, x2, y2; int bpp; int srcPitch, srcPitch2 = 0, dstPitch, size; BoxRec dstBox; CARD32 offset, offset2 = 0, offset3 = 0, tmp; int left, top, nPixels, nLines; unsigned char *dstStart; #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutImage\n"); #endif x1 = src_x; y1 = src_y; x2 = src_x + src_w; y2 = src_y + src_h; dstBox.x1 = drw_x; dstBox.y1 = drw_y; dstBox.x2 = drw_x + drw_w; dstBox.y2 = drw_y + drw_h; if (!NEOClipVideo(pScrn, &dstBox, &x1, &y1, &x2, &y2, clipBoxes, width, height)){ return (Success); } dstBox.x1 -= pScrn->frameX0; dstBox.y1 -= pScrn->frameY0; dstBox.x2 -= pScrn->frameX0; dstBox.y2 -= pScrn->frameY0; bpp = 2; switch (id){ case FOURCC_YV12: srcPitch = (width + 3) & ~3; offset2 = srcPitch * height; srcPitch2 = ((width >> 1) + 3) & ~3; offset3 = offset2 + (srcPitch2 * (height >> 1)); dstPitch = ((width << 1) + 15) & ~15; break; case FOURCC_I420: srcPitch = (width + 3) & ~3; offset3 = srcPitch * height; srcPitch2 = ((width >> 1) + 3) & ~3; offset2 = offset3 + (srcPitch2 * (height >> 1)); dstPitch = ((width << 1) + 15) & ~15; break; case FOURCC_YUY2: case FOURCC_RV15: case FOURCC_RV16: default: srcPitch = width * bpp; dstPitch = (srcPitch + 15) & ~15; break; } size = dstPitch * height; if ((pPriv->linear = NEOAllocateMemory(pScrn, pPriv->linear, size)) == NULL){ return (BadAlloc); } top = y1 >> 16; left = (x1 >> 16) & ~1; nPixels = ((((x2 + 0xFFFF) >> 16) + 1) & ~1) - left; left *= bpp; offset = pPriv->linear->offset * bpp; #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"offset=%x\n", offset); #endif dstStart = (unsigned char *)(nPtr->NeoFbBase + offset + left); switch (id){ case FOURCC_YV12: case FOURCC_I420: top &= ~1; tmp = ((top >> 1) * srcPitch2) + (left >> 2); offset2 += tmp; offset3 += tmp; nLines = ((((y2 + 0xFFFF) >> 16) + 1) & ~1) - top; NEOCopyYV12Data(buf + (top * srcPitch) + (left >> 1), buf + offset2, buf + offset3, dstStart, srcPitch, srcPitch2, dstPitch, nLines, nPixels); break; default: buf += (top * srcPitch) + left; nLines = ((y2 + 0xFFFF) >> 16) - top; NEOCopyData(buf, dstStart, srcPitch, dstPitch, nLines, nPixels * bpp); } if (!RegionsEqual(&pPriv->clip, clipBoxes)){ REGION_COPY(pScreen, &pPriv->clip, clipBoxes); XAAFillSolidRects(pScrn, pPriv->colorKey, GXcopy, ~0, REGION_NUM_RECTS(clipBoxes), REGION_RECTS(clipBoxes)); } NEODisplayVideo(pScrn, id, offset, width, height, dstPitch, x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); pPriv->videoStatus = CLIENT_VIDEO_ON; return (Success); } static int NEOQueryImageAttributes(ScrnInfoPtr pScrn, int id, unsigned short *width, unsigned short *height, int *pitches, int *offsets) { int size, tmp; #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOQueryImageAttributes\n"); #endif if (*width > 1024){ *width = 1024; } if (*height > 1024){ *height = 1024; } *width = (*width + 1) & ~1; if (offsets != NULL){ offsets[0] = 0; } switch (id){ case FOURCC_YV12: case FOURCC_I420: *height = (*height + 1) & ~1; size = (*width + 3) & ~3; if (pitches != NULL){ pitches[0] = size; } size *= *height; if (offsets != NULL){ offsets[1] = size; } tmp = ((*width >> 1) + 3) & ~3; if (pitches != NULL){ pitches[1] = pitches[2] = tmp; } tmp *= (*height >> 1); size += tmp; if (offsets != NULL){ offsets[2] = size; } size += tmp; break; case FOURCC_YUY2: case FOURCC_RV15: case FOURCC_RV16: default: size = *width * 2; if (pitches != NULL){ pitches[0] = size; } size *= *height; break; } return (size); } static Bool RegionsEqual(RegionPtr A, RegionPtr B) { int *dataA, *dataB; int num; num = REGION_NUM_RECTS(A); if (num != REGION_NUM_RECTS(B)){ return (FALSE); } if ((A->extents.x1 != B->extents.x1) || (A->extents.y1 != B->extents.y1) || (A->extents.x2 != B->extents.x2) || (A->extents.y2 != B->extents.y2)){ return (FALSE); } dataA = (int*) REGION_RECTS(A); dataB = (int*) REGION_RECTS(B); while (num--){ if ((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])){ return (FALSE); } dataA += 2; dataB += 2; } return (TRUE); } static Bool NEOClipVideo(ScrnInfoPtr pScrn, BoxPtr dst, INT32 *x1, INT32 *y1, INT32 *x2, INT32 *y2, RegionPtr reg, INT32 width, INT32 height) { INT32 vscale, hscale, delta; BoxPtr extents = REGION_EXTENTS(pScrn, reg); int diff; #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOClipVideo\n"); #endif extents->x1 = max(extents->x1, pScrn->frameX0); extents->y1 = max(extents->y1, pScrn->frameY0); hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1); vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1); *x1 <<= 16; *y1 <<= 16; *x2 <<= 16; *y2 <<= 16; diff = extents->x1 - dst->x1; if (diff > 0){ dst->x1 = extents->x1; *x1 += diff * hscale; } diff = extents->y1 - dst->y1; if (diff > 0){ dst->y1 = extents->y1; *y1 += diff * vscale; } diff = dst->x2 - extents->x2; if (diff > 0){ dst->x2 = extents->x2; *x2 -= diff * hscale; } diff = dst->y2 - extents->y2; if (diff > 0){ dst->y2 = extents->y2; *y2 -= diff * vscale; } if (*x1 < 0){ diff = (-*x1 + hscale - 1) / hscale; dst->x1 += diff; *x1 += diff * hscale; } if (*y1 < 0){ diff = (-*y1 + vscale - 1) / vscale; dst->y1 += diff; *y1 += diff * vscale; } delta = *x2 - (width << 16); if (delta > 0){ diff = (delta + hscale - 1) / hscale; dst->x2 -= diff; *x2 -= diff * hscale; } delta = *y2 - (height << 16); if (delta > 0){ diff = (delta + vscale - 1) / vscale; dst->y2 -= diff; *y2 -= diff * vscale; } if ((*x1 >= *x2) || (*y1 >= *y2)){ return (FALSE); } if ((dst->x1 != extents->x1) || (dst->y1 != extents->y1) || (dst->x2 != extents->x2) || (dst->y2 != extents->y2)){ RegionRec clipReg; REGION_INIT(pScrn, &clipReg, dst, 1); REGION_INTERSECT(pScrn, reg, reg, &clipReg); REGION_UNINIT(pScrn, &clipReg); } return (TRUE); } static void NEODisplayVideo(ScrnInfoPtr pScrn, int id, int offset, short width, short height, int pitch, int x1, int y1, int x2, int y2, BoxPtr dstBox, short src_w, short src_h, short drw_w, short drw_h) { NEOPtr nPtr = NEOPTR(pScrn); int hstretch, vstretch, fmt; #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEODisplayVideo\n"); xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEODisplayVideo src_w=%d, src_h=%d, pitch=%d, drw_w=%d, drw_h=%d\n", src_w, src_h, pitch, drw_w, drw_h); #endif fmt = 0x00; switch (id){ case FOURCC_YV12: case FOURCC_I420: case FOURCC_YUY2: fmt = 0x00; break; case FOURCC_RV15: case FOURCC_RV16: fmt = 0x20; break; } switch (nPtr->NeoChipset) { default: case NM2160: offset/=2; pitch/=2; OUTGR(0xbc, 0x4f); break; case NM2230: OUTGR(0xbc, 0x2e); break; case NM2360: OUTGR(0xbc, 0x2e); break; } hstretch = 0x1000; if (drw_w > src_w) hstretch = (((int)src_w) * hstretch) / (int) drw_w; vstretch = 0x1000; if (drw_h > src_h) vstretch = (((int)src_h) * vstretch )/ drw_h; OUTGR(0xb1, (((dstBox->x2-1)>>4)&0xf0)|((dstBox->x1>>8)&0x0f)); OUTGR(0xb2, dstBox->x1); OUTGR(0xb3, dstBox->x2-1); OUTGR(0xb4, (((dstBox->y2-1)>>4)&0xf0)|((dstBox->y1>>8)&0x0f)); OUTGR(0xb5, dstBox->y1); OUTGR(0xb6, dstBox->y2-1); OUTGR(0xb7, offset >> 16); OUTGR(0xb8, offset >> 8); OUTGR(0xb9, offset ); OUTGR(0xba, pitch >> 8); OUTGR(0xbb, pitch); OUTGR(0xbd, 0x02); OUTGR(0xbe, 0x00); OUTGR(0xbf, 0x02); OUTGR(0xc0, hstretch >> 8); OUTGR(0xc1, hstretch); OUTGR(0xc2, vstretch >> 8); OUTGR(0xc3, vstretch); OUTGR(0xb0, fmt | 0x03); OUTGR(0x0a, 0x21); OUTSR(0x08, 0xa0); OUTGR(0x0a, 0x01); } static void NEOInitOffscreenImages(ScreenPtr pScreen) { XF86OffscreenImagePtr offscreenImages; #ifdef DEBUG xf86DrvMsg(xf86Screens[pScreen->myNum]->scrnIndex,X_INFO,"NEOInitOffscreenImages\n"); #endif if ((offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))) == NULL){ return; } offscreenImages->image = NEOVideoImages; offscreenImages->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; offscreenImages->alloc_surface = NEOAllocSurface; offscreenImages->free_surface = NEOFreeSurface; offscreenImages->display = NEODisplaySurface; offscreenImages->stop = NEOStopSurface; offscreenImages->getAttribute = NEOGetSurfaceAttribute; offscreenImages->setAttribute = NEOSetSurfaceAttribute; offscreenImages->max_width = 1024; offscreenImages->max_height = 1024; offscreenImages->num_attributes = nElems(NEOVideoAttributes); offscreenImages->attributes = NEOVideoAttributes; xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); } static FBLinearPtr NEOAllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size) { ScreenPtr pScreen; FBLinearPtr new_linear; #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOAllocateMemory: linear=%x, size=%d\n", linear, size); #endif if (linear){ #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOAllocateMemory: linear->size=%d\n", linear->size); #endif if (linear->size >= size){ return (linear); } if (xf86ResizeOffscreenLinear(linear, size)){ return (linear); } xf86FreeOffscreenLinear(linear); } pScreen = screenInfo.screens[pScrn->scrnIndex]; if ((new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, NULL, NULL, NULL)) == NULL){ int max_size; xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, PRIORITY_EXTREME); #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOAllocateMemory: max_size=%d\n", max_size); #endif if (max_size < size){ return (NULL); } xf86PurgeUnlockedOffscreenAreas(pScreen); new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, NULL, NULL, NULL); } return (new_linear); } static void NEOCopyData(unsigned char *src, unsigned char *dst, int srcPitch, int dstPitch, int height, int width) { while (height-- > 0){ memcpy(dst, src, width); src += srcPitch; dst += dstPitch; } } static void NEOCopyYV12Data(unsigned char *src1, unsigned char *src2, unsigned char *src3, unsigned char *dst, int srcPitch1, int srcPitch2, int dstPitch, int height, int width) { CARD32 *pDst = (CARD32 *) dst; int i, j; for (j = 0; j < height; j++){ for (i =0; i < width; i++){ pDst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) | (src3[i] << 8) | (src2[i] << 24); } pDst += dstPitch >> 2; src1 += srcPitch1; if (j & 1){ src2 += srcPitch2; src3 += srcPitch2; } } } static int NEOAllocSurface(ScrnInfoPtr pScrn, int id, unsigned short width, unsigned short height, XF86SurfacePtr surface) { int pitch, bpp, size; NEOOffscreenPtr pPriv; FBLinearPtr linear; #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOAllocSurface\n"); #endif if (width > 1024 || height > 1024){ return (BadAlloc); } width = (width + 1) & ~1; bpp = 2; pitch = (width * bpp + 15) & ~15; size = pitch * height; if ((linear = NEOAllocateMemory(pScrn, NULL, size)) == NULL){ return (BadAlloc); } surface->width = width; surface->height = height; if ((surface->pitches = xalloc(sizeof(int))) == NULL){ xf86FreeOffscreenLinear(linear); return (BadAlloc); } if ((surface->offsets = xalloc(sizeof(int))) == NULL){ xfree(surface->pitches); xf86FreeOffscreenLinear(linear); return (BadAlloc); } if ((pPriv = xalloc(sizeof(NEOOffscreenRec))) == NULL){ xfree(surface->pitches); xfree(surface->offsets); xf86FreeOffscreenLinear(linear); return (BadAlloc); } pPriv->linear = linear; pPriv->isOn = FALSE; surface->pScrn = pScrn; surface->id = id; surface->pitches[0] = pitch; surface->offsets[0] = linear->offset * bpp; surface->devPrivate.ptr = (pointer)pPriv; return (Success); } static int NEOFreeSurface(XF86SurfacePtr surface) { NEOOffscreenPtr pPriv = (NEOOffscreenPtr)surface->devPrivate.ptr; #ifdef DEBUG xf86DrvMsg(0,X_INFO,"NEOFreeSurface\n"); #endif if (pPriv->isOn) NEOStopSurface(surface); xf86FreeOffscreenLinear(pPriv->linear); xfree(surface->pitches); xfree(surface->offsets); xfree(surface->devPrivate.ptr); return (Success); } static int NEODisplaySurface(XF86SurfacePtr surface, short src_x, short src_y, short drw_x, short drw_y, short src_w, short src_h, short drw_w, short drw_h, RegionPtr clipBoxes) { NEOOffscreenPtr pPriv = (NEOOffscreenPtr)surface->devPrivate.ptr; NEOPtr nPtr = NEOPTR(surface->pScrn); NEOPortPtr portPriv = nPtr->overlayAdaptor->pPortPrivates[0].ptr; INT32 x1, y1, x2, y2; BoxRec dstBox; #ifdef DEBUG xf86DrvMsg(surface->pScrn->scrnIndex,X_INFO,"NEODisplaySurface\n"); #endif x1 = src_x; x2 = src_x + src_w; y1 = src_y; y2 = src_y + src_h; dstBox.x1 = drw_x; dstBox.x2 = drw_x + drw_w; dstBox.y1 = drw_y; dstBox.y2 = drw_y + drw_h; if (!NEOClipVideo(surface->pScrn, &dstBox, &x1, &y1, &x2, &y2, clipBoxes, surface->width, surface->height)){ return (Success); } dstBox.x1 -= surface->pScrn->frameX0; dstBox.y1 -= surface->pScrn->frameY0; dstBox.x2 -= surface->pScrn->frameX0; dstBox.y2 -= surface->pScrn->frameY0; XAAFillSolidRects(surface->pScrn, portPriv->colorKey, GXcopy, ~0, REGION_NUM_RECTS(clipBoxes), REGION_RECTS(clipBoxes)); NEOResetVideo(surface->pScrn); NEODisplayVideo(surface->pScrn, surface->id, surface->offsets[0], surface->width, surface->height, surface->pitches[0], x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); pPriv->isOn = TRUE; if (portPriv->videoStatus & CLIENT_VIDEO_ON){ REGION_EMPTY(pScrn->pScreen, &portPriv->clip); UpdateCurrentTime(); portPriv->videoStatus = FREE_TIMER; portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; } return (Success); } static int NEOStopSurface(XF86SurfacePtr surface) { NEOOffscreenPtr pPriv = (NEOOffscreenPtr)surface->devPrivate.ptr; #ifdef DEBUG xf86DrvMsg(surface->pScrn->scrnIndex,X_INFO,"NEOStopSurface\n"); #endif if (pPriv->isOn){ NEOPtr nPtr = NEOPTR(surface->pScrn); OUTGR(0xb0, 0x02); pPriv->isOn = FALSE; } return (Success); } static int NEOGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 *value) { NEOPtr nPtr = NEOPTR(pScrn); #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOGetSurfaceAttribute\n"); #endif return (NEOGetPortAttribute(pScrn, attr, value, (pointer)nPtr->overlayAdaptor->pPortPrivates[0].ptr)); } static int NEOSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 value) { NEOPtr nPtr = NEOPTR(pScrn); #ifdef DEBUG xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOSetSurfaceAttribute\n"); #endif return (NEOSetPortAttribute(pScrn, attr, value, (pointer)nPtr->overlayAdaptor->pPortPrivates[0].ptr)); } #else /* XvExtension */ void NEOInitVideo(ScreenPtr pScreen) {} #endif