ct_video.c revision 9f4658d1
1c06b6b69Smrg 2c06b6b69Smrg#ifdef HAVE_CONFIG_H 3c06b6b69Smrg#include "config.h" 4c06b6b69Smrg#endif 5c06b6b69Smrg 6c06b6b69Smrg#include "xf86.h" 7c06b6b69Smrg#include "xf86_OSproc.h" 8c06b6b69Smrg#include "xf86Resources.h" 9c06b6b69Smrg#include "compiler.h" 10c06b6b69Smrg#include "xf86PciInfo.h" 11c06b6b69Smrg#include "xf86Pci.h" 12c06b6b69Smrg#include "xf86fbman.h" 13c06b6b69Smrg#include "regionstr.h" 14c06b6b69Smrg 15c06b6b69Smrg#include "ct_driver.h" 16c06b6b69Smrg#include <X11/extensions/Xv.h> 17c06b6b69Smrg#include "xaa.h" 18c06b6b69Smrg#include "xaalocal.h" 19c06b6b69Smrg#include "dixstruct.h" 20c06b6b69Smrg#include "fourcc.h" 21c06b6b69Smrg 22c06b6b69Smrg#define OFF_DELAY 200 /* milliseconds */ 23c06b6b69Smrg#define FREE_DELAY 60000 24c06b6b69Smrg 25c06b6b69Smrg#define OFF_TIMER 0x01 26c06b6b69Smrg#define FREE_TIMER 0x02 27c06b6b69Smrg#define CLIENT_VIDEO_ON 0x04 28c06b6b69Smrg 29c06b6b69Smrg#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 30c06b6b69Smrg 31c06b6b69Smrgstatic XF86VideoAdaptorPtr CHIPSSetupImageVideo(ScreenPtr); 32c06b6b69Smrgstatic void CHIPSInitOffscreenImages(ScreenPtr); 33c06b6b69Smrgstatic void CHIPSStopVideo(ScrnInfoPtr, pointer, Bool); 34c06b6b69Smrgstatic int CHIPSSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 35c06b6b69Smrgstatic int CHIPSGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); 36c06b6b69Smrgstatic void CHIPSQueryBestSize(ScrnInfoPtr, Bool, 37c06b6b69Smrg short, short, short, short, unsigned int *, unsigned int *, pointer); 38c06b6b69Smrgstatic int CHIPSPutImage( ScrnInfoPtr, 39c06b6b69Smrg short, short, short, short, short, short, short, short, 40c06b6b69Smrg int, unsigned char*, short, short, Bool, RegionPtr, pointer, 41c06b6b69Smrg DrawablePtr); 42c06b6b69Smrgstatic int CHIPSQueryImageAttributes(ScrnInfoPtr, 43c06b6b69Smrg int, unsigned short *, unsigned short *, int *, int *); 44c06b6b69Smrgstatic void CHIPSVideoTimerCallback(ScrnInfoPtr pScrn, Time time); 45c06b6b69Smrg 46c06b6b69Smrg 47c06b6b69Smrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 48c06b6b69Smrg 49c06b6b69Smrgstatic Atom xvColorKey; 50c06b6b69Smrg 51c06b6b69Smrgvoid 52c06b6b69SmrgCHIPSInitVideo(ScreenPtr pScreen) 53c06b6b69Smrg{ 54c06b6b69Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 55c06b6b69Smrg XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 56c06b6b69Smrg XF86VideoAdaptorPtr newAdaptor = NULL; 57c06b6b69Smrg CHIPSPtr cPtr = CHIPSPTR(pScrn); 58c06b6b69Smrg int num_adaptors; 59c06b6b69Smrg 60c06b6b69Smrg if (!(cPtr->Flags & ChipsOverlay8plus16) && 61c06b6b69Smrg (cPtr->Flags & ChipsVideoSupport)) { 62c06b6b69Smrg newAdaptor = CHIPSSetupImageVideo(pScreen); 63c06b6b69Smrg CHIPSInitOffscreenImages(pScreen); 64c06b6b69Smrg } 65c06b6b69Smrg 66c06b6b69Smrg num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 67c06b6b69Smrg 68c06b6b69Smrg if(newAdaptor) { 69c06b6b69Smrg if(!num_adaptors) { 70c06b6b69Smrg num_adaptors = 1; 71c06b6b69Smrg adaptors = &newAdaptor; 72c06b6b69Smrg } else { 73c06b6b69Smrg newAdaptors = /* need to free this someplace */ 74c06b6b69Smrg xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); 75c06b6b69Smrg if(newAdaptors) { 76c06b6b69Smrg memcpy(newAdaptors, adaptors, num_adaptors * 77c06b6b69Smrg sizeof(XF86VideoAdaptorPtr)); 78c06b6b69Smrg newAdaptors[num_adaptors] = newAdaptor; 79c06b6b69Smrg adaptors = newAdaptors; 80c06b6b69Smrg num_adaptors++; 81c06b6b69Smrg } 82c06b6b69Smrg } 83c06b6b69Smrg } 84c06b6b69Smrg 85c06b6b69Smrg if(num_adaptors) 86c06b6b69Smrg xf86XVScreenInit(pScreen, adaptors, num_adaptors); 87c06b6b69Smrg 88c06b6b69Smrg if(newAdaptors) 89c06b6b69Smrg xfree(newAdaptors); 90c06b6b69Smrg} 91c06b6b69Smrg 92c06b6b69Smrg/* client libraries expect an encoding */ 93c06b6b69Smrgstatic 94c06b6b69SmrgXF86VideoEncodingRec DummyEncoding[1] = 95c06b6b69Smrg{ 96c06b6b69Smrg { 97c06b6b69Smrg 0, 98c06b6b69Smrg "XV_IMAGE", 99c06b6b69Smrg 1024, 1024, 100c06b6b69Smrg {1, 1} 101c06b6b69Smrg } 102c06b6b69Smrg}; 103c06b6b69Smrg 104c06b6b69Smrg#define NUM_FORMATS 4 105c06b6b69Smrg 106c06b6b69Smrgstatic XF86VideoFormatRec Formats[NUM_FORMATS] = 107c06b6b69Smrg{ 108c06b6b69Smrg {8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 109c06b6b69Smrg}; 110c06b6b69Smrg 111c06b6b69Smrg#define NUM_ATTRIBUTES 1 112c06b6b69Smrg 113c06b6b69Smrgstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES] = 114c06b6b69Smrg{ 115c06b6b69Smrg {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"} 116c06b6b69Smrg}; 117c06b6b69Smrg 118c06b6b69Smrg#define NUM_IMAGES 4 119c06b6b69Smrg 120c06b6b69Smrgstatic XF86ImageRec Images[NUM_IMAGES] = 121c06b6b69Smrg{ 122c06b6b69Smrg { 123c06b6b69Smrg 0x35315652, 124c06b6b69Smrg XvRGB, 125c06b6b69Smrg LSBFirst, 126c06b6b69Smrg {'R','V','1','5', 127c06b6b69Smrg 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 128c06b6b69Smrg 16, 129c06b6b69Smrg XvPacked, 130c06b6b69Smrg 1, 131c06b6b69Smrg 15, 0x7C00, 0x03E0, 0x001F, 132c06b6b69Smrg 0, 0, 0, 133c06b6b69Smrg 0, 0, 0, 134c06b6b69Smrg 0, 0, 0, 135c06b6b69Smrg {'R','V','B',0, 136c06b6b69Smrg 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 137c06b6b69Smrg XvTopToBottom 138c06b6b69Smrg }, 139c06b6b69Smrg { 140c06b6b69Smrg 0x36315652, 141c06b6b69Smrg XvRGB, 142c06b6b69Smrg LSBFirst, 143c06b6b69Smrg {'R','V','1','6', 144c06b6b69Smrg 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 145c06b6b69Smrg 16, 146c06b6b69Smrg XvPacked, 147c06b6b69Smrg 1, 148c06b6b69Smrg 16, 0xF800, 0x07E0, 0x001F, 149c06b6b69Smrg 0, 0, 0, 150c06b6b69Smrg 0, 0, 0, 151c06b6b69Smrg 0, 0, 0, 152c06b6b69Smrg {'R','V','B',0, 153c06b6b69Smrg 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 154c06b6b69Smrg XvTopToBottom 155c06b6b69Smrg }, 156c06b6b69Smrg XVIMAGE_YV12, 157c06b6b69Smrg XVIMAGE_YUY2 158c06b6b69Smrg}; 159c06b6b69Smrg 160c06b6b69Smrgtypedef struct { 161c06b6b69Smrg FBLinearPtr linear; 162c06b6b69Smrg RegionRec clip; 163c06b6b69Smrg CARD32 colorKey; 164c06b6b69Smrg CARD32 videoStatus; 165c06b6b69Smrg Time offTime; 166c06b6b69Smrg Time freeTime; 167c06b6b69Smrg Bool doubleBuffer; 168c06b6b69Smrg Bool manualDoubleBuffer; 169c06b6b69Smrg int currentBuffer; 170c06b6b69Smrg} CHIPSPortPrivRec, *CHIPSPortPrivPtr; 171c06b6b69Smrg 172c06b6b69Smrg 173c06b6b69Smrg#define GET_PORT_PRIVATE(pScrn) \ 174c06b6b69Smrg (CHIPSPortPrivPtr)((CHIPSPTR(pScrn))->adaptor->pPortPrivates[0].ptr) 175c06b6b69Smrg 176c06b6b69Smrgvoid 177c06b6b69SmrgCHIPSResetVideo(ScrnInfoPtr pScrn) 178c06b6b69Smrg{ 179c06b6b69Smrg CHIPSPtr cPtr = CHIPSPTR(pScrn); 180c06b6b69Smrg CHIPSPortPrivPtr pPriv = cPtr->adaptor->pPortPrivates[0].ptr; 181c06b6b69Smrg unsigned char mr3c; 182c06b6b69Smrg int red, green, blue; 183c06b6b69Smrg 184c06b6b69Smrg if (cPtr->Flags & ChipsAccelSupport) 185c06b6b69Smrg CHIPSHiQVSync(pScrn); 186c06b6b69Smrg 187c06b6b69Smrg mr3c = cPtr->readMR(cPtr, 0x3C); 188c06b6b69Smrg cPtr->writeMR(cPtr, 0x3C, (mr3c | 0x6)); 189c06b6b69Smrg switch (pScrn->depth) { 190c06b6b69Smrg case 8: 191c06b6b69Smrg cPtr->writeMR(cPtr, 0x3D, 0x00); 192c06b6b69Smrg cPtr->writeMR(cPtr, 0x3E, 0x00); 193c06b6b69Smrg cPtr->writeMR(cPtr, 0x3F, (pPriv->colorKey & 0xFF)); 194c06b6b69Smrg cPtr->writeMR(cPtr, 0x40, 0xFF); 195c06b6b69Smrg cPtr->writeMR(cPtr, 0x41, 0xFF); 196c06b6b69Smrg cPtr->writeMR(cPtr, 0x42, 0x00); 197c06b6b69Smrg break; 198c06b6b69Smrg default: 199c06b6b69Smrg red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; 200c06b6b69Smrg green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; 201c06b6b69Smrg blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; 202c06b6b69Smrg switch (pScrn->depth) { 203c06b6b69Smrg case 15: 204c06b6b69Smrg cPtr->writeMR(cPtr, 0x3D, (red << 3)); 205c06b6b69Smrg cPtr->writeMR(cPtr, 0x3E, (green << 3)); 206c06b6b69Smrg cPtr->writeMR(cPtr, 0x3F, (blue << 3)); 207c06b6b69Smrg cPtr->writeMR(cPtr, 0x40, 0x07); 208c06b6b69Smrg cPtr->writeMR(cPtr, 0x41, 0x07); 209c06b6b69Smrg cPtr->writeMR(cPtr, 0x42, 0x07); 210c06b6b69Smrg break; 211c06b6b69Smrg case 16: 212c06b6b69Smrg cPtr->writeMR(cPtr, 0x3D, (red << 3)); 213c06b6b69Smrg cPtr->writeMR(cPtr, 0x3E, (green << 2)); 214c06b6b69Smrg cPtr->writeMR(cPtr, 0x3F, (blue << 3)); 215c06b6b69Smrg cPtr->writeMR(cPtr, 0x40, 0x07); 216c06b6b69Smrg cPtr->writeMR(cPtr, 0x41, 0x03); 217c06b6b69Smrg cPtr->writeMR(cPtr, 0x42, 0x07); 218c06b6b69Smrg break; 219c06b6b69Smrg case 24: 220c06b6b69Smrg cPtr->writeMR(cPtr, 0x3D, red); 221c06b6b69Smrg cPtr->writeMR(cPtr, 0x3E, green); 222c06b6b69Smrg cPtr->writeMR(cPtr, 0x3F, blue); 223c06b6b69Smrg cPtr->writeMR(cPtr, 0x40, 0x00); 224c06b6b69Smrg cPtr->writeMR(cPtr, 0x41, 0x00); 225c06b6b69Smrg cPtr->writeMR(cPtr, 0x42, 0x00); 226c06b6b69Smrg break; 227c06b6b69Smrg } 228c06b6b69Smrg } 229c06b6b69Smrg} 230c06b6b69Smrg 231c06b6b69Smrg 232c06b6b69Smrgstatic XF86VideoAdaptorPtr 233c06b6b69SmrgCHIPSSetupImageVideo(ScreenPtr pScreen) 234c06b6b69Smrg{ 235c06b6b69Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 236c06b6b69Smrg CHIPSPtr cPtr = CHIPSPTR(pScrn); 237c06b6b69Smrg XF86VideoAdaptorPtr adapt; 238c06b6b69Smrg CHIPSPortPrivPtr pPriv; 239c06b6b69Smrg 240c06b6b69Smrg if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + 241c06b6b69Smrg sizeof(CHIPSPortPrivRec) + 242c06b6b69Smrg sizeof(DevUnion)))) 243c06b6b69Smrg return NULL; 244c06b6b69Smrg 245c06b6b69Smrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 246c06b6b69Smrg adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 247c06b6b69Smrg adapt->name = "Chips and Technologies Backend Scaler"; 248c06b6b69Smrg adapt->nEncodings = 1; 249c06b6b69Smrg adapt->pEncodings = DummyEncoding; 250c06b6b69Smrg adapt->nFormats = NUM_FORMATS; 251c06b6b69Smrg adapt->pFormats = Formats; 252c06b6b69Smrg adapt->nPorts = 1; 253c06b6b69Smrg adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 254c06b6b69Smrg pPriv = (CHIPSPortPrivPtr)(&adapt->pPortPrivates[1]); 255c06b6b69Smrg adapt->pPortPrivates[0].ptr = (pointer)(pPriv); 256c06b6b69Smrg adapt->pAttributes = Attributes; 257c06b6b69Smrg adapt->nImages = NUM_IMAGES; 258c06b6b69Smrg adapt->nAttributes = NUM_ATTRIBUTES; 259c06b6b69Smrg adapt->pImages = Images; 260c06b6b69Smrg adapt->PutVideo = NULL; 261c06b6b69Smrg adapt->PutStill = NULL; 262c06b6b69Smrg adapt->GetVideo = NULL; 263c06b6b69Smrg adapt->GetStill = NULL; 264c06b6b69Smrg adapt->StopVideo = CHIPSStopVideo; 265c06b6b69Smrg adapt->SetPortAttribute = CHIPSSetPortAttribute; 266c06b6b69Smrg adapt->GetPortAttribute = CHIPSGetPortAttribute; 267c06b6b69Smrg adapt->QueryBestSize = CHIPSQueryBestSize; 268c06b6b69Smrg adapt->PutImage = CHIPSPutImage; 269c06b6b69Smrg adapt->QueryImageAttributes = CHIPSQueryImageAttributes; 270c06b6b69Smrg 271c06b6b69Smrg pPriv->colorKey = cPtr->videoKey; 272c06b6b69Smrg pPriv->videoStatus = 0; 273c06b6b69Smrg pPriv->manualDoubleBuffer = FALSE; 274c06b6b69Smrg pPriv->currentBuffer = 0; 275c06b6b69Smrg 276c06b6b69Smrg /* gotta uninit this someplace */ 277c06b6b69Smrg REGION_NULL(pScreen, &pPriv->clip); 278c06b6b69Smrg 279c06b6b69Smrg cPtr->adaptor = adapt; 280c06b6b69Smrg 281c06b6b69Smrg xvColorKey = MAKE_ATOM("XV_COLORKEY"); 282c06b6b69Smrg 283c06b6b69Smrg CHIPSResetVideo(pScrn); 284c06b6b69Smrg 285c06b6b69Smrg return adapt; 286c06b6b69Smrg} 287c06b6b69Smrg 288c06b6b69Smrg 289c06b6b69Smrgstatic void 290c06b6b69SmrgCHIPSStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shadow) 291c06b6b69Smrg{ 292c06b6b69Smrg CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data; 293c06b6b69Smrg CHIPSPtr cPtr = CHIPSPTR(pScrn); 294c06b6b69Smrg unsigned char mr3c, tmp; 295c06b6b69Smrg 296c06b6b69Smrg REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 297c06b6b69Smrg if (cPtr->Flags & ChipsAccelSupport) 298c06b6b69Smrg CHIPSHiQVSync(pScrn); 299c06b6b69Smrg if(shadow) { 300c06b6b69Smrg if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 301c06b6b69Smrg mr3c = cPtr->readMR(cPtr, 0x3C); 302c06b6b69Smrg cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE)); 303c06b6b69Smrg tmp = cPtr->readXR(cPtr, 0xD0); 304c06b6b69Smrg cPtr->writeXR(cPtr, 0xD0, (tmp & 0xf)); 305c06b6b69Smrg } 306c06b6b69Smrg if(pPriv->linear) { 307c06b6b69Smrg xf86FreeOffscreenLinear(pPriv->linear); 308c06b6b69Smrg pPriv->linear = NULL; 309c06b6b69Smrg } 310c06b6b69Smrg pPriv->videoStatus = 0; 311c06b6b69Smrg } else { 312c06b6b69Smrg if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 313c06b6b69Smrg pPriv->videoStatus |= OFF_TIMER; 314c06b6b69Smrg pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 315c06b6b69Smrg cPtr->VideoTimerCallback = CHIPSVideoTimerCallback; 316c06b6b69Smrg } 317c06b6b69Smrg } 318c06b6b69Smrg} 319c06b6b69Smrg 320c06b6b69Smrgstatic int 321c06b6b69SmrgCHIPSSetPortAttribute( 322c06b6b69Smrg ScrnInfoPtr pScrn, 323c06b6b69Smrg Atom attribute, 324c06b6b69Smrg INT32 value, 325c06b6b69Smrg pointer data 326c06b6b69Smrg){ 327c06b6b69Smrg CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data; 328c06b6b69Smrg CHIPSPtr cPtr = CHIPSPTR(pScrn); 329c06b6b69Smrg 330c06b6b69Smrg if (cPtr->Flags & ChipsAccelSupport) 331c06b6b69Smrg CHIPSHiQVSync(pScrn); 332c06b6b69Smrg if(attribute == xvColorKey) { 333c06b6b69Smrg int red, green, blue; 334c06b6b69Smrg pPriv->colorKey = value; 335c06b6b69Smrg switch (pScrn->depth) { 336c06b6b69Smrg case 8: 337c06b6b69Smrg cPtr->writeMR(cPtr, 0x3D, 0x00); 338c06b6b69Smrg cPtr->writeMR(cPtr, 0x3E, 0x00); 339c06b6b69Smrg cPtr->writeMR(cPtr, 0x3F, (pPriv->colorKey & 0xFF)); 340c06b6b69Smrg break; 341c06b6b69Smrg default: 342c06b6b69Smrg red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; 343c06b6b69Smrg green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; 344c06b6b69Smrg blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; 345c06b6b69Smrg switch (pScrn->depth) { 346c06b6b69Smrg case 15: 347c06b6b69Smrg cPtr->writeMR(cPtr, 0x3D, (red << 3)); 348c06b6b69Smrg cPtr->writeMR(cPtr, 0x3E, (green << 3)); 349c06b6b69Smrg cPtr->writeMR(cPtr, 0x3F, (blue << 3)); 350c06b6b69Smrg break; 351c06b6b69Smrg case 16: 352c06b6b69Smrg cPtr->writeMR(cPtr, 0x3D, (red << 3)); 353c06b6b69Smrg cPtr->writeMR(cPtr, 0x3E, (green << 2)); 354c06b6b69Smrg cPtr->writeMR(cPtr, 0x3F, (blue << 3)); 355c06b6b69Smrg break; 356c06b6b69Smrg case 24: 357c06b6b69Smrg cPtr->writeMR(cPtr, 0x3D, red); 358c06b6b69Smrg cPtr->writeMR(cPtr, 0x3E, green); 359c06b6b69Smrg cPtr->writeMR(cPtr, 0x3F, blue); 360c06b6b69Smrg break; 361c06b6b69Smrg } 362c06b6b69Smrg } 363c06b6b69Smrg REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 364c06b6b69Smrg } else return BadMatch; 365c06b6b69Smrg 366c06b6b69Smrg return Success; 367c06b6b69Smrg} 368c06b6b69Smrg 369c06b6b69Smrgstatic int 370c06b6b69SmrgCHIPSGetPortAttribute( 371c06b6b69Smrg ScrnInfoPtr pScrn, 372c06b6b69Smrg Atom attribute, 373c06b6b69Smrg INT32 *value, 374c06b6b69Smrg pointer data 375c06b6b69Smrg){ 376c06b6b69Smrg CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data; 377c06b6b69Smrg 378c06b6b69Smrg if(attribute == xvColorKey) { 379c06b6b69Smrg *value = pPriv->colorKey; 380c06b6b69Smrg } else return BadMatch; 381c06b6b69Smrg 382c06b6b69Smrg return Success; 383c06b6b69Smrg} 384c06b6b69Smrg 385c06b6b69Smrgstatic void 386c06b6b69SmrgCHIPSQueryBestSize( 387c06b6b69Smrg ScrnInfoPtr pScrn, 388c06b6b69Smrg Bool motion, 389c06b6b69Smrg short vid_w, short vid_h, 390c06b6b69Smrg short drw_w, short drw_h, 391c06b6b69Smrg unsigned int *p_w, unsigned int *p_h, 392c06b6b69Smrg pointer data 393c06b6b69Smrg){ 394c06b6b69Smrg *p_w = drw_w; 395c06b6b69Smrg *p_h = drw_h; 396c06b6b69Smrg 397c06b6b69Smrg if(*p_w > 16384) *p_w = 16384; 398c06b6b69Smrg} 399c06b6b69Smrg 400c06b6b69Smrg 401c06b6b69Smrgstatic void 402c06b6b69SmrgCHIPSCopyData( 403c06b6b69Smrg unsigned char *src, 404c06b6b69Smrg unsigned char *dst, 405c06b6b69Smrg int srcPitch, 406c06b6b69Smrg int dstPitch, 407c06b6b69Smrg int h, 408c06b6b69Smrg int w 409c06b6b69Smrg){ 410c06b6b69Smrg w <<= 1; 411c06b6b69Smrg while(h--) { 412c06b6b69Smrg memcpy(dst, src, w); 413c06b6b69Smrg src += srcPitch; 414c06b6b69Smrg dst += dstPitch; 415c06b6b69Smrg } 416c06b6b69Smrg} 417c06b6b69Smrg 418c06b6b69Smrgstatic void 419c06b6b69SmrgCHIPSCopyMungedData( 420c06b6b69Smrg unsigned char *src1, 421c06b6b69Smrg unsigned char *src2, 422c06b6b69Smrg unsigned char *src3, 423c06b6b69Smrg unsigned char *dst1, 424c06b6b69Smrg int srcPitch, 425c06b6b69Smrg int srcPitch2, 426c06b6b69Smrg int dstPitch, 427c06b6b69Smrg int h, 428c06b6b69Smrg int w 429c06b6b69Smrg){ 430c06b6b69Smrg CARD32 *dst = (CARD32*)dst1; 431c06b6b69Smrg int i, j; 432c06b6b69Smrg 433c06b6b69Smrg dstPitch >>= 2; 434c06b6b69Smrg w >>= 1; 435c06b6b69Smrg 436c06b6b69Smrg for(j = 0; j < h; j++) { 437c06b6b69Smrg for(i = 0; i < w; i++) { 438c06b6b69Smrg dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) | 439c06b6b69Smrg (src3[i] << 8) | (src2[i] << 24); 440c06b6b69Smrg } 441c06b6b69Smrg dst += dstPitch; 442c06b6b69Smrg src1 += srcPitch; 443c06b6b69Smrg if(j & 1) { 444c06b6b69Smrg src2 += srcPitch2; 445c06b6b69Smrg src3 += srcPitch2; 446c06b6b69Smrg } 447c06b6b69Smrg } 448c06b6b69Smrg} 449c06b6b69Smrg 450c06b6b69Smrgstatic FBLinearPtr 451c06b6b69SmrgCHIPSAllocateMemory( 452c06b6b69Smrg ScrnInfoPtr pScrn, 453c06b6b69Smrg FBLinearPtr linear, 454c06b6b69Smrg int size 455c06b6b69Smrg){ 456c06b6b69Smrg ScreenPtr pScreen; 457c06b6b69Smrg FBLinearPtr new_linear; 458c06b6b69Smrg 459c06b6b69Smrg if(linear) { 460c06b6b69Smrg if(linear->size >= size) 461c06b6b69Smrg return linear; 462c06b6b69Smrg 463c06b6b69Smrg if(xf86ResizeOffscreenLinear(linear, size)) 464c06b6b69Smrg return linear; 465c06b6b69Smrg 466c06b6b69Smrg xf86FreeOffscreenLinear(linear); 467c06b6b69Smrg } 468c06b6b69Smrg 469c06b6b69Smrg pScreen = screenInfo.screens[pScrn->scrnIndex]; 470c06b6b69Smrg 471c06b6b69Smrg new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, 472c06b6b69Smrg NULL, NULL, NULL); 473c06b6b69Smrg 474c06b6b69Smrg if(!new_linear) { 475c06b6b69Smrg int max_size; 476c06b6b69Smrg 477c06b6b69Smrg xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8, 478c06b6b69Smrg PRIORITY_EXTREME); 479c06b6b69Smrg 480c06b6b69Smrg if(max_size < size) 481c06b6b69Smrg return NULL; 482c06b6b69Smrg 483c06b6b69Smrg xf86PurgeUnlockedOffscreenAreas(pScreen); 484c06b6b69Smrg new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, 485c06b6b69Smrg NULL, NULL, NULL); 486c06b6b69Smrg } 487c06b6b69Smrg 488c06b6b69Smrg return new_linear; 489c06b6b69Smrg} 490c06b6b69Smrg 491c06b6b69Smrgstatic int 492c06b6b69SmrgCHIPSSetCurrentPlaybackBuffer(CHIPSPtr cPtr, int n) 493c06b6b69Smrg{ 494c06b6b69Smrg 495c06b6b69Smrg CARD8 mr20; 496c06b6b69Smrg mr20 = cPtr->readMR(cPtr, 0x20); 497c06b6b69Smrg mr20 &= ~0x1B; 498c06b6b69Smrg if (!n) mr20 |= 0x10; 499c06b6b69Smrg cPtr->writeMR(cPtr, 0x22, mr20); 500c06b6b69Smrg return n; 501c06b6b69Smrg} 502c06b6b69Smrg 503c06b6b69Smrgstatic int 504c06b6b69SmrgCHIPSWaitGetNextFrame(CHIPSPtr cPtr) 505c06b6b69Smrg{ 506c06b6b69Smrg volatile CARD8 mr20; 507c06b6b69Smrg volatile CARD8 mr21; 508c06b6b69Smrg 509c06b6b69Smrg mr20 = cPtr->readMR(cPtr, 0x20); 510c06b6b69Smrg while (1) { 511c06b6b69Smrg mr21 = cPtr->readMR(cPtr, 0x21); 512c06b6b69Smrg if (!(mr20 & (1 << 5)) || !(mr21 & 1)) 513c06b6b69Smrg break; 514c06b6b69Smrg } 515c06b6b69Smrg mr20 &= ~0x4; 516c06b6b69Smrg mr20 = cPtr->readMR(cPtr, 0x20); 517c06b6b69Smrg return (mr21 & 2)? 0 : 1; 518c06b6b69Smrg} 519c06b6b69Smrg 520c06b6b69Smrgstatic void 521c06b6b69SmrgCHIPSDisplayVideo( 522c06b6b69Smrg ScrnInfoPtr pScrn, 523c06b6b69Smrg int id, 524c06b6b69Smrg int offset, 525c06b6b69Smrg short width, short height, 526c06b6b69Smrg int pitch, 527c06b6b69Smrg int x1, int y1, int x2, int y2, 528c06b6b69Smrg BoxPtr dstBox, 529c06b6b69Smrg short src_w, short src_h, 530c06b6b69Smrg short drw_w, short drw_h, 531c06b6b69Smrg Bool triggerBufSwitch 532c06b6b69Smrg){ 533c06b6b69Smrg CHIPSPtr cPtr = CHIPSPTR(pScrn); 534c06b6b69Smrg CHIPSPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 535c06b6b69Smrg DisplayModePtr mode = pScrn->currentMode; 536c06b6b69Smrg unsigned char tmp, m1f, m1e; 537c06b6b69Smrg int buffer = pPriv->currentBuffer; 538c06b6b69Smrg Bool dblscan = (pScrn->currentMode->Flags & V_DBLSCAN) == V_DBLSCAN; 539c06b6b69Smrg int val; 540c06b6b69Smrg 541c06b6b69Smrg if (cPtr->Flags & ChipsAccelSupport) 542c06b6b69Smrg CHIPSHiQVSync(pScrn); 543c06b6b69Smrg 544c06b6b69Smrg tmp = cPtr->readXR(cPtr, 0xD0); 545c06b6b69Smrg cPtr->writeXR(cPtr, 0xD0, (tmp | 0x10)); 546c06b6b69Smrg 547c06b6b69Smrg m1e = cPtr->readMR(cPtr, 0x1E); 548c06b6b69Smrg m1e &= 0xE0; /* Set Zoom and Direction */ 549c06b6b69Smrg if ((!(cPtr->PanelType & ChipsLCD)) && (mode->Flags & V_INTERLACE)) 550c06b6b69Smrg m1e |= 0x10; 551c06b6b69Smrg 552c06b6b69Smrg m1f = cPtr->readMR(cPtr, 0x1F); 553c06b6b69Smrg m1f = (m1f & 0x14); /* Mask reserved bits, unset interpolation */ 554c06b6b69Smrg switch(id) { 555c06b6b69Smrg case 0x35315652: /* RGB15 */ 556c06b6b69Smrg m1f |= 0x09; 557c06b6b69Smrg break; 558c06b6b69Smrg case 0x36315652: /* RGB16 */ 559c06b6b69Smrg m1f |= 0x08; 560c06b6b69Smrg break; 561c06b6b69Smrg case FOURCC_YV12: /* YV12 */ 562c06b6b69Smrg /* m1f |= 0x03 */ 563c06b6b69Smrg m1f |= 0x00; 564c06b6b69Smrg break; 565c06b6b69Smrg case FOURCC_YUY2: /* YUY2 */ 566c06b6b69Smrg default: 567c06b6b69Smrg m1f |= 0x00; /* Do nothing here */ 568c06b6b69Smrg break; 569c06b6b69Smrg } 570c06b6b69Smrg 571c06b6b69Smrg offset += (x1 >> 15) & ~0x01; 572c06b6b69Smrg /* Setup Pointer 1 */ 573c06b6b69Smrg if (!buffer || pPriv->manualDoubleBuffer || !pPriv->doubleBuffer) { 574c06b6b69Smrg cPtr->writeMR(cPtr, 0x22, (offset & 0xF8)); 575c06b6b69Smrg cPtr->writeMR(cPtr, 0x23, ((offset >> 8) & 0xFF)); 576c06b6b69Smrg cPtr->writeMR(cPtr, 0x24, ((offset >> 16) & 0xFF)); 577c06b6b69Smrg } 578c06b6b69Smrg 579c06b6b69Smrg /* Setup Pointer 2 */ 580c06b6b69Smrg if ((buffer && !pPriv->manualDoubleBuffer) || !pPriv->doubleBuffer) { 581c06b6b69Smrg cPtr->writeMR(cPtr, 0x25, (offset & 0xF8)); 582c06b6b69Smrg cPtr->writeMR(cPtr, 0x26, ((offset >> 8) & 0xFF)); 583c06b6b69Smrg cPtr->writeMR(cPtr, 0x27, ((offset >> 16) & 0xFF)); 584c06b6b69Smrg } 585c06b6b69Smrg 586c06b6b69Smrg tmp = cPtr->readMR(cPtr, 0x04); 587c06b6b69Smrg if (pPriv->doubleBuffer && !pPriv->manualDoubleBuffer && triggerBufSwitch) 588c06b6b69Smrg tmp |= 0x18; 589c06b6b69Smrg cPtr->writeMR(cPtr, 0x04, tmp); 590c06b6b69Smrg 591c06b6b69Smrg tmp = cPtr->readMR(cPtr, 0x20); 592c06b6b69Smrg tmp &= 0xC3; 593c06b6b69Smrg 594c06b6b69Smrg if (pPriv->doubleBuffer && !pPriv->manualDoubleBuffer && triggerBufSwitch) 595c06b6b69Smrg tmp |= ((1 << 2 | 1 << 5) | ((buffer) ? (1 << 4) : 0)); 596c06b6b69Smrg cPtr->writeMR(cPtr, 0x20, tmp); 597c06b6b69Smrg 598c06b6b69Smrg cPtr->writeMR(cPtr, 0x28, ((width >> 2) - 1)); /* Width */ 599c06b6b69Smrg cPtr->writeMR(cPtr, 0x34, ((width >> 2) - 1)); 600c06b6b69Smrg 601c06b6b69Smrg /* Left Edge of Overlay */ 602c06b6b69Smrg cPtr->writeMR(cPtr, 0x2A, ((cPtr->OverlaySkewX + dstBox->x1) & 0xFF)); 603c06b6b69Smrg tmp = cPtr->readMR(cPtr, 0x2B); 604c06b6b69Smrg tmp = (tmp & 0xF8) + (((cPtr->OverlaySkewX + dstBox->x1) >> 8) & 0x07); 605c06b6b69Smrg cPtr->writeMR(cPtr, 0x2B, tmp); 606c06b6b69Smrg /* Right Edge of Overlay */ 607c06b6b69Smrg cPtr->writeMR(cPtr, 0x2C, ((cPtr->OverlaySkewX + dstBox->x2 -1) 608c06b6b69Smrg & 0xFF)); 609c06b6b69Smrg tmp = cPtr->readMR(cPtr, 0x2D); 610c06b6b69Smrg tmp = (tmp & 0xF8) + (((cPtr->OverlaySkewX + dstBox->x2 - 1) >> 8) & 0x07); 611c06b6b69Smrg cPtr->writeMR(cPtr, 0x2D, tmp); 612c06b6b69Smrg /* Top Edge of Overlay */ 613c06b6b69Smrg val = cPtr->OverlaySkewY + (dstBox->y1 << (dblscan ? 1 : 0)); 614c06b6b69Smrg cPtr->writeMR(cPtr, 0x2E, ((val) & 0xFF)); 615c06b6b69Smrg tmp = cPtr->readMR(cPtr, 0x2F); 616c06b6b69Smrg tmp = (tmp & 0xF8) + (((val) >> 8) & 0x07); 617c06b6b69Smrg cPtr->writeMR(cPtr, 0x2F, tmp); 618c06b6b69Smrg /* Bottom Edge of Overlay*/ 619c06b6b69Smrg val = cPtr->OverlaySkewY + (dstBox->y2 << (dblscan ? 1 : 0)); 620c06b6b69Smrg cPtr->writeMR(cPtr, 0x30, ((val - 1) & 0xFF)); 621c06b6b69Smrg tmp = cPtr->readMR(cPtr, 0x31); 622c06b6b69Smrg tmp = (tmp & 0xF8) + (((val - 1) >> 8) & 0x07); 623c06b6b69Smrg cPtr->writeMR(cPtr, 0x31, tmp); 624c06b6b69Smrg 625c06b6b69Smrg /* Horizontal Zoom */ 626c06b6b69Smrg if (drw_w > src_w) { 627c06b6b69Smrg m1f = m1f | 0x20; /* set H-interpolation */ 628c06b6b69Smrg m1e = m1e | 0x04; 629c06b6b69Smrg tmp = cPtr->VideoZoomMax * src_w / drw_w; 630c06b6b69Smrg cPtr->writeMR(cPtr, 0x32, tmp); 631c06b6b69Smrg } 632c06b6b69Smrg 633c06b6b69Smrg /* Vertical Zoom */ 634c06b6b69Smrg if (drw_h > src_h || dblscan) { 635c06b6b69Smrg m1f = m1f | 0x80; /* set V-interpolation */ 636c06b6b69Smrg m1e = m1e | 0x08; 637c06b6b69Smrg if (dblscan) 638c06b6b69Smrg tmp = cPtr->VideoZoomMax >> 1; 639c06b6b69Smrg if (drw_h > src_h) 6409f4658d1Smrg tmp = 256 * src_h / drw_h; 6419f4658d1Smrg cPtr->writeMR(cPtr, 0x33, tmp & 0xFC); 642c06b6b69Smrg } 643c06b6b69Smrg cPtr->writeMR(cPtr, 0x1F, m1f); 644c06b6b69Smrg cPtr->writeMR(cPtr, 0x1E, m1e); 645c06b6b69Smrg 646c06b6b69Smrg tmp = cPtr->readMR(cPtr, 0x3C); 647c06b6b69Smrg cPtr->writeMR(cPtr, 0x3C, (tmp | 0x7)); 648c06b6b69Smrg if (cPtr->Flags & ChipsAccelSupport) 649c06b6b69Smrg CHIPSHiQVSync(pScrn); 650c06b6b69Smrg} 651c06b6b69Smrg 652c06b6b69Smrgstatic int 653c06b6b69SmrgCHIPSPutImage( 654c06b6b69Smrg ScrnInfoPtr pScrn, 655c06b6b69Smrg short src_x, short src_y, 656c06b6b69Smrg short drw_x, short drw_y, 657c06b6b69Smrg short src_w, short src_h, 658c06b6b69Smrg short drw_w, short drw_h, 659c06b6b69Smrg int id, unsigned char* buf, 660c06b6b69Smrg short width, short height, 661c06b6b69Smrg Bool sync, 662c06b6b69Smrg RegionPtr clipBoxes, pointer data, 663c06b6b69Smrg DrawablePtr pDraw 664c06b6b69Smrg){ 665c06b6b69Smrg CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data; 666c06b6b69Smrg CHIPSPtr cPtr = CHIPSPTR(pScrn); 667c06b6b69Smrg INT32 x1, x2, y1, y2; 668c06b6b69Smrg unsigned char *dst_start; 669c06b6b69Smrg int new_size, offset, offset2 = 0, offset3 = 0; 670c06b6b69Smrg int srcPitch, srcPitch2 = 0, dstPitch; 671c06b6b69Smrg int top, left, npixels, nlines, bpp; 672c06b6b69Smrg BoxRec dstBox; 673c06b6b69Smrg CARD32 tmp; 674c06b6b69Smrg 675c06b6b69Smrg if(drw_w > 16384) drw_w = 16384; 676c06b6b69Smrg 677c06b6b69Smrg /* Clip */ 678c06b6b69Smrg x1 = src_x; 679c06b6b69Smrg x2 = src_x + src_w; 680c06b6b69Smrg y1 = src_y; 681c06b6b69Smrg y2 = src_y + src_h; 682c06b6b69Smrg 683c06b6b69Smrg dstBox.x1 = drw_x; 684c06b6b69Smrg dstBox.x2 = drw_x + drw_w; 685c06b6b69Smrg dstBox.y1 = drw_y; 686c06b6b69Smrg dstBox.y2 = drw_y + drw_h; 687c06b6b69Smrg 688c06b6b69Smrg if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, 689c06b6b69Smrg clipBoxes, width, height)) 690c06b6b69Smrg return Success; 691c06b6b69Smrg 692c06b6b69Smrg dstBox.x1 -= pScrn->frameX0 & cPtr->viewportMask; 693c06b6b69Smrg dstBox.x2 -= pScrn->frameX0 & cPtr->viewportMask; 694c06b6b69Smrg dstBox.y1 -= pScrn->frameY0; 695c06b6b69Smrg dstBox.y2 -= pScrn->frameY0; 696c06b6b69Smrg 697c06b6b69Smrg bpp = pScrn->bitsPerPixel >> 3; 698c06b6b69Smrg 699c06b6b69Smrg dstPitch = ((width << 1) + 15) & ~15; 700c06b6b69Smrg new_size = ((dstPitch * height) + bpp - 1) / bpp; 701c06b6b69Smrg 702c06b6b69Smrg pPriv->doubleBuffer = (pScrn->currentMode->Flags & V_DBLSCAN) != V_DBLSCAN; 703c06b6b69Smrg 704c06b6b69Smrg if (pPriv->doubleBuffer) 705c06b6b69Smrg new_size <<= 1; 706c06b6b69Smrg 707c06b6b69Smrg switch(id) { 708c06b6b69Smrg case FOURCC_YV12: /* YV12 */ 709c06b6b69Smrg srcPitch = (width + 3) & ~3; 710c06b6b69Smrg offset2 = srcPitch * height; 711c06b6b69Smrg srcPitch2 = ((width >> 1) + 3) & ~3; 712c06b6b69Smrg offset3 = (srcPitch2 * (height >> 1)) + offset2; 713c06b6b69Smrg break; 714c06b6b69Smrg default: /* RGB15, RGB16, YUY2 */ 715c06b6b69Smrg srcPitch = (width << 1); 716c06b6b69Smrg break; 717c06b6b69Smrg } 718c06b6b69Smrg 719c06b6b69Smrg if(!(pPriv->linear = CHIPSAllocateMemory(pScrn, pPriv->linear, new_size))) { 720c06b6b69Smrg if (pPriv->doubleBuffer 721c06b6b69Smrg && (pPriv->linear = CHIPSAllocateMemory(pScrn, pPriv->linear, 722c06b6b69Smrg new_size >> 1))) { 723c06b6b69Smrg new_size >>= 1; 724c06b6b69Smrg pPriv->doubleBuffer = FALSE; 725c06b6b69Smrg } else 726c06b6b69Smrg return BadAlloc; 727c06b6b69Smrg } 728c06b6b69Smrg 729c06b6b69Smrg /* copy data */ 730c06b6b69Smrg top = y1 >> 16; 731c06b6b69Smrg left = (x1 >> 16) & ~1; 732c06b6b69Smrg npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; 733c06b6b69Smrg left <<= 1; 734c06b6b69Smrg 735c06b6b69Smrg offset = pPriv->linear->offset * bpp; 736c06b6b69Smrg if (!pPriv->manualDoubleBuffer) 737c06b6b69Smrg pPriv->currentBuffer = CHIPSWaitGetNextFrame(cPtr); 738c06b6b69Smrg if(pPriv->doubleBuffer && pPriv->currentBuffer) 739c06b6b69Smrg offset += (new_size * bpp) >> 1; 740c06b6b69Smrg 741c06b6b69Smrg dst_start = cPtr->FbBase + offset + left + (top * dstPitch); 742c06b6b69Smrg 743c06b6b69Smrg switch(id) { 744c06b6b69Smrg case FOURCC_YV12: /* YV12 */ 745c06b6b69Smrg top &= ~1; 746c06b6b69Smrg tmp = ((top >> 1) * srcPitch2) + (left >> 2); 747c06b6b69Smrg offset2 += tmp; 748c06b6b69Smrg offset3 += tmp; 749c06b6b69Smrg nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; 750c06b6b69Smrg CHIPSCopyMungedData(buf + (top * srcPitch) + (left >> 1), 751c06b6b69Smrg buf + offset2, buf + offset3, dst_start, 752c06b6b69Smrg srcPitch, srcPitch2, dstPitch, nlines, npixels); 753c06b6b69Smrg break; 754c06b6b69Smrg default: /* RGB15, RGB16, YUY2 */ 755c06b6b69Smrg buf += (top * srcPitch) + left; 756c06b6b69Smrg nlines = ((y2 + 0xffff) >> 16) - top; 757c06b6b69Smrg CHIPSCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels); 758c06b6b69Smrg break; 759c06b6b69Smrg } 760c06b6b69Smrg 761c06b6b69Smrg /* update cliplist */ 762c06b6b69Smrg if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { 763c06b6b69Smrg REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 764c06b6b69Smrg xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 765c06b6b69Smrg } 766c06b6b69Smrg 767c06b6b69Smrg offset += top * dstPitch; 768c06b6b69Smrg CHIPSDisplayVideo(pScrn, id, offset, width, height, dstPitch, 769c06b6b69Smrg x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h, TRUE); 770c06b6b69Smrg 771c06b6b69Smrg pPriv->videoStatus = CLIENT_VIDEO_ON; 772c06b6b69Smrg 773c06b6b69Smrg if (pPriv->manualDoubleBuffer) 774c06b6b69Smrg pPriv->currentBuffer ^= 1; 775c06b6b69Smrg 776c06b6b69Smrg return Success; 777c06b6b69Smrg} 778c06b6b69Smrg 779c06b6b69Smrgstatic int 780c06b6b69SmrgCHIPSQueryImageAttributes( 781c06b6b69Smrg ScrnInfoPtr pScrn, 782c06b6b69Smrg int id, 783c06b6b69Smrg unsigned short *w, unsigned short *h, 784c06b6b69Smrg int *pitches, int *offsets 785c06b6b69Smrg){ 786c06b6b69Smrg int size, tmp; 787c06b6b69Smrg 788c06b6b69Smrg if(*w > 1024) *w = 1024; 789c06b6b69Smrg if(*h > 1024) *h = 1024; 790c06b6b69Smrg 791c06b6b69Smrg *w = (*w + 1) & ~1; 792c06b6b69Smrg if(offsets) offsets[0] = 0; 793c06b6b69Smrg 794c06b6b69Smrg switch(id) { 795c06b6b69Smrg case FOURCC_YV12: /* YV12 */ 796c06b6b69Smrg *h = (*h + 1) & ~1; 797c06b6b69Smrg size = (*w + 3) & ~3; 798c06b6b69Smrg if(pitches) pitches[0] = size; 799c06b6b69Smrg size *= *h; 800c06b6b69Smrg if(offsets) offsets[1] = size; 801c06b6b69Smrg tmp = ((*w >> 1) + 3) & ~3; 802c06b6b69Smrg if(pitches) pitches[1] = pitches[2] = tmp; 803c06b6b69Smrg tmp *= (*h >> 1); 804c06b6b69Smrg size += tmp; 805c06b6b69Smrg if(offsets) offsets[2] = size; 806c06b6b69Smrg size += tmp; 807c06b6b69Smrg break; 808c06b6b69Smrg default: /* RGB15, RGB16, YUY2 */ 809c06b6b69Smrg size = *w << 1; 810c06b6b69Smrg if(pitches) pitches[0] = size; 811c06b6b69Smrg size *= *h; 812c06b6b69Smrg break; 813c06b6b69Smrg } 814c06b6b69Smrg 815c06b6b69Smrg return size; 816c06b6b69Smrg} 817c06b6b69Smrg 818c06b6b69Smrg 819c06b6b69Smrgstatic void 820c06b6b69SmrgCHIPSVideoTimerCallback(ScrnInfoPtr pScrn, Time time) 821c06b6b69Smrg{ 822c06b6b69Smrg CHIPSPtr cPtr = CHIPSPTR(pScrn); 823c06b6b69Smrg CHIPSPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 824c06b6b69Smrg unsigned char mr3c; 825c06b6b69Smrg 826c06b6b69Smrg if(pPriv->videoStatus & TIMER_MASK) { 827c06b6b69Smrg if(pPriv->videoStatus & OFF_TIMER) { 828c06b6b69Smrg if(pPriv->offTime < time) { 829c06b6b69Smrg if (cPtr->Flags & ChipsAccelSupport) 830c06b6b69Smrg CHIPSHiQVSync(pScrn); 831c06b6b69Smrg mr3c = cPtr->readMR(cPtr, 0x3C); 832c06b6b69Smrg cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE)); 833c06b6b69Smrg pPriv->videoStatus = FREE_TIMER; 834c06b6b69Smrg pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 835c06b6b69Smrg } 836c06b6b69Smrg } else { /* FREE_TIMER */ 837c06b6b69Smrg if(pPriv->freeTime < time) { 838c06b6b69Smrg if(pPriv->linear) { 839c06b6b69Smrg xf86FreeOffscreenLinear(pPriv->linear); 840c06b6b69Smrg pPriv->linear = NULL; 841c06b6b69Smrg } 842c06b6b69Smrg pPriv->videoStatus = 0; 843c06b6b69Smrg cPtr->VideoTimerCallback = NULL; 844c06b6b69Smrg } 845c06b6b69Smrg } 846c06b6b69Smrg } else /* shouldn't get here */ 847c06b6b69Smrg cPtr->VideoTimerCallback = NULL; 848c06b6b69Smrg} 849c06b6b69Smrg 850c06b6b69Smrg 851c06b6b69Smrg/****************** Offscreen stuff ***************/ 852c06b6b69Smrg 853c06b6b69Smrgtypedef struct { 854c06b6b69Smrg FBLinearPtr linear; 855c06b6b69Smrg Bool isOn; 856c06b6b69Smrg} OffscreenPrivRec, * OffscreenPrivPtr; 857c06b6b69Smrg 858c06b6b69Smrgstatic int 859c06b6b69SmrgCHIPSAllocateSurface( 860c06b6b69Smrg ScrnInfoPtr pScrn, 861c06b6b69Smrg int id, 862c06b6b69Smrg unsigned short w, 863c06b6b69Smrg unsigned short h, 864c06b6b69Smrg XF86SurfacePtr surface 865c06b6b69Smrg){ 866c06b6b69Smrg FBLinearPtr linear; 867c06b6b69Smrg int pitch, size, bpp; 868c06b6b69Smrg OffscreenPrivPtr pPriv; 869c06b6b69Smrg 870c06b6b69Smrg if((w > 1024) || (h > 1024)) 871c06b6b69Smrg return BadAlloc; 872c06b6b69Smrg 873c06b6b69Smrg w = (w + 1) & ~1; 874c06b6b69Smrg pitch = ((w << 1) + 15) & ~15; 875c06b6b69Smrg bpp = pScrn->bitsPerPixel >> 3; 876c06b6b69Smrg size = ((pitch * h) + bpp - 1) / bpp; 877c06b6b69Smrg 878c06b6b69Smrg if(!(linear = CHIPSAllocateMemory(pScrn, NULL, size))) 879c06b6b69Smrg return BadAlloc; 880c06b6b69Smrg 881c06b6b69Smrg surface->width = w; 882c06b6b69Smrg surface->height = h; 883c06b6b69Smrg 884c06b6b69Smrg if(!(surface->pitches = xalloc(sizeof(int)))) { 885c06b6b69Smrg xf86FreeOffscreenLinear(linear); 886c06b6b69Smrg return BadAlloc; 887c06b6b69Smrg } 888c06b6b69Smrg if(!(surface->offsets = xalloc(sizeof(int)))) { 889c06b6b69Smrg xfree(surface->pitches); 890c06b6b69Smrg xf86FreeOffscreenLinear(linear); 891c06b6b69Smrg return BadAlloc; 892c06b6b69Smrg } 893c06b6b69Smrg if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) { 894c06b6b69Smrg xfree(surface->pitches); 895c06b6b69Smrg xfree(surface->offsets); 896c06b6b69Smrg xf86FreeOffscreenLinear(linear); 897c06b6b69Smrg return BadAlloc; 898c06b6b69Smrg } 899c06b6b69Smrg 900c06b6b69Smrg pPriv->linear = linear; 901c06b6b69Smrg pPriv->isOn = FALSE; 902c06b6b69Smrg 903c06b6b69Smrg surface->pScrn = pScrn; 904c06b6b69Smrg surface->id = id; 905c06b6b69Smrg surface->pitches[0] = pitch; 906c06b6b69Smrg surface->offsets[0] = linear->offset * bpp; 907c06b6b69Smrg surface->devPrivate.ptr = (pointer)pPriv; 908c06b6b69Smrg 909c06b6b69Smrg return Success; 910c06b6b69Smrg} 911c06b6b69Smrg 912c06b6b69Smrgstatic int 913c06b6b69SmrgCHIPSStopSurface( 914c06b6b69Smrg XF86SurfacePtr surface 915c06b6b69Smrg){ 916c06b6b69Smrg OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 917c06b6b69Smrg 918c06b6b69Smrg if(pPriv->isOn) { 919c06b6b69Smrg CHIPSPtr cPtr = CHIPSPTR(surface->pScrn); 920c06b6b69Smrg unsigned char mr3c, tmp; 921c06b6b69Smrg tmp = cPtr->readXR(cPtr, 0xD0); 922c06b6b69Smrg cPtr->writeXR(cPtr, 0xD0, (tmp & 0xf)); 923c06b6b69Smrg mr3c = cPtr->readMR(cPtr, 0x3C); 924c06b6b69Smrg cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE)); 925c06b6b69Smrg pPriv->isOn = FALSE; 926c06b6b69Smrg } 927c06b6b69Smrg 928c06b6b69Smrg return Success; 929c06b6b69Smrg} 930c06b6b69Smrg 931c06b6b69Smrg 932c06b6b69Smrgstatic int 933c06b6b69SmrgCHIPSFreeSurface( 934c06b6b69Smrg XF86SurfacePtr surface 935c06b6b69Smrg){ 936c06b6b69Smrg OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 937c06b6b69Smrg 938c06b6b69Smrg if(pPriv->isOn) 939c06b6b69Smrg CHIPSStopSurface(surface); 940c06b6b69Smrg xf86FreeOffscreenLinear(pPriv->linear); 941c06b6b69Smrg xfree(surface->pitches); 942c06b6b69Smrg xfree(surface->offsets); 943c06b6b69Smrg xfree(surface->devPrivate.ptr); 944c06b6b69Smrg 945c06b6b69Smrg return Success; 946c06b6b69Smrg} 947c06b6b69Smrg 948c06b6b69Smrgstatic int 949c06b6b69SmrgCHIPSGetSurfaceAttribute( 950c06b6b69Smrg ScrnInfoPtr pScrn, 951c06b6b69Smrg Atom attribute, 952c06b6b69Smrg INT32 *value 953c06b6b69Smrg){ 954c06b6b69Smrg return CHIPSGetPortAttribute(pScrn, attribute, value, 955c06b6b69Smrg (pointer)(GET_PORT_PRIVATE(pScrn))); 956c06b6b69Smrg} 957c06b6b69Smrg 958c06b6b69Smrgstatic int 959c06b6b69SmrgCHIPSSetSurfaceAttribute( 960c06b6b69Smrg ScrnInfoPtr pScrn, 961c06b6b69Smrg Atom attribute, 962c06b6b69Smrg INT32 value 963c06b6b69Smrg){ 964c06b6b69Smrg return CHIPSSetPortAttribute(pScrn, attribute, value, 965c06b6b69Smrg (pointer)(GET_PORT_PRIVATE(pScrn))); 966c06b6b69Smrg} 967c06b6b69Smrg 968c06b6b69Smrg 969c06b6b69Smrgstatic int 970c06b6b69SmrgCHIPSDisplaySurface( 971c06b6b69Smrg XF86SurfacePtr surface, 972c06b6b69Smrg short src_x, short src_y, 973c06b6b69Smrg short drw_x, short drw_y, 974c06b6b69Smrg short src_w, short src_h, 975c06b6b69Smrg short drw_w, short drw_h, 976c06b6b69Smrg RegionPtr clipBoxes 977c06b6b69Smrg){ 978c06b6b69Smrg OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 979c06b6b69Smrg ScrnInfoPtr pScrn = surface->pScrn; 980c06b6b69Smrg CHIPSPtr cPtr = CHIPSPTR(pScrn); 981c06b6b69Smrg CHIPSPortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn); 982c06b6b69Smrg INT32 x1, y1, x2, y2; 983c06b6b69Smrg BoxRec dstBox; 984c06b6b69Smrg 985c06b6b69Smrg x1 = src_x; 986c06b6b69Smrg x2 = src_x + src_w; 987c06b6b69Smrg y1 = src_y; 988c06b6b69Smrg y2 = src_y + src_h; 989c06b6b69Smrg 990c06b6b69Smrg dstBox.x1 = drw_x; 991c06b6b69Smrg dstBox.x2 = drw_x + drw_w; 992c06b6b69Smrg dstBox.y1 = drw_y; 993c06b6b69Smrg dstBox.y2 = drw_y + drw_h; 994c06b6b69Smrg 995c06b6b69Smrg if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, 996c06b6b69Smrg surface->width, surface->height)) 997c06b6b69Smrg return Success; 998c06b6b69Smrg 999c06b6b69Smrg dstBox.x1 -= pScrn->frameX0; 1000c06b6b69Smrg dstBox.x2 -= pScrn->frameX0; 1001c06b6b69Smrg dstBox.y1 -= pScrn->frameY0; 1002c06b6b69Smrg dstBox.y2 -= pScrn->frameY0; 1003c06b6b69Smrg 1004c06b6b69Smrg if (portPriv->doubleBuffer) 1005c06b6b69Smrg portPriv->currentBuffer = CHIPSSetCurrentPlaybackBuffer(cPtr,0); 1006c06b6b69Smrg else 1007c06b6b69Smrg portPriv->currentBuffer = 0; 1008c06b6b69Smrg 1009c06b6b69Smrg CHIPSDisplayVideo(pScrn, surface->id, surface->offsets[0], 1010c06b6b69Smrg surface->width, surface->height, surface->pitches[0], 1011c06b6b69Smrg x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h, FALSE); 1012c06b6b69Smrg xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes); 1013c06b6b69Smrg 1014c06b6b69Smrg pPriv->isOn = TRUE; 1015c06b6b69Smrg if(portPriv->videoStatus & CLIENT_VIDEO_ON) { 1016c06b6b69Smrg REGION_EMPTY(pScrn->pScreen, &portPriv->clip); 1017c06b6b69Smrg UpdateCurrentTime(); 1018c06b6b69Smrg portPriv->videoStatus = FREE_TIMER; 1019c06b6b69Smrg portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 1020c06b6b69Smrg cPtr->VideoTimerCallback = CHIPSVideoTimerCallback; 1021c06b6b69Smrg } 1022c06b6b69Smrg 1023c06b6b69Smrg return Success; 1024c06b6b69Smrg} 1025c06b6b69Smrg 1026c06b6b69Smrg 1027c06b6b69Smrgstatic void 1028c06b6b69SmrgCHIPSInitOffscreenImages(ScreenPtr pScreen) 1029c06b6b69Smrg{ 1030c06b6b69Smrg XF86OffscreenImagePtr offscreenImages; 1031c06b6b69Smrg 1032c06b6b69Smrg /* need to free this someplace */ 1033c06b6b69Smrg if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) 1034c06b6b69Smrg return; 1035c06b6b69Smrg 1036c06b6b69Smrg offscreenImages[0].image = &Images[0]; 1037c06b6b69Smrg offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | 1038c06b6b69Smrg VIDEO_CLIP_TO_VIEWPORT; 1039c06b6b69Smrg offscreenImages[0].alloc_surface = CHIPSAllocateSurface; 1040c06b6b69Smrg offscreenImages[0].free_surface = CHIPSFreeSurface; 1041c06b6b69Smrg offscreenImages[0].display = CHIPSDisplaySurface; 1042c06b6b69Smrg offscreenImages[0].stop = CHIPSStopSurface; 1043c06b6b69Smrg offscreenImages[0].setAttribute = CHIPSSetSurfaceAttribute; 1044c06b6b69Smrg offscreenImages[0].getAttribute = CHIPSGetSurfaceAttribute; 1045c06b6b69Smrg offscreenImages[0].max_width = 1024; 1046c06b6b69Smrg offscreenImages[0].max_height = 1024; 1047c06b6b69Smrg offscreenImages[0].num_attributes = NUM_ATTRIBUTES; 1048c06b6b69Smrg offscreenImages[0].attributes = Attributes; 1049c06b6b69Smrg 1050c06b6b69Smrg xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); 1051c06b6b69Smrg} 1052