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