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