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