1692f60a7Smrg/********************************************************************** 2692f60a7SmrgCopyright 2002 by Shigehiro Nomura. 3692f60a7Smrg 4692f60a7Smrg All Rights Reserved 5692f60a7Smrg 6692f60a7SmrgPermission to use, copy, modify, distribute, and sell this software and 7692f60a7Smrgits documentation for any purpose is hereby granted without fee, 8692f60a7Smrgprovided that the above copyright notice appear in all copies and that 9692f60a7Smrgboth that copyright notice and this permission notice appear in 10692f60a7Smrgsupporting documentation, and that the name of Shigehiro Nomura not be 11692f60a7Smrgused in advertising or publicity pertaining to distribution of the 12692f60a7Smrgsoftware without specific, written prior permission. Shigehiro Nomura 13692f60a7Smrgand its suppliers make no representations about the suitability of this 14692f60a7Smrgsoftware for any purpose. It is provided "as is" without express or 15692f60a7Smrgimplied warranty. 16692f60a7Smrg 17692f60a7SmrgSHIGEHIRO NOMURA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18692f60a7SmrgINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19692f60a7SmrgEVENT SHALL SHIGEHIRO NOMURA AND/OR ITS SUPPLIERS BE LIABLE FOR ANY 20692f60a7SmrgSPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 21692f60a7SmrgRESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 22692f60a7SmrgCONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 23692f60a7SmrgCONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 24692f60a7Smrg**********************************************************************/ 25692f60a7Smrg 26692f60a7Smrg/* 27692f60a7Smrg * Copyright 2002 SuSE Linux AG, Author: Egbert Eich 28692f60a7Smrg */ 29692f60a7Smrg 30692f60a7Smrg#ifdef HAVE_CONFIG_H 31692f60a7Smrg#include "config.h" 32692f60a7Smrg#endif 33692f60a7Smrg 34692f60a7Smrg#include "neo.h" 35692f60a7Smrg#include "neo_video.h" 36692f60a7Smrg 37692f60a7Smrg#define nElems(x) (sizeof(x) / sizeof(x[0])) 38692f60a7Smrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 39692f60a7Smrg 40692f60a7Smrg#include "dixstruct.h" 41692f60a7Smrg 42692f60a7Smrgstatic XF86VideoAdaptorPtr NEOSetupVideo(ScreenPtr); 43692f60a7Smrg 44692f60a7Smrgstatic int NEOPutVideo(ScrnInfoPtr, short, short, short, short, 45692f60a7Smrg short, short, short, short, RegionPtr, pointer, 46692f60a7Smrg DrawablePtr); 47692f60a7Smrg 48692f60a7Smrgstatic void NEOStopVideo(ScrnInfoPtr, pointer, Bool); 49692f60a7Smrgstatic int NEOSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 50692f60a7Smrgstatic int NEOGetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer); 51692f60a7Smrgstatic void NEOQueryBestSize(ScrnInfoPtr, Bool, short, short, short, 52692f60a7Smrg short, unsigned int *, unsigned int *, pointer); 53692f60a7Smrgstatic int NEOPutImage(ScrnInfoPtr, short, short, short, short, short, short, 54692f60a7Smrg short, short, int, unsigned char *, short, short, Bool, 55692f60a7Smrg RegionPtr, pointer, DrawablePtr); 56692f60a7Smrgstatic int NEOQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, 57692f60a7Smrg unsigned short *, int *, int *); 58692f60a7Smrg 59692f60a7Smrgstatic void NEODisplayVideo(ScrnInfoPtr, int, int, short, short, int, int, 60692f60a7Smrg int, int, int, BoxPtr, short, short, short, short); 61692f60a7Smrg 62692f60a7Smrgstatic void NEOInitOffscreenImages(ScreenPtr); 63692f60a7Smrgstatic FBLinearPtr NEOAllocateMemory(ScrnInfoPtr, FBLinearPtr, int); 64692f60a7Smrg 65692f60a7Smrgstatic int NEOAllocSurface(ScrnInfoPtr, int, unsigned short, unsigned short, 66692f60a7Smrg XF86SurfacePtr); 67692f60a7Smrgstatic int NEOFreeSurface(XF86SurfacePtr); 68692f60a7Smrgstatic int NEODisplaySurface(XF86SurfacePtr, short, short, short, short, 69692f60a7Smrg short, short, short, short, RegionPtr clipBoxes); 70692f60a7Smrgstatic int NEOStopSurface(XF86SurfacePtr); 71692f60a7Smrgstatic int NEOGetSurfaceAttribute(ScrnInfoPtr, Atom, INT32 *); 72692f60a7Smrgstatic int NEOSetSurfaceAttribute(ScrnInfoPtr, Atom, INT32); 73692f60a7Smrg 74692f60a7Smrgstatic Atom xvColorKey, xvBrightness, xvInterlace; 75692f60a7Smrg 76692f60a7Smrgvoid 77692f60a7SmrgNEOInitVideo(ScreenPtr pScreen) 78692f60a7Smrg{ 793f6d0e1dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 80692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 81692f60a7Smrg XF86VideoAdaptorPtr *overlayAdaptors, *newAdaptors = NULL; 82692f60a7Smrg XF86VideoAdaptorPtr newAdaptor = NULL; 83692f60a7Smrg int numAdaptors; 84692f60a7Smrg 85692f60a7Smrg numAdaptors = xf86XVListGenericAdaptors(pScrn, &overlayAdaptors); 86692f60a7Smrg 87692f60a7Smrg if (nPtr->NeoChipset > NM2070 88692f60a7Smrg && nPtr->NeoMMIOBase2 != NULL){ 89692f60a7Smrg nPtr->video = TRUE; 90692f60a7Smrg newAdaptor = NEOSetupVideo(pScreen); 91692f60a7Smrg NEOInitOffscreenImages(pScreen); 92692f60a7Smrg } else 93692f60a7Smrg nPtr->video = FALSE; 94692f60a7Smrg 95692f60a7Smrg if (newAdaptor){ 96692f60a7Smrg if (!numAdaptors){ 97692f60a7Smrg numAdaptors = 1; 98692f60a7Smrg overlayAdaptors = &newAdaptor; 99692f60a7Smrg } else { 1003f6d0e1dSmrg newAdaptors = malloc((numAdaptors + 1) 101692f60a7Smrg * sizeof(XF86VideoAdaptorPtr*)); 102692f60a7Smrg if (newAdaptors){ 103692f60a7Smrg memcpy(newAdaptors, overlayAdaptors, 104692f60a7Smrg numAdaptors * sizeof(XF86VideoAdaptorPtr)); 105692f60a7Smrg newAdaptors[numAdaptors++] = newAdaptor; 106692f60a7Smrg overlayAdaptors = newAdaptors; 107692f60a7Smrg } 108692f60a7Smrg } 109692f60a7Smrg } 110692f60a7Smrg 111692f60a7Smrg if (numAdaptors) 112692f60a7Smrg xf86XVScreenInit(pScreen, overlayAdaptors, numAdaptors); 113692f60a7Smrg 114692f60a7Smrg if (newAdaptors) 1153f6d0e1dSmrg free(newAdaptors); 116692f60a7Smrg} 117692f60a7Smrg 118692f60a7Smrgstatic XF86VideoEncodingRec NEOVideoEncodings[] = 119692f60a7Smrg{ 120692f60a7Smrg { 121692f60a7Smrg NEO_VIDEO_VIDEO, 122692f60a7Smrg "XV_VIDEO", 123692f60a7Smrg 1024, 1024, 124692f60a7Smrg {1, 1} 125692f60a7Smrg }, 126692f60a7Smrg { 127692f60a7Smrg NEO_VIDEO_IMAGE, 128692f60a7Smrg "XV_IMAGE", 129692f60a7Smrg 1024, 1024, 130692f60a7Smrg {1, 1} 131692f60a7Smrg } 132692f60a7Smrg}; 133692f60a7Smrg 134692f60a7Smrgstatic XF86VideoFormatRec NEOVideoFormats[] = 135692f60a7Smrg{ 136692f60a7Smrg { 8, PseudoColor }, 137692f60a7Smrg { 15, TrueColor }, 138692f60a7Smrg { 16, TrueColor }, 139692f60a7Smrg { 24, TrueColor }, 140692f60a7Smrg}; 141692f60a7Smrg 142692f60a7Smrgstatic XF86AttributeRec NEOVideoAttributes[] = 143692f60a7Smrg{ 144692f60a7Smrg { 145692f60a7Smrg XvSettable | XvGettable, 146692f60a7Smrg 0x000000, 0xFFFFFF, 147692f60a7Smrg "XV_COLORKEY" 148692f60a7Smrg }, 149692f60a7Smrg { 150692f60a7Smrg XvSettable | XvGettable, 151692f60a7Smrg -128, 127, 152692f60a7Smrg "XV_BRIGHTNESS" 153692f60a7Smrg }, 154692f60a7Smrg { 155692f60a7Smrg XvSettable | XvGettable, 156692f60a7Smrg 0,2, 157692f60a7Smrg "XV_INTERLACE" 158692f60a7Smrg }, 159692f60a7Smrg}; 160692f60a7Smrg 161692f60a7Smrgstatic XF86ImageRec NEOVideoImages[] = 162692f60a7Smrg{ 163692f60a7Smrg XVIMAGE_YUY2, 164692f60a7Smrg XVIMAGE_YV12, 165692f60a7Smrg XVIMAGE_I420, 166692f60a7Smrg { 167692f60a7Smrg FOURCC_RV15, 168692f60a7Smrg XvRGB, 169692f60a7Smrg LSBFirst, 170692f60a7Smrg { 'R', 'V' ,'1', '5', 171692f60a7Smrg 0x00,'5',0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 172692f60a7Smrg 16, 173692f60a7Smrg XvPacked, 174692f60a7Smrg 1, 175692f60a7Smrg 15, 0x001F, 0x03E0, 0x7C00, 176692f60a7Smrg 0, 0, 0, 177692f60a7Smrg 0, 0, 0, 178692f60a7Smrg 0, 0, 0, 179692f60a7Smrg { 'R', 'V', 'B' }, 180692f60a7Smrg XvTopToBottom 181692f60a7Smrg }, 182692f60a7Smrg { 183692f60a7Smrg FOURCC_RV16, 184692f60a7Smrg XvRGB, 185692f60a7Smrg LSBFirst, 186692f60a7Smrg { 'R', 'V' ,'1', '6', 187692f60a7Smrg 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 188692f60a7Smrg 16, 189692f60a7Smrg XvPacked, 190692f60a7Smrg 1, 191692f60a7Smrg 16, 0xF800, 0x07E0, 0x001F, 192692f60a7Smrg 0, 0, 0, 193692f60a7Smrg 0, 0, 0, 194692f60a7Smrg 0, 0, 0, 195692f60a7Smrg { 'R', 'V', 'B' }, 196692f60a7Smrg XvTopToBottom 197692f60a7Smrg } 198692f60a7Smrg}; 199692f60a7Smrg 200692f60a7Smrgstatic XF86VideoAdaptorPtr 201692f60a7SmrgNEOSetupVideo(ScreenPtr pScreen) 202692f60a7Smrg{ 2033f6d0e1dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 204692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 205692f60a7Smrg NEOPortPtr pPriv; 206692f60a7Smrg XF86VideoAdaptorPtr overlayAdaptor; 207692f60a7Smrg int i; 208692f60a7Smrg 209692f60a7Smrg#ifdef DEBUG 210692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOSetupVideo\n"); 211692f60a7Smrg#endif 2123f6d0e1dSmrg if ((overlayAdaptor = calloc(1, sizeof(XF86VideoAdaptorRec) + 213692f60a7Smrg sizeof(DevUnion) + 214692f60a7Smrg sizeof(NEOPortRec))) == NULL){ 215692f60a7Smrg return (NULL); 216692f60a7Smrg } 217692f60a7Smrg 218692f60a7Smrg overlayAdaptor->type = XvInputMask | XvImageMask | XvWindowMask 219692f60a7Smrg | XvOutputMask | XvVideoMask; 220692f60a7Smrg overlayAdaptor->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 221692f60a7Smrg overlayAdaptor->name = "NeoMagic Video Engine"; 222692f60a7Smrg overlayAdaptor->nEncodings = nElems(NEOVideoEncodings); 223692f60a7Smrg overlayAdaptor->pEncodings = NEOVideoEncodings; 224692f60a7Smrg for (i = 0; i < nElems(NEOVideoEncodings); i++){ 225692f60a7Smrg NEOVideoEncodings[i].width = 1024; 226692f60a7Smrg NEOVideoEncodings[i].height = 1024; 227692f60a7Smrg } 228692f60a7Smrg overlayAdaptor->nFormats = nElems(NEOVideoFormats); 229692f60a7Smrg overlayAdaptor->pFormats = NEOVideoFormats; 230692f60a7Smrg overlayAdaptor->nPorts = 1; 231692f60a7Smrg overlayAdaptor->pPortPrivates = (DevUnion*) &overlayAdaptor[1]; 232692f60a7Smrg overlayAdaptor->pPortPrivates[0].ptr = 233692f60a7Smrg (pointer) &overlayAdaptor->pPortPrivates[1]; 234692f60a7Smrg overlayAdaptor->nAttributes = nElems(NEOVideoAttributes); 235692f60a7Smrg overlayAdaptor->pAttributes = NEOVideoAttributes; 236692f60a7Smrg overlayAdaptor->nImages = nElems(NEOVideoImages); 237692f60a7Smrg overlayAdaptor->pImages = NEOVideoImages; 238692f60a7Smrg 239692f60a7Smrg overlayAdaptor->PutVideo = NEOPutVideo; 240692f60a7Smrg overlayAdaptor->PutStill = NULL; 241692f60a7Smrg overlayAdaptor->GetVideo = NULL; 242692f60a7Smrg overlayAdaptor->GetStill = NULL; 243692f60a7Smrg 244692f60a7Smrg overlayAdaptor->StopVideo = NEOStopVideo; 245692f60a7Smrg overlayAdaptor->SetPortAttribute = NEOSetPortAttribute; 246692f60a7Smrg overlayAdaptor->GetPortAttribute = NEOGetPortAttribute; 247692f60a7Smrg overlayAdaptor->QueryBestSize = NEOQueryBestSize; 248692f60a7Smrg overlayAdaptor->PutImage = NEOPutImage; 249692f60a7Smrg overlayAdaptor->QueryImageAttributes = NEOQueryImageAttributes; 250692f60a7Smrg 251692f60a7Smrg pPriv = (NEOPortPtr)overlayAdaptor->pPortPrivates[0].ptr; 252692f60a7Smrg pPriv->colorKey = nPtr->videoKey; 253692f60a7Smrg pPriv->interlace = nPtr->interlace; 254692f60a7Smrg pPriv->videoStatus = 0; 255692f60a7Smrg pPriv->brightness = 0; 256692f60a7Smrg REGION_NULL(pScreen, &pPriv->clip); 257692f60a7Smrg nPtr->overlayAdaptor = overlayAdaptor; 258692f60a7Smrg 259692f60a7Smrg xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 260692f60a7Smrg xvColorKey = MAKE_ATOM("XV_COLORKEY"); 261692f60a7Smrg xvInterlace = MAKE_ATOM("XV_INTERLACE"); 262692f60a7Smrg 263692f60a7Smrg NEOResetVideo(pScrn); 264692f60a7Smrg 265692f60a7Smrg return (overlayAdaptor); 266692f60a7Smrg} 267692f60a7Smrg 268692f60a7Smrgvoid 269692f60a7SmrgNEOResetVideo(ScrnInfoPtr pScrn) 270692f60a7Smrg{ 271692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 272692f60a7Smrg NEOPortPtr pPriv = (NEOPortPtr)nPtr->overlayAdaptor->pPortPrivates[0].ptr; 273692f60a7Smrg int r, g, b; 274692f60a7Smrg VGA_HWP(pScrn); 275692f60a7Smrg 276692f60a7Smrg#ifdef DEBUG 277692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOResetVideo\n"); 278692f60a7Smrg#endif 279692f60a7Smrg switch (pScrn->depth){ 280692f60a7Smrg case 8: 281692f60a7Smrg OUTGR(0xc6, pPriv->colorKey & 0); 282692f60a7Smrg OUTGR(0xc5, pPriv->colorKey & 0xff); 283692f60a7Smrg OUTGR(0xc7, pPriv->colorKey & 0); 284692f60a7Smrg break; 285692f60a7Smrg default: 286692f60a7Smrg r = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; 287692f60a7Smrg g = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; 288692f60a7Smrg b = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; 289692f60a7Smrg OUTGR(0xc5, r); 290692f60a7Smrg OUTGR(0xc6, g); 291692f60a7Smrg OUTGR(0xc7, b); 292692f60a7Smrg break; 293692f60a7Smrg } 294692f60a7Smrg OUTGR(0xc4, pPriv->brightness); 295692f60a7Smrg} 296692f60a7Smrg 297692f60a7Smrgstatic int 298692f60a7SmrgNEOPutVideo(ScrnInfoPtr pScrn, 299692f60a7Smrg short src_x, short src_y, short drw_x, short drw_y, 300692f60a7Smrg short src_w, short src_h, short drw_w, short drw_h, 301692f60a7Smrg RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) 302692f60a7Smrg{ 303692f60a7Smrg NEOPortPtr pPriv = (NEOPortPtr)data; 304692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 305692f60a7Smrg CARD32 src_pitch, offset; 306692f60a7Smrg int xscale, yscale; 307692f60a7Smrg BoxRec dstBox; 308692f60a7Smrg INT32 x1, y1, x2, y2; 309692f60a7Smrg int size, bpp; 310692f60a7Smrg unsigned char capctrl; 311692f60a7Smrg VGA_HWP(pScrn); 312692f60a7Smrg 313692f60a7Smrg#ifdef DEBUG 314692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: src: %d %d %d %d\n", 315692f60a7Smrg src_x, src_y, src_w, src_h); 316692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: drw: %d %d %d %d\n", 317692f60a7Smrg drw_x, drw_y, drw_w, drw_h); 318692f60a7Smrg#endif 319692f60a7Smrg if (src_w > 720) 320692f60a7Smrg src_w = 720; 321692f60a7Smrg if (src_h > 576) 322692f60a7Smrg src_h = 576; 323692f60a7Smrg if (pPriv->interlace != 2) 324692f60a7Smrg src_h /= 2; 325692f60a7Smrg x1 = src_x; 326692f60a7Smrg y1 = src_y; 327692f60a7Smrg x2 = src_x + src_w; 328692f60a7Smrg y2 = src_y + src_h; 329692f60a7Smrg 330692f60a7Smrg dstBox.x1 = drw_x; 331692f60a7Smrg dstBox.y1 = drw_y; 332692f60a7Smrg dstBox.x2 = drw_x + drw_w; 333692f60a7Smrg dstBox.y2 = drw_y + drw_h; 334692f60a7Smrg 335692f60a7Smrg if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, 336692f60a7Smrg clipBoxes, src_w, src_h)){ 337692f60a7Smrg return(Success); 338692f60a7Smrg } 339692f60a7Smrg#ifdef DEBUG 340692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: %d %d %d %d\n", 341692f60a7Smrg x1, y1, x2, y2); 342692f60a7Smrg#endif 343692f60a7Smrg 344692f60a7Smrg dstBox.x1 -= pScrn->frameX0; 345692f60a7Smrg dstBox.y1 -= pScrn->frameY0; 346692f60a7Smrg dstBox.x2 -= pScrn->frameX0; 347692f60a7Smrg dstBox.y2 -= pScrn->frameY0; 348692f60a7Smrg#ifdef DEBUG 349692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: dstBox %d %d %d %d\n", 350692f60a7Smrg dstBox.x1, dstBox.y1, dstBox.x2, dstBox.y2); 351692f60a7Smrg#endif 352692f60a7Smrg 353692f60a7Smrg bpp = (pScrn->bitsPerPixel + 1) >> 3; 354692f60a7Smrg src_pitch = (src_w + 7) & ~7; 355692f60a7Smrg 356692f60a7Smrg xscale = 0x1000; 357692f60a7Smrg if (src_w <= drw_w){ 358692f60a7Smrg xscale = (src_w * 0x1000 / drw_w) & 0xffff; 359692f60a7Smrg } 360692f60a7Smrg 361692f60a7Smrg yscale = 0x1000; 362692f60a7Smrg if (src_h <= drw_h){ 363692f60a7Smrg yscale = (src_h * 0x1000 / drw_h) & 0xffff; 364692f60a7Smrg } 365692f60a7Smrg 366692f60a7Smrg size = src_h * src_pitch * 2; 367692f60a7Smrg 368692f60a7Smrg if (size > nPtr->overlay){ 369692f60a7Smrg if ((pPriv->linear = NEOAllocateMemory(pScrn, pPriv->linear, size)) 370692f60a7Smrg == NULL){ 371692f60a7Smrg return (BadAlloc); 372692f60a7Smrg } 373692f60a7Smrg } else { 374692f60a7Smrg pPriv->linear = NULL; 375692f60a7Smrg } 376692f60a7Smrg 377692f60a7Smrg if (pPriv->linear == NULL){ 378692f60a7Smrg offset = nPtr->overlay_offset; 379692f60a7Smrg } else { 380692f60a7Smrg offset = pPriv->linear->offset * bpp; 381692f60a7Smrg } 382692f60a7Smrg 383692f60a7Smrg#ifdef DEBUG 384692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: offset=0x%x\n", offset); 385692f60a7Smrg#endif 386692f60a7Smrg WAIT_ENGINE_IDLE(); 387692f60a7Smrg memset(nPtr->NeoFbBase + offset, 0, size); 388692f60a7Smrg 389692f60a7Smrg if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)){ 390692f60a7Smrg REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 391692f60a7Smrg xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 392692f60a7Smrg } 393692f60a7Smrg 394692f60a7Smrg x1 >>= 16; 395692f60a7Smrg y1 >>= 16; 396692f60a7Smrg x2 >>= 16; 397692f60a7Smrg y2 >>= 16; 398692f60a7Smrg 399692f60a7Smrg switch (nPtr->NeoChipset) { 400692f60a7Smrg default: 401692f60a7Smrg case NM2090: 402692f60a7Smrg case NM2093: 403692f60a7Smrg case NM2097: 404692f60a7Smrg case NM2160: 405692f60a7Smrg offset/=2; 406692f60a7Smrg OUTGR(0xbc, 0x4f); 407692f60a7Smrg break; 408692f60a7Smrg case NM2200: 409692f60a7Smrg case NM2230: 410692f60a7Smrg case NM2360: 411692f60a7Smrg case NM2380: 412692f60a7Smrg OUTGR(0xbc, 0x2e); 413692f60a7Smrg break; 414692f60a7Smrg } 415692f60a7Smrg 416692f60a7Smrg 417692f60a7Smrg OUTGR(0xb1, (((dstBox.x2-1) >> 4) & 0xf0) | ((dstBox.x1 >> 8) & 0x0f)); 418692f60a7Smrg OUTGR(0xb2, dstBox.x1); 419692f60a7Smrg OUTGR(0xb3, dstBox.x2 - 1); 420692f60a7Smrg OUTGR(0xb4, (((dstBox.y2 - 1) >> 4) & 0xf0) | ((dstBox.y1 >> 8) & 0x0f)); 421692f60a7Smrg OUTGR(0xb5, dstBox.y1); 422692f60a7Smrg OUTGR(0xb6, dstBox.y2 - 1); 423692f60a7Smrg OUTGR(0xb7, offset >> 16); 424692f60a7Smrg OUTGR(0xb8, offset >> 8); 425692f60a7Smrg OUTGR(0xb9, offset ); 426692f60a7Smrg OUTGR(0xba, src_pitch >> 8); 427692f60a7Smrg OUTGR(0xbb, src_pitch); 428692f60a7Smrg 429692f60a7Smrg OUTGR(0xc0, xscale >> 8); 430692f60a7Smrg OUTGR(0xc1, xscale); 431692f60a7Smrg OUTGR(0xc2, yscale >> 8); 432692f60a7Smrg OUTGR(0xc3, yscale); 433692f60a7Smrg OUTGR(0xbf, 0x02); 434692f60a7Smrg 435692f60a7Smrg OUTGR(0x0a, 0x21); 436692f60a7Smrg 437692f60a7Smrg OUTSR(0x0c, offset ); 438692f60a7Smrg OUTSR(0x0d, offset >> 8); 439692f60a7Smrg OUTSR(0x0e, offset >> 16); 440692f60a7Smrg OUTSR(0x1a, src_pitch); 441692f60a7Smrg OUTSR(0x1b, src_pitch>>8); 442692f60a7Smrg 443692f60a7Smrg OUTSR(0x17, 0 + x1); 444692f60a7Smrg OUTSR(0x18, 0 + x2 -1); 445692f60a7Smrg OUTSR(0x19, (((0 + x2 - 1) >> 4) & 0xf0) | (((0 + x1) >> 8) & 0x0f)); 446692f60a7Smrg 447692f60a7Smrg OUTSR(0x14, 14 + y1); 448692f60a7Smrg OUTSR(0x15, 14 + y2 - 2); 449692f60a7Smrg OUTSR(0x16, (((14 + y2 - 1) >> 4) & 0xf0) | (((14 + y1) >> 8) & 0x0f)); 450692f60a7Smrg 451692f60a7Smrg OUTSR(0x1c, 0xfb); 452692f60a7Smrg OUTSR(0x1d, 0x00); 453692f60a7Smrg OUTSR(0x1e, 0xe2); 454692f60a7Smrg OUTSR(0x1f, 0x02); 455692f60a7Smrg 456692f60a7Smrg OUTSR(0x09, 0x11); 457692f60a7Smrg OUTSR(0x0a, 0x00); 458692f60a7Smrg 459692f60a7Smrg capctrl = 0x21; 460692f60a7Smrg switch (pPriv->interlace){ 461692f60a7Smrg case 0: /* Combine 2 fields */ 462692f60a7Smrg break; 463692f60a7Smrg case 1: /* one field only */ 464692f60a7Smrg capctrl |= 0x80; 465692f60a7Smrg break; 466692f60a7Smrg case 2: /* Interlaced fields */ 467692f60a7Smrg capctrl |= 0x40; 468692f60a7Smrg break; 469692f60a7Smrg } 470692f60a7Smrg OUTSR(0x08, capctrl); 471692f60a7Smrg 472692f60a7Smrg#if 0 473692f60a7Smrg OUTGR(0x0a, 0x01); 474692f60a7Smrg#endif 475692f60a7Smrg OUTGR(0xb0, 0x03); 476692f60a7Smrg 477692f60a7Smrg pPriv->videoStatus = CLIENT_VIDEO_ON; 478692f60a7Smrg return (Success); 479692f60a7Smrg} 480692f60a7Smrg 481692f60a7Smrgstatic void 482692f60a7SmrgNEOStopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit) 483692f60a7Smrg{ 484692f60a7Smrg NEOPortPtr pPriv = (NEOPortPtr)data; 485692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 486692f60a7Smrg VGA_HWP(pScrn); 487692f60a7Smrg 488692f60a7Smrg#ifdef DEBUG 489692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOStopVideo\n"); 490692f60a7Smrg#endif 491692f60a7Smrg REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 492692f60a7Smrg 493692f60a7Smrg if (exit){ 494692f60a7Smrg if (pPriv->videoStatus & CLIENT_VIDEO_ON){ 495692f60a7Smrg#ifdef DEBUG 496692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOStopVideo: stop capture\n"); 497692f60a7Smrg#endif 498692f60a7Smrg OUTGR(0xb0, 0x02); 499692f60a7Smrg OUTGR(0x0a, 0x21); 500692f60a7Smrg OUTSR(0x08, 0xa0); 501692f60a7Smrg#if 0 502692f60a7Smrg OUTGR(0x0a, 0x01); 503692f60a7Smrg#endif 504692f60a7Smrg } 505692f60a7Smrg if (pPriv->linear != NULL){ 506692f60a7Smrg xf86FreeOffscreenLinear(pPriv->linear); 507692f60a7Smrg pPriv->linear = NULL; 508692f60a7Smrg } 509692f60a7Smrg pPriv->videoStatus = 0; 510692f60a7Smrg } else { 511692f60a7Smrg if (pPriv->videoStatus & CLIENT_VIDEO_ON){ 512692f60a7Smrg OUTGR(0xb0, 0x02); 513692f60a7Smrg OUTGR(0x0a, 0x21); 514692f60a7Smrg OUTSR(0x08, 0xa0); 515692f60a7Smrg#if 0 516692f60a7Smrg OUTGR(0x0a, 0x01); 517692f60a7Smrg#endif 518692f60a7Smrg pPriv->videoStatus |= OFF_TIMER; 519692f60a7Smrg pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 520692f60a7Smrg } 521692f60a7Smrg } 522692f60a7Smrg} 523692f60a7Smrg 524692f60a7Smrgstatic int 525692f60a7SmrgNEOSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, 526692f60a7Smrg pointer data) 527692f60a7Smrg{ 528692f60a7Smrg NEOPortPtr pPriv = (NEOPortPtr)data; 529692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 530692f60a7Smrg VGA_HWP(pScrn); 531692f60a7Smrg 532692f60a7Smrg#ifdef DEBUG 533692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOSetPortAttribute\n"); 534692f60a7Smrg#endif 535692f60a7Smrg if (attribute == xvColorKey){ 536692f60a7Smrg int r, g, b; 537692f60a7Smrg 538692f60a7Smrg pPriv->colorKey = value; 539692f60a7Smrg switch (pScrn->depth){ 540692f60a7Smrg case 8: 541692f60a7Smrg OUTGR(0xc6, pPriv->colorKey & 0xff); 542692f60a7Smrg OUTGR(0xc5, 0x00); 543692f60a7Smrg OUTGR(0xc7, 0x00); 544692f60a7Smrg break; 545692f60a7Smrg default: 546692f60a7Smrg r = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; 547692f60a7Smrg g = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; 548692f60a7Smrg b = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; 549692f60a7Smrg OUTGR(0xc5, r); 550692f60a7Smrg OUTGR(0xc6, g); 551692f60a7Smrg OUTGR(0xc7, b); 552692f60a7Smrg } 553692f60a7Smrg } else if (attribute == xvBrightness){ 554692f60a7Smrg if ((value < -128) || (value > 127)){ 555692f60a7Smrg return (BadValue); 556692f60a7Smrg } 557692f60a7Smrg pPriv->brightness = value; 558692f60a7Smrg OUTGR(0xc4, value); 559692f60a7Smrg } else if (attribute == xvInterlace){ 560692f60a7Smrg if (value < 0 || value > 2){ 561692f60a7Smrg return (BadValue); 562692f60a7Smrg } 563692f60a7Smrg pPriv->interlace = value; 564692f60a7Smrg } else { 565692f60a7Smrg return (BadMatch); 566692f60a7Smrg } 567692f60a7Smrg return (Success); 568692f60a7Smrg} 569692f60a7Smrg 570692f60a7Smrgstatic int 571692f60a7SmrgNEOGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value, 572692f60a7Smrg pointer data) 573692f60a7Smrg{ 574692f60a7Smrg NEOPortPtr pPriv = (NEOPortPtr)data; 575692f60a7Smrg 576692f60a7Smrg#ifdef DEBUG 577692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOGetPortAttribute\n"); 578692f60a7Smrg#endif 579692f60a7Smrg if (attribute == xvColorKey){ 580692f60a7Smrg *value = pPriv->colorKey; 581692f60a7Smrg } else if (attribute == xvBrightness){ 582692f60a7Smrg *value = pPriv->brightness; 583692f60a7Smrg } else if (attribute == xvInterlace){ 584692f60a7Smrg *value = pPriv->interlace; 585692f60a7Smrg } else { 586692f60a7Smrg return (BadMatch); 587692f60a7Smrg } 588692f60a7Smrg return (Success); 589692f60a7Smrg} 590692f60a7Smrg 591692f60a7Smrgstatic void 592692f60a7SmrgNEOQueryBestSize(ScrnInfoPtr pScrn, Bool motion, 593692f60a7Smrg short vid_w, short vid_h, short drw_w, short drw_h, 594692f60a7Smrg unsigned int *p_w, unsigned int *p_h, 595692f60a7Smrg pointer data) 596692f60a7Smrg{ 597692f60a7Smrg#ifdef DEBUG 598692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOQueryBestSize\n"); 599692f60a7Smrg#endif 600692f60a7Smrg *p_w = min(drw_w, 1024); 601692f60a7Smrg *p_h = min(drw_h, 1024); 602692f60a7Smrg} 603692f60a7Smrg 604692f60a7Smrgstatic int 605692f60a7SmrgNEOPutImage(ScrnInfoPtr pScrn, 606692f60a7Smrg short src_x, short src_y, short drw_x, short drw_y, 607692f60a7Smrg short src_w, short src_h, short drw_w, short drw_h, 608692f60a7Smrg int id, unsigned char *buf, short width, short height, 609692f60a7Smrg Bool sync, RegionPtr clipBoxes, pointer data, 610692f60a7Smrg DrawablePtr pDraw) 611692f60a7Smrg{ 612692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 613692f60a7Smrg NEOPortPtr pPriv = (NEOPortPtr)nPtr->overlayAdaptor->pPortPrivates[0].ptr; 614692f60a7Smrg INT32 x1, y1, x2, y2; 615692f60a7Smrg int bpp; 616692f60a7Smrg int srcPitch, srcPitch2 = 0, dstPitch, size; 617692f60a7Smrg BoxRec dstBox; 618692f60a7Smrg CARD32 offset, offset2 = 0, offset3 = 0, tmp; 619692f60a7Smrg int left, top, nPixels, nLines; 620692f60a7Smrg unsigned char *dstStart; 621692f60a7Smrg 622692f60a7Smrg#ifdef DEBUG 623692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutImage\n"); 624692f60a7Smrg#endif 625692f60a7Smrg 626692f60a7Smrg x1 = src_x; 627692f60a7Smrg y1 = src_y; 628692f60a7Smrg x2 = src_x + src_w; 629692f60a7Smrg y2 = src_y + src_h; 630692f60a7Smrg 631692f60a7Smrg dstBox.x1 = drw_x; 632692f60a7Smrg dstBox.y1 = drw_y; 633692f60a7Smrg dstBox.x2 = drw_x + drw_w; 634692f60a7Smrg dstBox.y2 = drw_y + drw_h; 635692f60a7Smrg 636692f60a7Smrg if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, 637692f60a7Smrg clipBoxes, width, height)){ 638692f60a7Smrg return (Success); 639692f60a7Smrg } 640692f60a7Smrg 641692f60a7Smrg dstBox.x1 -= pScrn->frameX0; 642692f60a7Smrg dstBox.y1 -= pScrn->frameY0; 643692f60a7Smrg dstBox.x2 -= pScrn->frameX0; 644692f60a7Smrg dstBox.y2 -= pScrn->frameY0; 645692f60a7Smrg 646692f60a7Smrg bpp = ((pScrn->bitsPerPixel + 1) >> 3); 647692f60a7Smrg 648692f60a7Smrg switch (id){ 649692f60a7Smrg case FOURCC_YV12: 650692f60a7Smrg srcPitch = (width + 3) & ~3; 651692f60a7Smrg offset2 = srcPitch * height; 652692f60a7Smrg srcPitch2 = ((width >> 1) + 3) & ~3; 653692f60a7Smrg offset3 = offset2 + (srcPitch2 * (height >> 1)); 654692f60a7Smrg dstPitch = ((width << 1) + 15) & ~15; 655692f60a7Smrg break; 656692f60a7Smrg case FOURCC_I420: 657692f60a7Smrg srcPitch = (width + 3) & ~3; 658692f60a7Smrg offset3 = srcPitch * height; 659692f60a7Smrg srcPitch2 = ((width >> 1) + 3) & ~3; 660692f60a7Smrg offset2 = offset3 + (srcPitch2 * (height >> 1)); 661692f60a7Smrg dstPitch = ((width << 1) + 15) & ~15; 662692f60a7Smrg break; 663692f60a7Smrg case FOURCC_YUY2: 664692f60a7Smrg case FOURCC_RV15: 665692f60a7Smrg case FOURCC_RV16: 666692f60a7Smrg default: 667692f60a7Smrg srcPitch = width << 1; 668692f60a7Smrg dstPitch = (srcPitch + 15) & ~15; 669692f60a7Smrg break; 670692f60a7Smrg } 671692f60a7Smrg 672692f60a7Smrg size = dstPitch * height; 673692f60a7Smrg if (size > nPtr->overlay){ 674692f60a7Smrg if ((pPriv->linear = NEOAllocateMemory(pScrn, pPriv->linear, size)) 675692f60a7Smrg == NULL){ 676692f60a7Smrg return (BadAlloc); 677692f60a7Smrg } 678692f60a7Smrg } else { 679692f60a7Smrg pPriv->linear = NULL; 680692f60a7Smrg } 681692f60a7Smrg 682692f60a7Smrg top = y1 >> 16; 683692f60a7Smrg left = (x1 >> 16) & ~1; 684692f60a7Smrg nPixels = ((((x2 + 0xFFFF) >> 16) + 1) & ~1) - left; 685692f60a7Smrg left <<= 1; 686692f60a7Smrg 687692f60a7Smrg if (pPriv->linear == NULL){ 688692f60a7Smrg offset = nPtr->overlay_offset; 689692f60a7Smrg } else { 690692f60a7Smrg offset = pPriv->linear->offset * bpp; 691692f60a7Smrg } 692692f60a7Smrg 693692f60a7Smrg#ifdef DEBUG 694692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"offset=%x\n", offset); 695692f60a7Smrg#endif 696692f60a7Smrg 697692f60a7Smrg dstStart = (unsigned char *)(nPtr->NeoFbBase + offset + left); 698692f60a7Smrg 699692f60a7Smrg switch (id){ 700692f60a7Smrg case FOURCC_YV12: 701692f60a7Smrg case FOURCC_I420: 702692f60a7Smrg top &= ~1; 703692f60a7Smrg tmp = ((top >> 1) * srcPitch2) + (left >> 2); 704692f60a7Smrg offset2 += tmp; 705692f60a7Smrg offset3 += tmp; 706692f60a7Smrg nLines = ((((y2 + 0xFFFF) >> 16) + 1) & ~1) - top; 707692f60a7Smrg xf86XVCopyYUV12ToPacked(buf + (top * srcPitch) + (left >> 1), 708692f60a7Smrg buf + offset2, buf + offset3, 709692f60a7Smrg dstStart, srcPitch, srcPitch2, 710692f60a7Smrg dstPitch, nLines, nPixels); 711692f60a7Smrg break; 712692f60a7Smrg default: 713692f60a7Smrg buf += (top * srcPitch) + left; 714692f60a7Smrg nLines = ((y2 + 0xFFFF) >> 16) - top; 715692f60a7Smrg xf86XVCopyPacked(buf, dstStart, srcPitch, dstPitch, 716692f60a7Smrg nLines, nPixels << 1); 717692f60a7Smrg } 718692f60a7Smrg 719692f60a7Smrg if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)){ 720692f60a7Smrg REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 721692f60a7Smrg xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 722692f60a7Smrg } 723692f60a7Smrg NEODisplayVideo(pScrn, id, offset, width, height, dstPitch, x1, y1, 724692f60a7Smrg x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 725692f60a7Smrg 726692f60a7Smrg pPriv->videoStatus = CLIENT_VIDEO_ON; 727692f60a7Smrg return (Success); 728692f60a7Smrg 729692f60a7Smrg} 730692f60a7Smrg 731692f60a7Smrgstatic int 732692f60a7SmrgNEOQueryImageAttributes(ScrnInfoPtr pScrn, int id, 733692f60a7Smrg unsigned short *width, unsigned short *height, 734692f60a7Smrg int *pitches, int *offsets) 735692f60a7Smrg{ 736692f60a7Smrg int size, tmp; 737692f60a7Smrg 738692f60a7Smrg#ifdef DEBUG 739692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOQueryImageAttributes\n"); 740692f60a7Smrg#endif 741692f60a7Smrg if (*width > 1024){ 742692f60a7Smrg *width = 1024; 743692f60a7Smrg } 744692f60a7Smrg if (*height > 1024){ 745692f60a7Smrg *height = 1024; 746692f60a7Smrg } 747692f60a7Smrg 748692f60a7Smrg *width = (*width + 1) & ~1; 749692f60a7Smrg if (offsets != NULL){ 750692f60a7Smrg offsets[0] = 0; 751692f60a7Smrg } 752692f60a7Smrg 753692f60a7Smrg switch (id){ 754692f60a7Smrg case FOURCC_YV12: 755692f60a7Smrg case FOURCC_I420: 756692f60a7Smrg *height = (*height + 1) & ~1; 757692f60a7Smrg size = (*width + 3) & ~3; 758692f60a7Smrg if (pitches != NULL){ 759692f60a7Smrg pitches[0] = size; 760692f60a7Smrg } 761692f60a7Smrg size *= *height; 762692f60a7Smrg if (offsets != NULL){ 763692f60a7Smrg offsets[1] = size; 764692f60a7Smrg } 765692f60a7Smrg tmp = ((*width >> 1) + 3) & ~3; 766692f60a7Smrg if (pitches != NULL){ 767692f60a7Smrg pitches[1] = pitches[2] = tmp; 768692f60a7Smrg } 769692f60a7Smrg tmp *= (*height >> 1); 770692f60a7Smrg size += tmp; 771692f60a7Smrg if (offsets != NULL){ 772692f60a7Smrg offsets[2] = size; 773692f60a7Smrg } 774692f60a7Smrg size += tmp; 775692f60a7Smrg break; 776692f60a7Smrg case FOURCC_YUY2: 777692f60a7Smrg case FOURCC_RV15: 778692f60a7Smrg case FOURCC_RV16: 779692f60a7Smrg default: 780692f60a7Smrg size = *width * 2; 781692f60a7Smrg if (pitches != NULL){ 782692f60a7Smrg pitches[0] = size; 783692f60a7Smrg } 784692f60a7Smrg size *= *height; 785692f60a7Smrg break; 786692f60a7Smrg } 787692f60a7Smrg return (size); 788692f60a7Smrg} 789692f60a7Smrg 790692f60a7Smrgstatic void 791692f60a7SmrgNEODisplayVideo(ScrnInfoPtr pScrn, int id, int offset, 792692f60a7Smrg short width, short height, int pitch, 793692f60a7Smrg int x1, int y1, int x2, int y2, BoxPtr dstBox, 794692f60a7Smrg short src_w, short src_h, short drw_w, short drw_h) 795692f60a7Smrg{ 796692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 797692f60a7Smrg int hstretch, vstretch, fmt; 798692f60a7Smrg VGA_HWP(pScrn); 799692f60a7Smrg#ifdef DEBUG 800692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEODisplayVideo\n"); 801692f60a7Smrg 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); 802692f60a7Smrg#endif 803692f60a7Smrg#define WIDTH_THRESHOLD 160 804692f60a7Smrg if (dstBox->x2 >= pScrn->virtualX) { 805692f60a7Smrg /* 806692f60a7Smrg * This is a hack to work around a problem when video is moved 807efb46889Smrg * across the right border. 808692f60a7Smrg */ 809692f60a7Smrg int diff_s = (width - ((x2 - x1) >> 16)) & ~1; 810692f60a7Smrg int diff_d = (drw_w - dstBox->x2 + dstBox->x1) & ~1; 811692f60a7Smrg 812692f60a7Smrg offset -= 2 * ((diff_s > diff_d) ? diff_d : diff_s); 813692f60a7Smrg dstBox->x1 -= diff_d; 814692f60a7Smrg } else if (dstBox->x2 - dstBox->x1 < WIDTH_THRESHOLD) { 815692f60a7Smrg /* 816692f60a7Smrg * When the video window is less than about 160 pixel wide 817692f60a7Smrg * it will be distoreted. We attempt to fix it by actually 818692f60a7Smrg * making it wider and relying on the color key to prevent 819692f60a7Smrg * it from appearing outside of the video. 820692f60a7Smrg */ 821692f60a7Smrg int pre, post; 822692f60a7Smrg int scale = 1; 823692f60a7Smrg 824692f60a7Smrg if (dstBox->x1 < WIDTH_THRESHOLD) { 825692f60a7Smrg pre = dstBox->x1; 826692f60a7Smrg post = 160 - pre; 827692f60a7Smrg } else { 828692f60a7Smrg pre = 160; 829692f60a7Smrg post = 0; 830692f60a7Smrg } 831692f60a7Smrg offset -= 2 * scale * pre; 832692f60a7Smrg dstBox->x1 -= pre; 833692f60a7Smrg dstBox->x2 += post; 834692f60a7Smrg } 835692f60a7Smrg if (nPtr->videoHZoom != 1.0) { 836692f60a7Smrg if ((dstBox->x2 += 5) > pScrn->virtualX) 837692f60a7Smrg dstBox->x2 = pScrn->virtualX; 838692f60a7Smrg if (dstBox->x1 > 0) dstBox->x1 += 2; 839692f60a7Smrg } 840692f60a7Smrg 841692f60a7Smrg fmt = 0x00; 842692f60a7Smrg switch (id){ 843692f60a7Smrg case FOURCC_YV12: 844692f60a7Smrg case FOURCC_I420: 845692f60a7Smrg case FOURCC_YUY2: 846692f60a7Smrg fmt = 0x00; 847692f60a7Smrg break; 848692f60a7Smrg case FOURCC_RV15: 849692f60a7Smrg case FOURCC_RV16: 850692f60a7Smrg fmt = 0x20; 851692f60a7Smrg break; 852692f60a7Smrg } 853692f60a7Smrg 854692f60a7Smrg offset += (x1 >> 15) & ~0x03; 855692f60a7Smrg 856692f60a7Smrg switch (nPtr->NeoChipset) { 857692f60a7Smrg default: 858692f60a7Smrg case NM2090: 859692f60a7Smrg case NM2093: 860692f60a7Smrg case NM2097: 861692f60a7Smrg case NM2160: 862692f60a7Smrg offset/=2; 863692f60a7Smrg pitch/=2; 864692f60a7Smrg OUTGR(0xbc, 0x4f); 865692f60a7Smrg break; 866692f60a7Smrg case NM2200: 867692f60a7Smrg case NM2230: 868692f60a7Smrg case NM2360: 869692f60a7Smrg case NM2380: 870692f60a7Smrg OUTGR(0xbc, 0x2e); 871692f60a7Smrg break; 872692f60a7Smrg } 873692f60a7Smrg 874692f60a7Smrg /* factor 4 for granularity */ 875692f60a7Smrg hstretch = (double)0x1000 * 4 / (int)(nPtr->videoHZoom * 4); 876692f60a7Smrg if (drw_w > src_w) 877692f60a7Smrg hstretch = (((int)src_w) * hstretch) / (int) drw_w; 878692f60a7Smrg 879692f60a7Smrg vstretch = (double)0x1000 / nPtr->videoVZoom; 880692f60a7Smrg if (drw_h > src_h) 881692f60a7Smrg vstretch = (((int)src_h) * vstretch )/ (int) drw_h; 882692f60a7Smrg 883692f60a7Smrg OUTGR(0xb1, (((dstBox->x2 - 1) >> 4) & 0xf0) | ((dstBox->x1 >> 8) & 0x0f)); 884692f60a7Smrg OUTGR(0xb2, dstBox->x1); 885692f60a7Smrg OUTGR(0xb3, dstBox->x2 - 1); 886692f60a7Smrg OUTGR(0xb4, (((dstBox->y2 - 1) >> 4) & 0xf0) | ((dstBox->y1 >> 8) & 0x0f)); 887692f60a7Smrg OUTGR(0xb5, dstBox->y1); 888692f60a7Smrg OUTGR(0xb6, dstBox->y2 - 1); 889692f60a7Smrg OUTGR(0xb7, offset >> 16); 890692f60a7Smrg OUTGR(0xb8, offset >> 8); 891692f60a7Smrg OUTGR(0xb9, offset ); 892692f60a7Smrg OUTGR(0xba, pitch >> 8); 893692f60a7Smrg OUTGR(0xbb, pitch); 894692f60a7Smrg 895692f60a7Smrg OUTGR(0xbd, 0x02); 896692f60a7Smrg OUTGR(0xbe, 0x00); 897692f60a7Smrg OUTGR(0xbf, 0x02); 898692f60a7Smrg 899692f60a7Smrg OUTGR(0xc0, hstretch >> 8); 900692f60a7Smrg OUTGR(0xc1, hstretch); 901692f60a7Smrg OUTGR(0xc2, vstretch >> 8); 902692f60a7Smrg OUTGR(0xc3, vstretch); 903692f60a7Smrg 904692f60a7Smrg OUTGR(0xb0, fmt | 0x03); 905692f60a7Smrg 906692f60a7Smrg OUTGR(0x0a, 0x21); 907692f60a7Smrg OUTSR(0x08, 0xa0); 908692f60a7Smrg OUTGR(0x0a, 0x01); 909692f60a7Smrg} 910692f60a7Smrg 911692f60a7Smrgstatic void 912692f60a7SmrgNEOInitOffscreenImages(ScreenPtr pScreen) 913692f60a7Smrg{ 914692f60a7Smrg XF86OffscreenImagePtr offscreenImages; 915692f60a7Smrg 916692f60a7Smrg#ifdef DEBUG 9173f6d0e1dSmrg xf86DrvMsg(xf86ScreenToScrn(pScreen)->scrnIndex,X_INFO,"NEOInitOffscreenImages\n"); 918692f60a7Smrg#endif 9193f6d0e1dSmrg if ((offscreenImages = malloc(sizeof(XF86OffscreenImageRec))) == NULL){ 920692f60a7Smrg return; 921692f60a7Smrg } 922692f60a7Smrg 923692f60a7Smrg offscreenImages->image = NEOVideoImages; 924692f60a7Smrg offscreenImages->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 925692f60a7Smrg offscreenImages->alloc_surface = NEOAllocSurface; 926692f60a7Smrg offscreenImages->free_surface = NEOFreeSurface; 927692f60a7Smrg offscreenImages->display = NEODisplaySurface; 928692f60a7Smrg offscreenImages->stop = NEOStopSurface; 929692f60a7Smrg offscreenImages->getAttribute = NEOGetSurfaceAttribute; 930692f60a7Smrg offscreenImages->setAttribute = NEOSetSurfaceAttribute; 931692f60a7Smrg offscreenImages->max_width = 1024; 932692f60a7Smrg offscreenImages->max_height = 1024; 933692f60a7Smrg offscreenImages->num_attributes = nElems(NEOVideoAttributes); 934692f60a7Smrg offscreenImages->attributes = NEOVideoAttributes; 935692f60a7Smrg 936692f60a7Smrg xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); 937692f60a7Smrg} 938692f60a7Smrg 939692f60a7Smrgstatic FBLinearPtr 940692f60a7SmrgNEOAllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size) 941692f60a7Smrg{ 942692f60a7Smrg ScreenPtr pScreen; 943692f60a7Smrg FBLinearPtr new_linear; 944692f60a7Smrg int bytespp = pScrn->bitsPerPixel >> 3; 945692f60a7Smrg 946692f60a7Smrg /* convert size in bytes into number of pixels */ 947692f60a7Smrg size = (size + bytespp - 1) / bytespp; 948692f60a7Smrg#ifdef DEBUG 949692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, 950692f60a7Smrg "NEOAllocateMemory: linear=%x, size=%d\n", linear, size); 951692f60a7Smrg#endif 952692f60a7Smrg if (linear){ 953692f60a7Smrg#ifdef DEBUG 954692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, 955692f60a7Smrg "NEOAllocateMemory: linear->size=%d\n", linear->size); 956692f60a7Smrg#endif 957692f60a7Smrg if (linear->size >= size){ 958692f60a7Smrg return (linear); 959692f60a7Smrg } 960692f60a7Smrg 961692f60a7Smrg if (xf86ResizeOffscreenLinear(linear, size)){ 962692f60a7Smrg return (linear); 963692f60a7Smrg } 964692f60a7Smrg 965692f60a7Smrg xf86FreeOffscreenLinear(linear); 966692f60a7Smrg } 967692f60a7Smrg 968692f60a7Smrg 9693f6d0e1dSmrg pScreen = xf86ScrnToScreen(pScrn); 970692f60a7Smrg if ((new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, NULL, 971692f60a7Smrg NULL, NULL)) == NULL){ 972692f60a7Smrg int max_size; 973692f60a7Smrg 974692f60a7Smrg xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, 975692f60a7Smrg PRIORITY_EXTREME); 976692f60a7Smrg#ifdef DEBUG 977692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, 978692f60a7Smrg "NEOAllocateMemory: max_size=%d\n", max_size); 979692f60a7Smrg#endif 980692f60a7Smrg if (max_size < size){ 981692f60a7Smrg return (NULL); 982692f60a7Smrg } 983692f60a7Smrg 984692f60a7Smrg xf86PurgeUnlockedOffscreenAreas(pScreen); 985692f60a7Smrg new_linear = xf86AllocateOffscreenLinear(pScreen, 986692f60a7Smrg size, 16, NULL, NULL, NULL); 987692f60a7Smrg } 988692f60a7Smrg 989692f60a7Smrg return (new_linear); 990692f60a7Smrg} 991692f60a7Smrg 992692f60a7Smrgstatic int 993692f60a7SmrgNEOAllocSurface(ScrnInfoPtr pScrn, int id, 994692f60a7Smrg unsigned short width, unsigned short height, 995692f60a7Smrg XF86SurfacePtr surface) 996692f60a7Smrg{ 997692f60a7Smrg int pitch, size; 998692f60a7Smrg NEOOffscreenPtr pPriv; 999692f60a7Smrg FBLinearPtr linear; 1000692f60a7Smrg 1001692f60a7Smrg#ifdef DEBUG 1002692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOAllocSurface\n"); 1003692f60a7Smrg#endif 1004692f60a7Smrg if (width > 1024 || height > 1024){ 1005692f60a7Smrg return (BadAlloc); 1006692f60a7Smrg } 1007692f60a7Smrg 1008692f60a7Smrg width = (width + 1) & ~1; 1009692f60a7Smrg pitch = ((width << 1) + 15) & ~15; 1010692f60a7Smrg size = pitch * height; 1011692f60a7Smrg 1012692f60a7Smrg if ((linear = NEOAllocateMemory(pScrn, NULL, size)) == NULL){ 1013692f60a7Smrg return (BadAlloc); 1014692f60a7Smrg } 1015692f60a7Smrg 1016692f60a7Smrg surface->width = width; 1017692f60a7Smrg surface->height = height; 10183f6d0e1dSmrg if ((surface->pitches = malloc(sizeof(int))) == NULL){ 1019692f60a7Smrg xf86FreeOffscreenLinear(linear); 1020692f60a7Smrg return (BadAlloc); 1021692f60a7Smrg } 10223f6d0e1dSmrg if ((surface->offsets = malloc(sizeof(int))) == NULL){ 10233f6d0e1dSmrg free(surface->pitches); 1024692f60a7Smrg xf86FreeOffscreenLinear(linear); 1025692f60a7Smrg return (BadAlloc); 1026692f60a7Smrg } 1027692f60a7Smrg 10283f6d0e1dSmrg if ((pPriv = malloc(sizeof(NEOOffscreenRec))) == NULL){ 10293f6d0e1dSmrg free(surface->pitches); 10303f6d0e1dSmrg free(surface->offsets); 1031692f60a7Smrg xf86FreeOffscreenLinear(linear); 1032692f60a7Smrg return (BadAlloc); 1033692f60a7Smrg } 1034692f60a7Smrg 1035692f60a7Smrg pPriv->linear = linear; 1036692f60a7Smrg pPriv->isOn = FALSE; 1037692f60a7Smrg 1038692f60a7Smrg surface->pScrn = pScrn; 1039692f60a7Smrg surface->id = id; 1040692f60a7Smrg surface->pitches[0] = pitch; 1041692f60a7Smrg surface->offsets[0] = linear->offset << 1; 1042692f60a7Smrg surface->devPrivate.ptr = (pointer)pPriv; 1043692f60a7Smrg return (Success); 1044692f60a7Smrg} 1045692f60a7Smrg 1046692f60a7Smrgstatic int 1047692f60a7SmrgNEOFreeSurface(XF86SurfacePtr surface) 1048692f60a7Smrg{ 1049692f60a7Smrg NEOOffscreenPtr pPriv = (NEOOffscreenPtr)surface->devPrivate.ptr; 1050692f60a7Smrg 1051692f60a7Smrg#ifdef DEBUG 1052692f60a7Smrg xf86DrvMsg(0,X_INFO,"NEOFreeSurface\n"); 1053692f60a7Smrg#endif 1054692f60a7Smrg if (pPriv->isOn) 1055692f60a7Smrg NEOStopSurface(surface); 1056692f60a7Smrg 1057692f60a7Smrg xf86FreeOffscreenLinear(pPriv->linear); 10583f6d0e1dSmrg free(surface->pitches); 10593f6d0e1dSmrg free(surface->offsets); 10603f6d0e1dSmrg free(surface->devPrivate.ptr); 1061692f60a7Smrg return (Success); 1062692f60a7Smrg} 1063692f60a7Smrg 1064692f60a7Smrgstatic int 1065692f60a7SmrgNEODisplaySurface(XF86SurfacePtr surface, 1066692f60a7Smrg short src_x, short src_y, short drw_x, short drw_y, 1067692f60a7Smrg short src_w, short src_h, short drw_w, short drw_h, 1068692f60a7Smrg RegionPtr clipBoxes) 1069692f60a7Smrg{ 1070692f60a7Smrg NEOOffscreenPtr pPriv = (NEOOffscreenPtr)surface->devPrivate.ptr; 1071692f60a7Smrg NEOPtr nPtr = NEOPTR(surface->pScrn); 1072692f60a7Smrg NEOPortPtr portPriv = nPtr->overlayAdaptor->pPortPrivates[0].ptr; 1073692f60a7Smrg INT32 x1, y1, x2, y2; 1074692f60a7Smrg BoxRec dstBox; 1075692f60a7Smrg 1076692f60a7Smrg#ifdef DEBUG 1077692f60a7Smrg xf86DrvMsg(surface->pScrn->scrnIndex,X_INFO,"NEODisplaySurface\n"); 1078692f60a7Smrg#endif 1079692f60a7Smrg x1 = src_x; 1080692f60a7Smrg x2 = src_x + src_w; 1081692f60a7Smrg y1 = src_y; 1082692f60a7Smrg y2 = src_y + src_h; 1083692f60a7Smrg 1084692f60a7Smrg dstBox.x1 = drw_x; 1085692f60a7Smrg dstBox.x2 = drw_x + drw_w; 1086692f60a7Smrg dstBox.y1 = drw_y; 1087692f60a7Smrg dstBox.y2 = drw_y + drw_h; 1088692f60a7Smrg if (!xf86XVClipVideoHelper( &dstBox, &x1, &x2, &y1, &y2, 1089692f60a7Smrg clipBoxes, surface->width, surface->height)){ 1090692f60a7Smrg return (Success); 1091692f60a7Smrg } 1092692f60a7Smrg 1093692f60a7Smrg dstBox.x1 -= surface->pScrn->frameX0; 1094692f60a7Smrg dstBox.y1 -= surface->pScrn->frameY0; 1095692f60a7Smrg dstBox.x2 -= surface->pScrn->frameX0; 1096692f60a7Smrg dstBox.y2 -= surface->pScrn->frameY0; 1097692f60a7Smrg 1098692f60a7Smrg xf86XVFillKeyHelper(surface->pScrn->pScreen, portPriv->colorKey, 1099692f60a7Smrg clipBoxes); 1100692f60a7Smrg NEOResetVideo(surface->pScrn); 1101692f60a7Smrg NEODisplayVideo(surface->pScrn, surface->id, surface->offsets[0], 1102692f60a7Smrg surface->width, surface->height, surface->pitches[0], 1103692f60a7Smrg x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 1104692f60a7Smrg 1105692f60a7Smrg pPriv->isOn = TRUE; 1106692f60a7Smrg if (portPriv->videoStatus & CLIENT_VIDEO_ON){ 1107692f60a7Smrg REGION_EMPTY(surface->pScrn->pScreen, &portPriv->clip); 1108692f60a7Smrg UpdateCurrentTime(); 1109692f60a7Smrg portPriv->videoStatus = FREE_TIMER; 1110692f60a7Smrg portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 1111692f60a7Smrg } 1112692f60a7Smrg return (Success); 1113692f60a7Smrg} 1114692f60a7Smrg 1115692f60a7Smrgstatic int 1116692f60a7SmrgNEOStopSurface(XF86SurfacePtr surface) 1117692f60a7Smrg{ 1118692f60a7Smrg NEOOffscreenPtr pPriv = (NEOOffscreenPtr)surface->devPrivate.ptr; 1119692f60a7Smrg 1120692f60a7Smrg#ifdef DEBUG 1121692f60a7Smrg xf86DrvMsg(surface->pScrn->scrnIndex,X_INFO,"NEOStopSurface\n"); 1122692f60a7Smrg#endif 1123692f60a7Smrg if (pPriv->isOn){ 1124692f60a7Smrg NEOPtr nPtr = NEOPTR(surface->pScrn); 1125692f60a7Smrg VGA_HWP(surface->pScrn); 1126692f60a7Smrg OUTGR(0xb0, 0x02); 1127692f60a7Smrg pPriv->isOn = FALSE; 1128692f60a7Smrg } 1129692f60a7Smrg return (Success); 1130692f60a7Smrg} 1131692f60a7Smrg 1132692f60a7Smrgstatic int 1133692f60a7SmrgNEOGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 *value) 1134692f60a7Smrg{ 1135692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 1136692f60a7Smrg 1137692f60a7Smrg#ifdef DEBUG 1138692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOGetSurfaceAttribute\n"); 1139692f60a7Smrg#endif 1140692f60a7Smrg return (NEOGetPortAttribute(pScrn, 1141692f60a7Smrg attr, value, (pointer)nPtr->overlayAdaptor->pPortPrivates[0].ptr)); 1142692f60a7Smrg} 1143692f60a7Smrg 1144692f60a7Smrgstatic int 1145692f60a7SmrgNEOSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 value) 1146692f60a7Smrg{ 1147692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 1148692f60a7Smrg 1149692f60a7Smrg#ifdef DEBUG 1150692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOSetSurfaceAttribute\n"); 1151692f60a7Smrg#endif 1152692f60a7Smrg return (NEOSetPortAttribute(pScrn, 1153692f60a7Smrg attr, value, (pointer)nPtr->overlayAdaptor->pPortPrivates[0].ptr)); 1154692f60a7Smrg} 1155