s3v_xv.c revision ba85709e
11d54945dSmrg/* 21d54945dSmrgCopyright (C) 2000 The XFree86 Project, Inc. All Rights Reserved. 31d54945dSmrg 41d54945dSmrgPermission is hereby granted, free of charge, to any person obtaining a copy of 51d54945dSmrgthis software and associated documentation files (the "Software"), to deal in 61d54945dSmrgthe Software without restriction, including without limitation the rights to 71d54945dSmrguse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 81d54945dSmrgof the Software, and to permit persons to whom the Software is furnished to do 91d54945dSmrgso, subject to the following conditions: 101d54945dSmrg 111d54945dSmrgThe above copyright notice and this permission notice shall be included in all 121d54945dSmrgcopies or substantial portions of the Software. 131d54945dSmrg 141d54945dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 151d54945dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- 161d54945dSmrgNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 171d54945dSmrgXFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 181d54945dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 191d54945dSmrgWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 201d54945dSmrg 211d54945dSmrgExcept as contained in this notice, the name of the XFree86 Project shall not 221d54945dSmrgbe used in advertising or otherwise to promote the sale, use or other dealings 231d54945dSmrgin this Software without prior written authorization from the XFree86 Project. 241d54945dSmrg*/ 251d54945dSmrg 261d54945dSmrg/* 271d54945dSmrg * s3v_xv.c 281d54945dSmrg * X Video Extension support 291d54945dSmrg * 301d54945dSmrg * S3 ViRGE driver 311d54945dSmrg * 321d54945dSmrg * 7/2000 Kevin Brosius 331d54945dSmrg * 341d54945dSmrg * Useful references: 351d54945dSmrg * X Video extension support -> xc/programs/hw/xfree86/common/xf86xv.c 361d54945dSmrg * 371d54945dSmrg */ 381d54945dSmrg 391d54945dSmrg#ifdef HAVE_CONFIG_H 401d54945dSmrg#include "config.h" 411d54945dSmrg#endif 421d54945dSmrg 431d54945dSmrg /* Most xf86 commons are already in s3v.h */ 441d54945dSmrg#include "s3v.h" 451d54945dSmrg 461d54945dSmrg#if 0 471d54945dSmrg#define OFF_DELAY 250 /* milliseconds */ 481d54945dSmrg#define FREE_DELAY 15000 491d54945dSmrg 501d54945dSmrg#define OFF_TIMER 0x01 511d54945dSmrg#define FREE_TIMER 0x02 521d54945dSmrg#endif 531d54945dSmrg#define CLIENT_VIDEO_ON 0x04 541d54945dSmrg 551d54945dSmrg#define S3V_MAX_PORTS 1 561d54945dSmrg 571d54945dSmrg#if 0 581d54945dSmrgstatic void S3VInitOffscreenImages(ScreenPtr); 591d54945dSmrg#endif 601d54945dSmrg 611d54945dSmrgstatic XF86VideoAdaptorPtr S3VAllocAdaptor(ScrnInfoPtr pScrn); 621d54945dSmrgstatic XF86VideoAdaptorPtr S3VSetupImageVideoOverlay(ScreenPtr); 631d54945dSmrgstatic int S3VSetPortAttributeOverlay(ScrnInfoPtr, Atom, INT32, pointer); 641d54945dSmrgstatic int S3VGetPortAttributeOverlay(ScrnInfoPtr, Atom ,INT32 *, pointer); 651d54945dSmrg 66ba85709eSmrg 671d54945dSmrgstatic void S3VStopVideo(ScrnInfoPtr, pointer, Bool); 681d54945dSmrgstatic void S3VQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, 691d54945dSmrg unsigned int *, unsigned int *, pointer); 701d54945dSmrgstatic int S3VPutImage(ScrnInfoPtr, short, short, short, short, short, 711d54945dSmrg short, short, short, int, unsigned char*, short, 721d54945dSmrg short, Bool, RegionPtr, pointer, DrawablePtr); 731d54945dSmrgstatic int S3VQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, 741d54945dSmrg unsigned short *, int *, int *); 751d54945dSmrg 761d54945dSmrg 771d54945dSmrgstatic void S3VResetVideoOverlay(ScrnInfoPtr); 781d54945dSmrg 791d54945dSmrg#if 0 801d54945dSmrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 811d54945dSmrg 821d54945dSmrgstatic Atom xvBrightness, xvContrast, xvColorKey; 831d54945dSmrg 841d54945dSmrg#endif /* 0 */ 851d54945dSmrg 861d54945dSmrgint S3VQueryXvCapable(ScrnInfoPtr pScrn) 871d54945dSmrg{ 881d54945dSmrg S3VPtr ps3v = S3VPTR(pScrn); 891d54945dSmrg 901d54945dSmrg if( 911d54945dSmrg ((pScrn->bitsPerPixel == 24) || 921d54945dSmrg (pScrn->bitsPerPixel == 16) 931d54945dSmrg ) 941d54945dSmrg && 951d54945dSmrg ((ps3v->Chipset == S3_ViRGE_DXGX) || 961d54945dSmrg S3_ViRGE_MX_SERIES(ps3v->Chipset) || 971d54945dSmrg S3_ViRGE_GX2_SERIES(ps3v->Chipset) 981d54945dSmrg )) 991d54945dSmrg return TRUE; 1001d54945dSmrg else 1011d54945dSmrg return FALSE; 1021d54945dSmrg} 1031d54945dSmrg 1041d54945dSmrg 1051d54945dSmrgvoid S3VInitVideo(ScreenPtr pScreen) 1061d54945dSmrg{ 1071d54945dSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1081d54945dSmrg XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 1091d54945dSmrg XF86VideoAdaptorPtr newAdaptor = NULL; 1101d54945dSmrg S3VPtr ps3v = S3VPTR(pScrn); 1111d54945dSmrg int num_adaptors; 1121d54945dSmrg 1131d54945dSmrg if( 1141d54945dSmrg ((pScrn->bitsPerPixel == 24) || 1151d54945dSmrg (pScrn->bitsPerPixel == 16) 1161d54945dSmrg ) 1171d54945dSmrg && 1181d54945dSmrg ((ps3v->Chipset == S3_ViRGE_DXGX) || 1191d54945dSmrg S3_ViRGE_MX_SERIES(ps3v->Chipset) || 1201d54945dSmrg S3_ViRGE_GX2_SERIES(ps3v->Chipset) /* || */ 1211d54945dSmrg /* (ps3v->Chipset == S3_ViRGE) */ 1221d54945dSmrg ) 1231d54945dSmrg && !ps3v->NoAccel 1241d54945dSmrg && ps3v->XVideo 1251d54945dSmrg ) 1261d54945dSmrg { 1271d54945dSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using overlay video\n"); 1281d54945dSmrg newAdaptor = S3VSetupImageVideoOverlay(pScreen); 1291d54945dSmrg } 1301d54945dSmrg 1311d54945dSmrg 1321d54945dSmrg num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 1331d54945dSmrg 1341d54945dSmrg if(newAdaptor) { 1351d54945dSmrg if(!num_adaptors) { 1361d54945dSmrg num_adaptors = 1; 1371d54945dSmrg adaptors = &newAdaptor; 1381d54945dSmrg } else { 1391d54945dSmrg newAdaptors = /* need to free this someplace */ 1401d54945dSmrg xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); 1411d54945dSmrg if(newAdaptors) { 1421d54945dSmrg memcpy(newAdaptors, adaptors, num_adaptors * 1431d54945dSmrg sizeof(XF86VideoAdaptorPtr)); 1441d54945dSmrg newAdaptors[num_adaptors] = newAdaptor; 1451d54945dSmrg adaptors = newAdaptors; 1461d54945dSmrg num_adaptors++; 1471d54945dSmrg } 1481d54945dSmrg } 1491d54945dSmrg } 1501d54945dSmrg 1511d54945dSmrg if(num_adaptors) 1521d54945dSmrg xf86XVScreenInit(pScreen, adaptors, num_adaptors); 1531d54945dSmrg 1541d54945dSmrg if(newAdaptors) 1551d54945dSmrg xfree(newAdaptors); 1561d54945dSmrg} 1571d54945dSmrg 1581d54945dSmrg/* client libraries expect an encoding */ 1591d54945dSmrgstatic XF86VideoEncodingRec DummyEncoding[2] = 1601d54945dSmrg{ 1611d54945dSmrg { /* overlay limit */ 1621d54945dSmrg 0, 1631d54945dSmrg "XV_IMAGE", 1641d54945dSmrg 1024, 1024, 1651d54945dSmrg {1, 1} 1661d54945dSmrg }, 1671d54945dSmrg { /* texture limit */ 1681d54945dSmrg 0, 1691d54945dSmrg "XV_IMAGE", 1701d54945dSmrg 2046, 2046, 1711d54945dSmrg {1, 1} 1721d54945dSmrg } 1731d54945dSmrg}; 1741d54945dSmrg 1751d54945dSmrg#define NUM_FORMATS_OVERLAY 4 1761d54945dSmrg#define NUM_FORMATS_TEXTURE 4 1771d54945dSmrg 1781d54945dSmrgstatic XF86VideoFormatRec Formats[NUM_FORMATS_TEXTURE] = 1791d54945dSmrg{ 1801d54945dSmrg /*{15, TrueColor},*/ {16, TrueColor}, {24, TrueColor} /* , 1811d54945dSmrg {15, DirectColor}*/, {16, DirectColor}, {24, DirectColor} 1821d54945dSmrg}; 1831d54945dSmrg 1841d54945dSmrg#if 0 1851d54945dSmrg#define NUM_ATTRIBUTES_OVERLAY 3 1861d54945dSmrg 1871d54945dSmrgstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES_OVERLAY] = 1881d54945dSmrg{ 1891d54945dSmrg {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 1901d54945dSmrg {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, 1911d54945dSmrg {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"} 1921d54945dSmrg}; 1931d54945dSmrg#endif 1941d54945dSmrg 1951d54945dSmrg#define NUM_IMAGES 3 1961d54945dSmrg 1971d54945dSmrgstatic XF86ImageRec Images[NUM_IMAGES] = 1981d54945dSmrg{ 1991d54945dSmrg XVIMAGE_YUY2, 2001d54945dSmrg /* As in mga, YV12 & I420 are converted to YUY2 on the fly by */ 2011d54945dSmrg /* copy over conversion. */ 2021d54945dSmrg XVIMAGE_YV12, 2031d54945dSmrg XVIMAGE_I420 2041d54945dSmrg /* XVIMAGE_UYVY */ 2051d54945dSmrg}; 2061d54945dSmrg 2071d54945dSmrg 2081d54945dSmrg 2091d54945dSmrgstatic int 2101d54945dSmrgS3VSetPortAttributeOverlay( 2111d54945dSmrg ScrnInfoPtr pScrn, 2121d54945dSmrg Atom attribute, 2131d54945dSmrg INT32 value, 2141d54945dSmrg pointer data 2151d54945dSmrg){ 2161d54945dSmrg 2171d54945dSmrgreturn BadMatch; 2181d54945dSmrg 2191d54945dSmrg} 2201d54945dSmrg 2211d54945dSmrgstatic int 2221d54945dSmrgS3VGetPortAttributeOverlay( 2231d54945dSmrg ScrnInfoPtr pScrn, 2241d54945dSmrg Atom attribute, 2251d54945dSmrg INT32 *value, 2261d54945dSmrg pointer data 2271d54945dSmrg){ 228ba85709eSmrg 2291d54945dSmrg 2301d54945dSmrgreturn BadMatch; 2311d54945dSmrg 2321d54945dSmrg} 2331d54945dSmrg 2341d54945dSmrg 2351d54945dSmrg 2361d54945dSmrgstatic void 2371d54945dSmrgS3VQueryBestSize( 2381d54945dSmrg ScrnInfoPtr pScrn, 2391d54945dSmrg Bool motion, 2401d54945dSmrg short vid_w, short vid_h, 2411d54945dSmrg short drw_w, short drw_h, 2421d54945dSmrg unsigned int *p_w, unsigned int *p_h, 2431d54945dSmrg pointer data 2441d54945dSmrg){ 2451d54945dSmrg *p_w = drw_w; 2461d54945dSmrg *p_h = drw_h; 2471d54945dSmrg 2481d54945dSmrg#if 0 2491d54945dSmrg /* Only support scaling up, no down scaling. */ 2501d54945dSmrg /* This doesn't seem to work (at least for XMovie) */ 2511d54945dSmrg /* and the DESIGN doc says this is illegal anyway... */ 2521d54945dSmrg if( drw_w < vid_w ) *p_w = vid_w; 2531d54945dSmrg if( drw_h < vid_h ) *p_h = vid_h; 2541d54945dSmrg#endif 2551d54945dSmrg} 2561d54945dSmrg 2571d54945dSmrg 2581d54945dSmrg 2591d54945dSmrgstatic void 2601d54945dSmrgS3VResetVideoOverlay(ScrnInfoPtr pScrn) 2611d54945dSmrg{ 2621d54945dSmrg /* empty for ViRGE at the moment... */ 2631d54945dSmrg#if 0 2641d54945dSmrg S3VPtr ps3v = S3VPTR(pScrn); 2651d54945dSmrg S3VPortPrivPtr pPriv = ps3v->portPrivate; 2661d54945dSmrg 2671d54945dSmrg MGAPtr pMga = MGAPTR(pScrn); 2681d54945dSmrg MGAPortPrivPtr pPriv = pMga->portPrivate; 2691d54945dSmrg 2701d54945dSmrg CHECK_DMA_QUIESCENT(pMga, pScrn); 2711d54945dSmrg 2721d54945dSmrg outMGAdac(0x51, 0x01); /* keying on */ 2731d54945dSmrg outMGAdac(0x52, 0xff); /* full mask */ 2741d54945dSmrg outMGAdac(0x53, 0xff); 2751d54945dSmrg outMGAdac(0x54, 0xff); 2761d54945dSmrg 2771d54945dSmrg outMGAdac(0x55, (pPriv->colorKey & pScrn->mask.red) >> 2781d54945dSmrg pScrn->offset.red); 2791d54945dSmrg outMGAdac(0x56, (pPriv->colorKey & pScrn->mask.green) >> 2801d54945dSmrg pScrn->offset.green); 2811d54945dSmrg outMGAdac(0x57, (pPriv->colorKey & pScrn->mask.blue) >> 2821d54945dSmrg pScrn->offset.blue); 2831d54945dSmrg#endif 2841d54945dSmrg 2851d54945dSmrg#if 0 2861d54945dSmrg OUTREG(MGAREG_BESLUMACTL, ((pPriv->brightness & 0xff) << 16) | 2871d54945dSmrg (pPriv->contrast & 0xff)); 2881d54945dSmrg#endif /*0*/ 2891d54945dSmrg} 2901d54945dSmrg 2911d54945dSmrg 2921d54945dSmrg 2931d54945dSmrgstatic XF86VideoAdaptorPtr 2941d54945dSmrgS3VAllocAdaptor(ScrnInfoPtr pScrn) 2951d54945dSmrg{ 2961d54945dSmrg XF86VideoAdaptorPtr adapt; 2971d54945dSmrg S3VPtr ps3v = S3VPTR(pScrn); 2981d54945dSmrg S3VPortPrivPtr pPriv; 2991d54945dSmrg int i; 3001d54945dSmrg 3011d54945dSmrg if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn))) 3021d54945dSmrg return NULL; 3031d54945dSmrg 3041d54945dSmrg if(!(pPriv = xcalloc(1, sizeof(S3VPortPrivRec) + 3051d54945dSmrg (sizeof(DevUnion) * S3V_MAX_PORTS)))) 3061d54945dSmrg { 3071d54945dSmrg xfree(adapt); 3081d54945dSmrg return NULL; 3091d54945dSmrg } 3101d54945dSmrg 3111d54945dSmrg adapt->pPortPrivates = (DevUnion*)(&pPriv[1]); 3121d54945dSmrg 3131d54945dSmrg for(i = 0; i < S3V_MAX_PORTS; i++) 3141d54945dSmrg adapt->pPortPrivates[i].val = i; 3151d54945dSmrg 3161d54945dSmrg#if 0 3171d54945dSmrg xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 3181d54945dSmrg xvContrast = MAKE_ATOM("XV_CONTRAST"); 3191d54945dSmrg xvColorKey = MAKE_ATOM("XV_COLORKEY"); 3201d54945dSmrg#endif 3211d54945dSmrg 3221d54945dSmrg pPriv->colorKey = 3231d54945dSmrg (1 << pScrn->offset.red) | 3241d54945dSmrg (1 << pScrn->offset.green) | 3251d54945dSmrg (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue); 3261d54945dSmrg 3271d54945dSmrg#if 0 3281d54945dSmrg pPriv->brightness = 0; 3291d54945dSmrg pPriv->contrast = 128; 3301d54945dSmrg#endif 3311d54945dSmrg 3321d54945dSmrg pPriv->videoStatus = 0; 3331d54945dSmrg pPriv->lastPort = -1; 3341d54945dSmrg 3351d54945dSmrg ps3v->adaptor = adapt; 3361d54945dSmrg ps3v->portPrivate = pPriv; 3371d54945dSmrg 3381d54945dSmrg return adapt; 3391d54945dSmrg} 3401d54945dSmrg 3411d54945dSmrg 3421d54945dSmrg 3431d54945dSmrg 3441d54945dSmrg 3451d54945dSmrgstatic XF86VideoAdaptorPtr 3461d54945dSmrgS3VSetupImageVideoOverlay(ScreenPtr pScreen) 3471d54945dSmrg{ 3481d54945dSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 3491d54945dSmrg S3VPtr ps3v = S3VPTR(pScrn); 3501d54945dSmrg XF86VideoAdaptorPtr adapt; 3511d54945dSmrg 3521d54945dSmrg adapt = S3VAllocAdaptor(pScrn); 3531d54945dSmrg 3541d54945dSmrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 3551d54945dSmrg adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 3561d54945dSmrg adapt->name = "S3 ViRGE Backend Scaler"; 3571d54945dSmrg adapt->nEncodings = 1; 3581d54945dSmrg adapt->pEncodings = &DummyEncoding[0]; 3591d54945dSmrg adapt->nFormats = NUM_FORMATS_OVERLAY; 3601d54945dSmrg adapt->pFormats = Formats; 3611d54945dSmrg adapt->nPorts = 1; 3621d54945dSmrg adapt->pAttributes = NULL /*Attributes*/; 363ba85709eSmrg adapt->nImages = 3; 364ba85709eSmrg adapt->nAttributes = 0; 3651d54945dSmrg adapt->pImages = Images; 3661d54945dSmrg adapt->PutVideo = NULL; 3671d54945dSmrg adapt->PutStill = NULL; 3681d54945dSmrg adapt->GetVideo = NULL; 3691d54945dSmrg adapt->GetStill = NULL; 3701d54945dSmrg adapt->StopVideo = S3VStopVideo; 3711d54945dSmrg /* Empty Attrib functions - required anyway */ 3721d54945dSmrg adapt->SetPortAttribute = S3VSetPortAttributeOverlay; 3731d54945dSmrg adapt->GetPortAttribute = S3VGetPortAttributeOverlay; 3741d54945dSmrg adapt->QueryBestSize = S3VQueryBestSize; 3751d54945dSmrg adapt->PutImage = S3VPutImage; 3761d54945dSmrg adapt->QueryImageAttributes = S3VQueryImageAttributes; 3771d54945dSmrg 3781d54945dSmrg /* gotta uninit this someplace */ 3791d54945dSmrg REGION_NULL(pScreen, &(ps3v->portPrivate->clip)); 3801d54945dSmrg 3811d54945dSmrg S3VResetVideoOverlay(pScrn); 3821d54945dSmrg 3831d54945dSmrg return adapt; 3841d54945dSmrg} 3851d54945dSmrg 3861d54945dSmrg 3871d54945dSmrgstatic void 3881d54945dSmrgS3VStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) 3891d54945dSmrg{ 3901d54945dSmrg S3VPtr ps3v = S3VPTR(pScrn); 3911d54945dSmrg S3VPortPrivPtr pPriv = ps3v->portPrivate; 3921d54945dSmrg 3931d54945dSmrg REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 3941d54945dSmrg 3951d54945dSmrg if(shutdown) { 3961d54945dSmrg if(pPriv->videoStatus & CLIENT_VIDEO_ON) 3971d54945dSmrg { 3981d54945dSmrg if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 3991d54945dSmrg S3_ViRGE_MX_SERIES(ps3v->Chipset) 4001d54945dSmrg ) 4011d54945dSmrg { 4021d54945dSmrg /* Aaarg... It .. won't.. go .. away! */ 4031d54945dSmrg /* So let's be creative, make the overlay really */ 4041d54945dSmrg /* small and near an edge. */ 4051d54945dSmrg /* Size of 0 leaves a window sized vertical stripe */ 4061d54945dSmrg /* Size of 1 leaves a single pixel.. */ 4071d54945dSmrg OUTREG(SSTREAM_WINDOW_SIZE_REG, 1); 4081d54945dSmrg /* And hide it at 0,0 */ 4091d54945dSmrg OUTREG(SSTREAM_START_REG, 0 ); 4101d54945dSmrg } 4111d54945dSmrg else 4121d54945dSmrg { 4131d54945dSmrg /* Primary over secondary */ 4141d54945dSmrg OUTREG(BLEND_CONTROL_REG, 0x01000000); 4151d54945dSmrg } 4161d54945dSmrg } 4171d54945dSmrg 4181d54945dSmrg if(pPriv->area) { 4191d54945dSmrg xf86FreeOffscreenArea(pPriv->area); 4201d54945dSmrg pPriv->area = NULL; 4211d54945dSmrg } 4221d54945dSmrg pPriv->videoStatus = 0; 4231d54945dSmrg#if 0 4241d54945dSmrg } else { 4251d54945dSmrg if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 4261d54945dSmrg pPriv->videoStatus |= OFF_TIMER; 4271d54945dSmrg pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 4281d54945dSmrg } 4291d54945dSmrg#endif 4301d54945dSmrg } 4311d54945dSmrg} 4321d54945dSmrg 4331d54945dSmrg 4341d54945dSmrg 4351d54945dSmrgstatic FBAreaPtr 4361d54945dSmrgS3VAllocateMemory( 4371d54945dSmrg ScrnInfoPtr pScrn, 4381d54945dSmrg FBAreaPtr area, 4391d54945dSmrg int numlines 4401d54945dSmrg){ 4411d54945dSmrg ScreenPtr pScreen; 4421d54945dSmrg FBAreaPtr new_area; 4431d54945dSmrg 4441d54945dSmrg if(area) { 4451d54945dSmrg if((area->box.y2 - area->box.y1) >= numlines) 4461d54945dSmrg return area; 4471d54945dSmrg 4481d54945dSmrg if(xf86ResizeOffscreenArea(area, pScrn->displayWidth, numlines)) 4491d54945dSmrg return area; 4501d54945dSmrg 4511d54945dSmrg xf86FreeOffscreenArea(area); 4521d54945dSmrg } 4531d54945dSmrg 4541d54945dSmrg pScreen = screenInfo.screens[pScrn->scrnIndex]; 4551d54945dSmrg 4561d54945dSmrg new_area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, 4571d54945dSmrg numlines, 0, NULL, NULL, NULL); 4581d54945dSmrg 4591d54945dSmrg if(!new_area) { 4601d54945dSmrg int max_w, max_h; 4611d54945dSmrg 4621d54945dSmrg xf86QueryLargestOffscreenArea(pScreen, &max_w, &max_h, 0, 4631d54945dSmrg FAVOR_WIDTH_THEN_AREA, PRIORITY_EXTREME); 4641d54945dSmrg 4651d54945dSmrg if((max_w < pScrn->displayWidth) || (max_h < numlines)) 4661d54945dSmrg return NULL; 4671d54945dSmrg 4681d54945dSmrg xf86PurgeUnlockedOffscreenAreas(pScreen); 4691d54945dSmrg new_area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, 4701d54945dSmrg numlines, 0, NULL, NULL, NULL); 4711d54945dSmrg } 4721d54945dSmrg 4731d54945dSmrg return new_area; 4741d54945dSmrg} 4751d54945dSmrg 4761d54945dSmrg 4771d54945dSmrg 4781d54945dSmrgstatic void 4791d54945dSmrgS3VDisplayVideoOverlay( 4801d54945dSmrg ScrnInfoPtr pScrn, 4811d54945dSmrg int id, 4821d54945dSmrg int offset, 4831d54945dSmrg short width, short height, 4841d54945dSmrg int pitch, 4851d54945dSmrg /* x,y src co-ordinates */ 4861d54945dSmrg int x1, int y1, int x2, int y2, 4871d54945dSmrg /* dst in BoxPtr format */ 4881d54945dSmrg BoxPtr dstBox, 4891d54945dSmrg /* src width and height */ 4901d54945dSmrg short src_w, short src_h, 4911d54945dSmrg /* dst width and height */ 4921d54945dSmrg short drw_w, short drw_h 4931d54945dSmrg){ 4941d54945dSmrg int tmp; 4951d54945dSmrg 4961d54945dSmrg#if 0 4971d54945dSmrg CHECK_DMA_QUIESCENT(pMga, pScrn); 4981d54945dSmrg#endif 4991d54945dSmrg S3VPtr ps3v = S3VPTR(pScrn); 5001d54945dSmrg S3VPortPrivPtr pPriv = ps3v->portPrivate; 5011d54945dSmrg 5021d54945dSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 5031d54945dSmrg /* S3VPtr ps3v = S3VPTR(pScrn);*/ 5041d54945dSmrg int vgaCRIndex, vgaCRReg, vgaIOBase; 5051d54945dSmrg vgaIOBase = hwp->IOBase; 5061d54945dSmrg vgaCRIndex = vgaIOBase + 4; 5071d54945dSmrg vgaCRReg = vgaIOBase + 5; 5081d54945dSmrg 5091d54945dSmrg /* If streams aren't enabled, do nothing */ 5101d54945dSmrg if(!ps3v->NeedSTREAMS) 5111d54945dSmrg return; 5121d54945dSmrg 5131d54945dSmrg 5141d54945dSmrg /* Reference at http://www.webartz.com/fourcc/ */ 5151d54945dSmrg /* Looks like ViRGE only supports YUY2 and Y211?, */ 5161d54945dSmrg /* listed as YUV-16 (4.2.2) and YUV (2.1.1) in manual. */ 5171d54945dSmrg 5181d54945dSmrg#if 0 5191d54945dSmrg /* Only supporting modes we listed for the time being, */ 5201d54945dSmrg /* No, switching required... #if 0'd this out */ 5211d54945dSmrg 5221d54945dSmrg switch(id) { 5231d54945dSmrg case FOURCC_UYVY: 5241d54945dSmrg /* 5251d54945dSmrg FOURCC=0x59565955 5261d54945dSmrg bpp=16 5271d54945dSmrg YUV 4:2:2 (Y sample at every 5281d54945dSmrg pixel, U and V sampled at 5291d54945dSmrg every second pixel 5301d54945dSmrg horizontally on each line). A 5311d54945dSmrg macropixel contains 2 pixels 5321d54945dSmrg in 1 u_int32. 5331d54945dSmrg */ 5341d54945dSmrg 5351d54945dSmrg /* OUTREG(MGAREG_BESGLOBCTL, 0x000000c3 | (tmp << 16));*/ 5361d54945dSmrg break; 5371d54945dSmrg case FOURCC_YUY2: 5381d54945dSmrg /* 5391d54945dSmrg FOURCC=0x32595559 5401d54945dSmrg bpp=16 5411d54945dSmrg YUV 4:2:2 as for UYVY but 5421d54945dSmrg with different component 5431d54945dSmrg ordering within the u_int32 5441d54945dSmrg macropixel. 5451d54945dSmrg 5461d54945dSmrg Supports YV12 & I420 by copy over conversion of formats to YUY2, 5471d54945dSmrg copied from mga driver. Thanks Mark! 5481d54945dSmrg */ 5491d54945dSmrg default: 5501d54945dSmrg /*OUTREG(MGAREG_BESGLOBCTL, 0x00000083 | (tmp << 16));*/ 5511d54945dSmrg /* YUV-16 (4.2.2) Secondary stream */ 5521d54945dSmrg /* temp ... add DDA Horiz Accum. */ 5531d54945dSmrg /*OUTREG(SSTREAM_CONTROL_REG, 0x02000000); / YUV-16 */ 5541d54945dSmrg /* works for xvtest and suzi */ 5551d54945dSmrg /* OUTREG(SSTREAM_CONTROL_REG, 0x01000000); * YCbCr-16 * no scaling */ 5561d54945dSmrg 5571d54945dSmrg /* calc horizontal scale factor */ 5581d54945dSmrg tmp = drw_w / src_w; 5591d54945dSmrg if (drw_w == src_w) tmp = 0; 5601d54945dSmrg else if (tmp>=4) tmp =3; 5611d54945dSmrg else if (tmp>=2) tmp =2; 5621d54945dSmrg else tmp =1; 5631d54945dSmrg 5641d54945dSmrg /* YCbCr-16 */ 5651d54945dSmrg OUTREG(SSTREAM_CONTROL_REG, 5661d54945dSmrg tmp << 28 | 0x01000000 | 5671d54945dSmrg ((((src_w-1)<<1)-(drw_w-1)) & 0xfff) 5681d54945dSmrg ); 5691d54945dSmrg break; 5701d54945dSmrg } 5711d54945dSmrg#endif 5721d54945dSmrg 5731d54945dSmrg /* calc horizontal scale factor */ 5741d54945dSmrg if (drw_w == src_w) 5751d54945dSmrg tmp = 0; 5761d54945dSmrg else 5771d54945dSmrg tmp =2; 5781d54945dSmrg /* YCbCr-16 */ 5791d54945dSmrg OUTREG(SSTREAM_CONTROL_REG, 5801d54945dSmrg tmp << 28 | 0x01000000 | 5811d54945dSmrg ((((src_w-1)<<1)-(drw_w-1)) & 0xfff) 5821d54945dSmrg ); 5831d54945dSmrg 5841d54945dSmrg OUTREG(SSTREAM_STRETCH_REG, 5851d54945dSmrg ((src_w - 1) & 0x7ff) | (((src_w-drw_w-1) & 0x7ff) << 16) 5861d54945dSmrg ); 5871d54945dSmrg 5881d54945dSmrg /* Color key on primary */ 5891d54945dSmrg if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 5901d54945dSmrg S3_ViRGE_MX_SERIES(ps3v->Chipset) 5911d54945dSmrg ) 5921d54945dSmrg { 5931d54945dSmrg /* 100% of secondary, no primary */ 5941d54945dSmrg /* gx2/mx can both blend while keying, need to */ 5951d54945dSmrg /* select secondary here, otherwise all you'll get */ 5961d54945dSmrg /* from the primary is the color key. (And setting */ 5971d54945dSmrg /* 0 here gives you black... no primary or secondary. */ 5981d54945dSmrg /* Discovered that the hard way!) */ 5991d54945dSmrg OUTREG(BLEND_CONTROL_REG, 0x20 ); 6001d54945dSmrg } 6011d54945dSmrg else 6021d54945dSmrg { 6031d54945dSmrg OUTREG(BLEND_CONTROL_REG, 0x05000000); 6041d54945dSmrg } 6051d54945dSmrg 6061d54945dSmrg OUTREG(SSTREAM_FBADDR0_REG, offset & 0x3fffff ); 6071d54945dSmrg OUTREG(SSTREAM_STRIDE_REG, pitch & 0xfff ); 6081d54945dSmrg 6091d54945dSmrg OUTREG(K1_VSCALE_REG, src_h-1 ); 6101d54945dSmrg OUTREG(K2_VSCALE_REG, (src_h - drw_h) & 0x7ff ); 6111d54945dSmrg 6121d54945dSmrg if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 6131d54945dSmrg S3_ViRGE_MX_SERIES(ps3v->Chipset) ) 6141d54945dSmrg { 6151d54945dSmrg /* enable vert interp. & bandwidth saving - gx2 */ 6161d54945dSmrg OUTREG(DDA_VERT_REG, (((~drw_h)-1) & 0xfff ) | 6171d54945dSmrg /* bw & vert interp */ 6181d54945dSmrg 0xc000 6191d54945dSmrg /* no bw save 0x8000*/ 6201d54945dSmrg ); 6211d54945dSmrg } 6221d54945dSmrg else 6231d54945dSmrg { 6241d54945dSmrg OUTREG(DDA_VERT_REG, (((~drw_h)-1)) & 0xfff ); 6251d54945dSmrg } 6261d54945dSmrg 6271d54945dSmrg OUTREG(SSTREAM_START_REG, ((dstBox->x1 +1) << 16) | (dstBox->y1 +1)); 6281d54945dSmrg OUTREG(SSTREAM_WINDOW_SIZE_REG, 6291d54945dSmrg ( ((drw_w-1) << 16) | (drw_h ) ) & 0x7ff07ff 6301d54945dSmrg ); 6311d54945dSmrg 6321d54945dSmrg if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 6331d54945dSmrg S3_ViRGE_MX_SERIES(ps3v->Chipset) 6341d54945dSmrg ) 6351d54945dSmrg { 6361d54945dSmrg OUTREG(COL_CHROMA_KEY_CONTROL_REG, 6371d54945dSmrg /* color key ON - keying on primary */ 6381d54945dSmrg 0x40000000 | 6391d54945dSmrg /* # bits to compare */ 6401d54945dSmrg ((pScrn->weight.red-1) << 24) | 6411d54945dSmrg 6421d54945dSmrg ((pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red) << 6431d54945dSmrg (16 + 8-pScrn->weight.red) | 6441d54945dSmrg 6451d54945dSmrg ((pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green) << 6461d54945dSmrg (8 + 8-pScrn->weight.green) | 6471d54945dSmrg 6481d54945dSmrg ((pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue) << 6491d54945dSmrg (8-pScrn->weight.blue) 6501d54945dSmrg ); 6511d54945dSmrg } 6521d54945dSmrg else 6531d54945dSmrg { 6541d54945dSmrg OUTREG(COL_CHROMA_KEY_CONTROL_REG, 6551d54945dSmrg /* color key ON */ 6561d54945dSmrg 0x10000000 | 6571d54945dSmrg /* # bits to compare */ 6581d54945dSmrg ((pScrn->weight.red-1) << 24) | 6591d54945dSmrg 6601d54945dSmrg ((pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red) << 6611d54945dSmrg (16 + 8-pScrn->weight.red) | 6621d54945dSmrg 6631d54945dSmrg ((pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green) << 6641d54945dSmrg (8 + 8-pScrn->weight.green) | 6651d54945dSmrg 6661d54945dSmrg ((pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue) << 6671d54945dSmrg (8-pScrn->weight.blue) 6681d54945dSmrg ); 6691d54945dSmrg } 6701d54945dSmrg 6711d54945dSmrg if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 6721d54945dSmrg S3_ViRGE_MX_SERIES(ps3v->Chipset) ) 6731d54945dSmrg { 6741d54945dSmrg VGAOUT8(vgaCRIndex, 0x92); 6751d54945dSmrg VGAOUT8(vgaCRReg, (((pitch + 7) / 8) >> 8) | 0x80); 6761d54945dSmrg VGAOUT8(vgaCRIndex, 0x93); 6771d54945dSmrg VGAOUT8(vgaCRReg, (pitch + 7) / 8); 6781d54945dSmrg } 6791d54945dSmrg 6801d54945dSmrg} 6811d54945dSmrg 6821d54945dSmrg 6831d54945dSmrgstatic int 6841d54945dSmrgS3VPutImage( 6851d54945dSmrg ScrnInfoPtr pScrn, 6861d54945dSmrg short src_x, short src_y, 6871d54945dSmrg short drw_x, short drw_y, 6881d54945dSmrg short src_w, short src_h, 6891d54945dSmrg short drw_w, short drw_h, 6901d54945dSmrg int id, unsigned char* buf, 6911d54945dSmrg short width, short height, 6921d54945dSmrg Bool sync, 6931d54945dSmrg RegionPtr clipBoxes, pointer data, 6941d54945dSmrg DrawablePtr pDraw 6951d54945dSmrg){ 6961d54945dSmrg S3VPtr ps3v = S3VPTR(pScrn); 6971d54945dSmrg S3VPortPrivPtr pPriv = ps3v->portPrivate; 6981d54945dSmrg INT32 x1, x2, y1, y2; 6991d54945dSmrg unsigned char *dst_start; 7001d54945dSmrg int pitch, new_h, offset, offset2=0, offset3=0; 7011d54945dSmrg int srcPitch, srcPitch2=0, dstPitch; 7021d54945dSmrg int top, left, npixels, nlines; 7031d54945dSmrg BoxRec dstBox; 7041d54945dSmrg CARD32 tmp; 7051d54945dSmrg 7061d54945dSmrg /* If streams aren't enabled, do nothing */ 7071d54945dSmrg if(!ps3v->NeedSTREAMS) 7081d54945dSmrg return Success; 7091d54945dSmrg 7101d54945dSmrg /* Clip */ 7111d54945dSmrg x1 = src_x; 7121d54945dSmrg x2 = src_x + src_w; 7131d54945dSmrg y1 = src_y; 7141d54945dSmrg y2 = src_y + src_h; 7151d54945dSmrg 7161d54945dSmrg dstBox.x1 = drw_x; 7171d54945dSmrg dstBox.x2 = drw_x + drw_w; 7181d54945dSmrg dstBox.y1 = drw_y; 7191d54945dSmrg dstBox.y2 = drw_y + drw_h; 7201d54945dSmrg 7211d54945dSmrg if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, 7221d54945dSmrg clipBoxes, width, height)) 7231d54945dSmrg return Success; 7241d54945dSmrg 7251d54945dSmrg /*if(!pMga->TexturedVideo) {*/ 7261d54945dSmrg dstBox.x1 -= pScrn->frameX0; 7271d54945dSmrg dstBox.x2 -= pScrn->frameX0; 7281d54945dSmrg dstBox.y1 -= pScrn->frameY0; 7291d54945dSmrg dstBox.y2 -= pScrn->frameY0; 7301d54945dSmrg /*}*/ 7311d54945dSmrg 7321d54945dSmrg pitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3; 7331d54945dSmrg 7341d54945dSmrg dstPitch = ((width << 1) + 15) & ~15; 7351d54945dSmrg new_h = ((dstPitch * height) + pitch - 1) / pitch; 7361d54945dSmrg 7371d54945dSmrg switch(id) { 7381d54945dSmrg case FOURCC_YV12: 7391d54945dSmrg case FOURCC_I420: 7401d54945dSmrg srcPitch = (width + 3) & ~3; 7411d54945dSmrg offset2 = srcPitch * height; 7421d54945dSmrg srcPitch2 = ((width >> 1) + 3) & ~3; 7431d54945dSmrg offset3 = (srcPitch2 * (height >> 1)) + offset2; 7441d54945dSmrg break; 7451d54945dSmrg case FOURCC_UYVY: 7461d54945dSmrg case FOURCC_YUY2: 7471d54945dSmrg default: 7481d54945dSmrg srcPitch = (width << 1); 7491d54945dSmrg break; 7501d54945dSmrg } 7511d54945dSmrg 7521d54945dSmrg if(!(pPriv->area = S3VAllocateMemory(pScrn, pPriv->area, new_h))) 7531d54945dSmrg return BadAlloc; 7541d54945dSmrg 7551d54945dSmrg /* copy data */ 7561d54945dSmrg top = y1 >> 16; 7571d54945dSmrg left = (x1 >> 16) & ~1; 7581d54945dSmrg npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; 7591d54945dSmrg left <<= 1; 7601d54945dSmrg 7611d54945dSmrg offset = pPriv->area->box.y1 * pitch; 7621d54945dSmrg dst_start = ps3v->FBStart + offset + left + (top * dstPitch); 7631d54945dSmrg /*dst_start = pMga->FbStart + offset + left + (top * dstPitch);*/ 7641d54945dSmrg 7651d54945dSmrg 7661d54945dSmrg switch(id) { 7671d54945dSmrg case FOURCC_YV12: 7681d54945dSmrg case FOURCC_I420: 7691d54945dSmrg top &= ~1; 7701d54945dSmrg tmp = ((top >> 1) * srcPitch2) + (left >> 2); 7711d54945dSmrg offset2 += tmp; 7721d54945dSmrg offset3 += tmp; 7731d54945dSmrg if(id == FOURCC_I420) { 7741d54945dSmrg tmp = offset2; 7751d54945dSmrg offset2 = offset3; 7761d54945dSmrg offset3 = tmp; 7771d54945dSmrg } 7781d54945dSmrg nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; 7791d54945dSmrg xf86XVCopyYUV12ToPacked(buf + (top * srcPitch) + (left >> 1), 7801d54945dSmrg buf + offset2, buf + offset3, dst_start, 7811d54945dSmrg srcPitch, srcPitch2, dstPitch, nlines, npixels); 7821d54945dSmrg break; 7831d54945dSmrg case FOURCC_UYVY: 7841d54945dSmrg case FOURCC_YUY2: 7851d54945dSmrg default: 7861d54945dSmrg buf += (top * srcPitch) + left; 7871d54945dSmrg nlines = ((y2 + 0xffff) >> 16) - top; 7881d54945dSmrg xf86XVCopyPacked(buf, dst_start, srcPitch, dstPitch, nlines, npixels); 7891d54945dSmrg break; 7901d54945dSmrg } 7911d54945dSmrg 792ba85709eSmrg 7931d54945dSmrg /* update cliplist */ 7941d54945dSmrg if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { 7951d54945dSmrg REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 7961d54945dSmrg /* draw these */ 7971d54945dSmrg xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 7981d54945dSmrg } 7991d54945dSmrg 8001d54945dSmrg offset += left + (top * dstPitch); 8011d54945dSmrg S3VDisplayVideoOverlay(pScrn, id, offset, width, height, dstPitch, 8021d54945dSmrg x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 8031d54945dSmrg 8041d54945dSmrg pPriv->videoStatus = CLIENT_VIDEO_ON; 805ba85709eSmrg 8061d54945dSmrg 8071d54945dSmrg return Success; 8081d54945dSmrg} 8091d54945dSmrg 8101d54945dSmrg 8111d54945dSmrgstatic int 8121d54945dSmrgS3VQueryImageAttributes( 8131d54945dSmrg ScrnInfoPtr pScrn, 8141d54945dSmrg int id, 8151d54945dSmrg unsigned short *w, unsigned short *h, 8161d54945dSmrg int *pitches, int *offsets 8171d54945dSmrg){ 818ba85709eSmrg 8191d54945dSmrg int size, tmp; 8201d54945dSmrg 8211d54945dSmrg if(*w > 1024) *w = 1024; 8221d54945dSmrg if(*h > 1024) *h = 1024; 8231d54945dSmrg 8241d54945dSmrg *w = (*w + 1) & ~1; 8251d54945dSmrg if(offsets) offsets[0] = 0; 8261d54945dSmrg 8271d54945dSmrg switch(id) { 8281d54945dSmrg case FOURCC_YV12: 8291d54945dSmrg case FOURCC_I420: 8301d54945dSmrg *h = (*h + 1) & ~1; 8311d54945dSmrg size = (*w + 3) & ~3; 8321d54945dSmrg if(pitches) pitches[0] = size; 8331d54945dSmrg size *= *h; 8341d54945dSmrg if(offsets) offsets[1] = size; 8351d54945dSmrg tmp = ((*w >> 1) + 3) & ~3; 8361d54945dSmrg if(pitches) pitches[1] = pitches[2] = tmp; 8371d54945dSmrg tmp *= (*h >> 1); 8381d54945dSmrg size += tmp; 8391d54945dSmrg if(offsets) offsets[2] = size; 8401d54945dSmrg size += tmp; 8411d54945dSmrg break; 8421d54945dSmrg case FOURCC_UYVY: 8431d54945dSmrg case FOURCC_YUY2: 8441d54945dSmrg default: 8451d54945dSmrg size = *w << 1; 8461d54945dSmrg if(pitches) pitches[0] = size; 8471d54945dSmrg size *= *h; 8481d54945dSmrg break; 8491d54945dSmrg } 8501d54945dSmrg 8511d54945dSmrg return size; 8521d54945dSmrg} 853